Skip to content

Commit

Permalink
wip(frontend): category admin page
Browse files Browse the repository at this point in the history
  • Loading branch information
ElaBosak233 committed May 30, 2024
1 parent 71b5f9c commit b0478e3
Show file tree
Hide file tree
Showing 15 changed files with 407 additions and 37 deletions.
6 changes: 5 additions & 1 deletion internal/model/category.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ type Category struct {
}

func (c *Category) BeforeDelete(db *gorm.DB) (err error) {
db.Table("challenges").Where("category_id = ?", c.ID).Delete(&Challenge{})
var challenges []Challenge
db.Table("challenges").Where("category_id = ?", c.ID).Find(&challenges)
for _, challenge := range challenges {
db.Table("challenges").Delete(&challenge)
}
return nil
}
132 changes: 132 additions & 0 deletions web/src/components/modals/admin/CategoryCreateModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { useCategoryApi } from "@/api/category";
import MDIcon from "@/components/ui/MDIcon";
import { showSuccessNotification } from "@/utils/notification";
import {
Box,
Button,
Card,
Divider,
Flex,
Modal,
ModalProps,
Stack,
TextInput,
Text,
ColorInput,
} from "@mantine/core";
import { useForm, zodResolver } from "@mantine/form";
import { useEffect } from "react";
import { z } from "zod";

interface CategoryCreateModalProps extends ModalProps {
setRefresh: () => void;
}

export default function CategoryCreateModal(props: CategoryCreateModalProps) {
const { setRefresh, ...modalProps } = props;
const categoryApi = useCategoryApi();

const form = useForm({
mode: "controlled",
initialValues: {
name: "",
color: "",
icon: "",
},
validate: zodResolver(
z.object({
name: z.string(),
})
),
});

function createCategory() {
categoryApi
.createCategory({
name: form.getValues().name,
icon: form.getValues().icon,
color: form.getValues().color,
})
.then((_) => {
showSuccessNotification({
message: `分类 ${form.getValues().name} 创建成功`,
});
setRefresh();
modalProps.onClose();
});
}

useEffect(() => {
form.reset();
}, [modalProps.opened]);

return (
<>
<Modal.Root {...modalProps}>
<Modal.Overlay />
<Modal.Content
sx={{
flex: "none",
backgroundColor: "transparent",
}}
>
<Card
shadow="md"
padding={"lg"}
radius={"md"}
withBorder
w={"40rem"}
>
<Flex gap={10} align={"center"}>
<MDIcon>collections_bookmark</MDIcon>
<Text fw={600}>创建分类</Text>
</Flex>
<Divider my={10} />
<Box p={10}>
<form
onSubmit={form.onSubmit((_) =>
createCategory()
)}
>
<Stack gap={10}>
<TextInput
label="分类名"
withAsterisk
key={form.key("name")}
{...form.getInputProps("name")}
/>
<ColorInput
label="颜色"
key={form.key("color")}
{...form.getInputProps("color")}
/>
<TextInput
label="图标"
withAsterisk
leftSection={
<MDIcon>
{form.getValues().icon}
</MDIcon>
}
key={form.key("icon")}
{...form.getInputProps("icon")}
/>
</Stack>
<Flex mt={20} justify={"end"}>
<Button
type="submit"
leftSection={
<MDIcon c={"white"}>check</MDIcon>
}
>
创建
</Button>
</Flex>
</form>
</Box>
</Card>
</Modal.Content>
</Modal.Root>
</>
);
}
157 changes: 157 additions & 0 deletions web/src/components/modals/admin/CategoryEditModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { useCategoryApi } from "@/api/category";
import MDIcon from "@/components/ui/MDIcon";
import { Category } from "@/types/category";
import { showSuccessNotification } from "@/utils/notification";
import {
Box,
Button,
Card,
Divider,
Flex,
Modal,
ModalProps,
Stack,
TextInput,
Text,
ColorInput,
} from "@mantine/core";
import { useForm, zodResolver } from "@mantine/form";
import { useEffect, useState } from "react";
import { z } from "zod";

interface CategoryEditModalProps extends ModalProps {
setRefresh: () => void;
categoryID: number;
}

export default function CategoryEditModal(props: CategoryEditModalProps) {
const { setRefresh, categoryID, ...modalProps } = props;
const categoryApi = useCategoryApi();

const [category, setCategory] = useState<Category>();

const form = useForm({
mode: "controlled",
initialValues: {
name: "",
color: "",
icon: "",
},
validate: zodResolver(
z.object({
name: z.string(),
})
),
});

function getCategory() {
categoryApi.getCategories().then((res) => {
const r = res.data;
setCategory(r?.data?.find((c: Category) => c.id === categoryID));
});
}

function updateCategory() {
categoryApi
.updateCategory({
id: categoryID,
name: form.getValues().name,
icon: form.getValues().icon,
color: form.getValues().color,
})
.then((_) => {
showSuccessNotification({
message: `分类 ${form.getValues().name} 更新成功`,
});
setRefresh();
modalProps.onClose();
});
}

useEffect(() => {
form.reset();
if (modalProps.opened) {
getCategory();
}
}, [modalProps.opened]);

useEffect(() => {
if (category) {
form.setValues({
name: category.name,
color: category.color,
icon: category.icon,
});
}
}, [category]);

return (
<>
<Modal.Root {...modalProps}>
<Modal.Overlay />
<Modal.Content
sx={{
flex: "none",
backgroundColor: "transparent",
}}
>
<Card
shadow="md"
padding={"lg"}
radius={"md"}
withBorder
w={"40rem"}
>
<Flex gap={10} align={"center"}>
<MDIcon>collections_bookmark</MDIcon>
<Text fw={600}>更新分类</Text>
</Flex>
<Divider my={10} />
<Box p={10}>
<form
onSubmit={form.onSubmit((_) =>
updateCategory()
)}
>
<Stack gap={10}>
<TextInput
label="分类名"
withAsterisk
key={form.key("name")}
{...form.getInputProps("name")}
/>
<ColorInput
label="颜色"
key={form.key("color")}
{...form.getInputProps("color")}
/>
<TextInput
label="图标"
withAsterisk
leftSection={
<MDIcon>
{form.getValues().icon}
</MDIcon>
}
key={form.key("icon")}
{...form.getInputProps("icon")}
/>
</Stack>
<Flex mt={20} justify={"end"}>
<Button
type="submit"
leftSection={
<MDIcon c={"white"}>check</MDIcon>
}
>
保存
</Button>
</Flex>
</form>
</Box>
</Card>
</Modal.Content>
</Modal.Root>
</>
);
}
2 changes: 0 additions & 2 deletions web/src/components/modals/admin/ChallengeCreateModal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { useGameApi } from "@/api/game";
import MDIcon from "@/components/ui/MDIcon";
import { showSuccessNotification } from "@/utils/notification";
import {
Expand All @@ -13,7 +12,6 @@ import {
Text,
Card,
Textarea,
ThemeIcon,
SimpleGrid,
Select,
} from "@mantine/core";
Expand Down
2 changes: 0 additions & 2 deletions web/src/components/modals/admin/ChallengeFlagCreateModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ import {
ModalProps,
Stack,
TextInput,
ThemeIcon,
Text,
Switch,
Select,
Group,
} from "@mantine/core";
import { useForm } from "@mantine/form";
import { useEffect } from "react";
Expand Down
1 change: 0 additions & 1 deletion web/src/components/modals/admin/ChallengeSelectModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {
Modal,
ModalProps,
TextInput,
ThemeIcon,
Text,
Stack,
Group,
Expand Down
2 changes: 0 additions & 2 deletions web/src/components/modals/admin/GameChallengeCreateModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ import {
Flex,
Modal,
ModalProps,
ThemeIcon,
Text,
Divider,
TextInput,
Stack,
Button,
Box,
Expand Down
3 changes: 0 additions & 3 deletions web/src/components/modals/admin/GameCreateModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ import {
TextInput,
Text,
Card,
Group,
Input,
Textarea,
ThemeIcon,
} from "@mantine/core";
import { useForm, zodResolver } from "@mantine/form";
import { DateTimePicker } from "@mantine/dates";
Expand Down
1 change: 0 additions & 1 deletion web/src/components/modals/admin/GameNoticeCreateModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
ModalProps,
Stack,
TextInput,
ThemeIcon,
Text,
} from "@mantine/core";
import { useForm } from "@mantine/form";
Expand Down
1 change: 0 additions & 1 deletion web/src/components/modals/admin/GameTeamCreateModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import {
Modal,
ModalProps,
Stack,
ThemeIcon,
Text,
Avatar,
} from "@mantine/core";
Expand Down
14 changes: 0 additions & 14 deletions web/src/components/navigations/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -206,20 +206,6 @@ export default function Navbar() {
>
题库
</Button>
<Button
sx={{
backgroundColor: "transparent",
"&:hover": {
backgroundColor: "transparent",
},
}}
leftSection={
<MDIcon color={"white"}>category</MDIcon>
}
onClick={() => navigate("/admin/categories")}
>
分类
</Button>
<Button
sx={{
backgroundColor: "transparent",
Expand Down
Loading

0 comments on commit b0478e3

Please sign in to comment.