Skip to content

Commit 8c79d62

Browse files
Merge pull request #92 from RUBA-Labs/Uditha_Wijethunga_Dev
time table admin update
2 parents 2b8c26f + 4da1a7c commit 8c79d62

6 files changed

Lines changed: 376 additions & 24 deletions

File tree

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
"use client";
2+
import { useState } from "react";
3+
import { Button } from "@/components/ui/button";
4+
import {
5+
Card,
6+
CardContent,
7+
CardHeader,
8+
CardTitle,
9+
} from "@/components/ui/card";
10+
import { ChevronLeft, ChevronRight } from "lucide-react";
11+
12+
import {
13+
Table,
14+
TableBody,
15+
TableCell,
16+
TableHead,
17+
TableHeader,
18+
TableRow,
19+
} from "@/components/ui/table";
20+
21+
import { Input } from "@/components/ui/input";
22+
23+
const Timetable = () => {
24+
const [currentDate, setCurrentDate] = useState(new Date());
25+
const [selectedStartTime, setSelectedStartTime] = useState<string>("");
26+
27+
const handlePrevDay = () => {
28+
setCurrentDate((prevDate) => {
29+
const newDate = new Date(prevDate);
30+
newDate.setDate(newDate.getDate() - 1);
31+
return newDate;
32+
});
33+
};
34+
35+
const handleNextDay = () => {
36+
setCurrentDate((prevDate) => {
37+
const newDate = new Date(prevDate);
38+
newDate.setDate(newDate.getDate() + 1);
39+
return newDate;
40+
});
41+
};
42+
43+
const formattedDate = currentDate.toLocaleDateString("en-US", {
44+
weekday: "long",
45+
year: "numeric",
46+
month: "long",
47+
day: "numeric",
48+
});
49+
50+
// Mock data for the timetable
51+
const timetableData = [
52+
{
53+
locationCode: "E-FAC",
54+
roomName: "E-LH1",
55+
courseCode: "CO221",
56+
startTime: "08:00",
57+
endTime: "10:00",
58+
},
59+
{
60+
locationCode: "E-FAC",
61+
roomName: "E-LH2",
62+
courseCode: "CO222",
63+
startTime: "10:00",
64+
endTime: "12:00",
65+
},
66+
{
67+
locationCode: "E-FAC",
68+
roomName: "E-LH1",
69+
courseCode: "CO223",
70+
startTime: "13:00",
71+
endTime: "15:00",
72+
},
73+
{
74+
locationCode: "E-FAC",
75+
roomName: "E-LH3",
76+
courseCode: "CO224",
77+
startTime: "08:00",
78+
endTime: "10:00",
79+
},
80+
];
81+
82+
const filteredTimetableData = selectedStartTime
83+
? timetableData.filter((entry) => entry.startTime === selectedStartTime)
84+
: timetableData;
85+
86+
return (
87+
<Card>
88+
<CardHeader className="flex flex-row items-center justify-between">
89+
<Button variant="outline" size="icon" onClick={handlePrevDay}>
90+
<ChevronLeft className="h-4 w-4" />
91+
</Button>
92+
<CardTitle className="text-center text-lg font-medium">
93+
{formattedDate}
94+
</CardTitle>
95+
<Button variant="outline" size="icon" onClick={handleNextDay}>
96+
<ChevronRight className="h-4 w-4" />
97+
</Button>
98+
</CardHeader>
99+
<CardContent>
100+
<div className="mb-4 flex items-center space-x-2">
101+
<label htmlFor="startTimeInput" className="text-sm font-medium">
102+
Select Start Time:
103+
</label>
104+
<Input
105+
id="startTimeInput"
106+
type="time"
107+
value={selectedStartTime}
108+
onChange={(e) => setSelectedStartTime(e.target.value)}
109+
className="w-[110px]"
110+
/>
111+
</div>
112+
113+
<Table>
114+
<TableHeader>
115+
<TableRow>
116+
<TableHead>Location Code</TableHead>
117+
<TableHead>Room Name</TableHead>
118+
<TableHead>Course Code</TableHead>
119+
<TableHead>End Time</TableHead>
120+
</TableRow>
121+
</TableHeader>
122+
<TableBody>
123+
{filteredTimetableData.map((entry, index) => (
124+
<TableRow key={index}>
125+
<TableCell>{entry.locationCode}</TableCell>
126+
<TableCell>{entry.roomName}</TableCell>
127+
<TableCell>{entry.courseCode}</TableCell>
128+
<TableCell>{entry.endTime}</TableCell>
129+
</TableRow>
130+
))}
131+
</TableBody>
132+
</Table>
133+
</CardContent>
134+
</Card>
135+
);
136+
};
137+
138+
139+
export default Timetable;
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
"use client";
2+
import { useState } from "react";
3+
import { Button } from "@/components/ui/button";
4+
import {
5+
Dialog,
6+
DialogContent,
7+
DialogHeader,
8+
DialogTitle,
9+
DialogTrigger,
10+
DialogFooter,
11+
DialogClose,
12+
} from "@/components/ui/dialog";
13+
import {
14+
Table,
15+
TableBody,
16+
TableCell,
17+
TableHead,
18+
TableHeader,
19+
TableRow,
20+
} from "@/components/ui/table";
21+
import { Badge } from "@/components/ui/badge";
22+
23+
type Request = {
24+
id: string;
25+
studentId: string;
26+
courseCode: string;
27+
originalDay: string;
28+
originalTime: string;
29+
requestedSlots: { day: string; time: string }[];
30+
status: "Pending" | "Approved" | "Rejected";
31+
reason: string;
32+
};
33+
34+
const initialMockRequests: Request[] = [
35+
{
36+
id: "REQ001",
37+
studentId: "S001",
38+
courseCode: "CO221",
39+
originalDay: "Monday",
40+
originalTime: "08:00",
41+
requestedSlots: [
42+
{ day: "Wednesday", time: "10:00" },
43+
{ day: "Friday", time: "14:00" },
44+
],
45+
status: "Pending",
46+
reason: "Medical appointment",
47+
},
48+
{
49+
id: "REQ002",
50+
studentId: "S002",
51+
courseCode: "CO222",
52+
originalDay: "Tuesday",
53+
originalTime: "10:00",
54+
requestedSlots: [{ day: "Thursday", time: "13:00" }],
55+
status: "Pending",
56+
reason: "Family event",
57+
},
58+
{
59+
id: "REQ003",
60+
studentId: "S001",
61+
courseCode: "CO223",
62+
originalDay: "Friday",
63+
originalTime: "13:00",
64+
requestedSlots: [{ day: "Monday", time: "15:00" }],
65+
status: "Approved",
66+
reason: "Approved",
67+
},
68+
{
69+
id: "REQ004",
70+
studentId: "S003",
71+
courseCode: "CO224",
72+
originalDay: "Wednesday",
73+
originalTime: "11:00",
74+
requestedSlots: [{ day: "Friday", time: "09:00" }],
75+
status: "Rejected",
76+
reason: "Invalid reason",
77+
},
78+
];
79+
80+
export function ClashReports() {
81+
const [requests, setRequests] = useState<Request[]>(initialMockRequests);
82+
const [selectedRequest, setSelectedRequest] = useState<Request | null>(null);
83+
84+
const handleStatusChange = (requestId: string, status: "Approved" | "Rejected") => {
85+
setRequests(prevRequests =>
86+
prevRequests.map(req =>
87+
req.id === requestId ? { ...req, status } : req
88+
)
89+
);
90+
};
91+
92+
const newReports = requests.filter(req => req.status === "Pending");
93+
const viewedReports = requests.filter(req => req.status !== "Pending");
94+
95+
const renderTable = (title: string, reports: Request[]) => (
96+
<div className="mt-8">
97+
<h2 className="text-2xl font-bold mb-4">{title}</h2>
98+
<Table>
99+
<TableHeader>
100+
<TableRow>
101+
<TableHead>Request ID</TableHead>
102+
<TableHead>Student ID</TableHead>
103+
<TableHead>Course Code</TableHead>
104+
<TableHead>Status</TableHead>
105+
<TableHead>Action</TableHead>
106+
</TableRow>
107+
</TableHeader>
108+
<TableBody>
109+
{reports.map((request) => (
110+
<TableRow key={request.id}>
111+
<TableCell>{request.id}</TableCell>
112+
<TableCell>{request.studentId}</TableCell>
113+
<TableCell>{request.courseCode}</TableCell>
114+
<TableCell>
115+
<Badge
116+
variant={
117+
request.status === "Approved"
118+
? "default"
119+
: request.status === "Rejected"
120+
? "destructive"
121+
: "outline"
122+
}
123+
>
124+
{request.status}
125+
</Badge>
126+
</TableCell>
127+
<TableCell>
128+
<Dialog onOpenChange={(isOpen) => !isOpen && setSelectedRequest(null)}>
129+
<DialogTrigger asChild>
130+
<Button
131+
variant="outline"
132+
onClick={() => setSelectedRequest(request)}
133+
>
134+
View
135+
</Button>
136+
</DialogTrigger>
137+
{selectedRequest && selectedRequest.id === request.id && (
138+
<DialogContent>
139+
<DialogHeader>
140+
<DialogTitle>Request Details</DialogTitle>
141+
</DialogHeader>
142+
<div>
143+
<p><strong>Request ID:</strong> {selectedRequest.id}</p>
144+
<p><strong>Student ID:</strong> {selectedRequest.studentId}</p>
145+
<p><strong>Course Code:</strong> {selectedRequest.courseCode}</p>
146+
<p><strong>Original Slot:</strong> {selectedRequest.originalDay}, {selectedRequest.originalTime}</p>
147+
<p><strong>Status:</strong> {selectedRequest.status}</p>
148+
<p><strong>Reason:</strong> {selectedRequest.reason}</p>
149+
<h4 className="font-semibold mt-4">Requested Slots:</h4>
150+
<ul>
151+
{selectedRequest.requestedSlots.map((slot, index) => (
152+
<li key={index}>
153+
{slot.day}, {slot.time}
154+
</li>
155+
))}
156+
</ul>
157+
</div>
158+
{selectedRequest.status === 'Pending' && (
159+
<DialogFooter className="mt-4">
160+
<DialogClose asChild>
161+
<Button variant="outline">Cancel</Button>
162+
</DialogClose>
163+
<DialogClose asChild>
164+
<Button onClick={() => handleStatusChange(selectedRequest.id, 'Approved')}>Approve</Button>
165+
</DialogClose>
166+
<DialogClose asChild>
167+
<Button variant="destructive" onClick={() => handleStatusChange(selectedRequest.id, 'Rejected')}>Reject</Button>
168+
</DialogClose>
169+
</DialogFooter>
170+
)}
171+
</DialogContent>
172+
)}
173+
</Dialog>
174+
</TableCell>
175+
</TableRow>
176+
))}
177+
</TableBody>
178+
</Table>
179+
</div>
180+
);
181+
182+
return (
183+
<div className="p-4">
184+
<h1 className="text-3xl font-bold mb-6">Clash Reports</h1>
185+
{renderTable("New Clash Reports", newReports)}
186+
{renderTable("Viewed Clash Reports", viewedReports)}
187+
</div>
188+
);
189+
}

src/app/(main)/(dashboard)/(pages)/time-table-admin/TabContents/Home.tsx

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/app/(main)/(dashboard)/(pages)/time-table-admin/TabContents/Inbox.tsx

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
"use client";
2+
import { useState } from "react";
3+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
4+
5+
export function Overview() {
6+
const [newClashReportsCount, setNewClashReportsCount] = useState(5); // Mock data
7+
8+
return (
9+
<div className="p-4">
10+
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
11+
<Card>
12+
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
13+
<CardTitle className="text-sm font-medium">
14+
New Clash Reports
15+
</CardTitle>
16+
<svg
17+
xmlns="http://www.w3.org/2000/svg"
18+
viewBox="0 0 24 24"
19+
fill="none"
20+
stroke="currentColor"
21+
strokeLinecap="round"
22+
strokeLinejoin="round"
23+
strokeWidth="2"
24+
className="h-4 w-4 text-muted-foreground"
25+
>
26+
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" />
27+
<circle cx="9" cy="7" r="4" />
28+
<path d="M22 21v-2a4 4 0 0 0-3-3.87m-3-12a4 4 0 0 1 0 7.75" />
29+
</svg>
30+
</CardHeader>
31+
<CardContent>
32+
<div className="text-2xl font-bold">{newClashReportsCount}</div>
33+
</CardContent>
34+
</Card>
35+
{/* Other overview cards can go here */}
36+
</div>
37+
</div>
38+
);
39+
}

0 commit comments

Comments
 (0)