Skip to content

Commit ba6c475

Browse files
Added timetable pages and it's related components + a loading page
Introduces new timetable and timetable-test pages, including TimetableCell and WaitingPage React components, and a useTimetable hook for fetching and generating timetable data. Updates dashboard styling, adjusts dark mode background color, and adds routes for the new pages. Removes the unused database.sqlite file.
1 parent ed1a9f3 commit ba6c475

10 files changed

Lines changed: 821 additions & 20 deletions

File tree

database.sqlite

-144 KB
Binary file not shown.

package-lock.json

Lines changed: 1 addition & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/css/app.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
}
9999

100100
.dark {
101-
--background: oklch(0.145 0 0);
101+
--background: oklch(1 0 0);
102102
--foreground: oklch(0.985 0 0);
103103
--card: oklch(0.145 0 0);
104104
--card-foreground: oklch(0.985 0 0);
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import React from 'react';
2+
3+
interface CourseSlot {
4+
courseId: string;
5+
type: string;
6+
roomId: string;
7+
instructorId: string | null;
8+
}
9+
10+
interface TimetableCellProps {
11+
courses: CourseSlot[];
12+
}
13+
14+
const TimetableCell: React.FC<TimetableCellProps> = ({ courses }) => {
15+
// Simple solid color styles based on session type
16+
const getTypeStyles = (type: string) => {
17+
switch (type) {
18+
case 'Lecture':
19+
return 'bg-blue-100 border-blue-300 text-blue-800 hover:bg-blue-200';
20+
case 'Lab':
21+
return 'bg-green-100 border-green-300 text-green-800 hover:bg-green-200';
22+
case 'Tutorial':
23+
return 'bg-purple-100 border-purple-300 text-purple-800 hover:bg-purple-200';
24+
default:
25+
return 'bg-gray-100 border-gray-300 text-gray-800 hover:bg-gray-200';
26+
}
27+
};
28+
29+
// Remove gradients for empty cells and keep a simple look
30+
if (courses.length === 0) {
31+
return (
32+
<div className="h-full min-h-[60px] bg-gray-50 rounded-lg border border-dashed border-gray-300 flex items-center justify-center">
33+
<span className="text-gray-400 text-xs font-medium">Available</span>
34+
</div>
35+
);
36+
}
37+
38+
return (
39+
<div className="grid gap-2">
40+
{courses.map((course, idx) => (
41+
<div
42+
key={`${course.courseId}-${course.type}-${idx}`}
43+
className={`relative p-3 rounded-lg border ${getTypeStyles(course.type)} text-xs shadow-none transition-colors`}
44+
>
45+
<div className="font-bold text-sm mb-1">{course.courseId}</div>
46+
<div className="font-semibold text-xs mb-2 opacity-90">{course.type}</div>
47+
48+
<div className="space-y-1">
49+
<div className="text-xs opacity-75 flex items-center">
50+
<svg className="w-3 h-3 mr-1.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
51+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
52+
</svg>
53+
<span className="truncate">{course.roomId}</span>
54+
</div>
55+
{course.instructorId && (
56+
<div className="text-xs opacity-75 flex items-center">
57+
<svg className="w-3 h-3 mr-1.5 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
58+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
59+
</svg>
60+
<span className="truncate">{course.instructorId}</span>
61+
</div>
62+
)}
63+
</div>
64+
</div>
65+
))}
66+
</div>
67+
);
68+
};
69+
70+
export default TimetableCell;
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import React from "react";
2+
3+
interface WaitingPageProps {
4+
title?: string;
5+
description?: string;
6+
}
7+
8+
export const WaitingPage: React.FC<WaitingPageProps> = ({
9+
title = "Preparing your timetable",
10+
description = "Computing timetable data. This may take a moment...",
11+
}) => {
12+
return (
13+
<div className="flex min-h-screen w-full items-center justify-center bg-white px-4">
14+
<div className="w-full max-w-md rounded-xl border border-gray-200 bg-white p-6">
15+
{/* Spinner */}
16+
<div className="flex justify-center mb-4">
17+
<svg
18+
className="animate-spin h-8 w-8 text-blue-600"
19+
xmlns="http://www.w3.org/2000/svg"
20+
fill="none"
21+
viewBox="0 0 24 24"
22+
>
23+
<circle
24+
className="opacity-25"
25+
cx="12"
26+
cy="12"
27+
r="10"
28+
stroke="currentColor"
29+
strokeWidth="4"
30+
></circle>
31+
<path
32+
className="opacity-75"
33+
fill="currentColor"
34+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"
35+
></path>
36+
</svg>
37+
</div>
38+
39+
{/* Title */}
40+
<h2 className="text-center text-xl font-semibold text-gray-900">
41+
{title}
42+
</h2>
43+
44+
{/* Description */}
45+
<p className="mt-2 text-center text-sm text-gray-600">{description}</p>
46+
47+
{/* Progress bar */}
48+
<div className="mt-6">
49+
<div className="h-2 w-full rounded-full bg-gray-200">
50+
<div className="h-2 w-1/2 rounded-full bg-blue-600" />
51+
</div>
52+
<p className="mt-2 text-center text-xs text-gray-500">This won't take long.</p>
53+
</div>
54+
</div>
55+
</div>
56+
);
57+
};
58+
59+
export default WaitingPage;

0 commit comments

Comments
 (0)