|
|
@@ -0,0 +1,208 @@
|
|
|
+"use client";
|
|
|
+
|
|
|
+import { format, parseISO } from "date-fns";
|
|
|
+import { es } from "date-fns/locale";
|
|
|
+import { Clock, User, FileText, Calendar as CalendarIcon } from "lucide-react";
|
|
|
+import { COLOR_PALETTE } from "@/utils/palette";
|
|
|
+import type { Appointment } from "@/types/appointments";
|
|
|
+import Link from "next/link";
|
|
|
+
|
|
|
+interface CalendarAppointmentsListProps {
|
|
|
+ appointments: Appointment[];
|
|
|
+ selectedDate: Date;
|
|
|
+}
|
|
|
+
|
|
|
+const estadoConfig = {
|
|
|
+ PENDIENTE: {
|
|
|
+ label: "Pendiente",
|
|
|
+ color: COLOR_PALETTE.warning[500],
|
|
|
+ bgColor: COLOR_PALETTE.warning[50],
|
|
|
+ borderColor: COLOR_PALETTE.warning[200]
|
|
|
+ },
|
|
|
+ APROBADA: {
|
|
|
+ label: "Aprobada",
|
|
|
+ color: COLOR_PALETTE.success[600],
|
|
|
+ bgColor: COLOR_PALETTE.success[50],
|
|
|
+ borderColor: COLOR_PALETTE.success[200]
|
|
|
+ },
|
|
|
+ COMPLETADA: {
|
|
|
+ label: "Completada",
|
|
|
+ color: COLOR_PALETTE.primary[600],
|
|
|
+ bgColor: COLOR_PALETTE.primary[50],
|
|
|
+ borderColor: COLOR_PALETTE.primary[200]
|
|
|
+ },
|
|
|
+ CANCELADA: {
|
|
|
+ label: "Cancelada",
|
|
|
+ color: COLOR_PALETTE.gray[500],
|
|
|
+ bgColor: COLOR_PALETTE.gray[50],
|
|
|
+ borderColor: COLOR_PALETTE.gray[200]
|
|
|
+ },
|
|
|
+ RECHAZADA: {
|
|
|
+ label: "Rechazada",
|
|
|
+ color: COLOR_PALETTE.error[600],
|
|
|
+ bgColor: COLOR_PALETTE.error[50],
|
|
|
+ borderColor: COLOR_PALETTE.error[200]
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+export function CalendarAppointmentsList({
|
|
|
+ appointments,
|
|
|
+ selectedDate,
|
|
|
+}: CalendarAppointmentsListProps) {
|
|
|
+
|
|
|
+ if (appointments.length === 0) {
|
|
|
+ return (
|
|
|
+ <div className="bg-white rounded-lg shadow-sm border border-gray-200 p-8">
|
|
|
+ <div className="text-center">
|
|
|
+ <CalendarIcon
|
|
|
+ className="mx-auto h-12 w-12 mb-3"
|
|
|
+ style={{ color: COLOR_PALETTE.gray[400] }}
|
|
|
+ />
|
|
|
+ <h3
|
|
|
+ className="text-lg font-medium mb-1"
|
|
|
+ style={{ color: COLOR_PALETTE.gray[900] }}
|
|
|
+ >
|
|
|
+ No hay citas programadas
|
|
|
+ </h3>
|
|
|
+ <p style={{ color: COLOR_PALETTE.gray[500] }}>
|
|
|
+ {format(selectedDate, "EEEE, d 'de' MMMM 'de' yyyy", { locale: es })}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ return (
|
|
|
+ <div className="space-y-4">
|
|
|
+ <div className="flex items-center justify-between">
|
|
|
+ <h3
|
|
|
+ className="text-lg font-semibold"
|
|
|
+ style={{ color: COLOR_PALETTE.gray[900] }}
|
|
|
+ >
|
|
|
+ Citas del {format(selectedDate, "d 'de' MMMM", { locale: es })}
|
|
|
+ </h3>
|
|
|
+ <span
|
|
|
+ className="text-sm font-medium px-3 py-1 rounded-full"
|
|
|
+ style={{
|
|
|
+ backgroundColor: COLOR_PALETTE.primary[50],
|
|
|
+ color: COLOR_PALETTE.primary[600]
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {appointments.length} {appointments.length === 1 ? 'cita' : 'citas'}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div className="space-y-3">
|
|
|
+ {appointments.map((appointment) => {
|
|
|
+ const config = estadoConfig[appointment.estado as keyof typeof estadoConfig];
|
|
|
+ const appointmentDate = appointment.fechaSolicitada
|
|
|
+ ? (typeof appointment.fechaSolicitada === 'string'
|
|
|
+ ? parseISO(appointment.fechaSolicitada)
|
|
|
+ : appointment.fechaSolicitada)
|
|
|
+ : null;
|
|
|
+
|
|
|
+ return (
|
|
|
+ <Link
|
|
|
+ key={appointment.id}
|
|
|
+ href={`/appointments/${appointment.id}`}
|
|
|
+ className="block"
|
|
|
+ >
|
|
|
+ <div
|
|
|
+ className="bg-white rounded-lg shadow-sm border p-4 hover:shadow-md transition-all cursor-pointer"
|
|
|
+ style={{
|
|
|
+ borderColor: COLOR_PALETTE.gray[200],
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ <div className="flex items-start justify-between gap-4">
|
|
|
+ <div className="flex-1 space-y-3">
|
|
|
+ {/* Hora y estado */}
|
|
|
+ <div className="flex items-center gap-3 flex-wrap">
|
|
|
+ <div
|
|
|
+ className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg"
|
|
|
+ style={{ backgroundColor: COLOR_PALETTE.gray[50] }}
|
|
|
+ >
|
|
|
+ <Clock className="h-4 w-4" style={{ color: COLOR_PALETTE.gray[600] }} />
|
|
|
+ <span
|
|
|
+ className="font-semibold text-sm"
|
|
|
+ style={{ color: COLOR_PALETTE.gray[900] }}
|
|
|
+ >
|
|
|
+ {appointmentDate ? format(appointmentDate, "HH:mm", { locale: es }) : 'Sin hora'}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ <span
|
|
|
+ className="text-xs font-semibold px-3 py-1.5 rounded-lg"
|
|
|
+ style={{
|
|
|
+ backgroundColor: config.bgColor,
|
|
|
+ color: config.color,
|
|
|
+ }}
|
|
|
+ >
|
|
|
+ {config.label}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* Paciente */}
|
|
|
+ <div className="flex items-center gap-2">
|
|
|
+ <div
|
|
|
+ className="p-1.5 rounded-lg"
|
|
|
+ style={{ backgroundColor: COLOR_PALETTE.primary[50] }}
|
|
|
+ >
|
|
|
+ <User className="h-4 w-4" style={{ color: COLOR_PALETTE.primary[600] }} />
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <p className="text-xs" style={{ color: COLOR_PALETTE.gray[500] }}>
|
|
|
+ Paciente
|
|
|
+ </p>
|
|
|
+ <p className="font-medium" style={{ color: COLOR_PALETTE.gray[900] }}>
|
|
|
+ {appointment.paciente?.name} {appointment.paciente?.lastname}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* Motivo */}
|
|
|
+ <div className="flex items-start gap-2">
|
|
|
+ <div
|
|
|
+ className="p-1.5 rounded-lg mt-0.5"
|
|
|
+ style={{ backgroundColor: COLOR_PALETTE.gray[50] }}
|
|
|
+ >
|
|
|
+ <FileText className="h-4 w-4" style={{ color: COLOR_PALETTE.gray[600] }} />
|
|
|
+ </div>
|
|
|
+ <div className="flex-1">
|
|
|
+ <p className="text-xs mb-1" style={{ color: COLOR_PALETTE.gray[500] }}>
|
|
|
+ Motivo de consulta
|
|
|
+ </p>
|
|
|
+ <p
|
|
|
+ className="text-sm line-clamp-2"
|
|
|
+ style={{ color: COLOR_PALETTE.gray[700] }}
|
|
|
+ >
|
|
|
+ {appointment.motivoConsulta}
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ {/* Flecha indicadora */}
|
|
|
+ <div className="flex items-center">
|
|
|
+ <div
|
|
|
+ className="p-2 rounded-lg"
|
|
|
+ style={{ backgroundColor: COLOR_PALETTE.gray[50] }}
|
|
|
+ >
|
|
|
+ <svg
|
|
|
+ className="h-5 w-5"
|
|
|
+ style={{ color: COLOR_PALETTE.gray[400] }}
|
|
|
+ fill="none"
|
|
|
+ viewBox="0 0 24 24"
|
|
|
+ stroke="currentColor"
|
|
|
+ >
|
|
|
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
|
|
|
+ </svg>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </Link>
|
|
|
+ );
|
|
|
+ })}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ );
|
|
|
+}
|