149 lines
4.0 KiB
TypeScript
149 lines
4.0 KiB
TypeScript
import { create } from "zustand"
|
|
import type { User, UserRole, VerificationStatus } from "@/lib/types"
|
|
|
|
interface NotificationPrefs {
|
|
order: boolean
|
|
community: boolean
|
|
system: boolean
|
|
}
|
|
|
|
const defaultNotificationPrefs: NotificationPrefs = {
|
|
order: true,
|
|
community: true,
|
|
system: false,
|
|
}
|
|
|
|
interface AuthState {
|
|
isAuthenticated: boolean
|
|
currentRole: UserRole
|
|
verifiedRoles: UserRole[]
|
|
verificationStatus: Partial<Record<UserRole, VerificationStatus>>
|
|
verificationReasons: Partial<Record<UserRole, string>>
|
|
notificationPrefs: NotificationPrefs
|
|
user: User | null
|
|
switchRole: (role: UserRole) => void
|
|
submitVerification: (role: UserRole) => void
|
|
approveVerification: (role: UserRole) => void
|
|
rejectVerification: (role: UserRole, reason: string) => void
|
|
setNotificationPref: (type: keyof NotificationPrefs, enabled: boolean) => void
|
|
updateProfile: (patch: { nickname?: string; bio?: string; avatar?: string }) => void
|
|
login: (user: User, verifiedRoles?: UserRole[]) => void
|
|
logout: () => void
|
|
}
|
|
|
|
export const useAuthStore = create<AuthState>((set, get) => ({
|
|
isAuthenticated: false,
|
|
currentRole: "consumer",
|
|
verifiedRoles: ["consumer"],
|
|
verificationStatus: { consumer: "approved" },
|
|
verificationReasons: {},
|
|
notificationPrefs: defaultNotificationPrefs,
|
|
user: null,
|
|
switchRole: (role) => {
|
|
const { verifiedRoles } = get()
|
|
if (verifiedRoles.includes(role)) {
|
|
set({ currentRole: role })
|
|
}
|
|
},
|
|
submitVerification: (role) =>
|
|
set((state) => {
|
|
if (state.verifiedRoles.includes(role)) {
|
|
return state
|
|
}
|
|
|
|
const nextReasons = { ...state.verificationReasons }
|
|
delete nextReasons[role]
|
|
|
|
return {
|
|
verificationStatus: {
|
|
...state.verificationStatus,
|
|
[role]: "pending",
|
|
},
|
|
verificationReasons: nextReasons,
|
|
}
|
|
}),
|
|
approveVerification: (role) =>
|
|
set((state) => {
|
|
if (state.verifiedRoles.includes(role) && state.verificationStatus[role] === "approved") {
|
|
return state
|
|
}
|
|
|
|
const nextReasons = { ...state.verificationReasons }
|
|
delete nextReasons[role]
|
|
|
|
return {
|
|
verifiedRoles: state.verifiedRoles.includes(role)
|
|
? state.verifiedRoles
|
|
: [...state.verifiedRoles, role],
|
|
verificationStatus: {
|
|
...state.verificationStatus,
|
|
[role]: "approved",
|
|
},
|
|
verificationReasons: nextReasons,
|
|
}
|
|
}),
|
|
rejectVerification: (role, reason) =>
|
|
set((state) => {
|
|
if (state.verifiedRoles.includes(role)) {
|
|
return state
|
|
}
|
|
|
|
return {
|
|
verificationStatus: {
|
|
...state.verificationStatus,
|
|
[role]: "rejected",
|
|
},
|
|
verificationReasons: {
|
|
...state.verificationReasons,
|
|
[role]: reason.trim() || "认证资料不完整,请补充后重试",
|
|
},
|
|
}
|
|
}),
|
|
setNotificationPref: (type, enabled) =>
|
|
set((state) => ({
|
|
notificationPrefs: {
|
|
...state.notificationPrefs,
|
|
[type]: enabled,
|
|
},
|
|
})),
|
|
updateProfile: (patch) =>
|
|
set((state) => {
|
|
if (!state.user) return state
|
|
|
|
return {
|
|
user: {
|
|
...state.user,
|
|
nickname: patch.nickname ?? state.user.nickname,
|
|
bio: patch.bio ?? state.user.bio,
|
|
avatar: patch.avatar ?? state.user.avatar,
|
|
},
|
|
}
|
|
}),
|
|
login: (user, verifiedRoles = ["consumer"]) =>
|
|
set((state) => ({
|
|
isAuthenticated: true,
|
|
user,
|
|
currentRole: user.role,
|
|
verifiedRoles,
|
|
verificationStatus: verifiedRoles.reduce<Partial<Record<UserRole, VerificationStatus>>>(
|
|
(acc, role) => {
|
|
acc[role] = "approved"
|
|
return acc
|
|
},
|
|
{},
|
|
),
|
|
verificationReasons: {},
|
|
notificationPrefs: state.notificationPrefs,
|
|
})),
|
|
logout: () =>
|
|
set({
|
|
isAuthenticated: false,
|
|
currentRole: "consumer",
|
|
verifiedRoles: ["consumer"],
|
|
verificationStatus: { consumer: "approved" },
|
|
verificationReasons: {},
|
|
notificationPrefs: defaultNotificationPrefs,
|
|
user: null,
|
|
}),
|
|
}))
|