From a741c340cb268885ba76d3b71c8ac391f0d32d9b Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 03:15:17 +0000 Subject: [PATCH] Code edited in Lovable Code Editor Edited UI in Lovable Co-authored-by: renee-png <262607627+renee-png@users.noreply.github.com> --- src/components/app-shell.tsx | 136 +++-------------------------------- 1 file changed, 11 insertions(+), 125 deletions(-) diff --git a/src/components/app-shell.tsx b/src/components/app-shell.tsx index 6bdafd0..6f63b91 100644 --- a/src/components/app-shell.tsx +++ b/src/components/app-shell.tsx @@ -1,102 +1,29 @@ import { Link, useLocation, useNavigate } from "@tanstack/react-router"; -import { useEffect, useState } from "react"; import { useAuth } from "@/lib/auth"; import { Button } from "@/components/ui/button"; -import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; -import { supabase } from "@/integrations/supabase/client"; -import { - Briefcase, - Users, - Receipt, - ShieldCheck, - LogOut, - Scale, - LayoutDashboard, - CheckSquare, - MessageSquare, - Activity, - DollarSign, - FileText, - FolderOpen, - Settings as SettingsIcon, -} from "lucide-react"; +import { Briefcase, Users, FileText, Receipt, ShieldCheck, LogOut, Scale, LayoutDashboard } from "lucide-react"; import { cn } from "@/lib/utils"; import type { ReactNode } from "react"; -import { useBubbleCounts } from "@/lib/use-bubble-counts"; -import { NotificationBell } from "@/components/notifications/notification-bell"; -import { DateCalculator } from "@/components/date-calculator"; -import { HeaderTimer } from "@/components/timer/header-timer"; -import { QuickAddTime, QuickAddExpense } from "@/components/quick-add/quick-add"; - -function initials(name: string, email: string) { - const src = (name || email || "").trim(); - return src.split(/\s+/).map((p) => p[0]).filter(Boolean).slice(0, 2).join("").toUpperCase(); -} interface NavItem { to: string; label: string; icon: typeof Briefcase; adminOnly?: boolean; - bubbleKey?: "messages" | "tasks"; } const NAV: NavItem[] = [ { to: "/", label: "Dashboard", icon: LayoutDashboard }, { to: "/clients", label: "Clients", icon: Users }, { to: "/cases", label: "Cases", icon: Briefcase }, - { to: "/tasks", label: "Tasks", icon: CheckSquare, bubbleKey: "tasks" }, - { to: "/messages", label: "Messages", icon: MessageSquare, bubbleKey: "messages" }, - { to: "/status", label: "Status Updates", icon: Activity }, - { to: "/collections", label: "Collections", icon: DollarSign }, - { to: "/documents", label: "Documents", icon: FileText }, - { to: "/files", label: "Files", icon: FolderOpen }, { to: "/invoices", label: "Invoices", icon: Receipt }, - { to: "/settings", label: "Settings", icon: SettingsIcon }, { to: "/admin/users", label: "Users", icon: ShieldCheck, adminOnly: true }, ]; -function Bubble({ count }: { count: number }) { - if (!count) return null; - return ( - - {count > 99 ? "99+" : count} - - ); -} - export function AppShell({ children }: { children: ReactNode }) { const { user, signOut, isAdmin, roles } = useAuth(); const location = useLocation(); const navigate = useNavigate(); - const counts = useBubbleCounts(); - const [profile, setProfile] = useState<{ full_name: string; avatar_url: string | null } | null>(null); - - useEffect(() => { - if (!user) return; - supabase - .from("profiles") - .select("full_name, avatar_url") - .eq("id", user.id) - .maybeSingle() - .then(({ data }) => { - if (data) setProfile({ full_name: data.full_name || "", avatar_url: (data as any).avatar_url ?? null }); - }); - const ch = supabase - .channel(`profile-self-${user.id}-${Math.random().toString(36).slice(2)}`) - .on( - "postgres_changes", - { event: "UPDATE", schema: "public", table: "profiles", filter: `id=eq.${user.id}` }, - (payload) => { - const r = payload.new as any; - setProfile({ full_name: r.full_name || "", avatar_url: r.avatar_url ?? null }); - }, - ) - .subscribe(); - return () => { - supabase.removeChannel(ch); - }; - }, [user]); const handleSignOut = async () => { await signOut(); @@ -111,8 +38,8 @@ export function AppShell({ children }: { children: ReactNode }) {
-
-
Stage Law Firm, PLLC
+
+
Stage Law, PLLC
Law Firm Suite
@@ -121,7 +48,6 @@ export function AppShell({ children }: { children: ReactNode }) { {NAV.filter((n) => !n.adminOnly || isAdmin).map((item) => { const active = item.to === "/" ? location.pathname === "/" : location.pathname.startsWith(item.to); const Icon = item.icon; - const bubble = item.bubbleKey ? counts[item.bubbleKey] : 0; return ( {item.label} - ); })}
- - - {profile?.avatar_url ? : null} - - {initials(profile?.full_name || "", user?.email || "")} - - -
-
- {profile?.full_name || user?.email} -
-
- {roles.join(" · ") || "no role"} -
-
- +
{user?.email}
+
+ {roles.join(" · ") || "no role"} +
-
+
- {/* Desktop top toolbar */} -
- -
- - - - -
{NAV.filter((n) => !n.adminOnly || isAdmin).map((item) => { const active = item.to === "/" ? location.pathname === "/" : location.pathname.startsWith(item.to); - const bubble = item.bubbleKey ? counts[item.bubbleKey] : 0; return ( {item.label} - {bubble > 0 && ( - - {bubble > 99 ? "99+" : bubble} - - )} ); })}
-
- - - -
{children}