{viewMode !== 'lista' && (
@@ -805,34 +932,34 @@ const Agenda: FC = () => {
- {gridHours.map((hour) => (
-
- |
- {`${String(hour).padStart(2, '0')}:00`}
+ {gridSlots.map((slot) => (
+ |
+ |
+ {horaFloatStr(slot)}
|
{gridColumns.map((col) => {
- const cell = gridCellAppointments(col.doctorId, hour);
- const bloqueo = bloqueoEnCelda(col.doctorId, hour);
- const cellKey = `${col.key}-${hour}`;
+ const cell = gridCellAppointments(col.doctorId, slot);
+ const bloqueo = bloqueoEnCelda(col.doctorId, slot);
+ const cellKey = `${col.key}-${slot}`;
return (
{ if (dragApt && !bloqueo) { e.preventDefault(); setDropTarget(cellKey); } }}
onDragLeave={() => setDropTarget((t) => (t === cellKey ? null : t))}
- onDrop={(e) => { e.preventDefault(); handleDrop(col.doctorId, hour); }}
- className={`p-1.5 align-top border-b border-l border-theme-border transition-colors ${dropTarget === cellKey ? 'bg-theme-accent-bg' : ''}`}
+ onDrop={(e) => { e.preventDefault(); handleDrop(col.doctorId, slot); }}
+ className={`p-1 align-top border-b border-l border-theme-border transition-colors ${dropTarget === cellKey ? 'bg-theme-accent-bg' : ''}`}
>
{bloqueo ? (
-
+
Bloqueado{bloqueo.motivo ? ` — ${bloqueo.motivo}` : ''}
) : cell.length === 0 ? (
- {
key={apt.id}
onClick={() => openAptDetail(apt)}
{...chipDragProps(apt)}
- className={`mb-1.5 rounded-xl border-l-4 px-2.5 py-1.5 text-xs shadow-card transition-shadow hover:shadow-soft ${
+ className={`mb-1 rounded-lg border-l-4 px-2 py-1 text-[11px] leading-tight shadow-card transition-shadow hover:shadow-soft ${
DRAGGABLE_STATES.includes(apt.state) ? 'cursor-grab active:cursor-grabbing' : 'cursor-pointer'
} ${gridStateClass[apt.state] || 'border-theme-border-strong bg-theme-bg text-theme-heading'} ${quickFilter === 'libres' ? 'opacity-40' : ''}`}
title={`${apt.time} · ${apt.patient} · ${apt.service} · ${apt.state}`}
@@ -883,9 +1010,9 @@ const Agenda: FC = () => {
|
Médico
|
- {gridHours.map((hour) => (
-
- {`${String(hour).padStart(2, '0')}:00`}
+ {gridSlots.map((slot) => (
+ |
+ {horaFloatStr(slot)}
|
))}
@@ -908,34 +1035,34 @@ const Agenda: FC = () => {
- {gridHours.map((hour) => {
- const cell = gridCellAppointments(col.doctorId, hour);
- const bloqueo = bloqueoEnCelda(col.doctorId, hour);
- const cellKey = `${col.key}-${hour}`;
+ {gridSlots.map((slot) => {
+ const cell = gridCellAppointments(col.doctorId, slot);
+ const bloqueo = bloqueoEnCelda(col.doctorId, slot);
+ const cellKey = `${col.key}-${slot}`;
return (
{ if (dragApt && !bloqueo) { e.preventDefault(); setDropTarget(cellKey); } }}
onDragLeave={() => setDropTarget((t) => (t === cellKey ? null : t))}
- onDrop={(e) => { e.preventDefault(); handleDrop(col.doctorId, hour); }}
- className={`p-1 align-top border-b border-l border-theme-border transition-colors ${dropTarget === cellKey ? 'bg-theme-accent-bg' : ''}`}
+ onDrop={(e) => { e.preventDefault(); handleDrop(col.doctorId, slot); }}
+ className={`p-0.5 align-top border-b border-l border-theme-border transition-colors ${dropTarget === cellKey ? 'bg-theme-accent-bg' : ''}`}
>
{bloqueo ? (
-
+
) : cell.length === 0 ? (
) : (
cell.map((apt) => (
@@ -943,7 +1070,7 @@ const Agenda: FC = () => {
key={apt.id}
onClick={() => openAptDetail(apt)}
{...chipDragProps(apt)}
- className={`mb-1 rounded-lg border-l-2 px-1.5 py-1 text-[11px] leading-tight shadow-card transition-shadow hover:shadow-soft ${
+ className={`mb-0.5 rounded border-l-2 px-1 py-0.5 text-[10px] leading-tight shadow-card transition-shadow hover:shadow-soft ${
DRAGGABLE_STATES.includes(apt.state) ? 'cursor-grab active:cursor-grabbing' : 'cursor-pointer'
} ${gridStateClass[apt.state] || 'border-theme-border-strong bg-theme-bg text-theme-heading'} ${quickFilter === 'libres' ? 'opacity-40' : ''}`}
title={`${apt.time} · ${apt.patient} · ${apt.service} · ${apt.state}`}
@@ -970,7 +1097,7 @@ const Agenda: FC = () => {
title="Sin citas"
subtitle="No hay citas para los filtros seleccionados."
actionLabel="Nueva cita"
- onAction={() => setCreateOpen(true)}
+ onAction={openCreate}
/>
) : (
<>
@@ -1045,6 +1172,7 @@ const Agenda: FC = () => {
options={[{ value: '', label: 'Seleccionar médico...' }, ...doctors.map((d) => ({ value: String(d.id), label: d.name }))]}
value={bloqueoForm.doctor_id}
onChange={(e) => setBloqueoForm({ ...bloqueoForm, doctor_id: e.target.value })}
+ disabled={isMedico}
/>
{
footer={
<>
-
+
>
}
>
|