+
+
+ AI Assistant
+ {messages.length > 0 && (
+
+ )}
+
+
+
+
+ {messages.length === 0 && (
+
+
Try asking:
+
+ {SUGGESTIONS.map((s) => (
+
+ ))}
+
+ {!hasData &&
Upload a time log first to give the AI real context.
}
+
+ )}
+
+ {messages.map((m, i) => (
+
+ {m.role === 'assistant' && (
+
+ AI
+
+ )}
+
+ {m.content || (busy && i === messages.length - 1 ? '…' : '')}
+
+
+ ))}
+
+ {error && (
+
{error}
+ )}
+
+
+
+
+
+ );
+}
diff --git a/frontend/src/components/FilterBar.tsx b/frontend/src/components/FilterBar.tsx
index e1fb5fa..633b3f3 100644
--- a/frontend/src/components/FilterBar.tsx
+++ b/frontend/src/components/FilterBar.tsx
@@ -12,6 +12,10 @@ interface Props {
departments: string[];
names: string[];
billingTypes: string[];
+ brands?: string[];
+ divisions?: string[];
+ hubs?: string[];
+ userRoles?: string[];
showForecastToggle?: boolean;
}
@@ -29,7 +33,7 @@ function MultiSelect({
tutorialId?: string;
}) {
return (
-
+
);
}
diff --git a/frontend/src/components/Navbar.tsx b/frontend/src/components/Navbar.tsx
index 40d3a0a..5ac8562 100644
--- a/frontend/src/components/Navbar.tsx
+++ b/frontend/src/components/Navbar.tsx
@@ -1,12 +1,24 @@
import { NavLink, useNavigate } from 'react-router-dom';
import { LogOut, BarChart3 } from 'lucide-react';
-import { useAuth } from '../hooks/useAuth';
+import { canAccess, useAuth } from '../hooks/useAuth';
-const tabs = [
- { to: '/', label: 'Department', end: true },
- { to: '/resourcing', label: 'Resourcing' },
- { to: '/bookings', label: 'Bookings' },
- { to: '/tutorial', label: 'Tutorial' },
+interface Tab {
+ to: string;
+ label: string;
+ slug: string;
+ end?: boolean;
+}
+
+// Order matches the original SPA: Forecast, Project Type Summary, Time Log
+// Detail, Department, Resourcing, Bookings, Tutorial.
+const TABS: Tab[] = [
+ { to: '/forecast', label: 'Forecast', slug: 'forecast' },
+ { to: '/project-types', label: 'Project Type Summary', slug: 'project-type' },
+ { to: '/time-log', label: 'Time Log Detail', slug: 'time-log' },
+ { to: '/', label: 'Department', slug: 'department', end: true },
+ { to: '/resourcing', label: 'Resourcing', slug: 'resourcing' },
+ { to: '/bookings', label: 'Bookings', slug: 'bookings' },
+ { to: '/tutorial', label: 'Tutorial', slug: 'tutorial' },
];
export default function Navbar() {
@@ -18,20 +30,22 @@ export default function Navbar() {
navigate('/login', { replace: true });
};
+ const visible = TABS.filter((t) => canAccess(user?.role, t.slug));
+
return (
-
+
Utilisation
-