Skip to content

Commit 0ddb8a6

Browse files
committed
Add username badge for the compare timetable dropdown
1 parent 0ec1d35 commit 0ddb8a6

File tree

4 files changed

+82
-59
lines changed

4 files changed

+82
-59
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import * as React from "react"
2+
import { cva, type VariantProps } from "class-variance-authority"
3+
4+
import { cn } from "@/lib/utils"
5+
6+
const badgeVariants = cva(
7+
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8+
{
9+
variants: {
10+
variant: {
11+
default:
12+
"border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
13+
secondary:
14+
"border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15+
destructive:
16+
"border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
17+
outline: "text-foreground",
18+
},
19+
},
20+
defaultVariants: {
21+
variant: "default",
22+
},
23+
}
24+
)
25+
26+
export interface BadgeProps
27+
extends React.HTMLAttributes<HTMLDivElement>,
28+
VariantProps<typeof badgeVariants> {}
29+
30+
function Badge({ className, variant, ...props }: BadgeProps) {
31+
return (
32+
<div className={cn(badgeVariants({ variant }), className)} {...props} />
33+
)
34+
}
35+
36+
export { Badge, badgeVariants }

course-matrix/frontend/src/pages/Compare/CompareTimetables.tsx

Lines changed: 3 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { useGetTimetablesSharedWithMeQuery } from "@/api/sharedApiSlice";
2727
import { TimetableShare } from "../Home/Home";
2828
import ViewCalendar from "../TimetableBuilder/ViewCalendar";
2929
import { sortTimetablesComparator } from "@/utils/calendar-utils";
30+
import TimetableCompareItem from "../Home/TimetableCompareItem";
3031

3132
export const CompareTimetables = () => {
3233
const [timetable1, setTimetable1] = useState<Timetable>();
@@ -171,21 +172,7 @@ export const CompareTimetables = () => {
171172
</SelectTrigger>
172173
</FormControl>
173174
<SelectContent>
174-
{allTimetables &&
175-
allTimetables.map((timetable) => (
176-
<SelectItem
177-
key={`timetable1/${timetable.id}/${timetable.user_id}`}
178-
value={`timetable1/${timetable.id}/${timetable.user_id}`}
179-
>
180-
<div className="flex items-center gap-2">
181-
<SemesterIcon
182-
semester={timetable.semester}
183-
size={18}
184-
/>
185-
<span>{timetable.timetable_title}</span>
186-
</div>
187-
</SelectItem>
188-
))}
175+
{allTimetables && allTimetables.map((timetable) => <TimetableCompareItem key={`timetable1/${timetable.id}/${timetable.user_id}`} timetable={timetable} />)}
189176
</SelectContent>
190177
</Select>
191178
<FormMessage />
@@ -215,21 +202,7 @@ export const CompareTimetables = () => {
215202
</SelectTrigger>
216203
</FormControl>
217204
<SelectContent>
218-
{allTimetables &&
219-
allTimetables.map((timetable) => (
220-
<SelectItem
221-
key={`timetable2/${timetable.id}/${timetable.user_id}`}
222-
value={`timetable2/${timetable.id}/${timetable.user_id}`}
223-
>
224-
<div className="flex items-center gap-2">
225-
<SemesterIcon
226-
semester={timetable.semester}
227-
size={18}
228-
/>
229-
<span>{timetable.timetable_title}</span>
230-
</div>
231-
</SelectItem>
232-
))}
205+
{allTimetables && allTimetables.map((timetable) => <TimetableCompareItem key={`timetable2/${timetable.id}/${timetable.user_id}`} timetable={timetable} />)}
233206
</SelectContent>
234207
</Select>
235208
<FormMessage />

course-matrix/frontend/src/pages/Home/TimetableCompareButton.tsx

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import {
88
DialogFooter,
99
DialogTitle,
1010
DialogDescription,
11-
DialogClose,
1211
} from "@/components/ui/dialog";
1312
import {
1413
Form,
@@ -32,6 +31,7 @@ import { useState } from "react";
3231
import { useForm } from "react-hook-form";
3332
import { useNavigate } from "react-router-dom";
3433
import { z } from "zod";
34+
import TimetableCompareItem from "./TimetableCompareItem";
3535

3636
export const CompareFormSchema = z.object({
3737
timetable1: z.string().nonempty(),
@@ -115,20 +115,7 @@ export const TimetableCompareButton = ({
115115
</SelectTrigger>
116116
</FormControl>
117117
<SelectContent>
118-
{timetables.map((timetable) => (
119-
<SelectItem
120-
key={`timetable1/${timetable.id}/${timetable.user_id}`}
121-
value={`timetable1/${timetable.id}/${timetable.user_id}`}
122-
>
123-
<div className="flex items-center gap-2">
124-
<SemesterIcon
125-
semester={timetable.semester}
126-
size={18}
127-
/>
128-
<span>{timetable.timetable_title}</span>
129-
</div>
130-
</SelectItem>
131-
))}
118+
{timetables.map((timetable) => <TimetableCompareItem key={`timetable1/${timetable.id}/${timetable.user_id}`} timetable={timetable} />)}
132119
</SelectContent>
133120
</Select>
134121
<FormMessage />
@@ -149,20 +136,7 @@ export const TimetableCompareButton = ({
149136
</SelectTrigger>
150137
</FormControl>
151138
<SelectContent>
152-
{timetables.map((timetable) => (
153-
<SelectItem
154-
key={`timetable2/${timetable.id}/${timetable.user_id}`}
155-
value={`timetable2/${timetable.id}/${timetable.user_id}`}
156-
>
157-
<div className="flex items-center gap-2">
158-
<SemesterIcon
159-
semester={timetable.semester}
160-
size={18}
161-
/>
162-
<span>{timetable.timetable_title}</span>
163-
</div>
164-
</SelectItem>
165-
))}
139+
{timetables.map((timetable) => <TimetableCompareItem key={`timetable2/${timetable.id}/${timetable.user_id}`} timetable={timetable} /> )}
166140
</SelectContent>
167141
</Select>
168142
<FormMessage />
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { SemesterIcon } from "@/components/semester-icon";
2+
import { SelectItem } from "@/components/ui/select";
3+
import { Timetable } from "@/utils/type-utils";
4+
import { Badge } from "@/components/ui/badge"
5+
import { useGetUsernameFromUserIdQuery } from "@/api/authApiSlice";
6+
import { useEffect, useState } from "react";
7+
8+
interface TimetableCompareItemProps {
9+
timetable: Timetable;
10+
}
11+
12+
const TimetableCompareItem = ({
13+
timetable,
14+
}: TimetableCompareItemProps) => {
15+
const { data: usernameData } = useGetUsernameFromUserIdQuery(timetable.user_id);
16+
const [username, setUsername] = useState<string | null>("");
17+
const [loadedUsername, setLoadedUsername] = useState(false);
18+
19+
useEffect(() => {
20+
if (usernameData !== undefined && !loadedUsername) {
21+
setUsername(usernameData ?? "John Doe");
22+
setLoadedUsername(true);
23+
}
24+
}, [loadedUsername, usernameData]);
25+
26+
return <SelectItem key={`timetable2/${timetable.id}/${timetable.user_id}`} value={`timetable2/${timetable.id}/${timetable.user_id}`}>
27+
<div className="flex flex-row justify-between gap-2">
28+
<span className="flex items-center gap-2">
29+
<SemesterIcon
30+
semester={timetable.semester}
31+
size={18}
32+
/>
33+
<span>{timetable.timetable_title}</span>
34+
</span>
35+
<Badge variant="secondary">Owner: {username}</Badge>
36+
</div>
37+
</SelectItem>
38+
}
39+
40+
export default TimetableCompareItem;

0 commit comments

Comments
 (0)