@@ -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