Skip to content

Commit b4cb437

Browse files
committed
Refactorización del componente ImportantDates para mejorar la gestión de estados. Se ha renombrado la función getBadgeColor a getStatus y se ha simplificado la lógica de obtención de estado, incluyendo un nuevo formato para los colores y etiquetas. Además, se ha añadido una leyenda de estados más clara y se ha optimizado la presentación de las fechas importantes, mejorando la experiencia del usuario al visualizar la información.
1 parent 40d71f2 commit b4cb437

File tree

1 file changed

+111
-91
lines changed

1 file changed

+111
-91
lines changed

resources/js/pages/LegalCases/ImportantDates.tsx

Lines changed: 111 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -147,40 +147,41 @@ export default function ImportantDates({ legalCase, importantDates, nextImportan
147147
setIsDeleteDialogOpen(true);
148148
};
149149

150-
const getBadgeColor = (is_expired: boolean, end_date: string) => {
150+
const getStatus = (is_expired: boolean, end_date: string) => {
151151
if (is_expired) {
152-
return 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300';
152+
return {
153+
label: 'Cerrado',
154+
color: 'bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-300',
155+
bg: 'bg-red-50 dark:bg-red-950/20 border-red-200 dark:border-red-900/30',
156+
};
153157
}
154-
// Si no está vencido pero la fecha ya pasó
155-
if (new Date(end_date) < new Date()) {
156-
return 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-300';
158+
// Parsear end_date como local (no UTC)
159+
let end;
160+
if (/^\d{4}-\d{2}-\d{2}$/.test(end_date)) {
161+
const [year, month, day] = end_date.split('-').map(Number);
162+
end = new Date(year, month - 1, day);
163+
} else {
164+
end = new Date(end_date);
157165
}
158-
// Si está activo y la fecha no ha pasado
159-
return 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300';
160-
};
161-
162-
const getBadgeText = (is_expired: boolean, end_date: string) => {
163-
if (is_expired) {
164-
return 'Inactivo';
165-
}
166-
// Si no está vencido pero la fecha ya pasó
167-
if (new Date(end_date) < new Date()) {
168-
return 'Expirado';
166+
const today = new Date();
167+
const todayYMD = [today.getFullYear(), today.getMonth(), today.getDate()];
168+
const endYMD = [end.getFullYear(), end.getMonth(), end.getDate()];
169+
const isEndBeforeToday =
170+
endYMD[0] < todayYMD[0] ||
171+
(endYMD[0] === todayYMD[0] && endYMD[1] < todayYMD[1]) ||
172+
(endYMD[0] === todayYMD[0] && endYMD[1] === todayYMD[1] && endYMD[2] < todayYMD[2]);
173+
if (isEndBeforeToday) {
174+
return {
175+
label: 'Transcurrido',
176+
color: 'bg-orange-100 text-orange-800 dark:bg-orange-900 dark:text-orange-300',
177+
bg: 'bg-orange-50 dark:bg-orange-950/20 border-orange-200 dark:border-orange-900/30',
178+
};
169179
}
170-
// Si está activo y la fecha no ha pasado
171-
return 'Activo';
172-
};
173-
174-
const getBackgroundColor = (is_expired: boolean, end_date: string) => {
175-
if (is_expired) {
176-
return 'bg-red-50 dark:bg-red-950/20 border-red-200 dark:border-red-900/30';
177-
}
178-
// Si no está vencido pero la fecha ya pasó
179-
if (new Date(end_date) < new Date()) {
180-
return 'bg-orange-50 dark:bg-orange-950/20 border-orange-200 dark:border-orange-900/30';
181-
}
182-
// Si está activo y la fecha no ha pasado
183-
return 'bg-green-50 dark:bg-green-950/20 border-green-200 dark:border-green-900/30';
180+
return {
181+
label: 'En curso',
182+
color: 'bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-300',
183+
bg: 'bg-green-50 dark:bg-green-950/20 border-green-200 dark:border-green-900/30',
184+
};
184185
};
185186

186187
return (
@@ -208,25 +209,6 @@ export default function ImportantDates({ legalCase, importantDates, nextImportan
208209
</Button>
209210
</div>
210211

211-
{/* Leyenda de estados */}
212-
<div className="mb-6 p-4 bg-gray-50 dark:bg-zinc-800 rounded-lg border border-gray-200 dark:border-zinc-700">
213-
<h2 className="text-sm font-medium mb-2 text-gray-700 dark:text-gray-300">Leyenda de Estados:</h2>
214-
<div className="flex flex-wrap gap-4">
215-
<div className="flex items-center gap-2">
216-
<span className="w-3 h-3 rounded-full bg-green-100 dark:bg-green-900 border border-green-800 dark:border-green-300"></span>
217-
<span className="text-sm text-gray-600 dark:text-gray-400">Plazos activos con fecha futura</span>
218-
</div>
219-
<div className="flex items-center gap-2">
220-
<span className="w-3 h-3 rounded-full bg-orange-100 dark:bg-orange-900 border border-orange-800 dark:border-orange-300"></span>
221-
<span className="text-sm text-gray-600 dark:text-gray-400">Plazos activos pero con fecha ya pasada (Expirado)</span>
222-
</div>
223-
<div className="flex items-center gap-2">
224-
<span className="w-3 h-3 rounded-full bg-red-100 dark:bg-red-900 border border-red-800 dark:border-red-300"></span>
225-
<span className="text-sm text-gray-600 dark:text-gray-400">Plazos marcados como vencidos</span>
226-
</div>
227-
</div>
228-
</div>
229-
230212
{/* Próxima fecha importante */}
231213
{nextImportantDate && (
232214
<div className="mb-6 p-4 bg-blue-50 dark:bg-blue-900/20 rounded-lg border border-blue-200 dark:border-blue-800">
@@ -243,6 +225,25 @@ export default function ImportantDates({ legalCase, importantDates, nextImportan
243225
</div>
244226
)}
245227

228+
{/* Leyenda de estados */}
229+
<div className="mb-6 p-4 bg-gray-50 dark:bg-zinc-800 rounded-lg border border-gray-200 dark:border-zinc-700">
230+
<h2 className="text-sm font-medium mb-2 text-gray-700 dark:text-gray-300">Leyenda de Estados:</h2>
231+
<div className="flex flex-wrap gap-4">
232+
<div className="flex items-center gap-2">
233+
<span className="w-3 h-3 rounded-full bg-orange-100 dark:bg-orange-900 border border-orange-800 dark:border-orange-300"></span>
234+
<span className="text-sm text-gray-600 dark:text-gray-400">Plazos activos pero con fecha ya pasada <span className="font-semibold">(Transcurrido)</span></span>
235+
</div>
236+
<div className="flex items-center gap-2">
237+
<span className="w-3 h-3 rounded-full bg-green-100 dark:bg-green-900 border border-green-800 dark:border-green-300"></span>
238+
<span className="text-sm text-gray-600 dark:text-gray-400">Plazos activos con fecha futura <span className="font-semibold">(En curso)</span></span>
239+
</div>
240+
<div className="flex items-center gap-2">
241+
<span className="w-3 h-3 rounded-full bg-red-100 dark:bg-red-900 border border-red-800 dark:border-red-300"></span>
242+
<span className="text-sm text-gray-600 dark:text-gray-400">Plazos que ya no están activos y se conservan solo para referencia <span className="font-semibold">(Cerrado)</span></span>
243+
</div>
244+
</div>
245+
</div>
246+
246247
{/* Lista de fechas importantes */}
247248
<div className="space-y-4">
248249
{importantDates
@@ -254,49 +255,68 @@ export default function ImportantDates({ legalCase, importantDates, nextImportan
254255
// Si ambos están vencidos o no vencidos, ordenamos por fecha de fin
255256
return new Date(a.end_date).getTime() - new Date(b.end_date).getTime();
256257
})
257-
.map((date) => (
258-
<div
259-
key={date.id}
260-
className={`flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 p-4 rounded-lg border ${getBackgroundColor(date.is_expired, date.end_date)}`}
261-
>
262-
<div className="flex-1 space-y-1">
263-
<div className="flex items-center gap-2">
264-
<h3 className="font-medium">{date.title}</h3>
265-
<span className={`px-2 py-1 rounded-full text-xs font-medium ${getBadgeColor(date.is_expired, date.end_date)}`}>
266-
{getBadgeText(date.is_expired, date.end_date)}
267-
</span>
268-
</div>
269-
{date.description && (
270-
<p className="text-sm text-gray-600 dark:text-gray-400">
271-
{date.description}
272-
</p>
273-
)}
274-
<div className="flex flex-col gap-y-1 text-sm text-gray-500 dark:text-gray-400 mt-2">
275-
<span>Inicio: {formatDateSafe(date.start_date)}</span>
276-
<span>Fin: {formatDateSafe(date.end_date)}</span>
277-
<span>Creado por: {date.created_by && date.created_by.name ? date.created_by.name : 'N/A'}</span>
278-
</div>
279-
</div>
280-
<div className="flex gap-2 justify-end mt-2 sm:mt-0">
281-
<Button
282-
variant="ghost"
283-
size="icon"
284-
onClick={() => openEditDialog(date)}
258+
.map((date) => {
259+
const status = getStatus(date.is_expired, date.end_date);
260+
return (
261+
<div
262+
key={date.id}
263+
className={`flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 p-4 rounded-lg border ${status.bg}`}
285264
>
286-
<Pencil className="h-4 w-4" />
287-
</Button>
288-
<Button
289-
variant="ghost"
290-
size="icon"
291-
className="text-red-500 hover:text-red-700"
292-
onClick={() => openDeleteDialog(date)}
293-
>
294-
<Trash2 className="h-4 w-4" />
295-
</Button>
296-
</div>
297-
</div>
298-
))}
265+
<div className="flex-1 space-y-1">
266+
<div className="flex items-center gap-2">
267+
<h3 className="font-medium">{date.title}</h3>
268+
<span className={`px-2 py-1 rounded-full text-xs font-medium ${status.color}`}>
269+
{status.label}
270+
</span>
271+
</div>
272+
{date.description && (
273+
<>
274+
<div className="flex flex-col gap-y-1 text-sm text-gray-500 dark:text-gray-400 mt-2">
275+
<span>Inicio: {formatDateSafe(date.start_date)}</span>
276+
<span>Fin: {formatDateSafe(date.end_date)}</span>
277+
</div>
278+
<p className="text-sm text-gray-600 dark:text-gray-400 mt-2">
279+
{date.description}
280+
</p>
281+
</>
282+
)}
283+
<div className="flex flex-col gap-y-1 text-sm text-gray-500 dark:text-gray-400 mt-2">
284+
<span>Creado por: {date.created_by && date.created_by.name ? date.created_by.name : 'N/A'}</span>
285+
</div>
286+
</div>
287+
<div className="flex gap-2 justify-end mt-2 sm:mt-0">
288+
<Button
289+
variant="ghost"
290+
size="icon"
291+
onClick={() => openEditDialog(date)}
292+
>
293+
<Pencil className="h-4 w-4" />
294+
</Button>
295+
<Button
296+
variant="ghost"
297+
size="icon"
298+
className="text-red-500 hover:text-red-700"
299+
onClick={() => openDeleteDialog(date)}
300+
>
301+
<Trash2 className="h-4 w-4" />
302+
</Button>
303+
</div>
304+
</div>
305+
);
306+
})}
299307
</div>
308+
309+
{/* Sugerencia sobre la próxima fecha importante */}
310+
<div className="mt-8 mb-4 p-4 bg-gray-50 dark:bg-zinc-800 rounded-lg border border-gray-200 dark:border-zinc-700">
311+
<h3 className="text-base font-semibold text-gray-800 dark:text-gray-100 mb-2 flex items-center gap-2">
312+
<span className="inline-flex items-center justify-center"><svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 text-yellow-500 mr-1" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01M21 12A9 9 0 1 1 3 12a9 9 0 0 1 18 0Z" /></svg></span>
313+
¿Cómo se determina la próxima fecha importante?
314+
</h3>
315+
<p className="text-sm text-gray-700 dark:text-gray-200 mb-2 block">
316+
El plazo activo con fecha de finalización más cercana a la fecha actual será considerado la <b>fecha importante</b> para el expediente. Esta fecha se resalta automáticamente en la parte superior de la página.
317+
</p>
318+
</div>
319+
300320
{/* Leyenda de discriminación de días hábiles/no hábiles */}
301321
<div className="mt-8">
302322
<div className="p-4 bg-gray-50 dark:bg-zinc-800 rounded-lg border border-gray-200 dark:border-zinc-700">
@@ -309,7 +329,7 @@ export default function ImportantDates({ legalCase, importantDates, nextImportan
309329
Para mayor claridad, aparte de un titulo descriptivo para el rango de fechas, se recomienda que en la descripción indiques explícitamente qué días son hábiles y cuáles no, por ejemplo:
310330
</p>
311331
<div className="bg-gray-100 dark:bg-zinc-900 rounded p-3 text-xs text-gray-800 dark:text-gray-100 border border-gray-200 dark:border-zinc-700">
312-
<p className="mb-1">Días hábiles: 19/05/2025, 22/05/2025, 23/05/2025 | Días no hábiles: 20/05/2025, 21/05/2025</p>
332+
<p className="mb-1">Días hábiles: 12/05/2025, 13/05/2025, 14/05/2025, 19/05/2025 {'< | >'} Días no hábiles: 15/05/2025, 16/05/2025, 17/05/2025, 18/05/2025</p>
313333
</div>
314334
<p className="text-sm text-gray-600 dark:text-gray-400 mt-2 flex items-center gap-2">
315335
<span className="inline-flex items-center justify-center"></span>

0 commit comments

Comments
 (0)