/opt/mawid/apps/api/src/appointments
Edit: /opt/mawid/apps/api/src/appointments/appointments.controller.ts (2437B)
import { BadRequestException, Body, Controller, Get, Param, Patch, Post, Query } from '@nestjs/common';
import {
cancelAppointmentSchema,
createAppointmentSchema,
updateAppointmentSchema,
type CancelAppointmentInput,
type CreateAppointmentInput,
type UpdateAppointmentInput,
} from '@mawid/shared';
import { ClinicId } from '../auth/current-user.decorator';
import { ZodValidationPipe } from '../common/zod-validation.pipe';
import { AppointmentsService } from './appointments.service';
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
@Controller('appointments')
export class AppointmentsController {
constructor(private readonly appointments: AppointmentsService) {}
@Get()
list(@ClinicId() clinicId: string, @Query('from') from?: string, @Query('to') to?: string) {
const fromDate = from ? new Date(from) : new Date();
const toDate = to ? new Date(to) : new Date(fromDate.getTime() + 7 * 24 * 3600_000);
if (Number.isNaN(fromDate.getTime()) || Number.isNaN(toDate.getTime())) {
throw new BadRequestException('Invalid from/to');
}
return this.appointments.list(clinicId, fromDate, toDate);
}
@Get('availability')
availability(
@ClinicId() clinicId: string,
@Query('serviceId') serviceId?: string,
@Query('staffId') staffId?: string,
@Query('fromDate') fromDate?: string,
@Query('toDate') toDate?: string,
) {
if (!serviceId) throw new BadRequestException('serviceId is required');
if (!fromDate || !DATE_RE.test(fromDate) || !toDate || !DATE_RE.test(toDate)) {
throw new BadRequestException('fromDate/toDate must be YYYY-MM-DD');
}
return this.appointments.availability(clinicId, serviceId, staffId || undefined, fromDate, toDate);
}
@Post()
create(
@ClinicId() clinicId: string,
@Body(new ZodValidationPipe(createAppointmentSchema)) body: CreateAppointmentInput,
) {
return this.appointments.create(clinicId, body);
}
@Patch(':id')
update(
@ClinicId() clinicId: string,
@Param('id') id: string,
@Body(new ZodValidationPipe(updateAppointmentSchema)) body: UpdateAppointmentInput,
) {
return this.appointments.update(clinicId, id, body);
}
@Post(':id/cancel')
cancel(
@ClinicId() clinicId: string,
@Param('id') id: string,
@Body(new ZodValidationPipe(cancelAppointmentSchema)) body: CancelAppointmentInput,
) {
return this.appointments.cancel(clinicId, id, body.reason);
}
}