Skip to content

Commit 5fdf527

Browse files
Merge branch 'main' into feature/admin-dashboard-layout
2 parents 3f2d0d2 + f529ce1 commit 5fdf527

File tree

8 files changed

+439
-17
lines changed

8 files changed

+439
-17
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
"dependencies": {
1515
"@libsql/client": "^0.15.15",
1616
"@radix-ui/react-navigation-menu": "^1.2.14",
17+
"@radix-ui/react-progress": "^1.1.7",
18+
"@radix-ui/react-slot": "^1.2.3",
1719
"better-auth": "^1.3.26",
1820
"class-variance-authority": "^0.7.1",
1921
"clsx": "^2.1.1",

pnpm-lock.yaml

Lines changed: 13 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/home/page.tsx

Lines changed: 99 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,99 @@
1-
export default function Page() {
2-
return <div>This is the home page</div>;
3-
}
1+
import { CourseCard } from "@/components/course-card";
2+
3+
// sample data - replace with real data later
4+
const inProgressCourses = [
5+
{ id: 1, title: "Introduction to Python", progress: 45, units: 10, rating: 4, tags: ["Programming", "Python"] },
6+
{ id: 2, title: "Web Development Basics", progress: 70, units: 8, rating: 5, tags: ["HTML", "CSS", "JavaScript"] },
7+
{ id: 3, title: "Data Structures", progress: 20, units: 15, rating: 3, tags: ["Data Structures", "Algorithms"] },
8+
];
9+
10+
const favoriteCourses = [
11+
{ id: 4, title: "Advanced JavaScript", units: 12, rating: 5, tags: ["JavaScript", "Frontend"] },
12+
{ id: 5, title: "React Fundamentals", units: 8, rating: 4, tags: ["React", "Web Dev"] },
13+
];
14+
15+
const popularCourses = [
16+
{ id: 6, title: "Machine Learning 101", units: 20, rating: 5, tags: ["AI", "ML"] },
17+
{ id: 7, title: "Database Design", units: 10, rating: 4, tags: ["SQL", "Database"] },
18+
{ id: 8, title: "Algorithm Analysis", units: 12, rating: 5, tags: ["Algorithms", "Optimization"] },
19+
];
20+
21+
const completedCourses = [
22+
{ id: 9, title: "Git & GitHub Essentials", units: 6, rating: 5, tags: ["Version Control", "GitHub"] },
23+
];
24+
25+
export default function HomePage() {
26+
return (
27+
<div className="container mx-auto p-6 max-w-7xl">
28+
29+
{/* In Progress Section */}
30+
<section className="mb-12">
31+
<h2 className="text-2xl font-semibold mb-4">In progress</h2>
32+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
33+
{inProgressCourses.map((course) => (
34+
<CourseCard
35+
key={course.id}
36+
title={course.title}
37+
type="in-progress"
38+
progress={course.progress}
39+
units={course.units}
40+
rating={course.rating}
41+
tags={course.tags}
42+
/>
43+
))}
44+
</div>
45+
</section>
46+
47+
{/* Favorites Section */}
48+
<section className="mb-12">
49+
<h2 className="text-2xl font-semibold mb-4">Favorites</h2>
50+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
51+
{favoriteCourses.map((course) => (
52+
<CourseCard
53+
key={course.id}
54+
title={course.title}
55+
type="favorite"
56+
units={course.units}
57+
rating={course.rating}
58+
tags={course.tags}
59+
/>
60+
))}
61+
</div>
62+
</section>
63+
64+
{/* Popular Section */}
65+
<section className="mb-12">
66+
<h2 className="text-2xl font-semibold mb-4">Popular</h2>
67+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
68+
{popularCourses.map((course) => (
69+
<CourseCard
70+
key={course.id}
71+
title={course.title}
72+
type="popular"
73+
units={course.units}
74+
rating={course.rating}
75+
tags={course.tags}
76+
/>
77+
))}
78+
</div>
79+
</section>
80+
81+
{/* Completed Section */}
82+
<section className="mb-12">
83+
<h2 className="text-2xl font-semibold mb-4">Completed</h2>
84+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
85+
{completedCourses.map((course) => (
86+
<CourseCard
87+
key={course.id}
88+
title={course.title}
89+
type="completed"
90+
units={course.units}
91+
rating={course.rating}
92+
tags={course.tags}
93+
/>
94+
))}
95+
</div>
96+
</section>
97+
</div>
98+
);
99+
}

src/app/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Metadata } from "next";
22
import { Geist, Geist_Mono } from "next/font/google";
33
import "./globals.css";
4+
import Footer from "@/components/footer";
45

56
const geistSans = Geist({
67
variable: "--font-geist-sans",
@@ -28,6 +29,7 @@ export default function RootLayout({
2829
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
2930
>
3031
{children}
32+
<Footer />
3133
</body>
3234
</html>
3335
);

src/components/course-card.tsx

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
2+
import { Badge } from "@/components/ui/badge";
3+
4+
interface CourseCardProps {
5+
title: string;
6+
type: "in-progress" | "favorite" | "popular" | "completed";
7+
progress?: number;
8+
units?: number;
9+
rating?: number;
10+
tags?: string[];
11+
}
12+
13+
export function CourseCard({ title, type, progress, units, rating, tags = [] }: CourseCardProps) {
14+
return (
15+
<Card className="relative hover:shadow-lg transition-shadow cursor-pointer p-6">
16+
{/* Title and rating row */}
17+
<CardHeader className="p-0 mb-4">
18+
<div className="flex items-center justify-between">
19+
<CardTitle className="text-lg font-semibold">{title}</CardTitle>
20+
21+
{rating !== undefined && (
22+
<div className="flex items-center gap-0.5">
23+
{[...Array(5)].map((_, i) => (
24+
<span key={i} className={i < rating ? "text-yellow-500" : "text-gray-300"}>
25+
26+
</span>
27+
))}
28+
</div>
29+
)}
30+
</div>
31+
</CardHeader>
32+
33+
{/* Bottom info row */}
34+
<CardContent className="p-0">
35+
<div className="flex justify-between items-center mt-4">
36+
{/* Units on bottom left */}
37+
{units !== undefined && (
38+
<Badge variant="secondary">{units} units</Badge>
39+
)}
40+
41+
{/* Tags on bottom right */}
42+
<div className="flex flex-wrap justify-end gap-2">
43+
{tags.map((tag, i) => (
44+
<Badge key={i} variant="outline" className="text-xs">
45+
{tag}
46+
</Badge>
47+
))}
48+
49+
{type === "popular" && (
50+
<Badge>Popular</Badge>
51+
)}
52+
53+
{type === "completed" && (
54+
<Badge variant="outline" className="bg-green-50">
55+
✓ Completed
56+
</Badge>
57+
)}
58+
</div>
59+
</div>
60+
</CardContent>
61+
</Card>
62+
);
63+
}

src/components/footer.tsx

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import React from "react";
2+
import Link from "next/link";
3+
4+
export default function Footer() {
5+
const year = new Date().getFullYear();
6+
7+
return (
8+
<footer className="border-t bg-neutral-50 text-neutral-700 dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-300">
9+
<div className="mx-auto w-full max-w-7xl px-4 py-12 sm:px-6 lg:px-8">
10+
<div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-4">
11+
{/* About Section */}
12+
<nav className="space-y-4">
13+
<h3 className="text-xs font-semibold uppercase tracking-wider text-neutral-500 dark:text-neutral-400">About</h3>
14+
<ul className="space-y-2 text-sm">
15+
<li>
16+
<Link href="/home" className="hover:text-neutral-900 dark:hover:text-white">About Us</Link>
17+
</li>
18+
</ul>
19+
</nav>
20+
21+
{/* Events & Activities Section */}
22+
<nav className="space-y-4">
23+
<h3 className="text-xs font-semibold uppercase tracking-wider text-neutral-500 dark:text-neutral-400">Events & Activities</h3>
24+
<ul className="space-y-2 text-sm">
25+
<li>
26+
<Link href="https://portal.acmutsa.org/events" target="_blank" className="hover:text-neutral-900 dark:hover:text-white">Upcoming Events</Link>
27+
</li>
28+
</ul>
29+
</nav>
30+
31+
{/* Get Involved Section */}
32+
<nav className="space-y-4">
33+
<h3 className="text-xs font-semibold uppercase tracking-wider text-neutral-500 dark:text-neutral-400">Get Involved</h3>
34+
<ul className="space-y-2 text-sm">
35+
<li>
36+
<Link href="https://portal.acmutsa.org/" target="_blank" className="hover:text-neutral-900 dark:hover:text-white">Join ACM</Link>
37+
</li>
38+
</ul>
39+
</nav>
40+
41+
{/* Resources Section */}
42+
<nav className="space-y-4">
43+
<h3 className="text-xs font-semibold uppercase tracking-wider text-neutral-500 dark:text-neutral-400">Resources</h3>
44+
<ul className="space-y-2 text-sm">
45+
<li>
46+
<Link href="/home" className="hover:text-neutral-900 dark:hover:text-white">Terms of Service</Link>
47+
</li>
48+
</ul>
49+
</nav>
50+
</div>
51+
52+
{/* Divider */}
53+
<div className="mt-10 border-t border-neutral-200 dark:border-neutral-800"></div>
54+
55+
{/* Bottom Bar */}
56+
<div className="mt-6 flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
57+
<p className="text-sm text-neutral-600 dark:text-neutral-400">
58+
© {year} The University of Texas at San Antonio · Made by <span className="font-medium text-neutral-800 dark:text-neutral-200">ACM</span>
59+
{" "}x{" "}
60+
<span className="font-medium text-neutral-800 dark:text-neutral-200">Senior Design</span> Fall 2025
61+
</p>
62+
63+
{/* Social Links and Repo */}
64+
<div className="flex flex-wrap items-center gap-4 text-sm">
65+
<a
66+
href="https://github.com/acmutsa/cs-learn"
67+
target="_blank"
68+
rel="noopener noreferrer"
69+
className="inline-flex items-center gap-2 hover:text-neutral-900 dark:hover:text-white"
70+
>
71+
{/* svg for github logo */}
72+
<svg
73+
xmlns="http://www.w3.org/2000/svg"
74+
viewBox="0 0 24 24"
75+
fill="currentColor"
76+
className="h-4 w-4 opacity-80"
77+
aria-hidden="true"
78+
>
79+
<path
80+
fillRule="evenodd"
81+
d="M12 .5a11.5 11.5 0 0 0-3.637 22.41c.575.105.785-.25.785-.555 0-.274-.01-.999-.015-1.963-3.19.694-3.866-1.539-3.866-1.539-.523-1.327-1.277-1.681-1.277-1.681-1.043-.713.08-.699.08-.699 1.153.081 1.76 1.184 1.76 1.184 1.025 1.757 2.69 1.25 3.343.956.104-.742.4-1.25.727-1.538-2.548-.289-5.226-1.274-5.226-5.666 0-1.252.447-2.276 1.182-3.078-.119-.29-.512-1.454.112-3.03 0 0 .965-.309 3.164 1.176a10.96 10.96 0 0 1 2.881-.387c.978.004 1.964.132 2.882.387 2.198-1.485 3.162-1.176 3.162-1.176.625 1.576.232 2.74.114 3.03.737.802 1.18 1.826 1.18 3.078 0 4.402-2.683 5.374-5.24 5.66.41.353.775 1.05.775 2.116 0 1.527-.014 2.76-.014 3.134 0 .308.208.666.79.553A11.501 11.501 0 0 0 12 .5Z"
82+
clipRule="evenodd"
83+
/>
84+
</svg>
85+
<span>Repo</span>
86+
</a>
87+
88+
<a
89+
href="https://discord.com/invite/NvjUxmR"
90+
target="_blank"
91+
rel="noopener noreferrer"
92+
className="hover:text-neutral-900 dark:hover:text-white"
93+
>
94+
Discord
95+
</a>
96+
<a
97+
href="https://www.linkedin.com/company/acmutsa/"
98+
target="_blank"
99+
rel="noopener noreferrer"
100+
className="hover:text-neutral-900 dark:hover:text-white"
101+
>
102+
LinkedIn
103+
</a>
104+
<a
105+
href="https://www.instagram.com/acmutsa/"
106+
target="_blank"
107+
rel="noopener noreferrer"
108+
className="hover:text-neutral-900 dark:hover:text-white">
109+
Instagram
110+
</a>
111+
<a
112+
href="mailto:team@acmutsa.org"
113+
className="hover:text-neutral-900 dark:hover:text-white"
114+
>
115+
Email
116+
</a>
117+
</div>
118+
</div>
119+
</div>
120+
</footer>
121+
);
122+
}

0 commit comments

Comments
 (0)