94 lines
No EOL
3.9 KiB
TypeScript
94 lines
No EOL
3.9 KiB
TypeScript
// app/(app)/staff/virements-salaires/page.tsx
|
|
import { cookies } from "next/headers";
|
|
import NextDynamic from "next/dynamic";
|
|
import { createSbServer } from "@/lib/supabaseServer";
|
|
import { Metadata } from "next";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "Virements salaires (Staff) | Espace Paie Odentas",
|
|
};
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
const SalaryTransfersGrid = NextDynamic<any>(() => import("../../../../components/staff/SalaryTransfersGrid"), { ssr: false });
|
|
|
|
export default async function StaffSalaryTransfersPage() {
|
|
const sb = createSbServer();
|
|
const { data: { user } } = await sb.auth.getUser();
|
|
|
|
if (!user) {
|
|
return (
|
|
<main className="p-6">
|
|
<h1 className="text-lg font-semibold">Accès refusé</h1>
|
|
<p className="text-sm text-slate-600">Vous devez être connecté.</p>
|
|
</main>
|
|
);
|
|
}
|
|
|
|
const { data: me } = await sb.from("staff_users").select("is_staff").eq("user_id", user.id).maybeSingle();
|
|
const isStaff = !!me?.is_staff;
|
|
if (!isStaff) {
|
|
return (
|
|
<main className="p-6">
|
|
<h1 className="text-lg font-semibold">Accès refusé</h1>
|
|
<p className="text-sm text-slate-600">Cette page est réservée au Staff.</p>
|
|
</main>
|
|
);
|
|
}
|
|
|
|
// initial fetch: server-side list of latest salary transfers (limited)
|
|
const { data: salaryTransfers, error } = await sb
|
|
.from("salary_transfers")
|
|
.select("*")
|
|
.order("period_month", { ascending: false })
|
|
.limit(200);
|
|
|
|
// Server-side debug logging to help diagnose empty results (will appear in Next.js server logs)
|
|
try {
|
|
console.log("[staff/virements-salaires] supabase fetch salary_transfers result count:", Array.isArray(salaryTransfers) ? salaryTransfers.length : typeof salaryTransfers);
|
|
if (error) console.log("[staff/virements-salaires] supabase error:", error);
|
|
if (salaryTransfers && salaryTransfers.length > 0) console.log("[staff/virements-salaires] sample:", salaryTransfers.slice(0, 3));
|
|
} catch (e) {
|
|
// ignore logging errors
|
|
}
|
|
|
|
if (error) {
|
|
return (
|
|
<main className="p-6">
|
|
<h1 className="text-lg font-semibold">Erreur</h1>
|
|
<p className="text-sm text-rose-600">{error.message}</p>
|
|
<div className="mt-4 p-3 bg-slate-50 rounded text-sm text-slate-700">
|
|
<div><strong>Debug</strong></div>
|
|
<div>Supabase returned an error when reading <code>salary_transfers</code>. See server logs for details.</div>
|
|
</div>
|
|
</main>
|
|
);
|
|
}
|
|
|
|
// active org (optional) for staff we allow global view; keep cookie reading for parity
|
|
const c = cookies();
|
|
const activeOrgId = c.get("active_org_id")?.value || null;
|
|
|
|
return (
|
|
<main className="p-6">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h1 className="text-lg font-semibold">Virements de Salaires (Staff)</h1>
|
|
</div>
|
|
|
|
<div className="rounded-2xl border bg-white p-4">
|
|
{(!salaryTransfers || salaryTransfers.length === 0) && (
|
|
<div className="mb-4 p-3 rounded bg-yellow-50 text-sm text-slate-800 border">
|
|
<div><strong>Debug:</strong> Aucun virement de salaire trouvé côté serveur (initialData vide).</div>
|
|
<div className="mt-2 text-xs text-slate-600">Si tu utilises Realtime / RLS, vérifie que la table <code>salary_transfers</code> est publiée pour Realtime et que les policies autorisent la lecture pour ton utilisateur staff.</div>
|
|
<details className="mt-2 text-xs">
|
|
<summary className="cursor-pointer text-xs underline">Voir le payload serveur (preview)</summary>
|
|
<pre className="mt-2 max-h-48 overflow-auto text-xs bg-slate-50 p-2 rounded border">{JSON.stringify(salaryTransfers ?? [], null, 2)}</pre>
|
|
</details>
|
|
</div>
|
|
)}
|
|
{/* Client-side interactive grid */}
|
|
<SalaryTransfersGrid initialData={salaryTransfers ?? []} activeOrgId={activeOrgId} />
|
|
</div>
|
|
</main>
|
|
);
|
|
} |