Compare commits

...

2 Commits

7 changed files with 148 additions and 36 deletions

View File

@ -0,0 +1,7 @@
{
"totalCompanies": 1,
"totalBranches": 3,
"totalDepartments": 5,
"totalDesignations": 4,
"totalEmployees": 245
}

View File

@ -9,9 +9,9 @@ import LeaveRouter from '../../features/leave/routes/LeaveRouter';
import ApprovalRouter from '../../features/leave/routes/ApprovalRouter';
import AttendanceSummaryRouter from '../../features/attendance/routes/AttendanceSummaryRouter';
import LeaveSummaryRouter from '../../features/leave/routes/LeaveSummaryRouter';
import ManageEmployeesRouter from '../../features/dashboard/routes/ManageEmployeesRouter';
import ManageAdminsRouter from '../../features/dashboard/routes/ManageAdminsRouter';
import PolicyRouter from '../../features/dashboard/routes/PolicyRouter';
import MasterDataRouter from '../../features/employee-management/routes/MasterDataRouter'; // New Import
export default function MainLayout() {
const [isCollapsed, setIsCollapsed] = useState(false);
@ -40,7 +40,7 @@ export default function MainLayout() {
<Route path="/approval" element={<ApprovalRouter />} />
<Route path="/attendance-summary/*" element={<AttendanceSummaryRouter />} />
<Route path="/leave-summary" element={<LeaveSummaryRouter />} />
<Route path="/manage-employees" element={<ManageEmployeesRouter />} />
<Route path="/master-data/*" element={<MasterDataRouter />} />
<Route path="/manage-admins" element={<ManageAdminsRouter />} />
<Route path="/policies" element={<PolicyRouter />} />

View File

@ -5,13 +5,15 @@ import { getSidebarItems, type NavItem } from './types/sidebarConfig';
import { Link, useLocation } from 'react-router-dom';
import {
LayoutDashboard, CalendarCheck, Plane, CheckCircle, BarChart3, ClipboardList,
Menu, Users, ShieldUser, ScrollText, ChevronDown, FileText, CalendarDays, ClipboardCheck // Added ClipboardCheck
Menu, Users, ShieldUser, ScrollText, ChevronDown, FileText, CalendarDays, ClipboardCheck,
Database, Building, Network, Briefcase, Tag // Added new icons
} from 'lucide-react';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const iconMap: Record<string, any> = {
LayoutDashboard, CalendarCheck, Plane, CheckCircle, BarChart3, ClipboardList,
Users, ShieldUser, ScrollText, FileText, CalendarDays, ClipboardCheck // Added ClipboardCheck
Users, ShieldUser, ScrollText, FileText, CalendarDays, ClipboardCheck,
Database, Building, Network, Briefcase, Tag // Added new icons
};
export default function Sidebar({ isCollapsed, setIsCollapsed }: { isCollapsed: boolean; setIsCollapsed: (v: boolean) => void }) {
@ -43,7 +45,8 @@ export default function Sidebar({ isCollapsed, setIsCollapsed }: { isCollapsed:
{hasChildren ? (
<button
onClick={() => toggleDropdown(item.name)}
className={`w-full flex items-center px-4 py-3 transition-colors duration-200 text-left ${isChildActive ? 'text-white' : 'text-blue-100 hover:bg-sidebar-hover hover:text-white'
className={`w-full flex items-center px-4 py-3 transition-colors duration-200 text-left ${
isChildActive ? 'text-white' : 'text-blue-100 hover:bg-sidebar-hover hover:text-white'
} border-l-4 ${isChildActive ? 'border-action' : 'border-transparent'}`}
>
{Icon && <Icon size={20} className="flex-shrink-0" />}
@ -55,7 +58,8 @@ export default function Sidebar({ isCollapsed, setIsCollapsed }: { isCollapsed:
) : (
<Link
to={item.path!}
className={`flex items-center px-4 py-3 transition-colors duration-200 text-left ${isActive ? 'bg-sidebar-active text-white border-l-4 border-action' : 'text-blue-100 hover:bg-sidebar-hover hover:text-white border-l-4 border-transparent'
className={`flex items-center px-4 py-3 transition-colors duration-200 text-left ${
isActive ? 'bg-sidebar-active text-white border-l-4 border-action' : 'text-blue-100 hover:bg-sidebar-hover hover:text-white border-l-4 border-transparent'
}`}
>
{Icon && <Icon size={20} className="flex-shrink-0" />}

View File

@ -18,9 +18,7 @@ export const getSidebarItems = (role: UserRole): NavItem[] => {
return [...baseItems, { name: 'Approval', icon: 'CheckCircle', path: '/approval' }];
}
if (role === 'admin') {
return [
...baseItems,
const adminItems: NavItem[] = [
{
name: 'Attendance Summary',
icon: 'BarChart3',
@ -28,30 +26,33 @@ export const getSidebarItems = (role: UserRole): NavItem[] => {
{ name: 'Dashboard', icon: 'LayoutDashboard', path: '/attendance-summary/dashboard' },
{ name: 'Monthly Report', icon: 'FileText', path: '/attendance-summary/monthly' },
{ name: 'Daily Report', icon: 'CalendarDays', path: '/attendance-summary/daily' },
{ name: 'Regularization', icon: 'ClipboardCheck', path: '/attendance-summary/regularization' }, // New Item
...(role === 'admin' ? [{ name: 'Regularization', icon: 'ClipboardCheck', path: '/attendance-summary/regularization' }] : [])
]
},
{ name: 'Leave Summary', icon: 'ClipboardList', path: '/leave-summary' },
{ name: 'Manage Employees', icon: 'Users', path: '/manage-employees' },
{
name: 'Master Data',
icon: 'Database',
children: [
{ name: 'Dashboard', icon: 'LayoutDashboard', path: '/master-data/dashboard' },
{ name: 'Manage Company', icon: 'Building', path: '/master-data/company' },
{ name: 'Manage Branches', icon: 'Network', path: '/master-data/branches' },
{ name: 'Manage Departments', icon: 'Briefcase', path: '/master-data/departments' },
{ name: 'Manage Designations', icon: 'Tag', path: '/master-data/designations' },
{ name: 'Manage Employees', icon: 'Users', path: '/master-data/employees' },
]
},
];
if (role === 'admin') {
return [...baseItems, ...adminItems];
}
if (role === 'superadmin') {
return [
...baseItems,
{
name: 'Attendance Summary',
icon: 'BarChart3',
children: [
{ name: 'Dashboard', icon: 'LayoutDashboard', path: '/attendance-summary/dashboard' },
{ name: 'Monthly Report', icon: 'FileText', path: '/attendance-summary/monthly' },
{ name: 'Daily Report', icon: 'CalendarDays', path: '/attendance-summary/daily' },
// SuperAdmin does not get Regularization based on your requirement
]
},
{ name: 'Leave Summary', icon: 'ClipboardList', path: '/leave-summary' },
...adminItems,
{ name: 'Manage Admins', icon: 'ShieldUser', path: '/manage-admins' },
{ name: 'Manage Employees', icon: 'Users', path: '/manage-employees' },
{ name: 'Policy and Rules', icon: 'ScrollText', path: '/policies' },
];
}

View File

@ -0,0 +1,17 @@
import { useQuery } from '@tanstack/react-query';
import { fetchMockData } from '../../../api/client';
export interface MasterDataSummary {
totalCompanies: number;
totalBranches: number;
totalDepartments: number;
totalDesignations: number;
totalEmployees: number;
}
export const useMasterDataSummary = () => {
return useQuery<MasterDataSummary>({
queryKey: ['masterDataSummary'],
queryFn: () => fetchMockData<MasterDataSummary>('master-data/summary.json'),
});
};

View File

@ -0,0 +1,59 @@
import { Building, Network, Briefcase, Tag, Users } from 'lucide-react';
import Loader from '../../../components/ui/Loader';
import ErrorState from '../../../components/ui/ErrorState';
import StatCard from '../../attendance/components/summary/StatCard'; // Reusing StatCard
import { useMasterDataSummary } from '../api/useMasterData';
export default function MasterDataDashboard() {
const { data: summary, isLoading, isError } = useMasterDataSummary();
if (isLoading) return <Loader message="Loading master data..." />;
if (isError) return <ErrorState message="Failed to load master data." />;
return (
<div className="space-y-6">
<div className="bg-app-card p-6 rounded-lg shadow-sm">
<h2 className="text-xl font-bold text-text-primary">Master Data Dashboard</h2>
<p className="text-sm text-text-muted mt-2">Overview of organizational structure.</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
<StatCard
title="Total Companies"
value={summary?.totalCompanies || 0}
Icon={Building}
colorClass="text-primary"
bgClass="bg-primary/10"
/>
<StatCard
title="Total Branches"
value={summary?.totalBranches || 0}
Icon={Network}
colorClass="text-primary"
bgClass="bg-primary/10"
/>
<StatCard
title="Total Departments"
value={summary?.totalDepartments || 0}
Icon={Briefcase}
colorClass="text-primary"
bgClass="bg-primary/10"
/>
<StatCard
title="Total Designations"
value={summary?.totalDesignations || 0}
Icon={Tag}
colorClass="text-primary"
bgClass="bg-primary/10"
/>
<StatCard
title="Total Employees"
value={summary?.totalEmployees || 0}
Icon={Users}
colorClass="text-primary"
bgClass="bg-primary/10"
/>
</div>
</div>
);
}

View File

@ -0,0 +1,24 @@
import { Routes, Route, Navigate } from 'react-router-dom';
import MasterDataDashboard from '../pages/MasterDataDashboard';
// Placeholder for future pages
const Placeholder = ({ title }: { title: string }) => (
<div className="bg-app-card p-6 rounded-lg shadow-sm">
<h2 className="text-xl font-bold text-text-primary">{title}</h2>
<p className="text-text-muted mt-2">{title} UI will be implemented here.</p>
</div>
);
export default function MasterDataRouter() {
return (
<Routes>
<Route path="/" element={<Navigate to="/master-data/dashboard" replace />} />
<Route path="/dashboard" element={<MasterDataDashboard />} />
<Route path="/company" element={<Placeholder title="Manage Company" />} />
<Route path="/branches" element={<Placeholder title="Manage Branches" />} />
<Route path="/departments" element={<Placeholder title="Manage Departments" />} />
<Route path="/designations" element={<Placeholder title="Manage Designations" />} />
<Route path="/employees" element={<Placeholder title="Manage Employees" />} />
</Routes>
);
}