diff --git a/src/components/nav-sidebar/nav-breadcrumb.tsx b/src/components/nav-sidebar/nav-breadcrumb.tsx index 570f30b..ea5ae34 100644 --- a/src/components/nav-sidebar/nav-breadcrumb.tsx +++ b/src/components/nav-sidebar/nav-breadcrumb.tsx @@ -12,7 +12,7 @@ import { } from "@/components/ui/breadcrumb" import { useNavMenu } from "@/hooks/query/user-memu" import { cn } from "@/lib/utils" -import type { IMenu } from "@/models/menu" +import type { IMenu } from "@/schema/menu" interface Breadcrumb { title: I18nKeys diff --git a/src/components/nav-sidebar/nav-main.tsx b/src/components/nav-sidebar/nav-main.tsx index 928cfe7..dae05de 100644 --- a/src/components/nav-sidebar/nav-main.tsx +++ b/src/components/nav-sidebar/nav-main.tsx @@ -21,7 +21,7 @@ import { SidebarMenuSubButton, SidebarMenuSubItem, } from "@/components/ui/sidebar" -import type { IMenu } from "@/models/menu" +import type { IMenu } from "@/schema/menu" import { Button } from "../ui/button" diff --git a/src/hooks/query/use-album.ts b/src/hooks/query/use-album.ts index 97bfb0e..bde854d 100644 --- a/src/hooks/query/use-album.ts +++ b/src/hooks/query/use-album.ts @@ -1,7 +1,7 @@ import { useQuery } from "@tanstack/react-query" import { apiFetch } from "@/lib/api-fetch" -import type { IAlbum } from "@/models/album" +import type { IAlbum } from "@/schema/album" export function useAlbums() { return useQuery({ diff --git a/src/hooks/query/use-user.ts b/src/hooks/query/use-user.ts index 6e667cd..43da5af 100644 --- a/src/hooks/query/use-user.ts +++ b/src/hooks/query/use-user.ts @@ -9,7 +9,7 @@ import type { PaginationState } from "@tanstack/react-table" import { useNavigate } from "react-router-dom" import { apiFetch } from "@/lib/api-fetch" -import type { ILoginForm, IUserProfile, IUsers } from "@/models/user" +import type { ILoginForm, IUserProfile, IUsers } from "@/schema/user" export const queryUser = () => queryOptions({ queryKey: ["userInfo"], diff --git a/src/hooks/query/user-memu.ts b/src/hooks/query/user-memu.ts index 9063c59..7ca2086 100644 --- a/src/hooks/query/user-memu.ts +++ b/src/hooks/query/user-memu.ts @@ -22,7 +22,7 @@ import { Trash2, } from "lucide-react" -import type { IMenu } from "@/models/menu" +import type { IMenu } from "@/schema/menu" export const queryNavMenu = () => queryOptions({ queryKey: ["nav-menu"], diff --git a/src/lib/menu.ts b/src/lib/menu.ts index d0b6c4d..6cedef1 100644 --- a/src/lib/menu.ts +++ b/src/lib/menu.ts @@ -1,4 +1,4 @@ -import type { IMenu } from "@/models/menu" +import type { IMenu } from "@/schema/menu" export function findMenuTitleByPathname( menus: IMenu[], diff --git a/src/models/album.ts b/src/models/album.ts deleted file mode 100644 index 7dcddd8..0000000 --- a/src/models/album.ts +++ /dev/null @@ -1,9 +0,0 @@ -export interface IAlbum { - id: string - title: string - cover: string - url: string - slogan: string - updatedAt: Date - digitalDownloads: number -} diff --git a/src/models/menu.ts b/src/models/menu.ts deleted file mode 100644 index 9ed533c..0000000 --- a/src/models/menu.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { LucideIcon } from "lucide-react" - -export type MenuItem = { - title: I18nKeys - label?: I18nKeys - icon: LucideIcon - to: string - children?: IChildrenMenuItem[] -} - -interface IChildrenMenuItem { - title: I18nKeys - label?: I18nKeys - icon: LucideIcon - to: string -} -export type IMenu = MenuItem diff --git a/src/pages/(admin)/(with-layout)/list/basic-list.tsx b/src/pages/(admin)/(with-layout)/list/basic-list.tsx index d59fd66..5a59654 100644 --- a/src/pages/(admin)/(with-layout)/list/basic-list.tsx +++ b/src/pages/(admin)/(with-layout)/list/basic-list.tsx @@ -59,7 +59,7 @@ import { TableRow, } from "@/components/ui/table" import { useUsers } from "@/hooks/query/use-user" -import type { IUsers } from "@/models/user" +import type { IUsers } from "@/schema/user" import { ViewUser } from "./components/view-user" diff --git a/src/pages/(admin)/(with-layout)/list/components/album-card.tsx b/src/pages/(admin)/(with-layout)/list/components/album-card.tsx index 46f1bf9..aaf2a19 100644 --- a/src/pages/(admin)/(with-layout)/list/components/album-card.tsx +++ b/src/pages/(admin)/(with-layout)/list/components/album-card.tsx @@ -9,7 +9,7 @@ import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } import { Separator } from "@/components/ui/separator" import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip" import { cn } from "@/lib/utils" -import type { IAlbum } from "@/models/album" +import type { IAlbum } from "@/schema/album" export interface AlbumCardProps extends React.HTMLAttributes { album: IAlbum diff --git a/src/pages/(admin)/(with-layout)/list/components/view-user.tsx b/src/pages/(admin)/(with-layout)/list/components/view-user.tsx index e229897..0ebc042 100644 --- a/src/pages/(admin)/(with-layout)/list/components/view-user.tsx +++ b/src/pages/(admin)/(with-layout)/list/components/view-user.tsx @@ -30,8 +30,8 @@ import { SheetTrigger, } from "@/components/ui/sheet" import { toast } from "@/components/ui/use-toast" -import type { IUsers } from "@/models/user" -import { userRoles, userSchema } from "@/models/user" +import type { IUsers } from "@/schema/user" +import { userRoles, userSchema } from "@/schema/user" export function ViewUser({ user }: { user: IUsers }) { const form = useForm({ diff --git a/src/pages/(external)/login/index.tsx b/src/pages/(external)/login/index.tsx index cb42292..b5a4aa9 100644 --- a/src/pages/(external)/login/index.tsx +++ b/src/pages/(external)/login/index.tsx @@ -22,8 +22,8 @@ import { Input } from "@/components/ui/input" import { useUserLoginMutation } from "@/hooks/query/use-user" import { getFetchErrorMessage } from "@/lib/api-fetch" import { cn } from "@/lib/utils" -import type { ILoginForm } from "@/models/user" -import { loginFormSchema } from "@/models/user" +import type { ILoginForm } from "@/schema/user" +import { loginFormSchema } from "@/schema/user" export function Component() { const { t } = useTranslation("auth") diff --git a/src/schema/album.ts b/src/schema/album.ts new file mode 100644 index 0000000..6d7ceb1 --- /dev/null +++ b/src/schema/album.ts @@ -0,0 +1,13 @@ +import { z } from "zod" + +export const albumSchema = z.object({ + id: z.string(), + title: z.string(), + cover: z.string(), + url: z.string(), + slogan: z.string(), + updatedAt: z.date(), + digitalDownloads: z.number(), +}) + +export type IAlbum = z.infer diff --git a/src/schema/menu.ts b/src/schema/menu.ts new file mode 100644 index 0000000..833f502 --- /dev/null +++ b/src/schema/menu.ts @@ -0,0 +1,37 @@ +import type { LucideIcon } from "lucide-react" +import { z } from "zod" + +// 由于 LucideIcon 是一个类型,我们需要使用 custom 方法来验证 +const LucideIconSchema = z.custom( + (data) => { + return typeof data === "function" + }, + { + message: "Invalid Lucide icon", + }, +) + +// 子菜单项 Schema +export const ChildrenMenuItemSchema = z.object({ + title: z.string(), + label: z.string().optional(), + icon: LucideIconSchema, + to: z.string().url(), +}) + +// 菜单项 Schema +export const MenuItemSchema = z.object({ + title: z.string(), + label: z.string().optional(), + icon: LucideIconSchema, + to: z.string().url(), + children: z.array(ChildrenMenuItemSchema).optional(), +}) + +// 导出类型 +export type IChildrenMenuItem = z.infer +export type MenuItem = z.infer +export type IMenu = MenuItem + +// 如果需要验证菜单数组 +export const MenuArraySchema = z.array(MenuItemSchema) diff --git a/src/models/user.ts b/src/schema/user.ts similarity index 100% rename from src/models/user.ts rename to src/schema/user.ts