mirror of
https://github.com/zuiidea/antd-admin.git
synced 2026-10-19 16:14:37 +00:00
refactor(with-lingui): move theme and session, merge mock utils
- Theme hooks: tokenBuilders + useAppTheme under hooks; drop theme barrel - Session fetch helper under utils; update entry/login imports - Mock filter + avatar helpers in mocks/utils; avatars from API in UI - README tree updates Made-with: Cursor
This commit is contained in:
@@ -104,6 +104,8 @@ src/
|
||||
│ ├── UserMenu/ # User dropdown in sidebar: index.tsx + index.css
|
||||
│ └── Header/ # Top bar: index.tsx
|
||||
├── hooks/
|
||||
│ ├── tokenBuilders.ts # Shared Ant Design token/config builders
|
||||
│ ├── useAppTheme.ts # Theme selection hook (ConfigProvider)
|
||||
│ ├── usePermission.ts # Permission check hook
|
||||
│ └── useResourceCRUD.ts # Shared CRUD query/mutation wiring
|
||||
├── utils/
|
||||
@@ -116,7 +118,7 @@ src/
|
||||
│ ├── browser.ts # MSW worker setup
|
||||
│ ├── createHandler.ts # Shared MSW success/error/delay helpers
|
||||
│ ├── data.ts # Mock seed data (users, menus)
|
||||
│ ├── filterUtils.ts # Mock-only filtering and pagination helpers
|
||||
│ ├── utils.ts # Mock-only helpers (filters, pagination, demo avatar URLs)
|
||||
│ └── handlers/ # Request handlers (auth, user CRUD)
|
||||
├── routes/ # TanStack Router file-based routes
|
||||
│ ├── __root.tsx # Root layout (QueryClient, ConfigProvider, I18n)
|
||||
@@ -131,9 +133,6 @@ src/
|
||||
│ ├── auth.ts # Auth store (tokens, user, menus, permissions)
|
||||
│ ├── createPersistentStore.ts # Shared persisted-store factory
|
||||
│ └── settings.ts # Settings store (darkMode, locale, sidebar)
|
||||
├── theme/
|
||||
│ ├── tokenBuilders.ts # Shared Ant Design token/config builders
|
||||
│ └── useAppTheme.ts # Theme selection hook
|
||||
└── main.tsx # Entry point (MSW init → React render)
|
||||
|
||||
tests/
|
||||
|
||||
@@ -104,6 +104,8 @@ src/
|
||||
│ ├── UserMenu/ # User dropdown in sidebar: index.tsx + index.css
|
||||
│ └── Header/ # Top bar: index.tsx
|
||||
├── hooks/
|
||||
│ ├── tokenBuilders.ts # Shared Ant Design token/config builders
|
||||
│ ├── useAppTheme.ts # Theme selection hook (ConfigProvider)
|
||||
│ ├── usePermission.ts # Permission check hook
|
||||
│ └── useResourceCRUD.ts # Shared CRUD query/mutation wiring
|
||||
├── utils/
|
||||
@@ -116,7 +118,7 @@ src/
|
||||
│ ├── browser.ts # MSW worker setup
|
||||
│ ├── createHandler.ts # Shared MSW success/error/delay helpers
|
||||
│ ├── data.ts # Mock seed data (users, menus)
|
||||
│ ├── filterUtils.ts # Mock-only filtering and pagination helpers
|
||||
│ ├── utils.ts # Mock-only helpers (filters, pagination, demo avatar URLs)
|
||||
│ └── handlers/ # Request handlers (auth, user CRUD)
|
||||
├── routes/ # TanStack Router file-based routes
|
||||
│ ├── __root.tsx # Root layout (QueryClient, ConfigProvider, I18n)
|
||||
@@ -131,9 +133,6 @@ src/
|
||||
│ ├── auth.ts # Auth store (tokens, user, menus, permissions)
|
||||
│ ├── createPersistentStore.ts # Shared persisted-store factory
|
||||
│ └── settings.ts # Settings store (darkMode, locale, sidebar)
|
||||
├── theme/
|
||||
│ ├── tokenBuilders.ts # Shared Ant Design token/config builders
|
||||
│ └── useAppTheme.ts # Theme selection hook
|
||||
└── main.tsx # Entry point (MSW init → React render)
|
||||
|
||||
tests/
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Avatar, Button, Dropdown, Flex, Typography, theme } from "antd";
|
||||
import type { MenuProps } from "antd";
|
||||
import type { User } from "@/api/schemas";
|
||||
import { vercelAvatarUrl } from "@/utils/avatarUrl";
|
||||
import { MoreVertical } from "lucide-react";
|
||||
import "./index.css";
|
||||
|
||||
@@ -16,8 +15,7 @@ interface UserMenuProps {
|
||||
export function UserMenu({ collapsed, user, userMenuItems }: UserMenuProps) {
|
||||
const { token } = theme.useToken();
|
||||
|
||||
const avatarSrc =
|
||||
(user?.avatar ?? "").trim() || (user?.username ? vercelAvatarUrl(user.username) : undefined);
|
||||
const avatarSrc = (user?.avatar ?? "").trim() || undefined;
|
||||
const avatarSize = collapsed ? 32 : token.controlHeight;
|
||||
|
||||
const avatar = (
|
||||
|
||||
@@ -3,6 +3,10 @@ import type { ConfigProviderProps } from "antd";
|
||||
import { buildLightThemeConfig, buildDarkThemeConfig } from "./tokenBuilders";
|
||||
import { useSettingsStore } from "@/stores/settings";
|
||||
|
||||
/**
|
||||
* Theme selection for ConfigProvider: light/dark share radius, font, control tweaks.
|
||||
* @see https://ant.design/docs/react/customize-theme
|
||||
*/
|
||||
export function useAppTheme(): ConfigProviderProps {
|
||||
const darkMode = useSettingsStore((s) => s.darkMode);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { messages as enMessages } from "./locales/en/messages.po";
|
||||
import { messages as zhMessages } from "./locales/zh/messages.po";
|
||||
import { useSettingsStore } from "./stores/settings";
|
||||
import { useAuthStore } from "./stores/auth";
|
||||
import { fetchSessionAndApplyToStore } from "./auth/session";
|
||||
import { fetchSessionAndApplyToStore } from "./utils/session";
|
||||
|
||||
i18n.load("en", enMessages);
|
||||
i18n.load("zh", zhMessages);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { User } from "@/api/schemas";
|
||||
import { vercelAvatarUrl } from "@/utils/avatarUrl";
|
||||
import { vercelAvatarUrl } from "./utils";
|
||||
|
||||
/** Demo logins look like real org accounts (first.last @ northstar.io). Index 0 stays `admin` for mock login. */
|
||||
const MOCK_IDENTITIES: ReadonlyArray<[string, string]> = [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { http } from "msw";
|
||||
import { MOCK_USERS } from "../data";
|
||||
import { filterUsers, paginateList, parsePaginationParams } from "../filterUtils";
|
||||
import { filterUsers, paginateList, parsePaginationParams } from "../utils";
|
||||
import { withDelay, successResponse, errorResponse, ERROR_CODES } from "../createHandler";
|
||||
|
||||
let users = [...MOCK_USERS];
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
/**
|
||||
* Common filtering utilities for mock user handlers.
|
||||
* Mock-only helpers: demo avatars, list filtering, pagination.
|
||||
*/
|
||||
|
||||
/** Deterministic demo avatar URL from username (mock seed data only). */
|
||||
export function vercelAvatarUrl(username: string): string {
|
||||
return `https://vercel.com/api/www/avatar?u=${encodeURIComponent(username)}`;
|
||||
}
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
username: string;
|
||||
@@ -7,7 +7,7 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||
import { i18n } from "@lingui/core";
|
||||
import { I18nProvider } from "@lingui/react";
|
||||
import { useSettingsStore } from "@/stores/settings";
|
||||
import { useAppTheme } from "@/theme";
|
||||
import { useAppTheme } from "@/hooks/useAppTheme";
|
||||
import { NotFound } from "@/components/NotFound";
|
||||
import "@/index.css";
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ import { DataTable } from "@/components/DataTable";
|
||||
import { useResourceCRUD } from "@/hooks/useResourceCRUD";
|
||||
import { Toolbar } from "./-Toolbar";
|
||||
import { FormModal } from "./-FormModal";
|
||||
import { vercelAvatarUrl } from "@/utils/avatarUrl";
|
||||
|
||||
const UserSearchParamsSchema = z.object({
|
||||
limit: z.number().int().positive().catch(100),
|
||||
@@ -188,7 +187,7 @@ function UsersPage() {
|
||||
sorter: true,
|
||||
sortOrder: search.sortField === "username" ? search.sortOrder : null,
|
||||
render: (_: unknown, record: User) => {
|
||||
const src = record.avatar?.trim() || vercelAvatarUrl(record.username);
|
||||
const src = (record.avatar ?? "").trim() || undefined;
|
||||
return (
|
||||
<Flex align="center" gap={token.marginSM} style={{ minWidth: 0 }}>
|
||||
<Avatar size={24} src={src} shape="circle" style={{ flexShrink: 0 }}>
|
||||
|
||||
@@ -8,7 +8,7 @@ import { useAuthStore } from "@/stores/auth";
|
||||
import { useSettingsStore } from "@/stores/settings";
|
||||
import { AUTH_ENDPOINTS } from "@/api/auth";
|
||||
import { LoginRequestSchema, AuthTokensSchema } from "@/api/schemas";
|
||||
import { fetchSessionAndApplyToStore } from "@/auth/session";
|
||||
import { fetchSessionAndApplyToStore } from "@/utils/session";
|
||||
import type { LoginRequest } from "@/api/schemas";
|
||||
import { APP_BRAND_NAME, APP_FAVICON_SRC } from "@/utils/constants";
|
||||
import { Languages } from "lucide-react";
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* Theme entry: light/dark share radius, font, control tweaks; each sets primary/layout/border neutrals.
|
||||
* @see https://ant.design/docs/react/customize-theme
|
||||
*/
|
||||
export { useAppTheme } from "./useAppTheme";
|
||||
@@ -1,4 +0,0 @@
|
||||
/** Deterministic avatar image from username (Vercel avatar API). */
|
||||
export function vercelAvatarUrl(username: string): string {
|
||||
return `https://vercel.com/api/www/avatar?u=${encodeURIComponent(username)}`;
|
||||
}
|
||||
Reference in New Issue
Block a user