Compare commits
No commits in common. "22ee92190de5970abf1b9757cefd186f05874fd0" and "bc537f583f1f3cbadf9ce956681761249c21ebbf" have entirely different histories.
22ee92190d
...
bc537f583f
@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"totalCompanies": 1,
|
|
||||||
"totalBranches": 3,
|
|
||||||
"totalDepartments": 5,
|
|
||||||
"totalDesignations": 4,
|
|
||||||
"totalEmployees": 245
|
|
||||||
}
|
|
||||||
@ -9,9 +9,9 @@ import LeaveRouter from '../../features/leave/routes/LeaveRouter';
|
|||||||
import ApprovalRouter from '../../features/leave/routes/ApprovalRouter';
|
import ApprovalRouter from '../../features/leave/routes/ApprovalRouter';
|
||||||
import AttendanceSummaryRouter from '../../features/attendance/routes/AttendanceSummaryRouter';
|
import AttendanceSummaryRouter from '../../features/attendance/routes/AttendanceSummaryRouter';
|
||||||
import LeaveSummaryRouter from '../../features/leave/routes/LeaveSummaryRouter';
|
import LeaveSummaryRouter from '../../features/leave/routes/LeaveSummaryRouter';
|
||||||
|
import ManageEmployeesRouter from '../../features/dashboard/routes/ManageEmployeesRouter';
|
||||||
import ManageAdminsRouter from '../../features/dashboard/routes/ManageAdminsRouter';
|
import ManageAdminsRouter from '../../features/dashboard/routes/ManageAdminsRouter';
|
||||||
import PolicyRouter from '../../features/dashboard/routes/PolicyRouter';
|
import PolicyRouter from '../../features/dashboard/routes/PolicyRouter';
|
||||||
import MasterDataRouter from '../../features/employee-management/routes/MasterDataRouter'; // New Import
|
|
||||||
|
|
||||||
export default function MainLayout() {
|
export default function MainLayout() {
|
||||||
const [isCollapsed, setIsCollapsed] = useState(false);
|
const [isCollapsed, setIsCollapsed] = useState(false);
|
||||||
@ -40,7 +40,7 @@ export default function MainLayout() {
|
|||||||
<Route path="/approval" element={<ApprovalRouter />} />
|
<Route path="/approval" element={<ApprovalRouter />} />
|
||||||
<Route path="/attendance-summary/*" element={<AttendanceSummaryRouter />} />
|
<Route path="/attendance-summary/*" element={<AttendanceSummaryRouter />} />
|
||||||
<Route path="/leave-summary" element={<LeaveSummaryRouter />} />
|
<Route path="/leave-summary" element={<LeaveSummaryRouter />} />
|
||||||
<Route path="/master-data/*" element={<MasterDataRouter />} />
|
<Route path="/manage-employees" element={<ManageEmployeesRouter />} />
|
||||||
<Route path="/manage-admins" element={<ManageAdminsRouter />} />
|
<Route path="/manage-admins" element={<ManageAdminsRouter />} />
|
||||||
<Route path="/policies" element={<PolicyRouter />} />
|
<Route path="/policies" element={<PolicyRouter />} />
|
||||||
|
|
||||||
|
|||||||
@ -5,15 +5,13 @@ import { getSidebarItems, type NavItem } from './types/sidebarConfig';
|
|||||||
import { Link, useLocation } from 'react-router-dom';
|
import { Link, useLocation } from 'react-router-dom';
|
||||||
import {
|
import {
|
||||||
LayoutDashboard, CalendarCheck, Plane, CheckCircle, BarChart3, ClipboardList,
|
LayoutDashboard, CalendarCheck, Plane, CheckCircle, BarChart3, ClipboardList,
|
||||||
Menu, Users, ShieldUser, ScrollText, ChevronDown, FileText, CalendarDays, ClipboardCheck,
|
Menu, Users, ShieldUser, ScrollText, ChevronDown, FileText, CalendarDays, ClipboardCheck // Added ClipboardCheck
|
||||||
Database, Building, Network, Briefcase, Tag // Added new icons
|
|
||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
const iconMap: Record<string, any> = {
|
const iconMap: Record<string, any> = {
|
||||||
LayoutDashboard, CalendarCheck, Plane, CheckCircle, BarChart3, ClipboardList,
|
LayoutDashboard, CalendarCheck, Plane, CheckCircle, BarChart3, ClipboardList,
|
||||||
Users, ShieldUser, ScrollText, FileText, CalendarDays, ClipboardCheck,
|
Users, ShieldUser, ScrollText, FileText, CalendarDays, ClipboardCheck // Added ClipboardCheck
|
||||||
Database, Building, Network, Briefcase, Tag // Added new icons
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function Sidebar({ isCollapsed, setIsCollapsed }: { isCollapsed: boolean; setIsCollapsed: (v: boolean) => void }) {
|
export default function Sidebar({ isCollapsed, setIsCollapsed }: { isCollapsed: boolean; setIsCollapsed: (v: boolean) => void }) {
|
||||||
@ -32,7 +30,7 @@ export default function Sidebar({ isCollapsed, setIsCollapsed }: { isCollapsed:
|
|||||||
const Icon = iconMap[item.icon];
|
const Icon = iconMap[item.icon];
|
||||||
const hasChildren = item.children && item.children.length > 0;
|
const hasChildren = item.children && item.children.length > 0;
|
||||||
const isDropdownOpen = openDropdowns[item.name];
|
const isDropdownOpen = openDropdowns[item.name];
|
||||||
|
|
||||||
const isChildActive = hasChildren && item.children!.some(child => currentPath === child.path);
|
const isChildActive = hasChildren && item.children!.some(child => currentPath === child.path);
|
||||||
const isActive = currentPath === item.path;
|
const isActive = currentPath === item.path;
|
||||||
|
|
||||||
@ -45,9 +43,8 @@ export default function Sidebar({ isCollapsed, setIsCollapsed }: { isCollapsed:
|
|||||||
{hasChildren ? (
|
{hasChildren ? (
|
||||||
<button
|
<button
|
||||||
onClick={() => toggleDropdown(item.name)}
|
onClick={() => toggleDropdown(item.name)}
|
||||||
className={`w-full flex items-center px-4 py-3 transition-colors duration-200 text-left ${
|
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'
|
||||||
isChildActive ? 'text-white' : 'text-blue-100 hover:bg-sidebar-hover hover:text-white'
|
} border-l-4 ${isChildActive ? 'border-action' : 'border-transparent'}`}
|
||||||
} border-l-4 ${isChildActive ? 'border-action' : 'border-transparent'}`}
|
|
||||||
>
|
>
|
||||||
{Icon && <Icon size={20} className="flex-shrink-0" />}
|
{Icon && <Icon size={20} className="flex-shrink-0" />}
|
||||||
{!isCollapsed && <span className="ml-4 text-sm font-medium flex-grow">{item.name}</span>}
|
{!isCollapsed && <span className="ml-4 text-sm font-medium flex-grow">{item.name}</span>}
|
||||||
@ -58,9 +55,8 @@ export default function Sidebar({ isCollapsed, setIsCollapsed }: { isCollapsed:
|
|||||||
) : (
|
) : (
|
||||||
<Link
|
<Link
|
||||||
to={item.path!}
|
to={item.path!}
|
||||||
className={`flex items-center px-4 py-3 transition-colors duration-200 text-left ${
|
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'
|
||||||
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" />}
|
{Icon && <Icon size={20} className="flex-shrink-0" />}
|
||||||
{!isCollapsed && <span className="ml-4 text-sm font-medium">{item.name}</span>}
|
{!isCollapsed && <span className="ml-4 text-sm font-medium">{item.name}</span>}
|
||||||
|
|||||||
@ -18,41 +18,40 @@ export const getSidebarItems = (role: UserRole): NavItem[] => {
|
|||||||
return [...baseItems, { name: 'Approval', icon: 'CheckCircle', path: '/approval' }];
|
return [...baseItems, { name: 'Approval', icon: 'CheckCircle', path: '/approval' }];
|
||||||
}
|
}
|
||||||
|
|
||||||
const adminItems: NavItem[] = [
|
|
||||||
{
|
|
||||||
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' },
|
|
||||||
...(role === 'admin' ? [{ name: 'Regularization', icon: 'ClipboardCheck', path: '/attendance-summary/regularization' }] : [])
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{ name: 'Leave Summary', icon: 'ClipboardList', path: '/leave-summary' },
|
|
||||||
{
|
|
||||||
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') {
|
if (role === 'admin') {
|
||||||
return [...baseItems, ...adminItems];
|
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' },
|
||||||
|
{ name: 'Regularization', icon: 'ClipboardCheck', path: '/attendance-summary/regularization' }, // New Item
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{ name: 'Leave Summary', icon: 'ClipboardList', path: '/leave-summary' },
|
||||||
|
{ name: 'Manage Employees', icon: 'Users', path: '/manage-employees' },
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role === 'superadmin') {
|
if (role === 'superadmin') {
|
||||||
return [
|
return [
|
||||||
...baseItems,
|
...baseItems,
|
||||||
...adminItems,
|
{
|
||||||
|
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' },
|
||||||
{ name: 'Manage Admins', icon: 'ShieldUser', path: '/manage-admins' },
|
{ name: 'Manage Admins', icon: 'ShieldUser', path: '/manage-admins' },
|
||||||
|
{ name: 'Manage Employees', icon: 'Users', path: '/manage-employees' },
|
||||||
{ name: 'Policy and Rules', icon: 'ScrollText', path: '/policies' },
|
{ name: 'Policy and Rules', icon: 'ScrollText', path: '/policies' },
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +0,0 @@
|
|||||||
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'),
|
|
||||||
});
|
|
||||||
};
|
|
||||||
@ -1,59 +0,0 @@
|
|||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -1,24 +0,0 @@
|
|||||||
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>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Loading…
x
Reference in New Issue
Block a user