Skip to content

Latest commit

Β 

History

9 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

VCRoad

Flutter Dart Firebase License: MIT Website

Local road incident reporting & traffic advisory management for Valenzuela City, Philippines.

VCRoad is a cross-platform mobile and web application that empowers citizens to report road incidents (accidents, potholes, floods, debris) and stay informed with real-time traffic advisories. Built for Valenzuela City, the app replaces paper-based reporting with a digital, map-driven experience β€” integrating incident reports, traffic advisories, road safety education, and role-based administration into a single platform.


Features

πŸ—ΊοΈ Map Dashboard
  • Real-time map view of all reported incidents and active advisories using OpenStreetMap
  • Interactive markers with category-based icons and color coding
  • Barangay-level filtering and statistics
  • "Center on me" GPS location with permission-gated access
  • Marker clustering with responsive sizing across devices
πŸ“ Incident Reporting
  • Multi-step wizard: category selection β†’ location pinning β†’ media capture β†’ review & submit
  • Image upload with client-side validation (size, resolution, content heuristics)
  • GPS-assisted barangay auto-detection
  • Report history with status tracking
  • Email verification required before first report
🚦 Traffic Advisories
  • Create and publish advisories (road closures, stop-and-go, one-way, construction, etc.)
  • Map-based route plotting with OSRM road snapping, undo/redo history, and editable auto-detected road names
  • Real-time updates pushed to all users
  • Enhanced data model β€” advisories carry a stable barangayId (from the GeoJSON id), a Firestore GeoPoint center plus boundsNE/boundsSW for geo-queryability, denormalized lowercase searchKeywords for indexed array-contains search, createdByUid/updatedByUid audit fields, a capped versionHistory audit trail, and statusUpdatedAt/nextStatusAt timestamps
  • Tolerant parsing β€” fromJson coerces int coordinates, skips malformed route entries, validates weekday/time shapes, falls back unknown status to inactive (never published), and falls back bad dates to epoch instead of now
  • Optimistic locking β€” edits increment version inside a Firestore transaction and fail with a refresh prompt on conflict; security rules enforce the version + 1 bump and protect immutable fields (advisoryId, createdAt, createdBy, createdByUid)
  • Single consolidated stream β€” regular users share one realtime stream (active + scheduled, all barangays) that powers the home map, the advisory list, and the new-advisory alert popups (derived from new additions after the session baseline, with mute/dedupe/self-notification guards); the map always plots only active advisories and barangay selection on the advisory screen is a client-side filter. The admin/sysadmin all-statuses stream is capped at the 200 latest advisories for performance.
  • Shared advisory UI β€” status badges render through one AdvisoryStatusBadge widget and category icons through AdvisoryCategory.iconFor (labels/colors/icons come from the model, so cards, detail dialogs, and the wizard never drift apart). Cards show a fixed-height 96px photo strip (tap for fullscreen preview; identical height in loading/error/loaded states, sized image decode for cheap scrolling). The details dialog mirrors the exported share image's compact composition with native widgets: a poster-style list of labeled Reason/Location/Schedule rows, photo + navy-bordered map card (with an in-map route legend matching the export's red closed-segment / blue alternate-route swatches) beside them on wide surfaces or stacked below on phones, and lower-priority metadata (contractor, route counts, updated timestamp) collapsed behind a "More details" tile so the default view stays short, now including Created + Version rows and empty-state placeholders for missing photo/routes; its Edit/Download actions are wired from the management screen. Desktop/wide screens show the advisory list as a lazy responsive masonry grid (2 columns, 3 on very wide screens), and empty states offer an admin Create CTA. The advisory screen is split into testable widgets (AdvisoryCard, AdvisoryListView) so the list body can be exercised without Firebase.
  • Quick status toggle β€” admins can Activate/Deactivate/Cancel directly from a card or the details dialog (re-saves with the persisted status and a bumped version; reactivations re-derive from the schedule so past-end advisories can't go live stale; no manual re-save needed). expired is terminal and kept for the audit trail. Deleting an advisory enforces creator-or-admin ownership and removes its Supabase photo too (one silent retry, then an explicit warning with a Retry action on partial failure). The advisory list also supports Newest / Oldest / Recently-updated sorting.
  • Shareable advisory image β€” one-click Download on each card renders a share-ready 1920Γ—1080 image (PNG/JPEG) fully client-side, no server or API key required. The static map (OSM tiles + affected/alternate polylines) sits in a right-column card with a navy border and an in-card route legend (red = closed segment, blue = alternate route). The left column is a WCAG-AA public notice: a category title ("ROAD CLOSURE & REROUTING NOTICE"), an accent divider, labeled Reason / Location / Schedule rows, and an "ADVISORY FOR MOTORISTS" bullet list derived from the reason (shown only when it has multiple segments). A top-left "TRAFFIC ADVISORY" banner (procedural traffic-light icon) and a top-right decorative dot grid frame the header, and a layered blue wave with the brand text ("VCRoad β€’ City of Valenzuela") runs along the bottom. Category accents are darkened hue-preservingly (orange stays orange, yellow stays warm) so they read at β‰₯4.5:1 on the white panel, and the layout scales proportionally for landscape, square, and story formats. On web the PNG opens in a new tab via a blob URL; on native it saves a temp file with an Open action.
  • UI/UX & layout (ISO 25010-aligned) β€” the advisory screen surfaces the active sort as a labeled control, the top stat cards (admin/sysadmin only) are tappable filter shortcuts through the same funnel as the chips and sidebar (with selected-ring + button semantics), and pull-to-refresh (mobile) or a refresh action (desktop) re-subscribe the stream. Filter dropdowns (category, sort, barangay) share one active-state language β€” accent border/content if and only if set β€” and search preserves the status view while matching category titles and contractor fields on legacy docs. Contextual empty states distinguish "no data yet" from "no results for your search/filters" (with a Clear search & filters action). The whole surface is theme-aware β€” stat cards, filter chips, the card grid, and the details dialog all use Theme.colorScheme + AppColors.primaryAdaptive tokens (darker accents brightened in dark mode for ~3:1 contrast) with the brand-navy AppBar/FAB in light mode and theme defaults in dark; category icons pick dark or light ink from the chip color's luminance (e.g. the yellow partial-lane chip gets a dark icon) to keep WCAG contrast. Desktop uses a lazy responsive masonry grid with each card isolated in a RepaintBoundary so scrolling doesn't repaint off-screen cards, and card action rows wrap instead of overflowing on narrow screens. The advisory details dialog shows a read-only mini map that auto-fits the entire affected + alternate route plot (padded, zoomed out one level, with a graceful fallback for single-point routes), and its image preview uses a stable hero tag. Screen-reader users get labeled review Edit buttons, selected/button semantics on filters and stats, live regions on errors and the result count, an initial-focus Close on dialogs, and semantically labeled date/time/reason fields.
  • Inline wizard validation & save safety β€” validation errors in the create/edit wizard surface as a persistent inline banner above the navigation bar (not just a transient snackbar), the Details step shows live inline hints on the reason, contractor, and schedule fields as you type, and an advisory photo (validated client-side: 5 MB cap, JPG/PNG, enforced on all platforms) uploads to Supabase Storage at advisories/{id}/image.jpg with the superseded image cleaned up on edit (same-URL replacements are skipped, not deleted), failed creates cleaning their fresh upload, and image caches evicted so replacements never render stale. Save failures surface in the same inline banner with the real error, and leaving the wizard with unsaved changes triggers a discard confirmation via PopScope (with mounted guards on async saves).
  • Guided 4-step wizard β€” Type β†’ Details β†’ Routes β†’ Review with tap-to-jump steppers (desktop rail pinned far-left, live summary far-right, config spreading between in a uniform full-height frame; compact stepper + collapsible summary on mobile). Forward jumps live-validate every intermediate step (backward jumps and Review Edit buttons are always free), the live summary shows actual road names with counts, and final submit re-validates all steps as defense-in-depth. Details offers one-time/recurring schedules (segmented switch, weekday strip, overnight windows, stacked date/time fields on phones) with conditional contractor fields and a photo drop-zone with fullscreen preview; Routes keeps map tiles mounted across steps with a viewport-sized map, legend, editable route names (commit on blur, empties rejected), and plotter undo/redo; Review shows a truthful derived status preview with per-section Edit jumps.
  • Duplicate guard β€” before anything uploads, a modal warns when an active/scheduled advisory of the same type already exists nearby (1 km) or on the same road in the barangay (placeholder Route N names excluded; edits exclude the advisory being edited).
  • Status lifecycle (client-side evaluator) β€” statuses (active / inactive / expired / scheduled) are persisted on save, and nextStatusAt records when each should next change (one-time startDate/endDate or the next recurring window boundary). Every stream snapshot re-evaluates immediately (no waiting on a possibly-stale timer), a timer re-arms at the earliest nextStatusAt boundary (clamped to 500 ms–6 h as a safety net), and changes persist in a single idempotent batch with audit-trail history (a re-emitted snapshot won't loop). Overnight windows attribute post-midnight hours to the previous day, one-time expiry is end-inclusive, and empty weekday sets evaluate daily. inactive (user-controlled) and expired (terminal) are never auto-changed. Server-side auto-transitioning via a scheduled job is still a future option.
πŸ“š Road Safety Education
  • Interactive lessons with 4 question types: multiple choice, true/false, identification, matching type
  • Question images supported across all types (e.g., road-signage photos): question-level images for identification/true-false, per-option images for multiple choice, and imageβ†’meaning pairs for matching type
  • Admin question editor lets you attach images to any question or option (uploaded and compressed on save) β€” ideal for signage identification drills
  • Learn dashboard β€” stats header with level badge & title (Student Driver β†’ Road Master), XP progress bar, day streak, lessons completed X/Y, overall completion %, and a tappable due-review counter that jumps to the first lesson scheduled for review
  • Per-chapter progress β€” expandable chapter headers show completed/total lesson counts with green progress bars
  • Progressive unlocking β€” only the first lesson and each chapter's opener start unlocked (locked cards are greyed out); scoring 70% or higher completes a lesson and unlocks the next one
  • Retake flow β€” scores below 70% show a "Keep Going!" result with a pass-hint card and a Retake Lesson button that resets the lesson's progress for another attempt
  • Spaced-repetition reviews β€” completed lessons open a dedicated review screen: due questions by default (intervals double on correct answers, reset on wrong), an "All caught up!" state with a next-review countdown and a Review all questions anyway option, +5 XP per completed review, and a result screen showing the next review countdown
  • Preview mode β€” admin/sysadmin-only toggle on the Learn page that unlocks every lesson card for browsing; regular users always follow the locked progression. Opening an unlocked-but-not-completed lesson in preview is a placeholder ("coming soon"), while completed lessons open normally.
  • XP system with 5 levels (Student Driver β†’ Road Master), streak tracking, and streak bonuses
  • 8 achievement badges (First Steps, Perfect Score, On a Roll, Week Warrior, Chapter Master, Quick Learner, See It β€” Report It, Review Master) β€” 7 are earnable today; "See It, Report It" awaits the report-flow link-up
  • Animated XP preview as final onboarding slide β€” shows level progression before entering the app
  • Rich lesson result screen with animated score circle, XP counter, level-up indicator, and badge awards (plus a dedicated retake state when the pass threshold isn't met)
  • "Report It" prompt after lesson completion β€” encourages filing a road report tied to what was learned (placeholder: the report link-up is not yet wired)
  • Admin/sysadmin lesson management: create, edit, delete, publish/unpublish, and per-lesson question editor (lessons are auto-numbered; chapters and questions are drag-reorderable) β€” the lesson list adds search, summary chips (N Chapters / N Lessons / N Published), and pull-to-refresh, and the question editor guards against losing unsaved changes. Lessons auto-sum per-question points into their total, and per-answer analytics (timesAnswered / timesCorrect) are tracked in Firestore.
  • Chapter manager with drag-to-reorder chapters
  • Role-aware tutorial with animated widget previews (users: 5 slides including XP preview; admins: 3 slides with dashboard overview)
  • Location permission requested contextually at point of need (center-on-map or first report), not during onboarding
πŸ‘€ User Roles & Administration
  • Three roles: user, admin, sysadmin enforced at both UI and Firestore rules level
  • Admin panel for user management, bans, and role elevation
  • Account search scans the whole users collection (bounded scan loop over createdAt-ordered pages) so matches are found regardless of where they sit β€” no paid search service (Algolia) or Cloud Functions involved; pagination is cursor-based and compositely indexed in firestore.indexes.json
  • Registration flow with identity verification (valid ID + selfie capture)
  • Reusable searchable Barangay dropdown (register, profile details, and create-admin) with instant cached names, normalized/prefixed search, load error + Retry, and a no-results state
  • Profile details page: view/edit contact & address (phone, street, house number, barangay dropdown), read-only name & email, role/verification badges, selfie display, and an unsaved-changes guard when leaving while editing
  • Profile management with appearance settings (theme toggle)
πŸ” Security & Session Management
  • Firestore-based role verification in security rules (no self-elevation)
  • Brute force protection: Firestore-based per-email lockout (5 failed attempts β†’ 15-min block) + local SharedPreferences cache
  • Single-device session enforcement: on login from a new device, the old device is notified and signed out
  • Persistent login via Firebase Auth local persistence
  • Password reset via email link with rate-limited resends (45s cooldown) and anti-enumeration messaging
πŸŒ™ Theme System
  • Light and dark themes with a navy-based dark palette
  • Persistent theme toggle via SharedPreferences (Light / Dark / System)
  • Accessible from Profile β†’ Appearance β†’ Theme
  • Full dark-mode coverage, including the profile details page β€” surface cards, text, dividers, and outlined buttons adapt to the active theme while brand-blue header and input fields stay consistent

Technology Stack

πŸ“± Framework & Language
Component Technology
Framework Flutter ^3.12.2
Language Dart ^3.12.2
Platforms Android, iOS, Web, Windows, macOS, Linux
πŸ—„οΈ Backend & Database
Service Status Details
Firebase Authentication βœ… Active Email/password, Spark free tier (unlimited)
Cloud Firestore βœ… Active Primary database, Spark free tier (50K reads/day)
Supabase Storage βœ… Active Image uploads for advisories, reports & lessons (1 GB free tier)
Firebase Storage ⏸️ Parked Not used β€” Supabase Storage is the live backend
Cloud Functions ⏸️ Parked Login tracking migrated to Firestore directly
πŸ—ΊοΈ Maps & Location
Service Replacement For Status
OpenStreetMap via flutter_map Google Maps SDK βœ… Active
Nominatim (OSM geocoding) Google Places API βœ… Active
OSRM Nearest API (road snapping) Google Roads API βœ… Active
Client-side image validation Google Cloud Vision βœ… Active
OSM tile rendering via Canvas Static map generation βœ… Active
πŸ“¦ Key Packages
Category Packages
State Management provider
Routing go_router, url_strategy
Firebase firebase_core, firebase_auth, cloud_firestore
Maps & Location flutter_map, latlong2, geolocator, permission_handler
HTTP & APIs http
UI Components lottie, carousel_slider, introduction_screen, cached_network_image
Media image_picker, file_picker, image, flutter_image_compress, video_player, video_thumbnail
Utilities shared_preferences, uuid, device_info_plus, intl, url_launcher
Fonts Poppins (Regular + Bold)

Architecture

VCRoad follows Clean Architecture with feature-first organization, aligned with ISO 25010 quality standards.

Data Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Presentation Layer                      β”‚
β”‚  Screens ↔ Providers (ChangeNotifier) ↔ Shared Widgets   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                         β”‚ calls
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   Repository Layer                        β”‚
β”‚  AuthRepo β”‚ ReportRepo β”‚ AdvisoryRepo β”‚ LessonRepo ...    β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
       β”‚                      β”‚
β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Firebase        β”‚   β”‚  Free APIs / Client-Side         β”‚
β”‚  (Spark tier)    β”‚   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚   β”‚  β”‚ Nominatim (geocoding) βœ… β”‚    β”‚
β”‚  β”‚ Auth βœ…  β”‚    β”‚   β”‚  β”‚ OSRM (road snap)      βœ… β”‚    β”‚
β”‚  β”‚ Firestoreβœ…β”‚   β”‚   β”‚  β”‚ Client vision heuristicsβœ…β”‚    β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚   β”‚  β”‚ OSM tiles (static map) βœ… β”‚    β”‚
β”‚                  β”‚   β”‚  β”‚ CSV export             βœ… β”‚    β”‚
β”‚                  β”‚   β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

ISO 25010 Quality Mapping

Quality How the Structure Addresses It
Maintainability Feature modules encapsulate related UI, state, and logic. Clear dependency direction (β†’ presentation β†’ data β†’ core).
Portability Repository pattern abstracts data sources. Platform-specific code isolated via conditional exports.
Modularity Feature-first grouping makes it easy to add/remove/modify features without affecting others.
Analyzability File names reflect their purpose (e.g., login_screen.dart, auth_service.dart).
Testability Repositories can be mocked independently. Providers decoupled from UI. Domain logic testable without Flutter dependencies.
Reusability Shared widgets used across features. Utility functions are pure Dart with no UI coupling.
Replaceability External services isolated behind repository interfaces, swappable without touching UI code.

Installation

Prerequisites
  • Flutter SDK ^3.12.2
  • Dart SDK ^3.12.2
  • Firebase project (configured with Authentication and Firestore)
  • A code editor (VS Code, Android Studio, or IntelliJ)
Setup
# Clone the repository
git clone https://github.com/yo-gerr/vcroad.git
cd vcroad

# Configure environment variables
cp .env.example .env
#  -> Edit .env and fill in your Supabase project URL and anon/publishable key.

# Install dependencies
flutter pub get

# Run on your preferred platform
flutter run -d chrome     # Web
flutter run -d android    # Android
flutter run -d ios        # iOS (macOS only)

# Generate launcher icons (if needed)
flutter pub run flutter_launcher_icons

Note: .env is gitignored and holds the Supabase credentials. The anon/publishable key is public by design (it ships in the client binary), so production data security relies on Supabase RLS / storage-bucket policies, not on keeping the key secret.

Firebase Configuration

The app uses Firebase for authentication and data storage. Configuration files are included:

  • lib/firebase_options.dart β€” auto-generated by FlutterFire CLI
  • android/app/google-services.json β€” Android Firebase config
  • ios/Runner/GoogleService-Info.plist β€” iOS Firebase config (if present)

To use your own Firebase project, run:

flutter pub add firebase_core
flutterfire configure

This regenerates firebase_options.dart and the platform-specific config files.

Lint & Analyze
flutter analyze

Folder Structure

lib/
β”œβ”€β”€ main.dart                         # Entry point, provider setup, GoRouter
β”œβ”€β”€ core/                             # Cross-cutting concerns
β”‚   β”œβ”€β”€ constants/                    # App-wide constants (config, password policy)
β”‚   β”œβ”€β”€ errors/                       # Error types and handling
β”‚   β”œβ”€β”€ theme/                        # AppColors, AppTextStyles, AppTheme
β”‚   └── utils/                        # Pure utility modules (no UI)
β”‚       β”œβ”€β”€ debouncer/                # Debounce utility
β”‚       β”œβ”€β”€ exception/                # try/catch helpers
β”‚       β”œβ”€β”€ format/                   # Date/text formatting
β”‚       β”œβ”€β”€ input/                    # Input validation, styling
β”‚       β”œβ”€β”€ map/                      # Map configuration
β”‚       β”œβ”€β”€ responsive/               # Responsive breakpoint helpers
β”‚       β”œβ”€β”€ routing/                  # Role-based routing config
β”‚       └── web/                      # Web-specific stubs
β”œβ”€β”€ data/                             # Data layer
β”‚   β”œβ”€β”€ models/                       # Data models (DTOs, JSON serde)
β”‚   └── repositories/                 # Repository/service implementations
└── presentation/                     # UI layer
    β”œβ”€β”€ app/                          # App shell, splash screen
    β”œβ”€β”€ providers/                    # 7 ChangeNotifier state managers
    β”œβ”€β”€ shared/                       # Shared dialogs, snackbar, widgets (banner, location prompt, coach marks)
    └── features/                     # Feature modules
        β”œβ”€β”€ auth/                     # Login, Register, Reset Password
        β”œβ”€β”€ onboarding/               # Role-aware tutorial with animated slides
        β”œβ”€β”€ home/                     # Map dashboard
        β”œβ”€β”€ reports/                  # Incident reporting wizard
        β”œβ”€β”€ advisories/               # Advisory management wizard
        β”œβ”€β”€ lesson/                   # Quiz/lesson system
        β”œβ”€β”€ admin/                    # User/account administration
        └── profile/                  # User profile & settings

assets/
β”œβ”€β”€ fonts/                            # Poppins (Regular, Bold)
β”œβ”€β”€ icons/                            # Map markers, app icons (.webp)
β”œβ”€β”€ images/                           # Feature illustrations, user content
β”œβ”€β”€ lottie/                           # Lottie animation files
β”œβ”€β”€ json/                             # Static configuration
β”œβ”€β”€ texts/                            # Agreement text (EN + Tagalog)
β”œβ”€β”€ barangays/                        # Barangay boundary GeoJSON
β”œβ”€β”€ database/                         # Archived Firestore snapshots (reference only)
└── downloads/                        # Downloadable content

Security Model

Role-based access control is enforced at the database level via firestore.rules, not just the client UI.

Role Read Write Elevation
user Own data, public reports, advisories Own profile, own reports (if verified, not banned) Self-registration sets role: user only
admin All users, reports, advisories, settings User profiles (non-admin), reports, advisories, settings Cannot self-promote to sysadmin
sysadmin Everything Everything Full access

Key Rules

  • No self-elevation β€” role changes denied unless performed by admin/sysadmin on another user
  • Report integrity β€” userId and reportedBy must match the authenticated user
  • Verification gating β€” only verified users can create reports
  • Deny-all fallback β€” match /{document=**} at the bottom rejects anything not explicitly allowed

Deploy Rules & Indexes

firebase deploy --only firestore:rules,firestore:indexes

⚠️ Firestore may prompt you to accept the composite indexes added in firestore.indexes.json (advisories status/barangay/barangayId

  • createdAt, and status + nextStatusAt) before queries using them work.

Migrate Existing Advisories

After deploying rules + indexes, backfill existing advisory documents with the new schema (idempotent, dry-run by default):

node scripts/migrate_advisories.js            # preview what will change
node scripts/migrate_advisories.js --run      # apply the backfill

Testing

Pure-Dart and widget tests (no Firebase required):

flutter test
  • test/advisory_model_test.dart β€” model units: status labels/colors, category lookup + icon fallback, buildSearchKeywords, computeCenter/computeBounds, computeNextStatusAt (one-time + recurring + wrap-around), tolerant fromJson/toJson round-trips (int coordinates, malformed entries skipped, unknown status β†’ inactive, epoch date fallback, legacy route shapes), and lifecycle edge cases (overnight spillover attribution, empty-weekday daily evaluation, end-inclusive expiry, stale-active transitions).
  • test/advisory_announcement_test.dart β€” public-notice phrasing: the fixed "NOTICE TO THE PUBLIC" header, all six category causes, place/barangay location variants, and the richer-field reason fallback.
  • test/advisory_export_test.dart β€” export layout geometry at five canvas sizes (banner/dot-grid/two-column/wave framing, left+map column separation, content band) and the WCAG contrast helpers (onDarkColor lifting, hue-preserving onLightColor).
  • test/widget_test.dart β€” widget tests for the shared advisory UI: AdvisoryStatusBadge labels/colors and AdvisoryCard content, admin-action visibility, callback wiring, recurring-schedule rendering, the lazy desktop masonry grid, and the filtered-empty state's clear-filters action.
  • test/advisory_details_dialog_test.dart β€” details-dialog tests: primary poster-style notice rows always visible (one-time and recurring schedules), secondary metadata hidden until "More details" expands, route legend labels, and rendering at narrow + wide widths.

Future Improvements

Planned Enhancements
Priority Feature Notes
πŸ”΄ High Add Firebase App Check Protects API keys from unauthorized use
🟑 Medium Storage quota & image optimization Uploads already run on Supabase Storage (1 GB free tier) with client-side orphan cleanup and image-cache eviction; add a compression pipeline for larger media
🟑 Medium Cloud Functions integration Login tracking migrated; remaining functions pending Blaze
🟑 Medium End-to-end testing suite Provider-based architecture primed for integration tests
🟑 Medium CI/CD pipeline GitHub Actions for lint β†’ test β†’ build
🟒 Low Push notifications Real-time alerting for new advisories
🟒 Low Offline-first support Firestore persistence + local sync
🟒 Low Accessibility (a11y) completion Screen-reader labels, live regions, focus management, and contrast largely covered in the advisory flows; remaining: keyboard navigation
🟒 Low Localization expansion Beyond English/Tagalog

Contributing

Contributions are welcome. This project does not yet have a formal CONTRIBUTING.md β€” for now, please open an issue or pull request on GitHub. Basic guidelines:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/my-feature)
  3. Commit your changes (git commit -m 'Add my feature')
  4. Push to the branch (git push origin feature/my-feature)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE for more information.

MIT is recommended for open-source Flutter projects β€” it's permissive, allows commercial use, and is the most widely adopted license in the Flutter ecosystem.


Links


Built with Flutter. Backend on Firebase Spark free tier. Maps powered by OpenStreetMap and contributors. Architecture restructured July 2026.

About

Local road incident reporting & traffic advisory management for Valenzuela City, Philippines.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages