Skip to content

Commit

Permalink
wip: update
Browse files Browse the repository at this point in the history
  • Loading branch information
ElaBosak233 committed Jan 16, 2025
1 parent 40cd2a0 commit 8125b4d
Show file tree
Hide file tree
Showing 16 changed files with 141 additions and 50 deletions.
4 changes: 1 addition & 3 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@
</head>
<body>
<div id="root"></div>
<div id="dialog-portal"></div>
<div id="popover-portal"></div>
<div id="tooltip-portal"></div>
<div id="portals"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
15 changes: 11 additions & 4 deletions src/api/challenge.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,18 @@ import {
ChallengeStatus,
ChallengeStatusRequest,
ChallengeUpdateRequest,
ChallengeDeleteRequest,
} from "@/models/challenge";
import { Response } from "@/types";
import { alovaInstance } from "@/utils/alova";

export async function get(request: ChallengeGetRequest) {
export async function getChallenges(request: ChallengeGetRequest) {
return alovaInstance.Get<Response<Array<Challenge>>>("/challenges", {
params: request,
});
}

export async function getStatus(request: ChallengeStatusRequest) {
export async function getChallengeStatus(request: ChallengeStatusRequest) {
return alovaInstance.Post<Response<Record<number, ChallengeStatus>>>(
"/challenges/status",
request,
Expand All @@ -25,7 +26,7 @@ export async function getStatus(request: ChallengeStatusRequest) {
);
}

export async function update(request: ChallengeUpdateRequest) {
export async function updateChallenge(request: ChallengeUpdateRequest) {
return alovaInstance.Put<Response<Challenge>>(
`/challenges/${request?.id}`,
request,
Expand All @@ -35,8 +36,14 @@ export async function update(request: ChallengeUpdateRequest) {
);
}

export async function create(request: ChallengeCreateRequest) {
export async function createChallenge(request: ChallengeCreateRequest) {
return alovaInstance.Post<Response<Challenge>>("/challenges", request, {
cacheFor: 0,
});
}

export async function deleteChallenge(request: ChallengeDeleteRequest) {
return alovaInstance.Delete<Response<never>>(`/challenges/${request.id}`, {
cacheFor: 0,
});
}
2 changes: 1 addition & 1 deletion src/components/core/Button/Button.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

&[data-variant="ghost"] {
background-color: transparent;
box-shadow: none;
box-shadow: 0 0 0 0 var(--button-bg-color);
color: var(--button-bg-color);
}

Expand Down
25 changes: 21 additions & 4 deletions src/components/core/Dialog/Dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import styles from "./Dialog.module.scss";
import React, { ComponentProps, useRef } from "react";
import React, { ComponentProps, useEffect, useRef } from "react";
import { Dialog as ArkDialog, Portal } from "@ark-ui/react";
import { nanoid } from "nanoid";

export interface DialogProps extends ComponentProps<"dialog"> {
open: boolean;
Expand All @@ -10,9 +11,25 @@ export interface DialogProps extends ComponentProps<"dialog"> {

export function Dialog(props: DialogProps) {
const { children, open, onClose } = props;
const portal = useRef<HTMLElement | null>(
document.getElementById("dialog-portal")!
);
const portal = useRef<HTMLElement | null>(null);

useEffect(() => {
const ctn = document.createElement("div");
ctn.id = `dialog-portal-${nanoid()}`;
document.getElementById("portals")!.appendChild(ctn);
portal.current = ctn;

return () => {
if (portal.current) {
document.getElementById("portals")!.removeChild(portal.current);
portal.current = null;
}
};
}, []);

if (!portal.current) {
return;
}

return (
<ArkDialog.Root open={open} onOpenChange={(details) => onClose()}>
Expand Down
25 changes: 21 additions & 4 deletions src/components/core/Popover/Popover.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useRef, useState } from "react";
import { useEffect, useRef, useState } from "react";
import styles from "./Popover.module.scss";
import clsx from "clsx";
import { Popover as ArkPopover, Portal } from "@ark-ui/react";
import { nanoid } from "nanoid";

export interface PopoverProps {
children: React.ReactElement;
Expand Down Expand Up @@ -44,9 +45,25 @@ export function Popover(props: PopoverProps) {
}
}

const portal = useRef<HTMLElement | null>(
document.getElementById("popover-portal")!
);
const portal = useRef<HTMLElement | null>(null);

useEffect(() => {
const ctn = document.createElement("div");
ctn.id = `popover-portal-${nanoid()}`;
document.getElementById("portals")!.appendChild(ctn);
portal.current = ctn;

return () => {
if (portal.current) {
document.getElementById("portals")!.removeChild(portal.current);
portal.current = null;
}
};
}, []);

if (!portal.current) {
return;
}

return (
<ArkPopover.Root
Expand Down
25 changes: 21 additions & 4 deletions src/components/core/Tooltip/Tooltip.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import styles from "./Tooltip.module.scss";
import { Tooltip as ArkTooltip, Portal } from "@ark-ui/react";
import { useRef } from "react";
import { nanoid } from "nanoid";
import { useEffect, useRef } from "react";

export interface TooltipProps {
content?: React.ReactNode;
Expand All @@ -25,9 +26,25 @@ export function Tooltip(props: TooltipProps) {
children,
} = props;

const portal = useRef<HTMLElement | null>(
document.getElementById("tooltip-portal")!
);
const portal = useRef<HTMLElement | null>(null);

useEffect(() => {
const ctn = document.createElement("div");
ctn.id = `tooltip-portal-${nanoid()}`;
document.getElementById("portals")!.appendChild(ctn);
portal.current = ctn;

return () => {
if (portal.current) {
document.getElementById("portals")!.removeChild(portal.current);
portal.current = null;
}
};
}, []);

if (!portal.current) {
return;
}

return (
<ArkTooltip.Root
Expand Down
8 changes: 1 addition & 7 deletions src/components/widgets/Navbar/Navbar.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,6 @@
}

.avatar {
border-radius: 50%;
padding: 2px;
transition: all 200ms ease-in-out;
padding: 5px;
cursor: pointer;

&:active {
transform: translateY(2px);
}
}
14 changes: 7 additions & 7 deletions src/components/widgets/Navbar/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import SolarRoundArrowLeftBold from "~icons/solar/round-arrow-left-bold";
import StarFallMinimalistic2Bold from "~icons/solar/star-fall-minimalistic-2-bold";
import CupStarBold from "~icons/solar/cup-star-bold";
import styles from "./Navbar.module.scss";
import { useEffect, useMemo, useRef, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { Link, useLocation, useParams } from "react-router";
import {
Avatar,
Expand All @@ -20,7 +20,7 @@ import {
Flex,
Box,
} from "@/components/core";
import { Dropdown } from "./Dropdown";
import { Dropdown } from "./_blocks/Dropdown";
import React from "react";
import { get } from "@/api/game";
import { Game } from "@/models/game";
Expand Down Expand Up @@ -116,9 +116,6 @@ export function Navbar() {
});
}, [location.pathname]);

const [dropdownMenuOpen, setDropdownMenuOpen] = useState<boolean>(false);
const dropdownMenuButtonRef = useRef(null);

return (
<header className={styles["root"]}>
<Box className={styles["left-section"]}>
Expand Down Expand Up @@ -207,7 +204,10 @@ export function Navbar() {
</Link>
)}
<Popover content={<Dropdown />}>
<Box className={styles["avatar"]}>
<Button
variant={"ghost"}
className={styles["avatar"]}
>
<Avatar
src={
authStore?.user
Expand All @@ -218,7 +218,7 @@ export function Navbar() {
color={"#ffffff"}
size={2}
/>
</Box>
</Button>
</Popover>
</Box>
</Box>
Expand Down
6 changes: 3 additions & 3 deletions src/pages/challenges/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { get, getStatus } from "@/api/challenge";
import { getChallenges, getChallengeStatus } from "@/api/challenge";
import {
Button,
Dialog,
Expand Down Expand Up @@ -52,7 +52,7 @@ export function Index() {
function fetchChallenges() {
setLoading(true);
setChallenges([]);
get({
getChallenges({
id: id ? id : undefined,
is_public: true,
page: page,
Expand All @@ -65,7 +65,7 @@ export function Index() {
}

function fetchChallengeStatus() {
getStatus({
getChallengeStatus({
challenge_ids: challenges?.map((challenge) => challenge.id!) || [],
user_id: authStore?.user?.id,
}).then((res) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import ArrowRightLinear from "~icons/solar/arrow-right-linear";
import styles from "./ChallengeCreateModal.module.scss";
import { useState } from "react";
import { useCategoryStore } from "@/stores/category";
import { create } from "@/api/challenge";
import { createChallenge } from "@/api/challenge";
import { useToastStore } from "@/stores/toast";
import { useNavigate } from "react-router";

Expand All @@ -32,7 +32,7 @@ export function ChallengeCreateModal() {
return;
}

create({
createChallenge({
title: title,
category: category,
is_public: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
.root {
background-color: var(--bg-color);
border-radius: 12px;
min-height: 15rem;
width: 30rem;
padding: 20px;
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
import { Box, Flex, Stack } from "@/components/core";
import { Box, Button, Flex, Stack } from "@/components/core";
import { Challenge } from "@/models/challenge";
import TrashBinTrashBold from "~icons/solar/trash-bin-trash-bold";
import styles from "./ChallengeDeleteModal.module.scss";
import { deleteChallenge } from "@/api/challenge";
import { useToastStore } from "@/stores/toast";
import { useSharedStore } from "@/stores/shared";

export interface ChallengeDeleteModalProps {
challenge?: Challenge;
onClose: () => void;
}

export function ChallengeDeleteModal(props: ChallengeDeleteModalProps) {
const { challenge } = props;
const { challenge, onClose } = props;
const toastStore = useToastStore();
const sharedStore = useSharedStore();

function handleChallengeDelete() {
deleteChallenge({
id: challenge?.id,
}).then((_) => {
toastStore.add({
type: "success",
title: "成功",
description: `题目 ${challenge?.title} 删除成功`,
});
onClose();
sharedStore?.setRefresh();
});
}

return (
<Stack className={styles["root"]}>
Expand All @@ -24,10 +44,29 @@ export function ChallengeDeleteModal(props: ChallengeDeleteModalProps) {
</Box>
<h2 style={{ fontSize: "0.95rem" }}>从题库中删除题目</h2>
</Flex>
<p style={{ fontSize: "0.875rem" }}>
{challenge?.title}{" "}
将从题库中删除,并且无法恢复。所有与此题目相关的数据(提交、赛题等)都会随之删除。
</p>
<Flex width={"100%"} justify={"center"}>
<p
style={{
fontSize: "1.25rem",
fontWeight: 600,
textDecoration: "underline",
}}
>
{challenge?.title}
</p>
</Flex>
<span>
将从题库中软删除,但无法恢复。所有与之相关的数据会得到保留。请问你确定要删除这道题目吗?
</span>
<Flex width={"100%"} justify={"flex-end"}>
<Button
variant={"solid"}
color={"error"}
onClick={handleChallengeDelete}
>
确定
</Button>
</Flex>
</Stack>
);
}
Loading

0 comments on commit 8125b4d

Please sign in to comment.