import { // Activity, BadgeCheck, BookOpen, // Coins, DollarSign, HelpCircle, MessageSquare, Star, TicketCheck, // TrendingUp, Users, Bell, UsersRound, } from "lucide-react" import spinnerSrc from "../assets/Circular-indeterminate progress indicator.svg" import { Area, AreaChart, Bar, BarChart, CartesianGrid, Cell, Pie, PieChart, ResponsiveContainer, Tooltip, XAxis, YAxis, } from "recharts" import { StatCard } from "../components/dashboard/StatCard" import alertSrc from "../assets/Alert.svg" import { Card, CardContent, CardHeader, CardTitle } from "../components/ui/card" import { cn } from "../lib/utils" import { getTeamMemberById } from "../api/team.api" import { getDashboard } from "../api/analytics.api" import { getRatings } from "../api/courses.api" import { useEffect, useState } from "react" import type { DashboardData } from "../types/analytics.types" import type { Rating } from "../types/course.types" const PIE_COLORS = ["#9E2891", "#FFD23F", "#1DE9B6", "#C26FC0", "#6366F1", "#F97316", "#14B8A6", "#EF4444"] function formatDate(dateStr: string) { const d = new Date(dateStr) return d.toLocaleDateString("en-US", { month: "short", day: "numeric" }) } export function DashboardPage() { const [userFirstName, setUserFirstName] = useState("") const [dashboard, setDashboard] = useState(null) const [loading, setLoading] = useState(true) const [activeStatTab, setActiveStatTab] = useState<"primary" | "secondary">("primary") const [appRatings, setAppRatings] = useState([]) const [appRatingsLoading, setAppRatingsLoading] = useState(true) useEffect(() => { const fetchUser = async () => { try { const memberId = Number(localStorage.getItem("member_id")) const res = await getTeamMemberById(memberId) const member = res.data.data setUserFirstName(member.first_name) localStorage.setItem("user_first_name", member.first_name) localStorage.setItem("user_last_name", member.last_name) window.dispatchEvent(new Event("user-profile-updated")) } catch (err) { console.error(err) } } const fetchDashboard = async () => { try { const res = await getDashboard() setDashboard(res.data as unknown as DashboardData) } catch (err) { console.error(err) } finally { setLoading(false) } } const fetchAppRatings = async () => { try { const res = await getRatings({ target_type: "app", target_id: 1, limit: 5 }) setAppRatings(res.data.data) } catch (err) { console.error(err) } finally { setAppRatingsLoading(false) } } fetchUser() fetchDashboard() fetchAppRatings() }, []) const registrationData = dashboard?.users.registrations_last_30_days.map((d) => ({ date: formatDate(d.date), count: d.count, })) ?? [] const revenueData = dashboard?.payments.revenue_last_30_days.map((d) => ({ date: formatDate(d.date), revenue: d.revenue, })) ?? [] const subscriptionStatusData = dashboard?.subscriptions.by_status.map((s, i) => ({ name: s.label, value: s.count, color: PIE_COLORS[i % PIE_COLORS.length], })) ?? [] const issueStatusData = dashboard?.issues.by_status.map((s, i) => ({ name: s.label, value: s.count, color: PIE_COLORS[i % PIE_COLORS.length], })) ?? [] return (
Dashboard
Welcome, {userFirstName || localStorage.getItem("user_first_name")}
{loading ? (
Loading dashboard…
) : !dashboard ? (
Failed to load dashboard data.
) : ( <> {/* Stat tabs */}
{/* Stat Cards */} {activeStatTab === "primary" && (
0} /> 0} /> 0} /> 0.5} />
)} {/* Secondary Stats */} {activeStatTab === "secondary" && (
)} {/* User Registrations Chart */}
User Registrations
{dashboard.users.total_users.toLocaleString()}
+{dashboard.users.new_today} today · +{dashboard.users.new_week} this week
Last 30 Days
{/* Subscription / Issue Status Pie */} {subscriptionStatusData.length > 0 ? "Subscription Status" : "Issue Status"} {(subscriptionStatusData.length > 0 ? subscriptionStatusData : issueStatusData).length > 0 ? ( <>
0 ? subscriptionStatusData : issueStatusData} dataKey="value" nameKey="name" innerRadius={55} outerRadius={80} paddingAngle={2} > {(subscriptionStatusData.length > 0 ? subscriptionStatusData : issueStatusData).map( (entry) => ( ), )}
{(subscriptionStatusData.length > 0 ? subscriptionStatusData : issueStatusData).map((s) => (
{s.name}
{s.value.toLocaleString()}
))}
) : (
No data available
)}
{/* Revenue Chart */}
Revenue Trend
ETB {dashboard.payments.total_revenue.toLocaleString()}
Last 30 Days (ETB)
[`${Number(v).toLocaleString()}`, "ETB"]} contentStyle={{ borderRadius: 12, border: "1px solid #E0E0E0", boxShadow: "0 10px 30px rgba(0,0,0,0.08)", }} />
{/* Users by Role / Region / Knowledge Level */}
{[ { title: "Users by Role", data: dashboard.users.by_role }, { title: "Users by Region", data: dashboard.users.by_region }, { title: "Users by Knowledge Level", data: dashboard.users.by_knowledge_level }, ].map(({ title, data }) => ( {title} {data.length > 0 ? (
{data.map((item, i) => (
{item.label}
{item.count.toLocaleString()}
))}
) : (
No data available
)}
))}
{/* App Ratings */}
Recent App Reviews
{appRatingsLoading ? (
) : appRatings.length === 0 ? (
No app reviews yet
) : ( <>
{Array.from({ length: 5 }).map((_, i) => ( sum + r.stars, 0) / appRatings.length, ) ? "fill-amber-400 text-amber-400" : "fill-grayScale-200 text-grayScale-200", )} /> ))}
{(appRatings.reduce((sum, r) => sum + r.stars, 0) / appRatings.length).toFixed(1)} ({appRatings.length} {appRatings.length === 1 ? "review" : "reviews"})
{appRatings.map((rating) => (
U{rating.user_id}
User #{rating.user_id} {formatDate(rating.created_at)}
{Array.from({ length: 5 }).map((_, i) => ( ))}
{rating.review && (

{rating.review}

)}
))}
)}
)}
) }