Skip to content

Commit e2be796

Browse files
Add AI Engineering, Data Engineering, and Software Engineering course pages with modules, prerequisites, and session handling
1 parent 85ae74c commit e2be796

File tree

6 files changed

+1985
-404
lines changed

6 files changed

+1985
-404
lines changed
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
import React from "react";
2+
3+
interface User {
4+
id: number;
5+
name: string;
6+
email: string;
7+
status: string;
8+
enrolled: string;
9+
progress: number;
10+
}
11+
12+
interface VerticalStats {
13+
name: string;
14+
enrolled: number;
15+
avgProgress: number;
16+
}
17+
18+
// Simple progress bar component with proper TypeScript
19+
const ProgressBar = ({ progress }: { progress: number }) => {
20+
const getWidthClass = (value: number) => {
21+
const rounded = Math.round(value / 5) * 5; // Round to nearest 5
22+
return `tw-w-[${Math.min(rounded, 100)}%]`;
23+
};
24+
25+
return (
26+
<div className="tw-h-2 tw-w-full tw-rounded-full tw-bg-gray-200">
27+
<div className={`tw-h-2 tw-rounded-full tw-bg-primary ${getWidthClass(progress)}`} />
28+
</div>
29+
);
30+
};
31+
32+
export const OverviewStats = () => {
33+
const stats = [
34+
{ label: "Total Enrolled", value: "1,234", change: "+12%" },
35+
{ label: "Active Learners", value: "892", change: "+8%" },
36+
{ label: "Completed Courses", value: "456", change: "+15%" },
37+
{ label: "Success Rate", value: "87%", change: "+3%" },
38+
];
39+
40+
return (
41+
<div className="tw-mb-8 tw-grid tw-grid-cols-1 tw-gap-6 md:tw-grid-cols-2 lg:tw-grid-cols-4">
42+
{stats.map((stat) => (
43+
<div key={stat.label} className="tw-rounded-lg tw-bg-white tw-p-6 tw-shadow-md">
44+
<h3 className="tw-text-lg tw-font-semibold tw-text-gray-800">{stat.label}</h3>
45+
<p className="tw-mt-2 tw-text-3xl tw-font-bold tw-text-primary">{stat.value}</p>
46+
<p className="tw-mt-2 tw-text-sm tw-text-green-600">
47+
{stat.change} from last month
48+
</p>
49+
</div>
50+
))}
51+
</div>
52+
);
53+
};
54+
55+
export const VerticalProgress = () => {
56+
const verticals: VerticalStats[] = [
57+
{ name: "Software Engineering", enrolled: 456, avgProgress: 65 },
58+
{ name: "Data Engineering", enrolled: 234, avgProgress: 52 },
59+
{ name: "AI Engineering", enrolled: 189, avgProgress: 48 },
60+
];
61+
62+
return (
63+
<div className="tw-mb-8 tw-rounded-lg tw-bg-white tw-p-6 tw-shadow-md">
64+
<h3 className="tw-mb-4 tw-text-xl tw-font-semibold tw-text-gray-800">
65+
Course Verticals Progress
66+
</h3>
67+
<div className="tw-space-y-4">
68+
{verticals.map((vertical) => (
69+
<div
70+
key={vertical.name}
71+
className="tw-border-b tw-border-gray-200 tw-pb-4 last:tw-border-b-0"
72+
>
73+
<div className="tw-mb-2 tw-flex tw-items-center tw-justify-between">
74+
<span className="tw-font-medium tw-text-gray-800">{vertical.name}</span>
75+
<span className="tw-text-sm tw-text-gray-600">
76+
{vertical.enrolled} enrolled · {vertical.avgProgress}% avg progress
77+
</span>
78+
</div>
79+
<ProgressBar progress={vertical.avgProgress} />
80+
</div>
81+
))}
82+
</div>
83+
</div>
84+
);
85+
};
86+
87+
export const AnalyticsCharts = () => {
88+
return (
89+
<div className="tw-mb-8 tw-grid tw-grid-cols-1 tw-gap-6 lg:tw-grid-cols-2">
90+
<div className="tw-rounded-lg tw-bg-white tw-p-6 tw-shadow-md">
91+
<h3 className="tw-mb-4 tw-text-xl tw-font-semibold tw-text-gray-800">
92+
Enrollment Trends
93+
</h3>
94+
<div className="tw-flex tw-h-64 tw-items-center tw-justify-center tw-rounded tw-bg-gray-50">
95+
<p className="tw-text-gray-500">
96+
Chart placeholder - Integration with chart library needed
97+
</p>
98+
</div>
99+
</div>
100+
<div className="tw-rounded-lg tw-bg-white tw-p-6 tw-shadow-md">
101+
<h3 className="tw-mb-4 tw-text-xl tw-font-semibold tw-text-gray-800">
102+
Completion Rates
103+
</h3>
104+
<div className="tw-flex tw-h-64 tw-items-center tw-justify-center tw-rounded tw-bg-gray-50">
105+
<p className="tw-text-gray-500">
106+
Chart placeholder - Integration with chart library needed
107+
</p>
108+
</div>
109+
</div>
110+
</div>
111+
);
112+
};
113+
114+
export const TabNavigation = ({
115+
activeTab,
116+
setActiveTab,
117+
}: {
118+
activeTab: string;
119+
setActiveTab: (tab: string) => void;
120+
}) => {
121+
const tabs = [
122+
{ id: "overview", label: "Overview" },
123+
{ id: "users", label: "User Management" },
124+
{ id: "courses", label: "Course Management" },
125+
{ id: "analytics", label: "Analytics" },
126+
{ id: "reports", label: "Reports" },
127+
];
128+
129+
return (
130+
<div className="tw-mb-8 tw-border-b tw-border-gray-200">
131+
<nav className="tw-flex tw-space-x-8">
132+
{tabs.map((tab) => (
133+
<button
134+
key={tab.id}
135+
type="button"
136+
onClick={() => setActiveTab(tab.id)}
137+
className={`tw-border-b-2 tw-px-1 tw-py-2 tw-text-sm tw-font-medium ${
138+
activeTab === tab.id
139+
? "tw-border-primary tw-text-primary"
140+
: "tw-border-transparent tw-text-gray-500 hover:tw-border-gray-300 hover:tw-text-gray-700"
141+
}`}
142+
>
143+
{tab.label}
144+
</button>
145+
))}
146+
</nav>
147+
</div>
148+
);
149+
};
150+
151+
export const UserProgress = ({ progress }: { progress: number }) => {
152+
const getProgressWidth = (value: number) => {
153+
const rounded = Math.round(value / 10) * 10;
154+
const widthMap: Record<number, string> = {
155+
0: "tw-w-0",
156+
10: "tw-w-[10%]",
157+
20: "tw-w-[20%]",
158+
30: "tw-w-[30%]",
159+
40: "tw-w-[40%]",
160+
50: "tw-w-1/2",
161+
60: "tw-w-[60%]",
162+
70: "tw-w-[70%]",
163+
80: "tw-w-[80%]",
164+
90: "tw-w-[90%]",
165+
100: "tw-w-full",
166+
};
167+
return widthMap[Math.min(rounded, 100)] || "tw-w-0";
168+
};
169+
170+
return (
171+
<div className="tw-w-full tw-rounded-full tw-bg-gray-200">
172+
<div className={`tw-h-2 tw-rounded-full tw-bg-primary ${getProgressWidth(progress)}`} />
173+
<span className="tw-mt-1 tw-block tw-text-xs tw-text-gray-600">{progress}%</span>
174+
</div>
175+
);
176+
};
177+
178+
export const UserManagement = () => {
179+
const users: User[] = [
180+
{
181+
id: 1,
182+
name: "John Doe",
183+
184+
status: "Active",
185+
enrolled: "Software Engineering",
186+
progress: 75,
187+
},
188+
{
189+
id: 2,
190+
name: "Jane Smith",
191+
192+
status: "Active",
193+
enrolled: "Data Engineering",
194+
progress: 60,
195+
},
196+
{
197+
id: 3,
198+
name: "Mike Johnson",
199+
200+
status: "Inactive",
201+
enrolled: "AI Engineering",
202+
progress: 30,
203+
},
204+
];
205+
206+
return (
207+
<div className="tw-rounded-lg tw-bg-white tw-p-6 tw-shadow-md">
208+
<div className="tw-mb-6 tw-flex tw-items-center tw-justify-between">
209+
<h3 className="tw-text-xl tw-font-semibold tw-text-gray-800">User Management</h3>
210+
<button
211+
type="button"
212+
className="tw-rounded-md tw-bg-primary tw-px-4 tw-py-2 tw-text-white hover:tw-bg-primary/90"
213+
>
214+
Add User
215+
</button>
216+
</div>
217+
218+
<div className="tw-overflow-x-auto">
219+
<table className="tw-min-w-full tw-divide-y tw-divide-gray-200">
220+
<thead className="tw-bg-gray-50">
221+
<tr>
222+
<th className="tw-px-6 tw-py-3 tw-text-left tw-text-xs tw-font-medium tw-uppercase tw-tracking-wider tw-text-gray-500">
223+
User
224+
</th>
225+
<th className="tw-px-6 tw-py-3 tw-text-left tw-text-xs tw-font-medium tw-uppercase tw-tracking-wider tw-text-gray-500">
226+
Status
227+
</th>
228+
<th className="tw-px-6 tw-py-3 tw-text-left tw-text-xs tw-font-medium tw-uppercase tw-tracking-wider tw-text-gray-500">
229+
Enrolled In
230+
</th>
231+
<th className="tw-px-6 tw-py-3 tw-text-left tw-text-xs tw-font-medium tw-uppercase tw-tracking-wider tw-text-gray-500">
232+
Progress
233+
</th>
234+
<th className="tw-px-6 tw-py-3 tw-text-left tw-text-xs tw-font-medium tw-uppercase tw-tracking-wider tw-text-gray-500">
235+
Actions
236+
</th>
237+
</tr>
238+
</thead>
239+
<tbody className="tw-divide-y tw-divide-gray-200 tw-bg-white">
240+
{users.map((user) => (
241+
<tr key={user.id}>
242+
<td className="tw-whitespace-nowrap tw-px-6 tw-py-4">
243+
<div>
244+
<div className="tw-text-sm tw-font-medium tw-text-gray-900">
245+
{user.name}
246+
</div>
247+
<div className="tw-text-sm tw-text-gray-500">
248+
{user.email}
249+
</div>
250+
</div>
251+
</td>
252+
<td className="tw-whitespace-nowrap tw-px-6 tw-py-4">
253+
<span
254+
className={`tw-inline-flex tw-rounded-full tw-px-2 tw-text-xs tw-font-semibold ${
255+
user.status === "Active"
256+
? "tw-bg-green-100 tw-text-green-800"
257+
: "tw-bg-red-100 tw-text-red-800"
258+
}`}
259+
>
260+
{user.status}
261+
</span>
262+
</td>
263+
<td className="tw-whitespace-nowrap tw-px-6 tw-py-4 tw-text-sm tw-text-gray-900">
264+
{user.enrolled}
265+
</td>
266+
<td className="tw-whitespace-nowrap tw-px-6 tw-py-4">
267+
<UserProgress progress={user.progress} />
268+
</td>
269+
<td className="tw-whitespace-nowrap tw-px-6 tw-py-4 tw-text-sm tw-font-medium">
270+
<button
271+
type="button"
272+
className="tw-mr-4 tw-text-primary hover:tw-text-primary/80"
273+
>
274+
Edit
275+
</button>
276+
<button
277+
type="button"
278+
className="tw-text-red-600 hover:tw-text-red-900"
279+
>
280+
Remove
281+
</button>
282+
</td>
283+
</tr>
284+
))}
285+
</tbody>
286+
</table>
287+
</div>
288+
</div>
289+
);
290+
};

0 commit comments

Comments
 (0)