import { Suspense } from "react"; import { ReportsPageClient } from "@/components/reports/ReportsPageClient"; import { aggregateReport, DATE_SCOPED_MEASURES, type GroupDimension, type Measure, type OrgLookups, type ReportEmployee, } from "@/lib/reports"; import { createClient } from "@/lib/supabase/server"; import type { EmploymentStatus, EmploymentType } from "@/lib/supabase/types"; type SearchParams = { measure?: string; group?: string; split?: string; division?: string; location?: string; status?: string; employment?: string; from?: string; to?: string; }; export default async function ReportsPage({ searchParams }: { searchParams: Promise }) { const params = await searchParams; const supabase = await createClient(); const measure = (params.measure as Measure) || "headcount"; const group = (params.group as GroupDimension) || "division"; const split = (params.split as GroupDimension) || undefined; const [{ data: divisions }, { data: departments }, { data: teams }, { data: locations }] = await Promise.all([ supabase.from("divisions").select("id, name").order("name"), supabase.from("departments").select("id, name"), supabase.from("teams").select("id, name, department_id"), supabase.from("locations").select("id, name").order("name"), ]); const departmentNameById = new Map((departments ?? []).map((d) => [d.id, d.name])); const lookups: OrgLookups = { divisionName: new Map((divisions ?? []).map((d) => [d.id, d.name])), departmentNameByTeam: new Map((teams ?? []).map((t) => [t.id, departmentNameById.get(t.department_id) ?? "Unbekannt"])), teamName: new Map((teams ?? []).map((t) => [t.id, t.name])), locationName: new Map((locations ?? []).map((l) => [l.id, l.name])), }; let query = supabase .from("employees_directory") .select( "id, first_name, last_name, job_title, division_id, team_id, location_id, status, employment_type, contract_type, entry_date, exit_date, weekly_hours, monthly_salary_gross, source, paygrade, birth_date, gender" ); if (params.division) query = query.eq("division_id", params.division); if (params.location) query = query.eq("location_id", params.location); if (params.status) query = query.eq("status", params.status as EmploymentStatus); if (params.employment) query = query.eq("employment_type", params.employment as EmploymentType); const isDateScoped = DATE_SCOPED_MEASURES.includes(measure); const currentYear = new Date().getFullYear(); const from = params.from || `${currentYear}-01-01`; const to = params.to || `${currentYear}-12-31`; if (isDateScoped) { if (measure === "hires") query = query.gte("entry_date", from).lte("entry_date", to); else query = query.gte("exit_date", from).lte("exit_date", to).not("exit_date", "is", null); } else if (!params.status) { query = query.in("status", ["Aktiv", "Karenz"]); } const { data: employeesData } = await query; const employees = (employeesData ?? []) as ReportEmployee[]; const rows = aggregateReport(employees, measure, group, split ?? null, lookups); const total = measureValueForTotal(rows, measure); const { data: { user }, } = await supabase.auth.getUser(); const { data: savedReports } = user ? await supabase.from("saved_reports").select("id, name, config").eq("created_by", user.id).order("created_at", { ascending: false }) : { data: [] }; return ( ); } function measureValueForTotal(rows: { value: number; count: number }[], measure: Measure): number { if (["headcount", "fte", "hires", "exits"].includes(measure)) { return rows.reduce((s, r) => s + r.value, 0); } // averages/ratios: weight by underlying count for a sensible overall figure const totalCount = rows.reduce((s, r) => s + r.count, 0); if (totalCount === 0) return 0; return rows.reduce((s, r) => s + r.value * r.count, 0) / totalCount; }