import { useEffect } from "react"; import { useNavigate, useParams } from "react-router-dom"; import * as LucideIcons from "lucide-react"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Skeleton } from "@/components/ui/skeleton"; import { ArrowLeft, BookOpen, Clock, Check, Tag, CalendarDays, } from "lucide-react"; import { useClientTiers } from "@/contexts/ClientTiersProvider"; import { useProfile } from "@/contexts/ProfileProvider"; import { PageMeta } from "@/contexts/MetadataContext"; import { useDateFormat } from "@/hooks/useDateFormat"; import { resolveTierBadge } from "@/utils/tierBadge.util"; import { getTierColor } from "@/utils/tierColors"; // ─── Helpers ────────────────────────────────────────────────────────────────── const UNIT_TO_DAYS = { minute: 1 / 1440, hour: 1 / 24, day: 1, month: 30, year: 365 }; function formatDuration(days, unit) { if (!days) return null; const multiplier = UNIT_TO_DAYS[unit] ?? 1; const value = Math.round((days / multiplier) * 1000) / 1000; const label = unit ?? "day"; return `${value} ${label}${value !== 1 ? "s" : ""}`; } function formatCourseDuration(seconds = 0) { if (!seconds) return null; const h = Math.floor(seconds / 3600); const m = Math.floor((seconds % 3600) / 60); if (h && m) return `${h}h ${m}m`; if (h) return `${h}h`; return `${m}m`; } // ─── Skeleton ───────────────────────────────────────────────────────────────── const ViewPlanSkeleton = () => (
); // ─── Component ──────────────────────────────────────────────────────────────── const ViewPlan = () => { const { id } = useParams(); const navigate = useNavigate(); const { myTier, getMyTier, plans, plansLoading, getPlans, tierMap, getTierCategories } = useClientTiers(); const { getProfile } = useProfile(); const { fmtCurrency } = useDateFormat(); useEffect(() => { getProfile(); getMyTier(); getTierCategories(); if (!plans.length) getPlans(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [id]); const plan = plans.find((p) => String(p.plan_id) === String(id)) ?? null; const loading = plansLoading; if (loading) return ; if (!plan) return null; const { label: tierLabel, cls: badgeCls } = resolveTierBadge(plan.tier, tierMap); const Icon = LucideIcons[tierMap[plan.tier]?.badge_icon] ?? Tag; const colors = getTierColor(tierMap[plan.tier]?.color ?? "purple"); const accentSwatch = colors.swatch; const accentStyle = { color: accentSwatch }; const accentBg = colors.panel.bg; const accentBorder = colors.panel.border; const features = plan.features ?? []; const duration = formatDuration(plan.duration_days, plan.duration_unit); const isCurrent = myTier?.tier === plan.tier && myTier?.status === "active"; const totalSeconds = (plan.courses ?? []).reduce((sum, c) => sum + (c.duration_seconds ?? 0), 0); const totalDuration = formatCourseDuration(totalSeconds); return (
{/* ── Hero Banner ───────────────────────────────────────────── */}
{/* Decorative blobs */}
{tierLabel}

{plan.label}

{plan.description || `Everything you need with the ${tierLabel} plan.`}

{fmtCurrency(plan.price, plan.currency)} {duration && ( / {duration} )}
{isCurrent ? ( Your Current Plan ) : !plan.is_active ? ( Not Available at the Moment ) : ( )}
{/* ── What's included ───────────────────────────────────── */} {features.length > 0 && (

What's included

{features.map(({ text }, i) => (
{text}
))}
)} {/* ── Stats row ─────────────────────────────────────────── */}
{[ { label: "Courses", value: plan.course_count ?? 0, icon: BookOpen }, { label: "Content", value: totalDuration ?? "—", icon: Clock }, { label: "Access", value: duration ?? "Lifetime", icon: CalendarDays }, ].map(({ label, value, icon: StatIcon }) => (

{value}

{label}

))}
{/* ── Included Courses ──────────────────────────────────── */}
Included Courses
{plan.course_count ?? 0}
{plan.courses?.length > 0 ? ( plan.courses.map((course) => (

{course.title}

{course.level && ( {course.level} )} {formatCourseDuration(course.duration_seconds) && ( {formatCourseDuration(course.duration_seconds)} )} {course.course_code && ( {course.course_code} )}
)) ) : (

Courses coming soon

We're curating the best content for this plan. Subscribe now and get instant access the moment they go live.

)}
{/* ── Bottom CTA ────────────────────────────────────────── */} {!isCurrent && (

{plan.is_active ? "Ready to get started?" : "Coming Soon"}

{plan.is_active ? (plan.description || `Everything you need with the ${tierLabel} plan.`) : "This plan is not available for purchase at the moment. Check back later."}

{plan.is_active && ( )}
)}
); }; export default ViewPlan;