App.tsx 5.73 KB
import { useCallback, useEffect, useState } from 'react';
import { Toaster, toast } from 'sonner';
import { Layout } from './components/layout/Layout';
import { Dashboard } from './components/dashboard/Dashboard';
import { PlaceholderView } from './components/PlaceholderView';

import { LabelsView } from './components/labels/LabelsView';
import { TrainingView } from './components/training/TrainingView';
import { AlertsView } from './components/alerts/AlertsView';
import { ProductsView } from './components/products/ProductsView';
import { PeopleView } from './components/people/PeopleView';
import { ReportsView } from './components/reports/ReportsView';
import { SystemMenuView } from './components/system-menu/SystemMenuView';
import { SupportView } from './components/support/SupportView';
import { AuthProvider, useAuth } from './components/auth/AuthProvider';
import { LoginView } from './components/auth/LoginView';

function AuthedApp() {
  const auth = useAuth();
  const [currentView, setCurrentView] = useState('Dashboard');
  /** 侧栏点「Location Manager」时打开 Account Management 并切到门店 Tab */
  const [pendingPeopleSubTab, setPendingPeopleSubTab] = useState<'Location Manager' | null>(null);
  /** Dashboard「View Reports」:与 reportsTargetTab 配合,仅在意图跳转时递增 */
  const [reportsOpenKey, setReportsOpenKey] = useState(0);
  const [reportsTargetTab, setReportsTargetTab] = useState<'print-log' | 'label-report'>('print-log');
  /** 标签模板编辑器全屏:Layout 隐藏侧栏/顶栏 */
  const [labelTemplateEditorFullscreen, setLabelTemplateEditorFullscreen] = useState(false);
  /** 顶栏点头像:打开 Account Management → Team Member 中当前用户编辑弹窗 */
  const [profileEditIntent, setProfileEditIntent] = useState<{ userId: string; nonce: number } | null>(null);
  const clearProfileEditIntent = useCallback(() => setProfileEditIntent(null), []);

  const resolveView = (name: string) => {
    const s = (name ?? "").trim();
    if (!s) return "Dashboard";
    // 后端菜单可能会返回更偏“模块名”的英文,这里做一次别名兼容
    if (s === "System Management") return "System Menu";
    if (s === "Location Management") return "Location Manager";
    if (s === "Account Manager") return "Account Management";
    if (s === "Multiple Options") return "Multiple Option Sets";
    return s;
  };

  const resolvedView = resolveView(currentView);

  const navigateToView = useCallback((view: string) => {
    const v = resolveView(view);
    if (v === 'Location Manager') {
      setPendingPeopleSubTab('Location Manager');
      setCurrentView('Account Management');
      return;
    }
    setCurrentView(v);
  }, []);

  const handleOpenMyProfileEditor = useCallback(() => {
    const id = (auth.user?.id ?? "").trim();
    if (!id) {
      toast.error("Profile unavailable", {
        description: "User information is still loading. Please try again in a moment.",
      });
      return;
    }
    setProfileEditIntent((prev) => ({
      userId: id,
      nonce: (prev?.nonce ?? 0) + 1,
    }));
    setPendingPeopleSubTab(null);
    navigateToView("Account Management");
  }, [auth.user, navigateToView]);

  useEffect(() => {
    if (resolvedView !== 'Reports') {
      setReportsOpenKey(0);
    }
    if (resolvedView !== 'Label Templates') {
      setLabelTemplateEditorFullscreen(false);
    }
  }, [resolvedView]);

  if (!auth.token) {
    return <LoginView />;
  }

  const renderView = () => {
    const view = resolvedView;
    switch (view) {
      case 'Dashboard':
        return (
          <Dashboard
            onViewReports={() => {
              setReportsTargetTab('label-report');
              setReportsOpenKey((k) => k + 1);
              setCurrentView('Reports');
            }}
            onViewAllRecentLabels={() => {
              setReportsTargetTab('print-log');
              setReportsOpenKey((k) => k + 1);
              setCurrentView('Reports');
            }}
          />
        );
      case 'Training':
        return <TrainingView />;
      case 'Alerts':
        return <AlertsView />;
      case 'Menu Management':
        // 还原:Menu Management 对应“商品管理/新增”页面
        return <ProductsView />;
      case 'System Menu':
        return <SystemMenuView />;
      case 'Account Management':
        return (
          <PeopleView
            initialSubTab={pendingPeopleSubTab}
            onInitialSubTabConsumed={() => setPendingPeopleSubTab(null)}
            profileEditIntent={profileEditIntent}
            onProfileEditIntentConsumed={clearProfileEditIntent}
          />
        );
      case 'Reports':
        return (
          <ReportsView layoutReportsOpenKey={reportsOpenKey} layoutReportsTargetTab={reportsTargetTab} />
        );
      case 'Support':
        return <SupportView />;
      case 'Labels':
      case 'Label Categories':
      case 'Label Types':
      case 'Label Templates':
      case 'Multiple Option Sets':
        return (
          <LabelsView
            currentView={view}
            onViewChange={setCurrentView}
            onLabelTemplateEditorLayoutOverlay={setLabelTemplateEditorFullscreen}
          />
        );
      default:
        return <PlaceholderView title={view} />;
    }
  };

  return (
    <>
      <Layout
        currentView={resolvedView}
        setCurrentView={navigateToView}
        menus={auth.menus}
        onLogout={auth.logout}
        onProfileClick={handleOpenMyProfileEditor}
        hideAppChrome={labelTemplateEditorFullscreen}
      >
        {renderView()}
      </Layout>
    </>
  );
}

export default function App() {
  return (
    <>
      <AuthProvider>
        <AuthedApp />
      </AuthProvider>
      <Toaster position="top-center" richColors closeButton expand={false} />
    </>
  );
}