diff --git a/frontend/src/components/dashboard/OpenSessions.tsx b/frontend/src/components/dashboard/OpenSessions.tsx
new file mode 100644
index 00000000..88c77695
--- /dev/null
+++ b/frontend/src/components/dashboard/OpenSessions.tsx
@@ -0,0 +1,65 @@
+import { Link } from 'react-router-dom'
+import { getTreeNavigatePath } from '@/lib/routing'
+
+interface OpenSession {
+ id: string
+ treeName: string
+ treeId: string
+ treeType?: string
+ stepNumber?: number
+ totalSteps?: number
+ timeAgo: string
+}
+
+interface OpenSessionsProps {
+ sessions: OpenSession[]
+}
+
+export function OpenSessions({ sessions }: OpenSessionsProps) {
+ return (
+
+
+
My Open Sessions
+
+ View All
+
+
+
+ {sessions.length === 0 ? (
+
+ ) : (
+ sessions.map((session, i) => (
+
+
+
+
{session.treeName}
+
+ {session.stepNumber && session.totalSteps
+ ? `Step ${session.stepNumber} of ${session.totalSteps}`
+ : 'In progress'}
+ ·
+ {session.timeAgo}
+
+
+
+ Resume
+
+
+ ))
+ )}
+
+
+ )
+}
diff --git a/frontend/src/components/dashboard/QuickActions.tsx b/frontend/src/components/dashboard/QuickActions.tsx
new file mode 100644
index 00000000..0062a1bb
--- /dev/null
+++ b/frontend/src/components/dashboard/QuickActions.tsx
@@ -0,0 +1,41 @@
+import { useNavigate } from 'react-router-dom'
+import { Plus, Play, BookOpen, UserPlus } from 'lucide-react'
+
+const ACTIONS = [
+ { icon: Plus, label: 'New Flow', description: 'Create a new flow', href: '/trees/new', color: '#06b6d4' },
+ { icon: Play, label: 'Resume Session', description: 'Continue where you left off', href: '/sessions', color: '#34d399' },
+ { icon: BookOpen, label: 'Browse Library', description: 'Explore step library', href: '/step-library', color: '#fbbf24' },
+ { icon: UserPlus, label: 'Invite Team', description: 'Add team members', href: '/account', color: '#818cf8' },
+] as const
+
+export function QuickActions() {
+ const navigate = useNavigate()
+
+ return (
+
+
+
Quick Actions
+
+
+ {ACTIONS.map(({ icon: Icon, label, description, href, color }) => (
+
+ ))}
+
+
+ )
+}
diff --git a/frontend/src/components/dashboard/RecentActivity.tsx b/frontend/src/components/dashboard/RecentActivity.tsx
new file mode 100644
index 00000000..157b592a
--- /dev/null
+++ b/frontend/src/components/dashboard/RecentActivity.tsx
@@ -0,0 +1,58 @@
+import type { LucideIcon } from 'lucide-react'
+import { GitBranch, Play, CheckCircle, FileText, Edit } from 'lucide-react'
+
+interface ActivityItem {
+ id: string
+ icon: LucideIcon
+ iconColor: string
+ iconBg: string
+ description: string
+ timestamp: string
+}
+
+interface RecentActivityProps {
+ activities?: ActivityItem[]
+}
+
+const DEFAULT_ACTIVITIES: ActivityItem[] = [
+ { id: '1', icon: Play, iconColor: '#34d399', iconBg: 'rgba(52, 211, 153, 0.1)', description: 'Started VPN Connectivity Triage session', timestamp: '2 min ago' },
+ { id: '2', icon: CheckCircle, iconColor: '#06b6d4', iconBg: 'rgba(6, 182, 212, 0.1)', description: 'Completed M365 License Provisioning', timestamp: '15 min ago' },
+ { id: '3', icon: Edit, iconColor: '#fbbf24', iconBg: 'rgba(251, 191, 36, 0.1)', description: 'Updated Printer Troubleshooting flow', timestamp: '1 hr ago' },
+ { id: '4', icon: GitBranch, iconColor: '#818cf8', iconBg: 'rgba(129, 140, 248, 0.1)', description: 'Created new DNS Resolution flow', timestamp: '3 hr ago' },
+ { id: '5', icon: FileText, iconColor: '#8891a0', iconBg: 'rgba(136, 145, 160, 0.1)', description: 'Exported session report #TK-4821', timestamp: 'Yesterday' },
+]
+
+export function RecentActivity({ activities = DEFAULT_ACTIVITIES }: RecentActivityProps) {
+ return (
+
+
+
Recent Activity
+
+
+ {activities.map((item, i) => (
+
+
+
+
+
+
+ {item.timestamp}
+
+
+ ))}
+
+
+ )
+}
diff --git a/frontend/src/components/dashboard/WeeklyCalendar.tsx b/frontend/src/components/dashboard/WeeklyCalendar.tsx
new file mode 100644
index 00000000..b9a1e51d
--- /dev/null
+++ b/frontend/src/components/dashboard/WeeklyCalendar.tsx
@@ -0,0 +1,91 @@
+import { useMemo } from 'react'
+import { Calendar } from 'lucide-react'
+
+interface CalendarEvent {
+ id: string
+ title: string
+ time: string
+ type: 'default' | 'maintenance'
+}
+
+interface WeeklyCalendarProps {
+ events?: Record
+}
+
+const DAY_NAMES = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']
+
+function getWeekDays(): { label: string; date: Date; dateStr: string; isToday: boolean }[] {
+ const now = new Date()
+ const day = now.getDay()
+ const mondayOffset = day === 0 ? 6 : day - 1
+ const monday = new Date(now)
+ monday.setDate(now.getDate() - mondayOffset)
+
+ return DAY_NAMES.map((label, i) => {
+ const d = new Date(monday)
+ d.setDate(monday.getDate() + i)
+ const dateStr = d.toISOString().split('T')[0]
+ const isToday = d.toDateString() === now.toDateString()
+ return { label, date: d, dateStr, isToday }
+ })
+}
+
+export function WeeklyCalendar({ events = {} }: WeeklyCalendarProps) {
+ const days = useMemo(() => getWeekDays(), [])
+
+ return (
+
+
+
+
This Week
+
+
+ {days.map((day, i) => {
+ const dayEvents = events[day.dateStr] || []
+ return (
+
+
+
+ {day.label}
+
+
+ {day.date.getDate()}
+
+
+
+ {dayEvents.length === 0 ? (
+
No events
+ ) : (
+ dayEvents.map(event => (
+
+
{event.title}
+
{event.time}
+
+ ))
+ )}
+
+
+ )
+ })}
+
+
+ )
+}