diff --git a/web/src/components/DashboardApp.tsx b/web/src/components/DashboardApp.tsx
index 9c43d15..c607fae 100644
--- a/web/src/components/DashboardApp.tsx
+++ b/web/src/components/DashboardApp.tsx
@@ -1,39 +1,27 @@
-import { useEffect } from 'react';
+import { lazy, Suspense, useEffect } from 'react';
import { BrowserRouter, Navigate, Route, Routes, useNavigate } from 'react-router-dom';
+import type { Locale, Translations } from '../i18n/utils';
import AppShell from './AppShell';
-import Dashboard from './Dashboard';
-import StorePage from './StorePage';
-import HistoryListPage from './HistoryListPage';
-import DivinationResultPage from './DivinationResultPage';
-import HistoryFollowUpPage from './HistoryFollowUpPage';
-import NotificationPage from './NotificationPage';
-import ProfileDetailPage from './ProfileDetailPage';
-import SettingsPage from './SettingsPage';
-import GeneralSettingsPage from './GeneralSettingsPage';
-import FeedbackPage from './FeedbackPage';
-import ManualDivinationPage from './ManualDivinationPage';
-import AutoDivinationPage from './AutoDivinationPage';
import { getNavConfig } from './navConfig';
-type TranslationMap = Record
;
-
interface DashboardAppProps {
- locale: string;
- translations: {
- dashboard: TranslationMap;
- store: TranslationMap;
- pricing: TranslationMap;
- history: TranslationMap;
- notifications: TranslationMap;
- profile: TranslationMap;
- settings: TranslationMap;
- divination: TranslationMap;
- general: TranslationMap;
- feedback: TranslationMap;
- result: TranslationMap;
- };
+ locale: Locale;
+ translations: Pick;
}
+const Dashboard = lazy(() => import('./Dashboard'));
+const StorePage = lazy(() => import('./StorePage'));
+const HistoryListPage = lazy(() => import('./HistoryListPage'));
+const DivinationResultPage = lazy(() => import('./DivinationResultPage'));
+const HistoryFollowUpPage = lazy(() => import('./HistoryFollowUpPage'));
+const NotificationPage = lazy(() => import('./NotificationPage'));
+const ProfileDetailPage = lazy(() => import('./ProfileDetailPage'));
+const SettingsPage = lazy(() => import('./SettingsPage'));
+const GeneralSettingsPage = lazy(() => import('./GeneralSettingsPage'));
+const FeedbackPage = lazy(() => import('./FeedbackPage'));
+const ManualDivinationPage = lazy(() => import('./ManualDivinationPage'));
+const AutoDivinationPage = lazy(() => import('./AutoDivinationPage'));
+
const APP_PATHS = [
'/dashboard',
'/store',
@@ -77,6 +65,14 @@ function AppLinkInterceptor({ locale }: { locale: string }) {
return null;
}
+function RouteFallback() {
+ return (
+
+ );
+}
+
function DashboardRoutes({ locale, translations }: DashboardAppProps) {
const dashboard = translations.dashboard;
const navItems = getNavConfig(locale, dashboard);
@@ -84,24 +80,26 @@ function DashboardRoutes({ locale, translations }: DashboardAppProps) {
return (
-
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
- } />
-
+ }>
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
);
}
diff --git a/web/src/components/DivinationResultPage.tsx b/web/src/components/DivinationResultPage.tsx
index d15272d..64dcfe9 100644
--- a/web/src/components/DivinationResultPage.tsx
+++ b/web/src/components/DivinationResultPage.tsx
@@ -1,5 +1,5 @@
import { useEffect, useState } from 'react';
-import { useLocation, useNavigate, useParams } from 'react-router-dom';
+import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom';
import { historyMessageToResultData, type DivinationResultData, type YaoType } from '../lib/api';
import { useHistoryThread } from '../lib/resources';
import Icon from './Icon';
@@ -339,7 +339,9 @@ const RESULT_STORAGE_KEY = 'divination_result_data';
export default function DivinationResultPage({ locale, translations: t }: Props) {
const location = useLocation();
const navigate = useNavigate();
- const { id: threadId } = useParams<{ id: string }>();
+ const { id: routeThreadId } = useParams<{ id: string }>();
+ const [searchParams] = useSearchParams();
+ const threadId = routeThreadId ?? searchParams.get('threadId') ?? undefined;
const threadState = useHistoryThread(threadId);
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
@@ -403,7 +405,7 @@ export default function DivinationResultPage({ locale, translations: t }: Props)
const handleFollowUp = () => {
const effectiveThreadId = data?.threadId || threadId;
if (effectiveThreadId) {
- navigate(`/${locale}/history/${effectiveThreadId}/followup`, { state: { result: data } });
+ navigate(`/${locale}/history/followup?threadId=${encodeURIComponent(effectiveThreadId)}`, { state: { result: data } });
}
};
diff --git a/web/src/components/FeedbackPage.tsx b/web/src/components/FeedbackPage.tsx
index 7e0c7d5..eebf398 100644
--- a/web/src/components/FeedbackPage.tsx
+++ b/web/src/components/FeedbackPage.tsx
@@ -2,7 +2,7 @@ import { useState, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import { authFetch } from '../lib/auth';
import { API_ROUTES } from '../lib/api-routes';
-import { apiUrl, jsonHeaders } from '../lib/api-client';
+import { apiUrl } from '../lib/api-client';
interface Props {
locale: string;
diff --git a/web/src/components/HistoryFollowUpPage.tsx b/web/src/components/HistoryFollowUpPage.tsx
index 135653b..6fd04e4 100644
--- a/web/src/components/HistoryFollowUpPage.tsx
+++ b/web/src/components/HistoryFollowUpPage.tsx
@@ -1,5 +1,5 @@
import { useState, useEffect, useRef, useCallback } from 'react';
-import { useLocation, useNavigate, useParams } from 'react-router-dom';
+import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom';
import {
historyMessageToResultData,
enqueueFollowUpRun,
@@ -63,7 +63,9 @@ const CATEGORY_COLORS: Record = {
export default function HistoryFollowUpPage({ locale, history: h }: Props) {
const location = useLocation();
const navigate = useNavigate();
- const { id: threadId } = useParams<{ id: string }>();
+ const { id: routeThreadId } = useParams<{ id: string }>();
+ const [searchParams] = useSearchParams();
+ const threadId = routeThreadId ?? searchParams.get('threadId') ?? undefined;
const [resultData, setResultData] = useState(null);
const [messages, setMessages] = useState([]);
@@ -373,7 +375,7 @@ export default function HistoryFollowUpPage({ locale, history: h }: Props) {
{h.relatedActions}