ggop213's picture
refactor(ui): complete platform de-slop and remove AI badges across all pages
48e2068
Raw History Blame Contribute Delete
11.6 kB
import { useState } from 'react';
import type { CertificationTrack } from '../../types/getcertV2';
import {
ArrowLeft,
ArrowRight,
Shield,
TrendingUp,
CheckCircle2,
ClipboardList,
PenTool
} from 'lucide-react';
import { resolveCanonicalCourseTitle } from '../../utils/courseTitleResolver';
interface CourseSelectionProps {
onCourseSelect: (courseName: string, category?: string) => void;
loading: boolean;
onBackToDashboard: () => void;
certificationTrack?: CertificationTrack | null;
}
export function CourseSelection({
onCourseSelect,
loading,
onBackToDashboard,
certificationTrack
}: CourseSelectionProps) {
const [customCourse, setCustomCourse] = useState('');
const [selectedCategory, setSelectedCategory] = useState<string | null>(null);
// Popular course recommendations
const recommendedCourses = [
{ name: 'JavaScript Fundamentals', category: 'Programming', popularity: 95 },
{ name: 'HTML & CSS Basics', category: 'Web Development', popularity: 92 },
{ name: 'Git & Version Control', category: 'Developer Tools', popularity: 88 },
{ name: 'Python Basics', category: 'Programming', popularity: 90 },
{ name: 'WordPress Basics', category: 'CMS', popularity: 85 },
{ name: 'Basic SQL', category: 'Databases', popularity: 87 },
{ name: 'Graphic Design Basics', category: 'Design', popularity: 94 },
{ name: 'UI / UX Design', category: 'Design', popularity: 96 },
{ name: 'Digital Marketing', category: 'Marketing', popularity: 83 },
{ name: 'Photoshop Basics', category: 'Design', popularity: 80 }
];
const categories = [
{ name: 'Programming', count: 25 },
{ name: 'Web Development', count: 18 },
{ name: 'Design', count: 15 },
{ name: 'Marketing', count: 12 },
{ name: 'Developer Tools', count: 10 }
];
const handleCourseSubmit = () => {
if (customCourse.trim()) {
const canonical = resolveCanonicalCourseTitle(customCourse.trim());
onCourseSelect(canonical);
}
};
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' && !loading) {
handleCourseSubmit();
}
};
const filteredCourses = selectedCategory
? recommendedCourses.filter(course => course.category === selectedCategory)
: recommendedCourses;
return (
<div className="bg-slate-50 min-h-full text-slate-900 font-sans transition-colors duration-200">
<div className="max-w-4xl mx-auto px-4 sm:px-6 py-6 sm:py-8 pb-16">
{/* Header */}
<div className="text-center mb-8">
<div className="flex justify-start mb-4">
<button
onClick={onBackToDashboard}
className="inline-flex items-center gap-2 text-xs font-semibold text-slate-600 hover:text-slate-900 transition-colors px-3 py-1.5 rounded-lg bg-white border border-slate-200 shadow-2xs cursor-pointer"
>
<ArrowLeft className="w-3.5 h-3.5" />
<span>Back to Dashboard</span>
</button>
</div>
<h1 className="text-2xl sm:text-4xl font-extrabold tracking-tight text-slate-900 mb-2">
Select Course or Enter Any Technical Domain
</h1>
<p className="text-xs sm:text-sm text-slate-500 max-w-2xl mx-auto leading-relaxed">
Enter any technical topic or skill to generate your syllabus, or choose from our curated courses below.
</p>
</div>
{/* Custom Course Input Scratchpad */}
<div className="bg-white rounded-2xl border border-slate-200/90 p-5 sm:p-7 mb-8 shadow-xs">
<div className="flex items-center space-x-2 mb-3">
<PenTool className="w-4 h-4 text-[#132F50]" />
<h2 className="text-sm font-bold text-slate-900">
Enter Any Technical Skill
</h2>
</div>
<div className="flex flex-col sm:flex-row gap-3">
<input
type="text"
value={customCourse}
onChange={(e) => setCustomCourse(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="e.g. React 19, Distributed Systems, Rust Systems, Machine Learning..."
className="flex-1 px-4 py-2.5 bg-slate-50 border border-slate-300 rounded-lg text-sm text-slate-900 focus:outline-none focus:border-[#132F50] focus:ring-2 focus:ring-[#132F50]/20 transition-all"
disabled={loading}
/>
<button
onClick={handleCourseSubmit}
disabled={!customCourse.trim() || loading}
className="px-5 py-2.5 bg-[#132F50] hover:bg-[#0e233d] text-white font-semibold text-xs tracking-wide rounded-lg shadow-xs flex items-center justify-center gap-2 disabled:opacity-50 transition-all cursor-pointer active:scale-[0.98]"
>
{loading ? (
<>
<span className="w-3.5 h-3.5 border-2 border-white border-t-transparent rounded-full animate-spin"></span>
<span>Preparing Curriculum...</span>
</>
) : (
<span>Start Curriculum</span>
)}
</button>
</div>
</div>
{/* Categories */}
<div className="mb-6">
<h3 className="text-xs font-semibold uppercase tracking-wider text-slate-700 mb-3">
Domain Categories
</h3>
<div className="flex flex-wrap gap-2">
<button
onClick={() => setSelectedCategory(null)}
className={`px-3.5 py-1.5 rounded-full text-xs font-semibold transition-all cursor-pointer ${
selectedCategory === null
? 'bg-[#132F50] text-white shadow-2xs'
: 'bg-white text-slate-700 border border-slate-200 hover:bg-slate-100'
}`}
>
All Categories
</button>
{categories.map((category) => (
<button
key={category.name}
onClick={() => setSelectedCategory(category.name)}
className={`px-3.5 py-1.5 rounded-full text-xs font-semibold transition-all flex items-center gap-1.5 cursor-pointer ${
selectedCategory === category.name
? 'bg-[#132F50] text-white shadow-2xs'
: 'bg-white text-slate-700 border border-slate-200 hover:bg-slate-100'
}`}
>
<span>{category.name}</span>
<span className="text-[10px] opacity-75">({category.count})</span>
</button>
))}
</div>
</div>
{/* Recommended Courses Grid */}
<div className="bg-white rounded-2xl border border-slate-200/90 p-6 shadow-xs mb-8">
<div className="flex items-center justify-between pb-3 mb-4 border-b border-slate-100">
<h3 className="text-base font-bold text-slate-900">
{selectedCategory ? `${selectedCategory} Syllabi` : 'Accredited Curricula'}
</h3>
<span className="text-xs text-blue-700 font-semibold flex items-center gap-1 bg-blue-50 px-2.5 py-0.5 rounded-full border border-blue-100">
<CheckCircle2 className="w-3.5 h-3.5 text-blue-600" />
<span>Transcript Grounded</span>
</span>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{filteredCourses.map((course, index) => {
const canonicalName = resolveCanonicalCourseTitle(course.name);
return (
<button
key={index}
onClick={() => onCourseSelect(canonicalName, course.category)}
disabled={loading}
className="p-4 text-left bg-slate-50/70 hover:bg-blue-50/40 rounded-xl border border-slate-200/80 hover:border-[#132F50]/40 transition-all flex flex-col justify-between h-[155px] group cursor-pointer"
>
<div className="flex items-start justify-between w-full">
<span className="text-[10px] font-semibold text-slate-600 uppercase tracking-wider px-2 py-0.5 rounded bg-white border border-slate-200">
{course.category}
</span>
<div className="text-[11px] font-semibold text-slate-500 flex items-center gap-1">
<TrendingUp className="w-3 h-3 text-emerald-600" />
<span>{course.popularity}% rating</span>
</div>
</div>
<h4 className="font-bold text-slate-900 tracking-tight text-sm line-clamp-2 mt-2">
{canonicalName}
</h4>
<div className="flex items-center justify-between w-full border-t border-slate-200/60 pt-2 text-xs font-semibold text-[#132F50] group-hover:text-blue-700">
<span>Enroll Syllabus</span>
<ArrowRight className="w-3.5 h-3.5 transition-transform group-hover:translate-x-1" />
</div>
</button>
);
})}
</div>
</div>
{/* Info Section */}
<div className="bg-white rounded-2xl border border-slate-200/90 p-6 shadow-xs">
<div className="flex items-center gap-2 mb-4">
<ClipboardList className="w-4 h-4 text-[#132F50]" />
<h3 className="text-xs font-bold text-slate-700 uppercase tracking-wider">
Certification Workflow
</h3>
</div>
<div className="divide-y divide-slate-100 sm:divide-y-0 sm:flex sm:items-start sm:justify-between sm:gap-6 text-xs">
<div className="flex items-start space-x-3 py-3 sm:py-0 flex-1">
<span className="w-6 h-6 rounded-full bg-blue-50 text-[#132F50] font-bold text-xs flex items-center justify-center shrink-0 border border-blue-200/60">1</span>
<div className="space-y-0.5">
<div className="font-bold text-slate-900 text-xs">Learning Modules</div>
<div className="text-slate-500 leading-relaxed font-normal">Review core concepts with concise takeaways and practical code examples.</div>
</div>
</div>
<div className="flex items-start space-x-3 py-3 sm:py-0 flex-1">
<span className="w-6 h-6 rounded-full bg-blue-50 text-[#132F50] font-bold text-xs flex items-center justify-center shrink-0 border border-blue-200/60">2</span>
<div className="space-y-0.5">
<div className="font-bold text-slate-900 text-xs">Assessment</div>
<div className="text-slate-500 leading-relaxed font-normal">Complete a comprehensive evaluation aligned directly with the curriculum.</div>
</div>
</div>
<div className="flex items-start space-x-3 py-3 sm:py-0 flex-1">
<span className="w-6 h-6 rounded-full bg-blue-50 text-[#132F50] font-bold text-xs flex items-center justify-center shrink-0 border border-blue-200/60">3</span>
<div className="space-y-0.5">
<div className="font-bold text-slate-900 text-xs">Official Certificate</div>
<div className="text-slate-500 leading-relaxed font-normal">Receive your verified certificate with instant QR validation and PDF download.</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}