- Murattal: Spotify-style 5-button controls [Shuffle, Prev, Play, Next, Playlist] - Murattal: Animated 7-bar equalizer visualization in player circle - Murattal: Unsplash API background with frosted glass player overlay - Murattal: Transparent AppBar with backdrop blur - Murattal: Surah playlist bottom sheet with full 114 Surah list - Murattal: Auto-play disabled on screen open, enabled on navigation - Murattal: Shuffle mode for random Surah playback - Murattal: Photographer attribution per Unsplash guidelines - Dashboard: Auto-scroll prayer schedule to next active prayer - Fix: setState lifecycle errors on Reading & Murattal screens - Setup: flutter_dotenv, cached_network_image, url_launcher deps
24 KiB
Jamshalat Diary — Phase-Based Implementation Tasklist
Project: Jamshalat Diary Flutter App
PRD Reference: PRD.md
Design Reference: stitch/ folder (18 screens)
Last Updated: March 2026
How to Use This Document
- Status legend:
[ ]Not started ·[~]In progress ·[x]Done ·[-]Skipped/deferred - Dependency notation: Tasks marked with
⚠️ depends on: [task ref]must not start until that task is complete - Assignable units: Each task is atomic enough to delegate to a single agent/developer
- Phase gates: Do not start a phase until all
[x]required tasks in the previous phase are complete
Phase 1 — Foundation
Goal: Runnable Flutter app with navigation shell, design system, and theme engine wired up.
Gate to Phase 2: App boots, bottom nav switches tabs, light/dark toggle works.
1.1 Project Bootstrap
- 1.1.1 Create Flutter project:
flutter create jamshalat_diary --org com.jamshalat --platforms android,ios - 1.1.2 Add all dependencies to
pubspec.yaml(see PRD §8 — Third-Party Dependencies) - 1.1.3 Run
flutter pub getand verify zero conflicts - 1.1.4 Configure
analysis_options.yamlwith strict linting rules (flutter_lints+prefer_const_constructors) - 1.1.5 Set up folder structure as defined in PRD §4.1 (create all
lib/directories and placeholder files) - 1.1.6 Add font assets to
pubspec.yaml: Google Fonts (Plus Jakarta Sans viagoogle_fontspackage) + Amiri (bundled TTF inassets/fonts/) - 1.1.7 Add asset directories to
pubspec.yaml:assets/fonts/,assets/quran/,assets/dzikir/,assets/images/ - 1.1.8 Configure Android
minSdkVersion: 21,targetSdkVersion: 34inandroid/app/build.gradle - 1.1.9 Configure iOS deployment target: 13.0 in
ios/Podfile
1.2 Design System
- 1.2.1 Create
lib/app/theme/app_colors.dart— all color tokens from PRD §3.1 (light + dark values as static consts) - 1.2.2 Create
lib/app/theme/app_text_styles.dart— fullTextThemefrom PRD §3.2 (Plus Jakarta Sans weights, Amiri definitions) - 1.2.3 Create
lib/app/theme/app_theme.dart—ThemeDatafor light and dark using tokens from 1.2.1 + 1.2.2; Material 3 enabled - 1.2.4 Create
lib/core/widgets/ios_toggle.dart— custom iOS-style toggle widget (51×31dp, animated thumb,AnimatedContainer+GestureDetector) per PRD §6.9 - 1.2.5 Create
lib/core/widgets/section_header.dart— reusable section label widget (uppercase, tracking-wider, sage color) - 1.2.6 Create
lib/core/widgets/progress_bar.dart— reusable linear progress bar (primary fill, configurable height + borderRadius) - 1.2.7 Verify
AppColorsagainst all 18 stitch screens — no hardcoded colors in any widget
1.3 Navigation Shell
- 1.3.1 Add
go_routerand set uplib/app/router.dartwithShellRoutefor bottom nav tabs - 1.3.2 Define all routes from PRD §5.2 in
router.dart(top-level + nested) - 1.3.3 Create
lib/core/widgets/bottom_nav_bar.dart— 5-tab nav bar per PRD §5.1 spec (active/inactive states, Material Symbols filled/outlined) - 1.3.4 Create stub screens for all 9 features (empty
Scaffold+AppBarwith feature name) so routing is testable - 1.3.5 Create
lib/app/app.dart—MaterialApp.routerwired torouter.dart+themeModefrom Riverpod provider
1.4 Theme Engine
- 1.4.1 Create
lib/core/providers/theme_provider.dart—StateProvider<ThemeMode>initialized from Hive settings - 1.4.2 Wrap
MaterialAppinProviderScope; consumethemeProviderforthemeMode - 1.4.3 Verify light ↔ dark toggle visually applies instantly on all stub screens
- 1.4.4 Create
lib/main.dart— initializes Hive, runsProviderScope+App
Phase 2 — Core Data Layer
Goal: All services and local storage ready. Features can read/write data.
Gate to Phase 3: Prayer times calculate correctly for Jakarta coords, Hive boxes open without errors, notifications schedule in emulator.
⚠️ Depends on: Phase 1 complete
2.1 Hive Setup
- 2.1.1 Create all 6 Hive
@HiveTypemodel classes from PRD §7.1:AppSettings,ChecklistItem,DailyWorshipLog,DzikirCounter,QuranBookmark,CachedPrayerTimes - 2.1.2 Run
build_runnerto generate HiveTypeAdapterfiles (*.g.dart) - 2.1.3 Create
lib/data/local/hive_boxes.dart— box name constants +initHive()function that opens all boxes - 2.1.4 Call
initHive()inmain.dartbeforerunApp() - 2.1.5 Seed default
AppSettingson first launch (if settings box is empty) - 2.1.6 Seed default 10
ChecklistItementries on first launch (per PRD §6.3 default items table)
2.2 Prayer Time Service
- 2.2.1 Create
lib/data/services/prayer_service.dartusingadhanpackage- Method:
PrayerTimes getPrayerTimes(double lat, double lng, DateTime date) - Calculation method: Muslim World League (default), configurable in settings
- Returns: Fajr, Sunrise, Dhuhr, Asr, Maghrib, Isha as
DateTime
- Method:
- 2.2.2 Implement cache logic: before calculating, check
CachedPrayerTimesHive box for existinglat_lng_datekey; write result to box after calculation - 2.2.3 Create
lib/features/dashboard/data/prayer_times_provider.dart—AsyncNotifierProviderthat fetches location then returns today'sPrayerTimes - 2.2.4 Unit test:
getPrayerTimes(lat: -6.2088, lng: 106.8456, date: 2026-03-06)→ verify Maghrib ≈ 18:05 WIB
2.3 Location Service
- 2.3.1 Create
lib/data/services/location_service.dart- Method:
Future<Position?> getCurrentLocation()— requests permission, gets GPS fix - Method:
Position? getLastKnownLocation()— reads fromAppSettingsHive box - Method:
Future<String> getCityName(double lat, double lng)— reverse geocode viageocodingpackage
- Method:
- 2.3.2 Implement fallback chain: GPS → last saved → manual city picker
- 2.3.3 Save successful GPS fix to
AppSettings(lat, lng, cityName) after each successful fetch - 2.3.4 Add
ACCESS_FINE_LOCATIONpermission to AndroidAndroidManifest.xml - 2.3.5 Add
NSLocationWhenInUseUsageDescriptionto iOSInfo.plist
2.4 Notification Service
- 2.4.1 Create
lib/data/services/notification_service.dartusingflutter_local_notifications- Method:
Future<void> init()— initializes channels (Android: high-priority Adhan channel) - Method:
Future<void> scheduleAdhan(Prayer prayer, DateTime time)— schedules exact alarm - Method:
Future<void> scheduleIqamah(Prayer prayer, DateTime adhanTime, int offsetMinutes)— schedules iqamah reminder - Method:
Future<void> cancelAll()— cancels all pending notifications - Method:
Future<void> rescheduleAll(PrayerTimes times, AppSettings settings)— cancels + re-schedules based on current settings
- Method:
- 2.4.2 Add
SCHEDULE_EXACT_ALARM+POST_NOTIFICATIONSpermissions to Android manifest - 2.4.3 Add iOS background modes for notifications in
Info.plist - 2.4.4 Call
rescheduleAll()on app start and whenever settings or location changes - 2.4.5 Manual test: enable Fajr notification in settings → verify notification fires at correct time in emulator
2.5 Quran Data Service
- 2.5.1 Source or create
assets/quran/quran_id.json— 114 Surahs, each entry:{ id, nameArabic, nameLatin, verseCount, juzStart, verses: [{id, arabic, transliteration, translation_id}] } - 2.5.2 Create
lib/data/services/quran_service.dart- Method:
Future<List<Surah>> getAllSurahs()— loads + parses JSON asset (cached in memory after first load) - Method:
Future<Surah> getSurah(int id)— returns single surah with all verses
- Method:
- 2.5.3 Verify JSON loads correctly; log verse count for Surah 2 (Al-Baqarah) = 286 verses
2.6 Dzikir Data Service
- 2.6.1 Create
assets/dzikir/dzikir_pagi.jsonandassets/dzikir/dzikir_petang.json— each entry:{ id, arabic, transliteration, translation, target_count, source } - 2.6.2 Create
lib/data/services/dzikir_service.dart- Method:
Future<List<DzikirItem>> getDzikir(DzikirType type)— loads from JSON asset - Method:
Map<String, int> getCountersForDate(String date)— reads from Hivedzikir_countersbox - Method:
void increment(String dzikirId, String date)— writes to Hive
- Method:
Phase 3 — Dashboard & Prayer Calendar
Goal: The two primary daily-use screens are fully functional.
Gate to Phase 4: Dashboard shows live countdown, correct prayer times, checklist summary. Imsakiyah shows full monthly table.
⚠️ Depends on: Phase 2 complete
3.1 Dashboard Screen
- 3.1.1 Build
DashboardScreensticky header: avatar + greeting + notification bell (taps → Settings) - 3.1.2 Build Next Prayer Hero Card: bg-primary card, prayer name+time (displayLarge), live countdown timer widget
- Countdown:
StreamBuilderonStream.periodic(Duration(seconds: 1))computing time to next prayer
- Countdown:
- 3.1.3 Build Adhan/Iqamah badge: notification bell icon absolutely positioned on active prayer card (shown when Adhan has been called, hidden otherwise)
- 3.1.4 Build "View Qibla" button on hero card → navigates to
/tools/qibla - 3.1.5 Build Prayer Times horizontal scroll:
ListView.builderhorizontal, 5 prayer cards (Fajr–Isha), active card highlighted - 3.1.6 Build Today's Checklist Summary Card: circular SVG progress + 2 preview items + "View Full Checklist" CTA
- 3.1.7 Build Weekly Progress bar chart: 7 bars (Mon–Sun), data from
worship_logsHive box - 3.1.8 Wire
prayer_times_providerto all prayer time displays - 3.1.9 Wire checklist summary to today's
DailyWorshipLogfrom Hive - 3.1.10 Verify screen matches
stitch/dashboard_active_nav/screen.pngvisually
3.2 Prayer Calendar (Imsakiyah) Screen
- 3.2.1 Build Imsakiyah screen header: back + "Prayer Calendar" +
more_vert - 3.2.2 Build Hijri month selector: horizontal scroll chip row; compute current + surrounding Hijri months
- 3.2.3 Build location card: shows current city name +
expand_moretapping opens city search bottom sheet - 3.2.4 Build city search bottom sheet:
TextField+ListViewof bundled Indonesian cities (local JSON asset) - 3.2.5 Build prayer times table:
GridView7-column, header row, data rows for all days of selected Hijri month - 3.2.6 Highlight today's row with
primary/5background - 3.2.7 Wire month selector + location to
PrayerService— recalculate on change - 3.2.8 Auto-scroll to today's row on screen open
- 3.2.9 Verify screen matches
stitch/imsakiyah_active_nav/screen.pngvisually
Phase 4 — Worship Tracking
Goal: Checklist, Dzikir, and Reports fully functional with persistent data.
Gate to Phase 5: Checklist persists across restarts, Dzikir counter works, Reports chart renders from real log data.
⚠️ Depends on: Phase 2 complete (data layer), Phase 3 (worship_logs written by Dashboard)
4.1 Daily Checklist Screen
- 4.1.1 Build Checklist header: "Daily Worship" + date string + calendar icon (date picker for viewing past days)
- 4.1.2 Build Progress Card: dark bg,
auto_awesomedecoration, percentage text, progress bar, motivational quote - 4.1.3 Build task list:
ListViewofChecklistItemwidgets with custom checkbox - 4.1.4 Implement custom checkbox widget: 24dp, primary border, animated check SVG on tap
- 4.1.5 Wire tap → update
DailyWorshipLogin Hive → Riverpod provider invalidate → progress card updates reactively - 4.1.6 Implement daily reset: on date change, create new empty
DailyWorshipLogfor new date - 4.1.7 Write completion data to
worship_logsbox (for Reports feature to consume) - 4.1.8 Verify screen matches
stitch/checklist_active_nav/screen.pngandstitch/checklist_dark_mode/screen.png
4.2 Dzikir Screen
- 4.2.1 Build Dzikir header: back + "Dzikir Pagi & Petang" + info button (bottom sheet explanation)
- 4.2.2 Build Pagi/Petang tab bar with animated underline indicator
- 4.2.3 Build hero banner: gradient bg + title + subtitle
- 4.2.4 Build Dzikir card: Arabic text (Amiri, RTL, 24sp), transliteration (italic), translation, counter row
- 4.2.5 Implement tap counter:
+button → increments count in Hive → rebuilds counter row reactively - 4.2.6 Implement completion state: when
count >= target, button becomescheck_circle, card shows subtle primary glow - 4.2.7 Implement smart tab pre-selection: Pagi between Fajr–Dhuhr, Petang between Maghrib–Isha
- 4.2.8 Verify Arabic text renders correctly RTL, no overflow, no visual glitches
- 4.2.9 Verify screen matches
stitch/dzikir_active_nav/screen.pngandstitch/dzikir_dark_mode/screen.png
4.3 Reports (Laporan) Screen
- 4.3.1 Build Reports header: back + "Worship Quality Report" + share button
- 4.3.2 Build Weekly/Monthly/Yearly tab bar
- 4.3.3 Build main chart card: analytics badge + completion % + trend chip
- 4.3.4 Build bar chart widget: custom
CustomPainterorColumn+Expandedbars, proportional heights from log data - 4.3.5 Implement tap-on-bar tooltip:
OverlayEntryorTooltipshowing date + exact % on tap - 4.3.6 Build summary stats row: Best streak, Average %, Total completed
- 4.3.7 Implement streak calculation: consecutive days with completion > 0% from
worship_logs - 4.3.8 Implement share button: generate shareable text summary (no image generation in v1.0)
- 4.3.9 Build empty state: illustration + "Start tracking to see your progress" when no logs exist
- 4.3.10 Verify screen matches
stitch/laporan_active_nav/screen.pngandstitch/laporan_dark_mode/screen.png
Phase 5 — Islamic Tools
Goal: Qibla, Quran Reader, and Murattal player fully functional.
Gate to Phase 6: Qibla compass rotates with device, Quran displays all 114 Surahs, audio plays in background.
⚠️ Depends on: Phase 2 complete (data layer)
5.1 Qibla Finder Screen
- 5.1.1 Build Qibla header: back + "Qibla Finder" +
my_locationbutton - 5.1.2 Build location + degree display: city name +
"{n}°} from North"label - 5.1.3 Build compass widget: circular ring with N/S/E/W labels,
AnimatedRotationdriven byflutter_compassstream - 5.1.4 Build Qibla arrow: overlaid pointer that stays fixed to calculated Qibla bearing while compass ring rotates
- 5.1.5 Build mosque silhouette overlay:
ShaderMaskwith gradient mask (fade-to-transparent at top) - 5.1.6 Build accuracy indicator: "High accuracy" / "Low accuracy" label based on sensor data
- 5.1.7 Build permission-denied state: explanation card + "Open Settings" button
- 5.1.8 Verify compass direction is correct for Jakarta coordinates (Qibla ≈ 295° from North)
5.2 Quran List Screen
- 5.2.1 Build Quran list screen header: search bar at top
- 5.2.2 Build Surah list:
ListView.builderof 114 items- Each item: number badge (primary/10 bg) + Arabic name (Amiri) + Latin name + verse count + Juz
- 5.2.3 Implement search filter: filters by Latin name or Surah number in real time
5.3 Quran Reading Screen
- 5.3.1 Build reading screen sticky header: back + Surah name (Arabic, Amiri) + Juz info +
more_vert - 5.3.2 Build Bismillah banner (shown for all Surahs except Surah 9 — At-Tawbah)
- 5.3.3 Build verse card: verse number badge + Arabic text (Amiri, 28sp, RTL) + transliteration + translation
- 5.3.4 Build verse action row:
bookmark,share,playicons per verse - 5.3.5 Implement bookmarking: tap bookmark icon → save
QuranBookmarkto Hive → icon toggles to filled - 5.3.6 Implement reading position persistence: save last scroll position (verse index) to Hive per Surah
- 5.3.7 Wire
playicon on verse → navigate to/tools/quran/:surahId/murattalstarting at that verse - 5.3.8 Verify Arabic text is RTL, no clipping, line-height comfortable (2.2 per PRD)
- 5.3.9 Verify screen matches
stitch/quran_reading_active_nav/screen.pngandstitch/quran_dark_mode/screen.png
5.4 Quran Murattal Screen
- 5.4.1 Initialize
just_audioplayer +audio_servicefor background playback - 5.4.2 Build Murattal screen: inherits Quran Reading layout + adds audio player panel at bottom
- 5.4.3 Build audio player panel: reciter name + progress slider + transport controls (
skip_previous,replay_10, play/pause,forward_10,skip_next) - 5.4.4 Build playback speed selector: 0.75x / 1x / 1.25x / 1.5x chips
- 5.4.5 Implement verse highlight sync: highlight current verse based on audio position (timed segments per Surah)
- 5.4.6 Implement auto-scroll:
ScrollControllerscrolls to current verse during playback - 5.4.7 Configure background audio:
audio_servicehandler, system media controls in notification tray - 5.4.8 Bundle short Surahs (Juz Amma: Surah 78–114) as local MP3 assets
- 5.4.9 Implement streaming fallback for longer Surahs (mp3quran.net API)
- 5.4.10 Build offline fallback state for streamed Surahs: "Connect to internet to play this Surah"
- 5.4.11 Verify screen matches
stitch/quran_murattal_active_nav/screen.png
Phase 6 — Settings & System Polish
Goal: Settings screen complete, all toggles wired, notifications working end-to-end, dark mode seamless.
Gate to Phase 7: All settings persist, dark mode switches instantly, Adhan notification fires correctly, no hardcoded colors remain.
⚠️ Depends on: Phase 4 + Phase 5 complete
6.1 Settings Screen
- 6.1.1 Build Settings header: back + "Settings" title
- 6.1.2 Build Profile section: avatar + name + email + edit button (inline editing)
- 6.1.3 Build Notifications group: per-prayer Adhan toggles (5 prayers) using
IosTogglewidget - 6.1.4 Build Iqamah offset row: per-prayer minute offset picker (stepper, default 10 min)
- 6.1.5 Build Daily Checklist Reminder row: time picker, default 9:00 AM
- 6.1.6 Build Display group: Dark Mode 3-way control (Light/Dark/Auto), Font Size selector, Language selector
- 6.1.7 Build About group: App Version, Privacy Policy (in-app WebView), Rate App link, Feedback
- 6.1.8 Wire all toggles → write to
AppSettingsHive box → trigger side effects (notification reschedule, theme change) - 6.1.9 Verify screen matches
stitch/settings_with_dark_mode_option/screen.pngandstitch/settings_dark_mode/screen.png
6.2 Dark Mode Polish
- 6.2.1 Audit ALL screens in dark mode against
stitch/*_dark_mode/screen.png— fix any color token mismatches - 6.2.2 Verify no hardcoded
Colors.white,Colors.black, or raw hex strings remain in widget code (grep codebase) - 6.2.3 Verify
AnimatedThemetransition is smooth (no flash/jank on toggle) - 6.2.4 Test system auto mode: app follows device dark mode setting correctly
6.3 Notification End-to-End
- 6.3.1 Verify Adhan notifications fire at correct prayer times on Android emulator (API 34)
- 6.3.2 Verify Adhan notifications fire correctly on iOS simulator (iOS 16+)
- 6.3.3 Verify notifications are cancelled when prayer toggle is turned off in Settings
- 6.3.4 Verify Iqamah notification fires
nminutes after Adhan (configurable offset) - 6.3.5 Verify notifications reschedule correctly after location changes (new prayer times → cancel old → schedule new)
- 6.3.6 Verify tapping notification → opens app on Dashboard screen
6.4 Accessibility Pass
- 6.4.1 Audit all
IconButtons and small tap targets: minimum 48×48dp (addSizedBoxwrappers where needed) - 6.4.2 Add
Semantics(label: ...)to all icon-only buttons across all screens - 6.4.3 Verify all Arabic text has explicit
textDirection: TextDirection.rtl - 6.4.4 Verify contrast ratios for all text on primary bg (
#70df20background with dark text = check) - 6.4.5 Test with TalkBack (Android) and VoiceOver (iOS) — all interactive elements must be reachable
6.5 Localization
- 6.5.1 Set up
flutter_localizations+intlinpubspec.yaml - 6.5.2 Create
lib/l10n/app_id.arb(Indonesian) andlib/l10n/app_en.arb(English) with all UI strings - 6.5.3 Replace all hardcoded Indonesian strings in widgets with
AppLocalizations.of(context).* - 6.5.4 Verify language switch in Settings changes all UI strings (no restart required)
Phase 7 — QA & Release Prep
Goal: App is production-ready. All screens verified, performance validated, store assets ready.
Gate to ship: Zero critical bugs, performance targets met, store listing complete.
⚠️ Depends on: Phase 6 complete
7.1 Integration Testing
- 7.1.1 Write integration test: full checklist flow (open app → check 5 items → verify progress = 50% → restart → verify persisted)
- 7.1.2 Write integration test: prayer time accuracy for 5 major Indonesian cities (Jakarta, Surabaya, Medan, Makassar, Denpasar)
- 7.1.3 Write integration test: dark mode toggle persists across app restart
- 7.1.4 Write integration test: Dzikir counter increments and resets on next day
- 7.1.5 Manual test: Quran reads all 114 Surahs without crash (test Surah 2 — largest Surah)
- 7.1.6 Manual test: Murattal audio plays + background playback continues when screen locked
7.2 Performance Audit
- 7.2.1 Profile cold start time on mid-range Android device — must be < 2 seconds
- 7.2.2 Profile bottom nav tab switches — must be < 150ms
- 7.2.3 Profile Quran Surah 2 scroll (286 verses) — must maintain 60fps
- 7.2.4 Run
flutter analyze— zero warnings, zero errors - 7.2.5 Run
flutter test— all unit tests pass
7.3 App Assets & Store Prep
- 7.3.1 Create app icon (1024×1024px): mosque/compass motif with
#70df20primary color - 7.3.2 Apply app icon via
flutter_launcher_iconspackage (all densities, adaptive icon for Android) - 7.3.3 Create splash screen via
flutter_native_splashpackage (white/dark bg, centered logo) - 7.3.4 Set app name: "Jamshalat Diary" in
AndroidManifest.xmlandInfo.plist - 7.3.5 Set bundle ID:
com.jamshalat.diaryon both platforms - 7.3.6 Configure release signing (Android keystore, iOS certificates) — document in private README
- 7.3.7 Build release APK:
flutter build apk --release— verify no build errors - 7.3.8 Build iOS release:
flutter build ipa --release— verify no build errors - 7.3.9 Write Play Store listing: app description (Indonesian + English), screenshots (1 per key screen), tags
- 7.3.10 Write App Store listing: same content, App Store Connect metadata
Progress Tracker
| Phase | Total Tasks | Done | Remaining | Status |
|---|---|---|---|---|
| Phase 1 — Foundation | 22 | 0 | 22 | Not started |
| Phase 2 — Data Layer | 21 | 0 | 21 | Not started |
| Phase 3 — Dashboard & Calendar | 18 | 0 | 18 | Not started |
| Phase 4 — Worship Tracking | 28 | 0 | 28 | Not started |
| Phase 5 — Islamic Tools | 27 | 0 | 27 | Not started |
| Phase 6 — Settings & Polish | 22 | 0 | 22 | Not started |
| Phase 7 — QA & Release | 20 | 0 | 20 | Not started |
| TOTAL | 158 | 0 | 158 | 🔴 Not started |
Quick Reference — Key Files
| File | Purpose |
|---|---|
PRD.md |
Full product requirements — source of truth |
stitch/*/screen.png |
Visual reference for each screen |
stitch/*/code.html |
HTML implementation reference for each screen |
TASKLIST.md |
This document — execution plan |
TASKLIST v1.0 — Jamshalat Diary — March 2026