Skip to content

Commit

Permalink
wip: update
Browse files Browse the repository at this point in the history
  • Loading branch information
ElaBosak233 committed Nov 11, 2024
1 parent 5e96b3c commit b295fe5
Show file tree
Hide file tree
Showing 16 changed files with 209 additions and 50 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"install": "^0.13.0",
"katex": "^0.16.11",
"luxon": "^3.5.0",
"nanoid": "^5.0.8",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-markdown": "^9.0.1",
Expand Down
7 changes: 7 additions & 0 deletions src/api/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { User, UserLoginRequest } from "@/models/user";
import { Result } from "@/types";
import { alovaInstance } from "@/utils/alova";

export async function login(request: UserLoginRequest) {
return alovaInstance.Post<Result<User>>("/users/login", request);
}
20 changes: 8 additions & 12 deletions src/components/core/Toast/Toast.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,16 @@ $border-color: var(--toast-border-color);
background-color: $bg-color;
border: 2.75px solid $border-color;
border-radius: 16px;
padding: 10px 15px;
padding: 10px 20px;
min-width: 20vw;
position: relative;

background-image: linear-gradient(to right, #ffffff0d 1px, transparent 1px),
linear-gradient(to bottom, #ffffff0d 1px, transparent 1px);

background-size: 20px 20px;
}

.icon {
width: 2.5rem;
height: 2.5rem;
width: 2rem;
height: 2rem;
color: #ffffff;
border-radius: 50%;
}

.content-wrapper {
Expand All @@ -34,13 +30,13 @@ $border-color: var(--toast-border-color);
}

.title {
font-size: 1.125rem;
line-height: 1.75rem;
font-size: 1rem;
line-height: 1.5rem;
color: #ffffff;
}

.description {
font-size: 1rem;
line-height: 1.5rem;
font-size: 0.75rem;
line-height: 1.125rem;
color: #ffffff;
}
9 changes: 5 additions & 4 deletions src/components/core/Toast/Toast.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import styles from "./Toast.module.scss";
import useThemeColor from "@/hooks/useThemeColor";
import chroma from "chroma-js";
import { ComponentProps } from "react";
import { Icon } from "../Icon";

export interface ToastProps extends ComponentProps<"div"> {
id?: string;
title?: string;
description?: string;
color?: string;
icon?: React.ReactNode;
icon?: React.ReactElement;
type?: string;
duration?: number;
}

export function Toast(props: ToastProps) {
Expand All @@ -23,7 +23,6 @@ export function Toast(props: ToastProps) {
color = "primary",
icon = <InfoCircleBold />,
type,
duration = 3000,
...rest
} = props;

Expand All @@ -38,7 +37,9 @@ export function Toast(props: ToastProps) {

return (
<div className={styles["root"]} style={variables} {...rest}>
<div className={styles["icon"]}>{icon}</div>
<div className={styles["icon"]}>
<Icon icon={icon} />
</div>
<div className={styles["content-wrapper"]}>
<h2 className={styles["title"]}>{title}</h2>
<p className={styles["description"]}>{description}</p>
Expand Down
25 changes: 22 additions & 3 deletions src/components/widgets/Toaster/Toaster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,29 @@ import { useToastStore } from "@/stores/toast";
import styles from "./Toaster.module.scss";
import React, { useEffect, useRef, useState } from "react";
import { TransitionGroup, CSSTransition } from "react-transition-group";
import InfoCircleBold from "~icons/solar/info-circle-bold";
import CheckCircleBold from "~icons/solar/check-circle-bold";
import DangerCircleBold from "~icons/solar/danger-circle-bold";
import CloseCircleBold from "~icons/solar/close-circle-bold";

export function Toaster() {
const toastStore = useToastStore();
const nodeRefs = useRef(new Map());
const [visibleToasts, setVisibleToasts] = useState(new Set());

function getIcon(type: string) {
switch (type) {
case "info":
return <InfoCircleBold />;
case "success":
return <CheckCircleBold />;
case "warning":
return <DangerCircleBold />;
case "error":
return <CloseCircleBold />;
}
}

useEffect(() => {
toastStore.toasts.forEach((toast) => {
if (!visibleToasts.has(toast.id)) {
Expand All @@ -20,7 +37,7 @@ export function Toaster() {
newSet.delete(toast.id);
return newSet;
});
toastStore.removeToast(toast.id);
toastStore.remove(toast.id);
nodeRefs.current.delete(toast.id);
}, toast.duration || 3000);

Expand Down Expand Up @@ -53,8 +70,10 @@ export function Toaster() {
>
<div ref={nodeRef} className={styles["toast"]}>
<Toast
title={`你好 ${toast.id}`}
description={"ciallo~"}
title={toast?.title}
description={toast?.description}
icon={toast?.icon || getIcon(toast?.type)}
color={toast?.type}
/>
</div>
</CSSTransition>
Expand Down
8 changes: 4 additions & 4 deletions src/models/submission.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Game } from "@/types/game";
import { Team } from "@/types/team";
import { Challenge } from "@/types/challenge";
import { User } from "@/types/user";
import { Game } from "./game";
import { Team } from "./team";
import { Challenge } from "./challenge";
import { User } from "./user";

export interface Submission {
id?: number;
Expand Down
2 changes: 1 addition & 1 deletion src/models/team.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { User } from "@/types/user";
import { User } from "./user";

export interface Team {
id?: number;
Expand Down
2 changes: 1 addition & 1 deletion src/models/user.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Team } from "@/types/team";
import { Team } from "./team";

export interface User {
id?: number;
Expand Down
35 changes: 32 additions & 3 deletions src/pages/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@ import UserBold from "~icons/solar/user-bold";
import LockPasswordBold from "~icons/solar/lock-password-bold";
import LoginBold from "~icons/solar/login-bold";
import useThemeColor from "@/hooks/useThemeColor";
import { login } from "@/api/user";
import { useAuthStore } from "@/stores/auth";
import { useNavigate } from "react-router-dom";
import { useToastStore } from "@/stores/toast";

export function Page() {
const authStore = useAuthStore();
const categoryStore = useCategoryStore();
const toastStore = useToastStore();
const navigate = useNavigate();

const categories = categoryStore.categories;

Expand All @@ -18,8 +25,28 @@ export function Page() {
useThemeColor(category.color!)
);

const [username, setUsername] = useState<string>("");
const [account, setAccount] = useState<string>("");
const [password, setPassword] = useState<string>("");
const [loading, setLoading] = useState<boolean>(false);

async function handleLogin() {
setLoading(true);
const res = await login({ account, password });
const code = res?.code;
switch (code) {
case 200:
const user = res?.data;
authStore.setUser(user);
toastStore.add({
title: "登录成功",
description: `欢迎你 ${user?.nickname}`,
type: "success",
duration: 3000,
});
navigate("/");
}
setLoading(false);
}

useEffect(() => {
const intervalId = setInterval(() => {
Expand Down Expand Up @@ -49,8 +76,8 @@ export function Page() {
placeholder="Username"
label={"用户名"}
icon={<UserBold />}
value={username}
onChange={(value) => setUsername(value)}
value={account}
onChange={(value) => setAccount(value)}
/>
<TextInput
width="100%"
Expand All @@ -67,6 +94,8 @@ export function Page() {
style={{
margin: "1rem 0",
}}
onClick={handleLogin}
loading={loading}
>
登录
</Button>
Expand Down
76 changes: 62 additions & 14 deletions src/pages/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -307,22 +307,70 @@ ReactDOM.render(
))}
</div>

<Button
variant="solid"
onClick={() => {
useToastStore.getState().addToast({
title: "通知",
description: "这是一个通知",
type: "success",
meta: {
icon: "123",
},
duration: 3000,
});
<div
style={{
display: "flex",
gap: "20px",
}}
>
发送通知114514
</Button>
<Button
variant="solid"
onClick={() => {
useToastStore.getState().add({
title: "Info Message",
description: "这是一个通知",
type: "info",
duration: 3000,
});
}}
color={"info"}
>
info
</Button>
<Button
variant="solid"
onClick={() => {
useToastStore.getState().add({
title: "Success Message",
description: "这是一个通知",
type: "success",
duration: 3000,
});
}}
color={"success"}
>
success
</Button>
<Button
variant="solid"
onClick={() => {
useToastStore.getState().add({
title: "Warning Message",
description: "这是一个通知",
type: "warning",
duration: 3000,
});
}}
color={"warning"}
>
warning
</Button>
<Button
variant="solid"
onClick={() => {
useToastStore.getState().add({
title: "Error Message",
description: "这是一个通知",
type: "error",
duration: 3000,
});
}}
color={"error"}
>
error
</Button>
</div>

<div
style={{
display: "flex",
Expand Down
22 changes: 22 additions & 0 deletions src/stores/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { User } from "@/models/user";
import { create } from "zustand";
import { createJSONStorage, persist } from "zustand/middleware";

interface AuthState {
user?: User;
setUser: (user?: User) => void;
clear: () => void;
}

export const useAuthStore = create<AuthState>()(
persist(
(set, get) => ({
setUser: (user?: User) => set({ user }),
clear: () => set({ user: undefined }),
}),
{
name: "auth",
storage: createJSONStorage(() => localStorage),
}
)
);
27 changes: 21 additions & 6 deletions src/stores/toast.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
import { Toast } from "@/types/toast";
import { create } from "zustand";
import { nanoid } from "nanoid";

interface ToastState {
toasts: any[];
addToast: (toast: any) => void;
removeToast: (id: string) => void;
toasts: Array<Toast>;
add: (toast: Toast) => void;
update: (id?: string, toast?: Toast) => void;
remove: (id?: string) => void;
}

export const useToastStore = create<ToastState>()((set) => ({
toasts: [],
addToast: (toast) =>
add: (toast) =>
set((state) => ({
toasts: [...state.toasts, { id: Date.now(), ...toast }],
toasts: [
...state.toasts,
{
id: toast.id || nanoid(),
...toast,
},
],
})),
removeToast: (id) =>
update: (id, toast) =>
set((state) => ({
toasts: state.toasts.map((t) =>
t.id === id ? { ...t, ...toast } : t
),
})),
remove: (id) =>
set((state) => ({
toasts: state.toasts.filter((toast) => toast.id !== id),
})),
Expand Down
4 changes: 2 additions & 2 deletions src/styles/_theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
--color-primary: #0d47a1;
--color-secondary: #eca758;
--color-info: #0ea5e9;
--color-success: #10b981;
--color-success: #28a745;
--color-warning: #fb923c;
--color-error: #ef4444;
--color-error: #dc3545;
}

:root[data-theme="light"] {
Expand Down
Loading

0 comments on commit b295fe5

Please sign in to comment.