m3mo 04863ff008 Add setup and onboarding screens
- Create SetupPage for choosing local or online mode
- Create OnboardingPage with 3-slide tutorial
- Explain Eisenhower Method and ALPEN planning approach
2026-02-03 14:21:58 +01:00

160 lines
4.9 KiB
Dart

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:provider/provider.dart';
import '../../../../l10n/app_localizations.dart';
import '../../../settings/domain/enums/app_mode.dart';
import '../../../settings/presentation/viewmodels/settings_viewmodel.dart';
class SetupPage extends StatelessWidget {
const SetupPage({super.key});
Future<void> _selectMode(BuildContext context, AppMode mode) async {
final settingsVm = context.read<SettingsViewModel>();
await settingsVm.setAppMode(mode);
await settingsVm.setSetupCompleted(true);
if (context.mounted) {
context.go('/onboarding');
}
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final theme = Theme.of(context);
return Scaffold(
body: SafeArea(
child: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.all(24),
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 400),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Icon(
Icons.task_alt,
size: 80,
color: theme.colorScheme.primary,
),
const SizedBox(height: 24),
Text(
l10n.setupTitle,
style: theme.textTheme.headlineMedium?.copyWith(
fontWeight: FontWeight.bold,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 8),
Text(
l10n.setupSubtitle,
style: theme.textTheme.bodyLarge?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 48),
_ModeCard(
icon: Icons.smartphone,
title: l10n.useLocally,
description: l10n.useLocallyDesc,
onTap: () => _selectMode(context, AppMode.local),
),
const SizedBox(height: 16),
_ModeCard(
icon: Icons.cloud_sync,
title: l10n.syncOnline,
description: l10n.syncOnlineDesc,
onTap: () => _selectMode(context, AppMode.online),
),
],
),
),
),
),
),
);
}
}
class _ModeCard extends StatelessWidget {
final IconData icon;
final String title;
final String description;
final VoidCallback onTap;
const _ModeCard({
required this.icon,
required this.title,
required this.description,
required this.onTap,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Card(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
side: BorderSide(
color: theme.colorScheme.outlineVariant,
),
),
child: InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(16),
child: Padding(
padding: const EdgeInsets.all(20),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: theme.colorScheme.primaryContainer,
borderRadius: BorderRadius.circular(12),
),
child: Icon(
icon,
size: 28,
color: theme.colorScheme.onPrimaryContainer,
),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 4),
Text(
description,
style: theme.textTheme.bodyMedium?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
],
),
),
Icon(
Icons.arrow_forward_ios,
size: 16,
color: theme.colorScheme.onSurfaceVariant,
),
],
),
),
),
);
}
}