Skip to content

Commit

Permalink
Redesign course listing page and progress bar design (code100x#1485)
Browse files Browse the repository at this point in the history
* redesign course listing page and progress bar design

* indented CourseCard.tsx

* Delete .vscode directory

* Update src/components/CourseCard.tsx

* Update src/components/CourseCard.tsx

---------

Co-authored-by: Sargam <[email protected]>
  • Loading branch information
Rahul-Bhati and devsargam authored Nov 17, 2024
1 parent 3207754 commit 4c734d8
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 42 deletions.
94 changes: 53 additions & 41 deletions src/components/CourseCard.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
'use client';
import { Course } from '@/store/atoms';
import PercentageComplete from './PercentageComplete';
import { useRouter } from 'next/navigation';
import Link from 'next/link';
import { Button } from './ui/button';
import { Card, CardContent } from "@/components/ui/card";
import { motion } from "framer-motion";
import { MessageCircle, PlayCircle } from "lucide-react";

export const CourseCard = ({
course,
Expand All @@ -14,54 +16,63 @@ export const CourseCard = ({
}) => {
const router = useRouter();
const imageUrl = course.imageUrl ? course.imageUrl : 'banner_placeholder.png';
const percentage = course.totalVideos !== undefined ? Math.ceil(((course.totalVideosWatched ?? 0) / course?.totalVideos) * 100) : 0;

return (
<div
className={`flex w-full cursor-pointer flex-col rounded-2xl bg-primary/5 transition-all duration-300 hover:-translate-y-2 hover:border-primary/20`}
onClick={onClick}
>
<div className="flex flex-col">
<Card className="w-full max-w-sm overflow-hidden transition-all hover:shadow-lg cursor-pointer" onClick={onClick}>
<div className="relative aspect-video overflow-hidden">
<img
alt={course.title}
className="size-full rounded-t-2xl bg-cover"
className="object-cover w-full h-full transition-transform hover:scale-105"
height="200"
src={imageUrl}
style={{
aspectRatio: "300/200",
objectFit: "cover",
filter: "brightness(1.2) contrast(1.1)",
}}
width="300"
/>

{course.totalVideos !== undefined && (
<>
<PercentageComplete
percent={Math.ceil(
((course.totalVideosWatched ?? 0) / course.totalVideos) * 100,
)}
/>
</>
)}
</div>
<div className="flex flex-1 flex-col justify-between gap-4 p-4">
<div className="flex w-full justify-between gap-2">
<h3 className="w-full truncate text-xl font-bold capitalize tracking-tighter md:text-2xl">
{course.title}
</h3>
{course.totalVideos !== undefined && (
<>
<span
className={`text-lg font-bold tracking-tight text-primary/80`}
>
{Math.ceil(
((course.totalVideosWatched ?? 0) / course.totalVideos) * 100,
)}
%
</span>
</>
)}
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent" />
<div className="absolute bottom-4 right-4 flex justify-between items-end">
<div className="bg-white rounded-full p-1 shadow-md">
<div className="relative w-12 h-12">
<svg className="w-12 h-12 transform -rotate-90" viewBox="0 0 100 100">
<circle className="stroke-current text-gray-300" strokeWidth="10" fill="gray" r="40" cx="50" cy="50" />
<motion.circle
className="stroke-current text-black"
strokeWidth="10"
strokeLinecap="round"
fill="white"
r="40"
cx="50"
cy="50"
initial={{ strokeDasharray: "0 251.2" }}
animate={{ strokeDasharray: `${percentage * 2.512} 251.2` }}
transition={{ duration: 1, ease: "easeInOut" }}
/>
</svg>
<div className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-center">
<span className="text-xs font-bold text-black dark:text-black flex justify-center">{percentage}%</span>
</div>
</div>
</div>

</div>
<div className="flex flex-col gap-2">
<Button size={'lg'} variant={'branding'} onClick={onClick}>
</div>
<CardContent className="p-4">
<h3 className="text-lg font-semibold text-primary mb-2 line-clamp-2">
{course.title}
</h3>
<div className="flex space-x-2">
<Button className="flex-1" variant="default" onClick={onClick}>
<PlayCircle className="w-4 h-4 mr-2" />
View Course
</Button>

{course.certIssued ? (
<Button
variant="link"
variant="outline"
size={'lg'}
onClick={(e) => {
e.stopPropagation();
Expand All @@ -72,16 +83,17 @@ export const CourseCard = ({
</Button>
) : (
<Link
className="inline-flex items-center justify-center rounded-md py-2 text-sm font-medium text-primary underline-offset-4 ring-offset-background transition-colors hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
className="flex-1 inline-flex items-center justify-center rounded-md py-2 text-sm font-medium text-primary underline-offset-4 ring-offset-background transition-colors hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
href={course.discordOauthUrl}
target={'blank'}
>
<MessageCircle className="w-4 h-4 mr-2" />
Join Discord
</Link>
)}
</div>
</div>
</div>
</CardContent>
</Card>
);
};

Expand Down
2 changes: 1 addition & 1 deletion src/components/Courses.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const Courses = ({ courses }: { courses: Course[] }) => {
/>
))}
<div
className={`flex w-full cursor-pointer flex-col items-center rounded-2xl bg-primary/5 p-16 transition-all duration-300 hover:-translate-y-2 hover:border-primary/20`}
className={`flex w-full max-w-sm cursor-pointer flex-col items-center rounded-2xl bg-primary/5 p-16 transition-all duration-300 hover:-translate-y-2 hover:border-primary/20`}
>
<div className="flex h-full flex-col items-center justify-center gap-4 text-center">
<div className="flex flex-col items-center text-center">
Expand Down

0 comments on commit 4c734d8

Please sign in to comment.