import { Injectable } from '@nestjs/common' import { classToPlain, plainToClass } from 'class-transformer' import { format } from 'date-fns' import { isEmpty } from 'lodash' import { Availability, AvailabilityTime } from '../models' import { HttpService } from '../services/http' import { parseISO } from '../utils/date' import { BaseRepository } from './base.repository' const DATE_FORMAT = 'yyyy-MM-dd' const ATTRIBUTES = ` id date user_id ` const INSERT = ` mutation insertAvailability($availability: availability_insert_input!) { insert_availability_one(object: $availability) { ${ATTRIBUTES} } } ` const INSERT_WITH_NESTED_AVAILABILITY_TIMES = ` mutation insertAvailabilityWithNestedAvailabilityTimes($availabilities: [availability_insert_input!]!) { insert_availability(objects: $availabilities) { affected_rows returning { ${ATTRIBUTES} available_times { id status time timezone } } } } ` const GET_BY_USER_AND_DATE = ` query availability($user_id: String!, $date: date!) { availability(where: {user_id: {_eq: $user_id}, date: {_eq: $date}}) { ${ATTRIBUTES} } } ` const GET = ` query availability($id: uuid!) { availability(where: {id: {_eq: $id}}) { ${ATTRIBUTES} } } ` const FIND_SCHEDULED_AVAILABILITY = ` query findAllAppointmentsDate($userId: String!) { dates: availability_aggregate(where: {user_id: {_eq: $userId}, available_times: {appointment_id: {_is_null: false}}}) { nodes { date } } } ` @Injectable() export class AvailabilityRepository extends BaseRepository { constructor(protected readonly httpService: HttpService) { super(httpService, 'availability') } async create(availability: Availability): Promise { const qv = { availability: classToPlain(availability) } const { data } = await this.fetchGraphQL({ body: { query: INSERT, variables: qv }, }) return data.insert_availability_one.id } async createWithNestedAvailabilityTimes( availability: Availability, availabilityTimes: Array, ): Promise { const qv = { availabilities: [ { ...classToPlain(availability), available_times: { data: availabilityTimes.map(availabilityTime => classToPlain(availabilityTime)) }, }, ], } const { data } = await this.fetchGraphQL({ body: { query: INSERT_WITH_NESTED_AVAILABILITY_TIMES, variables: qv }, }) return plainToClass(Availability, data.insert_availability.returning) } async getByUserAndDate(userId: string, date: Date): Promise { const { data } = await this.fetchGraphQL({ body: { query: GET_BY_USER_AND_DATE, variables: { user_id: userId, date: format(date, DATE_FORMAT) }, }, }) return isEmpty(data.availability) ? null : plainToClass(Availability, data.availability[0]) } async get(id: string): Promise { const { data } = await this.fetchGraphQL({ body: { query: GET, variables: { id } }, }) return isEmpty(data.availability) ? null : plainToClass(Availability, data.availability[0]) } async findScheduledAvailabilityDates(userId: string): Promise { const { data } = await this.fetchGraphQL({ body: { query: FIND_SCHEDULED_AVAILABILITY, variables: { userId } }, }) return data?.dates?.nodes?.map(row => parseISO(row.date)) || [] } async delete(id: string): Promise { const result = await super.delete(id, { returning: ['id'] }) return result.id } }