Merge pull request 'Se agrega paginacion a historial' (#95) from issue/82-paginacin-del-historial-para-evitar-que-crezca-al- into main

Reviewed-on: #95
This commit was merged in pull request #95.
This commit is contained in:
2026-02-12 16:55:56 +00:00
4 changed files with 74 additions and 17 deletions

View File

@@ -176,18 +176,31 @@ export async function plan_asignaturas_list(
return data ?? [] return data ?? []
} }
export async function plans_history(planId: UUID): Promise<Array<CambioPlan>> { export async function plans_history(
planId: UUID,
page: number = 0,
pageSize: number = 4,
): Promise<{ data: Array<CambioPlan>; count: number }> {
// Cambiamos el retorno
const supabase = supabaseBrowser() const supabase = supabaseBrowser()
const { data, error } = await supabase const from = page * pageSize
const to = from + pageSize - 1
const { data, error, count } = await supabase
.from('cambios_plan') .from('cambios_plan')
.select( .select(
'id,plan_estudio_id,cambiado_por,cambiado_en,tipo,campo,valor_anterior,valor_nuevo', 'id,plan_estudio_id,cambiado_por,cambiado_en,tipo,campo,valor_anterior,valor_nuevo',
{ count: 'exact' }, // <--- Pedimos el conteo exacto
) )
.eq('plan_estudio_id', planId) .eq('plan_estudio_id', planId)
.order('cambiado_en', { ascending: false }) .order('cambiado_en', { ascending: false })
.range(from, to)
throwIfError(error) throwIfError(error)
return data ?? [] return {
data: data ?? [],
count: count ?? 0,
}
} }
/** Wizard: crear plan manual (Edge Function) */ /** Wizard: crear plan manual (Edge Function) */

View File

@@ -80,11 +80,17 @@ export function usePlanAsignaturas(planId: UUID | null | undefined) {
}) })
} }
export function usePlanHistorial(planId: UUID | null | undefined) { export function usePlanHistorial(
planId: UUID | null | undefined,
page: number,
) {
return useQuery({ return useQuery({
queryKey: planId ? qk.planHistorial(planId) : ['planes', 'historial', null], queryKey: planId
queryFn: () => plans_history(planId as UUID), ? [...qk.planHistorial(planId), page]
: ['planes', 'historial', null, page],
queryFn: () => plans_history(planId as UUID, page),
enabled: Boolean(planId), enabled: Boolean(planId),
placeholderData: (previousData) => previousData,
}) })
} }

View File

@@ -12,10 +12,13 @@ import {
Eye, Eye,
History, History,
Calendar, Calendar,
ChevronLeft,
ChevronRight,
} from 'lucide-react' } from 'lucide-react'
import { useEffect, useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { Card, CardContent } from '@/components/ui/card' import { Card, CardContent } from '@/components/ui/card'
import { import {
Dialog, Dialog,
@@ -57,15 +60,14 @@ const getEventConfig = (tipo: string, campo: string) => {
function RouteComponent() { function RouteComponent() {
const { planId } = Route.useParams() const { planId } = Route.useParams()
const { data: rawData, isLoading } = usePlanHistorial(planId) const [page, setPage] = useState(0)
const pageSize = 4
const { data: response, isLoading } = usePlanHistorial(planId, page)
const rawData = response?.data ?? []
const totalRecords = response?.count ?? 0
const totalPages = Math.ceil(totalRecords / pageSize)
const [structure, setStructure] = useState<any>(null) const [structure, setStructure] = useState<any>(null)
const { data } = usePlan(planId) const { data } = usePlan(planId)
console.log('analizando estructura')
console.log(data?.estructuras_plan?.definicion?.properties)
// console.log(structure)
// ESTADOS PARA EL MODAL
const [selectedEvent, setSelectedEvent] = useState<any>(null) const [selectedEvent, setSelectedEvent] = useState<any>(null)
const [isModalOpen, setIsModalOpen] = useState(false) const [isModalOpen, setIsModalOpen] = useState(false)
@@ -229,6 +231,46 @@ function RouteComponent() {
</div> </div>
)) ))
)} )}
{historyEvents.length > 0 && (
<div className="mt-10 ml-20 flex items-center justify-between border-t pt-4">
<p className="text-xs text-slate-500">
Mostrando {rawData.length} de {totalRecords} cambios
</p>
<div className="flex items-center gap-4">
<Button
variant="outline"
size="sm"
onClick={() => {
setPage((p) => Math.max(0, p - 1))
window.scrollTo(0, 0) // Opcional: volver arriba
}}
disabled={page === 0 || isLoading}
>
<ChevronLeft className="mr-2 h-4 w-4" />
Anterior
</Button>
<span className="text-sm font-medium text-slate-700">
Página {page + 1} de {totalPages || 1}
</span>
<Button
variant="outline"
size="sm"
onClick={() => {
setPage((p) => p + 1)
window.scrollTo(0, 0)
}}
// Ahora se deshabilita si llegamos a la última página real
disabled={page + 1 >= totalPages || isLoading}
>
Siguiente
<ChevronRight className="ml-2 h-4 w-4" />
</Button>
</div>
</div>
)}
</div> </div>
{/* MODAL DE COMPARACIÓN CON SCROLL INTERNO */} {/* MODAL DE COMPARACIÓN CON SCROLL INTERNO */}

View File

@@ -163,10 +163,6 @@ function RouteComponent() {
) )
}, [data]) }, [data])
useEffect(() => {
console.log(uploadedFiles)
}, [uploadedFiles])
// 2. Manejar el estado inicial si viene de "Datos Generales" // 2. Manejar el estado inicial si viene de "Datos Generales"
useEffect(() => { useEffect(() => {
const state = routerState.location.state as any const state = routerState.location.state as any