feat(app): add error/loading boundaries and update dashboard routes
- Add error.tsx and loading.tsx boundaries for admin, parent, student, teacher routes - Add dashboard-error-fallback and dashboard-loading-skeleton components - Add student/learning page, parent/leave routes, teacher textbook components - Update existing app routes across auth, dashboard, and API endpoints - Update proxy middleware and next-auth type declarations
This commit is contained in:
@@ -1,16 +1,18 @@
|
||||
import { redirect } from "next/navigation"
|
||||
import { getTranslations } from "next-intl/server"
|
||||
import { headers } from "next/headers"
|
||||
|
||||
import { requireAuth } from "@/shared/lib/auth-guard"
|
||||
import { SettingsView } from "@/modules/settings/components/settings-view"
|
||||
import { SettingsServiceProvider } from "@/modules/settings/components/settings-service-context"
|
||||
import { resolveRoleSettingsConfig } from "@/modules/settings/config/role-settings-config"
|
||||
import type { SettingsService } from "@/modules/settings/types"
|
||||
import {
|
||||
updateProfileAction,
|
||||
updateNotificationPreferencesAction,
|
||||
} from "@/modules/settings/actions-service"
|
||||
import { getUserProfile } from "@/modules/users/data-access"
|
||||
import { updateUserProfile } from "@/modules/users/actions"
|
||||
import { getNotificationPreferences } from "@/modules/notifications/preferences"
|
||||
import { updateNotificationPreferencesAction } from "@/modules/messaging/actions"
|
||||
import type { UpdateNotificationPreferencesInput } from "@/modules/notifications/types"
|
||||
|
||||
export const dynamic = "force-dynamic"
|
||||
|
||||
@@ -18,32 +20,6 @@ export const metadata = {
|
||||
title: "Settings",
|
||||
}
|
||||
|
||||
/**
|
||||
* 将通知偏好输入对象转换为 FormData,适配 updateNotificationPreferencesAction 的签名。
|
||||
* Action 内部通过 formData.get(key) === "on" 解析布尔值。
|
||||
*/
|
||||
function buildNotificationFormData(input: UpdateNotificationPreferencesInput): FormData {
|
||||
const formData = new FormData()
|
||||
const booleanFields: Array<keyof UpdateNotificationPreferencesInput> = [
|
||||
"emailEnabled",
|
||||
"smsEnabled",
|
||||
"pushEnabled",
|
||||
"homeworkNotifications",
|
||||
"gradeNotifications",
|
||||
"announcementNotifications",
|
||||
"messageNotifications",
|
||||
"attendanceNotifications",
|
||||
"quietHoursEnabled",
|
||||
]
|
||||
for (const field of booleanFields) {
|
||||
const value = input[field]
|
||||
if (value === true) formData.set(field, "on")
|
||||
}
|
||||
if (input.quietHoursStart) formData.set("quietHoursStart", input.quietHoursStart)
|
||||
if (input.quietHoursEnd) formData.set("quietHoursEnd", input.quietHoursEnd)
|
||||
return formData
|
||||
}
|
||||
|
||||
export default async function SettingsPage() {
|
||||
const ctx = await requireAuth()
|
||||
|
||||
@@ -56,22 +32,23 @@ export default async function SettingsPage() {
|
||||
const notificationPrefs = await getNotificationPreferences(userId)
|
||||
const t = await getTranslations("settings")
|
||||
|
||||
// 获取当前请求的 User-Agent,用于安全中心标记当前会话
|
||||
const headerList = await headers()
|
||||
const currentUserAgent = headerList.get("user-agent") ?? ""
|
||||
|
||||
const config = resolveRoleSettingsConfig(roles)
|
||||
const description = t(config?.descriptionKey ?? "title")
|
||||
const backHref = config?.backHref ?? "/dashboard"
|
||||
const generalExtra = config?.generalExtra
|
||||
|
||||
// 构建 SettingsService 实现,注入到 SettingsServiceProvider
|
||||
// 组件层通过 useSettingsService() 消费,不直接 import users/messaging actions
|
||||
// 构建 SettingsService:仅传递 Server Action 引用
|
||||
// (Next.js 要求传递给 Client Component 的函数必须是 "use server" 标记的 Server Action)
|
||||
const service: SettingsService = {
|
||||
profile: {
|
||||
getProfile: async () => getUserProfile(userId),
|
||||
updateProfile: async (input) => updateUserProfile(input),
|
||||
updateProfile: updateProfileAction,
|
||||
},
|
||||
notifications: {
|
||||
getPreferences: async () => getNotificationPreferences(userId),
|
||||
updatePreferences: async (input) =>
|
||||
updateNotificationPreferencesAction(null, buildNotificationFormData(input)),
|
||||
updatePreferences: updateNotificationPreferencesAction,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -83,6 +60,7 @@ export default async function SettingsPage() {
|
||||
user={userProfile}
|
||||
notificationPreferences={notificationPrefs}
|
||||
generalExtra={generalExtra}
|
||||
currentUserAgent={currentUserAgent}
|
||||
/>
|
||||
</SettingsServiceProvider>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user