Add an accommodations reservations module (#188)
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			Add a new module to enable accommodations reservation  Reviewed-on: #188
This commit is contained in:
		@@ -88,10 +88,12 @@ export class Family implements FamilyAPI {
 | 
			
		||||
export class ExtendedFamilyInfo extends Family {
 | 
			
		||||
  public disable_couple_photos: boolean;
 | 
			
		||||
  public enable_genealogy: boolean;
 | 
			
		||||
  public enable_accommodations: boolean;
 | 
			
		||||
  constructor(p: any) {
 | 
			
		||||
    super(p);
 | 
			
		||||
    this.disable_couple_photos = p.disable_couple_photos;
 | 
			
		||||
    this.enable_genealogy = p.enable_genealogy;
 | 
			
		||||
    this.enable_accommodations = p.enable_accommodations;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -235,6 +237,7 @@ export class FamilyApi {
 | 
			
		||||
    id: number;
 | 
			
		||||
    name?: string;
 | 
			
		||||
    enable_genealogy?: boolean;
 | 
			
		||||
    enable_accommodations?: boolean;
 | 
			
		||||
    disable_couple_photos?: boolean;
 | 
			
		||||
  }): Promise<void> {
 | 
			
		||||
    await APIClient.exec({
 | 
			
		||||
@@ -243,6 +246,7 @@ export class FamilyApi {
 | 
			
		||||
      jsonData: {
 | 
			
		||||
        name: settings.name,
 | 
			
		||||
        enable_genealogy: settings.enable_genealogy,
 | 
			
		||||
        enable_accommodations: settings.enable_accommodations,
 | 
			
		||||
        disable_couple_photos: settings.disable_couple_photos,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,9 @@ interface Constraints {
 | 
			
		||||
  member_country: LenConstraint;
 | 
			
		||||
  member_sex: LenConstraint;
 | 
			
		||||
  member_note: LenConstraint;
 | 
			
		||||
  accommodation_name_len: LenConstraint;
 | 
			
		||||
  accommodation_description_len: LenConstraint;
 | 
			
		||||
  accommodation_calendar_name_len: LenConstraint;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
interface OIDCProvider {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										124
									
								
								geneit_app/src/api/accommodations/AccommodationListApi.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								geneit_app/src/api/accommodations/AccommodationListApi.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
			
		||||
import { APIClient } from "../ApiClient";
 | 
			
		||||
import { Family } from "../FamilyApi";
 | 
			
		||||
 | 
			
		||||
export interface Accommodation {
 | 
			
		||||
  id: number;
 | 
			
		||||
  family_id: number;
 | 
			
		||||
  time_create: number;
 | 
			
		||||
  time_update: number;
 | 
			
		||||
  name: string;
 | 
			
		||||
  need_validation: boolean;
 | 
			
		||||
  description?: string;
 | 
			
		||||
  color?: string;
 | 
			
		||||
  open_to_reservations: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class AccommodationsList {
 | 
			
		||||
  private list: Accommodation[];
 | 
			
		||||
  private map: Map<number, Accommodation>;
 | 
			
		||||
 | 
			
		||||
  constructor(list: Accommodation[]) {
 | 
			
		||||
    this.list = list;
 | 
			
		||||
    this.map = new Map();
 | 
			
		||||
 | 
			
		||||
    for (const m of list) {
 | 
			
		||||
      this.map.set(m.id, m);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.list.sort((a, b) =>
 | 
			
		||||
      a.name.toLowerCase().localeCompare(b.name.toLocaleLowerCase())
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get isEmpty(): boolean {
 | 
			
		||||
    return this.list.length === 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get size(): number {
 | 
			
		||||
    return this.list.length;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get fullList(): Accommodation[] {
 | 
			
		||||
    return this.list;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  filter(predicate: (m: Accommodation) => boolean): Accommodation[] {
 | 
			
		||||
    return this.list.filter(predicate);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get openToReservationList(): Accommodation[] {
 | 
			
		||||
    return this.filter((a) => a.open_to_reservations);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get(id: number): Accommodation | undefined {
 | 
			
		||||
    return this.map.get(id);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface UpdateAccommodation {
 | 
			
		||||
  name: string;
 | 
			
		||||
  need_validation: boolean;
 | 
			
		||||
  description?: string;
 | 
			
		||||
  color?: string;
 | 
			
		||||
  open_to_reservations: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class AccommodationListApi {
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the list of accommodation of a family
 | 
			
		||||
   */
 | 
			
		||||
  static async GetListOfFamily(family: Family): Promise<AccommodationsList> {
 | 
			
		||||
    const data = (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "GET",
 | 
			
		||||
        uri: `/family/${family.family_id}/accommodations/list/list`,
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
 | 
			
		||||
    return new AccommodationsList(data);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a new accommodation
 | 
			
		||||
   */
 | 
			
		||||
  static async Create(
 | 
			
		||||
    family: Family,
 | 
			
		||||
    accommodation: UpdateAccommodation
 | 
			
		||||
  ): Promise<Accommodation> {
 | 
			
		||||
    return (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "POST",
 | 
			
		||||
        uri: `/family/${family.family_id}/accommodations/list/create`,
 | 
			
		||||
        jsonData: accommodation,
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Update an accommodation
 | 
			
		||||
   */
 | 
			
		||||
  static async Update(
 | 
			
		||||
    accommodation: Accommodation,
 | 
			
		||||
    update: UpdateAccommodation
 | 
			
		||||
  ): Promise<Accommodation> {
 | 
			
		||||
    return (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "PUT",
 | 
			
		||||
        uri: `/family/${accommodation.family_id}/accommodations/list/${accommodation.id}`,
 | 
			
		||||
        jsonData: update,
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Delete an accommodation
 | 
			
		||||
   */
 | 
			
		||||
  static async Delete(accommodation: Accommodation): Promise<Accommodation> {
 | 
			
		||||
    return (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "DELETE",
 | 
			
		||||
        uri: `/family/${accommodation.family_id}/accommodations/list/${accommodation.id}`,
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,69 @@
 | 
			
		||||
import { APIClient } from "../ApiClient";
 | 
			
		||||
import { Family } from "../FamilyApi";
 | 
			
		||||
 | 
			
		||||
export interface NewCalendarURL {
 | 
			
		||||
  accommodation_id?: number;
 | 
			
		||||
  name: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface AccommodationCalendarURL {
 | 
			
		||||
  id: number;
 | 
			
		||||
  family_id: number;
 | 
			
		||||
  accommodation_id: number;
 | 
			
		||||
  user_id: number;
 | 
			
		||||
  name: string;
 | 
			
		||||
  token: string;
 | 
			
		||||
  time_create: number;
 | 
			
		||||
  time_used: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class AccommodationsCalendarURLApi {
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a new accommodation calendar URL
 | 
			
		||||
   */
 | 
			
		||||
  static async Create(
 | 
			
		||||
    family: Family,
 | 
			
		||||
    calendar: NewCalendarURL
 | 
			
		||||
  ): Promise<AccommodationCalendarURL> {
 | 
			
		||||
    return (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "POST",
 | 
			
		||||
        uri: `/family/${family.family_id}/accommodations/reservations_calendars/create`,
 | 
			
		||||
        jsonData: calendar,
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get accommodation calendar URL route
 | 
			
		||||
   */
 | 
			
		||||
  static CalendarURL(c: AccommodationCalendarURL): string {
 | 
			
		||||
    return `${APIClient.backendURL()}/acccommodations_calendar/${c.token}`;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get accommodations calendars list
 | 
			
		||||
   */
 | 
			
		||||
  static async GetList(family: Family): Promise<AccommodationCalendarURL[]> {
 | 
			
		||||
    return (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "GET",
 | 
			
		||||
        uri: `/family/${family.family_id}/accommodations/reservations_calendars/list`,
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Delete an accommodation calendar
 | 
			
		||||
   */
 | 
			
		||||
  static async Delete(
 | 
			
		||||
    calendar: AccommodationCalendarURL
 | 
			
		||||
  ): Promise<AccommodationCalendarURL> {
 | 
			
		||||
    return (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "DELETE",
 | 
			
		||||
        uri: `/family/${calendar.family_id}/accommodations/reservations_calendars/${calendar.id}`,
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,175 @@
 | 
			
		||||
import { APIClient } from "../ApiClient";
 | 
			
		||||
import { Family } from "../FamilyApi";
 | 
			
		||||
import { Accommodation } from "./AccommodationListApi";
 | 
			
		||||
 | 
			
		||||
export enum ValidateResaResult {
 | 
			
		||||
  Success,
 | 
			
		||||
  Error,
 | 
			
		||||
  Conflict,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface AccommodationReservation {
 | 
			
		||||
  id: number;
 | 
			
		||||
  family_id: number;
 | 
			
		||||
  accommodation_id: number;
 | 
			
		||||
  user_id: number;
 | 
			
		||||
  time_create: number;
 | 
			
		||||
  time_update: number;
 | 
			
		||||
  reservation_start: number;
 | 
			
		||||
  reservation_end: number;
 | 
			
		||||
  validated?: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class AccommodationsReservationsList {
 | 
			
		||||
  private list: AccommodationReservation[];
 | 
			
		||||
  private map: Map<number, AccommodationReservation>;
 | 
			
		||||
 | 
			
		||||
  constructor(list: AccommodationReservation[]) {
 | 
			
		||||
    this.list = list;
 | 
			
		||||
    this.map = new Map();
 | 
			
		||||
 | 
			
		||||
    for (const m of list) {
 | 
			
		||||
      this.map.set(m.id, m);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.list.sort((a, b) => a.reservation_start - b.reservation_start);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get isEmpty(): boolean {
 | 
			
		||||
    return this.list.length === 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get size(): number {
 | 
			
		||||
    return this.list.length;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public get fullList(): AccommodationReservation[] {
 | 
			
		||||
    return this.list;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  filter(
 | 
			
		||||
    predicate: (m: AccommodationReservation) => boolean
 | 
			
		||||
  ): AccommodationReservation[] {
 | 
			
		||||
    return this.list.filter(predicate);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  forAccommodation(id: number): AccommodationReservation[] {
 | 
			
		||||
    return this.filter((a) => a.accommodation_id === id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  get(id: number): AccommodationReservation | undefined {
 | 
			
		||||
    return this.map.get(id);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export interface UpdateAccommodationReservation {
 | 
			
		||||
  start: number;
 | 
			
		||||
  end: number;
 | 
			
		||||
  accommodation_id: number;
 | 
			
		||||
  reservation_id?: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class AccommodationsReservationsApi {
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a new reservation
 | 
			
		||||
   */
 | 
			
		||||
  static async Create(
 | 
			
		||||
    family: Family,
 | 
			
		||||
    reservation: UpdateAccommodationReservation
 | 
			
		||||
  ): Promise<AccommodationReservation> {
 | 
			
		||||
    return (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "POST",
 | 
			
		||||
        uri: `/family/${family.family_id}/accommodations/reservations/accommodation/${reservation.accommodation_id}/create`,
 | 
			
		||||
        jsonData: {
 | 
			
		||||
          start: reservation.start,
 | 
			
		||||
          end: reservation.end,
 | 
			
		||||
        },
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the entire list of accommodations of a family
 | 
			
		||||
   */
 | 
			
		||||
  static async FullListOfFamily(
 | 
			
		||||
    family: Family
 | 
			
		||||
  ): Promise<AccommodationsReservationsList> {
 | 
			
		||||
    const data = (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "GET",
 | 
			
		||||
        uri: `/family/${family.family_id}/accommodations/reservations/full_list`,
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
 | 
			
		||||
    return new AccommodationsReservationsList(data);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Get the reservations of a given time interval for an accommodation
 | 
			
		||||
   */
 | 
			
		||||
  static async ReservationsForInterval(
 | 
			
		||||
    family: Family,
 | 
			
		||||
    accommodation: Accommodation,
 | 
			
		||||
    start: number,
 | 
			
		||||
    end: number
 | 
			
		||||
  ): Promise<AccommodationsReservationsList> {
 | 
			
		||||
    const data = (
 | 
			
		||||
      await APIClient.exec({
 | 
			
		||||
        method: "GET",
 | 
			
		||||
        uri: `/family/${family.family_id}/accommodations/reservations/accommodation/${accommodation.id}/for_interval?start=${start}&end=${end}`,
 | 
			
		||||
      })
 | 
			
		||||
    ).data;
 | 
			
		||||
 | 
			
		||||
    return new AccommodationsReservationsList(data);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Update a reservation
 | 
			
		||||
   */
 | 
			
		||||
  static async Update(
 | 
			
		||||
    family: Family,
 | 
			
		||||
    r: UpdateAccommodationReservation
 | 
			
		||||
  ): Promise<void> {
 | 
			
		||||
    await APIClient.exec({
 | 
			
		||||
      method: "PATCH",
 | 
			
		||||
      uri: `/family/${family.family_id}/accommodations/reservation/${r.reservation_id}`,
 | 
			
		||||
      jsonData: {
 | 
			
		||||
        start: r.start,
 | 
			
		||||
        end: r.end,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Delete a reservation
 | 
			
		||||
   */
 | 
			
		||||
  static async Delete(r: AccommodationReservation): Promise<void> {
 | 
			
		||||
    await APIClient.exec({
 | 
			
		||||
      method: "DELETE",
 | 
			
		||||
      uri: `/family/${r.family_id}/accommodations/reservation/${r.id}`,
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Validate or reject a reservation request
 | 
			
		||||
   */
 | 
			
		||||
  static async Validate(
 | 
			
		||||
    r: AccommodationReservation,
 | 
			
		||||
    accept: boolean
 | 
			
		||||
  ): Promise<ValidateResaResult> {
 | 
			
		||||
    const res = await APIClient.exec({
 | 
			
		||||
      method: "POST",
 | 
			
		||||
      uri: `/family/${r.family_id}/accommodations/reservation/${r.id}/validate`,
 | 
			
		||||
      jsonData: {
 | 
			
		||||
        validate: accept,
 | 
			
		||||
      },
 | 
			
		||||
      allowFail: true,
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (res.status >= 200 && res.status <= 299)
 | 
			
		||||
      return ValidateResaResult.Success;
 | 
			
		||||
    if (res.status === 409) return ValidateResaResult.Conflict;
 | 
			
		||||
    return ValidateResaResult.Error;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user