feat: complete Simple Mode contextual routing and navigation state synchronization

This commit is contained in:
dwindown
2026-03-15 07:24:13 +07:00
parent faadc1865d
commit 25728583b3
21 changed files with 1095 additions and 320 deletions

View File

@@ -3,9 +3,11 @@ import 'package:go_router/go_router.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:intl/intl.dart';
import 'package:lucide_icons/lucide_icons.dart';
import '../../../app/theme/app_colors.dart';
import '../../../core/widgets/progress_bar.dart';
import '../../../data/local/hive_boxes.dart';
import '../../../data/local/models/app_settings.dart';
import '../../../data/local/models/daily_worship_log.dart';
import '../../../data/local/models/checklist_item.dart';
@@ -168,6 +170,31 @@ class _LaporanScreenState extends ConsumerState<LaporanScreen>
Widget build(BuildContext context) {
final theme = Theme.of(context);
final isDark = theme.brightness == Brightness.dark;
final settingsBox = Hive.box<AppSettings>(HiveBoxes.settings);
final isSimpleMode = settingsBox.get('default')?.simpleMode ?? false;
if (isSimpleMode) {
return Scaffold(
appBar: AppBar(
title: const Text('Riwayat Ibadah'),
centerTitle: false,
actions: [
IconButton(
onPressed: () {},
icon: const Icon(LucideIcons.bell),
),
IconButton(
onPressed: () => context.push('/settings'),
icon: const Icon(LucideIcons.settings),
),
const SizedBox(width: 8),
],
),
body: _buildRiwayatSimpel(context, isDark),
);
}
final weekData = _getWeeklyData();
final avgPercent = _weekAverage(weekData);
final insights = _getInsights();
@@ -179,11 +206,11 @@ class _LaporanScreenState extends ConsumerState<LaporanScreen>
actions: [
IconButton(
onPressed: () {},
icon: const Icon(Icons.notifications_outlined),
icon: const Icon(LucideIcons.bell),
),
IconButton(
onPressed: () => context.push('/settings'),
icon: const Icon(Icons.settings_outlined),
icon: const Icon(LucideIcons.settings),
),
const SizedBox(width: 8),
],
@@ -283,7 +310,7 @@ class _LaporanScreenState extends ConsumerState<LaporanScreen>
color: AppColors.primary.withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(10),
),
child: const Icon(Icons.stars,
child: const Icon(LucideIcons.star,
color: AppColors.primary, size: 18),
),
],
@@ -373,7 +400,7 @@ class _LaporanScreenState extends ConsumerState<LaporanScreen>
_insightCard(
context,
isDark,
icon: Icons.star,
icon: LucideIcons.star,
iconBg: AppColors.primary.withValues(alpha: 0.15),
iconColor: AppColors.primary,
label: 'PALING RAJIN',
@@ -386,7 +413,7 @@ class _LaporanScreenState extends ConsumerState<LaporanScreen>
_insightCard(
context,
isDark,
icon: Icons.trending_up,
icon: LucideIcons.trendingUp,
iconBg: const Color(0xFFFFF3E0),
iconColor: Colors.orange,
label: 'PERLU DITINGKATKAN',
@@ -520,21 +547,16 @@ class _LaporanScreenState extends ConsumerState<LaporanScreen>
);
}
Widget _buildComingSoon(BuildContext context, String period) {
Widget _buildComingSoon(BuildContext context, String title) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.bar_chart,
Icon(LucideIcons.barChart3,
size: 48, color: AppColors.primary.withValues(alpha: 0.3)),
const SizedBox(height: 12),
Text(
'Laporan $period',
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
),
const SizedBox(height: 4),
Text(
'Segera hadir',
'$title: Segera hadir',
style: TextStyle(
color: Theme.of(context).brightness == Brightness.dark
? AppColors.textSecondaryDark
@@ -544,6 +566,107 @@ class _LaporanScreenState extends ConsumerState<LaporanScreen>
),
);
}
Widget _buildRiwayatSimpel(BuildContext context, bool isDark) {
final logBox = Hive.box<DailyWorshipLog>(HiveBoxes.worshipLogs);
final now = DateTime.now();
final logs = <DailyWorshipLog>[];
// Fetch up to 14 days of history
for (int i = 0; i < 14; i++) {
final date = now.subtract(Duration(days: i));
final key = DateFormat('yyyy-MM-dd').format(date);
final log = logBox.get(key);
if (log != null && log.totalItems > 0 && log.completedCount > 0) {
logs.add(log);
}
}
if (logs.isEmpty) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(LucideIcons.history, size: 64, color: AppColors.sage.withValues(alpha: 0.5)),
const SizedBox(height: 16),
const Text('Belum ada riwayat ibadah', style: TextStyle(color: AppColors.sage)),
],
),
);
}
return ListView.separated(
padding: const EdgeInsets.all(16),
itemCount: logs.length,
separatorBuilder: (_, __) => const SizedBox(height: 12),
itemBuilder: (context, index) {
final log = logs[index];
final isToday = log.date == DateFormat('yyyy-MM-dd').format(now);
// Build summary text
final List<String> finished = [];
int fardhuCount = log.shalatLogs.values.where((l) => l.completed).length;
if (fardhuCount > 0) finished.add('$fardhuCount Fardhu');
if (log.tilawahLog?.isCompleted == true) finished.add('Tilawah');
if (log.dzikirLog != null) {
int d = 0;
if (log.dzikirLog!.pagi) d++;
if (log.dzikirLog!.petang) d++;
if (d > 0) finished.add('$d Dzikir');
}
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: isDark ? AppColors.surfaceDark : AppColors.surfaceLight,
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: isDark
? AppColors.primary.withValues(alpha: 0.1)
: AppColors.cream,
),
),
child: Row(
children: [
Container(
width: 48,
height: 48,
decoration: BoxDecoration(
color: AppColors.primary.withValues(alpha: 0.15),
borderRadius: BorderRadius.circular(12),
),
child: const Icon(LucideIcons.checkCircle2, color: AppColors.primary),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
isToday ? 'Hari Ini' : DateFormat('EEEE, d MMM yyyy').format(DateTime.parse(log.date)),
style: const TextStyle(
fontWeight: FontWeight.w700,
fontSize: 15,
),
),
const SizedBox(height: 4),
Text(
finished.isNotEmpty ? finished.join('') : 'Belum ada aktivitas',
style: TextStyle(
fontSize: 13,
color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight,
height: 1.4,
),
),
],
),
),
],
),
);
},
);
}
}
class _DayData {