Skip to main content
RapidDev - Software Development Agency
flutterflow-tutorials

How to Create a Crowd-Sourced Incident Reporting Feature in FlutterFlow

Build an incident reporting system where users submit reports with location, type, photos, and description. Display incidents on a Google Map with colored markers by type and status. Other users can upvote reports with a Me Too button to increase priority. An admin dashboard provides a triage queue for acknowledging, assigning, and resolving reports. Reporter identity is hidden from public views for safety.

What you'll learn

  • How to capture the user's current GPS location and attach it to incident reports
  • How to display incidents as colored map markers categorized by type and status
  • How to implement a Me Too upvote system for community incident confirmation
  • How to build an admin triage dashboard with status updates and department assignment
  • How to anonymize reporter identity in public views while preserving it for admin follow-up
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner8 min read35-45 minFlutterFlow Free+ (Google Maps API key required, Cloud Functions require Firebase Blaze plan)March 2026RapidDev Engineering Team
TL;DR

Build an incident reporting system where users submit reports with location, type, photos, and description. Display incidents on a Google Map with colored markers by type and status. Other users can upvote reports with a Me Too button to increase priority. An admin dashboard provides a triage queue for acknowledging, assigning, and resolving reports. Reporter identity is hidden from public views for safety.

Building a Community Incident Reporting System in FlutterFlow

Crowd-sourced incident reporting lets communities flag issues like potholes, graffiti, broken streetlights, or accidents. The key challenges are capturing accurate location data, categorizing reports visually on a map, letting the community validate reports via upvoting, and giving administrators tools to triage and resolve incidents. This tutorial covers each piece with FlutterFlow, Google Maps, Firestore, and Cloud Functions.

Prerequisites

  • A FlutterFlow project with Firestore and Firebase Authentication configured
  • Google Maps API key configured in FlutterFlow project settings
  • Firebase Storage for photo uploads
  • Location permissions configured in the FlutterFlow project

Step-by-step guide

1

Set up the Firestore data model for incidents and upvotes

Create an incidents collection with fields: userId (Reference, the reporter), type (String: pothole/graffiti/streetlight/accident/flooding/other), description (String), lat (Double), lng (Double), address (String, reverse geocoded), photoUrls (Array of Strings), status (String: reported/acknowledged/inProgress/resolved), priority (String: low/medium/high, derived from confirmCount), confirmCount (Int, number of Me Too upvotes), assignedDepartment (String, nullable), adminNotes (String, nullable), createdAt (Timestamp), resolvedAt (Timestamp, nullable). Create an incident_confirmations subcollection: incidents/{id}/confirmations with userId (Reference) to track who confirmed. This prevents duplicate upvotes. Add a Firestore composite index on status + createdAt for the admin dashboard query.

Expected result: Firestore has incidents with location, type, status tracking, and a confirmations subcollection for upvote deduplication.

2

Build the incident submission form with location and photo capture

Create a ReportIncidentPage. On page load, get the current user's location using FlutterFlow's Get Current Location action and store lat/lng in Page State. Display a mini Google Map centered on the user's location with a draggable marker so they can adjust the exact spot. Below the map, add an incident type selector: a GridView of 6 tappable Container cards, each with an icon and label (Pothole, Graffiti, Streetlight, Accident, Flooding, Other). Selected type gets a blue border. Add a description TextField (multiline, max 500 chars). Add a photo section with FlutterFlowUploadButton supporting multiple images (up to 3). On Submit, create the incidents doc with the location, type, photos, status as reported, confirmCount 0, and the current user's ID. Show a success SnackBar and navigate to the map view.

Expected result: Users can submit incident reports with precise location, categorized type, description, and up to 3 photos.

3

Display incidents on a Google Map with colored markers by type

Create an IncidentMapPage with a FlutterFlowGoogleMap filling most of the screen. Query all incidents where status is not resolved (or add a toggle to show resolved). For each incident, add a map marker at lat/lng with a color based on type: red for accident, orange for pothole, yellow for streetlight, blue for flooding, purple for graffiti, grey for other. Tapping a marker shows a BottomSheet with the incident details: type icon and label, description (first 100 chars), photo thumbnail (first photo), status badge (color-coded: grey=reported, blue=acknowledged, yellow=inProgress, green=resolved), confirmCount with a thumbs-up icon, and a View Details button. The View Details button navigates to IncidentDetailPage.

Expected result: The map shows all active incidents as colored markers. Tapping a marker reveals a summary with the option to view full details.

4

Implement the Me Too upvote system for community confirmation

On the IncidentDetailPage, below the full incident details (photos, description, map, status), add a Me Too button. Before showing the button, query the confirmations subcollection for a document with the current user's ID. If found, show 'You confirmed this' in grey instead of the button. On button tap, create a confirmation doc in the subcollection with the current userId and timestamp. Increment the incident's confirmCount using FieldValue.increment(1). If confirmCount reaches 5, update priority to medium. If it reaches 15, update priority to high. Display the confirmCount prominently: 'X people confirmed this incident'. A Cloud Function can optionally send a notification to the admin when confirmCount crosses threshold values.

Expected result: Users can upvote incidents they also observe, each user can only vote once, and high vote counts automatically increase incident priority.

5

Build the admin triage dashboard with status management

Create an AdminDashboardPage (protected by role check on page load). Display a TabBar with tabs: New (status reported), Active (acknowledged or inProgress), and Resolved. Each tab shows a ListView querying incidents by status, ordered by priority desc then createdAt asc (highest priority, oldest first). Each list item shows: type icon, address, description preview, confirmCount badge, and time since reported. Tapping opens the incident with admin controls: a DropDown to change status (acknowledged/inProgress/resolved), a DropDown for assignedDepartment (Roads, Parks, Utilities, Safety), and a TextField for adminNotes. On status change, update the incident doc. When marking resolved, set resolvedAt to now. Importantly, the admin view shows the reporter userId for follow-up, but public views never display reporter identity.

Expected result: Admins can triage incidents by priority, update statuses, assign departments, add notes, and contact reporters while public views stay anonymous.

Complete working example

FlutterFlow Incident Reporting Setup
1FIRESTORE DATA MODEL:
2 incidents/{incidentId}
3 userId: Reference (users, the reporter)
4 type: String (pothole | graffiti | streetlight | accident | flooding | other)
5 description: String
6 lat: Double
7 lng: Double
8 address: String (reverse geocoded)
9 photoUrls: Array of Strings
10 status: String (reported | acknowledged | inProgress | resolved)
11 priority: String (low | medium | high)
12 confirmCount: Int (default 0)
13 assignedDepartment: String (nullable)
14 adminNotes: String (nullable)
15 createdAt: Timestamp
16 resolvedAt: Timestamp (nullable)
17
18 incidents/{incidentId}/confirmations/{confirmId}
19 userId: Reference (users)
20 timestamp: Timestamp
21
22PAGE: ReportIncidentPage
23 Column
24 FlutterFlowGoogleMap (height: 200, draggable marker at user location)
25 Text "What type of incident?" (titleMedium)
26 GridView (crossAxisCount: 3, height: 200)
27 6x Container cards (icon + label, tappable, blue border when selected)
28 Pothole | Graffiti | Streetlight | Accident | Flooding | Other
29 TextField (description, multiline, maxLength: 500)
30 FlutterFlowUploadButton (multiple, max: 3)
31 Button "Submit Report"
32 On Tap Create incidents doc SnackBar Navigate map
33
34PAGE: IncidentMapPage
35 Stack
36 FlutterFlowGoogleMap (full screen)
37 Markers: colored by type, from incidents query
38 On Marker Tap show BottomSheet summary
39 FAB (bottom right) Navigate ReportIncidentPage
40 BottomSheet
41 Row: type icon + type label + status badge
42 Text (description, maxLines: 2)
43 Image (first photo, 80x60)
44 Row: thumbsUp icon + confirmCount + "people confirmed"
45 Button "View Details" Navigate IncidentDetailPage
46
47PAGE: AdminDashboardPage
48 TabBar: New | Active | Resolved
49 Each tab: ListView
50 Query: incidents by status, order by priority desc, createdAt asc
51 Card
52 Row: type icon + Text(address) + Badge(confirmCount)
53 Text (description, maxLines: 1)
54 Text (time ago, bodySmall)
55 On Tap Incident detail with admin controls
56 DropDown (status update)
57 DropDown (assign department)
58 TextField (admin notes)

Common mistakes when creating a Crowd-Sourced Incident Reporting Feature in FlutterFlow

Why it's a problem: Displaying the reporter's name and profile in the public incident view

How to avoid: Show incidents on the map and detail pages without any reporter information. Only the admin dashboard reveals the reporter userId for follow-up purposes.

Why it's a problem: Allowing users to upvote the same incident multiple times

How to avoid: Store each confirmation in a subcollection with the userId. Before showing the Me Too button, check if a confirmation doc already exists for the current user.

Why it's a problem: Not reverse-geocoding the GPS coordinates into a readable address

How to avoid: Use Google Maps Geocoding API in a Custom Action or Cloud Function to convert lat/lng to a human-readable address and store it on the incident document.

Best practices

  • Anonymize reporter identity in all public-facing views — only admins should see who reported
  • Use Firestore subcollection for confirmations to enforce one-vote-per-user deduplication
  • Auto-escalate priority based on confirmCount thresholds (5 = medium, 15 = high)
  • Color-code map markers by incident type for instant visual categorization
  • Reverse-geocode GPS coordinates to readable addresses for admin usability
  • Add photo evidence support (up to 3 images) to give admins visual context for triage
  • Sort the admin triage queue by priority descending, then oldest first, to surface urgent issues

Still stuck?

Copy one of these prompts to get a personalized, step-by-step explanation.

ChatGPT Prompt

I want to build a crowd-sourced incident reporting feature in FlutterFlow. Show me the Firestore data model, incident submission form with location and photos, a map view with colored markers by type, a Me Too upvote system, and an admin triage dashboard.

FlutterFlow Prompt

Create a page with a Google Map filling most of the screen. Add a floating action button in the bottom right corner for reporting new incidents. When a map marker is tapped, show a bottom sheet with an incident type icon, description, photo, confirmation count, and a View Details button.

Frequently asked questions

How accurate is the GPS location on the incident report?

GPS accuracy is typically 3-5 meters on modern smartphones. The draggable map marker lets users fine-tune the exact location if the GPS position is slightly off.

Can I add custom incident types beyond the default six?

Yes. Store incident types in a Firestore collection with name, icon, and color fields. Query this collection to populate the type selector grid dynamically. Admins can add new types without app updates.

How do I prevent spam or false reports?

Require authentication to submit reports. Track reports per user and flag accounts with high volumes. Add a report-as-spam button on incidents so the community can self-moderate. Admins can remove false reports and warn repeat offenders.

Can I notify nearby users about new incidents?

Yes. When an incident is created, a Cloud Function can query users within a radius using geohash comparison, then send push notifications to nearby users about the new report.

How do I generate analytics on incident patterns?

Query incidents grouped by type and time period in a Cloud Function. Display results on an admin analytics page with charts showing most common incident types, average resolution time, and geographic hotspots.

What if I need a full civic reporting platform with department routing?

RapidDev has built city-scale incident reporting systems in FlutterFlow with automated department routing, SLA tracking, public transparency dashboards, and integration with municipal work order systems.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.