From ab8447af33fb4c3f9bbea5a31247da29981f60e9 Mon Sep 17 00:00:00 2001 From: devwums Date: Thu, 25 Jun 2026 14:43:06 +0100 Subject: [PATCH 1/2] feat: add Check-in/Check-out page [FE-11] (#948) --- .../app/(dashboard)/check-in-out/page.tsx | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 frontend/app/(dashboard)/check-in-out/page.tsx diff --git a/frontend/app/(dashboard)/check-in-out/page.tsx b/frontend/app/(dashboard)/check-in-out/page.tsx new file mode 100644 index 00000000..0052a445 --- /dev/null +++ b/frontend/app/(dashboard)/check-in-out/page.tsx @@ -0,0 +1,52 @@ +'use client'; + +import { useState } from 'react'; +import { Plus, ArrowDownCircle, ArrowUpCircle } from 'lucide-react'; +import { Button } from '@/components/ui/button'; + +interface BorrowRecord { id: string; asset: string; borrowedBy: string; checkedOut: string; dueDate: string; returned: boolean } + +const MOCK: BorrowRecord[] = [ + { id:'1', asset:'Dell Laptop #7', borrowedBy:'Emma W.', checkedOut:'2024-01-15', dueDate:'2024-01-22', returned:false }, + { id:'2', asset:'Canon Camera', borrowedBy:'Liam T.', checkedOut:'2024-01-10', dueDate:'2024-01-17', returned:true }, + { id:'3', asset:'iPad Pro', borrowedBy:'Sophia R.', checkedOut:'2024-01-20', dueDate:'2024-01-27', returned:false }, +]; + +export default function CheckInOutPage() { + const [records, setRecords] = useState(MOCK); + + const markReturned = (id: string) => setRecords(prev => prev.map(r => r.id === id ? { ...r, returned: true } : r)); + + return ( +
+
+

Check-in / Check-out

Borrow assets with due dates and return flow

+ +
+
+ + {["Asset","Borrowed By","Checked Out","Due Date","Status","Action"].map(h=>)} + + {records.map(r => { + const overdue = !r.returned && new Date(r.dueDate) < new Date(); + return ( + + + + + + + + + ); + })} + +
{h}
{r.asset}{r.borrowedBy}{r.checkedOut}{r.dueDate}{overdue && ' (Overdue)'} + {r.returned + ? Returned + : Out} + {!r.returned && }
+
+
+ ); +} \ No newline at end of file From 17298be19e99816326a52fbf984470bff4e7af40 Mon Sep 17 00:00:00 2001 From: devwums Date: Thu, 25 Jun 2026 14:43:08 +0100 Subject: [PATCH 2/2] feat: add Notification Preferences settings tab [FE-29] (#966) --- .../settings/notifications/page.tsx | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 frontend/app/(dashboard)/settings/notifications/page.tsx diff --git a/frontend/app/(dashboard)/settings/notifications/page.tsx b/frontend/app/(dashboard)/settings/notifications/page.tsx new file mode 100644 index 00000000..4fdb0173 --- /dev/null +++ b/frontend/app/(dashboard)/settings/notifications/page.tsx @@ -0,0 +1,55 @@ +'use client'; + +import { useState } from 'react'; +import { Button } from '@/components/ui/button'; + +const EVENTS = [ + { key:'asset_checkout', label:'Asset Checked Out' }, + { key:'asset_return', label:'Asset Returned' }, + { key:'maintenance_due', label:'Maintenance Due' }, + { key:'low_stock', label:'Low Stock Alert' }, + { key:'asset_assigned', label:'Asset Assigned to Me' }, + { key:'work_order', label:'Work Order Update' }, +]; + +const CHANNELS = ['Email', 'In-App', 'Push']; + +type Prefs = Record>; + +export default function NotificationPreferencesPage() { + const [prefs, setPrefs] = useState(() => { + const init: Prefs = {}; + EVENTS.forEach(e => { init[e.key] = { Email: true, 'In-App': true, Push: false }; }); + return init; + }); + + const toggle = (event: string, channel: string) => + setPrefs(prev => ({ ...prev, [event]: { ...prev[event], [channel]: !prev[event][channel] } })); + + return ( +
+

Notification Preferences

Per-event channel toggles

+
+ + + + {CHANNELS.map(c => )} + + + {EVENTS.map(ev => ( + + + {CHANNELS.map(ch => ( + + ))} + + ))} + +
Event{c}
{ev.label} + toggle(ev.key, ch)} className="rounded cursor-pointer" /> +
+
+
+
+ ); +} \ No newline at end of file