import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:lucide_icons/lucide_icons.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:intl/intl.dart'; import '../../../app/theme/app_colors.dart'; import '../../../data/local/hive_boxes.dart'; import '../../../data/local/models/dzikir_counter.dart'; import '../../../data/local/models/app_settings.dart'; class DzikirScreen extends ConsumerStatefulWidget { final bool isSimpleModeTab; const DzikirScreen({super.key, this.isSimpleModeTab = false}); @override ConsumerState createState() => _DzikirScreenState(); } class _DzikirScreenState extends ConsumerState with SingleTickerProviderStateMixin { late TabController _tabController; List> _pagiItems = []; List> _petangItems = []; late Box _counterBox; late String _todayKey; @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); _counterBox = Hive.box(HiveBoxes.dzikirCounters); _todayKey = DateFormat('yyyy-MM-dd').format(DateTime.now()); _loadData(); } @override void dispose() { _tabController.dispose(); super.dispose(); } Future _loadData() async { final pagiJson = await rootBundle.loadString('assets/dzikir/dzikir_pagi.json'); final petangJson = await rootBundle.loadString('assets/dzikir/dzikir_petang.json'); setState(() { _pagiItems = List>.from(json.decode(pagiJson)); _petangItems = List>.from(json.decode(petangJson)); }); } DzikirCounter _getCounter(String dzikirId, int target) { final key = '${dzikirId}_$_todayKey'; return _counterBox.get(key) ?? DzikirCounter( dzikirId: dzikirId, date: _todayKey, count: 0, target: target, ); } void _increment(String dzikirId, int target) { final key = '${dzikirId}_$_todayKey'; var counter = _counterBox.get(key); if (counter == null) { counter = DzikirCounter( dzikirId: dzikirId, date: _todayKey, count: 1, target: target, ); _counterBox.put(key, counter); } else { if (counter.count < counter.target) { counter.count++; counter.save(); } } setState(() {}); // Haptic feedback HapticFeedback.lightImpact(); } @override Widget build(BuildContext context) { final isDark = Theme.of(context).brightness == Brightness.dark; final box = Hive.box(HiveBoxes.settings); final isSimpleMode = box.get('default')?.simpleMode ?? false; return Scaffold( appBar: AppBar( automaticallyImplyLeading: !widget.isSimpleModeTab, title: const Text('Dzikir Pagi & Petang'), actions: [ IconButton( onPressed: () {}, icon: const Icon(LucideIcons.info), ), ], ), body: Column( children: [ // Tabs Container( margin: const EdgeInsets.symmetric(horizontal: 16), child: TabBar( controller: _tabController, labelColor: AppColors.primary, unselectedLabelColor: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight, indicatorColor: AppColors.primary, indicatorWeight: 3, labelStyle: const TextStyle(fontWeight: FontWeight.w700, fontSize: 14), tabs: const [ Tab(text: 'Pagi'), Tab(text: 'Petang'), ], ), ), Expanded( child: TabBarView( controller: _tabController, children: [ _buildDzikirList(context, isDark, _pagiItems, 'pagi', 'Dzikir Pagi', 'Dibaca setelah shalat Shubuh hingga terbit matahari'), _buildDzikirList(context, isDark, _petangItems, 'petang', 'Dzikir Petang', 'Dibaca setelah shalat Ashar hingga terbenam matahari'), ], ), ), ], ), ); } Widget _buildDzikirList(BuildContext context, bool isDark, List> items, String prefix, String title, String subtitle) { if (items.isEmpty) { return const Center(child: CircularProgressIndicator()); } return ListView.builder( padding: const EdgeInsets.all(16), itemCount: items.length + 1, // +1 for header itemBuilder: (context, index) { if (index == 0) { return Padding( padding: const EdgeInsets.only(bottom: 20), child: Column( children: [ Text(title, style: const TextStyle( fontSize: 22, fontWeight: FontWeight.w800)), const SizedBox(height: 4), Text( subtitle, textAlign: TextAlign.center, style: TextStyle( color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight, fontSize: 13, ), ), ], ), ); } final item = items[index - 1]; final dzikirId = '${prefix}_${item['id']}'; final target = (item['count'] as num?)?.toInt() ?? 1; final counter = _getCounter(dzikirId, target); final isComplete = counter.count >= counter.target; return Padding( padding: const EdgeInsets.only(bottom: 16), child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( color: isDark ? AppColors.surfaceDark : AppColors.surfaceLight, borderRadius: BorderRadius.circular(16), border: Border.all( color: isComplete ? AppColors.primary.withValues(alpha: 0.3) : (isDark ? AppColors.primary.withValues(alpha: 0.08) : AppColors.cream), ), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // Header row: count badge + number Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( padding: const EdgeInsets.symmetric( horizontal: 10, vertical: 4), decoration: BoxDecoration( color: AppColors.primary.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(50), ), child: Text( '$target KALI', style: TextStyle( fontSize: 10, fontWeight: FontWeight.w700, color: AppColors.primary, ), ), ), Text( '${(index).toString().padLeft(2, '0')}', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight, ), ), ], ), const SizedBox(height: 16), // Arabic text SizedBox( width: double.infinity, child: Text( item['arabic'] ?? '', textAlign: TextAlign.right, style: const TextStyle( fontFamily: 'Amiri', fontSize: 24, height: 2.0, ), ), ), const SizedBox(height: 12), // Transliteration Text( item['transliteration'] ?? '', style: TextStyle( fontSize: 13, fontStyle: FontStyle.italic, color: AppColors.primary, ), ), const SizedBox(height: 8), // Translation Text( '"${item['translation'] ?? ''}"', style: TextStyle( fontSize: 13, color: isDark ? AppColors.textSecondaryDark : AppColors.textSecondaryLight, ), ), const SizedBox(height: 16), // Counter button GestureDetector( onTap: () => _increment(dzikirId, target), child: Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 14), decoration: BoxDecoration( color: isComplete ? AppColors.primary.withValues(alpha: 0.15) : AppColors.primary, borderRadius: BorderRadius.circular(50), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( isComplete ? LucideIcons.check : LucideIcons.fingerprint, size: 18, color: isComplete ? AppColors.primary : AppColors.onPrimary, ), const SizedBox(width: 8), Text( '${counter.count} / $target', style: TextStyle( fontSize: 15, fontWeight: FontWeight.w700, color: isComplete ? AppColors.primary : AppColors.onPrimary, ), ), ], ), ), ), ], ), ), ); }, ); } }