Polish navigation, Quran flows, and sharing UX
This commit is contained in:
@@ -5,6 +5,7 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:lucide_icons/lucide_icons.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import '../../../app/theme/app_colors.dart';
|
||||
import '../../../core/widgets/notification_bell_button.dart';
|
||||
import '../../../core/widgets/progress_bar.dart';
|
||||
import '../../../data/local/hive_boxes.dart';
|
||||
import '../../../data/local/models/app_settings.dart';
|
||||
@@ -27,7 +28,13 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
late Box<AppSettings> _settingsBox;
|
||||
late AppSettings _settings;
|
||||
|
||||
final List<String> _fardhuPrayers = ['Subuh', 'Dzuhur', 'Ashar', 'Maghrib', 'Isya'];
|
||||
final List<String> _fardhuPrayers = [
|
||||
'Subuh',
|
||||
'Dzuhur',
|
||||
'Ashar',
|
||||
'Maghrib',
|
||||
'Isya'
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -45,7 +52,7 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
for (final p in _fardhuPrayers) {
|
||||
shalatLogs[p.toLowerCase()] = ShalatLog();
|
||||
}
|
||||
|
||||
|
||||
_logBox.put(
|
||||
_todayKey,
|
||||
DailyWorshipLog(
|
||||
@@ -69,7 +76,8 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
final log = _todayLog;
|
||||
|
||||
// Lazily attach Dzikir and Puasa if user toggles them mid-day
|
||||
if (_settings.trackDzikir && log.dzikirLog == null) log.dzikirLog = DzikirLog();
|
||||
if (_settings.trackDzikir && log.dzikirLog == null)
|
||||
log.dzikirLog = DzikirLog();
|
||||
if (_settings.trackPuasa && log.puasaLog == null) log.puasaLog = PuasaLog();
|
||||
|
||||
int total = 0;
|
||||
@@ -155,17 +163,16 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
Text(
|
||||
DateFormat('EEEE, d MMM yyyy').format(DateTime.now()),
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight,
|
||||
color: isDark
|
||||
? AppColors.textSecondaryDark
|
||||
: AppColors.textSecondaryLight,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
centerTitle: false,
|
||||
actions: [
|
||||
IconButton(
|
||||
onPressed: () {},
|
||||
icon: const Icon(LucideIcons.bell),
|
||||
),
|
||||
const NotificationBellButton(),
|
||||
IconButton(
|
||||
onPressed: () => context.push('/settings'),
|
||||
icon: const Icon(LucideIcons.settings),
|
||||
@@ -246,14 +253,16 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 12, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.primary.withValues(alpha: 0.15),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(LucideIcons.star, color: AppColors.primary, size: 14),
|
||||
const Icon(LucideIcons.star,
|
||||
color: AppColors.primary, size: 14),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
'${log.totalPoints} pts',
|
||||
@@ -334,7 +343,9 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
border: Border.all(
|
||||
color: isCompleted
|
||||
? AppColors.primary.withValues(alpha: 0.3)
|
||||
: (isDark ? AppColors.primary.withValues(alpha: 0.08) : AppColors.cream),
|
||||
: (isDark
|
||||
? AppColors.primary.withValues(alpha: 0.08)
|
||||
: AppColors.cream),
|
||||
),
|
||||
),
|
||||
child: Theme(
|
||||
@@ -347,10 +358,14 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
decoration: BoxDecoration(
|
||||
color: isCompleted
|
||||
? AppColors.primary.withValues(alpha: 0.15)
|
||||
: (isDark ? AppColors.primary.withValues(alpha: 0.08) : AppColors.cream.withValues(alpha: 0.5)),
|
||||
: (isDark
|
||||
? AppColors.primary.withValues(alpha: 0.08)
|
||||
: AppColors.cream.withValues(alpha: 0.5)),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Icon(LucideIcons.building, size: 22, color: isCompleted ? AppColors.primary : AppColors.sage),
|
||||
child: Icon(LucideIcons.building,
|
||||
size: 22,
|
||||
color: isCompleted ? AppColors.primary : AppColors.sage),
|
||||
),
|
||||
title: Text(
|
||||
'Sholat $prayerName',
|
||||
@@ -362,7 +377,9 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
),
|
||||
),
|
||||
subtitle: log.location != null
|
||||
? Text('Di ${log.location}', style: const TextStyle(fontSize: 12, color: AppColors.primary))
|
||||
? Text('Di ${log.location}',
|
||||
style:
|
||||
const TextStyle(fontSize: 12, color: AppColors.primary))
|
||||
: null,
|
||||
trailing: _CustomCheckbox(
|
||||
value: isCompleted,
|
||||
@@ -371,14 +388,17 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
_recalculateProgress();
|
||||
},
|
||||
),
|
||||
childrenPadding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
|
||||
childrenPadding:
|
||||
const EdgeInsets.only(left: 16, right: 16, bottom: 16),
|
||||
children: [
|
||||
const Divider(),
|
||||
const SizedBox(height: 8),
|
||||
// Location Radio
|
||||
Row(
|
||||
children: [
|
||||
const Text('Pelaksanaan:', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600)),
|
||||
const Text('Pelaksanaan:',
|
||||
style:
|
||||
TextStyle(fontSize: 13, fontWeight: FontWeight.w600)),
|
||||
const SizedBox(width: 16),
|
||||
_radioOption('Masjid', log, () {
|
||||
log.location = 'Masjid';
|
||||
@@ -422,7 +442,9 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
color: selected ? AppColors.primary : Colors.grey,
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(title, style: TextStyle(fontSize: 13, color: selected ? AppColors.primary : null)),
|
||||
Text(title,
|
||||
style: TextStyle(
|
||||
fontSize: 13, color: selected ? AppColors.primary : null)),
|
||||
],
|
||||
),
|
||||
);
|
||||
@@ -453,7 +475,9 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
border: Border.all(
|
||||
color: log.isCompleted
|
||||
? AppColors.primary.withValues(alpha: 0.3)
|
||||
: (isDark ? AppColors.primary.withValues(alpha: 0.08) : AppColors.cream),
|
||||
: (isDark
|
||||
? AppColors.primary.withValues(alpha: 0.08)
|
||||
: AppColors.cream),
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
@@ -467,10 +491,15 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
decoration: BoxDecoration(
|
||||
color: log.isCompleted
|
||||
? AppColors.primary.withValues(alpha: 0.15)
|
||||
: (isDark ? AppColors.primary.withValues(alpha: 0.08) : AppColors.cream.withValues(alpha: 0.5)),
|
||||
: (isDark
|
||||
? AppColors.primary.withValues(alpha: 0.08)
|
||||
: AppColors.cream.withValues(alpha: 0.5)),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Icon(LucideIcons.bookOpen, size: 22, color: log.isCompleted ? AppColors.primary : AppColors.sage),
|
||||
child: Icon(LucideIcons.bookOpen,
|
||||
size: 22,
|
||||
color:
|
||||
log.isCompleted ? AppColors.primary : AppColors.sage),
|
||||
),
|
||||
const SizedBox(width: 14),
|
||||
Expanded(
|
||||
@@ -482,13 +511,17 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: log.isCompleted && isDark ? AppColors.textSecondaryDark : null,
|
||||
decoration: log.isCompleted ? TextDecoration.lineThrough : null,
|
||||
color: log.isCompleted && isDark
|
||||
? AppColors.textSecondaryDark
|
||||
: null,
|
||||
decoration:
|
||||
log.isCompleted ? TextDecoration.lineThrough : null,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'Target: ${log.targetValue} ${log.targetUnit}',
|
||||
style: const TextStyle(fontSize: 12, color: AppColors.primary),
|
||||
style: const TextStyle(
|
||||
fontSize: 12, color: AppColors.primary),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -516,14 +549,17 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight,
|
||||
color: isDark
|
||||
? AppColors.textSecondaryDark
|
||||
: AppColors.textSecondaryLight,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (log.autoSync)
|
||||
Tooltip(
|
||||
message: 'Sinkron dari Al-Quran',
|
||||
child: Icon(LucideIcons.refreshCw, size: 16, color: AppColors.primary),
|
||||
child: Icon(LucideIcons.refreshCw,
|
||||
size: 16, color: AppColors.primary),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(LucideIcons.minusCircle, size: 20),
|
||||
@@ -536,7 +572,8 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
: null,
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(LucideIcons.plusCircle, size: 20, color: AppColors.primary),
|
||||
icon: const Icon(LucideIcons.plusCircle,
|
||||
size: 20, color: AppColors.primary),
|
||||
visualDensity: VisualDensity.compact,
|
||||
onPressed: () {
|
||||
log.rawAyatRead++;
|
||||
@@ -568,7 +605,8 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
children: [
|
||||
Icon(LucideIcons.sparkles, size: 20, color: AppColors.sage),
|
||||
const SizedBox(width: 8),
|
||||
const Text('Dzikir Harian', style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15)),
|
||||
const Text('Dzikir Harian',
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
@@ -599,13 +637,17 @@ class _ChecklistScreenState extends ConsumerState<ChecklistScreen> {
|
||||
children: [
|
||||
const Icon(LucideIcons.moonStar, size: 20, color: AppColors.sage),
|
||||
const SizedBox(width: 8),
|
||||
const Expanded(child: Text('Puasa Sunnah', style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15))),
|
||||
const Expanded(
|
||||
child: Text('Puasa Sunnah',
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15))),
|
||||
DropdownButton<String>(
|
||||
value: log.jenisPuasa,
|
||||
hint: const Text('Jenis', style: TextStyle(fontSize: 12)),
|
||||
underline: const SizedBox(),
|
||||
items: ['Senin', 'Kamis', 'Ayyamul Bidh', 'Daud', 'Lainnya']
|
||||
.map((e) => DropdownMenuItem(value: e, child: Text(e, style: const TextStyle(fontSize: 13))))
|
||||
.map((e) => DropdownMenuItem(
|
||||
value: e,
|
||||
child: Text(e, style: const TextStyle(fontSize: 13))))
|
||||
.toList(),
|
||||
onChanged: (v) {
|
||||
log.jenisPuasa = v;
|
||||
@@ -644,7 +686,9 @@ class _CustomCheckbox extends StatelessWidget {
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
border: value ? null : Border.all(color: Colors.grey, width: 2),
|
||||
),
|
||||
child: value ? const Icon(LucideIcons.check, size: 16, color: Colors.white) : null,
|
||||
child: value
|
||||
? const Icon(LucideIcons.check, size: 16, color: Colors.white)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user