# Product Requirements Document
## JamShalat — Islamic Worship Companion App

**Version:** 1.0  
**Date:** March 2026  
**Platform:** Flutter (iOS + Android)  
**Status:** Draft

---

## Table of Contents

1. [Overview](#1-overview)
2. [Target Users](#2-target-users)
3. [Design System](#3-design-system)
4. [App Architecture](#4-app-architecture)
5. [Navigation](#5-navigation)
6. [Feature Specifications](#6-feature-specifications)
   - 6.1 Dashboard
   - 6.2 Prayer Calendar (Imsakiyah)
   - 6.3 Daily Checklist
   - 6.4 Dzikir
   - 6.5 Reports (Laporan)
   - 6.6 Qibla Finder
   - 6.7 Quran Reading
   - 6.8 Quran Murattal
   - 6.9 Settings
7. [Data Model](#7-data-model)
8. [Third-Party Dependencies](#8-third-party-dependencies)
9. [Non-Functional Requirements](#9-non-functional-requirements)
10. [Permissions](#10-permissions)
11. [Out of Scope (v1.0)](#11-out-of-scope-v10)

---

## 1. Overview

**JamShalat** is an offline-first Muslim daily worship companion app built in Flutter. It helps Muslim users track their daily prayers, worship habits, and spiritual growth with a clean, modern UI that supports both light and dark themes.

**Core value proposition:**
- Never miss a prayer — real-time prayer time countdowns with Adhan/Iqamah notifications
- Track daily worship completion — checklist for Sholat, Tilawah, Dzikir
- Build consistent habits — weekly/monthly progress reports
- All-in-one Islamic toolkit — Qibla compass, Quran reader, Murattal player, Dzikir counter

---

## 2. Target Users

**Primary:** Muslim adults (18–45) who want to improve consistency in daily worship
**Secondary:** Parents tracking worship habits for the family

**User goals:**
- Know exact prayer times for their location, offline
- Get reminded for Adhan and Iqamah
- Log daily ibadah (worship) completion
- Read Quran and perform guided Dzikir
- Find Qibla direction while traveling
- Review worship quality over time

---

## 3. Design System

### 3.1 Color Tokens

| Token | Light Value | Dark Value | Usage |
|---|---|---|---|
| `primary` | `#70df20` | `#70df20` | Active states, CTAs, progress fills |
| `background` | `#f7f8f6` | `#182111` | App background |
| `surface` | `#ffffff` | `#1e2a14` | Cards, bottom nav |
| `sage` | `#728764` | `#728764` | Secondary text, section labels |
| `cream` | `#f2f4f0` | — | Dividers, borders (light mode) |
| `on-primary` | `#0a1a00` | `#0a1a00` | Text on primary bg |
| `text-primary` | `#1a2a0a` | `#f2f4f0` | Body text |
| `text-secondary` | `#64748b` | `#94a3b8` | Captions, labels |
| `error` | `#ef4444` | `#f87171` | Error states |
| `success` | `#22c55e` | `#4ade80` | Success/completed states |

### 3.2 Typography

| Style | Font | Weight | Size | Usage |
|---|---|---|---|---|
| `displayLarge` | Plus Jakarta Sans | 800 (ExtraBold) | 32sp | Hero numbers (next prayer) |
| `headlineMedium` | Plus Jakarta Sans | 700 (Bold) | 24sp | Screen titles, section headers |
| `titleMedium` | Plus Jakarta Sans | 600 (SemiBold) | 16sp | Card titles, nav labels |
| `bodyLarge` | Plus Jakarta Sans | 400 (Regular) | 16sp | Body text |
| `bodySmall` | Plus Jakarta Sans | 400 (Regular) | 12sp | Captions, timestamps |
| `labelSmall` | Plus Jakarta Sans | 700 (Bold) | 10sp | Uppercase tags, section labels |
| `arabicBody` | Amiri | 400 (Regular) | 24sp | Quran verses, Dzikir Arabic text |
| `arabicLarge` | Amiri | 700 (Bold) | 28sp | Surah headings in Arabic |

### 3.3 Spacing & Shape

| Token | Value | Flutter |
|---|---|---|
| `radiusSm` | 8dp | `BorderRadius.circular(8)` |
| `radiusMd` | 12dp | `BorderRadius.circular(12)` |
| `radiusLg` | 16dp | `BorderRadius.circular(16)` |
| `radiusXl` | 24dp | `BorderRadius.circular(24)` |
| `radiusFull` | 9999dp | `StadiumBorder()` |
| `spacingXs` | 4dp | — |
| `spacingSm` | 8dp | — |
| `spacingMd` | 16dp | — |
| `spacingLg` | 24dp | — |
| `spacingXl` | 32dp | — |

### 3.4 Iconography

- **Library:** Material Symbols Outlined (via `material_symbols_icons` Flutter package)
- **Filled variant:** Used for active bottom nav tab icons only
- **Size:** 24dp default, 20dp for compact rows, 32dp for feature section icons

### 3.5 Dark Mode

- Toggled via user preference in Settings (stored locally)
- Options: **Light**, **Dark**, **System (Auto)**
- Implemented via Flutter `ThemeMode` — `ThemeMode.light`, `ThemeMode.dark`, `ThemeMode.system`
- All color tokens have explicit light and dark values; no transparency hacks

---

## 4. App Architecture

### 4.1 Structure

```
lib/
├── main.dart
├── app/
│   ├── app.dart                  # MaterialApp.router + theme + locale
│   ├── router.dart               # GoRouter — shell route for bottom nav
│   └── theme/
│       ├── app_theme.dart        # ThemeData light + dark
│       ├── app_colors.dart       # AppColors class with static consts
│       └── app_text_styles.dart  # TextTheme definitions
├── core/
│   ├── widgets/
│   │   ├── bottom_nav_bar.dart
│   │   ├── prayer_time_card.dart
│   │   ├── section_header.dart
│   │   ├── ios_toggle.dart
│   │   ├── progress_bar.dart
│   │   └── circular_progress_indicator_custom.dart
│   ├── utils/
│   │   ├── date_utils.dart
│   │   ├── prayer_utils.dart     # Hijri date conversion helpers
│   │   └── arabic_utils.dart     # RTL text helpers
│   └── providers/
│       └── theme_provider.dart   # ThemeMode state via Riverpod
├── features/
│   ├── dashboard/
│   │   ├── data/
│   │   ├── domain/
│   │   └── presentation/
│   │       ├── dashboard_screen.dart
│   │       └── widgets/
│   ├── imsakiyah/
│   ├── checklist/
│   ├── dzikir/
│   ├── laporan/
│   ├── qibla/
│   ├── quran/
│   │   ├── presentation/
│   │   │   ├── quran_screen.dart       # Surah list
│   │   │   ├── quran_reading_screen.dart
│   │   │   └── quran_murattal_screen.dart
│   └── settings/
└── data/
    ├── local/
    │   ├── hive_boxes.dart        # Box names constants
    │   └── adapters/             # Hive TypeAdapters
    └── services/
        ├── prayer_service.dart    # Adhan calculation
        ├── location_service.dart  # GPS + last known
        ├── notification_service.dart
        └── quran_service.dart    # Local JSON asset
```

### 4.2 State Management

**Riverpod** (flutter_riverpod + riverpod_annotation + riverpod_generator)

- Every feature has its own `*_provider.dart`
- Async data via `AsyncNotifierProvider`
- UI state (loading, error, data) handled via `AsyncValue`
- Theme mode via `StateProvider<ThemeMode>`

### 4.3 Local Storage

**Hive** for offline-first persistence:

| Box | Key | Value type |
|---|---|---|
| `settings` | String key | dynamic |
| `checklist_items` | date string (yyyy-MM-dd) | `List<ChecklistItem>` |
| `worship_logs` | date string | `WorshipLog` |
| `dzikir_counters` | dzikir ID | int count |
| `cached_prayer_times` | `lat_lng_date` | `PrayerTimes` |

---

## 5. Navigation

### 5.1 Bottom Navigation Bar (5 tabs)

| Index | Label | Icon (inactive) | Icon (active) | Route |
|---|---|---|---|---|
| 0 | Home | `home_outlined` | `home` (filled) | `/` |
| 1 | Calendar | `calendar_today_outlined` | `calendar_today` | `/imsakiyah` |
| 2 | Checklist | `rule_outlined` | `rule` (filled) | `/checklist` |
| 3 | Reports | `bar_chart_outlined` | `bar_chart` | `/laporan` |
| 4 | Tools | `auto_fix_high_outlined` | `auto_fix_high` (filled) | `/tools` |

- Bottom nav is persistent across all 5 tabs (shell route via GoRouter)
- Safe area padding (bottom) applied to nav bar (`pb: 24dp`)
- Active tab: `primary` text + filled icon
- Inactive tab: `text-secondary` color

### 5.2 Full Route Map

```
/                           → DashboardScreen
  /qibla                    → QiblaScreen (push, no bottom nav)
/imsakiyah                  → ImsakiyahScreen
/checklist                  → ChecklistScreen
/laporan                    → LaporanScreen
/tools                      → ToolsScreen (hub for Dzikir, Quran, Qibla)
  /tools/dzikir             → DzikirScreen
  /tools/quran              → QuranListScreen
    /tools/quran/:surahId   → QuranReadingScreen
    /tools/quran/:surahId/murattal → QuranMurattalScreen
  /tools/qibla              → QiblaScreen
/settings                   → SettingsScreen (push from Dashboard header)
```

---

## 6. Feature Specifications

---

### 6.1 Dashboard

**Route:** `/`  
**Description:** App home screen showing next prayer, daily prayer schedule, checklist summary, and weekly progress.

#### UI Components

**Header (sticky)**
- Left: Circular user avatar (40dp, primary border 2dp) + greeting text ("Welcome back," / user name "Assalamu'alaikum, [Name]")
- Right: Notification bell `IconButton` → opens notification settings

**Next Prayer Hero Card**
- Full-width card, `bg-primary`, `borderRadius: 24dp`, `padding: 20dp`, `boxShadow: lg`
- Content:
  - Label: "Next Prayer" with `schedule` icon
  - Title: `"{PrayerName} at {HH:mm}"` — `displayLarge` weight 800
  - Subtitle: `"Countdown: HH:mm:ss"` — live countdown timer updating every second
  - Actions row:
    - "View Qibla" button (`black bg`, `white text`, `explore icon`, `borderRadius: full`)
    - Volume/mute toggle button (`white/30 backdrop-blur`, `rounded-full`)
  - Decorative: white/20 blurred circle blob (top-right, size 120dp)

**Prayer Times Horizontal Scroll**
- Section title: "Daily Prayer Times" + "Today" chip (`primary/10 bg`, `primary text`)
- Horizontal `ListView.builder`, no scroll indicator, `padding: 16dp horizontal`
- Each card: `width: 112dp`, `borderRadius: 16dp`, `border: primary/10`
  - Icon (Material Symbol): Fajr→`wb_twilight`, Dhuhr→`wb_sunny`, Asr→`filter_drama`, Maghrib→`wb_twilight`, Isha→`dark_mode`
  - Prayer name (`sm font-bold`)
  - Time string (`xs text-secondary`)
- **Active prayer card:** `bg-primary/10`, `border-2 border-primary`, primary text color
- **Adhan/Iqamah variant:** Active card shows notification badge (small bell icon, white circle, shadow, absolute top-right)

**Daily Checklist Summary Card**
- Title: "Today's Checklist" + subtitle "{n} dari {total} Ibadah selesai"
- Circular SVG progress indicator (48dp, `strokeWidth: 4`, `primary` stroke)
- Percentage text centered inside circle
- 2 preview items: "Sholat Fardhu (4 of 5)" and "Tilawah Quran (1 Juz)"
  - Completed items: `check_circle` icon in `primary` color
- "View Full Checklist" CTA button → navigates to `/checklist`

**Weekly Progress Chart**
- Title: "Weekly Progress"
- `Container` with `bg-surface`, `borderRadius: 16dp`, `padding: 20dp`
- 7 vertical bars (Mon–Sun): each bar is `Expanded`, `bg-primary/20`, with `primary` fill overlay proportional to completion %
- Day labels below each bar: `10sp`, `font-bold`, `text-secondary`

#### Behavior

- Countdown timer refreshes every 1 second via `Timer.periodic`
- Prayer times are calculated from device location via `adhan` package on app start
- If location unavailable, use last cached location; if none, prompt user
- Notification badge on prayer card: shown when Adhan has been called (within current window)
- Tapping the Next Prayer card → navigates to Imsakiyah screen

#### Acceptance Criteria

- [ ] Correct prayer times displayed for device's current GPS location
- [ ] Countdown shows real-time seconds tick
- [ ] Active prayer card highlighted with `primary` border and color
- [ ] Checklist summary reflects today's actual completion state from local storage
- [ ] Weekly chart bars reflect daily worship logs from past 7 days
- [ ] Works fully offline (cached prayer times used when no internet)

---

### 6.2 Prayer Calendar (Imsakiyah)

**Route:** `/imsakiyah`  
**Description:** Full Hijri-calendar view of prayer times, organized by month, with location selection.

#### UI Components

**Header**
- Back arrow + "Prayer Calendar" (centered, `headlineMedium`) + `more_vert` menu button

**Month Selector**
- Horizontal scrolling chip row (no scrollbar)
- Selected: `bg-primary`, `text-slate-900`, `font-semibold`, `borderRadius: full`
- Unselected: `bg-surface`, `text-secondary`, `borderRadius: full`
- Months shown in Hijri format: "Ramadan 1445H", "Shawwal 1445H", etc.

**Location Card**
- `bg-surface`, `borderRadius: 16dp`, `border: 1dp`
- `location_on` icon (primary) + "Your Location" label + city name (e.g., "Jakarta, Indonesia")
- `expand_more` chevron — tapping opens city search/picker

**Prayer Times Table**
- 7-column grid: Day | Fajr | Sunrise | Dhuhr | Asr | Maghrib | Isha
- Header row: `bg-primary/10`, `10sp font-bold uppercase tracking-wider text-secondary`
- Data rows: alternating subtle bg for readability
- Today's row: highlighted with `primary/5` background, bold text

#### Behavior

- Loads prayer times for entire selected month using `adhan` package
- Location defaults to last GPS fix; editable via city search
- City search: local bundled list of major Indonesian cities (offline), Geocoding API optional
- Changing month or location recalculates and re-renders table
- Scroll position resets to today's row on initial load

#### Acceptance Criteria

- [ ] Displays complete monthly prayer timetable for selected Hijri month
- [ ] Today's row is visually highlighted
- [ ] Month chip scroll updates table data
- [ ] Location change triggers recalculation
- [ ] Works offline with bundled city coordinates

---

### 6.3 Daily Checklist

**Route:** `/checklist`  
**Description:** Daily worship completion tracker with custom checklist items and progress visualization.

#### UI Components

**Header**
- "Daily Worship" (`headlineMedium`) + date string ("Tuesday, 24 Oct") + calendar icon button (date picker)

**Progress Card**
- `bg-slate-900 / bg-primary/10 (dark)`, `borderRadius: 16dp`, `padding: 20dp`
- Decorative `auto_awesome` icon (64sp, opacity 10%, top-right)
- "Today's Goal" label (`xs uppercase tracking-wider text-slate-400`)
- Percentage: "{n}% Complete" (`displayLarge font-bold white`)
- "{completed} / {total} Tasks" (`primary color xs`)
- Progress bar: `h-12dp`, `bg-white/10`, `primary fill`, `borderRadius: full`
- Motivational quote text below bar (`xs text-slate-300`)

**Task List**

Section header: "Religious Tasks" (`sm font-bold uppercase tracking-widest text-secondary`)

Each checklist item:
- `Container` with `bg-surface / bg-primary/5 (dark)`, `borderRadius: 12dp`, `border: 1dp`
- Custom checkbox: 24dp square, `border-2 border-primary/30`, `borderRadius: 6dp`
  - Checked state: `bg-primary`, white checkmark SVG inside
- Task label: `bodyLarge font-medium`
- Optional: sub-label (e.g., target count for Tilawah)

**Default checklist items (seeded on first launch):**

| Item | Category | Default Target |
|---|---|---|
| Sholat Fajr | Sholat Fardhu | 1x |
| Sholat Dhuhr | Sholat Fardhu | 1x |
| Sholat Asr | Sholat Fardhu | 1x |
| Sholat Maghrib | Sholat Fardhu | 1x |
| Sholat Isha | Sholat Fardhu | 1x |
| Tilawah Quran | Tilawah | 1 Juz |
| Dzikir Pagi | Dzikir | 1 session |
| Dzikir Petang | Dzikir | 1 session |
| Sholat Sunnah Rawatib | Sunnah | 1x |
| Shodaqoh | Charity | 1x |

#### Behavior

- Checklist resets daily at midnight (new date key in Hive)
- Checking/unchecking an item updates Hive immediately (no "save" button)
- Progress card and percentage update reactively via Riverpod
- Motivational quotes rotate from a bundled list
- User can add/remove/reorder checklist items (edit mode)
- Completion data written to `worship_logs` for use by Reports feature

#### Acceptance Criteria

- [ ] Default 10 items seeded on first launch
- [ ] Checking item updates progress bar + percentage in real time
- [ ] Data persists across app restarts (Hive)
- [ ] New empty checklist created automatically on date change
- [ ] Historical completion accessible by Reports feature

---

### 6.4 Dzikir

**Route:** `/tools/dzikir`  
**Description:** Guided morning and evening remembrance (Dzikir) with Arabic text, transliteration, translation, and tap counter.

#### UI Components

**Header (sticky)**
- `back arrow` + "Dzikir Pagi & Petang" (centered, `titleLarge font-bold`) + `info` icon button
- `bg-surface/80`, `backdropFilter: blur(12dp)`, `borderBottom: 1dp primary/10`

**Tab Bar**
- 2 tabs: "Pagi" (Morning) and "Petang" (Evening)
- Active tab: `border-bottom-2 border-primary`, `text-primary`, `font-semibold`
- Inactive tab: `text-secondary`

**Hero Banner**
- `text-center`, `padding: 32dp vertical`
- `bg-gradient(primary/5 → transparent, top → bottom)`
- Title: "Dzikir Pagi / Petang" (`headlineMedium font-bold`)
- Subtitle: context text in Indonesian (`bodySmall text-secondary max-width: 280dp`)

**Dzikir Cards (scrollable list)**
- Each card: `bg-surface`, `borderRadius: 16dp`, `border: 1dp primary/10`, `padding: 20dp`, `margin: 8dp bottom`
- **Arabic text** (`Amiri font`, `24sp`, `RTL direction`, `line-height: 2.0`, `text-right`)
- **Transliteration** (`bodySmall`, `italic`, `text-secondary`, `mt: 12dp`)
- **Translation (Indonesian)** (`bodyMedium`, `text-primary`, `mt: 8dp`)
- **Counter row:**
  - "Dibaca: {count} / {target}x" label
  - `+` tap button (`bg-primary/10`, `text-primary`, `borderRadius: full`, `size: 40dp`)
  - Counter increments on tap; fills to target
  - When target reached: button becomes `check_circle` (green), card shows completion glow

#### Behavior

- Default content: bundled local JSON with standard Dzikir Pagi (~20 items) and Dzikir Petang (~20 items)
- Counter state persisted per dzikir per session in Hive (`dzikir_counters` box)
- Counter resets daily (tied to date)
- "Pagi" tab auto-selected between Fajr and Dhuhr; "Petang" between Maghrib and Isha; user can override
- Info button → bottom sheet with brief explanation of dzikir practice

#### Acceptance Criteria

- [ ] Arabic text renders correctly with Amiri font, RTL direction
- [ ] Tap counter increments and persists within the day
- [ ] Counter resets the next day
- [ ] Tab switches between Pagi and Petang content
- [ ] Completion state shown when all counters reach target

---

### 6.5 Reports (Laporan)

**Route:** `/laporan`  
**Description:** Visual analytics of worship completion across weekly, monthly, and yearly timeframes.

#### UI Components

**Header**
- Back arrow + "Worship Quality Report" (centered) + `share` icon button

**Tab Bar**
- 3 tabs: Weekly · Monthly · Yearly
- Active: `border-bottom-2 border-primary text-primary`
- Tab bar: `border-bottom: 1dp`

**Main Chart Card**
- `bg-surface`, `borderRadius: 16dp`, `border: 1dp`, `padding: 20dp`
- Header row:
  - Left: `analytics` icon badge (`bg-primary/10`, `primary`, `borderRadius: 12dp`, `40dp size`)
  - Center: "Daily Completion" label (`bodySmall text-secondary`) + percentage (`displayLarge font-bold`)
  - Right: trend chip: `trending_up` icon + delta % (`text-emerald-500` if positive)
- **Bar Chart:**
  - `height: 160dp`, flex row of 7 bars (weekly) or 30/12 bars
  - Each bar: `Expanded`, `bg-primary/20` track, `bg-primary` fill overlay (proportional to % complete)
  - `borderRadius: top only (full)`
  - Day/date labels below (`10sp font-bold text-secondary uppercase`)
- Tapping a bar → shows tooltip with exact date + completion %

**Summary Stats Row (below chart)**
- 3 stat cards in a row:
  - Best streak: "{n} days" + `local_fire_department` icon
  - Average: "{n}%" + `percent` icon
  - Total completed: "{n} tasks" + `check_circle` icon

#### Behavior

- Weekly: shows past 7 days (Mon–Sun of current week)
- Monthly: shows all days of current month (30/31 bars, may need scroll)
- Yearly: shows 12 months as bars
- Data sourced from `worship_logs` Hive box (daily completion records)
- Share button: generates a shareable image/text summary of current period stats

#### Acceptance Criteria

- [ ] Correct bar heights proportional to actual daily completion %
- [ ] Tab switching updates chart data and labels
- [ ] Tooltip on bar tap shows date + details
- [ ] Summary stats calculated correctly from logs
- [ ] Empty state when no logs exist ("Start tracking to see your progress")

---

### 6.6 Qibla Finder

**Route:** `/tools/qibla` or `/qibla` (accessible from Dashboard hero card)  
**Description:** Compass-based Qibla direction finder showing the direction of Mecca.

#### UI Components

**Header**
- Back arrow + "Qibla Finder" (centered) + `my_location` button (top-right, re-centers GPS)

**Main Content (centered)**
- Location display: `location_on` icon (primary) + city name + Qibla degree ("142.3° from North")
- **Compass widget:**
  - Circular compass with N/S/E/W labels
  - Rotating needle pointing to Qibla direction
  - Mosque silhouette icon overlaid at compass center (fade-to-transparent mask top)
  - Green pointer / arrow indicating Qibla direction
- Accuracy indicator: "High accuracy" / "Low accuracy" based on sensor confidence

#### Behavior

- Uses `flutter_qiblah` package for Qibla calculation + `flutter_compass` for device heading
- Rotates compass ring based on device orientation (sensor stream)
- Displays degree from North
- If location permission denied → prompt to enable, fallback to manual city entry
- Mosque silhouette uses a local SVG/image asset with `ShaderMask` fade

#### Acceptance Criteria

- [ ] Compass rotates smoothly with device orientation
- [ ] Qibla arrow points to correct direction based on GPS coordinates
- [ ] Works offline (no internet needed for calculation)
- [ ] Graceful fallback if compass sensor unavailable

---

### 6.7 Quran Reading

**Route:** `/tools/quran` → `/tools/quran/:surahId`  
**Description:** Full Quran reader with Arabic text, Indonesian translation, and verse-by-verse display.

#### UI Components

**Surah List Screen (`/tools/quran`)**
- Search bar at top
- `ListView` of 114 Surahs: number badge + Arabic name + Latin name + verse count + Juz info

**Reading Screen (`/tools/quran/:surahId`)**

Header (sticky, `bg-surface/80 backdrop-blur`):
- Back arrow
- Center column: Surah name (Arabic, `Amiri`) + "Juz {n}" label + verse count
- `more_vert` menu (bookmarks, jump to verse, settings)

**Bismillah banner:** Centered, Arabic font, before verse 1 (except Surah 9)

**Verse Cards:**
- Each verse: `Container`, `bg-surface`, `borderRadius: 12dp`, `padding: 16dp`, `border: 1dp`
- Verse number badge: small circle, `bg-primary/10`, `primary text`, left-aligned
- **Arabic text:** `Amiri`, `28sp`, `RTL`, `line-height: 2.2`, right-aligned, full width
- **Transliteration** (optional, toggled in settings): `bodySmall italic text-secondary`
- **Indonesian translation:** `bodyMedium text-primary`, left-aligned, `mt: 8dp`
- Verse action row: `bookmark`, `share`, `play` (Murattal) icons

#### Behavior

- Quran data: bundled local JSON asset (`assets/quran/quran_id.json`) — 114 surahs, Arabic + Indonesian translation
- Reading position persisted per Surah (last verse read)
- Bookmarks stored in Hive
- "Play" icon on verse → navigates to Murattal screen for that Surah starting at that verse
- Font size adjustable via settings (stored preference)

#### Acceptance Criteria

- [ ] All 114 Surahs accessible
- [ ] Arabic text renders with Amiri font, correct RTL layout
- [ ] Indonesian translation displayed below each verse
- [ ] Reading position saved across app restarts
- [ ] Bookmarking a verse persists in Hive
- [ ] Works fully offline

---

### 6.8 Quran Murattal

**Route:** `/tools/quran/:surahId/murattal`  
**Description:** Audio recitation player synchronized with Quran text display.

#### UI Components

**Header:** Same as Quran Reading (Surah name + Juz info)

**Quran Text:** Same as Reading screen — synchronized verse highlight follows audio playback

**Audio Player (bottom persistent panel)**
- Reciter name + surah name
- Progress slider (current position / total duration)
- `skip_previous` | `replay_10` | Play/Pause (`play_circle` / `pause_circle`, 56dp) | `forward_10` | `skip_next`
- Playback speed selector (0.75x, 1x, 1.25x, 1.5x)
- Sleep timer button

#### Behavior

- Audio source: Bundled MP3s for commonly used Surahs (short ones: Al-Fatihah, Juz Amma) — OR streamed from a free Quran audio API (e.g., mp3quran.net)
- Currently playing verse highlighted with `primary/10 bg` + left border accent
- Auto-scrolls to current verse during playback
- Background audio playback (continues when app backgrounded)
- Notification media controls shown in system tray during playback

#### Acceptance Criteria

- [ ] Audio plays and pauses correctly
- [ ] Current verse highlighted in sync with audio (best effort with timed segments)
- [ ] Background playback works (audio continues when screen off)
- [ ] System notification with media controls displayed during playback
- [ ] Playback speed adjustment works

---

### 6.9 Settings

**Route:** `/settings`  
**Description:** User profile, notification preferences, display preferences, and app info.

#### UI Components

**Header (sticky)**
- Back arrow + "Settings" (`titleLarge font-bold`) + no right action

**Profile Section**
- Avatar: 64dp circle, `bg-primary/20`, `border-2 border-primary`, initials or photo
- Name: (`titleMedium font-bold`)
- Email: (`bodySmall text-secondary`)
- Edit button (`text-primary`, `edit` icon, top-right of card) → edit name/email inline

**Notification Settings Group**

Label: "NOTIFICATIONS" (`labelSmall uppercase tracking-wider sage color`)

Rows (separated by thin divider):
- **Adhan Notification** — per prayer toggle: Fajr, Dhuhr, Asr, Maghrib, Isha
- **Iqamah Reminder** — offset in minutes (default: 10 min, stepper or picker)
- **Daily Checklist Reminder** — time picker (default: 9:00 AM)

Each row: `leading icon (bg-primary/10, rounded-lg, 40dp)` + `label + subtitle` + **iOS-style toggle**

**iOS-style toggle spec:**
- Size: `51dp × 31dp`
- Track: `bg-cream (off)` / `bg-primary (on)`, `borderRadius: full`
- Thumb: `27dp` white circle, `shadow-md`, animates left↔right on toggle
- Implemented via `AnimatedContainer` + `GestureDetector`

**Display Settings Group**

Label: "DISPLAY"

Rows:
- **Dark Mode**: Light / Dark / Auto (3-way segmented control or cycle toggle)
- **Font Size**: Small / Medium / Large (affects Quran + Dzikir text)
- **Language**: Indonesian / English (UI language, not Quran translation)

**About Group**

Label: "ABOUT"

Rows:
- App Version: "JamShalat v1.0.0"
- Privacy Policy (launches in-app browser)
- Rate the App (links to store)
- Contact / Feedback

#### Behavior

- All settings persisted in Hive `settings` box immediately on change
- Dark mode change applies instantly (no restart needed) via ThemeMode Riverpod provider
- Notification toggles register/unregister `flutter_local_notifications` channels
- Iqamah offset: default 10 minutes, adjustable per prayer
- Profile name/email stored locally only (no backend account system in v1.0)

#### Acceptance Criteria

- [ ] All toggle states persisted and restored on restart
- [ ] Dark mode applies instantly with animation
- [ ] Adhan/Iqamah notifications schedule correctly based on calculated prayer times
- [ ] Notifications cancel when their toggle is turned off
- [ ] iOS-style toggle animation is smooth (no jank)

---

## 7. Data Model

### 7.1 Hive Boxes & Schemas

```dart
// Settings box (key-value)
class AppSettings {
  String userName;          // 'Alex Rivers'
  String userEmail;         // 'alex@example.com'
  ThemeMode themeMode;      // ThemeMode.system
  double arabicFontSize;    // 24.0
  String uiLanguage;        // 'id' | 'en'
  Map<String, bool> adhanEnabled;   // {'fajr': true, 'dhuhr': true, ...}
  Map<String, int> iqamahOffset;    // {'fajr': 15, 'dhuhr': 10, ...} in minutes
  DateTime? checklistReminderTime;
  double? lastLat;
  double? lastLng;
  String? lastCityName;
}

// Checklist box
@HiveType(typeId: 1)
class ChecklistItem {
  String id;           // UUID
  String title;        // 'Sholat Fajr'
  String category;     // 'sholat_fardhu'
  String? subtitle;    // '1 Juz'
  int sortOrder;
  bool isCustom;       // false for default items
}

// Daily log box (keyed by 'yyyy-MM-dd')
@HiveType(typeId: 2)
class DailyWorshipLog {
  String date;                      // '2026-03-06'
  Map<String, bool> completedItems; // {'item_id': true}
  int totalItems;
  int completedCount;
  double completionPercent;
}

// Dzikir counter box (keyed by 'dzikir_id:yyyy-MM-dd')
@HiveType(typeId: 3)
class DzikirCounter {
  String dzikirId;
  String date;
  int count;
  int target;
}

// Bookmarks box
@HiveType(typeId: 4)
class QuranBookmark {
  int surahId;
  int verseId;
  String surahName;
  String verseText;   // Arabic snippet
  DateTime savedAt;
}

// Cached prayer times box (keyed by 'lat_lng_yyyy-MM-dd')
@HiveType(typeId: 5)
class CachedPrayerTimes {
  String key;
  double lat;
  double lng;
  String date;
  DateTime fajr;
  DateTime sunrise;
  DateTime dhuhr;
  DateTime asr;
  DateTime maghrib;
  DateTime isha;
}
```

---

## 8. Third-Party Dependencies

| Package | Version | Purpose |
|---|---|---|
| `flutter_riverpod` | ^2.x | State management |
| `riverpod_annotation` | ^2.x | Code gen for providers |
| `go_router` | ^13.x | Declarative navigation |
| `hive_flutter` | ^1.x | Local key-value storage |
| `hive_generator` | ^2.x | Hive TypeAdapter codegen |
| `adhan` | ^1.x | Prayer time calculation (offline) |
| `geolocator` | ^11.x | GPS location |
| `geocoding` | ^3.x | Reverse geocoding (city name) |
| `flutter_qiblah` | ^2.x | Qibla direction calculation |
| `flutter_compass` | ^0.x | Device compass heading |
| `flutter_local_notifications` | ^17.x | Adhan + Iqamah notifications |
| `just_audio` | ^0.x | Quran Murattal audio playback |
| `audio_service` | ^0.x | Background audio + media controls |
| `google_fonts` | ^6.x | Plus Jakarta Sans |
| `material_symbols_icons` | ^4.x | Material Symbols icon set |
| `build_runner` | ^2.x | Code generation runner |

**Quran Data Sources:**
- Arabic text + Indonesian translation: bundled as `assets/quran/quran_id.json` (local, offline)
- Audio (Murattal): streamed from `https://server6.mp3quran.net/` (Mishari Al-Afasy) or bundled short Surahs

---

## 9. Non-Functional Requirements

### 9.1 Performance

- App cold start: < 2 seconds on mid-range devices (Snapdragon 700 series / Apple A14)
- Bottom nav tab switch: < 150ms
- Prayer time calculation: < 50ms (synchronous, offline)
- Quran verse list render: use `ListView.builder` (lazy loading), never `ListView` with all children

### 9.2 Offline-First

- Core features work with no internet: Dashboard, Checklist, Dzikir, Reports, Qibla, Quran Reading, Settings
- Quran Murattal: short Surahs bundled; longer Surahs require connectivity (graceful fallback shown)
- Prayer times: cached per location+date in Hive; recalculated on location change

### 9.3 Accessibility

- Minimum touch target: 48×48dp for all interactive elements
- All icons have semantic labels (`Semantics(label: ...)`)
- Arabic text has `textDirection: TextDirection.rtl` explicitly set
- Sufficient contrast ratios for both light and dark themes (WCAG AA)

### 9.4 Dark Mode

- All screens must look correct in both light and dark mode
- No hardcoded `Colors.white` or `Colors.black` — use `AppColors` tokens only
- Theme transitions are animated (Material 3 `AnimatedTheme`)

### 9.5 Localization

- v1.0: Indonesian (id) as primary language, English (en) as secondary
- Use `flutter_localizations` + `intl` package for date/number formatting
- All UI strings in `AppLocalizations` (ARB files); no hardcoded Indonesian strings in widgets

---

## 10. Permissions

| Permission | Reason | Timing |
|---|---|---|
| `ACCESS_FINE_LOCATION` (Android) / `NSLocationWhenInUseUsageDescription` (iOS) | Prayer time calculation, Qibla direction | On first Dashboard load |
| `POST_NOTIFICATIONS` (Android 13+) | Adhan and Iqamah notifications | On Settings → Notifications first toggle |
| `SCHEDULE_EXACT_ALARM` (Android 12+) | Exact Adhan notification timing | When notification enabled |
| Background audio (iOS: `audio` background mode) | Murattal background playback | On Murattal first play |

**Permission UX:**
- Never request permission without explaining why first (show rationale bottom sheet)
- Graceful degradation: if location denied → manual city picker; if notifications denied → remind once, then respect

---

## 11. Out of Scope (v1.0)

The following features are **explicitly excluded** from v1.0 to keep scope focused:

- User accounts / cloud sync (no backend, local-only)
- Social features (sharing worship progress to social media, leaderboards)
- Full Quran audio library (only short Surahs bundled/streamed)
- Quran memorization (Hafalan) mode
- Hijri calendar widget beyond Imsakiyah
- Community / forum features
- Multi-user / family tracking
- Wear OS / watchOS companion
- Widgets (home screen app widget)
- Apple Watch prayer time complication
- In-app purchases or subscriptions
- Push notifications from a server (only local scheduled notifications)

---

*PRD v1.0 — JamShalat — March 2026*
