feat(web): add authenticated app shell
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { useState } from 'react';
|
||||
|
||||
interface Props {
|
||||
locale: string;
|
||||
dashboard: { brandName: string; navHome: string; navStore: string; navDivination: string; navManual: string; navAuto: string; navHistory: string; navLanguage: string; navSettings: string; logout: string };
|
||||
history: { title: string; statTotal: string; statFollow: string; statLatest: string; filters: string; filterAll: string; filterCareer: string; filterLove: string; filterWealth: string; noResults: string };
|
||||
}
|
||||
|
||||
const MOCK_HISTORY = [
|
||||
{ id: 1, question: '今年转岗是否合适?', date: '2025-05-08', category: '事业', hexagram: '天雷无妄', rating: '上上签', followUp: false },
|
||||
{ id: 2, question: '最近感情是否能推进?', date: '2025-05-07', category: '感情', hexagram: '泽火革', rating: '中上签', followUp: true },
|
||||
{ id: 3, question: '投资理财近期运势如何?', date: '2025-05-05', category: '财富', hexagram: '水地比', rating: '中签', followUp: false },
|
||||
{ id: 4, question: '学业考试能否顺利通过?', date: '2025-05-03', category: '学业', hexagram: '山火贲', rating: '上签', followUp: true },
|
||||
];
|
||||
|
||||
const CATEGORY_COLORS: Record<string, string> = {
|
||||
'事业': 'bg-blue-50 text-blue-500', '感情': 'bg-pink-50 text-pink-500', '财富': 'bg-amber-50 text-amber-600', '学业': 'bg-green-50 text-green-600',
|
||||
};
|
||||
|
||||
export default function HistoryListPage({ locale, history: h }: Props) {
|
||||
const [selectedId, setSelectedId] = useState(1);
|
||||
const [filter, setFilter] = useState('all');
|
||||
|
||||
const filters = [
|
||||
{ id: 'all', label: h.filterAll },
|
||||
{ id: 'career', label: h.filterCareer },
|
||||
{ id: 'love', label: h.filterLove },
|
||||
{ id: 'wealth', label: h.filterWealth },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-5 min-h-full">
|
||||
{/* Stats */}
|
||||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||||
{[{ label: h.statTotal, value: '12' }, { label: h.statFollow, value: '3' }, { label: h.statLatest, value: '5/8' }].map((stat, i) => (
|
||||
<div key={i} className="bg-white rounded-xl p-4 border border-slate-200 flex flex-col gap-1.5">
|
||||
<p className="text-slate-400 text-xs">{stat.label}</p>
|
||||
<p className="text-slate-900 text-xl font-bold">{stat.value}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Main: List + Filters */}
|
||||
<div className="flex flex-col lg:flex-row gap-5 flex-1 min-h-0">
|
||||
<div className="flex-1 bg-white rounded-2xl p-[18px] border border-slate-200 flex flex-col gap-3 overflow-y-auto">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-slate-900 text-sm font-bold">{h.title}</h3>
|
||||
</div>
|
||||
{MOCK_HISTORY.map(item => (
|
||||
<a key={item.id} href={`/${locale}/history/${item.id}`}
|
||||
onClick={(e) => { e.preventDefault(); setSelectedId(item.id); }}
|
||||
className={`flex items-center gap-3.5 rounded-xl p-4 cursor-pointer transition-colors border ${selectedId === item.id ? 'bg-violet-50 border-violet-400' : 'bg-white border-slate-200 hover:bg-slate-50'}`}>
|
||||
<div className="w-10 h-10 rounded-[10px] bg-blue-50 flex items-center justify-center shrink-0">
|
||||
<span className="text-blue-400 text-lg">◇</span>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<p className="text-slate-900 text-sm font-medium truncate">{item.question}</p>
|
||||
<div className="flex items-center gap-2 mt-1">
|
||||
<span className={`px-2 py-0.5 rounded-md text-xs font-medium ${CATEGORY_COLORS[item.category] || 'bg-slate-100 text-slate-500'}`}>{item.category}</span>
|
||||
<span className="px-2 py-0.5 rounded-md bg-violet-50 text-violet-600 text-xs font-medium">{item.hexagram}</span>
|
||||
</div>
|
||||
</div>
|
||||
<span className="text-slate-400 text-xs shrink-0">{item.date}</span>
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* Side: Filters */}
|
||||
<div className="w-full lg:w-[300px] flex flex-col gap-4 shrink-0">
|
||||
<div className="bg-white rounded-2xl p-[18px] border border-slate-200 flex flex-col gap-2.5">
|
||||
<h3 className="text-slate-900 text-sm font-bold">{h.filters}</h3>
|
||||
{filters.map(f => (
|
||||
<button key={f.id} onClick={() => setFilter(f.id)}
|
||||
className={`px-3 py-2 rounded-lg text-sm text-left transition-colors ${filter === f.id ? 'bg-violet-50 text-violet-600 font-medium' : 'text-slate-500 hover:bg-slate-50'}`}>
|
||||
{f.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user