dramaling-vocab-learning/docs/02_design/component-library/pages/dashboard.html

845 lines
24 KiB
HTML

<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>儀表板 - Drama Ling</title>
<link rel="stylesheet" href="../../design-system/tokens/design-tokens.css">
<link rel="stylesheet" href="../assets/styles/base.css">
<link rel="stylesheet" href="../assets/styles/components.css">
<style>
body {
background: var(--background-primary);
margin: 0;
padding: 0;
min-height: 100vh;
}
/* 布局容器 */
.dashboard-container {
display: grid;
grid-template-areas:
"sidebar header header"
"sidebar main stats"
"sidebar main activity";
grid-template-columns: 260px 1fr 320px;
grid-template-rows: auto 1fr auto;
min-height: 100vh;
gap: 0;
}
/* 頂部導航 */
.dashboard-header {
grid-area: header;
background: var(--background-secondary);
border-bottom: 1px solid var(--divider);
padding: var(--space-4) var(--space-6);
display: flex;
justify-content: space-between;
align-items: center;
}
.header-left {
display: flex;
align-items: center;
gap: var(--space-4);
}
.header-title {
font-size: var(--text-xl);
font-weight: 700;
color: var(--text-primary);
margin: 0;
}
.header-subtitle {
font-size: var(--text-sm);
color: var(--text-secondary);
}
.header-right {
display: flex;
align-items: center;
gap: var(--space-4);
}
.notification-icon {
position: relative;
padding: var(--space-2);
background: var(--card-background);
border-radius: var(--radius-full);
cursor: pointer;
transition: all 0.3s ease;
}
.notification-icon:hover {
background: var(--primary-teal);
color: var(--background-dark);
}
.notification-badge {
position: absolute;
top: -4px;
right: -4px;
background: var(--error-red);
color: white;
font-size: 10px;
font-weight: 700;
padding: 2px 6px;
border-radius: var(--radius-full);
}
/* 側邊欄 */
.dashboard-sidebar {
grid-area: sidebar;
background: var(--background-secondary);
border-right: 1px solid var(--divider);
padding: var(--space-6);
overflow-y: auto;
}
.sidebar-logo {
display: flex;
align-items: center;
gap: var(--space-3);
margin-bottom: var(--space-8);
font-size: var(--text-xl);
font-weight: 700;
color: var(--primary-teal);
}
.sidebar-nav {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.nav-item {
display: flex;
align-items: center;
gap: var(--space-3);
padding: var(--space-3) var(--space-4);
border-radius: var(--radius-lg);
color: var(--text-secondary);
text-decoration: none;
transition: all 0.3s ease;
font-size: var(--text-sm);
font-weight: 500;
}
.nav-item:hover {
background: var(--background-primary);
color: var(--text-primary);
transform: translateX(4px);
}
.nav-item.active {
background: linear-gradient(135deg, var(--primary-teal), var(--primary-teal-light));
color: var(--background-dark);
font-weight: 600;
}
/* 主要內容區 */
.dashboard-main {
grid-area: main;
padding: var(--space-6);
overflow-y: auto;
}
/* 歡迎區塊 */
.welcome-section {
background: linear-gradient(135deg, var(--primary-teal), var(--accent-violet));
border-radius: var(--radius-xl);
padding: var(--space-8);
margin-bottom: var(--space-6);
color: white;
position: relative;
overflow: hidden;
}
.welcome-section::before {
content: '🎭';
position: absolute;
right: var(--space-8);
top: 50%;
transform: translateY(-50%);
font-size: 80px;
opacity: 0.2;
}
.welcome-title {
font-size: var(--text-2xl);
font-weight: 700;
margin-bottom: var(--space-2);
}
.welcome-message {
font-size: var(--text-base);
opacity: 0.9;
margin-bottom: var(--space-6);
}
.streak-info {
display: flex;
align-items: center;
gap: var(--space-4);
font-size: var(--text-lg);
font-weight: 600;
}
.streak-number {
font-size: var(--text-3xl);
font-weight: 700;
}
/* 快速操作 */
.quick-actions {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: var(--space-4);
margin-bottom: var(--space-6);
}
.action-card {
background: var(--card-background);
border: 1px solid var(--divider);
border-radius: var(--radius-xl);
padding: var(--space-6);
text-align: center;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
color: var(--text-primary);
}
.action-card:hover {
transform: translateY(-4px);
box-shadow: 0 8px 32px rgba(0, 229, 204, 0.2);
border-color: var(--primary-teal);
}
.action-icon {
font-size: 48px;
margin-bottom: var(--space-3);
}
.action-title {
font-size: var(--text-base);
font-weight: 600;
margin-bottom: var(--space-1);
}
.action-desc {
font-size: var(--text-xs);
color: var(--text-secondary);
}
/* 學習進度 */
.progress-section {
margin-bottom: var(--space-6);
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: var(--space-4);
}
.section-title {
font-size: var(--text-lg);
font-weight: 700;
color: var(--text-primary);
}
.view-all {
color: var(--primary-teal);
text-decoration: none;
font-size: var(--text-sm);
font-weight: 500;
transition: color 0.2s ease;
}
.view-all:hover {
color: var(--primary-teal-light);
text-decoration: underline;
}
.progress-cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: var(--space-4);
}
/* 統計側邊欄 */
.dashboard-stats {
grid-area: stats;
background: var(--background-secondary);
border-left: 1px solid var(--divider);
padding: var(--space-6);
}
.stats-header {
font-size: var(--text-base);
font-weight: 700;
color: var(--text-primary);
margin-bottom: var(--space-4);
}
.stat-item {
background: var(--card-background);
border-radius: var(--radius-lg);
padding: var(--space-4);
margin-bottom: var(--space-3);
}
.stat-label {
font-size: var(--text-xs);
color: var(--text-tertiary);
margin-bottom: var(--space-1);
}
.stat-value {
font-size: var(--text-xl);
font-weight: 700;
color: var(--primary-teal);
}
.stat-change {
font-size: var(--text-xs);
color: var(--success-green);
margin-top: var(--space-1);
}
.stat-change.negative {
color: var(--error-red);
}
/* 活動記錄 */
.dashboard-activity {
grid-area: activity;
background: var(--background-secondary);
border-left: 1px solid var(--divider);
border-top: 1px solid var(--divider);
padding: var(--space-6);
max-height: 400px;
overflow-y: auto;
}
.activity-header {
font-size: var(--text-base);
font-weight: 700;
color: var(--text-primary);
margin-bottom: var(--space-4);
}
.activity-list {
display: flex;
flex-direction: column;
gap: var(--space-3);
}
.activity-item {
display: flex;
align-items: start;
gap: var(--space-3);
padding: var(--space-3);
background: var(--card-background);
border-radius: var(--radius-md);
font-size: var(--text-sm);
}
.activity-icon {
flex-shrink: 0;
width: 32px;
height: 32px;
background: linear-gradient(135deg, var(--primary-teal), var(--primary-teal-light));
border-radius: var(--radius-full);
display: flex;
align-items: center;
justify-content: center;
}
.activity-content {
flex: 1;
}
.activity-title {
color: var(--text-primary);
font-weight: 500;
margin-bottom: 2px;
}
.activity-time {
color: var(--text-tertiary);
font-size: var(--text-xs);
}
/* 成就展示 */
.achievements-showcase {
background: var(--card-background);
border-radius: var(--radius-xl);
padding: var(--space-6);
margin-bottom: var(--space-6);
}
.achievements-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
gap: var(--space-4);
margin-top: var(--space-4);
}
.achievement-item {
text-align: center;
cursor: pointer;
transition: transform 0.3s ease;
}
.achievement-item:hover {
transform: scale(1.1);
}
.achievement-badge-icon {
width: 60px;
height: 60px;
margin: 0 auto var(--space-2);
background: linear-gradient(135deg, var(--gold), var(--warning-yellow));
border-radius: var(--radius-full);
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
box-shadow: 0 4px 16px rgba(255, 215, 0, 0.3);
}
.achievement-badge-icon.locked {
background: var(--divider);
filter: grayscale(1);
opacity: 0.5;
}
.achievement-name {
font-size: var(--text-xs);
color: var(--text-secondary);
}
/* 響應式設計 */
@media (max-width: 1200px) {
.dashboard-container {
grid-template-areas:
"header header"
"sidebar main"
"sidebar stats"
"sidebar activity";
grid-template-columns: 220px 1fr;
}
.dashboard-stats,
.dashboard-activity {
border-left: none;
border-top: 1px solid var(--divider);
}
}
@media (max-width: 768px) {
.dashboard-container {
grid-template-areas:
"header"
"main"
"stats"
"activity";
grid-template-columns: 1fr;
}
.dashboard-sidebar {
display: none;
}
.quick-actions {
grid-template-columns: 1fr;
}
.progress-cards {
grid-template-columns: 1fr;
}
}
/* 動畫效果 */
@keyframes slideInFromTop {
from {
opacity: 0;
transform: translateY(-20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes slideInFromLeft {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
.welcome-section {
animation: slideInFromTop 0.6s ease-out;
}
.action-card {
animation: slideInFromTop 0.6s ease-out backwards;
}
.action-card:nth-child(1) { animation-delay: 0.1s; }
.action-card:nth-child(2) { animation-delay: 0.2s; }
.action-card:nth-child(3) { animation-delay: 0.3s; }
.action-card:nth-child(4) { animation-delay: 0.4s; }
.nav-item {
animation: slideInFromLeft 0.5s ease-out backwards;
}
.nav-item:nth-child(1) { animation-delay: 0.05s; }
.nav-item:nth-child(2) { animation-delay: 0.1s; }
.nav-item:nth-child(3) { animation-delay: 0.15s; }
.nav-item:nth-child(4) { animation-delay: 0.2s; }
.nav-item:nth-child(5) { animation-delay: 0.25s; }
.nav-item:nth-child(6) { animation-delay: 0.3s; }
</style>
</head>
<body>
<div class="dashboard-container">
<!-- 頂部導航 -->
<header class="dashboard-header">
<div class="header-left">
<div>
<h1 class="header-title">儀表板</h1>
<p class="header-subtitle">歡迎回來,讓我們繼續學習之旅!</p>
</div>
</div>
<div class="header-right">
<!-- 通知 -->
<div class="notification-icon">
<span>🔔</span>
<span class="notification-badge">3</span>
</div>
<!-- 用戶資料 -->
<div style="display: flex; align-items: center; gap: var(--space-3);">
<div style="text-align: right;">
<div style="font-size: var(--text-sm); font-weight: 600; color: var(--text-primary);">王小明</div>
<div style="font-size: var(--text-xs); color: var(--text-secondary);">Level 12</div>
</div>
<div style="width: 40px; height: 40px; background: linear-gradient(135deg, var(--primary-teal), var(--accent-violet)); border-radius: var(--radius-full); display: flex; align-items: center; justify-content: center; color: white; font-weight: 700;">
W
</div>
</div>
</div>
</header>
<!-- 側邊欄 -->
<aside class="dashboard-sidebar">
<div class="sidebar-logo">
<span>🎭</span>
<span>Drama Ling</span>
</div>
<nav class="sidebar-nav">
<a href="#" class="nav-item active">
<span>📊</span>
<span>儀表板</span>
</a>
<a href="#" class="nav-item">
<span>📚</span>
<span>學習中心</span>
</a>
<a href="#" class="nav-item">
<span>💬</span>
<span>對話練習</span>
</a>
<a href="#" class="nav-item">
<span>🎯</span>
<span>每日任務</span>
</a>
<a href="#" class="nav-item">
<span>🏆</span>
<span>成就</span>
</a>
<a href="#" class="nav-item">
<span>🛍️</span>
<span>道具商店</span>
</a>
<a href="#" class="nav-item">
<span>⚙️</span>
<span>設定</span>
</a>
</nav>
</aside>
<!-- 主要內容 -->
<main class="dashboard-main">
<!-- 歡迎區塊 -->
<div class="welcome-section">
<h2 class="welcome-title">歡迎回來,小明!🎉</h2>
<p class="welcome-message">你已經連續學習了 7 天,再堅持 3 天就能獲得「學習達人」成就!</p>
<div class="streak-info">
<span>🔥</span>
<span class="streak-number">7</span>
<span>天連續學習</span>
<button class="btn btn-secondary" style="margin-left: auto;">繼續學習</button>
</div>
</div>
<!-- 快速操作 -->
<div class="quick-actions">
<a href="#" class="action-card">
<div class="action-icon">📖</div>
<div class="action-title">繼續學習</div>
<div class="action-desc">Level 3 - 第5課</div>
</a>
<a href="#" class="action-card">
<div class="action-icon">🎯</div>
<div class="action-title">每日任務</div>
<div class="action-desc">2/5 已完成</div>
</a>
<a href="#" class="action-card">
<div class="action-icon">🔄</div>
<div class="action-title">複習</div>
<div class="action-desc">15個詞彙待複習</div>
</a>
<a href="#" class="action-card">
<div class="action-icon"></div>
<div class="action-title">限時挑戰</div>
<div class="action-desc">300秒對話挑戰</div>
</a>
</div>
<!-- 學習進度 -->
<div class="progress-section">
<div class="section-header">
<h3 class="section-title">學習進度</h3>
<a href="#" class="view-all">查看全部 →</a>
</div>
<div class="progress-cards">
<!-- 詞彙學習卡片 -->
<div class="card card-learning">
<div class="card-header">
<h3 class="card-title">詞彙學習</h3>
<div class="badge badge-level">Level 3</div>
</div>
<div class="card-body">
<p style="margin-bottom: var(--space-3);">今日新學: <strong>12個詞彙</strong></p>
<p style="margin-bottom: var(--space-4);">總掌握詞彙: <strong>245/500</strong></p>
<div class="progress">
<div class="progress-bar" style="width: 49%"></div>
</div>
<div style="display: flex; justify-content: space-between; margin-top: var(--space-2); font-size: var(--text-xs); color: var(--text-secondary);">
<span>49% 完成</span>
<span>255個待學習</span>
</div>
</div>
</div>
<!-- 口說練習卡片 -->
<div class="card card-learning">
<div class="card-header">
<h3 class="card-title">口說練習</h3>
<div class="badge badge-warning">需要練習</div>
</div>
<div class="card-body">
<p style="margin-bottom: var(--space-3);">本週練習: <strong>3次</strong></p>
<p style="margin-bottom: var(--space-4);">平均得分: <strong>85分</strong></p>
<div class="star-rating" style="margin-bottom: var(--space-3);">
<span class="star active"></span>
<span class="star active"></span>
<span class="star active"></span>
<span class="star active"></span>
<span class="star"></span>
</div>
<button class="btn btn-primary btn-sm" style="width: 100%;">開始練習</button>
</div>
</div>
<!-- 對話練習卡片 -->
<div class="card card-learning">
<div class="card-header">
<h3 class="card-title">對話練習</h3>
<div class="badge badge-success">表現優秀</div>
</div>
<div class="card-body">
<p style="margin-bottom: var(--space-3);">完成對話: <strong>28個</strong></p>
<p style="margin-bottom: var(--space-4);">連續正確: <strong>5個</strong></p>
<div class="life-bar" style="justify-content: center; margin-bottom: var(--space-3);">
<span class="life-heart">❤️</span>
<span class="life-heart">❤️</span>
<span class="life-heart">❤️</span>
<span class="life-heart">❤️</span>
<span class="life-heart empty">❤️</span>
</div>
<button class="btn btn-secondary btn-sm" style="width: 100%;">繼續對話</button>
</div>
</div>
</div>
</div>
<!-- 成就展示 -->
<div class="achievements-showcase">
<div class="section-header">
<h3 class="section-title">最近成就</h3>
<a href="#" class="view-all">查看全部 →</a>
</div>
<div class="achievements-grid">
<div class="achievement-item">
<div class="achievement-badge-icon">🏆</div>
<div class="achievement-name">新手上路</div>
</div>
<div class="achievement-item">
<div class="achievement-badge-icon">🔥</div>
<div class="achievement-name">連續7天</div>
</div>
<div class="achievement-item">
<div class="achievement-badge-icon">📚</div>
<div class="achievement-name">詞彙大師</div>
</div>
<div class="achievement-item">
<div class="achievement-badge-icon">💬</div>
<div class="achievement-name">對話達人</div>
</div>
<div class="achievement-item">
<div class="achievement-badge-icon locked">🎯</div>
<div class="achievement-name">完美通關</div>
</div>
<div class="achievement-item">
<div class="achievement-badge-icon locked"></div>
<div class="achievement-name">全五星</div>
</div>
</div>
</div>
</main>
<!-- 統計側邊欄 -->
<aside class="dashboard-stats">
<h3 class="stats-header">今日統計</h3>
<div class="stat-item">
<div class="stat-label">學習時間</div>
<div class="stat-value">45分鐘</div>
<div class="stat-change">▲ 比昨天多15分鐘</div>
</div>
<div class="stat-item">
<div class="stat-label">獲得經驗</div>
<div class="stat-value">280 XP</div>
<div class="stat-change">▲ 比平均高20%</div>
</div>
<div class="stat-item">
<div class="stat-label">正確率</div>
<div class="stat-value">92%</div>
<div class="stat-change negative">▼ 比昨天低3%</div>
</div>
<div class="stat-item">
<div class="stat-label">排名</div>
<div class="stat-value">#156</div>
<div class="stat-change">▲ 上升12名</div>
</div>
</aside>
<!-- 活動記錄 -->
<aside class="dashboard-activity">
<h3 class="activity-header">最近活動</h3>
<div class="activity-list">
<div class="activity-item">
<div class="activity-icon">📖</div>
<div class="activity-content">
<div class="activity-title">完成了「餐廳點餐」對話</div>
<div class="activity-time">5分鐘前</div>
</div>
</div>
<div class="activity-item">
<div class="activity-icon">🏆</div>
<div class="activity-content">
<div class="activity-title">獲得「連續7天」成就</div>
<div class="activity-time">1小時前</div>
</div>
</div>
<div class="activity-item">
<div class="activity-icon"></div>
<div class="activity-content">
<div class="activity-title">口說練習獲得4星評價</div>
<div class="activity-time">2小時前</div>
</div>
</div>
<div class="activity-item">
<div class="activity-icon">💎</div>
<div class="activity-content">
<div class="activity-title">購買了「發音助手」道具</div>
<div class="activity-time">今天早上</div>
</div>
</div>
<div class="activity-item">
<div class="activity-icon">📝</div>
<div class="activity-content">
<div class="activity-title">學習了15個新詞彙</div>
<div class="activity-time">昨天</div>
</div>
</div>
</div>
</aside>
</div>
<!-- 返回連結 -->
<a href="../index.html" style="position: fixed; bottom: 20px; right: 20px; background: var(--primary-teal); color: var(--background-dark); padding: var(--space-3) var(--space-4); border-radius: var(--radius-full); text-decoration: none; font-weight: 600; box-shadow: 0 4px 16px rgba(0, 229, 204, 0.3); z-index: 1000;">
← 返回元件庫
</a>
<script>
// 模擬數據更新
function updateStats() {
const xpValue = document.querySelector('.stat-value');
if (xpValue && xpValue.textContent.includes('XP')) {
const currentXP = parseInt(xpValue.textContent);
const newXP = currentXP + Math.floor(Math.random() * 10);
xpValue.textContent = newXP + ' XP';
}
}
// 模擬通知
function showNotification() {
const badge = document.querySelector('.notification-badge');
if (badge) {
const count = parseInt(badge.textContent);
badge.textContent = count + 1;
badge.style.animation = 'pulse 0.5s ease';
setTimeout(() => {
badge.style.animation = '';
}, 500);
}
}
// 定期更新(演示用)
// setInterval(updateStats, 5000);
// setTimeout(showNotification, 3000);
// 點擊動畫
document.querySelectorAll('.action-card, .achievement-item').forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
this.style.transform = 'scale(0.95)';
setTimeout(() => {
this.style.transform = '';
}, 200);
});
});
</script>
</body>
</html>