"use client"; import { useCallback, useEffect, useState } from "react"; import type { ReactElement, ReactNode } from "react"; import { WorkspaceMemberRole } from "@mosaic/shared"; import { useAuth } from "@/lib/auth/auth-context"; import { fetchUserWorkspaces } from "@/lib/api/workspaces"; import Link from "next/link"; interface CategoryConfig { title: string; description: string; href: string; accent: string; iconBg: string; icon: ReactNode; adminOnly?: boolean; } interface SettingsCategoryCardProps { category: CategoryConfig; } function SettingsCategoryCard({ category }: SettingsCategoryCardProps): ReactElement { const [hovered, setHovered] = useState(false); return (
{ setHovered(true); }} onMouseLeave={(): void => { setHovered(false); }} style={{ background: hovered ? "var(--surface-2)" : "var(--surface)", border: `1px solid ${hovered ? category.accent : "var(--border)"}`, borderRadius: "var(--r-lg)", padding: 20, transition: "background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease", boxShadow: hovered ? "0 4px 16px rgba(0,0,0,0.2)" : "none", cursor: "pointer", display: "flex", flexDirection: "column", gap: 12, height: "100%", }} > {/* Icon well */}
{category.icon}
{/* Title */}
{category.title}
{/* Description */}
{category.description}
{/* CTA */}
Manage →
); } const categories: CategoryConfig[] = [ { title: "Appearance", description: "Choose a theme for the interface. Switch between Dark, Light, Nord, Dracula, and more.", href: "/settings/appearance", accent: "var(--ms-pink-500)", iconBg: "rgba(236, 72, 153, 0.12)", icon: ( ), }, { title: "Credentials", description: "Securely store and manage API keys, tokens, and passwords used by agents and integrations.", href: "/settings/credentials", accent: "var(--ms-blue-400)", iconBg: "rgba(47, 128, 255, 0.12)", icon: ( ), }, { title: "Domains", description: "Organize tasks and projects by life areas or functional domains within your workspace.", href: "/settings/domains", accent: "var(--ms-teal-400)", iconBg: "rgba(20, 184, 166, 0.12)", icon: ( ), }, { title: "AI Personalities", description: "Customize how the AI assistant communicates \u2014 tone, formality, and response style.", href: "/settings/personalities", accent: "var(--ms-purple-400)", iconBg: "rgba(139, 92, 246, 0.12)", icon: ( ), }, { title: "LLM Providers", description: "Add and manage LLM providers, encrypted API keys, base URLs, and model inventories.", href: "/settings/providers", accent: "var(--ms-blue-400)", iconBg: "rgba(47, 128, 255, 0.12)", icon: ( ), }, { title: "Agent Config", description: "Choose primary and fallback models, plus optional personality/SOUL instructions.", href: "/settings/agent-config", accent: "var(--ms-teal-400)", iconBg: "rgba(20, 184, 166, 0.12)", icon: ( ), }, { title: "Authentication", description: "Manage OIDC provider settings and breakglass admin password recovery.", href: "/settings/auth", accent: "var(--ms-amber-400)", iconBg: "rgba(245, 158, 11, 0.12)", icon: ( ), }, { title: "Users", description: "Invite, manage roles, and deactivate users across your workspaces.", href: "/settings/users", adminOnly: true, accent: "var(--ms-green-400)", iconBg: "rgba(34, 197, 94, 0.12)", icon: ( ), }, { title: "Teams", description: "Create and manage teams within your active workspace.", href: "/settings/teams", adminOnly: true, accent: "var(--ms-blue-400)", iconBg: "rgba(47, 128, 255, 0.12)", icon: ( ), }, { title: "Workspaces", description: "Create and manage workspaces to organize projects and collaborate with your team.", href: "/settings/workspaces", accent: "var(--ms-amber-400)", iconBg: "rgba(245, 158, 11, 0.12)", icon: ( ), }, ]; const ADMIN_ROLES: WorkspaceMemberRole[] = [WorkspaceMemberRole.OWNER, WorkspaceMemberRole.ADMIN]; export default function SettingsPage(): ReactElement { const { user } = useAuth(); const [isAdmin, setIsAdmin] = useState(false); const checkRole = useCallback(async (): Promise => { if (user === null) return; try { const workspaces = await fetchUserWorkspaces(); const hasAdminRole = workspaces.some((ws) => ADMIN_ROLES.includes(ws.role)); setIsAdmin(hasAdminRole); } catch { // Fail open — show all items if we can't determine role setIsAdmin(true); } }, [user]); useEffect(() => { void checkRole(); }, [checkRole]); const visibleCategories = categories.filter((c) => c.adminOnly !== true || isAdmin); return (
{/* Page header */}

Settings

Configure your workspace, credentials, and preferences

{/* Category grid */}
{visibleCategories.map((category) => ( ))}
); }