What's Happening
The main dashboard (app/dashboard/page.jsx) is largely decorative — several widgets fetch or could fetch real data but render hardcoded placeholder values:
components/organisms/dashboard/StatsOverview.jsx actually calls useStats() and destructures coursesEnrolled, booksRead, upcomingSessions, messagesUnread, totalUptime, loading, error from the real endpoint GET /api/users/:id/stats (hooks/useStats.js)… and then never uses any of it. It maps over a module-level stats array with hardcoded values (Courses Enrolled: 8, Books Read: 5, Messages Unread: 3, Total Uptime: "3643"). The fetched data is thrown away, and loading/error are ignored — there's no skeleton and no error state. Icons are also mismatched (a DollarSign icon for "Courses Enrolled", no icon at all for "Messages Unread").
components/organisms/dashboard/UpcomingSessions.jsx renders a hardcoded sessions array ("Yaoumul Jumuah Rituals — Jul 21", etc.) with the same static avatar /images/img1.jpeg for every row, and a "View Upcomings" button that navigates nowhere.
components/organisms/dashboard/LearningProgress.jsx charts a hardcoded chartData (January–June, fixed numbers) and shows a static "You've boosted study by 30%" footer. Both Bar series use the same fill (var(--color-accent)), so the "course" and "book" bars are indistinguishable despite chartConfig defining two colors.
For a returning learner, every number on the home dashboard is fiction.
Where to Find This
app/dashboard/page.jsx — composition of the widgets
components/organisms/dashboard/StatsOverview.jsx
components/organisms/dashboard/UpcomingSessions.jsx
components/organisms/dashboard/LearningProgress.jsx
hooks/useStats.js — existing, working stats fetch
What We Want
StatsOverview: render the values returned by useStats(); keep the CountUp animation for numeric values; show skeleton tiles while loading and a compact error/retry state when error is set; fix the icon mapping (book icon for books, message icon for unread messages, etc.).
UpcomingSessions: fetch the user's real upcoming sessions from the backend (coordinate the endpoint with the backend repo — if none exists yet, gate the widget behind the API and show an honest empty state "No upcoming sessions" instead of fake ones). The button should link somewhere real (e.g. /dashboard/spaces).
LearningProgress: drive the chart from real per-month activity if the stats endpoint provides it; otherwise clearly derive from available data or show an empty/placeholder state that says data is coming — remove the fabricated "+30%" claim. Give the two Bar series distinct fills (var(--color-course) / var(--color-book) from chartConfig).
- All three widgets must handle loading, error, and empty states without layout jumps.
Technical Context
useStats returns flattened res.data merged with { loading, error } — check the actual backend response shape and adjust destructuring if fields are nested.
StatsOverview already uses react-intersection-observer + react-countup for the count-up-on-scroll effect; preserve it.
- Charting is Recharts via the shadcn
ChartContainer wrapper (components/ui/chart.jsx).
- If a backend endpoint is missing, prefer an honest empty state over mock data — mention what's missing in the PR so a backend issue can be filed.
Acceptance Criteria
What's Happening
The main dashboard (
app/dashboard/page.jsx) is largely decorative — several widgets fetch or could fetch real data but render hardcoded placeholder values:components/organisms/dashboard/StatsOverview.jsxactually callsuseStats()and destructurescoursesEnrolled, booksRead, upcomingSessions, messagesUnread, totalUptime, loading, errorfrom the real endpointGET /api/users/:id/stats(hooks/useStats.js)… and then never uses any of it. It maps over a module-levelstatsarray with hardcoded values (Courses Enrolled: 8,Books Read: 5,Messages Unread: 3,Total Uptime: "3643"). The fetched data is thrown away, andloading/errorare ignored — there's no skeleton and no error state. Icons are also mismatched (aDollarSignicon for "Courses Enrolled", no icon at all for "Messages Unread").components/organisms/dashboard/UpcomingSessions.jsxrenders a hardcodedsessionsarray ("Yaoumul Jumuah Rituals — Jul 21", etc.) with the same static avatar/images/img1.jpegfor every row, and a "View Upcomings" button that navigates nowhere.components/organisms/dashboard/LearningProgress.jsxcharts a hardcodedchartData(January–June, fixed numbers) and shows a static "You've boosted study by 30%" footer. BothBarseries use the same fill (var(--color-accent)), so the "course" and "book" bars are indistinguishable despitechartConfigdefining two colors.For a returning learner, every number on the home dashboard is fiction.
Where to Find This
app/dashboard/page.jsx— composition of the widgetscomponents/organisms/dashboard/StatsOverview.jsxcomponents/organisms/dashboard/UpcomingSessions.jsxcomponents/organisms/dashboard/LearningProgress.jsxhooks/useStats.js— existing, working stats fetchWhat We Want
StatsOverview: render the values returned byuseStats(); keep theCountUpanimation for numeric values; show skeleton tiles whileloadingand a compact error/retry state whenerroris set; fix the icon mapping (book icon for books, message icon for unread messages, etc.).UpcomingSessions: fetch the user's real upcoming sessions from the backend (coordinate the endpoint with the backend repo — if none exists yet, gate the widget behind the API and show an honest empty state "No upcoming sessions" instead of fake ones). The button should link somewhere real (e.g./dashboard/spaces).LearningProgress: drive the chart from real per-month activity if the stats endpoint provides it; otherwise clearly derive from available data or show an empty/placeholder state that says data is coming — remove the fabricated "+30%" claim. Give the twoBarseries distinct fills (var(--color-course)/var(--color-book)fromchartConfig).Technical Context
useStatsreturns flattenedres.datamerged with{ loading, error }— check the actual backend response shape and adjust destructuring if fields are nested.StatsOverviewalready usesreact-intersection-observer+react-countupfor the count-up-on-scroll effect; preserve it.ChartContainerwrapper (components/ui/chart.jsx).Acceptance Criteria
StatsOverviewreflects the numbers from/api/users/:id/stats, with skeletons while loading and an error state on failure.UpcomingSessionsshows real sessions or an honest empty state; every row's avatar/title comes from data.