ios-projects/react/src/pages/StudyHomePage.tsx
WangDL c10e299dc0 feat: add React UI prototype for iOS UX reference
- 22-page high-fidelity design gallery
- shadcn/ui + Tailwind CSS + Vite
- iPhone frame wrapper for realistic preview
- Bottom tab bar component
- All pages match ZhiXi app screens
2026-05-09 11:21:05 +08:00

231 lines
9.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Page 8: Study Workbench - 学习首页/学习工作台
import { PlayIcon, CheckCircleIcon, CircleIcon, FlameIcon, CalendarIcon } from 'lucide-react';
import BottomTabBar from '../components/BottomTabBar';
const todayTasks = [
{ title: '机器学习 - 回忆测试', type: '回忆测试', mins: 10, done: true, color: '#7C6EFA' },
{ title: '高数 - 间隔复习 8 题', type: '间隔复习', mins: 15, done: true, color: '#F97316' },
{ title: '英语词汇 - 25 个待复习', type: '词汇复习', mins: 8, done: false, color: '#2DD4BF' },
{ title: '注意力机制 - 费曼解释', type: '费曼练习', mins: 12, done: false, color: '#A78BFA' },
{ title: '产品设计 - 薄弱点复习', type: '薄弱点', mins: 10, done: false, color: '#F59E0B' },
];
const weekActivity = [0.3, 0.7, 1, 0.4, 0.9, 0.6, 0.2];
const weekDays = ['一', '二', '三', '四', '五', '六', '日'];
const StudyHomePage = () => {
const done = todayTasks.filter(t => t.done).length;
const total = todayTasks.length;
const progress = (done / total) * 100;
return (
<div
data-cmp="StudyHomePage"
className="absolute inset-0 flex flex-col"
style={{
background: '#0F0F1A',
paddingTop: '44px',
}}
>
{/* Header */}
<div className="flex items-center justify-between px-5 pt-4 pb-3">
<div>
<p style={{ fontSize: '12px', color: 'rgba(240,240,255,0.4)', fontWeight: '500' }}>116</p>
<h1 style={{ fontSize: '20px', fontWeight: '800', color: '#F0F0FF', letterSpacing: '-0.4px' }}></h1>
</div>
<div className="flex items-center gap-2 px-3 py-1.5"
style={{
background: 'rgba(249,115,22,0.15)',
border: '1px solid rgba(249,115,22,0.3)',
borderRadius: '20px',
}}
>
<FlameIcon size={14} style={{ color: '#F97316' }} />
<span style={{ fontSize: '13px', fontWeight: '700', color: '#F97316' }}>14 </span>
</div>
</div>
<div className="flex-1 overflow-y-auto px-5 pb-24">
{/* Today's progress card */}
<div
className="mb-5"
style={{
borderRadius: '20px',
background: 'linear-gradient(135deg, rgba(124,110,250,0.15) 0%, rgba(45,212,191,0.08) 100%)',
border: '1px solid rgba(124,110,250,0.2)',
padding: '16px',
}}
>
<div className="flex items-center justify-between mb-4">
<div>
<p style={{ fontSize: '13px', color: 'rgba(240,240,255,0.5)', fontWeight: '500' }}></p>
<p style={{ fontSize: '26px', fontWeight: '900', color: '#F0F0FF', letterSpacing: '-0.5px', marginTop: '2px' }}>
{done} / {total}
<span style={{ fontSize: '14px', fontWeight: '500', color: 'rgba(240,240,255,0.4)', marginLeft: '6px' }}></span>
</p>
</div>
<div
style={{
width: '64px', height: '64px',
borderRadius: '50%',
background: 'conic-gradient(#7C6EFA 0%, #7C6EFA ' + progress + '%, rgba(255,255,255,0.08) ' + progress + '%)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<div
style={{
width: '48px', height: '48px',
borderRadius: '50%',
background: '#12122A',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<span style={{ fontSize: '14px', fontWeight: '800', color: '#7C6EFA' }}>{Math.round(progress)}%</span>
</div>
</div>
</div>
{/* Progress bar */}
<div style={{ height: '6px', background: 'rgba(255,255,255,0.08)', borderRadius: '3px', overflow: 'hidden' }}>
<div
style={{
height: '100%',
width: `${progress}%`,
background: 'linear-gradient(90deg, #7C6EFA, #A78BFA)',
borderRadius: '3px',
}}
/>
</div>
{/* Stats */}
<div className="flex items-center gap-4 mt-4">
{[
{ label: '已学', value: `${done * 12} 分钟` },
{ label: '剩余', value: `${(total - done) * 11} 分钟` },
{ label: '掌握', value: '+5 点' },
].map((s, i) => (
<div key={i} className="flex flex-col">
<span style={{ fontSize: '13px', fontWeight: '700', color: '#F0F0FF' }}>{s.value}</span>
<span style={{ fontSize: '10px', color: 'rgba(240,240,255,0.4)' }}>{s.label}</span>
</div>
))}
</div>
</div>
{/* Today's tasks */}
<div className="mb-5">
<div className="flex items-center justify-between mb-3">
<h2 style={{ fontSize: '15px', fontWeight: '700', color: '#F0F0FF' }}></h2>
<div className="flex items-center gap-1">
<CalendarIcon size={12} style={{ color: 'rgba(240,240,255,0.4)' }} />
<span style={{ fontSize: '12px', color: 'rgba(240,240,255,0.4)' }}>AI </span>
</div>
</div>
<div className="flex flex-col gap-2.5">
{todayTasks.map((task, i) => (
<div
key={i}
className="flex items-center gap-3 px-4 py-3"
style={{
background: task.done ? 'rgba(255,255,255,0.03)' : 'rgba(255,255,255,0.05)',
border: `1px solid ${task.done ? 'rgba(255,255,255,0.05)' : 'rgba(255,255,255,0.08)'}`,
borderRadius: '14px',
opacity: task.done ? 0.6 : 1,
}}
>
{task.done
? <CheckCircleIcon size={20} style={{ color: '#34D399', flexShrink: 0 }} />
: <CircleIcon size={20} style={{ color: 'rgba(240,240,255,0.2)', flexShrink: 0 }} />
}
<div className="flex-1 min-w-0">
<p
style={{
fontSize: '13px',
fontWeight: '600',
color: task.done ? 'rgba(240,240,255,0.4)' : '#F0F0FF',
textDecoration: task.done ? 'line-through' : 'none',
}}
>
{task.title}
</p>
<div className="flex items-center gap-2 mt-1">
<span
style={{
fontSize: '10px',
fontWeight: '600',
color: task.color,
padding: '1px 6px',
background: `${task.color}22`,
borderRadius: '20px',
}}
>
{task.type}
</span>
<span style={{ fontSize: '10px', color: 'rgba(240,240,255,0.35)' }}> {task.mins} </span>
</div>
</div>
{!task.done && (
<div
style={{
width: '32px', height: '32px',
borderRadius: '10px',
background: `linear-gradient(135deg, ${task.color}, ${task.color}aa)`,
display: 'flex', alignItems: 'center', justifyContent: 'center',
flexShrink: 0,
}}
>
<PlayIcon size={14} style={{ color: 'white' }} />
</div>
)}
</div>
))}
</div>
</div>
{/* Weekly activity heatmap */}
<div>
<h2 style={{ fontSize: '15px', fontWeight: '700', color: '#F0F0FF', marginBottom: '14px' }}></h2>
<div className="flex items-end gap-2">
{weekActivity.map((val, i) => (
<div key={i} className="flex-1 flex flex-col items-center gap-2">
<div
style={{
width: '100%',
height: `${val * 60}px`,
background: i === 6 ? 'rgba(255,255,255,0.1)' : `rgba(124,110,250,${val * 0.9 + 0.1})`,
borderRadius: '6px',
minHeight: '8px',
transition: 'height 0.3s',
}}
/>
<span
style={{
fontSize: '10px',
color: i === 2 ? '#7C6EFA' : 'rgba(240,240,255,0.3)',
fontWeight: i === 2 ? '700' : '400',
}}
>
{weekDays[i]}
</span>
</div>
))}
</div>
<div className="flex items-center justify-between mt-3 px-1">
<span style={{ fontSize: '11px', color: 'rgba(240,240,255,0.3)' }}> 3.5 </span>
<span style={{ fontSize: '11px', color: 'rgba(240,240,255,0.3)' }}> 30 </span>
</div>
</div>
</div>
<BottomTabBar active="study" />
</div>
);
};
export default StudyHomePage;