dramaling-app/apps/mobile/lib/features/learning/screens/home_screen.dart

285 lines
9.2 KiB
Dart
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.

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../../shared/providers/auth_provider.dart';
class HomeScreen extends ConsumerWidget {
const HomeScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final authState = ref.watch(authProvider);
return Scaffold(
appBar: AppBar(
title: const Text('Drama Ling'),
actions: [
IconButton(
icon: const Icon(Icons.person),
onPressed: () => context.go('/profile'),
),
],
),
body: SafeArea(
child: SingleChildScrollView(
padding: const EdgeInsets.all(24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Welcome Section
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Theme.of(context).colorScheme.primary,
Theme.of(context).colorScheme.primary.withOpacity(0.8),
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
borderRadius: BorderRadius.circular(16),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'歡迎回來,${authState.displayName ?? '學習者'}',
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 8),
Text(
'繼續您的語言學習之旅',
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: Colors.white.withOpacity(0.9),
),
),
const SizedBox(height: 16),
Row(
children: [
_buildStatCard('今日學習', '25分鐘', Icons.timer, context),
const SizedBox(width: 16),
_buildStatCard('連續天數', '7天', Icons.local_fire_department, context),
],
),
],
),
),
const SizedBox(height: 32),
// Learning Options
Text(
'選擇學習方式',
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
// Learning Cards
_buildLearningCard(
context,
'詞彙練習',
'學習新詞彙,擴充詞彙量',
Icons.book_outlined,
Colors.blue,
() => context.go('/vocabulary'),
),
const SizedBox(height: 16),
_buildLearningCard(
context,
'對話練習',
'AI互動對話提升口說能力',
Icons.chat_bubble_outline,
Colors.green,
() => context.go('/dialogue'),
),
const SizedBox(height: 16),
_buildLearningCard(
context,
'限時挑戰',
'測試反應速度和語言技能',
Icons.timer_outlined,
Colors.orange,
() => context.go('/challenge'),
),
const SizedBox(height: 32),
// Progress Section
Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(16),
boxShadow: [
BoxShadow(
color: Colors.black.withOpacity(0.05),
blurRadius: 10,
offset: const Offset(0, 2),
),
],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'學習進度',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 16),
_buildProgressItem('詞彙掌握', 0.7, '70%', context),
const SizedBox(height: 12),
_buildProgressItem('對話流暢度', 0.5, '50%', context),
const SizedBox(height: 12),
_buildProgressItem('聽力理解', 0.8, '80%', context),
],
),
),
],
),
),
),
);
}
Widget _buildStatCard(String title, String value, IconData icon, BuildContext context) {
return Expanded(
child: Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
borderRadius: BorderRadius.circular(12),
),
child: Column(
children: [
Icon(icon, color: Colors.white, size: 24),
const SizedBox(height: 4),
Text(
value,
style: const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
Text(
title,
style: TextStyle(
color: Colors.white.withOpacity(0.8),
fontSize: 12,
),
),
],
),
),
);
}
Widget _buildLearningCard(
BuildContext context,
String title,
String subtitle,
IconData icon,
Color color,
VoidCallback onTap,
) {
return Card(
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(16),
child: Container(
padding: const EdgeInsets.all(20),
child: Row(
children: [
Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: color.withOpacity(0.1),
borderRadius: BorderRadius.circular(12),
),
child: Icon(
icon,
color: color,
size: 28,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: Theme.of(context).textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold,
),
),
const SizedBox(height: 4),
Text(
subtitle,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.7),
),
),
],
),
),
Icon(
Icons.arrow_forward_ios,
color: Theme.of(context).colorScheme.onSurface.withOpacity(0.5),
size: 16,
),
],
),
),
),
);
}
Widget _buildProgressItem(String title, double progress, String percentage, BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w500,
),
),
Text(
percentage,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: Theme.of(context).colorScheme.primary,
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 8),
LinearProgressIndicator(
value: progress,
backgroundColor: Theme.of(context).colorScheme.primary.withOpacity(0.1),
valueColor: AlwaysStoppedAnimation<Color>(
Theme.of(context).colorScheme.primary,
),
),
],
);
}
}