Skip to content

Commit

Permalink
wip(frontend): loading overlay
Browse files Browse the repository at this point in the history
  • Loading branch information
ElaBosak233 committed Jun 5, 2024
1 parent 9acec95 commit f029237
Show file tree
Hide file tree
Showing 10 changed files with 192 additions and 127 deletions.
2 changes: 1 addition & 1 deletion web/src/components/layouts/withGame.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export default function withGame(WrappedComponent: React.ComponentType<any>) {
flexShrink: 0,
}}
>
<Text fw={700} size="1.5rem">
<Text fw={700} size="2rem">
{game?.title}
</Text>
</Box>
Expand Down
115 changes: 46 additions & 69 deletions web/src/components/modals/ChallengeModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ import {
} from "@/utils/notification";
import { useForm } from "@mantine/form";
import { useTeamStore } from "@/stores/team";
import { useInterval } from "@mantine/hooks";
import { set } from "zod";

interface ChallengeModalProps extends ModalProps {
challenge?: Challenge;
Expand All @@ -54,7 +56,11 @@ export default function ChallengeModal(props: ChallengeModalProps) {
const teamStore = useTeamStore();

const [pod, setPod] = useState<Pod>();
const [podTime, setPodTime] = useState<number>(0);
const interval = useInterval(() => setPodTime((s) => s - 1), 1000);
const [podCreateLoading, setPodCreateLoading] = useState(false);
const [podRemoveLoading, setPodRemoveLoading] = useState(false);
const [podRenewLoading, setPodRenewLoading] = useState(false);

const form = useForm({
mode: "uncontrolled",
Expand Down Expand Up @@ -108,23 +114,26 @@ export default function ChallengeModal(props: ChallengeModalProps) {
}

function removePod() {
setPodRemoveLoading(true);
podApi
.removePod({
id: pod?.id as number,
})
.then((res) => {
const r = res.data;
if (r?.code === 200) {
setPod(undefined);
}
.then((_) => {
setPod(undefined);
setPodTime(0);
showSuccessNotification({
title: "操作成功",
message: "实例已销毁!",
});
})
.finally(() => {
setPodRemoveLoading(false);
});
}

function renewPod() {
setPodRenewLoading(true);
podApi
.renewPod({
id: pod?.id!,
Expand All @@ -134,6 +143,9 @@ export default function ChallengeModal(props: ChallengeModalProps) {
if (r?.code === 200) {
getPod();
}
})
.finally(() => {
setPodRenewLoading(false);
});
}

Expand Down Expand Up @@ -196,14 +208,31 @@ export default function ChallengeModal(props: ChallengeModalProps) {
});
}

useEffect(() => {
if (podTime > 0) {
interval.start();
return interval.stop;
}
}, [podTime]);

useEffect(() => {
if (pod) {
setPodTime(
Math.ceil(pod?.removed_at - new Date().getTime() / 1000)
);
}
}, [pod]);

useEffect(() => {
if (challenge?.is_dynamic) {
getPod();
}
}, [challenge]);
}, [challenge, modalProps.opened]);

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

return (
Expand Down Expand Up @@ -238,18 +267,7 @@ export default function ChallengeModal(props: ChallengeModalProps) {
}}
>
<Group gap={6}>
<MDIcon
color={
colorScheme === "light"
? challenge?.category?.color ||
"#3F51B5"
: lighten(
challenge?.category
?.color || "#3F51B5",
0.15
)
}
>
<MDIcon color={challenge?.category?.color}>
{challenge?.category?.icon}
</MDIcon>
<Text fw={700}>{challenge?.title}</Text>
Expand Down Expand Up @@ -345,16 +363,7 @@ export default function ChallengeModal(props: ChallengeModalProps) {
key={nat?.id}
value={nat?.entry}
readOnly
sx={{
input: {
"&:focus": {
borderColor:
challenge?.category
?.color ||
"#3F51B5",
},
},
}}
color={challenge?.category?.color}
leftSectionWidth={135}
leftSection={
<Flex
Expand Down Expand Up @@ -431,36 +440,23 @@ export default function ChallengeModal(props: ChallengeModalProps) {
本题为动态容器题目,解题需开启容器实例
</Text>
<Text size="0.8rem" c="secondary">
本题容器时间 {challenge?.duration}s
本题容器时间{" "}
{podTime || challenge?.duration}s
</Text>
</Stack>
<Flex gap={10}>
{pod?.id && (
<>
<Button
sx={{
backgroundColor:
"#3b81f5",
"&:hover": {
backgroundColor:
"#3b81f5",
},
color: "#FFF",
}}
loading={podRenewLoading}
color={"blue"}
onClick={renewPod}
>
实例续期
</Button>
<Button
sx={{
backgroundColor:
"#d22e2d",
"&:hover": {
backgroundColor:
"#d22e2d",
},
color: "#FFF",
}}
loading={podRemoveLoading}
color={"red"}
onClick={removePod}
>
销毁实例
Expand All @@ -470,18 +466,8 @@ export default function ChallengeModal(props: ChallengeModalProps) {
{!pod?.id && (
<Button
size="sm"
bg={
colorScheme === "light"
? challenge?.category
?.color ||
"#3F51B5"
: darken(
challenge
?.category
?.color ||
"#3F51B5",
0.25
)
color={
challenge?.category?.color
}
loading={podCreateLoading}
onClick={createPod}
Expand Down Expand Up @@ -523,16 +509,7 @@ export default function ChallengeModal(props: ChallengeModalProps) {
{...form.getInputProps("flag")}
/>
<Button
bg={
colorScheme === "light"
? challenge?.category?.color ||
"#3F51B5"
: darken(
challenge?.category
?.color || "#3F51B5",
0.25
)
}
color={challenge?.category?.color}
w={"15%"}
type="submit"
>
Expand Down
4 changes: 2 additions & 2 deletions web/src/components/navigations/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ export default function Navbar() {
</Menu.Target>
<Menu.Dropdown>
<Menu.Item
c={"brand"}
color={"brand"}
leftSection={<MDIcon>person</MDIcon>}
onClick={() => navigate("/profile")}
>
Expand All @@ -314,7 +314,7 @@ export default function Navbar() {
</Menu.Item>
<Menu.Divider />
<Menu.Item
c={"red"}
color={"red"}
leftSection={
<MDIcon color={"red"}>logout</MDIcon>
}
Expand Down
14 changes: 10 additions & 4 deletions web/src/components/widgets/GameNoticeArea.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useGameApi } from "@/api/game";
import { Notice } from "@/types/notice";
import { Box, Flex, ScrollArea } from "@mantine/core";
import { Box, Flex, ScrollArea, ThemeIcon } from "@mantine/core";
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import MDIcon from "@/components/ui/MDIcon";
Expand Down Expand Up @@ -75,13 +75,19 @@ export default function GameNoticeArea() {
<MDIcon>campaign</MDIcon>
)}
{notice?.type === "first_blood" && (
<FirstBloodIcon />
<ThemeIcon variant={"transparent"}>
<FirstBloodIcon />
</ThemeIcon>
)}
{notice?.type === "second_blood" && (
<SecondBloodIcon />
<ThemeIcon variant={"transparent"}>
<SecondBloodIcon />
</ThemeIcon>
)}
{notice?.type === "third_blood" && (
<ThirdBloodIcon />
<ThemeIcon variant={"transparent"}>
<ThirdBloodIcon />
</ThemeIcon>
)}
{notice?.type === "new_challenge" && (
<MDIcon color={"green"}>add</MDIcon>
Expand Down
23 changes: 21 additions & 2 deletions web/src/components/widgets/TeamCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Stack,
Tooltip,
Divider,
Title,
} from "@mantine/core";
import MDIcon from "@/components/ui/MDIcon";

Expand All @@ -34,10 +35,28 @@ export default function TeamCard({ team }: { team?: Team }) {
<MDIcon size={40}>people</MDIcon>
</Avatar>
<Stack gap={5}>
<Text size="2rem" fw={600}>
<Title
size="2rem"
fw={600}
maw={200}
sx={{
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
{team?.name}
</Title>
<Text
maw={200}
sx={{
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap",
}}
>
{team?.description}
</Text>
<Text>{team?.description}</Text>
</Stack>
</Flex>
<Divider my={15} />
Expand Down
9 changes: 9 additions & 0 deletions web/src/composables/useTheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ export default function useTheme() {
],
},
primaryColor: "brand",
components: {
LoadingOverlay: {
defaultProps: {
transitionProps: {
exitDuration: 250,
},
},
},
},
});
return { theme: theme };
}
2 changes: 1 addition & 1 deletion web/src/pages/challenges/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default function Page() {
const [selectedCategory, setSelectedCategory] = useState<number>(0);
const [sort, setSort] = useState<string>("id_desc");

const [loading, setLoading] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(true);

const [opened, { open, close }] = useDisclosure(false);
const [selectedChallenge, setSelectedChallenge] = useState<Challenge>();
Expand Down
Loading

0 comments on commit f029237

Please sign in to comment.