From b77b041b4ee66b07da5b8af0d852e3ed3873a0f4 Mon Sep 17 00:00:00 2001 From: devwums Date: Thu, 25 Jun 2026 14:43:51 +0100 Subject: [PATCH 1/2] feat: add Activity Feed component page [FE-36] (#973) --- frontend/app/(dashboard)/activity/page.tsx | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 frontend/app/(dashboard)/activity/page.tsx diff --git a/frontend/app/(dashboard)/activity/page.tsx b/frontend/app/(dashboard)/activity/page.tsx new file mode 100644 index 00000000..606f4a44 --- /dev/null +++ b/frontend/app/(dashboard)/activity/page.tsx @@ -0,0 +1,45 @@ +'use client'; + +import { useState } from 'react'; +import { Package, UserCheck, Wrench, AlertTriangle, Settings } from 'lucide-react'; + +type EventType = 'checkout' | 'return' | 'maintenance' | 'alert' | 'system'; + +interface ActivityEvent { id: string; type: EventType; actor: string; description: string; timestamp: string } + +const MOCK: ActivityEvent[] = [ + { id:'1', type:'checkout', actor:'Alice M.', description:'checked out Dell Laptop #7', timestamp:'2024-01-22T09:15:00Z' }, + { id:'2', type:'maintenance', actor:'Tech Team', description:'completed maintenance on Server Rack A', timestamp:'2024-01-22T08:30:00Z' }, + { id:'3', type:'alert', actor:'System', description:'Printer Ink stock fell below reorder level', timestamp:'2024-01-22T07:45:00Z' }, + { id:'4', type:'return', actor:'Bob K.', description:'returned Canon Camera', timestamp:'2024-01-21T17:00:00Z' }, + { id:'5', type:'system', actor:'Admin', description:'updated permissions for Manager role', timestamp:'2024-01-21T14:20:00Z' }, +]; + +const ICON: Record = { + checkout: , + return: , + maintenance: , + alert: , + system: , +}; + +export default function ActivityFeedPage() { + const [events] = useState(MOCK); + return ( +
+

Activity Feed

Org-wide timeline of asset and system events

+
+
+
+ {events.map(ev => ( +
+
{ICON[ev.type]}
+

{ev.actor} {ev.description}

+

{new Date(ev.timestamp).toLocaleString()}

+
+ ))} +
+
+
+ ); +} \ No newline at end of file From 18ea8e5f098286bc55ad132981645c7967ce59f8 Mon Sep 17 00:00:00 2001 From: devwums Date: Thu, 25 Jun 2026 14:43:53 +0100 Subject: [PATCH 2/2] feat: add @mention support in asset notes with user autocomplete [FE-37] (#974) --- frontend/app/(dashboard)/asset-notes/page.tsx | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 frontend/app/(dashboard)/asset-notes/page.tsx diff --git a/frontend/app/(dashboard)/asset-notes/page.tsx b/frontend/app/(dashboard)/asset-notes/page.tsx new file mode 100644 index 00000000..efadc244 --- /dev/null +++ b/frontend/app/(dashboard)/asset-notes/page.tsx @@ -0,0 +1,77 @@ +'use client'; + +import { useState, useRef } from 'react'; +import { Send } from 'lucide-react'; +import { Button } from '@/components/ui/button'; + +const USERS = ['alice.m', 'bob.k', 'carol.s', 'dave.t', 'emma.w']; + +interface Note { id: string; author: string; text: string; timestamp: string } + +const MOCK_NOTES: Note[] = [ + { id:'1', author:'Alice M.', text:'Sent for repair. @bob.k please follow up with vendor.', timestamp:'2024-01-20T10:00:00Z' }, + { id:'2', author:'Bob K.', text:'Will check @carol.s for parts availability.', timestamp:'2024-01-20T10:30:00Z' }, +]; + +export default function AssetNotesPage() { + const [notes, setNotes] = useState(MOCK_NOTES); + const [text, setText] = useState(''); + const [suggestions, setSuggestions] = useState([]); + const [mentionStart, setMentionStart] = useState(-1); + const inputRef = useRef(null); + + const handleChange = (val: string) => { + setText(val); + const atIdx = val.lastIndexOf('@'); + if (atIdx >= 0 && atIdx === val.length - 1 - (val.slice(atIdx + 1).length) + atIdx) { + const fragment = val.slice(atIdx + 1); + const matches = USERS.filter(u => u.startsWith(fragment)); + setSuggestions(matches); + setMentionStart(atIdx); + } else if (val.slice(val.lastIndexOf('@') + 1).includes(' ')) { + setSuggestions([]); + } + }; + + const insertMention = (user: string) => { + const newText = text.slice(0, mentionStart) + @ ; + setText(newText); + setSuggestions([]); + inputRef.current?.focus(); + }; + + const addNote = () => { + if (!text.trim()) return; + setNotes(prev => [...prev, { id: Date.now().toString(), author:'You', text, timestamp: new Date().toISOString() }]); + setText(''); + }; + + const renderText = (t: string) => t.replace(/@(\w+\.\w+)/g, '@'); + + return ( +
+

Asset Notes

@mention support with user autocomplete

+
+ {notes.map(n => ( +
+
+ {n.author} + {new Date(n.timestamp).toLocaleString()} +
+

+

+ ))} +
+
+