// src/App.tsx
// ===================================================================
// COMPLETE NORTHWIND TEAMS APPLICATION
// Single-file implementation (React + TanStack Router + Tailwind)
// ===================================================================
import React, { useState } from "react";
import {
Activity,
Bell,
Calendar,
CalendarDays,
CalendarPlus,
Check,
CheckCheck,
ChevronLeft,
ChevronRight,
Circle,
Copy,
FileText,
FolderClosed,
FolderPlus,
Forward,
Hand,
Hash,
Image as ImageIcon,
KeyRound,
Link as LinkIcon,
Lock,
LogOut,
Mail,
Menu,
MessageSquare,
Mic,
MicOff,
MonitorUp,
MoreHorizontal,
Palette,
Paperclip,
Pencil,
Phone,
PhoneOff,
Pin,
Play,
Plus,
Presentation,
Reply,
Search,
Send,
Settings,
Shield,
Smile,
Sparkles,
Trash2,
Upload,
UserPlus,
Users,
Video,
VideoOff,
Vote,
Eye,
EyeOff,
Download,
Share2,
Star,
Flag,
CalendarClock,
PhoneMissed,
ArrowDownLeft,
ArrowUpRight,
Camera,
ArrowRight,
Settings2
} from "lucide-react";
import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, Line, LineChart, Pie, PieChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts";
// VideoIcon is used as a distinct alias for the "camera on" state icon
// elsewhere in this file β lucide-react only exports it as `Video`.
const VideoIcon = Video;
// ===================================================================
// 1. MOCK DATA
// ===================================================================
export const currentUser = {
id: "u1",
name: "Aarav Mehta",
initials: "AM",
email: "aarav@northwind.io",
role: "Lead Product Manager",
department: "Product",
presence: "online",
favorite: true,
};
export const people = [
{ id: "u1", name: "Aarav Mehta", initials: "AM", email: "aarav@northwind.io", role: "Lead Product Manager", department: "Product", presence: "online", favorite: true },
{ id: "u2", name: "Priya Nair", initials: "PN", email: "priya@northwind.io", role: "Engineering Manager", department: "Engineering", presence: "online" },
{ id: "u3", name: "Sofia Rossi", initials: "SR", email: "sofia@northwind.io", role: "Lead Designer", department: "Design", presence: "busy" },
{ id: "u4", name: "Kenji Watanabe", initials: "KW", email: "kenji@northwind.io", role: "Data Analyst", department: "Product", presence: "away", favorite: true },
{ id: "u5", name: "Amara Diallo", initials: "AD", email: "amara@northwind.io", role: "Customer Success", department: "Sales", presence: "online" },
{ id: "u6", name: "Daniel Osei", initials: "DO", email: "daniel@northwind.io", role: "Senior Engineer", department: "Engineering", presence: "online" },
{ id: "u7", name: "Liam O'Connor", initials: "LO", email: "liam@northwind.io", role: "DevOps Engineer", department: "Engineering", presence: "offline" },
{ id: "u8", name: "Hannah Blum", initials: "HB", email: "hannah@northwind.io", role: "Marketing Manager", department: "Marketing", presence: "offline" },
{ id: "u9", name: "Marco Silva", initials: "MS", email: "marco@northwind.io", role: "VP of Sales", department: "Sales", presence: "busy", favorite: true },
];
export const presenceLabel = {
online: "Online",
busy: "Busy",
away: "Away",
offline: "Offline",
};
export const teams = [
{ id: "t1", name: "Product Core", description: "Roadmap, discovery and release planning", visibility: "Private", members: 24, channels: ["General", "Roadmap", "Release 4.2", "Design reviews"], files: 148, meetings: 62, color: "oklch(0.583 0.183 268.5)" },
{ id: "t2", name: "Platform Engineering", description: "Services, infra and reliability", visibility: "Private", members: 31, channels: ["General", "Incidents", "Deploys", "RFCs"], files: 402, meetings: 118, color: "oklch(0.442 0.132 262)" },
{ id: "t3", name: "Design Studio", description: "Brand, product and systems design", visibility: "Public", members: 12, channels: ["General", "Critique", "Design system"], files: 97, meetings: 40, color: "oklch(0.7 0.13 200)" },
{ id: "t4", name: "Go To Market", description: "Campaigns, launches and enablement", visibility: "Public", members: 18, channels: ["General", "Launches", "Content"], files: 63, meetings: 51, color: "oklch(0.63 0.15 155)" },
];
export const conversations = [
{ id: "c1", name: "Priya Nair", kind: "dm", preview: "Pushed the fix β can you re-check staging?", time: "09:41", unread: 2, presence: "online", initials: "PN" },
{ id: "c2", name: "Release 4.2", kind: "channel", teamName: "Product Core", preview: "Sofia: Final specs are attached here.", time: "09:12", unread: 5, initials: "R4" },
{ id: "c3", name: "Design Sync", kind: "group", preview: "Kenji: Numbers look good for the pilot.", time: "Yesterday", unread: 0, initials: "DS" },
{ id: "c4", name: "Sofia Rossi", kind: "dm", preview: "Sent over the updated component sheet.", time: "Yesterday", unread: 0, presence: "busy", initials: "SR" },
{ id: "c5", name: "Incidents", kind: "channel", teamName: "Platform Engineering", preview: "Daniel: All clear, latency back to normal.", time: "Mon", unread: 0, initials: "IN" },
{ id: "c6", name: "Amara Diallo", kind: "dm", preview: "Customer asked about the export feature.", time: "Mon", unread: 0, presence: "online", initials: "AD" },
];
export const messages = [
{ id: "m1", author: "Priya Nair", initials: "PN", time: "09:02", body: "Morning! I merged the presence refactor overnight. Staging should be stable now.", reactions: [{ emoji: "π", count: 3 }], pinned: true },
{ id: "m2", author: "Aarav Mehta", initials: "AM", time: "09:05", body: "Nice. I'll run through the meeting flows before standup.", self: true, read: true },
{ id: "m3", author: "Sofia Rossi", initials: "SR", time: "09:18", body: "Here's the updated spec with the new gallery view states.", attachment: { name: "meeting-gallery-spec-v4.pdf", size: "2.4 MB" } },
{ id: "m4", author: "Aarav Mehta", initials: "AM", time: "09:20", body: "Perfect timing β sharing with the platform crew.", self: true, edited: true, read: true },
{ id: "m5", author: "Priya Nair", initials: "PN", time: "09:41", body: "Pushed the fix β can you re-check staging?", reactions: [{ emoji: "π", count: 2 }, { emoji: "π", count: 1 }] },
];
export const meetings = [
{ id: "mt1", title: "Daily standup β Product Core", time: "10:00", day: "Today", duration: "15 min", organizer: "Priya Nair", attendees: ["PN", "SR", "DO", "KW"], status: "live" },
{ id: "mt2", title: "Release 4.2 go/no-go", time: "13:30", day: "Today", duration: "45 min", organizer: "Aarav Mehta", attendees: ["AM", "PN", "MS", "HB", "LO"], status: "upcoming" },
{ id: "mt3", title: "Design critique", time: "16:00", day: "Today", duration: "60 min", organizer: "Sofia Rossi", attendees: ["SR", "AM", "AD"], status: "upcoming" },
{ id: "mt4", title: "Quarterly business review", time: "09:30", day: "Tomorrow", duration: "90 min", organizer: "Marco Silva", attendees: ["MS", "AM", "HB", "PN", "KW", "AD"], status: "upcoming" },
{ id: "mt5", title: "Incident retro β API latency", time: "15:00", day: "Yesterday", duration: "30 min", organizer: "Daniel Osei", attendees: ["DO", "PN", "LO"], status: "past", recorded: true },
{ id: "mt6", title: "Customer advisory call", time: "11:00", day: "Yesterday", duration: "45 min", organizer: "Amara Diallo", attendees: ["AD", "AM"], status: "past", recorded: true },
];
export const files = [
{ id: "f1", name: "Release 4.2", kind: "folder", owner: "Priya Nair", modified: "Today, 09:12", size: "β", shared: 12 },
{ id: "f2", name: "Design system", kind: "folder", owner: "Sofia Rossi", modified: "Yesterday", size: "β", shared: 9 },
{ id: "f3", name: "meeting-gallery-spec-v4.pdf", kind: "pdf", owner: "Sofia Rossi", modified: "Today, 09:18", size: "2.4 MB", shared: 5 },
{ id: "f4", name: "Q3 roadmap.docx", kind: "doc", owner: "Aarav Mehta", modified: "Today, 08:02", size: "820 KB", shared: 18 },
{ id: "f5", name: "Adoption metrics.xlsx", kind: "sheet", owner: "Kenji Watanabe", modified: "Yesterday", size: "1.1 MB", shared: 7 },
{ id: "f6", name: "Launch deck.pptx", kind: "slide", owner: "Hannah Blum", modified: "Mon", size: "14.2 MB", shared: 22 },
{ id: "f7", name: "onboarding-flow.png", kind: "image", owner: "Sofia Rossi", modified: "Mon", size: "640 KB", shared: 4 },
];
export const tasks = [
{ id: "k1", title: "Finalize release notes for 4.2", scope: "Team", team: "Product Core", due: "Today", priority: "Urgent", status: "In progress", progress: 70, assignee: "AM" },
{ id: "k2", title: "Review gallery view spec", scope: "Personal", due: "Today", priority: "High", status: "To do", progress: 0, assignee: "AM" },
{ id: "k3", title: "Patch presence websocket reconnect", scope: "Team", team: "Platform Engineering", due: "Tomorrow", priority: "High", status: "In progress", progress: 45, assignee: "DO" },
{ id: "k4", title: "Refresh onboarding illustrations", scope: "Team", team: "Design Studio", due: "Fri", priority: "Medium", status: "To do", progress: 10, assignee: "SR" },
{ id: "k5", title: "Prepare QBR deck", scope: "Personal", due: "Fri", priority: "Medium", status: "In progress", progress: 30, assignee: "AM" },
{ id: "k6", title: "Archive Q2 meeting recordings", scope: "Team", team: "Platform Engineering", due: "Done", priority: "Low", status: "Done", progress: 100, assignee: "LO" },
];
export const notifications = [
{ id: "n1", kind: "meeting", title: "Release 4.2 go/no-go", detail: "Starts in 40 minutes", time: "now", unread: true },
{ id: "n2", kind: "message", title: "Priya Nair mentioned you", detail: "\"@Aarav can you re-check staging?\"", time: "12m", unread: true },
{ id: "n3", kind: "file", title: "New file in Release 4.2", detail: "Sofia uploaded meeting-gallery-spec-v4.pdf", time: "38m", unread: true },
{ id: "n4", kind: "team", title: "Team invitation", detail: "Go To Market invited you to join", time: "2h", unread: false },
{ id: "n5", kind: "task", title: "Task due today", detail: "Finalize release notes for 4.2", time: "3h", unread: false },
];
export const activity = [
{ id: "a1", actor: "Sofia Rossi", initials: "SR", action: "uploaded a file to", target: "Release 4.2", time: "38m ago" },
{ id: "a2", actor: "Daniel Osei", initials: "DO", action: "closed the incident in", target: "Platform Engineering", time: "1h ago" },
{ id: "a3", actor: "Hannah Blum", initials: "HB", action: "scheduled a meeting in", target: "Go To Market", time: "2h ago" },
{ id: "a4", actor: "Kenji Watanabe", initials: "KW", action: "commented on", target: "Adoption metrics.xlsx", time: "3h ago" },
{ id: "a5", actor: "Priya Nair", initials: "PN", action: "added 2 members to", target: "Product Core", time: "5h ago" },
];
export const callHistory = [
{ id: "cl1", name: "Priya Nair", initials: "PN", type: "Video", direction: "Outgoing", time: "Today, 08:40", duration: "12 min" },
{ id: "cl2", name: "Design Sync", initials: "DS", type: "Audio", direction: "Incoming", time: "Yesterday, 17:05", duration: "34 min" },
{ id: "cl3", name: "Marco Silva", initials: "MS", type: "Audio", direction: "Missed", time: "Yesterday, 14:22", duration: "β" },
{ id: "cl4", name: "Amara Diallo", initials: "AD", type: "Video", direction: "Incoming", time: "Mon, 11:10", duration: "22 min" },
];
export const adminStats = [
{ label: "Total users", value: "1,284", delta: "+42 this month" },
{ label: "Active users", value: "912", delta: "71% of workspace" },
{ label: "Meetings today", value: "186", delta: "+18% vs. yesterday" },
{ label: "Messages sent", value: "48.2k", delta: "last 7 days" },
{ label: "Files uploaded", value: "3,401", delta: "+126 today" },
{ label: "Teams created", value: "94", delta: "+6 this month" },
];
export const dauSeries = [
{ day: "Mon", users: 720 }, { day: "Tue", users: 810 }, { day: "Wed", users: 865 },
{ day: "Thu", users: 912 }, { day: "Fri", users: 848 }, { day: "Sat", users: 320 }, { day: "Sun", users: 288 },
];
export const meetingSeries = [
{ month: "Jan", meetings: 1240 }, { month: "Feb", meetings: 1380 }, { month: "Mar", meetings: 1610 },
{ month: "Apr", meetings: 1520 }, { month: "May", meetings: 1740 }, { month: "Jun", meetings: 1980 },
];
export const chatSeries = [
{ day: "Mon", messages: 6200 }, { day: "Tue", messages: 7100 }, { day: "Wed", messages: 7650 },
{ day: "Thu", messages: 8120 }, { day: "Fri", messages: 7380 }, { day: "Sat", messages: 1720 }, { day: "Sun", messages: 1410 },
];
export const storageSeries = [
{ name: "Documents", value: 42 },
{ name: "Recordings", value: 28 },
{ name: "Images", value: 18 },
{ name: "Other", value: 12 },
];
export const activityLogs = [
{ id: "l1", actor: "priya@northwind.io", action: "team.member.added", target: "Product Core", ip: "10.4.22.8", time: "Today, 09:44" },
{ id: "l2", actor: "daniel@northwind.io", action: "meeting.recording.deleted", target: "Incident retro", ip: "10.4.19.2", time: "Today, 08:58" },
{ id: "l3", actor: "aarav@northwind.io", action: "role.updated", target: "hannah@northwind.io", ip: "10.4.31.7", time: "Yesterday, 18:20" },
{ id: "l4", actor: "system", action: "storage.quota.warning", target: "Platform Engineering", ip: "β", time: "Yesterday, 12:03" },
];
export const emojis = ["π", "β€οΈ", "π", "π", "π", "π", "π", "π", "π€", "π", "π―", "π₯"];
// ===================================================================
// 2. UTILITY FUNCTIONS
// ===================================================================
function cn(...classes) {
return classes.filter(Boolean).join(" ");
}
// ===================================================================
// 3. UI COMPONENTS (Stubs for shadcn/ui used in App)
// ===================================================================
function Badge({ children, className, variant = "default" }) {
const variants = {
default: "bg-primary text-primary-foreground",
secondary: "bg-secondary text-secondary-foreground",
destructive: "bg-destructive text-destructive-foreground",
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground"
};
return {children} ;
}
function Button({ children, className, variant = "default", size = "default", asChild, ...props }) {
const variants = {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
};
const sizes = {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
};
const Comp = asChild ? "span" : "button";
return {children} ;
}
function Card({ children, className }) {
return
{children}
;
}
function CardHeader({ children, className }) {
return {children}
;
}
function CardTitle({ children, className }) {
return {children} ;
}
function CardContent({ children, className }) {
return {children}
;
}
function Input({ className, ...props }) {
return ;
}
function Label({ children, className, ...props }) {
return {children} ;
}
function Separator({ className }) {
return
;
}
function Switch({ className, defaultChecked, checked, onCheckedChange }) {
const [isChecked, setIsChecked] = useState(defaultChecked || checked || false);
const toggle = () => {
const newVal = !isChecked;
setIsChecked(newVal);
if (onCheckedChange) onCheckedChange(newVal);
};
return ;
}
function Progress({ value, className }) {
return ;
}
function Checkbox({ className, defaultChecked }) {
const [checked, setChecked] = useState(defaultChecked || false);
return setChecked(!checked)} className={cn("peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground", className)}>{checked ? : null} ;
}
function ScrollArea({ children, className }) {
return {children}
;
}
// Dialog Stubs
function Dialog({ children, open, onOpenChange }) { return <>{open && }>; }
function DialogTrigger({ children, asChild }) { return asChild ? children : {}}>{children} ; }
function DialogContent({ children }) { return <>{children}>; }
function DialogHeader({ children }) { return {children}
; }
function DialogTitle({ children }) { return {children} ; }
function DialogDescription({ children }) { return {children}
; }
function DialogFooter({ children }) { return {children}
; }
// Dropdown Stubs
function DropdownMenu({ children }) { return {children}
; }
function DropdownMenuTrigger({ children, asChild }) { return asChild ? children : {children} ; }
function DropdownMenuContent({ children, align, className }) { return {children}
; }
function DropdownMenuItem({ children, className }) { return {children}
; }
function DropdownMenuLabel({ children }) { return {children}
; }
function DropdownMenuSeparator() { return
; }
// Tabs Stubs
function Tabs({ children, defaultValue, value, onValueChange }) {
const [active, setActive] = useState(value || defaultValue);
const handleChange = (val) => { setActive(val); if (onValueChange) onValueChange(val); };
return {React.Children.map(children, child => React.cloneElement(child, { _active: active, _onChange: handleChange }))}
;
}
function TabsList({ children, className }) { return {children}
; }
function TabsTrigger({ children, value, className, _active, _onChange }) {
const isActive = _active === value;
return _onChange(value)} className={cn("inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50", isActive ? "bg-background text-foreground shadow-sm" : "hover:bg-background/50", className)}>{children} ;
}
function TabsContent({ children, value, className, _active }) {
if (_active !== value) return null;
return {children}
;
}
// Popover Stubs
function Popover({ children, open, onOpenChange }) { return <>{open && {children}
}>; }
function PopoverTrigger({ children, asChild }) { return asChild ? children : {}}>{children} ; }
function PopoverContent({ children, className, align }) { return {children}
; }
// Sheet Stubs
function Sheet({ children, open, onOpenChange }) { return <>{open && }>; }
function SheetTrigger({ children, asChild }) { return asChild ? children : {children} ; }
function SheetContent({ children, side, className }) { return {children}
; }
function SheetTitle({ children }) { return {children} ; }
// Radio Stubs
function RadioGroup({ children, defaultValue, className }) { return {children}
; }
function RadioGroupItem({ value, className }) { return ; }
// Table Stubs
function Table({ children, className }) { return ; }
function TableHeader({ children }) { return {children} ; }
function TableBody({ children }) { return {children} ; }
function TableRow({ children, className }) { return {children} ; }
function TableHead({ children, className }) { return {children} ; }
function TableCell({ children, className }) { return {children} ; }
function Textarea({ className, ...props }) { return ; }
function Avatar({ children, className }) { return {children}
; }
function AvatarFallback({ children, className, style }) { return {children}
; }
// ===================================================================
// 4. CORE COMPONENTS (AppShell & UserAvatar)
// ===================================================================
function PresenceDot({ presence, className }) {
const presenceColor = {
online: "bg-success",
busy: "bg-destructive",
away: "bg-warning",
offline: "bg-muted-foreground",
};
return ;
}
function UserAvatar({ initials, presence, size = "md", tint }) {
const dims = size === "sm" ? "size-8 text-xs" : size === "lg" ? "size-12 text-base" : "size-10 text-sm";
return (
{initials}
{presence ? : null}
);
}
function NotificationsPopover() {
const unread = notifications.filter((n) => n.unread).length;
return (
{unread > 0 ? {unread} : null}
Notifications
{unread} new
{notifications.map((n) => (
{n.detail}
))}
);
}
function NavRail({ onNavigate }) {
const navItems = [
{ label: "Activity", icon: Activity, to: "/" },
{ label: "Chat", icon: MessageSquare, to: "/chat" },
{ label: "Teams", icon: Users, to: "/teams" },
{ label: "Meetings", icon: Video, to: "/meetings" },
{ label: "Calendar", icon: Calendar, to: "/calendar" },
{ label: "Files", icon: FileText, to: "/files" },
{ label: "Tasks", icon: CheckCheck, to: "/tasks" },
{ label: "Calls", icon: Phone, to: "/calls" },
{ label: "Contacts", icon: Users, to: "/contacts" },
{ label: "Admin", icon: Shield, to: "/admin" },
{ label: "Settings", icon: Settings, to: "/settings" },
];
return (
{navItems.map((item) => (
{item.label}
))}
Logout
);
}
function AppShell({ children, rightRail, contentClassName }) {
const [mobileOpen, setMobileOpen] = useState(false);
return (
{currentUser.name}
{currentUser.email}
Profile & settings
Admin panel
Sign out
{children}
{rightRail ?
: null}
);
}
function PageHeader({ title, subtitle, actions }) {
return (
{title}
{subtitle ?
{subtitle}
: null}
{actions ?
{actions}
: null}
);
}
// ===================================================================
// 5. PAGE COMPONENTS
// ===================================================================
// --- LOGIN ---
function LoginPage() {
const [showPassword, setShowPassword] = useState(false);
const { navigate } = React.useContext(RouteContext);
return (
Northwind Teams
Chat, meetings, files and tasks for the whole organisation β one secure workspace that works on every device.
HD video meetings with recording and screen share Realtime channels, threads and file sharing Role-based admin controls and analytics
Northwind Teams
Sign in
Use your work account to continue.
or
G Continue with Google
New to Northwind? Create an account
);
}
// --- HOME ---
function HomePage() {
const upcoming = meetings.filter((m) => m.status !== "past");
const quickActions = [{ label: "New chat", icon: MessageSquare, to: "/chat" }, { label: "Meet now", icon: Video, to: "/meetings" }, { label: "Schedule", icon: CalendarDays, to: "/meetings" }, { label: "Upload file", icon: Upload, to: "/files" }];
return (
}>
Thursday, 6 August
Good evening, Aarav You have 4 meetings left today, 7 unread messages and 2 tasks due.
Meet now Schedule
{quickActions.map((a) => (
{a.label}
))}
Upcoming meetings All
{upcoming.map((m) => (
{m.day} {m.time}
{m.title}
{m.organizer} Β· {m.duration}
{m.status === "live" ?
Live :
Join}
))}
Recent chats All
{conversations.slice(0, 5).map((c) => (
{c.time}
{c.unread > 0 ?
{c.unread} : null}
))}
Team activity {activity.map((a) => {a.actor} {a.action} {a.target} {a.time}
)}
Recent files All
{files.slice(2, 7).map((f) => (
{f.name.split(".").pop()?.slice(0, 3)}
{f.name}
{f.owner} Β· {f.modified}
{f.size}
))}
);
}
function RightRail() {
return (
Online members {people.filter((p) => p.presence !== "offline").map((p) => {p.name}
{presenceLabel[p.presence]}
)}
Today {meetings.filter((m) => m.day === "Today").map((m) => {m.time}
{m.title}
{m.duration}
)}
Notifications {notifications.slice(0, 4).map((n) => {n.title}
{n.detail}
)}
);
}
// --- CHAT ---
function ChatPage() {
const [draft, setDraft] = useState("");
const active = conversations[0];
return (
{active.name}
{active.teamName ? `${active.teamName} Β· channel` : active.presence ? presenceLabel[active.presence] : "Group chat"}
{messages.map((m) => (
{m.author} {m.time} {m.pinned ?
Pinned : null}
{m.body}
{m.attachment ?
PDF {m.attachment.name} {m.attachment.size}
: null}
{m.edited ?
(edited) : null}
{[Reply, Forward, Pin].map((Icon, i) =>
)}
Edit message Forward Delete
{m.reactions?.map((r) => {r.emoji} {r.count} )}
{m.self ? (m.read ? : ) : null}
))}
Sofia is typingβ¦
Emoji & GIF
{emojis.map((e) => setDraft((d) => d + e)} className="grid size-8 place-items-center rounded-lg hover:bg-muted">{e} )}
setDraft(e.target.value)} placeholder={`Message ${active.name}`} className="rounded-xl" />
setDraft("")} aria-label="Send">
);
}
// --- TEAMS ---
function CreateTeamDialog() {
return (
Create team
Create a team Teams hold channels, files, tasks and meeting history.
Create team
);
}
function TeamsPage() {
return (
Join team >} />
{teams.map((team) => (
{team.name.slice(0, 2).toUpperCase()}
{team.name}{team.visibility}
{team.description}
Channels Members More
{team.channels.map((ch) => {ch}
)}
{people.slice(0, 4).map((p) => {p.name} {p.id === "u1" ? "Admin" : "Member"}
)}
+{team.members - 4} more members
{team.members} members
{team.files} shared files
{team.meetings} past meetings
Invite
Manage
Leave
))}
);
}
// --- MEETINGS ---
function ScheduleDialog() {
return (
Schedule
Schedule a meeting Invitees get an email and a calendar entry.
Schedule
);
}
function MeetingCard({ meeting }) {
return (
{meeting.title}
{meeting.status === "live" ?
Live : meeting.recorded ?
Recorded : null}
{meeting.day} Β· {meeting.time} Β· {meeting.duration}
{meeting.attendees.slice(0, 5).map((a) => )}
{meeting.attendees.length > 5 ? +{meeting.attendees.length - 5} : null}
{meeting.status === "past" ? "Details" : "Join"}
);
}
function MeetingsPage() {
const upcoming = meetings.filter((m) => m.status !== "past");
const past = meetings.filter((m) => m.status === "past");
return (
Meet now >} />
Join with a meeting ID
Or paste a link
Join
Upcoming Past & recordings
{upcoming.map((m) => )}
Add to calendar
{past.map((m) => )}
Share an invite https://meet.northwind.io/j/8241-9930-114 Copy link
);
}
// --- MEETING DETAIL (Live Call) ---
function MeetingDetailPage() {
const [muted, setMuted] = useState(false);
const [camOff, setCamOff] = useState(false);
const [hand, setHand] = useState(false);
const [recording, setRecording] = useState(false);
const [panel, setPanel] = useState("people");
const [gallery, setGallery] = useState(false);
const participants = people.slice(0, 6);
return (
{participants.map((p) => )}
{panel ? (
setPanel(v)} className="flex min-h-0 flex-1 flex-col">
Chat People
{[{ who: "Priya Nair", text: "Sharing my screen in a second." }, { who: "Sofia Rossi", text: "The new gallery states look great here." }, { who: "Kenji Watanabe", text: "Can you zoom in on the chart?" }].map((m, i) =>
)}
In the meeting
{participants.map((p, i) => {p.name} {i === 0 ? Host : null}{i % 3 === 1 ? : null} )}
Waiting room (1)
Hannah Blum Admit
Host controls
Mute on entry
Lock meeting
Recording
) : null}
setMuted((v) => !v)} label={muted ? "Unmute" : "Mute"}>{muted ? : }
setCamOff((v) => !v)} label="Camera">{camOff ? : }
setHand((v) => !v)} label="Raise hand">
setPanel(panel === "chat" ? null : "chat")}>
setPanel(panel === "people" ? null : "people")}>
Leave
);
}
function ControlButton({ children, label, active, onClick, className }) {
return {children} ;
}
function Tile({ person, large }) {
return {person.name} {person.presence === "busy" ? : null}
;
}
// --- CALENDAR ---
function CalendarPage() {
const [monthOffset, setMonthOffset] = useState(0);
const hours = Array.from({ length: 10 }, (_, i) => `${8 + i}:00`);
const weekDays = ["Mon 3", "Tue 4", "Wed 5", "Thu 6", "Fri 7"];
const weekEvents = { "Thu 6": [{ time: "10:00", title: "Daily standup", tone: "bg-primary/10 text-primary" }, { time: "13:30", title: "Release 4.2", tone: "bg-chart-3/20 text-chart-3" }], "Fri 7": [{ time: "09:30", title: "QBR", tone: "bg-chart-4/20 text-chart-4" }] };
return (
setMonthOffset((v) => v - 1)} aria-label="Previous"> {monthOffset === 0 ? "Today" : `${monthOffset > 0 ? "+" : ""}${monthOffset}`} setMonthOffset((v) => v + 1)} aria-label="Next">
New event >} />
Day Week Month
{hours.map((h) => { const ev = meetings.find((m) => m.day === "Today" && m.time.startsWith(h.slice(0, 2))); return {h} {ev ? {ev.title}
{ev.duration} Β· {ev.organizer}
:
} ; })}
{weekDays.map((d) => (
{d}
{(weekEvents[d] ?? []).map((e) =>
)}
))}
{["S", "M", "T", "W", "T", "F", "S"].map((d, i) => {d} )}
{Array.from({ length: 35 }, (_, i) => { const day = i - 5; const inMonth = day >= 1 && day <= 31; const isToday = day === 6; return
{inMonth ? day : ""} {inMonth && [6, 7, 12, 19].includes(day) ? {day === 6 ? "3 meetings" : "1 meeting"} : null}
; })}
Reminders {meetings.slice(0, 3).map((m) => {m.title}
{m.day} at {m.time}
15 min before )}
Connected calendars Google Calendar Connect
Outlook Calendar Connect
);
}
// --- FILES ---
const kindLabel = { folder: "FLD", doc: "DOC", sheet: "XLS", slide: "PPT", image: "IMG", pdf: "PDF" };
function FilesPage() {
const [query, setQuery] = useState("");
const filtered = files.filter((f) => f.name.toLowerCase().includes(query.toLowerCase()));
return (
New folder Upload >} />
setQuery(e.target.value)} maxLength={100} placeholder="Search files and folders" className="rounded-xl pl-9" />
Name Owner Modified Size Shared with {filtered.map((f) => {f.kind === "folder" ? : kindLabel[f.kind]} {f.name}
{f.owner} {f.modified} {f.size} {f.shared} people Preview Download Share Rename Delete )}
);
}
// --- TASKS ---
const priorityTone = { Urgent: "bg-destructive/10 text-destructive", High: "bg-chart-5/20 text-warning-foreground", Medium: "bg-accent text-accent-foreground", Low: "bg-secondary text-secondary-foreground" };
const taskColumns = ["To do", "In progress", "Done"];
function TaskCard({ task }) {
return {task.priority} {task.due}{task.team ?? task.scope}
;
}
function Board({ filter }) {
const list = filter ? tasks.filter((t) => t.scope === filter) : tasks;
return {taskColumns.map((col) => { const items = list.filter((t) => t.status === col); return
{col} {items.length} {items.map((t) => )}{items.length === 0 ? Nothing here
: null} ; })}
;
}
function TasksPage() {
return New task} />All Personal Team ;
}
// --- CALLS ---
function CallsPage() {
return
Recent calls {callHistory.map((c) => {c.name}
{c.direction === "Missed" ? : c.direction === "Incoming" ? : }{c.type} Β· {c.time} Β· {c.duration}
)}
;
}
// --- CONTACTS ---
function ContactGrid({ list }) {
return {list.map((p) =>
{p.name}
{p.favorite ?
: null}
{p.role}
{p.email}
{presenceLabel[p.presence]} {p.department}
)}
;
}
function ContactsPage() {
const [query, setQuery] = useState("");
const filtered = people.filter((p) => `${p.name} ${p.department} ${p.role}`.toLowerCase().includes(query.toLowerCase()));
return setQuery(e.target.value)} placeholder="Search contacts" className="rounded-xl pl-9" />
All Online Offline Favourites p.presence !== "offline")} /> p.presence === "offline")} /> p.favorite)} /> ;
}
// --- SETTINGS ---
function SettingsPage() {
return Profile Security Appearance Notifications
Your profile Change picture
Save changes
Password & securityTwo-factor authentication (email OTP) Sign out of all other devices Update password
Theme{["Light", "Dark", "System"].map((t) => {t} )}
Notification preferences{[ "Browser notifications", "Email notifications", "Push notifications", "Meeting invitations", "Mentions and replies", "Task reminders" ].map((label, i) => {label} )}
;
}
// --- ADMIN ---
const chartColors = ["var(--chart-1)", "var(--chart-2)", "var(--chart-3)", "var(--chart-4)", "var(--chart-5)"];
function AdminPage() {
return Owner access} />
{adminStats.map((s) =>
{s.label}
{s.value}
{s.delta}
)}
Daily active users
Meeting trends
Message volume
Storage breakdown `${name} ${(percent * 100).toFixed(0)}%`} labelLine={{ stroke: "var(--muted-foreground)" }}>{storageSeries.map((entry, index) => | )}
Activity log Actor Action Target IP Time {activityLogs.map((l) => {l.actor} {l.action} {l.target} {l.ip} {l.time} )}
;
}
// ===================================================================
// 6. ROUTER & APP ENTRY
// (Lightweight in-memory router β replaces @tanstack/react-router, which
// isn't available in this preview sandbox. Behaves like the original:
// Link navigates without a full page reload.)
// ===================================================================
const RouteContext = React.createContext({ path: "/", navigate: () => {} });
function Link({ to, params, className, onClick, children, ...props }) {
const { navigate } = React.useContext(RouteContext);
let href = to;
if (params) {
Object.entries(params).forEach(([k, v]) => {
href = href.replace(`$${k}`, v);
});
}
return (
{
e.preventDefault();
if (onClick) onClick(e);
navigate(href);
}}
{...props}
>
{children}
);
}
// Create "virtual" file routes since we are in a single file
const routeTree = [
{ path: "/login", component: LoginPage },
{ path: "/", component: HomePage },
{ path: "/chat", component: ChatPage },
{ path: "/teams", component: TeamsPage },
{ path: "/meetings", component: MeetingsPage },
{ path: "/meetings/", component: MeetingDetailPage, prefix: true },
{ path: "/calendar", component: CalendarPage },
{ path: "/files", component: FilesPage },
{ path: "/tasks", component: TasksPage },
{ path: "/calls", component: CallsPage },
{ path: "/contacts", component: ContactsPage },
{ path: "/settings", component: SettingsPage },
{ path: "/admin", component: AdminPage },
];
function matchRoute(path) {
const exact = routeTree.find((r) => !r.prefix && r.path === path);
if (exact) return exact.component;
const prefixMatch = routeTree.find((r) => r.prefix && path.startsWith(r.path));
if (prefixMatch) return prefixMatch.component;
return HomePage;
}
function AppRouter() {
const [path, setPath] = useState("/");
const navigate = (to) => setPath(to);
const Component = matchRoute(path);
return (
);
}
// ===================================================================
// 7. GLOBAL CSS
// ===================================================================
const globalCSS = `
:root {
--background: oklch(0.97 0.003 255);
--foreground: oklch(0.15 0.02 265);
--card: oklch(1 0 0);
--card-foreground: oklch(0.15 0.02 265);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.15 0.02 265);
--primary: oklch(0.583 0.183 268.5);
--primary-foreground: oklch(1 0 0);
--primary-dark: oklch(0.442 0.132 262);
--secondary: oklch(0.962 0.006 258);
--secondary-foreground: oklch(0.35 0.02 260);
--muted: oklch(0.962 0.006 258);
--muted-foreground: oklch(0.53 0.02 260);
--accent: oklch(0.938 0.028 266);
--accent-foreground: oklch(0.442 0.132 262);
--destructive: oklch(0.577 0.221 25);
--destructive-foreground: oklch(1 0 0);
--success: oklch(0.63 0.15 155);
--success-foreground: oklch(1 0 0);
--warning: oklch(0.78 0.15 78);
--warning-foreground: oklch(0.25 0 0);
--border: oklch(0.912 0.008 258);
--input: oklch(0.912 0.008 258);
--ring: oklch(0.583 0.183 268.5);
--chart-1: oklch(0.583 0.183 268.5);
--chart-2: oklch(0.442 0.132 262);
--chart-3: oklch(0.7 0.13 200);
--chart-4: oklch(0.63 0.15 155);
--chart-5: oklch(0.78 0.15 78);
--sidebar: oklch(1 0 0);
--sidebar-foreground: oklch(0.35 0.02 260);
--sidebar-primary: oklch(0.583 0.183 268.5);
--sidebar-primary-foreground: oklch(1 0 0);
--sidebar-accent: oklch(0.955 0.02 266);
--sidebar-accent-foreground: oklch(0.442 0.132 262);
--sidebar-border: oklch(0.925 0.008 258);
--sidebar-ring: oklch(0.583 0.183 268.5);
--shadow-card: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--shadow-float: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--radius-xl: 1rem;
}
.dark {
--background: oklch(0.19 0.02 265);
--foreground: oklch(0.97 0.003 255);
--card: oklch(0.235 0.022 265);
--card-foreground: oklch(0.97 0.003 255);
--popover: oklch(0.235 0.022 265);
--popover-foreground: oklch(0.97 0.003 255);
--primary: oklch(0.66 0.16 268.5);
--primary-foreground: oklch(0.15 0.02 265);
--primary-dark: oklch(0.5 0.14 262);
--secondary: oklch(0.29 0.025 265);
--secondary-foreground: oklch(0.95 0.005 255);
--muted: oklch(0.29 0.025 265);
--muted-foreground: oklch(0.72 0.02 260);
--accent: oklch(0.33 0.05 266);
--accent-foreground: oklch(0.92 0.02 266);
--destructive: oklch(0.65 0.2 25);
--destructive-foreground: oklch(1 0 0);
--success: oklch(0.7 0.15 155);
--success-foreground: oklch(0.15 0.02 265);
--warning: oklch(0.82 0.15 78);
--warning-foreground: oklch(0.2 0 0);
--border: oklch(1 0 0 / 12%);
--input: oklch(1 0 0 / 16%);
--ring: oklch(0.66 0.16 268.5);
--chart-1: oklch(0.66 0.16 268.5);
--chart-2: oklch(0.55 0.14 262);
--chart-3: oklch(0.75 0.12 200);
--chart-4: oklch(0.7 0.15 155);
--chart-5: oklch(0.82 0.15 78);
--sidebar: oklch(0.22 0.022 265);
--sidebar-foreground: oklch(0.9 0.01 258);
--sidebar-primary: oklch(0.66 0.16 268.5);
--sidebar-primary-foreground: oklch(0.15 0.02 265);
--sidebar-accent: oklch(0.31 0.04 266);
--sidebar-accent-foreground: oklch(0.95 0.01 266);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.66 0.16 268.5);
}
body { background-color: var(--background); color: var(--foreground); font-family: system-ui, -apple-system, sans-serif; -webkit-font-smoothing: antialiased; }
.glass-panel { background: color-mix(in oklab, var(--card) 72%, transparent); backdrop-filter: blur(18px) saturate(140%); border: 1px solid color-mix(in oklab, var(--border) 80%, transparent); }
.surface-card { background: var(--card); border: 1px solid var(--border); border-radius: var(--radius-xl); box-shadow: var(--shadow-card); }
.brand-gradient { background-image: linear-gradient(135deg, var(--primary), var(--primary-dark)); }
.scroll-slim { scrollbar-width: thin; scrollbar-color: color-mix(in oklab, var(--muted-foreground) 40%, transparent) transparent; }
`;
// ===================================================================
// 8. MOUNT APPLICATION
// ===================================================================
export default function App() {
return (
);
}