diff --git a/frontend/index.html b/frontend/index.html index 1abf41b..2da949e 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,6 +3,10 @@ + + + + UMBRA diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 66de45d..98d7a3e 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -21,7 +21,7 @@ function ProtectedRoute({ children }: { children: React.ReactNode }) { if (isLoading) { return ( -
+
Loading...
); @@ -39,7 +39,7 @@ function AdminRoute({ children }: { children: React.ReactNode }) { if (isLoading) { return ( -
+
Loading...
); diff --git a/frontend/src/components/admin/AdminDashboardPage.tsx b/frontend/src/components/admin/AdminDashboardPage.tsx index 0b5cd04..bc6a517 100644 --- a/frontend/src/components/admin/AdminDashboardPage.tsx +++ b/frontend/src/components/admin/AdminDashboardPage.tsx @@ -23,9 +23,9 @@ export default function AdminDashboardPage() { dashboard ? dashboard.total_users - dashboard.active_users : null; return ( -
+
{/* Stats grid */} -
+
{isLoading ? ( Array.from({ length: 5 }).map((_, i) => ( @@ -94,10 +94,10 @@ export default function AdminDashboardPage() { - - @@ -111,8 +111,8 @@ export default function AdminDashboardPage() { idx % 2 === 0 ? '' : 'bg-card-elevated/25' )} > - - + @@ -142,16 +142,16 @@ export default function AdminDashboardPage() {
+ Username + When
{entry.username} + {entry.username} {getRelativeTime(entry.last_login_at)}
- - - - @@ -165,7 +165,7 @@ export default function AdminDashboardPage() { idx % 2 === 0 ? '' : 'bg-card-elevated/25' )} > - - - - diff --git a/frontend/src/components/admin/AdminPortal.tsx b/frontend/src/components/admin/AdminPortal.tsx index b519f6f..2f8e5ad 100644 --- a/frontend/src/components/admin/AdminPortal.tsx +++ b/frontend/src/components/admin/AdminPortal.tsx @@ -17,32 +17,34 @@ export default function AdminPortal() { return (
{/* Portal header with tab navigation */} -
-
-
+
+
+
-

Admin Portal

+

Admin

{/* Horizontal tab navigation */} -
+ Action + Actor + Target + When
+ + {entry.actor_username ?? ( system )} + {entry.target_username ?? '—'} + {getRelativeTime(entry.created_at)}
- - - - - - @@ -158,15 +158,15 @@ export default function ConfigPage() { idx % 2 === 0 ? '' : 'bg-card-elevated/25' )} > - - - - - - diff --git a/frontend/src/components/admin/IAMPage.tsx b/frontend/src/components/admin/IAMPage.tsx index 9eb3166..2c83957 100644 --- a/frontend/src/components/admin/IAMPage.tsx +++ b/frontend/src/components/admin/IAMPage.tsx @@ -95,7 +95,7 @@ export default function IAMPage() { : null; return ( -
+
{/* Stats row */}
- +
@@ -139,12 +139,12 @@ export default function IAMPage() { value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} placeholder="Search users..." - className="pl-8 h-8 w-48 text-xs" + className="pl-8 h-8 w-32 sm:w-48 text-xs" />
@@ -160,38 +160,38 @@ export default function IAMPage() { {searchQuery ? 'No users match your search.' : 'No users found.'}

) : ( -
+
+ Time + Actor + Action + Target + IP + Detail
+ {getRelativeTime(entry.created_at)} + {entry.actor_username ?? ( system )} + + {entry.target_username ?? '—'} + {entry.ip_address ?? '—'} + {entry.detail ?? '—'}
- - - - - - - - - - @@ -211,17 +211,17 @@ export default function IAMPage() { ) )} > - - + - - - - - - - - diff --git a/frontend/src/components/admin/UserActionsMenu.tsx b/frontend/src/components/admin/UserActionsMenu.tsx index f4a641d..056e5a7 100644 --- a/frontend/src/components/admin/UserActionsMenu.tsx +++ b/frontend/src/components/admin/UserActionsMenu.tsx @@ -147,7 +147,7 @@ export default function UserActionsMenu({ user, currentUsername }: UserActionsMe {roleSubmenuOpen && (
setRoleSubmenuOpen(true)} onMouseLeave={() => setRoleSubmenuOpen(false)} > diff --git a/frontend/src/components/admin/UserDetailSection.tsx b/frontend/src/components/admin/UserDetailSection.tsx index 26ab578..f5b8e09 100644 --- a/frontend/src/components/admin/UserDetailSection.tsx +++ b/frontend/src/components/admin/UserDetailSection.tsx @@ -71,15 +71,15 @@ export default function UserDetailSection({ userId, onClose }: UserDetailSection if (isLoading) { return ( -
- +
+ {Array.from({ length: 5 }).map((_, i) => ( ))} - + {Array.from({ length: 7 }).map((_, i) => ( @@ -109,9 +109,9 @@ export default function UserDetailSection({ userId, onClose }: UserDetailSection if (!user) return null; return ( -
+
{/* User Information (read-only) */} - +
@@ -152,7 +152,7 @@ export default function UserDetailSection({ userId, onClose }: UserDetailSection {/* Security & Permissions */} - +
@@ -168,7 +168,7 @@ export default function UserDetailSection({ userId, onClose }: UserDetailSection changeView(e.target.value as CalendarView)} + className="h-8 text-sm w-auto pr-8 md:hidden" + > + {(Object.entries(viewLabels) as [CalendarView, string][]).map(([view, label]) => ( + + ))} + + +
{(Object.entries(viewLabels) as [CalendarView, string][]).map(([view, label]) => (
@@ -621,7 +644,7 @@ export default function CalendarPage() { onClick={handlePanelClose} >
e.stopPropagation()} > (functio {cal.name} @@ -184,7 +184,7 @@ const CalendarSidebar = forwardRef(functio setEditingTemplate(tmpl); setShowTemplateForm(true); }} - className="opacity-0 group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-foreground" + className="opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-foreground" > @@ -194,7 +194,7 @@ const CalendarSidebar = forwardRef(functio if (!window.confirm(`Delete template "${tmpl.name}"?`)) return; deleteTemplateMutation.mutate(tmpl.id); }} - className="opacity-0 group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-destructive" + className="opacity-100 md:opacity-0 md:group-hover:opacity-100 transition-opacity duration-150 text-muted-foreground hover:text-destructive" > diff --git a/frontend/src/components/calendar/SharedCalendarSection.tsx b/frontend/src/components/calendar/SharedCalendarSection.tsx index d42308c..b0ecee6 100644 --- a/frontend/src/components/calendar/SharedCalendarSection.tsx +++ b/frontend/src/components/calendar/SharedCalendarSection.tsx @@ -73,7 +73,7 @@ export default function SharedCalendarSection({ @@ -104,7 +104,7 @@ export default function SharedCalendarSection({ {m.calendar_name} diff --git a/frontend/src/components/dashboard/DashboardPage.tsx b/frontend/src/components/dashboard/DashboardPage.tsx index 7a1e9c4..59fb09f 100644 --- a/frontend/src/components/dashboard/DashboardPage.tsx +++ b/frontend/src/components/dashboard/DashboardPage.tsx @@ -86,13 +86,13 @@ export default function DashboardPage() { if (isLoading) { return (
-
+
-
+
@@ -110,7 +110,7 @@ export default function DashboardPage() { return (
{/* Header — greeting + date + quick add */} -
+

{getGreeting(settings?.preferred_name || undefined)} @@ -156,8 +156,8 @@ export default function DashboardPage() {

-
-
+
+
{/* Week Timeline */} {upcomingData && (
@@ -187,7 +187,7 @@ export default function DashboardPage() { {/* Main Content — 2 columns */} -
+
{/* Left: Upcoming feed (wider) */}
{upcomingData && upcomingData.items.length > 0 ? ( @@ -207,7 +207,7 @@ export default function DashboardPage() {
{/* Right: Countdown + Today's events + todos stacked */} -
+
{data.starred_events.length > 0 && ( )} diff --git a/frontend/src/components/dashboard/StatsWidget.tsx b/frontend/src/components/dashboard/StatsWidget.tsx index 34d09a9..1fd72a9 100644 --- a/frontend/src/components/dashboard/StatsWidget.tsx +++ b/frontend/src/components/dashboard/StatsWidget.tsx @@ -42,7 +42,7 @@ export default function StatsWidget({ projectStats, totalIncompleteTodos, weathe ]; return ( -
+
{statCards.map((stat) => ( {task.parent_task_title} )}
- {task.project_name} + {task.project_name} - +
+ Username + Umbral Name + Email + Role + Status + Last Login + MFA + Sessions + Created + Actions
{user.username} + {user.username} {user.umbral_name || user.username} + {user.email || '—'} + + + {user.last_login_at ? getRelativeTime(user.last_login_at) : '—'} + {user.totp_enabled ? ( On @@ -249,13 +249,13 @@ export default function IAMPage() { )} + {user.active_sessions} + {getRelativeTime(user.created_at)} e.stopPropagation()}> + e.stopPropagation()}>