Se crea funcionalidad de exportar pdf desde front y generar historial de version de cambios se agrego una libreri jspdf
This commit is contained in:
@@ -20,6 +20,7 @@ import { AuroraButton } from "@/components/effect/aurora-button"
|
||||
import { DeletePlanButton } from "@/components/planes/DeletePlan"
|
||||
import { AddAsignaturaButton } from "@/components/planes/AddAsignaturaButton"
|
||||
import { DescargarPdfButton } from "@/components/planes/GenerarPdfButton"
|
||||
import { DownloadPlanPDF } from "@/components/planes/DownloadPlanPDF"
|
||||
|
||||
type LoaderData = { plan: PlanFull; asignaturas: AsignaturaLite[] }
|
||||
|
||||
@@ -105,7 +106,8 @@ function RouteComponent() {
|
||||
{/* <div className='flex gap-2'> */}
|
||||
<EditPlanButton plan={plan} />
|
||||
<AdjustAIButton plan={plan} />
|
||||
<DescargarPdfButton planId={plan.id} opcion="plan" />
|
||||
{/* <DescargarPdfButton planId={plan.id} opcion="plan" /> */}
|
||||
<DownloadPlanPDF plan={plan} />
|
||||
<DescargarPdfButton planId={plan.id} opcion="asignaturas" />
|
||||
<DeletePlanButton planId={plan.id} />
|
||||
{/* </div> */}
|
||||
@@ -203,33 +205,77 @@ function StatCard({ label, value = "—", Icon = Icons.Info, accent, className =
|
||||
|
||||
/* ===== Editar ===== */
|
||||
function EditPlanButton({ plan }: { plan: PlanFull }) {
|
||||
const auth = useSupabaseAuth()
|
||||
const [open, setOpen] = useState(false)
|
||||
const [form, setForm] = useState<Partial<PlanFull>>({})
|
||||
const [saving, setSaving] = useState(false)
|
||||
const qc = useQueryClient()
|
||||
|
||||
// Función para comparar valores y generar diffs tipo JSON Patch
|
||||
function generateDiff(oldData: PlanFull, newData: Partial<PlanFull>) {
|
||||
const changes: any[] = []
|
||||
for (const key of Object.keys(newData)) {
|
||||
const oldValue = (oldData as any)[key]
|
||||
const newValue = (newData as any)[key]
|
||||
if (newValue !== undefined && newValue !== oldValue) {
|
||||
changes.push({
|
||||
op: "replace",
|
||||
path: `/${key}`,
|
||||
from: oldValue,
|
||||
value: newValue
|
||||
})
|
||||
}
|
||||
}
|
||||
return changes
|
||||
}
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: async (payload: Partial<PlanFull>) => {
|
||||
const { error } = await supabase.from('plan_estudios').update({
|
||||
nombre: payload.nombre ?? plan.nombre,
|
||||
nivel: payload.nivel ?? plan.nivel,
|
||||
duracion: payload.duracion ?? plan.duracion,
|
||||
total_creditos: payload.total_creditos ?? plan.total_creditos,
|
||||
}).eq('id', plan.id)
|
||||
// 1️⃣ Generar las diferencias antes del update
|
||||
const diff = generateDiff(plan, payload)
|
||||
|
||||
// 2️⃣ Guardar respaldo (solo si hay cambios)
|
||||
if (diff.length > 0) {
|
||||
const { error: backupError } = await supabase.from("historico_cambios").insert({
|
||||
id_plan_estudios: plan.id,
|
||||
json_cambios: diff, // jsonb
|
||||
user_id:auth.user?.id,
|
||||
created_at: new Date().toISOString()
|
||||
})
|
||||
if (backupError) throw backupError
|
||||
}
|
||||
|
||||
// 3️⃣ Actualizar el plan principal
|
||||
const { error } = await supabase
|
||||
.from("plan_estudios")
|
||||
.update({
|
||||
nombre: payload.nombre ?? plan.nombre,
|
||||
nivel: payload.nivel ?? plan.nivel,
|
||||
duracion: payload.duracion ?? plan.duracion,
|
||||
total_creditos: payload.total_creditos ?? plan.total_creditos,
|
||||
})
|
||||
.eq("id", plan.id)
|
||||
|
||||
if (error) throw error
|
||||
},
|
||||
|
||||
onMutate: async (payload) => {
|
||||
await qc.cancelQueries({ queryKey: planKeys.byId(plan.id) })
|
||||
const prev = qc.getQueryData<PlanFull>(planKeys.byId(plan.id))
|
||||
qc.setQueryData<PlanFull>(planKeys.byId(plan.id), (old) => old ? { ...old, ...payload } as PlanFull : old as any)
|
||||
qc.setQueryData<PlanFull>(
|
||||
planKeys.byId(plan.id),
|
||||
(old) => (old ? { ...old, ...payload } as PlanFull : old as any)
|
||||
)
|
||||
return { prev }
|
||||
},
|
||||
|
||||
onError: (_e, _vars, ctx) => {
|
||||
if (ctx?.prev) qc.setQueryData(planKeys.byId(plan.id), ctx.prev)
|
||||
},
|
||||
|
||||
onSettled: async () => {
|
||||
await qc.invalidateQueries({ queryKey: planKeys.byId(plan.id) })
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
async function save() {
|
||||
|
||||
Reference in New Issue
Block a user