Your Name 964797d2e9 feat: 完善品牌方和代理商前端功能
品牌方功能:
- 项目看板: 添加截止日期编辑功能
- 项目详情: 添加代理商管理、截止日期编辑、最近任务显示代理商
- 项目创建: 代理商选择支持搜索(名称/ID/公司名)
- 代理商管理: 通过ID邀请、添加备注/分配项目/移除操作
- Brief配置: 新增项目级Brief和规则配置页面
- 系统设置: 完善账户安全(密码/2FA/邮箱/手机/设备管理)、数据导出、退出登录

代理商功能:
- 个人中心: 新增代理商ID展示、公司信息(企业验证)、个人信息编辑
- 账户设置: 密码修改、手机/邮箱绑定、两步验证
- 通知设置: 分类型和渠道的通知开关
- 审核历史: 搜索筛选和统计展示
- 帮助反馈: FAQ分类搜索和客服联系

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 17:40:11 +08:00

245 lines
7.6 KiB
TypeScript

'use client'
import { useState } from 'react'
import { useRouter } from 'next/navigation'
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card'
import { Button } from '@/components/ui/Button'
import {
ArrowLeft,
BellRing,
MessageSquare,
Mail,
Smartphone,
FileText,
Users,
AlertTriangle
} from 'lucide-react'
// 通知设置类型
interface NotificationSetting {
id: string
icon: React.ElementType
iconColor: string
title: string
description: string
email: boolean
push: boolean
sms: boolean
}
// 通知设置数据
const initialSettings: NotificationSetting[] = [
{
id: 'review',
icon: FileText,
iconColor: 'text-accent-indigo',
title: '审核任务通知',
description: '有新任务待审核时通知',
email: true,
push: true,
sms: false,
},
{
id: 'appeal',
icon: MessageSquare,
iconColor: 'text-accent-amber',
title: '申诉通知',
description: '达人提交申诉时通知',
email: true,
push: true,
sms: true,
},
{
id: 'creator',
icon: Users,
iconColor: 'text-accent-green',
title: '达人动态',
description: '达人提交内容、完成任务时通知',
email: false,
push: true,
sms: false,
},
{
id: 'urgent',
icon: AlertTriangle,
iconColor: 'text-accent-coral',
title: '紧急通知',
description: '任务即将超时、品牌方催促等',
email: true,
push: true,
sms: true,
},
{
id: 'system',
icon: BellRing,
iconColor: 'text-accent-blue',
title: '系统通知',
description: '系统更新、维护公告等',
email: true,
push: false,
sms: false,
},
]
// 开关组件
function Toggle({ checked, onChange }: { checked: boolean; onChange: (checked: boolean) => void }) {
return (
<button
type="button"
onClick={() => onChange(!checked)}
className={`relative w-11 h-6 rounded-full transition-colors ${
checked ? 'bg-accent-indigo' : 'bg-bg-elevated'
}`}
>
<span
className={`absolute top-1 w-4 h-4 rounded-full bg-white shadow transition-transform ${
checked ? 'left-6' : 'left-1'
}`}
/>
</button>
)
}
export default function AgencyNotificationSettingsPage() {
const router = useRouter()
const [settings, setSettings] = useState(initialSettings)
const [isSaving, setIsSaving] = useState(false)
const updateSetting = (id: string, field: 'email' | 'push' | 'sms', value: boolean) => {
setSettings(prev =>
prev.map(s =>
s.id === id ? { ...s, [field]: value } : s
)
)
}
const handleSave = async () => {
setIsSaving(true)
await new Promise(resolve => setTimeout(resolve, 1000))
setIsSaving(false)
alert('通知设置已保存')
}
return (
<div className="space-y-6">
{/* 顶部导航 */}
<div className="flex items-center justify-between">
<div className="flex items-center gap-4">
<button
type="button"
onClick={() => router.back()}
className="p-2 rounded-lg hover:bg-bg-elevated transition-colors"
>
<ArrowLeft size={20} className="text-text-secondary" />
</button>
<div>
<h1 className="text-2xl font-bold text-text-primary"></h1>
<p className="text-sm text-text-secondary mt-0.5"></p>
</div>
</div>
<Button variant="primary" onClick={handleSave} disabled={isSaving}>
{isSaving ? '保存中...' : '保存设置'}
</Button>
</div>
{/* 通知渠道说明 */}
<div className="flex gap-6 p-4 rounded-xl bg-bg-elevated">
<div className="flex items-center gap-2">
<div className="w-8 h-8 rounded-lg bg-accent-indigo/15 flex items-center justify-center">
<BellRing size={16} className="text-accent-indigo" />
</div>
<span className="text-sm text-text-secondary">App推送</span>
</div>
<div className="flex items-center gap-2">
<div className="w-8 h-8 rounded-lg bg-accent-blue/15 flex items-center justify-center">
<Mail size={16} className="text-accent-blue" />
</div>
<span className="text-sm text-text-secondary"></span>
</div>
<div className="flex items-center gap-2">
<div className="w-8 h-8 rounded-lg bg-accent-green/15 flex items-center justify-center">
<Smartphone size={16} className="text-accent-green" />
</div>
<span className="text-sm text-text-secondary"></span>
</div>
</div>
{/* 通知设置列表 */}
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<BellRing size={18} className="text-accent-indigo" />
</CardTitle>
</CardHeader>
<CardContent className="space-y-1">
{/* 表头 */}
<div className="flex items-center py-3 px-4 text-sm text-text-tertiary border-b border-border-subtle">
<div className="flex-1"></div>
<div className="w-20 text-center">App推送</div>
<div className="w-20 text-center"></div>
<div className="w-20 text-center"></div>
</div>
{/* 设置项 */}
{settings.map((setting) => {
const Icon = setting.icon
return (
<div
key={setting.id}
className="flex items-center py-4 px-4 hover:bg-bg-elevated/50 rounded-lg transition-colors"
>
<div className="flex-1 flex items-center gap-3">
<div className={`w-10 h-10 rounded-lg bg-opacity-15 flex items-center justify-center`}
style={{ backgroundColor: `${setting.iconColor.replace('text-', '')}15` }}
>
<Icon size={20} className={setting.iconColor} />
</div>
<div>
<p className="font-medium text-text-primary">{setting.title}</p>
<p className="text-sm text-text-tertiary">{setting.description}</p>
</div>
</div>
<div className="w-20 flex justify-center">
<Toggle
checked={setting.push}
onChange={(v) => updateSetting(setting.id, 'push', v)}
/>
</div>
<div className="w-20 flex justify-center">
<Toggle
checked={setting.email}
onChange={(v) => updateSetting(setting.id, 'email', v)}
/>
</div>
<div className="w-20 flex justify-center">
<Toggle
checked={setting.sms}
onChange={(v) => updateSetting(setting.id, 'sms', v)}
/>
</div>
</div>
)
})}
</CardContent>
</Card>
{/* 免打扰设置 */}
<Card>
<CardHeader>
<CardTitle></CardTitle>
</CardHeader>
<CardContent>
<div className="flex items-center justify-between p-4 rounded-xl bg-bg-elevated">
<div>
<p className="font-medium text-text-primary"></p>
<p className="text-sm text-text-tertiary">22:00 - 08:00 </p>
</div>
<Toggle checked={true} onChange={() => {}} />
</div>
</CardContent>
</Card>
</div>
)
}