Skip to content

CreatorB/flutter_syathiby

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

35 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Syathiby App

Attendance and staff management application for Ma'had Tahfizh al-Qur'an al-Imam as-Syathiby.

Enhanced and customized version of Syathiby Vendor App β€” https://github.com/creatorb/flutter-syathiby-vendor

πŸ“‹ Changelog: See CHANGELOG.md for full version history.


πŸ“‘ Table of Contents


πŸ“š Quick Documentation Links


πŸš€ Quick Start

# 1. Clone repository
git clone https://github.com/creatorb/flutter_syathiby.git
cd flutter_syathiby

# 2. Install dependencies
fvm flutter pub get

# 3. Generate code
fvm flutter pub run build_runner build --delete-conflicting-outputs

# 4. Run app (PROD flavor β€” automatically uses production URL)
fvm flutter run --flavor prod --dart-define=FLAVOR=prod

# 5. Run app (LOCAL flavor β€” automatically uses local URL)
fvm flutter run --flavor local --dart-define=FLAVOR=local

πŸ“‹ Prerequisites

  • Flutter SDK: Managed via FVM
  • Android Studio / Xcode (for Android/iOS builds)
  • ADB (Android Debug Bridge) for device deployment
  • Git

Install FVM (Flutter Version Manager)

# Windows (PowerShell)
choco install fvm

# macOS
brew tap leoafarias/fvm
brew install fvm

# Linux / Manual
dart pub global activate fvm

πŸ”§ Installation

1. Set Up FVM and Flutter SDK

# Install the Flutter version used by this project
fvm install

# Activate FVM version
fvm use

2. Install Dependencies

fvm flutter pub get

3. Generate Models & Code

fvm flutter pub run build_runner build --delete-conflicting-outputs

4. (Optional) Set Up Keystore for Release Build

See the Keystore section below.


🌐 URL Environment Setup (Flavor-Based)

The app uses automatic flavor-based URL configuration. The backend URL is selected automatically based on the active flavor:

Default Configuration (Built-in)

Flavor API URL Link Base App Name
prod https://aplikasi.syathiby.id/geten/ https://aplikasi.syathiby.id Syathiby
local http://192.168.50.100/aplikasi/geten/ http://192.168.50.100/aplikasi Syathiby LOCAL

⚑ Usage

Production:

fvm flutter run --flavor prod --dart-define=FLAVOR=prod

βœ… Automatically uses: https://aplikasi.syathiby.id

Local Development:

fvm flutter run --flavor local --dart-define=FLAVOR=local

βœ… Automatically uses: http://192.168.50.100/aplikasi

Note: --dart-define=FLAVOR=xxx tells the app which flavor is active so the correct URL is selected automatically.

πŸ”§ Changing the Default URL

If your local server IP is not 192.168.50.100, edit:

πŸ“„ lib/res/flavor_config.dart

static const Map<String, Map<String, String>> _configs = {
  'prod': {
    'API_URL': 'https://aplikasi.syathiby.id/geten/',
    'LINK_BASE': 'https://aplikasi.syathiby.id',
  },
  'local': {
    'API_URL': 'http://192.168.1.100/aplikasi/geten/',  // ← Change IP here
    'LINK_BASE': 'http://192.168.1.100/aplikasi',       // ← and here
  },
};

After editing, rebuild:

fvm flutter clean
fvm flutter pub get
fvm flutter run --flavor local --dart-define=FLAVOR=local

πŸŽ›οΈ Runtime URL Override (Without Rebuild)

You can also temporarily override the URL at runtime without rebuilding:

  1. Launch the app (any flavor)
  2. On the Login screen, long-press the Syathiby logo
  3. A dialog appears showing the active URL
  4. Enter your custom URL:
    API URL:   http://192.168.1.200/aplikasi/geten/
    Link Base: http://192.168.1.200/aplikasi
    
  5. Tap "Save & Restart"

The override is stored in SharedPreferences and persists until manually reset.

πŸ”„ Reset to Flavor Default

  1. Long-press the logo on the Login screen
  2. Clear all fields
  3. Tap "Save & Restart"

The app will revert to the default URL for the active flavor.

πŸ’‘ Development Tips

Find your server's local IP:

Windows:

ipconfig

macOS / Linux:

ifconfig
# or
ip addr show

Look for an IP starting with 192.168.x.x or 10.x.x.x.

Environment detection:

The app automatically detects the environment based on the active URL:

  • Local IP (192.168.x.x, 10.x.x.x, 172.16–31.x.x, localhost) β†’ LOCAL (red banner)
  • Other public domain β†’ PROD (green banner, hidden in release)

πŸ“ Relevant File Structure

flutter_syathiby/
└── lib/res/
    β”œβ”€β”€ flavor_config.dart          # URL configuration per flavor
    β”œβ”€β”€ environment_config.dart     # Runtime config + URL override logic
    └── env.dart                    # Legacy (optional, for MAPS_API_KEY)

πŸ› URL Environment Troubleshooting

Issue: URL still wrong after changing flavor

# Make sure to pass --dart-define=FLAVOR
fvm flutter run --flavor local --dart-define=FLAVOR=local
# ⚠️ NOT: fvm flutter run --flavor local  (missing --dart-define)

Issue: Cannot connect to local server

  1. βœ… Verify the backend server is running
  2. βœ… Device and server are on the same network (same Wi-Fi)
  3. βœ… Test the URL in a browser: http://192.168.x.x/aplikasi/geten/
  4. βœ… Check firewall is not blocking the connection
  5. βœ… Use the device's IP address, not localhost

Issue: Environment label shows PROD instead of LOCAL

  • Long-press the logo to verify the actual URL in use
  • Ensure the URL uses http:// (not https://) for local
  • Confirm the IP matches the local pattern: 192.168.x.x

🎨 Color Palette & Theme

The app uses a custom green color palette with a modern 3D gradient design.

Base Colors

Role Hex Code Color Preview
Primary #26774e #26774e
Dark #19633f #19633f
Light #82aa68 #82aa68

Theme Features

✨ Modern 3D Gradient Design:

  • Strong gradient colors using base color palette (Dark β†’ Primary β†’ Light)
  • 3D elevation effects with deep shadows (elevation 8-16)
  • Bold visual depth with multi-layer shadows
  • Material 3 design system with enhanced depth perception
  • Gradient accents on AppBar, buttons, cards, and navigation
  • Support for dark and light modes with adaptive gradients
  • Rounded corners (16-28px) and generous padding
  • High-contrast color scheme for better visibility

Key Design Elements:

  • 🎨 AppBar: Gradient background with 8px elevation
  • πŸ’³ Cards: Strong 3D shadow with 8-10px elevation
  • πŸ”˜ Buttons: Bold gradient colors with 8-12px elevation
  • πŸ“± Navigation Bar: Gradient indicators with 12px elevation
  • 🎯 Inputs: Gradient focus borders (2.5px)
  • ✨ Dialogs & Sheets: Deep shadows with 16px elevation

3D Icon Grid Design

🎯 Elegant 3D Menu Icons: All grid menu icons throughout the app feature an elegant 3D design:

  • Multi-layer shadows: 3 shadow layers for realistic depth perception
    • Top-left highlight (simulated light source)
    • Main shadow (bottom-right)
    • Additional depth shadow (deeper)
  • Gradient backgrounds: Smooth color transitions from light to dark
  • Icon shadows: Individual icon elements have subtle shadows
  • Text shadows: Labels feature depth shadows
  • Rounded corners: 20px border radius for smooth, modern look
  • Border highlights: Semi-transparent borders for edge definition
  • Compact size: 58x58px menu icon containers for cleaner layout density

Applied in:

  • Home screen menu grids (all menu categories)
  • Prayer/Ibadah screen icons
  • Book selection grid
  • All other menu navigation elements

Attendance Button Motion (Premium + Fast)

The main attendance CTA (Absen Masuk / Absen Pulang) now uses a compact, premium interaction model:

  • Compact geometry: 44px rendered height on Home for a tighter, modern look
  • Fast premium tap animation: quick bounce timing tuned for responsiveness
  • Fetch-aware loading state: inline spinner + dynamic label (Absen masuk... / Absen pulang...)
  • Tap lock during processing: prevents accidental double-submit while status is updating
  • Smooth state handoff: waits for refreshed presence/profile data before returning to idle

Reusable 3D Widgets

πŸ“¦ Custom 3D Components: The app includes reusable widgets for consistent 3D styling:

Elegant3DIcon - Beautiful 3D icon container

  • Multi-layer shadows with adjustable depth
  • Gradient backgrounds
  • Customizable size and colors
  • Icon shadow effects

Elegant3DCard - 3D elevated card widget

  • Multi-layer shadow system
  • Optional gradient backgrounds
  • Customizable borders and corners
  • Adjustable depth intensity (0.0 to 1.0)

Elegant3DButton - compact premium action button

  • Fast bounce animation on press
  • Built-in loading mode (isLoading) with inline progress indicator
  • Dynamic loading label support (loadingLabel)
  • Designed for primary CTAs like attendance check-in/check-out

Usage Example:

// Simple 3D icon
Elegant3DIcon(
  iconData: Icons.home,
  size: 58,
  iconSize: 24,
)

// Interactive 3D icon button
Elegant3DIconButton(
  iconData: Icons.settings,
  onTap: () { /* action */ },
  depth: 0.72,
)

// Compact attendance button with loading state
Elegant3DButton(
  label: 'Absen Masuk',
  icon: Icons.check_circle,
  height: 44,
  depth: 0.62,
  isLoading: false,
  loadingLabel: 'Absen masuk...',
  onPressed: () { /* action */ },
)

// 3D card with gradient
Elegant3DCard(
  borderRadius: 20,
  useGradient: true,
  child: YourContent(),
)

πŸ“„ Theme Configuration Files:

To modify the theme:

  1. Edit the color values in lib/res/colors.dart
  2. Update theme configuration in lib/app.dart
  3. Adjust 3D icon effects in buildListMenu() method or use reusable widgets
  4. Customize Elegant3DIcon and Elegant3DCard depth parameter (0.0 - 1.0)
  5. Rebuild the app with fvm flutter run

πŸ’» Development

Run App (Development Mode)

# PROD flavor (automatically uses https://aplikasi.syathiby.id)
fvm flutter run --flavor prod --dart-define=FLAVOR=prod

# LOCAL flavor (automatically uses http://192.168.50.100/aplikasi)
fvm flutter run --flavor local --dart-define=FLAVOR=local

# Specify device
fvm flutter run -d <device-id> --flavor prod --dart-define=FLAVOR=prod
fvm flutter run -d 127.0.0.1:5555 --flavor local --dart-define=FLAVOR=local

Hot Reload & Restart

  • Hot Reload: r (in terminal while app is running)
  • Hot Restart: R
  • Quit: q

Web Development

Run Flutter web version locally for development and debugging:

Production Mode

# Simulates production environment (uses production API)
fvm flutter run -d chrome
  • URL: http://localhost:8080
  • API: https://aplikasi.syathiby.id (production)
  • Best for: Final testing before deployment

Local/Development Mode

# Development environment (uses local backend API)
fvm flutter run -d chrome --web-hostname 192.168.50.100 --web-port 8082
  • URL: http://192.168.50.100:8082
  • API: http://192.168.50.100/aplikasi (local)
  • Hot reload: Enabled (press r for instant reload)
  • Best for: Debugging with local backend

Run Both Simultaneously

# Starts PROD and LOCAL servers in separate browser windows
.\run-web-both.ps1

# PROD: http://localhost:8080
# LOCAL: http://192.168.50.100:8082

See WEB_DEV_CHEATSHEET.md for more web development tips & tricks!

Code Generation

Run whenever you modify models or environment config:

fvm flutter pub run build_runner build --delete-conflicting-outputs

Watch mode (auto-generates on file changes):

fvm flutter pub run build_runner watch --delete-conflicting-outputs

Clean Build

If you encounter cache or dependency issues:

fvm flutter clean
fvm flutter pub get
fvm flutter pub run build_runner build --delete-conflicting-outputs

πŸ”¨ Building & Deployment

Android APK (Debug)

# PROD flavor
fvm flutter build apk --debug --flavor prod --dart-define=FLAVOR=prod

# LOCAL flavor
fvm flutter build apk --debug --flavor local --dart-define=FLAVOR=local

Output: build/app/outputs/flutter-apk/

Android APK (Release)

# PROD flavor
fvm flutter clean
fvm flutter pub get
fvm flutter pub run build_runner build --delete-conflicting-outputs
fvm flutter build apk --release --flavor prod --dart-define=FLAVOR=prod

# LOCAL flavor
fvm flutter clean
fvm flutter pub get
fvm flutter pub run build_runner build --delete-conflicting-outputs
fvm flutter build apk --release --flavor local --dart-define=FLAVOR=local

Android App Bundle (AAB) β€” Play Store

# PROD
fvm flutter clean
fvm flutter pub get
fvm flutter pub run build_runner build --delete-conflicting-outputs
fvm flutter build appbundle --release --flavor prod --dart-define=FLAVOR=prod

# LOCAL
fvm flutter clean
fvm flutter pub get
fvm flutter pub run build_runner build --delete-conflicting-outputs
fvm flutter build appbundle --release --flavor local --dart-define=FLAVOR=local

Output: build/app/outputs/bundle/

Install Both APKs Side-by-Side

Use the PowerShell script to install PROD and LOCAL simultaneously:

.\install-both-apks.ps1

Requirements:

  • Android device connected via USB or Wi-Fi
  • ADB installed and available in PATH
  • Both APKs already built (see above)

The script will:

  1. Validate ADB availability
  2. Check device connection
  3. Install app-local-debug.apk β†’ id.syathiby.app.local
  4. Install app-prod-debug.apk β†’ id.syathiby.app
  5. Display colored status output (green = success, red = failed)

Web Build

Production build (deployed to aplikasi.syathiby.id/web/):

# Manual build (step by step)
fvm flutter clean
fvm flutter pub get
fvm flutter pub run build_runner build --delete-conflicting-outputs
fvm flutter build web --release --base-href /web/ --tree-shake-icons

⚠️ IMPORTANT: Flag --base-href /web/ is REQUIRED because Flutter web is deployed as a subfolder /web/ at aplikasi.syathiby.id.

OR use automated deployment script (recommended):

# Full build + auto-copy to ../aplikasi/web/ + rename htaccess -> .htaccess
.\deploy-web.ps1

# Skip clean step (faster for minor changes)
.\deploy-web.ps1 -SkipClean

The script will:

  1. Clean, get dependencies, generate code
  2. Build web with --base-href /web/
  3. Verify critical files (htaccess, flutter_bootstrap.js, main.dart.js, version.json)
  4. Prompt to auto-copy build output to ../aplikasi/web/ (with auto-rename htaccess β†’ .htaccess)

Output: build/web/

⚠️ CRITICAL: Web Deployment

  1. Upload contents of build/web/ to web/ folder on server aplikasi.syathiby.id
  2. DELETE old files in web/ folder before uploading
  3. Clear server cache (Cloudflare/cPanel/Nginx)
  4. Verify: https://aplikasi.syathiby.id/web/version.json

See comprehensive guide: WEB_DEPLOYMENT_GUIDE.md

Local Testing Before Deployment (Laragon)

Test the built web app locally before uploading to production.

Recommended: Laragon Virtual Host

Laragon auto-creates a virtual host for every folder in C:/laragon/www/. The aplikasi folder becomes aplikasi.test:

http://aplikasi.test/web/    ← same path as production, works with --base-href /web/

No extra configuration needed β€” just run the deploy script with auto-copy, then open http://aplikasi.test/web/.

Alternative: localhost/aplikasi/web/ via .htaccess Rewrite

If you prefer localhost/aplikasi/web/, create C:/laragon/www/.htaccess:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteCond %{REQUEST_URI} ^/web/
  RewriteCond %{REQUEST_URI} !^/aplikasi/
  RewriteRule ^web/(.*)$ /aplikasi/web/$1 [L]
</IfModule>

This rewrites localhost/web/* β†’ localhost/aplikasi/web/* so Flutter can find its assets.

A pre-made template is available at aplikasi/web/htaccess_xampp_root β€” copy and rename to .htaccess in your Laragon/XAMPP www root.

Local testing workflow:

1. .\deploy-web.ps1           β†’ build + auto-copy to aplikasi/web/
2. Open http://aplikasi.test/web/  β†’ test (should match native app)
3. Confirmed OK β†’ upload aplikasi/web/ to server

Note: Web version includes Guest Mode with News, Prayer Schedule, and Quran features accessible without login. The app automatically starts in guest mode at /guest-news when no session exists.

Web Architecture (Same-Origin, No CORS):

aplikasi.syathiby.id/           -> redirect to /web/
aplikasi.syathiby.id/web/       -> Flutter web app (subfolder)
aplikasi.syathiby.id/geten/     -> Backend API
aplikasi.syathiby.id/wordpress_images.php -> Image proxy

Flutter web and backend run on the same origin (aplikasi.syathiby.id), so there are no CORS issues.

Web Changelog Notification

Problem: Unlike native apps that show update dialogs from Play Store, web users don't know when new features are deployed because files are replaced instantly.

Solution: Web-specific changelog notification system using localStorage version tracking:

  • Automatic detection: App checks current version vs last seen version on home screen load
  • First-time visitors: See changelog modal for current version on first visit
  • After updates: When deployment replaces files with new version, modal appears automatically
  • Content: Changelog fetched from GitHub CHANGELOG.md (same as native)
  • User control: "Understood" action closes the modal and marks the version as seen
  • Storage: Uses browser localStorage to persist last seen version

Implementation:

  • UpdateChecker.checkForWeb(): Check if changelog should be shown (web only)
  • UpdateChecker.markChangelogAsSeen(): Save current version to localStorage
  • Modal shows "What's New" instead of "Update Available"
  • No Play Store button on web (replaced with an "Understood" acknowledgment)

Benefits:

  • Web users always informed about new features after deployment
  • Consistent changelog experience across native and web platforms
  • No manual user action required (automatic detection)
  • Non-intrusive (appears once per version, can be dismissed)

After deployment:

  1. Open incognito/private window (Ctrl+Shift+N) β€” old service worker won't interfere
  2. Test guest mode: Should land on News page automatically
  3. Test login: Click "Pengguna" tab β†’ "Masuk" button
  4. Verify icons and UI match the native APK β€” if different, the .htaccess cache headers may not be active

Why icons/UI may appear outdated after rebuild:

Flutter web uses a service worker (flutter_service_worker.js) to cache assets. If this file is cached by the browser, the old service worker keeps serving old assets even after you rebuild and upload.

The .htaccess in web/ includes Cache-Control: no-store for critical files:

  • flutter_service_worker.js β€” most important: must always be fresh
  • flutter_bootstrap.js, index.html, version.json, manifest.json

Static assets (.js, .wasm, fonts, images) use long-term caching β€” the service worker handles invalidation via content hash manifests.

Run Web Locally for Development & Debugging

⚠️ Important: Web requires Chrome browser and active internet connection to backend server.

1. Production Mode (Simulates Production Server)

# Run production build on Chrome (default: localhost:8080)
fvm flutter run -d chrome

# Or specify production server URL
fvm flutter run -d chrome --web-hostname localhost --web-port 8080

Features:

  • Uses production API URL: https://aplikasi.syathiby.id
  • No banner (clean production UI)
  • Resembles deployed version
  • Best for final testing before deployment

2. Local Development Mode (For Debugging)

# Run local build on Chrome with custom hostname/port
fvm flutter run -d chrome --web-hostname 192.168.50.100 --web-port 8082

# Or if using localhost (same machine)
fvm flutter run -d chrome --web-hostname localhost --web-port 8082

Configuration:

  • Change 192.168.50.100 to your machine's IP address
  • Change 8082 to any available port
  • Requires local backend server running at http://192.168.50.100/aplikasi

Features:

  • Uses local/development API URL
  • Shows RED banner with "LOCAL" indicator
  • Hot reload enabled (press r in terminal)
  • Perfect for debugging and development
  • Preserves app state on refresh

3. Debug Mode with Hot Reload

# Start development server with full debugging
fvm flutter run -d chrome --web-hostname 192.168.50.100 --web-port 8082 -v

# After app loads, press 'r' for hot reload
# Press 'q' to quit

Development Workflow:

  1. Run command above
  2. Browser opens automatically at http://192.168.50.100:8082
  3. Edit Dart code in IDE
  4. Press r in terminal β†’ app reloads instantly
  5. See changes immediately
  6. Check DevTools for logs (http://localhost:9222 in new browser tab)

4. Chrome DevTools for Debugging

# Run with debugging support
fvm flutter run -d chrome --web-hostname 192.168.50.100 --web-port 8082 -v

# Open new Chrome tab and go to:
chrome://inspect/#devices

# Click "inspect" on the Flutter app

Available in DevTools:

  • Widget tree explorer
  • Performance profiler
  • Network requests
  • Console logs
  • Breakpoints & step debugging

5. Quick Test Both Variants

# Run PROD environment
Write-Host "Starting PROD server..." -ForegroundColor Green
Start-Process -NoNewWindow pwsh -ArgumentList @"-NoExit", "-Command", "fvm flutter run -d chrome --web-hostname localhost --web-port 8080"

# Wait a moment for server to start
Start-Sleep -Seconds 3

# Run LOCAL environment in another terminal
Write-Host "Starting LOCAL server..." -ForegroundColor Yellow
Start-Process -NoNewWindow pwsh -ArgumentList @"-NoExit", "-Command", "fvm flutter run -d chrome --web-hostname 192.168.50.100 --web-port 8082"

Write-Host ""
Write-Host "βœ“ PROD: http://localhost:8080" -ForegroundColor Green
Write-Host "βœ“ LOCAL: http://192.168.50.100:8082" -ForegroundColor Yellow

Save as run-web-both.ps1 and run: .\run-web-both.ps1


Troubleshooting web routing:

  • If landing on login instead of guest mode: Clear browser localStorage
  • Open DevTools β†’ Application β†’ Local Storage β†’ Delete all entries
  • Refresh page β†’ Should redirect to guest news
  • Use incognito/private mode to avoid cached assets

πŸ“± Platform Differences: APK vs Web

⚠️ Important: While APK and Web versions share the same version number, certain features have different capabilities due to platform constraints.

Quick Comparison Table

Feature APK (Mobile) Web (Browser)
Push Notifications βœ… Full FCM support ❌ Disabled
GPS Location βœ… Native GPS ⚠️ Browser geolocation (limited)
Biometric Auth βœ… Fingerprint/Face ❌ Not available
Camera/QR Scanner βœ… Native camera ⚠️ Browser camera (limited)
Offline Mode βœ… Local caching ❌ Requires internet
Background Services βœ… Supported ❌ Not available
File System βœ… Full access ⚠️ Downloads only
Guest Mode βœ… Full support βœ… Full support
WordPress News βœ… Full support βœ… Full support
Attendance βœ… GPS + Wi-Fi ⚠️ Browser location + Wi-Fi
Login/Auth βœ… Full support βœ… Full support
Reports & Analytics βœ… Full support βœ… Full support

Detailed Feature Comparison

πŸ”” Push Notifications

  • APK: Firebase Cloud Messaging with background notifications, notification channels, and message handling
  • Web: Completely disabled. Firebase initialization is skipped on web for Safari compatibility
  • Impact: Web users won't receive real-time notifications about attendance, announcements, or updates

πŸ“ Location & Permissions

  • APK:
    • Native Android location services with high accuracy
    • Permission dialogs with "Open Settings" direct link
    • Wi-Fi attendance with IP validation
    • GPS-based attendance with radius validation
  • Web:
    • Browser Geolocation API (accuracy varies by device/browser)
    • Permission dialogs show an acknowledgment-only action ("Mengerti")
    • Users must grant location manually via browser settings
    • Wi-Fi attendance works via IP detection from server headers
  • Impact: Web attendance may have lower GPS accuracy; users need to manually enable browser location

πŸ” Biometric Authentication

  • APK: Local Auth plugin supports fingerprint and face unlock
  • Web: Not implemented (no Web Authentication API integration)
  • Impact: Web users can only use password authentication

πŸ“± Native Device Features

  • APK:
    • Barcode/QR scanner for attendance, meetings, inventory
    • Full camera access for photo capture
    • Local file system read/write
    • Background service for location tracking
  • Web:
    • Browser camera API (may require HTTPS)
    • File downloads only, no direct filesystem
    • No background services
    • QR scanner works but limited by browser camera quality
  • Impact: QR scanning and photo features work better on APK

🌐 Connectivity & Offline Mode

  • APK: Local database caching allows viewing previously loaded data offline
  • Web: Requires active internet connection for all operations
  • Impact: APK more reliable in areas with poor connectivity

🎨 User Experience

  • APK: Native UI with smooth animations, system integration, navigation gestures
  • Web: Responsive design that adapts to screen size, works on any device with browser
  • Impact: APK feels more native, Web more accessible cross-platform

βœ… Features That Work Identically

Both platforms support:

  • βœ… Guest Mode: News, Prayer Times, Quran, Qibla
  • βœ… Authentication: Login, password change, session management
  • βœ… WordPress News: Full news feed with images and rich content
  • βœ… Attendance: Check-in/out (with platform-specific location handling)
  • βœ… Staff Management: View and manage staff data
  • βœ… Reports: Attendance reports, performance tracking, analytics
  • βœ… Dark/Light Theme: Adaptive theme switching

πŸ“° WordPress Detail Rendering Strategy

  • Web: WpPostDetailScreen loads the article URL directly from WordPress response (post.link) via WebView URL request.
  • Android/iOS (APK): WpPostDetailScreen keeps the previous rich HTML rendering flow (initialData) for stable native behavior.
  • Fallback: If post.link is missing/invalid on web, the screen falls back to HTML rendering.

This split approach keeps native behavior unchanged while avoiding black/blank embed rendering issues on web.

πŸ’‘ Usage Recommendations

Use APK when:

  • Staff needs daily attendance check-in/out
  • Push notifications are required
  • Working in areas with intermittent internet
  • Need QR scanner for meetings/events
  • Prefer native app experience

Use Web when:

  • Occasional access to view information
  • No access to Play Store (restricted devices)
  • Need quick access from any device/computer
  • Only need to view reports and data
  • Don't need push notifications

Hybrid Approach:

  • Give field staff APK for daily use
  • Use Web for management/admin dashboard access
  • Both platforms share same backend API and data

✨ Features

WordPress News Integration

The app displays news and announcements from the Ma'had Syathiby WordPress site:

  • WordPress REST API: Pull latest posts from https://syathiby.id/wp-json/wp/v2/posts
  • SEO-Optimized Images: Uses Yoast SEO og_image for fast-loading, optimized thumbnails
  • Rich Content Display: Full HTML rendering with InAppWebView
  • Embedded Media Support: YouTube videos, Instagram posts, Twitter embeds automatically rendered
  • Skeleton Loading: Smooth loading animations while fetching content
  • WebP Image Support: Native support for modern WebP format images
  • Available in: Guest News screen and Member News screen

How it works:

  • News content is managed through WordPress CMS at syathiby.id
  • App fetches posts via REST API with embedded featured media
  • Images prioritize Yoast SEO optimized thumbnails from yoast_head_json
  • Detail screen uses WebView for rich content including videos and embeds
  • HTML entities automatically decoded for proper text display

Attendance System

The app supports two attendance methods:

  1. Location (GPS): Validates attendance based on GPS coordinates and location radius
  2. Network (Wi-Fi / LAN): Validates attendance using the device's public IP address

How Wi-Fi attendance works:

  • User selects the attendance method when tapping the check-in/out button
  • Wi-Fi mode sends coordinates (0, 0) as a mode indicator to the backend
  • The app fetches the allowed public IP from the server endpoint (settings/wificonfig.php)
  • The app validates the device's current public IP against the allowed IP via an external IP API
  • If validation passes, the attendance request is submitted β€” backend skips GPS radius check for (0, 0) coordinates
  • Error code 03 is used for Wi-Fi validation failures

Update Checker

  • Automatically checks for a new version on app startup (Home screen)
  • Compares current app version with the latest version in CHANGELOG.md on GitHub
  • Dynamic Branch Selection: Selects the appropriate GitHub branch based on current flavor:
    • LOCAL flavor (--flavor local): Fetches CHANGELOG from test branch for development updates
    • PROD flavor (--flavor prod): Fetches CHANGELOG from dev branch for stable releases
  • Displays a bottom sheet modal with the changelog content when an update is available
  • Provides a direct link to the Play Store for the update
  • Non-blocking: users can dismiss and continue using the current version

Profile Management

View and manage staff profile information.

Leave Request System

Submit and track leave/permit requests.

Timeline & Activity Tracking

View attendance history and activity timeline.


🎨 Environment Indicators

The app provides visual indicators to distinguish between environments:

Global Banner (Ribbon) β€” LOCAL Only

  • LOCAL: Red ribbon with "LOCAL" label (development indicator)
  • PROD: No banner β€” clean UI for end users

Production builds have a clean UI without any environment banner.

Dynamic App Name

  • Local environment: "Syathiby LOCAL"
  • Production environment: "Syathiby"

Login Screen Badge

  • Displays the active ENV label and API URL
  • Red for LOCAL, green for PROD
  • Long-press logo to override the API URL at runtime

Android Flavors

Flavor prod Flavor local
Application ID id.syathiby.app id.syathiby.app.local
App Label Syathiby Syathiby LOCAL
Banner ❌ None (clean UI) πŸ”΄ Red ribbon

Both flavors can be installed simultaneously on the same device.


πŸ§ͺ Testing

Wi-Fi Attendance Test Guide

A detailed test checklist for Wi-Fi attendance is available at:

πŸ“„ ATTENDANCE_WIFI_TEST_CHECKLIST.md

Flutter Analyzer

fvm flutter analyze

Unit Tests

fvm flutter test

πŸ“° WordPress API Configuration

WordPress REST API Endpoint

The app fetches news from the WordPress site using the REST API:

Base URL: https://syathiby.id/wp-json/wp/v2
Posts Endpoint: /posts?_embed=true

Query Parameters:

  • _embed=true: Includes embedded resources (featured media, author, etc.)
  • page=1: Page number for pagination
  • per_page=10: Number of posts per page (default: 10, max: 100)
  • orderby=date: Sort by date, relevance, id, etc.
  • order=desc: Descending order (newest first)

WordPress Models

The app uses Freezed models for WordPress data:

WpPost - Main post model

  • id, date, slug, link
  • title, content, excerpt (rendered HTML)
  • featured_media (media ID)
  • _embedded (embedded resources)
  • yoast_head_json (Yoast SEO metadata)

YoastHeadJson - SEO metadata from Yoast plugin

  • og_image[] - Open Graph images (optimized thumbnails)

OgImage - SEO-optimized image

  • url: Direct image URL (WebP format)
  • width, height: Image dimensions
  • type: MIME type (image/webp)

WpEmbedded - Embedded resources

  • wp:featuredmedia[] - Featured media with source_url

Image Loading Strategy

The app uses a prioritized fallback strategy for images:

  1. Primary: Yoast SEO og_image

    yoast_head_json.og_image[0].url

    βœ… SEO-optimized, pre-resized WebP thumbnails

  2. Fallback: Featured media from embedded data

    _embedded['wp:featuredmedia'][0].source_url

    ⚠️ Full-resolution original image

WordPress Service Configuration

Location: lib/models/wordpress/wp_api_service.dart

@RestApi(baseUrl: 'https://syathiby.id/wp-json/wp/v2')
abstract class WpApiService {
  factory WpApiService(Dio dio, {String baseUrl}) = _WpApiService;

  @GET('/posts')
  Future<List<WpPost>> getPosts({
    @Query('page') int? page,
    @Query('per_page') int? perPage,
    @Query('_embed') bool? embed,
  });

  @GET('/posts/{id}')
  Future<WpPost> getPost(@Path('id') int id);
}

Dependency Injection: lib/di/providers.dart

final wpApiServiceProvider = Provider<WpApiService>((ref) {
  final dio = ref.watch(dioProvider);
  return WpApiService(dio);
});

WordPress Content Display

List View (wp_post_list_item.dart):

  • Featured image (200px height)
  • Title (HTML decoded)
  • Excerpt (HTML stripped and decoded)
  • Skeleton loading animation

Detail View (wp_post_detail_screen.dart):

  • Featured image at top
  • Full HTML content rendering with InAppWebView
  • Embedded media support (YouTube, Instagram, etc.)
  • Custom CSS for responsive layout

Yoast SEO Plugin

The WordPress site uses Yoast SEO plugin which provides:

  • Optimized og_image thumbnails (WebP format)
  • SEO metadata in yoast_head_json field
  • Better performance with pre-resized images

To check if Yoast is installed:

curl https://syathiby.id/wp-json/wp/v2/posts?per_page=1 | jq '.[0].yoast_head_json'

πŸ› οΈ Troubleshooting

Build Runner β€” Conflicting Outputs

fvm flutter pub run build_runner build --delete-conflicting-outputs

Gradle Issues (Android)

Clear Gradle cache:

# Windows
Remove-Item -Recurse -Force $env:USERPROFILE\.gradle\caches

# macOS/Linux
rm -rf ~/.gradle/caches

Then rebuild:

fvm flutter clean
fvm flutter pub get

ADB Device Not Found

# Check connected devices
adb devices

# Restart ADB server
adb kill-server
adb start-server

# Connect via Wi-Fi (after USB pairing)
adb tcpip 5555
adb connect <device-ip>:5555

FVM Not Found

Make sure FVM is added to PATH:

# Check FVM installation
fvm --version

# Install FVM if missing
dart pub global activate fvm

# Add to PATH (Windows example)
# Add: %USERPROFILE%\AppData\Local\Pub\Cache\bin

πŸ” Keystore

Debug Keystore

Generate a debug keystore for development:

keytool -genkeypair -v `
  -keystore debug.keystore `
  -alias androiddebugkey `
  -keyalg RSA -keysize 2048 `
  -validity 10000 `
  -storetype pkcs12 `
  -storepass android `
  -keypass android `
  -dname "CN=https://github.com/CreatorB, O=Freelance Fullstack Developer, C=ID"

Release Keystore

For production builds, use a secure keystore. Store it in a safe location and never commit it to git.


πŸ› οΈ Advanced Configuration

Rename App and Package Name

dart run flutter_application_id:main -f flutter_application_id.yaml

Change App Icon

# Generate configuration
dart run flutter_launcher_icons:generate --override

# Generate icons
dart run flutter_launcher_icons

Change Splash Screen

dart run flutter_native_splash:create

πŸ“¦ Project Structure

flutter_syathiby/
β”œβ”€β”€ android/                        # Android native code & flavor config
β”œβ”€β”€ ios/                            # iOS native code
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ app.dart                    # Root MaterialApp with environment banner
β”‚   β”œβ”€β”€ data/                       # Data layer (repositories, local storage)
β”‚   β”œβ”€β”€ models/
β”‚   β”‚   β”œβ”€β”€ wordpress/               # WordPress REST API models
β”‚   β”‚   β”‚   β”œβ”€β”€ wp_api_service.dart # Retrofit API service
β”‚   β”‚   β”‚   └── wp_post.dart        # WpPost model (Freezed + JSON)
β”‚   β”‚   └── ...                     # Other models
β”‚   β”œβ”€β”€ presentation/
β”‚   β”‚   β”œβ”€β”€ home/                   # Home screen with update checker
β”‚   β”‚   β”œβ”€β”€ login/                  # Login screen with environment badge
β”‚   β”‚   β”œβ”€β”€ presence/               # Attendance screen with Wi-Fi option
β”‚   β”‚   β”œβ”€β”€ wordpress/              # WordPress news screens
β”‚   β”‚   β”‚   β”œβ”€β”€ wp_posts_controller.dart   # Riverpod controller
β”‚   β”‚   β”‚   β”œβ”€β”€ wp_post_list_item.dart     # News list item widget
β”‚   β”‚   β”‚   └── wp_post_detail_screen.dart # Article detail (WebView)
β”‚   β”‚   β”œβ”€β”€ guest/                  # Guest screens (uses WordPress API)
β”‚   β”‚   └── news/                   # Member news (uses WordPress API)
β”‚   β”œβ”€β”€ di/
β”‚   β”‚   └── providers.dart          # Riverpod providers & DI
β”‚   β”œβ”€β”€ res/
β”‚   β”‚   β”œβ”€β”€ flavor_config.dart      # Built-in URL configuration per flavor
β”‚   β”‚   β”œβ”€β”€ environment_config.dart # Runtime config + URL override
β”‚   β”‚   └── strings.dart            # App constants, dynamic app name
β”‚   └── utils/
β”‚       └── update_checker.dart     # GitHub CHANGELOG version check
β”œβ”€β”€ test/                           # Unit & widget tests
β”œβ”€β”€ build/                          # Build outputs (gitignored)
β”œβ”€β”€ web/
β”‚   β”œβ”€β”€ htaccess                    # Apache config: SPA routing + Cache-Control headers
β”‚   β”œβ”€β”€ index.html                  # Flutter web entry point
β”‚   └── ...
β”œβ”€β”€ CHANGELOG.md                    # Version history
β”œβ”€β”€ ATTENDANCE_WIFI_TEST_CHECKLIST.md  # Wi-Fi attendance test guide
β”œβ”€β”€ WEB_DEPLOYMENT_GUIDE.md         # Web deployment checklist & troubleshooting
β”œβ”€β”€ install-both-apks.ps1           # Dual APK installer script
β”œβ”€β”€ deploy-web.ps1                  # Web build + auto-copy + verification script
β”œβ”€β”€ pubspec.yaml                    # Flutter dependencies
└── README.md                       # This file

🀝 Contributing

  1. Create a new branch from dev
  2. Implement features or fixes with clear commit messages
  3. Update CHANGELOG.md with a new entry
  4. Test all changes thoroughly
  5. Open a Pull Request to the dev branch

Commit Message Convention

feat: add feature X
fix: resolve bug Y
docs: update documentation for Z
chore: update dependencies
refactor: restructure code for A

🌿 Branches

Active development branch β€” continuously updated with the latest features and requirements.

Stable branch. Maintained to support the latest production requirements with original features intact.


πŸ‘₯ Team & Contact

Ma'had Tahfizh al-Qur'an al-Imam as-Syathiby
Cileungsi, Bogor, Indonesia

  • Website: syathiby.com
  • Tags: pondok jabodetabek ma'had tahfizh al-Qur'an sunnah manhaj salaf cileungsi bogor indonesia syathiby

πŸ“„ License

Copyright IT Syathiby 2024

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

About

An app for Ma'had Tahfizh Al-Qur'an Al-Imam Asy-Syathiby

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors