mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-10-01 19:36:43 +02:00
* Course landing page * Add ai course page * wip * wip * wip * wip * wip * wip * wip * wip: error handling * wip * wip * wip * wip: ai course progress * wip * wip * wip * feat: code highlighting * feat: usage limit * feat: follow up message * Update UI * wip * Add course content * wip: autogrow textarea & examples * Update types * Update * fix: add highlight to the AI chat * UI changes * Refactor * Update * Improve outline style * Improve spacing * Improve spacing * UI changes for sidebar * Update UI for sidebar * Improve course UI * Mark done, undone * Add toggle lesson done/undone * Update forward backward UI * wip * Minor ui change * Responsiveness of sidebar * wip * wip * wip: billing page * wip * Update UI * fix: hide upgrade if paid user * feat: token usage * feat: list ai courses * fix: limit for followup * Course content responsiveness * Make course content responsive * Responsiveness * Outline button * Responsiveness of course content * Responsiveness of course content * Add course upgrade button * Update design for upgrade * Improve logic for upgrade and limits button * Limits and errors * Add lesson count * Add course card * Improve UI for course generator * Update course functionality * Refactor AI course generation * Responsiveness of screen * Improve * Add responsiveness * Improve empty billing page design * Add empty billing screen * Update UI for billing page * Update UI for billing page * Update UI for billing page * Update billing page design * Update * Remove sidebar * Update --------- Co-authored-by: Arik Chakma <arikchangma@gmail.com>
74 lines
2.3 KiB
TypeScript
74 lines
2.3 KiB
TypeScript
import type { AICourseListItem } from '../../queries/ai-course';
|
|
import type { DifficultyLevel } from './AICourse';
|
|
import { BookOpen } from 'lucide-react';
|
|
|
|
type AICourseCardProps = {
|
|
course: AICourseListItem;
|
|
};
|
|
|
|
export function AICourseCard(props: AICourseCardProps) {
|
|
const { course } = props;
|
|
|
|
// Format date if available
|
|
const formattedDate = course.createdAt
|
|
? new Date(course.createdAt).toLocaleDateString('en-US', {
|
|
month: 'short',
|
|
day: 'numeric',
|
|
})
|
|
: null;
|
|
|
|
// Map difficulty to color
|
|
const difficultyColor =
|
|
{
|
|
beginner: 'text-green-700',
|
|
intermediate: 'text-blue-700',
|
|
advanced: 'text-purple-700',
|
|
}[course.difficulty as DifficultyLevel] || 'text-gray-700';
|
|
|
|
// Calculate progress percentage
|
|
const totalTopics = course.lessonCount || 0;
|
|
const completedTopics = course.progress?.done?.length || 0;
|
|
const progressPercentage =
|
|
totalTopics > 0 ? Math.round((completedTopics / totalTopics) * 100) : 0;
|
|
|
|
return (
|
|
<a
|
|
href={`/ai-tutor/${course.slug}`}
|
|
className="hover:border-gray-3 00 group relative flex w-full flex-col overflow-hidden rounded-lg border border-gray-200 bg-white p-4 text-left transition-all hover:bg-gray-50"
|
|
>
|
|
<div className="flex items-center justify-between">
|
|
<span
|
|
className={`rounded-full text-xs font-medium capitalize opacity-80 ${difficultyColor}`}
|
|
>
|
|
{course.difficulty}
|
|
</span>
|
|
</div>
|
|
|
|
<h3 className="my-2 text-base font-semibold text-gray-900">
|
|
{course.title}
|
|
</h3>
|
|
|
|
<div className="mt-auto flex items-center justify-between pt-2">
|
|
<div className="flex items-center text-xs text-gray-600">
|
|
<BookOpen className="mr-1 h-3.5 w-3.5" />
|
|
<span>{totalTopics} lessons</span>
|
|
</div>
|
|
|
|
{totalTopics > 0 && (
|
|
<div className="flex items-center">
|
|
<div className="mr-2 h-1.5 w-16 overflow-hidden rounded-full bg-gray-200">
|
|
<div
|
|
className="h-full rounded-full bg-blue-600"
|
|
style={{ width: `${progressPercentage}%` }}
|
|
/>
|
|
</div>
|
|
<span className="text-xs font-medium text-gray-700">
|
|
{progressPercentage}%
|
|
</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</a>
|
|
);
|
|
}
|