bugfix: delete action removed from appointment banners to avoid banner sizing issues. the appointment can be deleted via edit modal.

This commit is contained in:
2026-05-17 17:14:00 +03:30
parent 375fdc60b4
commit e119d02759
5 changed files with 65 additions and 56 deletions

View File

@@ -1,12 +1,8 @@
'use client';
import { Trash2 } from 'lucide-react';
import type { AppointmentColumnProvider, AppointmentRecord } from '@/types/appointment';
import { formatHourLabel } from '@/lib/appointmentTime';
import {
purposeDeleteIconClass,
purposeStyle,
} from '@/components/ui/appointments/appointmentPurposeStyles';
import { purposeStyle } from '@/components/ui/appointments/appointmentPurposeStyles';
const HOUR_PX = 40;
const HOURS = Array.from({ length: 24 }, (_, i) => i);
@@ -27,13 +23,17 @@ function layoutBlock(apt: AppointmentRecord, day: Date): { top: string; height:
return { top: `${top}%`, height: `${height}%` };
}
function appointmentDurationMinutes(apt: AppointmentRecord): number {
const start = new Date(apt.startAt).getTime();
const end = new Date(apt.endAt).getTime();
return Math.max(0, Math.round((end - start) / 60_000));
}
interface AppointmentScheduleGridProps {
day: Date;
providers: AppointmentColumnProvider[];
appointments: AppointmentRecord[];
canBook: boolean;
canDelete?: boolean;
onDeleteAppointment?: (id: string) => void;
onSlotClick: (hour: number, providerUserId: string, providerName: string) => void;
onAppointmentClick?: (appointment: AppointmentRecord) => void;
}
@@ -43,8 +43,6 @@ export function AppointmentScheduleGrid({
providers,
appointments,
canBook,
canDelete = false,
onDeleteAppointment,
onSlotClick,
onAppointmentClick,
}: AppointmentScheduleGridProps) {
@@ -121,35 +119,22 @@ export function AppointmentScheduleGrid({
if (!pos) {
return null;
}
const durationMin = appointmentDurationMinutes(apt);
return (
<button
type="button"
key={apt.id}
onClick={() => onAppointmentClick?.(apt)}
className={`absolute left-0.5 right-0.5 rounded-[var(--radius-sm)] border pointer-events-auto z-10 flex flex-row items-center gap-1.5 px-1.5 py-1 min-h-[36px] text-left ${purposeStyle(apt.purpose)} focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/35`}
style={{ top: pos.top, height: pos.height, minHeight: 36 }}
className={`absolute left-0.5 right-0.5 min-h-0 overflow-hidden rounded-[var(--radius-sm)] border pointer-events-auto z-10 flex flex-col justify-start px-1.5 py-0.5 text-left ${purposeStyle(apt.purpose)} focus:outline-none focus-visible:ring-2 focus-visible:ring-primary/35`}
style={{ top: pos.top, height: pos.height }}
>
<div className="pointer-events-none flex-1 min-w-0 overflow-hidden text-left">
<p className="text-[11px] font-medium leading-tight truncate">
{apt.patient.firstName} {apt.patient.lastName}
<p className="text-[11px] font-medium leading-tight truncate pointer-events-none">
{apt.patient.firstName} {apt.patient.lastName}
</p>
{durationMin >= 30 && apt.patient.phone && (
<p className="text-[10px] opacity-90 truncate pointer-events-none">
{apt.patient.phone}
</p>
{apt.patient.phone && (
<p className="text-[10px] opacity-90 truncate">{apt.patient.phone}</p>
)}
</div>
{canDelete && onDeleteAppointment && (
<button
type="button"
className="group pointer-events-auto shrink-0 self-center z-20 mr-0.5 ml-0.5 inline-flex cursor-pointer items-center justify-center rounded-[var(--radius-sm)] bg-transparent p-1 outline-none focus-visible:ring-2 focus-visible:ring-primary/35"
aria-label="Delete appointment"
title="Delete appointment"
onClick={(e) => {
e.stopPropagation();
onDeleteAppointment(apt.id);
}}
>
<Trash2 className={`w-4 h-4 ${purposeDeleteIconClass(apt.purpose)}`} />
</button>
)}
</button>
);