Files
edr-platform/apps/edr-freight-web/backoffice/src/super-admin/hooks/useDepartments.ts
2026-07-10 10:41:48 +03:00

254 lines
6.6 KiB
TypeScript

import { useState, useEffect } from "react";
import axios from "axios";
import { Position } from "./usePositions";
interface ApiResponse<T> {
success: boolean;
data: T;
message?: string;
}
export interface Department {
id: string;
name: string;
positions: Position[];
isExpanded?: boolean;
parentDepartmentId?: string;
}
export const useDepartments = (unitId: string) => {
const [departments, setDepartments] = useState<Department[]>([]);
const [selectedDepartmentId, setSelectedDepartmentId] = useState<string>("");
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
// Fetch departments for a unit
const fetchDepartments = async () => {
if (!unitId) {
setDepartments([]);
setSelectedDepartmentId("");
return;
}
setLoading(true);
try {
// In a real app, this would be an API call
setTimeout(() => {
// Mock departments for this unit
const mockDepartments: Department[] = [
{
id: "dept1",
name: "Directorate",
positions: [],
isExpanded: true,
},
{
id: "dept2",
name: "Development",
positions: [],
isExpanded: false,
},
{
id: "dept3",
name: "Operations",
positions: [],
isExpanded: false,
},
];
setDepartments(mockDepartments);
if (mockDepartments.length > 0) {
setSelectedDepartmentId(mockDepartments[0].id);
} else {
setSelectedDepartmentId("");
}
setLoading(false);
}, 500);
} catch (err) {
setError(
err instanceof Error ? err : new Error("Failed to fetch departments")
);
setLoading(false);
}
};
// Create a new department
const createDepartment = async (
departmentData: Partial<Department>
): Promise<Department> => {
if (!unitId) {
throw new Error("No unit selected");
}
setLoading(true);
try {
// In a real app, this would be an API call
// const response = await axios.post<ApiResponse<Department>>(
// `/api/units/${unitId}/departments`,
// departmentData
// );
// const newDepartment = response.data.data;
// For now, simulate API response
const newDepartment: Department = {
id: `dept-${Date.now()}`,
name: departmentData.name || "New Department",
positions: [],
isExpanded: false,
parentDepartmentId: departmentData.parentDepartmentId,
};
setDepartments((prev) => [...prev, newDepartment]);
setLoading(false);
return newDepartment;
} catch (err) {
setError(
err instanceof Error ? err : new Error("Failed to create department")
);
setLoading(false);
throw err;
}
};
// Update an existing department
const updateDepartment = async (
departmentId: string,
updates: Partial<Department>
): Promise<Department> => {
setLoading(true);
try {
// In a real app, this would be an API call
// const response = await axios.put<ApiResponse<Department>>(
// `/api/departments/${departmentId}`,
// updates
// );
// const updatedDepartment = response.data.data;
// For now, simulate API response
const updatedDepartments = departments.map((department) =>
department.id === departmentId
? { ...department, ...updates }
: department
);
setDepartments(updatedDepartments);
setLoading(false);
const updatedDepartment = updatedDepartments.find(
(d) => d.id === departmentId
);
if (!updatedDepartment) {
throw new Error("Department not found after update");
}
return updatedDepartment;
} catch (err) {
setError(
err instanceof Error ? err : new Error("Failed to update department")
);
setLoading(false);
throw err;
}
};
// Delete a department
const deleteDepartment = async (departmentId: string): Promise<void> => {
setLoading(true);
try {
// In a real app, this would be an API call
// await axios.delete<ApiResponse<void>>(`/api/departments/${departmentId}`);
// For now, simulate API response
setDepartments((prev) =>
prev.filter((department) => department.id !== departmentId)
);
// If the deleted department was selected, select another department
if (selectedDepartmentId === departmentId) {
const remaining = departments.filter(
(department) => department.id !== departmentId
);
if (remaining.length > 0) {
setSelectedDepartmentId(remaining[0].id);
} else {
setSelectedDepartmentId("");
}
}
setLoading(false);
} catch (err) {
setError(
err instanceof Error ? err : new Error("Failed to delete department")
);
setLoading(false);
throw err;
}
};
// Add a sub-department
const addSubDepartment = async (
parentDepartmentId: string,
name: string
): Promise<Department> => {
const subdepartment: Partial<Department> = {
name,
parentDepartmentId,
};
return createDepartment(subdepartment);
};
// Toggle expand/collapse for a department
const toggleDepartmentExpand = (departmentId: string) => {
setDepartments((prev) =>
prev.map((department) =>
department.id === departmentId
? { ...department, isExpanded: !department.isExpanded }
: department
)
);
};
// Get root-level departments (no parent)
const getRootDepartments = () => {
return departments.filter((department) => !department.parentDepartmentId);
};
// Get sub-departments of a department
const getSubDepartments = (parentDepartmentId: string) => {
return departments.filter(
(department) => department.parentDepartmentId === parentDepartmentId
);
};
// Select a department
const selectDepartment = (departmentId: string) => {
setSelectedDepartmentId(departmentId);
};
// Load departments when unitId changes
useEffect(() => {
fetchDepartments();
}, [unitId]);
return {
departments,
selectedDepartmentId,
selectedDepartment: departments.find(
(department) => department.id === selectedDepartmentId
),
loading,
error,
fetchDepartments,
createDepartment,
updateDepartment,
deleteDepartment,
addSubDepartment,
toggleDepartmentExpand,
getRootDepartments,
getSubDepartments,
selectDepartment,
};
};