feat: wire department management to real API

Remove FALLBACK_DEPARTMENTS array and fallback logic. Normalize fields
from snake_case backend response (total_employees, department_head,
department_email, transfers_enabled). Empty list shown on API failure.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Ashwin Kumar 2026-03-27 19:22:55 +01:00
parent c911a0c450
commit 0d9837b8dc

View file

@ -16,16 +16,6 @@ type DepartmentRecord = CrudRecord & {
visibility?: 'INTERNAL' | 'EXTERNAL';
};
const FALLBACK_DEPARTMENTS: DepartmentRecord[] = [
{ id: 'd1', name: 'Engineering', code: 'ENG-001', description: 'Software development and technical architecture', totalEmployees: 45, departmentHead: 'Arun Kumar', status: 'ACTIVE', updatedAt: '2026-03-01', createdDate: '2026-01-15' },
{ id: 'd2', name: 'Marketing', code: 'MKT-002', description: 'Brand management and digital marketing', totalEmployees: 23, departmentHead: 'Priya Sharma', status: 'ACTIVE', updatedAt: '2026-03-01', createdDate: '2026-01-15' },
{ id: 'd3', name: 'Human Resources', code: 'HR-003', description: 'Employee relations and talent acquisition', totalEmployees: 12, departmentHead: 'Rekha Nair', status: 'ACTIVE', updatedAt: '2026-03-01', createdDate: '2026-01-20' },
{ id: 'd4', name: 'Finance', code: 'FIN-004', description: 'Financial planning and accounting', totalEmployees: 18, departmentHead: 'Suresh Menon', status: 'ACTIVE', updatedAt: '2026-03-01', createdDate: '2026-01-20' },
{ id: 'd5', name: 'Operations', code: 'OPS-005', description: 'Business operations and process management', totalEmployees: 31, departmentHead: 'Deepak Verma', status: 'ACTIVE', updatedAt: '2026-03-01', createdDate: '2026-02-01' },
{ id: 'd6', name: 'Customer Success', code: 'CS-006', description: 'Client support and relationship management', totalEmployees: 27, departmentHead: 'Anita Pillai', status: 'ACTIVE', updatedAt: '2026-03-01', createdDate: '2026-02-01' },
{ id: 'd7', name: 'Product', code: 'PRD-007', description: 'Product strategy and development', totalEmployees: 19, departmentHead: 'Kiran Rao', status: 'INACTIVE', updatedAt: '2026-03-01', createdDate: '2026-02-10' },
{ id: 'd8', name: 'Sales', code: 'SAL-008', description: 'Revenue generation and client acquisition', totalEmployees: 34, departmentHead: 'Manoj Iyer', status: 'ACTIVE', updatedAt: '2026-03-01', createdDate: '2026-02-10' },
];
const permissionGroups = [
{ title: 'Employee Management', items: ['View Employees', 'Create Employees', 'Edit Employees', 'Delete Employees'] },
@ -50,16 +40,16 @@ function normalizeDepartment(item: any, idx: number): DepartmentRecord {
return {
id: String(item.id ?? `dep-${idx + 1}`),
name: String(item.name ?? ''),
code: String(item.code ?? ''),
description: String(item.description ?? ''),
totalEmployees: Number(item.totalEmployees ?? item.total_employees ?? 0),
departmentHead: String(item.departmentHead ?? item.department_head ?? ''),
departmentEmail: String(item.departmentEmail ?? item.department_email ?? ''),
transfersEnabled: Boolean(item.transfersEnabled ?? item.transfers_enabled ?? false),
code: item.code ? String(item.code) : undefined,
description: item.description ? String(item.description) : undefined,
totalEmployees: Number(item.total_employees ?? 0),
departmentHead: item.department_head ? String(item.department_head) : undefined,
departmentEmail: item.department_email ? String(item.department_email) : undefined,
transfersEnabled: Boolean(item.transfers_enabled ?? false),
visibility: String(item.visibility ?? 'INTERNAL').toUpperCase() === 'EXTERNAL' ? 'EXTERNAL' : 'INTERNAL',
status: isActive ? 'ACTIVE' : 'INACTIVE',
updatedAt: String(item.updatedAt ?? item.updated_at ?? ''),
createdDate: String(item.createdDate ?? item.created_at ?? ''),
updatedAt: String(item.updated_at ?? ''),
createdDate: String(item.created_at ?? ''),
};
}
@ -123,38 +113,30 @@ export default function DepartmentManagementPage() {
setIsLoading(true);
setError('');
try {
try {
const params = new URLSearchParams({
page: '1',
per_page: '100',
q: search().trim(),
});
if (statusFilter() !== 'all') {
params.set('status', statusFilter());
}
const res = await fetch(`${API}/api/admin/departments?${params.toString()}`);
if (!res.ok) {
throw new Error(`Request failed (${res.status})`);
}
const payload = (await res.json().catch(() => null)) as DepartmentListResponse | null;
const list = Array.isArray(payload)
? payload
: Array.isArray(payload?.departments)
? payload.departments
: Array.isArray(payload?.data)
? payload.data
: Array.isArray(payload?.items)
? payload.items
: [];
if (list.length === 0) {
setRows(FALLBACK_DEPARTMENTS);
} else {
setRows(list.map(normalizeDepartment));
}
} catch {
setRows(FALLBACK_DEPARTMENTS);
setError('Could not reach departments API, showing fallback data.');
const params = new URLSearchParams({
page: '1',
per_page: '100',
q: search().trim(),
});
if (statusFilter() !== 'all') {
params.set('status', statusFilter());
}
const res = await fetch(`${API}/api/admin/departments?${params.toString()}`);
if (!res.ok) throw new Error(`Request failed (${res.status})`);
const payload = (await res.json().catch(() => null)) as DepartmentListResponse | null;
const list = Array.isArray(payload)
? payload
: Array.isArray(payload?.departments)
? payload.departments
: Array.isArray(payload?.data)
? payload.data
: Array.isArray(payload?.items)
? payload.items
: [];
setRows(list.map(normalizeDepartment));
} catch (err: any) {
setError(err?.message || 'Could not reach departments API.');
setRows([]);
} finally {
setIsLoading(false);
}