Skip to content

Commit fc0dabf

Browse files
committed
add topics
1 parent 05177fe commit fc0dabf

File tree

3 files changed

+39
-12
lines changed

3 files changed

+39
-12
lines changed

peerprep-fe/src/app/(main)/components/filter/TopicsPopover.tsx

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,21 @@ import {
77
PopoverTrigger,
88
} from '@/components/ui/popover';
99
import { Button } from '@/components/ui/button';
10-
import { Check, ChevronsUpDown } from 'lucide-react';
10+
import { Check, ChevronsUpDown, Plus } from 'lucide-react';
1111
import { cn } from '@/lib/utils';
1212
import { Input } from '@/components/ui/input';
1313
import { ScrollArea } from '@/components/ui/scroll-area';
1414

1515
interface TopicsPopoverProps {
1616
selectedTopics: string[];
1717
onChange: (value: string[]) => void;
18+
isAdmin?: boolean;
1819
}
1920

2021
export function TopicsPopover({
2122
selectedTopics,
2223
onChange,
24+
isAdmin,
2325
}: TopicsPopoverProps) {
2426
const [open, setOpen] = useState(false);
2527
const [topics, setTopics] = useState<string[]>([]);
@@ -58,7 +60,7 @@ export function TopicsPopover({
5860
</Button>
5961
</PopoverTrigger>
6062
<PopoverContent className="w-[200px] p-0">
61-
<div className="p-2">
63+
<div className="flex gap-1 p-2">
6264
<Input
6365
placeholder="Search topics..."
6466
value={searchTerm}
@@ -68,8 +70,23 @@ export function TopicsPopover({
6870
}}
6971
className="mb-2"
7072
/>
73+
{isAdmin && (
74+
<Button
75+
onClick={async () => {
76+
if (!searchTerm.trim()) {
77+
return;
78+
}
79+
setTopics((prev) => [...prev, searchTerm]);
80+
setSearchTerm('');
81+
}}
82+
className="p-2"
83+
variant="outline"
84+
>
85+
<Plus className="h-4 w-4" />
86+
</Button>
87+
)}
7188
</div>
72-
<ScrollArea className="h-[300px]">
89+
<ScrollArea className="h-[300px] overflow-y-auto">
7390
{filteredTopics.length === 0 ? (
7491
<p className="p-2 text-sm text-muted-foreground">No topic found.</p>
7592
) : (

peerprep-fe/src/app/admin/page.tsx

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,18 @@ function AdminPage() {
2323
refetchFilter,
2424
} = useFilteredProblems();
2525

26+
const validateEntries = (problem: Problem) => {
27+
if (
28+
problem.description === '' ||
29+
problem.title === '' ||
30+
problem.tags.length === 0
31+
) {
32+
setInformationDialog('Please fill in all required fields');
33+
return false;
34+
}
35+
return true;
36+
};
37+
2638
const handleDelete = async (id: number) => {
2739
const res = await axiosClient.delete(`/questions/${id}`);
2840
if (res.status !== 200) {
@@ -34,6 +46,9 @@ function AdminPage() {
3446

3547
const handleEdit = async (problem: Problem) => {
3648
try {
49+
if (!validateEntries(problem)) {
50+
throw new Error('Invalid problem entries');
51+
}
3752
const res = await axiosClient.put(`/questions/${problem._id}`, {
3853
difficulty: problem.difficulty,
3954
description: problem.description,
@@ -68,16 +83,10 @@ function AdminPage() {
6883
};
6984

7085
const handleAdd = async (problem: Problem) => {
71-
// TODO: Add proper validation of fields
72-
if (
73-
problem.description === '' ||
74-
problem.title === '' ||
75-
problem.tags.length === 0
76-
) {
77-
setInformationDialog('Please fill in all required fields');
78-
return;
79-
}
8086
try {
87+
if (!validateEntries(problem)) {
88+
throw new Error('Invalid problem entries');
89+
}
8190
const res = await axiosClient.post(`/questions`, {
8291
difficulty: problem.difficulty,
8392
description: problem.description,

peerprep-fe/src/components/problems/ProblemInputDialog.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ function ProblemInputDialog({
9090
onChange={(value) => {
9191
setProblemData({ ...problemData, tags: value });
9292
}}
93+
isAdmin
9394
/>
9495
</div>
9596
<div className="mt-2 flex justify-end">

0 commit comments

Comments
 (0)