Three concerns from testing:
1. Chat typing UX: the textarea was disabled while a request was in
flight, so the user couldn't draft the next question. Removed the
disabled attribute; Enter is just a no-op while busy. Send button
still gates actual submission.
2. Sticky footer: switched the chat wrapper to 100svh (mobile-keyboard
aware) and made the composer sticky bottom-0 with a solid background
so it no longer fades into the scroll area.
3. Limit-warning: the SSE stream now reads the 'done' event and surfaces
a banner when the server reports the agent loop hit its iteration
cap, so a quiet stream end isn't mistaken for a complete answer.
Sidebar: added 'Ask' nav item pointing at /dashboard/chat with the
Sparkles icon so the chat is reachable from the dashboard even if the
standalone-PWA install path keeps misbehaving.
- Updated the Dashboard page to improve card styling with a warm-amber glow strip and adjusted icon presentation for better visual appeal.
- Expanded the Sidebar navigation by adding new entries for "Sites," "Workforce," "Plant & Equipment," "Fleet & Fuel," and "Purchasing," each with corresponding icons and descriptions to enhance user navigation and access to key features.
- Added `pocketbase` as a dependency in `package.json` and `package-lock.json`.
- Updated the `dev` script in `package.json` to run on port 6004 instead of 3000.
- Removed unused API routes: `src/app/api/health/route.ts`, `src/app/api/mcp/route.ts`, `src/app/api/upload/route.ts`, and their associated logic to streamline the codebase.
- Cleaned up `package-lock.json` by removing unnecessary peer dependencies and ensuring consistency in the dependency tree.
The sidebar was hidden until 1280px wide, which meant laptops and
small desktops between 1024-1280px (incl. iPads in landscape, many
Windows laptops, Chromebooks) saw the hamburger instead of the
persistent sidebar. That felt wrong on what was clearly a desktop.
Dropping to 'lg' (1024px):
- Phone portrait (< 768 px) → hamburger ✅
- Tablet portrait (768-1024 px) → hamburger ✅
- iPad landscape / laptop (1024 px+) → sidebar ✅
- 932 px iPhone landscape cap is below 1024 px, so the hamburger
still kicks in for all landscape phones.
Changed 4 occurrences: 3x 'xl:hidden' → 'lg:hidden', 1x
'hidden xl:block' → 'hidden lg:block' on the <aside> element.
New /dashboard/uploads page with a 2x2 grid of drop zones, one per
ingest source:
- Orders (orange) — CSV / XLS / XLSX, max 10 MB
- Delivery Notes (teal) — PDF / images, max 20 MB
- Fuel Logs (yellow-green) — CSV / XLS / XLSX, max 5 MB
- Time Sheets (green) — CSV / XLS / XLSX, max 5 MB
Each block has:
- A coloured left stripe + icon disc in the accent colour
- Title, format-count badge, and a long description of what to upload
- File-format chips and a max-size hint
- A drag-and-drop drop zone that also accepts files via click
- A primary 'Upload X' button in the accent colour
- A 'Recent' list showing the last 4 uploads with status badges
When files are dropped or picked, the client POSTs to
/api/upload with a 'type' field. The endpoint validates MIME and size
against the kind-specific rules in src/lib/uploads.ts and returns a
JSON descriptor with accepted/rejected entries. New entries are
prepended to the page's recent-uploads list in real time, and a
bottom-right toast shows accepted/rejected counts.
The sidebar gets a new 'Uploads' nav item with the upload icon.
Files:
- src/lib/types.ts type definitions
- src/lib/uploads.ts acceptance rules + mock history
- src/app/api/upload/route.ts type-aware upload handler
- src/app/dashboard/uploads/page.tsx the new page
- src/components/layout/sidebar.tsx Uploads nav entry
The card showed hardcoded '5 projects · 3 flagged · 2 on schedule'
stats that were never updated from the mock data and duplicated
information in the Sites module. Removing it gives the sidebar a
cleaner Logo → Nav → Lock structure and means the Lock screen button
is visible without scrolling on standard heights.
Also align the mobile drawer's close-button breakpoint from lg to xl
to match the rest of the sidebar's breakpoint logic.