feat: add Help page with search, streamline copilot, misc UI fixes

Adds searchable Help/User Guide page, trims copilot tool bloat,
adds OTHER department option, and various form/layout improvements.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 19:42:39 +01:00
parent b35c14fddc
commit 74a292ea93
33 changed files with 1815 additions and 453 deletions

View File

@@ -16,6 +16,7 @@
"axios": "^1.6.5",
"clsx": "^2.1.0",
"date-fns": "^3.2.0",
"fuse.js": "^7.1.0",
"leaflet": "^1.9.4",
"lucide-react": "^0.309.0",
"qrcode.react": "^4.2.0",
@@ -3442,6 +3443,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/fuse.js": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-7.1.0.tgz",
"integrity": "sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ==",
"license": "Apache-2.0",
"engines": {
"node": ">=10"
}
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",

View File

@@ -23,6 +23,7 @@
"axios": "^1.6.5",
"clsx": "^2.1.0",
"date-fns": "^3.2.0",
"fuse.js": "^7.1.0",
"leaflet": "^1.9.4",
"lucide-react": "^0.309.0",
"qrcode.react": "^4.2.0",

Binary file not shown.

After

Width:  |  Height:  |  Size: 468 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 170 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@@ -24,6 +24,7 @@ import { DriverProfile } from '@/pages/DriverProfile';
import { MySchedule } from '@/pages/MySchedule';
import { GpsTracking } from '@/pages/GpsTracking';
import { Reports } from '@/pages/Reports';
import { Help } from '@/pages/Help';
import { useAuth } from '@/contexts/AuthContext';
// Smart redirect based on user role
@@ -63,7 +64,7 @@ function App() {
scope: 'openid profile email offline_access',
}}
useRefreshTokens={true}
cacheLocation="memory"
cacheLocation="localstorage"
>
<QueryClientProvider client={queryClient}>
<AuthProvider>
@@ -124,6 +125,7 @@ function App() {
<Route path="/admin-tools" element={<AdminTools />} />
<Route path="/gps-tracking" element={<GpsTracking />} />
<Route path="/reports" element={<Reports />} />
<Route path="/help" element={<Help />} />
<Route path="/profile" element={<DriverProfile />} />
<Route path="/my-schedule" element={<MySchedule />} />
<Route path="/" element={<HomeRedirect />} />

View File

@@ -114,6 +114,7 @@ export function DriverForm({ driver, onSubmit, onCancel, isSubmitting }: DriverF
<option value="">Select Department</option>
<option value="OFFICE_OF_DEVELOPMENT">Office of Development</option>
<option value="ADMIN">Admin</option>
<option value="OTHER">Other</option>
</select>
</div>

View File

@@ -22,6 +22,7 @@ import {
Phone,
AlertCircle,
FileText,
HelpCircle,
} from 'lucide-react';
import { UserMenu } from '@/components/UserMenu';
import { AppearanceMenu } from '@/components/AppearanceMenu';
@@ -98,6 +99,7 @@ export function Layout({ children }: LayoutProps) {
{ name: 'Reports', href: '/reports', icon: FileText },
{ name: 'GPS Tracking', href: '/gps-tracking', icon: Radio },
{ name: 'Admin Tools', href: '/admin-tools', icon: Settings },
{ name: 'Help Guide', href: '/help', icon: HelpCircle },
];
// Filter navigation based on role and CASL permissions

View File

@@ -196,6 +196,7 @@ export function VIPForm({ vip, onSubmit, onCancel, isSubmitting }: VIPFormProps)
>
<option value="OFFICE_OF_DEVELOPMENT">Office of Development</option>
<option value="ADMIN">Admin</option>
<option value="OTHER">Other</option>
</select>
</div>

View File

@@ -17,7 +17,7 @@ export const copilotApi = axios.create({
headers: {
'Content-Type': 'application/json',
},
timeout: 120000, // 2 minute timeout for AI requests
timeout: 300000, // 5 minute timeout for AI requests (large tasks need multiple tool calls)
});
// Token getter function - set by AuthContext when authenticated

View File

@@ -196,6 +196,7 @@ export function DriverList({ embedded = false }: { embedded?: boolean }) {
const labels = {
'OFFICE_OF_DEVELOPMENT': 'Office of Development',
'ADMIN': 'Admin',
'OTHER': 'Other',
};
return labels[value as keyof typeof labels] || value;
};
@@ -541,6 +542,7 @@ export function DriverList({ embedded = false }: { embedded?: boolean }) {
options: [
{ value: 'OFFICE_OF_DEVELOPMENT', label: 'Office of Development' },
{ value: 'ADMIN', label: 'Admin' },
{ value: 'OTHER', label: 'Other' },
],
selectedValues: selectedDepartments,
onToggle: handleDepartmentToggle,

1078
frontend/src/pages/Help.tsx Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -234,6 +234,7 @@ export function Reports() {
<option value="all">All Departments</option>
<option value="OFFICE_OF_DEVELOPMENT">Office of Development</option>
<option value="ADMIN">Admin</option>
<option value="OTHER">Other</option>
</select>
</div>
<button

View File

@@ -192,6 +192,7 @@ export function VIPList() {
department: {
'OFFICE_OF_DEVELOPMENT': 'Office of Development',
'ADMIN': 'Admin',
'OTHER': 'Other',
},
arrivalMode: {
'FLIGHT': 'Flight',
@@ -546,6 +547,7 @@ export function VIPList() {
options: [
{ value: 'OFFICE_OF_DEVELOPMENT', label: 'Office of Development' },
{ value: 'ADMIN', label: 'Admin' },
{ value: 'OTHER', label: 'Other' },
],
selectedValues: selectedDepartments,
onToggle: handleDepartmentToggle,