2026-01-07 09:31:02 +00:00
|
|
|
import React, { useState } from 'react';
|
|
|
|
|
import { Button } from '../ui/button';
|
|
|
|
|
import { Card } from '../ui/card';
|
|
|
|
|
import { Course } from '../../types';
|
2026-01-13 18:47:57 +00:00
|
|
|
import {
|
|
|
|
|
PlayCircle,
|
|
|
|
|
Star,
|
|
|
|
|
Users,
|
|
|
|
|
CheckCircle,
|
|
|
|
|
Clock,
|
|
|
|
|
Globe,
|
|
|
|
|
ShieldCheck,
|
|
|
|
|
Lock,
|
|
|
|
|
ChevronDown,
|
|
|
|
|
ChevronUp,
|
|
|
|
|
} from 'lucide-react';
|
2026-01-26 13:12:17 +00:00
|
|
|
import { useToast } from '../../components/feedback/ToastProvider';
|
2026-01-07 09:31:02 +00:00
|
|
|
|
|
|
|
|
interface CourseDetailViewProps {
|
|
|
|
|
course: Course;
|
|
|
|
|
onBack: () => void;
|
|
|
|
|
onEnroll: () => void;
|
|
|
|
|
isEnrolled?: boolean;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
export const CourseDetailView: React.FC<CourseDetailViewProps> = ({
|
|
|
|
|
course,
|
|
|
|
|
onBack,
|
|
|
|
|
onEnroll,
|
|
|
|
|
isEnrolled,
|
|
|
|
|
}) => {
|
2026-01-07 09:31:02 +00:00
|
|
|
const { addToast: _addToast } = useToast();
|
2026-01-13 18:47:57 +00:00
|
|
|
const [activeTab, setActiveTab] = useState<
|
|
|
|
|
'overview' | 'curriculum' | 'reviews'
|
|
|
|
|
>('overview');
|
|
|
|
|
const [expandedModule, setExpandedModule] = useState<string | null>(
|
|
|
|
|
course.modules?.[0].id || null,
|
|
|
|
|
);
|
2026-01-07 09:31:02 +00:00
|
|
|
|
|
|
|
|
const toggleModule = (id: string) => {
|
2026-01-13 18:47:57 +00:00
|
|
|
setExpandedModule(expandedModule === id ? null : id);
|
2026-01-07 09:31:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="animate-fadeIn pb-20 max-w-7xl mx-auto">
|
2026-01-13 18:47:57 +00:00
|
|
|
{/* Breadcrumb */}
|
|
|
|
|
<div className="mb-6">
|
|
|
|
|
<Button
|
|
|
|
|
variant="ghost"
|
|
|
|
|
onClick={onBack}
|
2026-01-16 00:59:31 +00:00
|
|
|
className="pl-0 text-kodo-content-dim hover:text-white"
|
2026-01-13 18:47:57 +00:00
|
|
|
>
|
|
|
|
|
← Back to Courses
|
|
|
|
|
</Button>
|
|
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
|
|
|
|
|
{/* Left Content */}
|
|
|
|
|
<div className="lg:col-span-2 space-y-8">
|
|
|
|
|
{/* Header */}
|
|
|
|
|
<div>
|
|
|
|
|
<h1 className="text-3xl md:text-4xl font-display font-bold text-white mb-4">
|
|
|
|
|
{course.title}
|
|
|
|
|
</h1>
|
2026-01-16 00:59:31 +00:00
|
|
|
<p className="text-xl text-kodo-text-main mb-6 font-light">
|
2026-01-13 18:47:57 +00:00
|
|
|
{course.description}
|
|
|
|
|
</p>
|
2026-01-07 09:31:02 +00:00
|
|
|
|
2026-01-16 00:59:31 +00:00
|
|
|
<div className="flex flex-wrap items-center gap-6 text-sm text-kodo-content-dim mb-6">
|
2026-01-13 18:47:57 +00:00
|
|
|
{course.rating && (
|
|
|
|
|
<span className="flex items-center gap-1 text-kodo-gold font-bold">
|
|
|
|
|
<Star className="w-4 h-4 fill-current" /> {course.rating}
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
|
|
|
|
<span className="flex items-center gap-1">
|
|
|
|
|
<Users className="w-4 h-4" />{' '}
|
|
|
|
|
{(course.studentCount || 0).toLocaleString()} students
|
|
|
|
|
</span>
|
|
|
|
|
<span className="flex items-center gap-1">
|
|
|
|
|
<Clock className="w-4 h-4" /> {course.duration} total
|
|
|
|
|
</span>
|
|
|
|
|
<span className="flex items-center gap-1">
|
|
|
|
|
<Globe className="w-4 h-4" /> English
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<div className="flex items-center gap-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
<img
|
|
|
|
|
src={`https://ui-avatars.com/api/?name=${course.instructor}&background=random`}
|
|
|
|
|
className="w-10 h-10 rounded-full"
|
|
|
|
|
/>
|
|
|
|
|
<div>
|
2026-01-16 00:59:31 +00:00
|
|
|
<div className="text-xs text-kodo-content-dim uppercase">
|
2026-01-13 18:47:57 +00:00
|
|
|
Created by
|
|
|
|
|
</div>
|
|
|
|
|
<div className="text-sm font-bold text-white text-kodo-cyan cursor-pointer hover:underline">
|
|
|
|
|
{course.instructor}
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
2026-01-13 18:47:57 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
{/* Tabs */}
|
|
|
|
|
<div className="border-b border-kodo-steel flex gap-6">
|
|
|
|
|
{['overview', 'curriculum', 'reviews'].map((tab) => (
|
|
|
|
|
<button
|
|
|
|
|
key={tab}
|
|
|
|
|
onClick={() => setActiveTab(tab as any)}
|
2026-01-16 00:59:31 +00:00
|
|
|
className={`pb-3 text-sm font-bold uppercase tracking-wider border-b-2 transition-colors ${activeTab === tab ? 'border-kodo-cyan text-white' : 'border-transparent text-kodo-content-dim hover:text-kodo-text-main'}`}
|
2026-01-13 18:47:57 +00:00
|
|
|
>
|
|
|
|
|
{tab}
|
|
|
|
|
</button>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Tab Content */}
|
|
|
|
|
{activeTab === 'overview' && (
|
|
|
|
|
<div className="space-y-8 animate-fadeIn">
|
|
|
|
|
<Card variant="default">
|
|
|
|
|
<h3 className="font-bold text-white text-lg mb-4">
|
|
|
|
|
What you'll learn
|
|
|
|
|
</h3>
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
{course.whatYouWillLearn?.map((item, i) => (
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<div key={i} className="flex gap-4 text-sm text-kodo-text-main">
|
2026-01-13 18:47:57 +00:00
|
|
|
<CheckCircle className="w-4 h-4 text-kodo-lime flex-shrink-0 mt-0.5" />
|
|
|
|
|
<span>{item}</span>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
2026-01-13 18:47:57 +00:00
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</Card>
|
2026-01-07 09:31:02 +00:00
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
<div>
|
|
|
|
|
<h3 className="font-bold text-white text-lg mb-4">
|
|
|
|
|
Requirements
|
|
|
|
|
</h3>
|
2026-01-16 00:59:31 +00:00
|
|
|
<ul className="list-disc pl-5 space-y-1 text-sm text-kodo-content-dim">
|
2026-01-13 18:47:57 +00:00
|
|
|
{course.requirements?.map((req, i) => (
|
|
|
|
|
<li key={i}>{req}</li>
|
|
|
|
|
))}
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{activeTab === 'curriculum' && (
|
|
|
|
|
<div className="space-y-4 animate-fadeIn">
|
2026-01-16 00:59:31 +00:00
|
|
|
<div className="flex justify-between items-center text-sm text-kodo-content-dim mb-2">
|
2026-01-13 18:47:57 +00:00
|
|
|
<span>
|
|
|
|
|
{course.modules?.length} Modules •{' '}
|
|
|
|
|
{course.modules?.reduce(
|
|
|
|
|
(acc, m) => acc + m.lessons.length,
|
|
|
|
|
0,
|
|
|
|
|
)}{' '}
|
|
|
|
|
Lessons
|
|
|
|
|
</span>
|
|
|
|
|
<button
|
|
|
|
|
className="text-kodo-cyan hover:underline"
|
|
|
|
|
onClick={() =>
|
|
|
|
|
setExpandedModule(expandedModule ? null : 'all')
|
|
|
|
|
}
|
|
|
|
|
>
|
|
|
|
|
{expandedModule === 'all' ? 'Collapse All' : 'Expand All'}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{course.modules?.map((module) => (
|
|
|
|
|
<div
|
|
|
|
|
key={module.id}
|
|
|
|
|
className="border border-kodo-steel rounded-lg overflow-hidden bg-kodo-ink/30"
|
|
|
|
|
>
|
|
|
|
|
<div
|
|
|
|
|
className="p-4 flex justify-between items-center cursor-pointer hover:bg-white/5 transition-colors"
|
|
|
|
|
onClick={() => toggleModule(module.id)}
|
|
|
|
|
>
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<h4 className="font-bold text-white flex items-center gap-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
{expandedModule === module.id ||
|
|
|
|
|
expandedModule === 'all' ? (
|
|
|
|
|
<ChevronUp className="w-4 h-4" />
|
|
|
|
|
) : (
|
|
|
|
|
<ChevronDown className="w-4 h-4" />
|
|
|
|
|
)}
|
|
|
|
|
{module.title}
|
|
|
|
|
</h4>
|
2026-01-16 00:59:31 +00:00
|
|
|
<span className="text-xs text-kodo-content-dim">
|
2026-01-13 18:47:57 +00:00
|
|
|
{module.lessons.length} lectures
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{(expandedModule === module.id ||
|
|
|
|
|
expandedModule === 'all') && (
|
|
|
|
|
<div className="border-t border-kodo-steel">
|
|
|
|
|
{module.lessons.map((lesson) => (
|
|
|
|
|
<div
|
|
|
|
|
key={lesson.id}
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
className="p-4 pl-8 flex justify-between items-center hover:bg-white/5 border-b border-kodo-steel/30 last:border-0"
|
2026-01-13 18:47:57 +00:00
|
|
|
>
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<div className="flex items-center gap-4 text-sm text-kodo-text-main">
|
2026-01-13 18:47:57 +00:00
|
|
|
{lesson.type === 'video' ? (
|
|
|
|
|
<PlayCircle className="w-4 h-4" />
|
|
|
|
|
) : (
|
|
|
|
|
<ShieldCheck className="w-4 h-4" />
|
|
|
|
|
)}
|
|
|
|
|
{lesson.title}
|
|
|
|
|
</div>
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<div className="flex items-center gap-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
{lesson.isLocked && !isEnrolled && (
|
2026-01-16 00:59:31 +00:00
|
|
|
<Lock className="w-3 h-3 text-kodo-content-dim" />
|
2026-01-13 18:47:57 +00:00
|
|
|
)}
|
2026-01-16 00:59:31 +00:00
|
|
|
<span className="text-xs text-kodo-content-dim">
|
2026-01-13 18:47:57 +00:00
|
|
|
{lesson.duration}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
2026-01-13 18:47:57 +00:00
|
|
|
))}
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
2026-01-13 18:47:57 +00:00
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2026-01-07 09:31:02 +00:00
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
{activeTab === 'reviews' && (
|
|
|
|
|
<div className="space-y-6 animate-fadeIn">
|
|
|
|
|
{course.reviews?.map((review) => (
|
|
|
|
|
<div
|
|
|
|
|
key={review.id}
|
|
|
|
|
className="border-b border-kodo-steel/50 pb-6"
|
|
|
|
|
>
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<div className="flex items-center gap-4 mb-2">
|
2026-01-13 18:47:57 +00:00
|
|
|
<img
|
|
|
|
|
src={review.avatar}
|
|
|
|
|
className="w-10 h-10 rounded-full"
|
|
|
|
|
/>
|
|
|
|
|
<div>
|
|
|
|
|
<div className="font-bold text-white text-sm">
|
|
|
|
|
{review.username}
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex text-kodo-gold text-xs">
|
|
|
|
|
{[...Array(5)].map((_, i) => (
|
|
|
|
|
<Star
|
|
|
|
|
key={i}
|
2026-01-16 00:59:31 +00:00
|
|
|
className={`w-3 h-3 ${i < review.rating ? 'fill-current' : 'text-kodo-text-main'}`}
|
2026-01-13 18:47:57 +00:00
|
|
|
/>
|
2026-01-07 09:31:02 +00:00
|
|
|
))}
|
2026-01-13 18:47:57 +00:00
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
2026-01-16 00:59:31 +00:00
|
|
|
<span className="ml-auto text-xs text-kodo-content-dim">
|
2026-01-13 18:47:57 +00:00
|
|
|
{review.date}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
2026-01-16 00:59:31 +00:00
|
|
|
<p className="text-sm text-kodo-text-main">{review.comment}</p>
|
2026-01-13 18:47:57 +00:00
|
|
|
</div>
|
|
|
|
|
))}
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
2026-01-13 18:47:57 +00:00
|
|
|
)}
|
|
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
{/* Right Sidebar */}
|
|
|
|
|
<div className="relative">
|
|
|
|
|
<div className="sticky top-24 space-y-6">
|
|
|
|
|
<Card
|
|
|
|
|
variant="default"
|
aesthetic-improvements: reduce more decorative cyan backgrounds (80/20 rule, batch 3)
- Layout components: Sidebar hub header icon, Header icon background (2 instances) - decorative icons
- AutoMetadataDetectionModal: modal border (decorative)
- CourseDetailView: card border (decorative)
- Total: ~4 files, ~4 instances replaced
- Preserved: Active/selected states (AudioPlayer dragged item, Header active notification, VisualizerSettingsModal selected mode, CreateProjectModal selected DAW, AIToolsView active tool, CourseLearningView active lesson, TipStreamerModal selected payment, CloudFileBrowser active tag, PlaylistDetailView dragged item, AddToPlaylistModal selected playlist, CreatorModal selected visibility)
- Action 11.3.1.3 in progress (third batch: layout and modal decorative elements)
2026-01-16 10:07:01 +00:00
|
|
|
className="p-0 overflow-hidden border-kodo-steel/30"
|
2026-01-13 18:47:57 +00:00
|
|
|
>
|
|
|
|
|
{/* Preview Video Placeholder */}
|
|
|
|
|
<div className="relative aspect-video bg-black group cursor-pointer">
|
|
|
|
|
<img
|
|
|
|
|
src={course.thumbnailUrl}
|
|
|
|
|
className="w-full h-full object-cover opacity-80"
|
|
|
|
|
/>
|
|
|
|
|
<div className="absolute inset-0 flex items-center justify-center">
|
|
|
|
|
<div className="w-16 h-16 bg-white/90 rounded-full flex items-center justify-center shadow-lg group-hover:scale-110 transition-transform">
|
|
|
|
|
<PlayCircle className="w-8 h-8 text-black fill-current" />
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="absolute bottom-4 text-center w-full text-white font-bold text-sm drop-shadow-md">
|
|
|
|
|
Preview Course
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
<div className="p-6">
|
|
|
|
|
<div className="text-3xl font-display font-bold text-white mb-2">
|
|
|
|
|
{isEnrolled
|
|
|
|
|
? 'Enrolled'
|
|
|
|
|
: course.price && course.price > 0
|
|
|
|
|
? `$${course.price}`
|
|
|
|
|
: 'Free'}
|
|
|
|
|
</div>
|
|
|
|
|
{course.price && course.price > 0 && !isEnrolled && (
|
2026-01-16 00:59:31 +00:00
|
|
|
<p className="text-kodo-content-dim text-xs mb-6 line-through">
|
2026-01-13 18:47:57 +00:00
|
|
|
$199.99 (85% off)
|
|
|
|
|
</p>
|
|
|
|
|
)}
|
2026-01-07 09:31:02 +00:00
|
|
|
|
2026-01-13 18:47:57 +00:00
|
|
|
{isEnrolled ? (
|
|
|
|
|
<Button
|
|
|
|
|
variant="primary"
|
|
|
|
|
className="w-full h-12 text-lg"
|
|
|
|
|
onClick={onEnroll}
|
|
|
|
|
>
|
|
|
|
|
CONTINUE LEARNING
|
|
|
|
|
</Button>
|
|
|
|
|
) : (
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<div className="space-y-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
<Button
|
|
|
|
|
variant="primary"
|
|
|
|
|
className="w-full h-12 text-lg"
|
|
|
|
|
onClick={onEnroll}
|
|
|
|
|
>
|
|
|
|
|
ENROLL NOW
|
|
|
|
|
</Button>
|
2026-01-16 00:59:31 +00:00
|
|
|
<p className="text-center text-xs text-kodo-content-dim">
|
2026-01-13 18:47:57 +00:00
|
|
|
30-Day Money-Back Guarantee
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
2026-01-07 09:31:02 +00:00
|
|
|
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<div className="mt-6 space-y-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
<h4 className="font-bold text-white text-sm">
|
|
|
|
|
This course includes:
|
|
|
|
|
</h4>
|
2026-01-16 00:59:31 +00:00
|
|
|
<ul className="text-sm text-kodo-content-dim space-y-2">
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<li className="flex items-center gap-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
<PlayCircle className="w-4 h-4" /> {course.duration}{' '}
|
|
|
|
|
on-demand video
|
|
|
|
|
</li>
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<li className="flex items-center gap-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
<ShieldCheck className="w-4 h-4" /> Full lifetime access
|
|
|
|
|
</li>
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<li className="flex items-center gap-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
<Globe className="w-4 h-4" /> Access on mobile and TV
|
|
|
|
|
</li>
|
|
|
|
|
{course.certificateAvailable && (
|
aesthetic-improvements: align spacing to 8px grid (Action 11.2.1.3)
- Created automated script (scripts/align-8px-grid.py) to align all spacing to 8px grid
- Replaced non-8px-aligned spacing: gap-3/p-3/m-3 (12px) → gap-4/p-4/m-4 (16px), gap-5/p-5/m-5 (20px) → gap-6/p-6/m-6 (24px), gap-10/p-10/m-10 (40px) → gap-12/p-12/m-12 (48px), gap-20/p-20/m-20 (80px) → gap-24/p-24/m-24 (96px)
- Preserved: 4px values (gap-1, p-1, m-1) as they may be intentional fine-tuning, responsive breakpoints (sm:, md:, lg:), test files, documentation
- Modified files across all components to ensure consistent 8px grid alignment
- Action 11.2.1.3: Align all elements to 8px grid - COMPLETE
2026-01-16 10:50:46 +00:00
|
|
|
<li className="flex items-center gap-4">
|
2026-01-13 18:47:57 +00:00
|
|
|
<Star className="w-4 h-4" /> Certificate of completion
|
|
|
|
|
</li>
|
|
|
|
|
)}
|
|
|
|
|
</ul>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
2026-01-13 18:47:57 +00:00
|
|
|
</div>
|
|
|
|
|
</Card>
|
|
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
2026-01-13 18:47:57 +00:00
|
|
|
</div>
|
2026-01-07 09:31:02 +00:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|