-
Notifications
You must be signed in to change notification settings - Fork 0
Final Milestone Deliverables
Due dates: Software release 12.05.2026, 22:00 · Other deliverables 16.05.2026, 22:00
Group Number: 3
- 2026-02-18: Weekly Meeting #1
- 2026-02-18: Customer Meeting #1
- 2026-02-25: Stakeholder Meeting
- 2026-02-25: Weekly Meeting #2
- 2026-03-04: Weekly Meeting #3
- 2026-03-11: Weekly Meeting #4
- 2026-04-01: Weekly Meeting #5
- 2026-04-15: Weekly Meeting #6
- 2026-04-22: Weekly Meeting #7
- 2026-04-29: Weekly Meeting #8
- 2026-05-06: Weekly Meeting #9
- Final SRS: Software Requirements Specification
- Final Design:
- Deployed Web App: bounswe2026group3-azure.vercel.app
-
Mobile Release (.apk): GitHub Release
final-milestone
AccessMap (Neighborhood Accessibility Mapper) is, at the Final Milestone, a deployed cross-platform application — web (Vercel) and Android (APK release) — backed by a Django REST Framework API on a managed PostgreSQL database. The core product is a community-driven accessibility map: users discover obstacles around them, contribute new reports with photo evidence, validate each other's reports through upvotes and flags, and plan mobility-aware routes that avoid verified obstacles. The full citizen-facing lifecycle — guest browse → report submission → community verification → authority resolution → community-gated closure — works end-to-end across both platforms, alongside the supporting layers of authentication, mobility profile, saved places, trust score with Trusted Contributor badge, and asynchronous notifications.
Two areas were intentionally deprioritised in favour of the app-specific features above. Admin / moderation tooling has no dedicated frontend UI: the backend endpoints for flag review, report deletion, and account suspension exist and are tested, but we did not build a custom in-app admin surface this milestone — administrative actions are reachable only through the Django admin and direct API calls. This was a conscious scope decision rather than an oversight. Account-level spam detection (auto-flagging high-volume unverified accounts) was likewise deferred; moderation remains report-level through the existing flag-count threshold. Everything else either ships as completed or as a clearly scoped partial — see the detailed status in §4.2 — and the partials are documented behaviours (e.g. password-reset email delivery depends on production SMTP configuration, the in-app notifications_enabled toggle is supported by the backend but not yet surfaced as a profile control, the report-decay command is not yet attached to a scheduler, no formal WCAG audit or load benchmarks have been run, iOS lacks a production build pipeline) rather than missing functionality.
| Deliverable | Status | Notes |
|---|---|---|
| Web Application (deployed) | ✅ Complete | Live at bounswe2026group3-azure.vercel.app. |
| Mobile Application (Android APK) | ✅ Complete | Published as a release asset on the final-milestone GitHub Release. |
| Backend API | ✅ Complete | Containerized Django REST Framework service; OpenAPI/Swagger documentation served live. |
| Final SRS | ✅ Complete | Software Requirements Specification — kept in sync with the implementation. |
| Final Design (UML) | ✅ Complete | Class Diagram, Use Case Diagram, Sequence Diagrams. |
| Test Execution Reports (HTML + XML) | ✅ Complete | Backend, Web, Mobile reports linked in §4.6. All tests passing including regressions from MVP. |
| New Test Evidence (Integration / E2E / UI) | ✅ Complete | Playwright E2E smoke suite (PR #279) plus integration and UI tests added in this milestone. |
GitHub Release (final-milestone / v1.0.0) |
✅ Complete | Production tag on main; not marked pre-release. |
| README / Setup Instructions | ✅ Complete |
docker-compose.yml, .env.example, default credentials, and data-seeding instructions in the root README. |
| Wiki Final Milestone Deliverables page | ✅ Complete | This document. |
| W3C Standards Compliance Documentation | ✅ Complete | See §4.5 — WCAG 2.1, Schema.org, GeoJSON, JWT, ISO 8601, Activity Streams 2.0. |
Release: v1.0.0 — final-milestone (Official release)
Live web app: bounswe2026group3-azure.vercel.app
Headline features added since MVP
-
Full obstacle lifecycle.
Unverified→Confirmed(community-upvote-driven, threshold lowered for Trusted Contributors) →Resolved – Awaiting Validation(Authority-driven) →Closed(citizen-confirmation-gated). Markers are never silently removed; closure is community-validated. - Indoor / Outdoor obstacle reporting. Indoor pins render only above the High-Detail zoom threshold and are inherently excluded from routing.
- Trust Score & Trusted Contributor badge. Reputation increments on verified contributions; guests cannot earn score (enforced structurally by the auth requirement on submission).
- Infrastructure Authority dashboard. Filterable issue queue, mandatory post-repair verification photo on status transitions, official repair-note appending.
- Admin moderation. System-wide flagged-reports queue, permanent deletion, account suspension / banning.
-
Async notification system. Status-change notifications delivered to reporter and upvoters; authenticated newest-first feed endpoint; backend respects per-user
notifications_enabled. - Mobility Profile & Saved Places. Permanent profile with mobility aid type, accessibility preferences, and Home / Work shortcuts that tap-to-focus the map.
-
Obstacle-avoidance routing via Valhalla. Verified outdoor obstacles passed as
exclude_locations; passive and indoor reports inherently excluded from the avoidance set. - Accessibility standard violation chips. Reports surface which W3C / domain accessibility standards an obstacle violates (PR #262).
Infrastructure & quality improvements
- Containerized deployment (
docker-compose.yml+ Railway/Vercel pipelines). - Playwright E2E smoke suite gating CI (PR #279).
- Android APK build automated through EAS / GitHub Actions.
Known limitations (see §4.2 for the full list)
- Password-reset emails depend on production SMTP configuration (
EMAIL_BACKENDdefaults to console). -
notifications_enabledtoggle has no frontend control yet. -
decay_unverified_reportsruns as a command but is not yet on a scheduler. - No formal WCAG audit; performance / load benchmarks are unmeasured.
- iOS lacks a production build pipeline.
Most of these were called out as commitments in the post-MVP Project Retrospective and adopted in the weeks that followed.
- Fixed weekly meeting cadence. Weekly Meetings #6–#9 ran every Tuesday after MVP with full team attendance and an agenda prepared in advance — replacing the inconsistent, agenda-less meetings of the first half of the semester. The effect was concretely visible: Week 9's meeting was a structured gap-analysis that produced a per-member action list against the requirements catalog.
- Finer-grained, scope-tight GitHub issues. Post-MVP issues were opened with explicit scope, acceptance criteria, and a single owner — e.g. the Lab 8 issue cluster (#170, #171, #174, #177–#186) decomposed authority dashboard, moderation queue, decay automation, push notifications, and admin moderation UI into independently pickable units. Workload imbalance and hidden cross-team blockers — the retrospective's two biggest pain points — largely disappeared.
- Integration & testing treated as first-class work. Following the retrospective, integration tasks were no longer folded into feature issues. A dedicated E2E test suite (Issue #178 / PR #279) was opened, and Lab 8 / Lab 9 explicitly devoted their agendas to test coverage and gap analysis.
- Async sub-team sync on WhatsApp. Short weekly "what we did this week / what we need from you" messages between Backend, Frontend, and Mobile sub-teams reduced the cross-sub-team desyncs (mismatched endpoint contracts) we had during the MVP phase.
- 48-hour pre-deadline merge freeze on non-critical PRs. Carried over from the MVP and reused for the final-milestone release — code-complete but non-critical PRs were held to protect the deployed build from last-minute integration regressions.
-
Branch-protection + squash-merge on
mainenforced consistently. Conventional Commits andfeature/<issue>-<name>branch naming, established at the start of the semester, became fully consistent post-MVP — the final-milestone tag points cleanly at amaincommit with no out-of-band history.
The demo followed the scripted order from the Final Demo Plan, covering the full citizen-facing lifecycle across both web and mobile platforms. The authority and admin flows — new since MVP — were well received as meaningful additions to the system. The end-to-end obstacle lifecycle (submit → upvote → verify → authority resolve → community confirm → close) demonstrated clearly that the product has matured beyond a simple map viewer into a community-governed workflow.
The most prominent feedback from the instructors and customer centered on three areas. First, the status of a report was questioned — reviewers wanted clearer, more prominent display of what a report's current status means and how it progresses. Second, the overall presentation style was noted: this was our final presentation and the delivery was expected to be more polished. Third, the UI design of obstacle details was flagged: the photo on the detail page does not expand when tapped, and the detail view in general was felt to lack sufficient information depth.
A key conceptual question raised during the demo concerned the validation model: when an issue moves toward "Validated," reviewers asked what information other people would be using to validate it, and how confident those validators could reasonably be. This surfaces a gap in how we communicate the trust and evidence basis for community verification to the end user.
For future demos, we would invest more time in UI polish on the detail screens, ensure photo tap-to-expand is implemented, and prepare a cleaner narrative around the trust/validation model so that the "how does anyone know this is real?" question is answered proactively rather than reactively.
In the spirit of the Project Retrospective, and looking back across the full semester rather than just post-MVP:
-
Lock the routing engine choice in week 1. The OSRM-first → Valhalla pivot (PRs #134, #138) consumed two rounds of rework and compressed the testing window for routing. An earlier spike on
exclude_locations-style obstacle avoidance would have avoided the 60-metre-offset workaround entirely. - Stand up the test infrastructure (Playwright, backend integration harness, mobile component tests) by the end of week 3, not in the final milestone. Lab 8 / Lab 9 spent their agendas on test coverage that should have been baseline. Bugs the new tests caught late (e.g. duplicate notifications heading #270, saved-place precision #245) would have been caught when they were introduced.
-
Containerize and seed from day 1.
docker-compose.yml,.env.example, default seeded users, and a data-seeding script were finalized late in the project. Doing this in the first sprint would have given every team member identical local environments and removed an entire class of "works on my machine" issues that came up around the MVP demo. - Write GitHub issues with full acceptance criteria from the beginning. The retrospective identified this as the single biggest lever — and post-MVP issues confirmed it. The first half of the semester suffered from one-line issues without "definition of done", which is what drove workload imbalance and the bottlenecks where one merge blocked another.
- Decide on the resolution model (citizen-led vs. authority-led with citizen confirmation) before drafting use cases. We carried two resolution paths (1.1.6.3 citizen-proposed and 1.1.7.4 authority-led) in the SRS until late in the milestone, then collapsed to one. Locking that decision earlier would have removed a redundant entry from the requirements list and the design diagrams.
| Member (Surname, Name) | Core Contributions (Title) | Description (Brief Summary) | Related PRs | Related Issues |
|---|---|---|---|---|
| Akkaya, Ali | feat(map): add reporterId, userUpvoted, userFlagged to obstacle detail | Extends obstacle detail API with user interaction fields to support frontend UI states. | #203 | #196 |
| Akkaya, Ali | fix: use dynamic PORT for Railway nginx | Updates Nginx config to use dynamic PORT variable for Railway deployment. | #151 | - |
| Akkaya, Ali | fix: deploy fixes for Railway | Resolves npm peer dependencies and removes duplicate URL namespace for deployment. | #146 | - |
| Akkaya, Ali | feat: add Railway deployment config for frontend and backend | Adds Dockerfile and Nginx configurations for static serving and backend deployment. | #145 | - |
| Akkaya, Ali | feat(reports): implement POST /reports endpoint | Implements obstacle reporting endpoint with photo upload, proximity deduplication, and auto-verification. | #127 | #124 |
| Akkaya, Ali | fix: restore deleted migrations and fix .gitignore | Restores accidentally deleted database migrations and corrects .gitignore rules. |
#126 | - |
| Akkaya, Ali | feat: database schema, migrations & campus seed script | Adds core ORM models, enumerations, and a seed script for the campus graph. | #108 | #79 |
| Akkaya, Ali | feat: database schema, migrations & campus seed script | Configures Django settings and implements database schema based on SRS. | #103 | #79 |
| Akkaya, Ali | feat: implement Ali's Posts button with API integration and Dockerfile | Creates a Dockerfile for the static app and integrates JSONPlaceholder API for a stub page. | #70 | - |
| Aydemir, Bora | test(e2e): Playwright smoke test suite [QA] | Adds Playwright end-to-end smoke tests for core user flows in CI. | #279 | #178 |
| Aydemir, Bora | fix(frontend): remove duplicate Notifications heading and max slope gradient input | Fixes minor UI bugs in the notifications screen and mobility profile form. | #270 | #269 |
| Aydemir, Bora | feat(reports): accessibility standard violation chips on submit and detail | Adds accessibility violation chips mapping to Turkish standards in report forms. | #262 | #261 |
| Aydemir, Bora | feat(frontend): tap a saved place on profile to focus it on the map (#255) | Adds functionality to focus the map directly on a saved place from the profile tab. | #256 | #255 |
| Aydemir, Bora | refactor(frontend): drop ACTIVE pill and stub Badges card from profile (#253) | Cleans up profile UI by removing unused badges and pills based on user roles. | #254 | #253 |
| Aydemir, Bora | feat: show progress toward verification and resolution (#240) | Adds UI indicators showing current progress towards verification and resolution thresholds. | #246 | #240 |
| Aydemir, Bora | fix(places): accept high-precision lat/lng + surface real save errors + UX polish | Increases coordinate precision for saved places and improves error handling and toast UX. | #245 | #232 |
| Aydemir, Bora | fix(frontend): prefix mobility profile requests with /api/ | Fixes missing API prefix for mobility profile endpoints causing 404 errors. | #244 | #231 |
| Aydemir, Bora | feat: show UNVERIFIED reports on the map (hollow + dashed) and submit reports as UNVERIFIED by default | Renders UNVERIFIED reports as hollow markers on the map and reverts auto-verify dev shortcut. | #243 | #235 |
| Aydemir, Bora | feat(authority): dashboard UI for infrastructure authority role | Implements a dedicated dashboard UI for infrastructure authorities to resolve reports. | #229 | #181 |
| Aydemir, Bora | feat(frontend): merge route planning into map screen | Merges the separate Plan tab into a unified Google Maps-style map overlay. | #142 | #141 |
| Aydemir, Bora | fix(profile): correct /users/me endpoint URL and normalize reputationPoints to trustScore | Fixes profile screen empty fields by correcting endpoint URL and mapping response data. | #131 | #130 |
| Aydemir, Bora | feat(frontend): mobility profile | Implements the Mobility Profile feature, allowing users to set and save mobility preferences. | #113 | #91 |
| Aydemir, Bora | feat(frontend): report obstacle | Implements the Report Obstacle screen with GPS capture, photo attachment, and validation. | #111 | #92 |
| Aydemir, Bora | fix(frontend): auth routing | Fixes critical routing and authentication state bugs introduced in a previous merge. | #110 | #109 |
| Aydemir, Bora | feat: add Bora Aydemir button and TheSportsDB API integration | Adds a personalized button and integrates TheSportsDB API for a stub page. | #72 | - |
| Belemir, Ömer | Fix/backend critical bugs | Fixes indoor visibility logic, secures admin permissions, and removes redundant interactions app. | #268 | #263, #264, #265 |
| Belemir, Ömer | Fix/backend bugfixes | Fixes indoor visibility logic, secures admin permissions, and removes redundant interactions app. | #267 | #263, #264, #265 |
| Belemir, Ömer | Fix/backend bugfixes | Fixes indoor visibility logic, secures admin permissions, and removes redundant interactions app. | #266 | #263, #264, #265 |
| Belemir, Ömer | feat(users): implement GET/POST/PUT /users/me/mobility-profile endpoint | Implements backend API endpoints and serializers for managing user mobility profiles. | #227 | #143 |
| Belemir, Ömer | fix(notifications): alias serializer fields to camelCase for frontend | Fixes frontend crash by ensuring NotificationSerializer emits camelCase keys. | #224 | #223 |
| Belemir, Ömer | feat(users): implement GET/POST/PUT /users/me/mobility-profile endpoint | Implements backend API endpoints and serializers for managing user mobility profiles. | #144 | #143 |
| Belemir, Ömer | feat: add campus location search and switch routing to OSRM | Implements campus location search and switches routing logic from Dijkstra to OSRM pedestrian API. | #129 | #104, #102 |
| Belemir, Ömer | Routung Logic and some minor cleanup | Implements accessibility-aware routing utilizing Dijkstra's algorithm and user mobility preferences. | #122 | - |
| Belemir, Ömer | feat(auth): implement user registration endpoint with bcrypt hashing | Implements user registration endpoint, User model, and BCrypt password hashing. | #97 | - |
| Belemir, Ömer | feat: add omerbelemir API button with JSONPlaceholder integration | Adds a personalized button that fetches and displays posts from JSONPlaceholder API. | #71 | - |
| Evren, Arif | feat(backend): add Swagger UI via drf-spectacular | Adds Swagger UI API documentation using drf-spectacular. | #281 | #280 |
| Evren, Arif | docs: rewrite README with full project overview | Rewrites the README with comprehensive project documentation and setup guides. | #278 | - |
| Evren, Arif | fix(reports): show CLOSED reports as read-only on detail page | Updates backend and frontend to display CLOSED reports as read-only and allows all users to confirm resolutions. | #271 | #272 |
| Evren, Arif | fix(routing): always pass verified obstacles to Valhalla | Fixes routing logic to ensure verified obstacles are consistently passed to Valhalla for avoidance. | #257 | - |
| Evren, Arif | fix(deploy): install frontend deps before expo export to avoid npx pulling expo@55 | Fixes Vercel deployment error by ensuring correct dependencies are installed before exporting. | #249 | - |
| Evren, Arif | feat: suspend and ban user endpoints | Implements admin endpoints and permission checks to suspend or ban users. | #221 | #164 |
| Evren, Arif | feat: flag endpoint and exclude CLOSED reports from obstacle queries | Implements report flagging for moderation and explicitly excludes CLOSED reports from obstacle queries. | #220 | #179, #182 |
| Evren, Arif | feat: implement POST /api/reports/{id}/confirm-resolution endpoint | Implements the community resolution confirmation flow to transition reports to a closed state. | #195 | #166 |
| Evren, Arif | feat: implement password reset request and confirm endpoints | Implements backend password reset flow via email tokens. | #194 | #175 |
| Evren, Arif | feat: implement POST /api/reports/{id}/upvote endpoint | Implements the report upvoting endpoint, promoting reports to CONFIRMED status upon reaching a threshold. | #193 | #174 |
| Evren, Arif | feature: Github actions for apk flow added | Adds GitHub Actions workflow for automatic APK builds. | #157 | - |
| Evren, Arif | hotfix: Allow CORS | Enables CORS on the backend to allow requests from the frontend. | #154 | - |
| Evren, Arif | feature: all reports are now verified for MVP | Temporarily sets new reports to VERIFIED status by default for the MVP launch. | #140 | #139 |
| Evren, Arif | fixed report issue on backend | Fixes report ID type in responses and updates Supabase storage client configuration. | #132 | - |
| Evren, Arif | added users changes | Implements user profile GET and PUT endpoints for authenticated users. | #128 | #121 |
| Evren, Arif | Feature/supabase connection | Establishes the initial Supabase database connection and adds a backend health-check endpoint. | #101 | #100 |
| Evren, Arif | infra(docker): set up Docker, CI pipeline, and project configuration | Configures the Docker environment, GitHub CI pipeline, and base Django application setup. | #96 | - |
| Evren, Arif | feat: add Arif Evren button handler and page displaying Istanbul weather | Adds a custom button that fetches and displays Istanbul weather data via the Open-Meteo API. | #66 | - |
| Kemeç, Ulaş Sertan | Screen cache fixes for closed and fixing threshold logic to >= | Fixes map cache syncing issues for CLOSED/new reports, repairs broken report migrations, and corrects an off-by-one threshold logic error. | #274 | - |
| Kemeç, Ulaş Sertan | Feat/per trip route avoidance | Replaces global avoidance metrics with a per-trip system, rendering both baseline and alternative detour routes on the map. | #250 | #239 |
| Kemeç, Ulaş Sertan | Feat/saved places api | Implements the backend CRUD API endpoints, model definitions, and serializers for managing user-scoped saved places. | #219 | #199 |
| Kemeç, Ulaş Sertan | feat(reports): auto-decay stale UNVERIFIED reports to PASSIVE | Adds a Django management command to automatically transition old, interaction-free unverified reports to PASSIVE status. | #218 | #183 |
| Kemeç, Ulaş Sertan | feat: status-change notifications + authority resolve endpoint | Implements backend services and endpoints for in-app status notifications and an Infrastructure Authority report resolution endpoint. | #213 | #177, #172 |
| Kemeç, Ulaş Sertan | Feat/report upvote with trusted threshold | Adds report upvoting endpoint, lowering verification thresholds and handling role promotions for Trusted Contributors. | #191 | #174, #171 |
| Kemeç, Ulaş Sertan | feat: admin endpoint to delete reports as malicious | Adds an admin-only report deletion endpoint that automatically penalizes the reporter's trust score. | #189 | #187 |
| Kemeç, Ulaş Sertan | Feat/trust score | Establishes infrastructure and services for an environment-configurable trust score award and penalty system. | #188 | #165 |
| Kemeç, Ulaş Sertan | fix: align backend tests with current API and fix map serializer bugs | Resolves map app serializer bugs in production code and fixes various broken backend unit tests to match current APIs. | #158 | - |
| Kemeç, Ulaş Sertan | fix: remove unused tabs from layout | Removes placeholder bottom navigation tabs that are not yet implemented in the frontend. | #155 | - |
| Kemeç, Ulaş Sertan | fix: update nginx config | Updates the backend deployment Nginx server configuration details. | #150 | - |
| Kemeç, Ulaş Sertan | fix: remove redundant postgre db in frontend/docker file and window | Cleans up redundant PostgreSQL definitions in the frontend Dockerfile and corrects mobile map view setups. | #147 | - |
| Kemeç, Ulaş Sertan | fix: correct parameter errors in engine | Corrects parameter pass logic errors within the core routing calculation engine. | #136 | - |
| Kemeç, Ulaş Sertan | feat: update route engine to follow paths for foot, and escape obstacles | Upgrades pedestrian routing to actively avoid verified obstacles by injecting perpendicular detour waypoints into OSRM calls. | #134 | - |
| Kemeç, Ulaş Sertan | feature: map obstacles endpoints for single and multiple obstacles | Implements bounding box list views and individual detail endpoints for obstacle markers on the map. | #125 | #99 |
| Kemeç, Ulaş Sertan | Feature/report POST /report endpoint | Implements core report submission logic, database models, and Supabase storage uploads for attached photos. | #120 | #119 |
| Kemeç, Ulaş Sertan | Feature/authorization | Introduces role-based custom permission classes (IsUser, IsAuthority, IsAdmin) to secure protected backend endpoints. | #95 | #80 |
| Kemeç, Ulaş Sertan | feature: implement JWT auth endpoints (login, refresh, logout) | Sets up backend project skeleton and implements JWT authentication endpoints with token blacklisting. | #94 | #89 |
| Kemeç, Ulaş Sertan | Chore/project skeleton | Creates the foundational project repository folder architectures for parallel frontend and backend development. | #93 | #77 |
| Kemeç, Ulaş Sertan | feature: Add API calls for button 5 | Implements sample API calls for an individual placeholder landing page button. | #75 | - |
| Kemeç, Ulaş Sertan | Revert "feat: add Ulaş Sertan button handler displaying blog posts" | Reverts the prior individual blog post listing button handler functionality. | #73 | - |
| Kemeç, Ulaş Sertan | feat: add Ulaş Sertan button handler displaying blog posts | Adds an individual landing page button handler that fetches and lists sample blog posts via API. | #69 | - |
| Kılıç, Ekin | fix(frontend): resolve stale state in marker popup after detail view | Fixes map marker popup UI corruption after returning from report details by correcting state management and data flow. | #258 | - |
| Kılıç, Ekin | feat(frontend): add apply-to-authority screen (#228) | Adds a frontend screen for non-authority users to apply for the infrastructure authority role. | #248 | - |
| Kılıç, Ekin | fix(frontend): unwrap backend error envelope in parseDRFError (#233) | Fixes error parsing to properly display backend error messages instead of [object Object] in the UI. |
#247 | #233 |
| Kılıç, Ekin | feat(frontend): add map preview to authority report detail (#238) | Adds a lightweight, non-interactive map preview to the authority report detail screen. | #241 | #238 |
| Kılıç, Ekin | feat(interactions): hide upvote/flag buttons from guests (partial #90) | Implements guest restrictions by completely hiding upvote and flag buttons from unauthenticated users. | #217 | - |
| Kılıç, Ekin | feat(map): exclude CLOSED reports from map markers (#180) | Updates frontend map filters to explicitly prevent CLOSED reports from rendering as markers. | #216 | #180 |
| Kılıç, Ekin | Feature/trust score badge ekin | Adds numerical Trust Score display and a conditional "Trusted Contributor" SVG badge to the profile screen. | #215 | #168 |
| Kılıç, Ekin | feat(map): Google Maps-style overlay UI with route planning | Redesigns the map screen to a Google Maps-style layout, merging route planning directly into the map overlay. | #135 | - |
| Kılıç, Ekin | feat: implement password reset flow (issue #83) | Implements the frontend password reset flow screens and connects them to the backend API. | #118 | #83 |
| Kılıç, Ekin | feat: implement auth (login/register) and profile pages | Sets up initial Expo configuration, API services, and UI screens for authentication and user profiles. | #98 | - |
| Kılıç, Ekin | feat: add ekin button with random user API | Adds a custom button that fetches and displays data from the Random User API. | #68 | - |
| Önder, Baran | feat(notifications): notify reporter when their report is closed | Adds an in-app REPORT_CLOSED notification triggered when a report closes via community threshold, including the closure reason and a self-notification guard. |
#277 | #273 |
| Önder, Baran | feat(map): stale-while-revalidate refresh for obstacles | Implements stale-while-revalidate map refresh on focus and 60s TTL, ensuring obstacles update smoothly without the map blanking out. | #276 | #275 |
| Önder, Baran | fix(map): collapse route inputs into compact bar once route is calculated | Collapses the route planning input panel into a compact bar after route calculation to maximize map visibility. | #260 | - |
| Önder, Baran | perf(map): debounce bounds fetch, cache icons, fix popup flash on back | Improves web map performance by debouncing bounds fetch, caching DOM-heavy icons, and fixing Leaflet popup flashing bugs. | #252 | #251 |
| Önder, Baran | Feature/report discussion section | Adds a discussion section with comments and a status change timeline to the report detail screen, including backend endpoint integration. | #242 | #237, #236, #234 |
| Önder, Baran | feat(routing): ensure route response fields and add serializer unit tests | Ensures routing API correctly returns all fields with a 4km/h walking speed fallback and adds serializer unit tests. | #230 | #201 |
| Önder, Baran | feat(map): add passive obstacle toggle to map view | Adds a toggle switch to the map to display or hide inactive (PASSIVE) unverified reports. | #222 | #186 |
| Önder, Baran | fix: implement toggle behavior for upvote and flag interactions | Implements toggle behavior (ON/OFF) for upvotes and flags, enforces mutual exclusion, and adds cross-platform conflict alerts. | #214 | #209 |
| Önder, Baran | feat: implement notifications tab and in-app notification list | Implements the notifications tab on the frontend to list status updates and manage notification preferences via the profile screen. | #212 | #208 |
| Önder, Baran | Feature/saved places | Enables users to save frequent destinations and access them via quick-select chips during route planning and on their profile. | #211 | #198 |
| Önder, Baran | feat: add route summary panel to MapView (native and web) | Adds a route summary panel showing total distance, estimated time, and avoided obstacles count after calculation. | #210 | #204 |
| Önder, Baran | Feat/indoor form fields | Adds indoor reporting support with reverse-geocoded building auto-fill, floor fields, and distinct indoor map markers. | #192 | #173, #176 |
| Önder, Baran | Feat/obstacle interactions | Adds upvote, flag, and confirm-resolution buttons to obstacle details, implementing a bottom sheet on native and inline popup on web. | #190 | #169, #184, #152 |
| Önder, Baran | style: improve UI aesthetics across web and mobile screens | Improves overall UI aesthetics by updating search bars, input sizing, and tab bar layouts across platforms. | #153 | - |
| Önder, Baran | feat: add choose-on-map location picker to report form | Adds an interactive "Choose on Map" location picker to the report form for both web and mobile platforms. | #149 | #148 |
| Önder, Baran | fix: replace OSRM hacky rerouting with Valhalla exclude_locations | Upgrades obstacle avoidance by switching routing engine to Valhalla and passing verified obstacles to exclude_locations. |
#138 | #137 |
| Önder, Baran | fix: align frontend map API with backend response format | Aligns frontend map API transformers with the backend response format to properly render fetched obstacles. | #133 | - |
| Önder, Baran | feat(mobile): Implement map and route planning screens with WebView + Leaflet | Implements mobile-specific map and routing screens using WebView and Leaflet, and upgrades Expo SDK to 54. | #117 | #114, #115, #116 |
| Önder, Baran | feat(frontend): map view and route planning screens | Implements the initial web map view and route planning screens with OpenStreetMap tiles and API integrations. | #112 | #84, #85, #86 |
| Önder, Baran | feat: add Baran joke button with JokeAPI | Adds a custom button that fetches and displays a random programming joke from the JokeAPI. | #74 | - |
Completed = implemented + tested + documented + deployed.
| Requirement ID | Description | Status |
|---|---|---|
| 1.1.1.1 | Guest can browse the map without an account | ✅ Completed |
| 1.1.1.2 | Guest can view existing obstacle pins on the map | ✅ Completed |
| 1.1.1.3 | Register with valid email, full name, and birth date | ✅ Completed |
| 1.1.1.4 | Secure password required during registration | ✅ Completed |
| 1.1.1.5 | Registered user can log in with email and password | ✅ Completed |
| 1.1.1.6 | Registered user can log out | ✅ Completed |
| 1.1.1.7 | Request a password reset link via email | 🟡 Partial |
Notes: 1.1.1.3 — birth_date is captured at registration but is optional in the serializer rather than mandatory. 1.1.1.7 — token generation, expiry, and confirmation flow are implemented and tested, but EMAIL_BACKEND defaults to the console backend; real email delivery in the deployed environment depends on SMTP env configuration.
| Requirement ID | Description | Status |
|---|---|---|
| 1.1.2.1 | Create a permanent Mobility Profile | ✅ Completed |
| 1.1.2.2 | Select primary mobility aid from predefined categories | ✅ Completed |
| 1.1.2.3 | Guest can set temporary routing preferences for one session | ✅ Completed |
| 1.1.2.4 | Save frequent destinations (Home/Work) to profile | ✅ Completed |
| 1.1.2.5 | View earned badges (e.g. Trusted Contributor) on profile | ✅ Completed |
| 1.1.2.6 | Enable/disable in-app notifications from profile settings | 🟡 Partial |
Notes: 1.1.2.6 — backend fully supports and respects notifications_enabled (recipients with it disabled are skipped) and it is exposed/updatable via the profile-update serializer, but there is no in-app profile toggle control wired in the frontend yet.
| Requirement ID | Description | Status |
|---|---|---|
| 1.1.3.1 | Pan and browse the interactive map freely | ✅ Completed |
| 1.1.3.2 | Zoom in and out of the map | ✅ Completed |
| 1.1.3.3 | Click an obstacle marker to view details and photos | ✅ Completed |
| 1.1.3.4 | View indoor obstacle (POI) markers at high zoom | ✅ Completed |
| 1.1.3.5 | Toggle visibility of passive (stale/unverified) reports | ✅ Completed |
| 1.1.3.6 | Search for a location by text input | ✅ Completed |
| 1.1.3.7 | Manually select a location by dropping a pin | ✅ Completed |
| Requirement ID | Description | Status |
|---|---|---|
| 1.1.4.1 | Manually select a starting point | ✅ Completed |
| 1.1.4.2 | Manually select a destination point | ✅ Completed |
| 1.1.4.3 | Request a route calculation | ✅ Completed |
| 1.1.4.4 | View the generated route as a static visual path | ✅ Completed |
| 1.1.4.5 | View textual route summary (total distance, estimated time) | ✅ Completed |
| Requirement ID | Description | Status |
|---|---|---|
| 1.1.5.1 | Initiate a new report at current GPS location | ✅ Completed |
| 1.1.5.2 | Required Outdoor/Indoor context categorization | ✅ Completed |
| 1.1.5.3 | Optionally select an obstacle category | ✅ Completed |
| 1.1.5.4 | Required upload of at least one photo as evidence | ✅ Completed |
| 1.1.5.5 | Add a text description to the report | ✅ Completed |
| Requirement ID | Description | Status |
|---|---|---|
| 1.1.6.1 | Upvote (confirm) an unverified report | ✅ Completed |
| 1.1.6.2 | Flag a report as inaccurate or fake | ✅ Completed |
| 1.1.6.3 | Propose a solution by uploading a "Resolved" photo | ❌ Not Implemented |
| 1.1.6.4 | View the status timeline of an issue | ✅ Completed |
Notes: 1.1.6.3 — there is no citizen-facing "propose resolution with photo" flow; resolution-photo upload is handled exclusively by the Infrastructure Authority workflow (1.1.7.4), and citizens only cast "Confirm Resolution" votes.
| Requirement ID | Description | Status |
|---|---|---|
| 1.1.7.1 | Access a dedicated issue-management dashboard | ✅ Completed |
| 1.1.7.2 | Filter reports by status | ✅ Completed |
| 1.1.7.3 | Mark an issue as "Resolved – Awaiting Validation" | ✅ Completed |
| 1.1.7.4 | Required post-repair verification photo on status update | ✅ Completed |
| 1.1.7.5 | Append official repair notes to the issue | ✅ Completed |
| Requirement ID | Description | Status |
|---|---|---|
| 1.1.8.1 | View system-wide queue of community-flagged reports | 🟡 Partial |
| 1.1.8.2 | Permanently delete malicious reports | 🟡 Partial |
| 1.1.8.3 | Suspend or ban abusive user accounts | 🟡 Partial |
Notes: 1.1.8.1 / 1.1.8.2 / 1.1.8.3 — backend endpoints are implemented, tested, and deployed (PR #220 for flag-queue and CLOSED-report exclusion, PR #221 for suspend/ban), but we did not build a custom in-app admin UI this milestone. Administrative actions are reachable only through the Django admin and direct API calls. This was a conscious scope decision to prioritise app-specific citizen and authority features.
| Requirement ID | Description | Status |
|---|---|---|
| 1.2.1.1 | Render standard geographic base layers | ✅ Completed |
| 1.2.1.2 | Hide indoor markers until zoom exceeds High-Detail threshold | ✅ Completed |
| 1.2.1.3 | Render passive reports with a distinct semi-transparent style | ✅ Completed |
| Requirement ID | Description | Status |
|---|---|---|
| 1.2.2.1 | Calculate routes on an outdoor street-network graph | ✅ Completed |
| 1.2.2.2 | Exclude all "Indoor" reports from routing | ✅ Completed |
| 1.2.2.3 | Exclude "Passive" reports from routing | ✅ Completed |
| 1.2.2.4 | Generate routes up to the building entrance of the destination | 🟡 Partial |
Notes: 1.2.2.2 / 1.2.2.3 — only VERIFIED outdoor obstacles are passed to Valhalla as exclusion polygons; indoor and passive reports are inherently excluded from the avoidance set. 1.2.2.4 — routes are generated to the user-selected destination coordinate; there is no dedicated building-entrance snapping.
| Requirement ID | Description | Status |
|---|---|---|
| 1.2.3.1 | Assign initial "Unverified" status to new reports | ✅ Completed |
| 1.2.3.2 | Auto-transition to "Passive" after a period with no interaction | 🟡 Partial |
| 1.2.3.3 | Auto-transition to "Confirmed" when upvotes reach the threshold | ✅ Completed |
Notes: 1.2.3.2 — implemented and tested as the decay_unverified_reports management command, but no scheduler/cron is configured to run it automatically in the deployed environment.
| Requirement ID | Description | Status |
|---|---|---|
| 1.2.4.1 | Marker is not removed when an authority marks it resolved | ✅ Completed |
| 1.2.4.2 | Status updated to "Resolved – Awaiting Validation" | ✅ Completed |
| 1.2.4.3 | Notify the original reporter | ✅ Completed |
| 1.2.4.4 | Notify users who previously upvoted the issue | ✅ Completed |
| 1.2.4.5 | Require N "Confirm Resolution" votes to transition to Closed | ✅ Completed |
| Requirement ID | Description | Status |
|---|---|---|
| 1.2.5.1 | Maintain a Trust Score per registered user | ✅ Completed |
| 1.2.5.2 | Increment Trust Score when a submitted report is verified | ✅ Completed |
| 1.2.5.3 | Do not increment Trust Score for guest submissions | ✅ Completed |
| 1.2.5.4 | Grant "Trusted Contributor" role above the threshold | ✅ Completed |
| 1.2.5.5 | Lower verification threshold for Trusted Contributors | ✅ Completed |
Notes: 1.2.5.3 — enforced structurally: report submission requires authentication, so guests cannot create reports that would earn a score.
| Requirement ID | Description | Status |
|---|---|---|
| 1.2.6.1 | Auto-flag accounts with high volume of unverified reports as spam | ❌ Not Implemented |
| 1.2.6.2 | Async notification to reporter on "Confirmed" transition | ✅ Completed |
| 1.2.6.3 | Async notifications to reporter + upvoters on "Resolved – Awaiting Validation" | ✅ Completed |
| 1.2.6.4 | Authenticated endpoint returning notifications, newest first | ✅ Completed |
Notes: 1.2.6.1 — moderation is report-level (a report reaching SPAM_FLAG_THRESHOLD flags enters the moderation queue); there is no account-level rate/volume detection that marks a user as "Potential Spam".
| Requirement ID | Description | Status |
|---|---|---|
| NFR-1.1 | Available and functional as a web application | ✅ Completed |
| NFR-1.2 | Available and functional as a mobile application | 🟡 Partial |
Notes: NFR-1.2 — Android APK is produced via an EAS CI workflow; iOS is runnable through Expo but there is no production iOS build pipeline.
| Requirement ID | Description | Status |
|---|---|---|
| NFR-2.1 | Render map data/markers without perceptible delay | 🟡 Partial |
| NFR-2.2 | Compute routes within a reasonable time | 🟡 Partial |
| NFR-2.3 | Handle concurrent users without response-time degradation | 🟡 Partial |
Notes: Bbox-scoped queries, DB indexes, stale-while-revalidate caching, and select_for_update + atomic transactions address these, but there are no measured performance/load benchmarks proving the targets.
| Requirement ID | Description | Status |
|---|---|---|
| NFR-3.1 | Do not lose user-submitted reports on internal failure | ✅ Completed |
| NFR-3.2 | Validate all user-submitted data before public display | ✅ Completed |
| NFR-3.3 | Prioritize verified data over unverified in routing | ✅ Completed |
| NFR-3.4 | Recover from unexpected failures without manual intervention | 🟡 Partial |
Notes: NFR-3.1 — guaranteed via atomic writes to managed PostgreSQL. NFR-3.4 — relies on the hosting platform's auto-restart; no application-level self-recovery mechanism is implemented or tested.
| Requirement ID | Description | Status |
|---|---|---|
| NFR-4.1 | Conform to WCAG 2.1 Level AA | 🟡 Partial |
| NFR-4.2 | Usable on desktop and mobile screen sizes | ✅ Completed |
| NFR-4.3 | Operable using screen readers on all platforms | 🟡 Partial |
| NFR-4.4 | First-time user can submit a report without training | 🟡 Partial |
Notes: NFR-4.1 / 4.3 — an accessibility-standards catalog exists for obstacle classification, but the app UI has only minimal accessibilityLabel/accessibilityRole usage and no formal WCAG audit. NFR-4.4 — the report flow is a guided step form, but no usability validation was performed.
| Requirement ID | Description | Status |
|---|---|---|
| NFR-5.1 | Authenticate users before submission/data modification | ✅ Completed |
| NFR-5.2 | Transmit all data over encrypted connections | ✅ Completed |
| NFR-5.3 | Enforce role-based access control across roles | ✅ Completed |
| Requirement ID | Description | Status |
|---|---|---|
| NFR-6.1 | Require explicit permission for device location | ✅ Completed |
| NFR-6.2 | Do not expose PII of users who report issues | 🟡 Partial |
Notes: NFR-6.2 — reporter identity in public obstacle data is limited to a UUID, but the public status-history serializer exposes the email of the actor who changed a status (changedBy), which is a PII leak that should be reduced to a display name/ID.
| Requirement ID | Description | Status |
|---|---|---|
| NFR-7.1 | Function on all major modern browsers | ✅ Completed |
| NFR-7.2 | Support current and recent iOS and Android versions | 🟡 Partial |
Notes: NFR-7.2 — built on Expo SDK 54 / RN 0.81 (broad OS support), but only Android has a build pipeline and there is no tested device/OS-version matrix.
| Requirement ID | Description | Status |
|---|---|---|
| NFR-8.1 | Support multiple municipalities without degradation | ❌ Not Implemented |
| NFR-8.2 | Accommodate a growing number of reports and users over time | 🟡 Partial |
Notes: NFR-8.1 — there is no multi-tenant/municipality scoping; the system operates on a single shared dataset. NFR-8.2 — paginated, indexed PostgreSQL-backed design supports growth, but this is not validated by load testing.
The live API documentation is served directly from the deployed backend via drf-spectacular, so it is generated from the running code and is therefore inherently consistent with the final release and the Final SRS. Every endpoint in the final release is introspected and listed there; the removed interactions app left no public surface, and no previously documented endpoint is deprecated (the report interaction logic was consolidated under /api/reports/ rather than deprecated in place).
- Live API Docs (Swagger UI): https://bounswe2026group3-2.onrender.com/api/schema/swagger-ui/
- OpenAPI schema (raw): https://bounswe2026group3-2.onrender.com/api/schema/
A bearer token for the authenticated scenarios below is obtained from
POST /api/auth/login/(email + password) and passed asAuthorization: Bearer <token>.
Scenarios 2–4 demonstrate functionality added after the MVP milestone (community auto-verification with trust-score side effects, the authority resolution workflow, and per-trip obstacle-avoidance routing). Scenario 1 is the obstacle-report submission pipeline. None are simple data retrieval — each involves a multi-step workflow, a state transition, validation, and/or side effects.
-
Endpoint:
POST /api/reports/ -
Scenario Description: A citizen reports a broken sidewalk by submitting its GPS location, an obstacle category, and a photo — the backend uploads the image to object storage and atomically persists a new
UNVERIFIEDreport. - The Request:
curl -X POST "https://bounswe2026group3-2.onrender.com/api/reports/" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"location": { "lat": 41.085100, "lng": 29.051200 },
"context": "OUTDOOR",
"category": "DAMAGED_SURFACE",
"description": "Broken sidewalk segment, large gap blocking the path.",
"photos": ["data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...truncated..."],
"violations": []
}'- The Response:
{
"reportId": "5f1c2a90-3b7e-4d2a-9c11-8a6f0e2d4b71",
"status": "UNVERIFIED",
"autoVerified": false,
"duplicateCandidate": null,
"createdAt": "2026-05-14T09:22:41.512Z"
}-
Endpoint:
POST /api/reports/{reportId}/upvote/ -
Scenario Description: A second citizen upvotes a pending report; when the upvote count reaches the role-based threshold the system transitions the report to
VERIFIED, awards the reporter trust score, and emits a status-change notification — all in one atomic call. - The Request:
curl -X POST "https://bounswe2026group3-2.onrender.com/api/reports/5f1c2a90-3b7e-4d2a-9c11-8a6f0e2d4b71/upvote/" \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json"- The Response:
{
"reportId": "5f1c2a90-3b7e-4d2a-9c11-8a6f0e2d4b71",
"upvoteCount": 3,
"upvoteThreshold": 3,
"userUpvoted": true,
"status": "VERIFIED",
"autoVerified": true
}-
Endpoint:
PATCH /api/authority/reports/{reportId}/resolve -
Scenario Description: An infrastructure authority closes out a repair by uploading a mandatory post-repair photo and notes; the report transitions
VERIFIED → RESOLVED_AWAITING_VALIDATIONand the original reporter plus every upvoter are notified asynchronously. - The Request:
curl -X PATCH "https://bounswe2026group3-2.onrender.com/api/authority/reports/5f1c2a90-3b7e-4d2a-9c11-8a6f0e2d4b71/resolve" \
-H "Authorization: Bearer $AUTHORITY_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"repairPhoto": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...truncated...",
"repairNotes": "Sidewalk slab replaced and levelled on 2026-05-15; ramp gradient now compliant."
}'- The Response:
{
"reportId": "5f1c2a90-3b7e-4d2a-9c11-8a6f0e2d4b71",
"status": "RESOLVED_AWAITING_VALIDATION",
"repairPhotoUrl": "https://<project>.supabase.co/storage/v1/object/public/report-photos/9b2e1d77-4c3a-4f80-bc12-7e6a1f0d2c84.jpeg",
"updatedAt": "2026-05-15T14:07:03.889Z"
}-
Endpoint:
POST /api/routes/calculate - Scenario Description: A wheelchair user requests a pedestrian route from North Campus to Duatepe Park; the engine computes a baseline route, then a second pass that routes around verified outdoor obstacles, returning both legs and the number of obstacles avoided.
- The Request:
curl -X POST "https://bounswe2026group3-2.onrender.com/api/routes/calculate" \
-H "Content-Type: application/json" \
-d '{
"originLat": 41.086300,
"originLng": 29.050100,
"destinationLat": 41.043600,
"destinationLng": 29.003000,
"preferences": {
"avoidStairs": true,
"avoidSteepSlopes": true,
"maxSlopeGradient": 0.08
}
}'- The Response: (waypoint lists truncated in the middle; structure preserved)
{
"waypoints": [
[41.086300, 29.050100],
[41.085910, 29.049620],
"… 138 intermediate waypoints omitted …",
[41.043600, 29.003000]
],
"distanceMeters": 5124.7,
"estimatedTimeSeconds": 4612,
"baselineRoute": {
"waypoints": [
[41.086300, 29.050100],
"… 121 intermediate waypoints omitted …",
[41.043600, 29.003000]
],
"distanceMeters": 4880.2,
"estimatedTimeSeconds": 4392
},
"alternativeRoute": {
"waypoints": [
[41.086300, 29.050100],
"… 140 intermediate waypoints omitted …",
[41.043600, 29.003000]
],
"distanceMeters": 5124.7,
"estimatedTimeSeconds": 4612
},
"avoidedObstaclesCount": 1,
"warnings": [
"Unverified obstacle nearby: Construction near park entrance"
],
"isAccessible": true
}-
Frontend Code (Web): [TODO – link to
bounswe2026group3/frontendfinal commit / folder] -
Frontend Code (Mobile): [TODO – link to
bounswe2026group3/mobilefinal commit / folder]
Provide screenshots of only the new or significantly modified web and mobile interfaces developed in this milestone. Pair each image with a short description.
- [TODO – screenshot link] — [TODO – description]
- [TODO – screenshot link] — [TODO – description]
- [TODO – screenshot link] — [TODO – description]
Documents the W3C-led and closely related open web standards we applied in the final-milestone release. The list below matches the standards committed to in §3.1.2 (W3C Standards Compliance Documentation). A more discursive, pre-final overview lives on the Use of Standards wiki page.
- WCAG 2.1 — Web Content Accessibility Guidelines (W3C Recommendation).
- Schema.org — Structured-data vocabulary (W3C-affiliated community standard).
- GeoJSON (RFC 7946) — JSON encoding of geographic data structures.
- JSON Web Tokens (RFC 7519) — Compact, signed token format used for authentication.
- ISO 8601 — International date and time representation.
- Activity Streams 2.0 — W3C Recommendation for representing notifications / social activities.
-
Evidence:
- PR #262 (Issue #261) — feat(reports): accessibility standard violation chips on submit and detail. Surfaces, on every report, which accessibility standards an obstacle violates (TS-EN 17210, ADA / WCAG analogues for the built environment), turning the standards catalogue into a first-class UI affordance.
- PR #229 (Issue #181) — feat(authority): dashboard UI for infrastructure authority role. Built with explicit
accessibilityRole/accessibilityLabelprops on every interactive element and meets minimum touch-target sizing. - PR #246 (Issue #240) — feat: show progress toward verification and resolution. Progress indicators reinforce information by both colour and shape (SC 1.4.1 — Use of Color), not colour alone.
-
Code Coverage:
-
frontend/src/constants/theme.ts— central colour palette with documented foreground/background pairs chosen to clear WCAG AA contrast against neutral surfaces (e.g.green700 #27724A,gray900 #111827onwhite #FFFFFF). -
frontend/src/components/profile/AidTypeChips.tsx— chip buttons declareaccessibilityRole="radio"plusaccessibilityState={{ checked: active }}, render with a minimum 80 dp touch target (SC 2.5.5 — Target Size), and persist focus/selection visibly. -
frontend/src/components/profile/MobilityProfileCard.tsx,frontend/src/components/profile/TrustedContributorBadge.tsx— every actionable / informational element carries an explicitaccessibilityLabelandaccessibilityRoleso screen readers announce purpose and state. -
frontend/src/components/reports/ReportForm.tsx,frontend/src/components/map/MapView.web.tsx— semantic form controls, labelled inputs, andalttext on obstacle photos (SC 1.1.1 — Non-text Content). -
Product-level accessibility:
backend/apps/routing/services.pypasses verified outdoor obstacles to Valhalla'sexclude_locationsso wheelchair / reduced-mobility users get physically-accessible routes — a direct expression of the WCAG principle of perceivable, operable, navigable infrastructure extended to the built environment.
-
- Reasoning: The product's whole purpose is mobility access, so WCAG is applied at two levels. In-app we follow the operational SC family relevant to a React Native / Leaflet UI — colour contrast (1.4.3), use of colour as redundant signal (1.4.1), info & relationships exposed semantically via the React Native accessibility API (1.3.1), target size (2.5.5), and name/role/value on every interactive control (4.1.2). Beyond the app, the routing engine itself acts as an accessibility-conformance tool: it computes paths that avoid the very obstacles WCAG-style accessibility audits would flag in the physical world. We have not run a third-party WCAG AA audit (called out honestly under NFR-4.1 in §4.2), so we describe this as principled WCAG-aligned implementation rather than certified Level AA conformance.
-
Evidence:
- PR #219 (Issue #199) — feat: saved places API. Saved-place entities (Home / Work) are modelled on
schema:Placewithschema:name,schema:latitude,schema:longitude. - PR #227 (Issue #143) — feat(users): mobility-profile endpoint. User & profile fields map to
schema:Person(name,birthDate) plus mobility-aid extension fields aligned withschema:accessibilityFeature. - PR #262 — accessibility violation chips map our obstacle categories to the Schema.org
schema:accessibilityHazardvalue space (e.g.noPavingAccessibility,stairsOnly-style hazards).
- PR #219 (Issue #199) — feat: saved places API. Saved-place entities (Home / Work) are modelled on
-
Code Coverage:
-
backend/apps/map/serializers.py—LocationSerializerandObstacleDetailSerializerexpose lat/lng plus a category enum drawn from the Schema.org accessibility vocabulary. -
backend/apps/places/serializers.py— saved-place serializer (name + lat/lng) mirrorsschema:Place. -
backend/apps/users/serializers.py—UserProfileSerializerusesfullName/birthDatematchingschema:Person. -
frontend/src/constants/accessibilityStandards.ts— the catalogue PR #262 wires into the UI references Schema.org accessibility-hazard / accessibility-feature terms.
-
-
Reasoning: Schema.org gives us a stable, widely understood vocabulary so the JSON API is self-documenting and trivially indexable by external semantic tooling. We adopt the property names from Schema.org (
name,latitude,longitude,birthDate, accessibility hazard / feature concepts) without emitting full@contextJSON-LD framing — this keeps the wire format lean for the React Native client while keeping the data model isomorphic to Schema.orgPlaceandPersontypes.
-
Evidence:
- PR #250 (Issue #239) — feat: per-trip route avoidance. Encodes obstacle exclusions as GeoJSON-style
[lat, lng]coordinate pairs passed to Valhalla'sexclude_locations, and produces baseline + alternative polylines decoded into the same coordinate format. - PR #257 — fix(routing): always pass verified obstacles to Valhalla. Guarantees the verified obstacle set is serialised consistently as GeoJSON coordinates on every routing request.
- PR #138 — replace OSRM hacky rerouting with Valhalla
exclude_locations. The point at which the routing layer was rebuilt on top of GeoJSON-style exclusion polygons.
- PR #250 (Issue #239) — feat: per-trip route avoidance. Encodes obstacle exclusions as GeoJSON-style
-
Code Coverage:
-
backend/apps/routing/services.py— builds the request body for Valhalla using[lat, lng]coordinates and decodes returned polylines into coordinate arrays consistent with RFC 7946 axis ordering rules. -
backend/apps/map/serializers.py— obstacle locations are serialised as{ "latitude": …, "longitude": … }pairs, equivalent to GeoJSONPointcoordinates with a stable axis order. -
frontend/src/components/map/MapView.tsx,frontend/src/components/map/MapView.web.tsx— Leaflet markers and polylines consume[lat, lng]directly, end-to-end with no custom transformation layer.
-
-
Reasoning: GeoJSON is the de facto interchange format for geographic data on the web; aligning to it (even when we do not emit a full
FeatureCollectionenvelope) means our coordinates flow unmodified between the Django backend, Leaflet /react-leafleton the frontend, and the Valhalla routing service. This kept the OSRM → Valhalla pivot (PR #134 → PR #138 → PR #250) low-friction: only the request-shape changed, not the coordinate format.
-
Evidence:
- PR #94 (Issue #89) — feat: implement JWT auth endpoints (login, refresh, logout). Establishes the project's JWT auth via
djangorestframework-simplejwt, including rotation and blacklist on logout. - PR #194 (Issue #175) — feat: password reset request and confirm endpoints. Issues short-lived, single-purpose tokens for the password-reset flow.
- PR #221 (Issue #164) — feat: suspend and ban user endpoints. Server-side checks against the JWT subject claim enforce account-status gating on every authenticated request.
- PR #94 (Issue #89) — feat: implement JWT auth endpoints (login, refresh, logout). Establishes the project's JWT auth via
-
Code Coverage:
-
backend/config/settings.py—SIMPLE_JWTblock: access tokens 30 min, refresh tokens 7 days,ROTATE_REFRESH_TOKENS=True,BLACKLIST_AFTER_ROTATION=True. Standard claims (iss,sub,iat,exp,jti) are emitted by the library. -
backend/apps/users/views.py,backend/apps/users/urls.py— login / refresh / logout endpoints built onsimplejwt. -
frontend/src/services/auth.ts— client-side token lifecycle: persists access (am_access) and refresh (am_refresh) tokens, attachesAuthorization: Bearer <token>to every protected request, and refreshes on 401.
-
-
Reasoning: RFC 7519 specifies a stateless, signed token format with a well-defined claim set. Using
djangorestframework-simplejwtgives us a vetted implementation — no hand-rolled crypto — and the stateless property keeps the API horizontally scalable (no server-side session table). Token rotation plus blacklisting closes the "stolen refresh token" gap that pure stateless JWT would otherwise leave open.
-
Evidence:
- PR #224 (Issue #223) — fix(notifications): alias serializer fields to camelCase. Notification timestamps are emitted as
createdAtin ISO 8601 (YYYY-MM-DDTHH:mm:ssZ) for a clean wire contract. - PR #213 (Issues #177, #172) — feat: status-change notifications + authority resolve endpoint. All status-change timestamps are recorded and serialised in ISO 8601.
- PR #227 — feat(users): mobility-profile endpoint.
birthDateserialised as ISO 8601 date (YYYY-MM-DD).
- PR #224 (Issue #223) — fix(notifications): alias serializer fields to camelCase. Notification timestamps are emitted as
-
Code Coverage:
-
backend/apps/reports/serializers.py,backend/apps/notifications/serializers.py,backend/apps/users/serializers.py— everyDateTimeField/DateFielduses DRF's default ISO 8601 serialisation;createdAt,updatedAt,birthDate,closedAtall flow through this path. -
backend/apps/reports/models.py—auto_now_add/auto_nowtimestamps stored in UTC, serialised to ISO 8601 on read. -
frontend/src/services/*.ts— frontend parses ISO 8601 strings with the built-inDateconstructor; no custom format negotiation.
-
- Reasoning: ISO 8601 is unambiguous across locales and time zones — exactly the property we need across a Django backend (UTC), a React Native frontend (device-local), and any third-party that touches our API. We get this nearly for free by relying on DRF defaults; the only place we deviated was to alias snake_case → camelCase on the wire (PR #224), which is orthogonal to the date format.
-
Evidence:
- PR #213 (Issues #177, #172) — feat: status-change notifications + authority resolve endpoint. Introduces the
report_status_changedsignal and aNotificationmodel whose fields map to the AS 2.0 core activity shape (recipient / type / object / published). - PR #212 (Issue #208) — feat: implement notifications tab and in-app notification list. The frontend renders notifications as activity items with type-aware iconography (
REPORT_VERIFIED,REPORT_RESOLVED,REPORT_CLOSED). - PR #277 (Issue #273) — feat(notifications): notify reporter when their report is closed. Hooks a new activity type into the same
report_status_changedpipeline without touching the notification service — a benefit of designing the model around AS 2.0's extensibletypevocabulary.
- PR #213 (Issues #177, #172) — feat: status-change notifications + authority resolve endpoint. Introduces the
-
Code Coverage:
-
backend/apps/notifications/models.py—Notificationhasuser(AS 2.0 recipient /target),notification_type(AS 2.0type, drawn fromNotificationTypetext-choices:REPORT_VERIFIED,REPORT_RESOLVED,REPORT_CLOSED),related_report(AS 2.0object),created_at(AS 2.0published), andmessage(renderedsummary). -
backend/apps/notifications/services.py— fans a single status-change event out to the reporter and all prior upvoters, each materialised as its ownNotificationrow. Respects the per-usernotifications_enabledflag. -
backend/apps/notifications/signals.py— listens for thereport_status_changedsignal emitted by the reports app, decoupling activity production from activity delivery. -
backend/apps/notifications/serializers.py— exposes the activity over a paginated newest-first endpoint with camelCase field names (notificationType,relatedReport,createdAt).
-
-
Reasoning: Our notification system implements the shape and semantics of an AS 2.0 activity stream rather than its on-the-wire JSON-LD framing. Every notification carries the AS 2.0 essentials — a recipient, an activity
typedrawn from a controlled vocabulary, anobject(the affected report), and apublishedtimestamp — and is delivered through a feed endpoint sorted newest-first, exactly as AS 2.0'sOrderedCollectionprescribes. We deliberately omit the@context: "https://www.w3.org/ns/activitystreams"JSON-LD wrapper because no external consumer federates with us today; adopting the wrapper later would be a serialiser change only, since the underlying model is already isomorphic toUpdate/Announce-style activities.
All three test layers were executed with zero failures before the final release. Reports are committed on the chore/d7-test-reports branch.
Backend API (79 pytest tests, 0 failures, 88 % line coverage)
Web / Mobile App (46 Jest tests, 0 failures — shared React Native codebase)
The frontend is a single React Native codebase that targets both web (Expo Web) and mobile (iOS/Android via Expo Go), so one test run covers both platforms.
Integration Tests — new API & service interactions
The backend suite spans four application domains. All tests hit a real SQLite test database (no mocking) to prevent the prod/mock divergence that plagued earlier milestones.
| Module | Source |
|---|---|
| Map (obstacle list, detail, bbox, search) | backend/apps/map/tests.py |
| Reports (create service, serializer, view) | backend/apps/reports/tests.py |
| Routing (Valhalla integration, obstacle avoidance) | backend/apps/routing/tests.py |
| Users (registration, mobility profile) | backend/apps/users/tests.py |
End-to-end Tests — core user workflows (Playwright, added this milestone)
Three full browser flows covering registration, routing, and upvoting — the same paths a first-time user takes during a demo:
-
frontend/e2e/smoke.spec.ts— register → login → view map → submit report · login → route between two campus points · upvote a report → count increments -
frontend/e2e/helpers/api.ts— shared test helpers (registerUser, createReport, seedAuth) -
frontend/playwright.config.ts— Playwright configuration -
.github/workflows/e2e.yml— CI workflow (runs against deployed environment viaE2E_BASE_URL)
UI/UX Tests — component and hook coverage (Jest + React Testing Library)
| File | What it covers |
|---|---|
MobilityProfileCard.test.tsx |
View/edit mode, validation, all 7 aid-type chips |
ReportForm.test.tsx |
Category selection, photo requirement, context options, UAC-7.x acceptance criteria |
ReportSuccessScreen.test.tsx |
Success heading, report ID display, auto-verified badge |
useLocation.test.ts |
Loading state, permission grant/deny, refetch |
mobilityProfileApi.test.ts |
CRUD lifecycle for mobility profiles |
reports.api.test.ts |
submitReport payload shape, coordinate rounding, ISO timestamp |
Coverage
This milestone's testing effort focused on the three features that carried the highest risk of silent breakage before a public release: accessibility-aware routing, report submission, and the mobility profile. The backend routing suite (13 test cases in CalculateRouteViewTest) exercises Valhalla integration end-to-end — obstacle exclusion, mobility-profile preference propagation, and Valhalla failure handling — giving the team confidence that the core value proposition of the app works correctly under varied conditions. On the frontend, the ReportForm and MobilityProfileCard suites were written directly against the UAC acceptance criteria (UAC-7.x), making it impossible to ship a regression in the two primary user interactions without a red CI build. The new Playwright E2E suite closes the remaining gap: it is the only layer that exercises the full auth → map → submit flow as a real browser would, catching issues (CORS headers, token refresh, geolocation permissions) that unit tests cannot reach.
Bug Detection
-
Map serializer reported zero upvotes for all obstacles.
ObstacleSerializer.get_upvoteCountusedgetattr(obj, 'upvote_count', 0), assuming the ORM queryset would carry a pre-annotatedupvote_countfield. Because that annotation was not always applied, every obstacle silently returned 0 upvotes in the API response. The testtest_upvote_count_in_listcaught this immediately: it created a report, upvoted it, and asserted the list endpoint returned a non-zero count — which failed. The fix replaced the annotation lookup with a direct count ofUPVOTE-typed interactions (fix: align backend tests with current API). -
Campus location serializer crashed on dict input.
CampusLocationSerializer.get_locationassumedobjwas always a Django model instance and calledobj.latitude/obj.longitudeas attributes. When the routing service passed a plaindict(as it does for Nominatim geocoder results), this raised anAttributeErrorin production. The routing integration tests exposed the crash; the fix added anisinstance(obj, dict)guard to handle both cases before the code reached users (fix: align backend tests with current API).
Readiness
The combination of 79 passing backend tests at 88 % line coverage, 46 passing frontend unit tests, and a green Playwright smoke suite against the full stack gives the team a layered safety net: serializer contracts and business-logic edge cases are caught at the unit level; cross-service interactions (auth, routing, Valhalla) are validated at the integration level; and the most critical user journeys (register, report, route, upvote) are verified end-to-end in a real browser. Every regression that was introduced while aligning the test suite with the current API was caught and fixed before the branch was merged. The CI pipeline now enforces this baseline on every push, so the system enters the Official Release phase with both a clean test record and an automated guard against future regressions.
Handwritten notes taken during the demo session captured the following raw feedback points:
- Status of report is questioned — reviewers were unclear on the current state and progression of a report from the UI.
- Son (final) presentation — noted as the final presentation, implying higher expectations for polish and delivery quality.
- UI design of obstacle details — the detail screen was flagged for insufficient depth.
- Issue → Validated: A lot of reliance on other people. How people are gonna validate with which info. — core conceptual question about the evidence basis and information quality available to community validators.
-
Obstacle [section]:
- Photo does not get bigger on detail page.
- More detail needed on the obstacle detail screen.
The demo successfully walked through the full lifecycle across both platforms, and the authority dashboard received positive attention as a concrete new feature. The feedback on report status visibility and the validation information model are actionable: the status indicator needs to be more prominent and self-explanatory, and the detail screen should surface more context (reporter trust score, number of upvotes, photo evidence more prominently) so that a validator has everything they need without leaving the screen. The photo non-expandability is a straightforward UX fix that should have been caught before the demo. For the next iteration, UI polish on detail screens and a clearer in-app explanation of the trust/validation model would be the two highest-leverage improvements.
Each member adds a subsection below. Subsections are sorted alphabetically by surname. Include only contributions made since the previous milestone. Every claim must be backed by a hyperlink to a GitHub PR or Issue.
Strict limits: Top 3 issues per category (Code-Related, Non-Code-Related). Listing more than 3 per category incurs a grade penalty.
-
Responsibilities: Backend developer on the four-person backend sub-team and project-wide presentation lead. On the backend side I am the original author of the project's Django data layer (the obstacle/report/user/notification schema and the campus-graph seed script) and of the
POST /reportssubmission pipeline — the two surfaces that every other backend feature in the final milestone extends rather than replaces (trust score, upvote/flag, status-change notifications, decay-to-passive, authority resolve, admin malicious-deletion, route exclusion, all read on top of the schema and the report object I shipped). In the final milestone my responsibility narrowed to maintaining and extending those owned surfaces — most visibly through the obstacle-detail user-state contract in PR #203 — and broadened on the non-code side: I served as the project's main presenter (MVP demo and Final Milestone demo), drove the architectural narrative that the team used in stakeholder presentations, and specced two backend-facing features (#196, #261) that the team subsequently built out. -
Main Contributions:
-
Obstacle-detail user-state contract (PR #203, Issue #196). Extended
GET /api/map/obstacles/{id}/withreporterId,userUpvoted, anduserFlagged. This is the backend contract the entire obstacle-detail UI flow (PR #190 by Önder), the upvote/flag toggle behaviour (PR #214), the guest-vs-authenticated button gating (PR #217 by Kılıç), and the own-report detection on the detail screen all read against. Addedselect_related("reporter")to avoid the N+1 the new field would otherwise have caused, and wiredrequestinto the serialiser context so the auth-aware fields aren't alwaysfalse. 5 new tests (ObstacleDetailUserFieldsTest) cover anonymous, own-report, upvoted, flagged, and per-user-isolation cases. - Specification of cross-team features I did not implement myself. Authored Issue #261 (feat(reports): show accessibility standard violations on report detail screen) which Aydemir picked up and shipped as PR #262, and Issue #196 which I then resolved myself via PR #203. The accessibility-standard-violations feature was a non-trivial requirements spec — mapping our obstacle categories onto the W3C / Schema.org / domain accessibility-standards catalogue — and reusable across submit and detail surfaces.
-
Backend surface ownership carried into final milestone. The schema introduced in PR #108 (8 ORM models, 7 enumerations, 22 campus nodes / 44 edges seed) and the
POST /reportspipeline introduced in PR #127 (proximity dedup, trust-score-gated auto-verification, photo upload to Supabase) are the foundations every post-MVP backend feature in §4.1 extends. I continued to be the point person on questions about those surfaces during the final-milestone sprint (schema migrations on the report enum, theis_indoorfield, the dedup distance threshold). - Project presentation & demo lead. Main presenter for the MVP demo and the Final Milestone demo. Owned the architectural narrative for stakeholder presentations — the customer-facing story of how guest browse → community verification → authority resolution → citizen-confirmed closure traces end-to-end through the deployed system, and how the routing engine consumes only verified outdoor obstacles. Coordinated with Aydemir on the Final Demo Plan structure (scenarios A–F) and led the live walkthrough segments.
- Lab 9 documentation (Issues #206, #207). Authored the Example Acceptance Tests and Individual Contributions sections of the Lab 9 Report (Requirements Review & Acceptance Testing), which fed directly into the §4.2 status table in this document.
-
Final-milestone UI direction (
feat/ui-redesignbranch, commit068d06f— feat(ui): civic topographic palette, Fraunces titles, ink CTAs). Drove the visual-identity refresh used in the Final Milestone demo: a civic, topographic colour palette with Fraunces title type and ink-on-paper CTAs. The branch is stand-alone, not blocking the v1.0.0 tag, and was used to harden the demo presentation rather than shipped to main.
-
Obstacle-detail user-state contract (PR #203, Issue #196). Extended
-
Significant Issues (Top 3 per category):
-
Code-Related:
-
#196 — Extend
/api/map/obstacles/{id}withuserUpvoted,userFlagged,reporterId(priority: high, backend). Specced and resolved myself in PR #203; unblocked the obstacle-detail UI on both web and native. - #261 — Show accessibility standard violations on report detail screen (backend + frontend). Specced; picked up and implemented by Aydemir as PR #262. The catalogue from this issue is what §4.5 (WCAG / Schema.org standards) cites as evidence.
-
#124 —
POST /reports— Obstacle Report Submission (backend). Specced and authored the pipeline (PR #127); every post-MVP report-lifecycle feature reads or writes the rows this pipeline produces.
-
#196 — Extend
-
Non-Code-Related:
- #207 — Lab 9 Report — Individual Contributions Section (lab report). Authored; fed §4.1 / §5 of this document.
- #206 — Lab 9 Report — Example Acceptance Tests Section (documentation, lab report). Authored; fed §4.2's Acceptance Test framing.
- Demo coordination & main-presenter role for the Final Milestone demo (not tracked as a single issue, see Final Demo Plan wiki). Owned the live walkthrough script and the architectural narrative used in the stakeholder presentation.
-
Code-Related:
-
Pull Requests:
-
#203 — feat(map): add
reporterId,userUpvoted,userFlaggedto obstacle detail. Extends the existing serialiser with three auth-aware fields, addsselect_related("reporter")for the N+1 risk, and ships 5 new isolation tests. Reviewed and merged cleanly; no merge-conflict resolution required. - Pre-final-milestone PRs that are still load-bearing in the deployed final release (listed for traceability — not counted as final-milestone contributions per the §5 scope rule): #108 (DB schema & campus seed, closes #79), #127 (POST /reports, closes #124), #145 / #146 / #151 (Railway deployment configuration). These ship in v1.0.0 unchanged except for additive migrations that other teammates authored on top of them.
Conflict resolution: PR #203 landed during the post-MVP sprint while several other backend PRs were also editing
apps/map/serializers.py(#220, #214, #257). I rebased onto main once before merge and resolved the serialiser-context plumbing against the concurrent flag-toggle work; the consistent squash-merge workflow plus the 48-hour pre-deadline merge freeze kept this from compounding. -
#203 — feat(map): add
-
AI Transparency & Documentation:
-
Tool summary:
-
Claude Code (Anthropic) — primary in-repository coding assistant. Used to: implement the auth-aware serialiser-context plumbing and the 5 isolation tests for PR #203; iterate on the civic-topographic UI palette and the Fraunces / ink-CTA tokens on the
feat/ui-redesignbranch; draft this very §5 subsection (Akkaya, Ali) from public PR / Issue evidence; and audit cross-team backend PR contracts before review. Operated as a tight loop: describe the target → implement → run pytest / lints → revise on failures. - ChatGPT (OpenAI) — used for design-side thinking and presenter prep. Walking through the architectural narrative for the MVP and Final Milestone demos (how the lifecycle traces end-to-end, what to foreground for non-technical stakeholders), drafting talking points for the customer / TA Q&A, and stress-testing requirement / spec language before opening backend issues (#196, #261).
-
Claude Code (Anthropic) — primary in-repository coding assistant. Used to: implement the auth-aware serialiser-context plumbing and the 5 isolation tests for PR #203; iterate on the civic-topographic UI palette and the Fraunces / ink-CTA tokens on the
-
Prompts: representative prompts from this milestone include:
- "Extend
ObstacleDetailSerializerwithreporterId,userUpvoted,userFlagged. The auth-aware fields must read fromrequest.userin the serializer context — without that they will always befalse. Add tests for anonymous, own-report, upvoted, flagged, and per-user-isolation cases. Avoid an N+1 on the reporter lookup." - "Draft a backend GitHub issue (priority: high, backend label) to extend
/api/map/obstacles/{id}with the three user-interaction fields above. Include explicit acceptance criteria and a scoped 'definition of done' so it's independently pickable." - "Help me design the demo narrative for the Final Milestone. The audience is a non-technical customer plus the TA. I want to walk the end-to-end lifecycle on web and Android in 8 minutes — guest browse → register → submit report → community upvote → authority resolve → citizen-confirmed close — and surface the trust-score and notification side effects in passing. Suggest a scene-by-scene script with the role split between the web operator and the mobile operator."
- "Audit this Final-Milestone wiki page's §4.5 (Utilized Standards) against the §3.1.2 compliance row and the public Use-of-Standards page. Flag any standard claimed in one place but missing evidence in another."
- "Extend
- A consolidated prompts log lives on the Wiki under the team's prompt archive — to be linked here once the team's central prompts page is consolidated.
-
Tool summary:
-
Individual Testing Efforts:
-
ObstacleDetailUserFieldsTest(PR #203,backend/apps/map/tests.py) — 5 new tests covering: (a) anonymous GET returns bothuserUpvoted/userFlaggedasfalseandreporterIdcorrectly set; (b) authenticated GET reflects the requesting user's own upvote; (c) authenticated GET reflects the requesting user's own flag; (d) own-report detection (thereporterIdmatchesrequest.user.id); (e) per-user isolation — one user's upvote does not leak into another user's response. Fullpytest apps/map/tests.py -v(46 tests = 41 existing + 5 new) green on the PR. -
Regression-baseline maintenance on owned surfaces. The schema (PR #108) and
POST /reportspipeline (PR #127) tests I authored pre-MVP continued to gate every post-MVP backend change that touched the reports table — proximity dedup, trust-score-gated auto-verification, theUNVERIFIEDinitial-status revert in PR #243, the auto-decay command in PR #218, and the off-by-one threshold fix in PR #274 were all run against this baseline before merge.
-
-
Additional Information:
- Main presenter, whole project. Across both the MVP demo and the Final Milestone demo I have been the lead presenter — owning the architectural narrative for stakeholder presentations and the live walkthrough script. The §3.1.1 Project Status Summary prose in this document reflects the framing I used in those presentations: a deployed end-to-end lifecycle, two consciously-scoped deferrals (admin UI surface, account-level spam detection), and an honest partial-status list rather than a glossy "all green" claim.
-
Architectural ownership of the data layer. Beyond the PRs themselves, I am the point person on backend-schema questions during the sprint — migration ordering, the
is_indoorboolean's placement, the report-enum transitions, and the campus-graph seed shape. This continued through the final-milestone sprint even though the new merged PR count from me is small: most of the post-MVP feature PRs by Evren, Kemeç, and Delier extend the schema I authored. - Lab Report 8 review (peer reviewer). Reviewed the team's Lab 8 deliverables (Project Retrospective + Use of Standards) against the actual codebase before they were finalised, to ensure standards claims and the retrospective's process-improvement commitments matched what we'd shipped.
-
Responsibilities: Owner of the React Native / Expo frontend and mobile codebase. In the final milestone my responsibility expanded from feature ownership (Report Obstacle, Mobility Profile, route planning integration during MVP) to two new areas:
- Authority-facing frontend. End-to-end ownership of the Infrastructure Authority dashboard UI — the surface the Authority role uses to triage, resolve, and validate reports.
- Frontend QA infrastructure. Stood up the project's first dedicated end-to-end test suite (Playwright) and wired it into CI, closing the E2E gap explicitly flagged as a milestone risk in D6 §D6.4.
In parallel I continued contributing to design and requirements work (UML refinement, SRS revisions for new flows), to sprint planning (opening scoped issues for the team's post-MVP work), and to project-level documentation (the wiki template that the team is filling in right now).
-
Main Contributions:
- Authority Dashboard UI (PR #229, Issue #181). Built the dedicated dashboard surface for the Infrastructure Authority role: filterable report queue, report-detail flow with the "Mark as Resolved – Awaiting Validation" action, required post-repair photo upload, and the official repair-note field. Covers SRS 1.1.7.1 – 1.1.7.5.
-
Playwright E2E smoke test suite (PR #279, Issue #178). Added the project's first end-to-end suite (
frontend/e2e/) covering core user flows — guest browse, register, login, submit report, view report detail — and wired it into the CI pipeline gated byE2E_*_URLrepo variables. -
Unverified marker rendering + auto-verify revert (PR #243, Issue #235). Rendered
UNVERIFIEDreports on the map with a hollow / dashed style and reverted the MVP-era auto-verify shortcut so new reports are submitted with the correct initial status (SRS 1.2.1.3, 1.2.3.1). - Verification & resolution progress indicators (PR #246, Issue #240). Added the progress UI showing how close a report is to the upvote-verification threshold and to the resolution-confirmation threshold, making the trust-score / community-gating logic visible to users.
- Accessibility standard violation chips (PR #262, Issue #261). Wired the W3C / domain accessibility standards catalog into the report submit and detail flows: reports now surface which standards an obstacle violates.
- Saved-place tap-to-focus + precision fixes (PR #256, PR #245). Made saved places (Home / Work) tappable on the profile to focus directly on the map, increased coordinate precision so saved places match map state, and surfaced real save errors instead of swallowing them.
-
Mobility profile API prefix fix (PR #244, Issue #231). Fixed silent 404s on mobility-profile requests caused by the missing
/api/prefix — a cross-team integration bug that had been swallowed. - Profile UI cleanup (PR #254) and Notifications / max-slope input fixes (PR #270). Removed the unused ACTIVE pill and stub Badges card based on role, fixed a duplicate Notifications heading, and fixed the max-slope-gradient input in the mobility profile form.
-
Final Milestone Deliverables wiki template. Drafted the full structure of this document (every section / subsection per the official template) with explicit English
[TODO]markers so the team could fill the remaining slots in parallel. - Sprint planning post-MVP (Issues #170, #180, #182, #185, #186). Translated customer / TA feedback from the MVP demo into scoped, independently pickable issues that drove the team's first post-MVP sprint.
-
Significant Issues (Top 3 per category):
-
Code-Related:
- #235 — Show UNVERIFIED reports on the map (hollow + dashed) and submit reports as UNVERIFIED by default. Implemented as PR #243; reverted the MVP-era auto-verify shortcut and brought report lifecycle rendering in line with SRS 1.2.1.3 and 1.2.3.1.
- #181 — Authority dashboard UI. Implemented as PR #229; net new surface for the Authority role and a hard prerequisite for the Authority demo segment.
- #261 — Accessibility standard violation chips. Implemented as PR #262; surfaces the standards catalog (1.2.x.x family) in the report flows.
-
Non-Code-Related:
- Final Milestone Deliverables wiki template (this document). Authored the full template structure replacing the half-Turkish placeholders and split Section 5 into one editable subsection per team member, so all seven teammates could fill their sections in parallel without coordination overhead.
- #225 — Final Demo Plan organisation. Collaborated on structuring the scripted demo flow (scenarios A–F, role assignments, pre-seeded demo data strategy) on the Final Demo Plan wiki page.
- Lab 8 documentation peer review. Peer-reviewed the team's Lab 8 wiki deliverables — Project Retrospective and Use of Standards — to ensure they accurately reflected the team's actual progress, architectural decisions, and roadmap before the documents were finalised.
-
Code-Related:
-
Pull Requests:
-
#279 —
test(e2e): Playwright smoke test suite [QA]. New E2E suite for core flows, gated in CI. -
#270 —
fix(frontend): remove duplicate Notifications heading and max slope gradient input. -
#262 —
feat(reports): accessibility standard violation chips on submit and detail. -
#256 —
feat(frontend): tap a saved place on profile to focus it on the map. -
#254 —
refactor(frontend): drop ACTIVE pill and stub Badges card from profile. -
#246 —
feat: show progress toward verification and resolution. -
#245 —
fix(places): accept high-precision lat/lng + surface real save errors + UX polish. -
#244 —
fix(frontend): prefix mobility profile requests with /api/. Cross-team integration fix. -
#243 —
feat: show UNVERIFIED reports on the map (hollow + dashed) and submit reports as UNVERIFIED by default. -
#229 —
feat(authority): dashboard UI for infrastructure authority role.
Conflict resolution: none of the above required non-trivial merge-conflict resolution. The merge-freeze policy in the final 48 hours and the consistent squash-merge workflow on
mainkept the branch history clean and rebase-friendly. -
#279 —
-
AI Transparency & Documentation:
I used two AI tools in clearly separated roles across this milestone — Gemini for the what (specification, design, planning) and Claude Code for the how (implementation, refactoring, testing). The split was intentional: Gemini is well-suited to long-form, requirement-shaped thinking (translating customer Q&A into structured requirement IDs, iterating on UML diagrams, sanity-checking scenario coverage against use cases), and Claude Code is well-suited to running directly inside the repository and producing working code that compiles, passes tests, and respects existing patterns. Gemini also frequently sat upstream of Claude Code: when I had a coding intent that was still vague (e.g. "I want to display verification progress on the map and on the report detail screen, in a way that doesn't conflict with the existing trust-score UI"), I would describe it to Gemini in conversational form, have it produce a precise, well-scoped prompt with the relevant files, constraints, and acceptance criteria, and then hand that prompt to Claude Code for execution.
-
Tool summary:
-
Gemini (Google) — design, requirements, planning, prompt generation. Used primarily during the design and specification phases throughout the semester, and continuously during the final milestone for: (a) drafting and refining the SRS requirement hierarchy (
1.x.xnumbering) and translating customer-meeting transcripts and TA feedback into structured requirements; (b) iterating on UML diagrams — Class Diagram alignment between frontend models and the Django ORM, Sequence Diagram for the obstacle reporting flow, Use Case Diagram for the Municipality Resolution scenario; (c) scoping post-MVP sprint issues (acceptance criteria, dependencies, effort estimates) before opening them on GitHub; and (d) acting as a "prompt generator" upstream of Claude Code — turning a conversational coding intent into a precise, file-scoped, constraint-aware prompt. Conversation archive: gemini.google.com/app/a857719f084f36e8. -
Claude Code (Anthropic) — implementation, refactoring, testing, debugging. Used as the primary in-editor coding assistant: scaffolded the Playwright E2E suite (PR #279) including the page-object pattern and CI config; implemented the Authority Dashboard UI (PR #229) and the verification/resolution progress indicators (PR #246); diagnosed the silent
/api/prefix bug on mobility-profile requests (PR #244); refactored the saved-place coordinate handling for high-precision lat/lng (PR #245); and drafted the structural skeleton of this very Final Milestone Deliverables wiki page. Operated as an iterative loop: receive a Gemini-shaped prompt → implement → run lints/tests → revise based on failures.
-
Gemini (Google) — design, requirements, planning, prompt generation. Used primarily during the design and specification phases throughout the semester, and continuously during the final milestone for: (a) drafting and refining the SRS requirement hierarchy (
- Prompts: Gemini conversation archive (covers requirements, UML iteration, and prompt-generation sessions for Claude): gemini.google.com/app/a857719f084f36e8. Claude Code sessions are not centrally archived as a single transcript; the workflow and concrete usage points are described above and each PR's commit history reflects the resulting changes.
-
Tool summary:
-
Individual Testing Efforts:
-
Playwright E2E smoke suite — new this milestone.
frontend/e2e/introduced in PR #279 (Issue #178). Covers guest map browse, register, login, submit report, and report-detail flows; runs in CI gated byE2E_*_URLrepo variables andMOCK=trueuntil backend test-mode is finalised. -
Frontend Jest component / hook / API tests — carried and extended from MVP. I authored the original suites for
MobilityProfileCard(244 lines),ReportForm(120 lines),ReportSuccessScreen(77 lines),mobilityProfileApi(132 lines),useLocation(73 lines), and the reports API client (84 lines) during MVP (documented in D6 §D6.4). These suites continued to gate frontend regressions in the final milestone — the duplicate Notifications heading and max-slope-input bugs (PR #270) were caught against this baseline. -
Manual / contract testing on cross-team integration fixes. The
/api/prefix fix (PR #244) and the saved-place precision fix (PR #245) were both validated end-to-end against the deployed backend before merge to ensure no other endpoints had silent contract drift.
-
Playwright E2E smoke suite — new this milestone.
-
Additional Information:
- Team leadership across design, role assignments, and demo flow decisions (whole project). Across the full semester I generally took the lead on design-side decisions — driving the requirements-elicitation discussions, owning the structural choices on the UML diagrams (Class Diagram alignment, Sequence Diagram for the report flow, Use Case Diagram for the Municipality Resolution scenario), and proposing the frontend/backend/mobile sub-team split and the per-feature role assignments that the team adopted. I played the same role for both the MVP demo (defining scenarios, scripted user journey, pre-seeded data strategy) and the Final Milestone demo flow (scenarios A–F, role split between web/mobile operators, presenter assignments). When a project-level decision needed to be made — what to descope, which routing approach to commit to, what the resolution model should look like, how to organize the demo — I typically opened the discussion, framed the trade-offs, and drove the team toward a concrete decision.
-
Final Milestone Deliverables template authorship. I authored the structural skeleton of this wiki page — replacing the half-Turkish placeholder content with the full English template, splitting Section 5 into one editable subsection per team member sorted alphabetically by surname, and tagging every empty slot with an explicit
[TODO]marker so the team could fill remaining sections in parallel without coordination overhead. The push history on the wiki repo shows this as the initial "full template" commit and the subsequent fill-in commits. - Post-MVP planning ownership. Lab 8 documented this in detail: I synthesised TA and customer feedback from the MVP demo into the team's revised plan and opened five scoped issues (#170, #180, #182, #185, #186) that defined the first post-MVP sprint backlog.
- Continuity with MVP responsibilities. The Test Plan & Coverage wiki, the Mobility Profile feature, the Report Obstacle flow, and the route-planning integration that I owned during MVP all remained under my maintenance in the final milestone; the new PRs above are extensions or corrections of those areas, not net-new ownership.
-
Responsibilities: Backend developer responsible for the authentication foundation, mobility profile API, routing engine (OSRM phase), campus location search, and backend bug triage and critical fixes in the final milestone. Shared ownership of the RBAC permission layer and the core report submission pipeline with other backend contributors.
-
Main Contributions:
- Implemented the user registration endpoint with bcrypt password hashing and the User model (PR #97).
- Built the GET/POST/PUT
/users/me/mobility-profileendpoints and serializers, both in the MVP phase (PR #144) and revised for the final milestone (PR #227). - Implemented campus location search and migrated the routing engine from a custom Dijkstra implementation to the OSRM pedestrian API (PR #129).
- Triaged and fixed a cluster of critical pre-release backend bugs:
indoor obstacle visibility logic, admin permission security gap, and
removal of the redundant
interactionsapp (PRs #266, #267, #268, Issues #263, #264, #265). - Fixed
NotificationSerializerto emit camelCase keys, resolving a frontend crash (PR #224, Issue #223). - Implemented the Dijkstra-based accessibility-aware routing engine using user mobility preferences in the early project phase (PR #122).
-
Significant Issues (Top 3 per category):
-
Code-Related:
- #263 / #264 / #265 — Fixed indoor visibility logic, secured admin permissions, and removed the redundant interactions app (PRs #266, #267, #268). These were critical pre-release blockers: the indoor visibility bug caused indoor markers to appear at all zoom levels contrary to SRS 1.2.1.2, the admin permission gap allowed non-admin roles to reach privileged endpoints, and the redundant interactions app introduced conflicting URL namespaces.
- #143 — Mobility profile endpoints (PRs #144, #227). The foundational user-preference API that the frontend mobility profile feature and the routing engine both depend on for preference propagation. Delivered across two milestones with the final-milestone revision aligning the serializer with the updated field contract.
- #223 — NotificationSerializer camelCase alias fix (PR #224). Resolved a frontend crash caused by snake_case keys reaching the React Native client; a cross-team integration fix with immediate visible impact on the notification tab.
-
Non-Code-Related:
- Backend sub-team coordination on routing engine choice. Actively participated in the OSRM-first → Valhalla routing-engine discussion that is documented in §3.1.6 as one of the semester's costliest pivots. The OSRM integration (PR #129) was the team's first working pedestrian-routing implementation and established the API contract that the later Valhalla migration (PRs #138, #250) preserved without breaking the frontend or mobile clients.
- Requirements and SRS alignment for mobility profile. Collaborated on translating customer and TA feedback on user accessibility preferences into the SRS mobility-profile requirement set (1.1.2.1–1.1.2.3) and ensured the backend serializer fields matched the agreed schema before frontend integration began, preventing the kind of endpoint-contract mismatch that caused extra rework in the first half of the semester.
-
Cross-sub-team integration support for mobility profile and
notifications. Acted as the primary backend contact for the
frontend team during the mobility-profile and notification integration
phases — clarifying endpoint contracts, diagnosing the camelCase
serializer mismatch (Issue #223),
and verifying end-to-end that the
/api/prefix fix (PR #244) resolved the silent 404s on mobility-profile requests after the frontend was already in testing.
-
Code-Related:
-
Pull Requests:
-
#268 —
Fix/backend critical bugs— fixed indoor visibility logic, secured admin permissions, removed redundant interactions app. Final of three staged PRs in the critical-bug cluster; merged after confirming all three fixes passed the backend test suite together. -
#267 —
Fix/backend bugfixes— second staged PR in the same critical-bug cluster; isolated to admin permission hardening, ensuring non-admin roles receive 403 on privileged endpoints (SRS NFR-5.3). -
#266 —
Fix/backend bugfixes— first staged PR in the critical-bug cluster; isolated to indoor visibility logic, ensuring indoor markers are filtered below the High-Detail zoom threshold (SRS 1.2.1.2). -
#227 —
feat(users): implement GET/POST/PUT /users/me/mobility-profile endpoint— final-milestone revision: updated serializer fields and aligned the response shape with the routing engine's preference-propagation contract and the frontend's expected camelCase keys. -
#224 —
fix(notifications): alias serializer fields to camelCase for frontend— aliased allNotificationSerializerfields to camelCase, resolving the React Native crash on the notifications tab caused by snake_case keys in the API response. -
#144 —
feat(users): implement GET/POST/PUT /users/me/mobility-profile endpoint— initial MVP-phase implementation including theMobilityProfilemodel, all three HTTP verbs, and the initial serializer covering mobility aid type and accessibility preferences. -
#129 —
feat: add campus location search and switch routing to OSRM— replaced the custom Dijkstra engine with the OSRM pedestrian API for real-world street-network routing, and added text-based campus location search backed by a geocoding integration. -
#122 —
Routing logic and some minor cleanup— the project's first working routing implementation: a Dijkstra-based engine that consumed user mobility preferences (avoidStairs,avoidSteepSlopes,maxSlopeGradient) to compute accessibility-aware paths. -
#97 —
feat(auth): implement user registration endpoint with bcrypt hashing— implemented theUsermodel, registration serializer, and thePOST /api/auth/register/endpoint with BCrypt password hashing; the authentication foundation every subsequent role-gated endpoint builds on. -
#71 —
feat: add omerbelemir API button with JSONPlaceholder integration— Lab 5 stub-app task; fetches and displays posts from the JSONPlaceholder API via a personalized landing-page button.
-
#268 —
-
AI Transparency & Documentation:
-
Tool summary:
- ChatGPT (OpenAI): Used for design-level reasoning and brainstorming — evaluating trade-offs between Dijkstra and OSRM for pedestrian routing, drafting the initial mobility-profile field schema before aligning it with the SRS, and exploring Django serializer patterns for camelCase aliasing. Served as a sounding board for architectural decisions before committing to an implementation approach.
- GitHub Copilot: Used as an in-editor autocomplete assistant during implementation — completing repetitive serializer field declarations, Django model boilerplate, and test fixture setup in the mobility-profile and critical-bug-fix PRs. All suggestions were reviewed and adjusted to match the project's existing patterns and naming conventions before committing.
-
Prompts (representative):
- "I am building a Django REST Framework endpoint for a user mobility profile. The profile should store mobility aid type (wheelchair, cane, none, etc.), whether the user wants to avoid stairs, avoid steep slopes, and a max slope gradient float. What model fields and serializer structure would you recommend, and how should I handle the PUT vs POST distinction on a singleton sub-resource?"
- "My Django serializer is returning snake_case field names but my React Native frontend expects camelCase. What is the cleanest way to alias all fields in a DRF ModelSerializer to camelCase without renaming the underlying model fields?"
- "I have an indoor obstacle visibility bug: indoor markers are
rendering at all zoom levels instead of only above a High-Detail
threshold. The threshold logic lives in the serializer's
to_representationmethod. How should I structure a zoom-level filter in DRF when the zoom level is passed as a query parameter?" - "What are the trade-offs between using OSRM and Valhalla for pedestrian routing when I need to pass a list of obstacle coordinates to exclude from the route? Which engine has better native support for this use case?"
-
Tool summary:
-
Individual Testing Efforts:
-
Mobility profile endpoint tests —
backend/apps/users/tests.py(PRs #144, #227). Authored tests covering the full GET/POST/PUT lifecycle for the mobility profile sub-resource: unauthenticated access returns 401, POST creates a profile with valid fields, PUT updates individual preference flags, and the response shape matches the camelCase contract expected by the frontend. These tests caught a field-naming regression when the serializer was revised for the final milestone. -
Indoor visibility fix tests —
(PR #266).
Added assertion that obstacle list endpoints filter out indoor markers
when the
zoomquery parameter is below the High-Detail threshold, and return them when zoom meets or exceeds it — directly pinning the corrected logic against SRS 1.2.1.2 to prevent future regression. -
Admin permission tests —
(PR #267).
Added permission-boundary tests asserting that authenticated users
with the
USERandAUTHORITYroles receive403 Forbiddenon admin-only endpoints (flag-queue, report deletion, account suspension), and that only theADMINrole receives200, in line with SRS NFR-5.3 (role-based access control). -
NotificationSerializer contract test —
(PR #224).
Added a serializer unit test asserting that all output keys are
camelCase (
notificationType,relatedReport,createdAt,isRead) to prevent the snake_case regression from being reintroduced silently in a future serializer change.
-
Mobility profile endpoint tests —
-
Additional Information:
- Pre-MVP authentication foundation. The registration endpoint and User model (PR #97) underpin every authenticated flow in the system. Although delivered early in the semester, this work was a hard prerequisite for the JWT auth layer (PR #94), the RBAC permission classes (PR #95), and all subsequent role-gated endpoints built by the rest of the backend team.
-
Routing engine continuity. The Dijkstra engine
(PR #122)
and the OSRM migration
(PR #129)
established the routing service's API shape and the accessibility-
preference propagation pattern —
avoidStairs,avoidSteepSlopes,maxSlopeGradient— that the final Valhalla-based engine (PRs #138, #250) preserved without requiring frontend or mobile changes. Ömer's early routing work therefore directly shaped the architecture of the feature that became the product's primary value proposition. - Critical-bug ownership at release. The three-PR bug-fix cluster (#266, #267, #268) landed in the final days before the release tag and addressed issues that would have been directly visible during the demo (indoor markers at all zoom levels) or constituted a security regression (admin endpoint exposure to non-admin roles). Identifying, isolating into reviewable PRs, and resolving all three before the 48-hour merge freeze was a meaningful contribution to release readiness and demo stability.
- Responsibilities: [TODO]
- Main Contributions: [TODO]
-
Significant Issues (Top 3 per category):
-
Code-Related:
- [#TODO] – [brief explanation]
- [#TODO] – [brief explanation]
- [#TODO] – [brief explanation]
-
Non-Code-Related:
- [#TODO] – [brief explanation]
- [#TODO] – [brief explanation]
- [#TODO] – [brief explanation]
-
Code-Related:
-
Pull Requests:
- [#PR – TODO] – [description] – [conflict resolution, if applicable]
- [#PR – TODO] – [description]
-
AI Transparency & Documentation:
-
Tool summary:
- [TODO – Tool 1]: [functional role]
- [TODO – Tool 2]: [functional role]
- Prompts: [TODO – link to prompts log]
-
Tool summary:
-
Individual Testing Efforts:
- [Test name, commit #TODO] – [brief explanation]
- [Test name, commit #TODO] – [brief explanation]
- Additional Information: [TODO]
-
Responsibilities: Map & routing infrastructure (web and mobile), obstacle interaction system, indoor report form, notification system, report discussion section, saved places, and frontend performance optimisations.
-
Main Contributions: Built the core map view and route-planning screens for both web (Leaflet) and mobile (WebView + Leaflet), then progressively enriched them with obstacle interactions (upvote / flag / confirm-resolution), indoor-specific form fields with auto-geocoding, a comments/discussion section on report detail, a saved-places flow, an in-app notification list, and a series of performance fixes (debounced bounds fetch, icon caching, stale-while- revalidate obstacle refresh). Also contributed backend work: Comment model
- GET/POST endpoint, routing serialiser unit tests, and Valhalla exclude_locations integration.
-
Significant Issues (Top 3 per category):
-
Code-Related:
- #190 – Obstacle interactions: implemented InteractionBar (upvote/flag with optimistic updates), ConfirmResolutionButton with eligibility check, obstacle detail screen, and web/native navigation to that screen.
- #192 – Indoor form fields: added buildingName/floor/isIndoor to the report payload, auto-filled building name via reverse geocoding, context-specific indoor obstacle categories, a distinct indoor marker icon, and cleaned up timer refs on unmount.
- #138 – Routing engine migration: replaced the existing OSRM-based hacky rerouting logic with Valhalla exclude_locations integration, enabling proper obstacle-aware route planning; also reduced obstacle cache TTL for faster report visibility.
-
Non-Code-Related:
- Meeting Moderation & Documentation – Facilitated weekly synchronization meetings between the frontend and backend sub-teams, and consistently documented comprehensive meeting notes to maintain team alignment throughout the milestone.
-
Routing Engine Research – Conducted research on spatial routing engines, specifically evaluating Valhalla's
exclude_locationscapabilities to replace geometric waypoint offsetting for robust, road-following obstacle avoidance. - Project Management & Issue Tracking – Actively maintained the repository's GitHub issue board by defining, organizing, and tracking milestone tasks related to map overlays, notification systems, and user interaction mechanics.
-
Code-Related:
-
Pull Requests:
- #112 – Initial web map view and route-planning screen (Leaflet); merged after multiple package-lock conflict resolutions with main.
- #117 – Mobile map and route-planning screens via WebView + Leaflet; fixed re-render loop causing map flicker and loading-bar resize jitter.
- #190 – Obstacle interactions feature (InteractionBar, detail screen, upvote/flag API, ConfirmResolutionButton); reconciled server upvote count after optimistic update.
- #192 – Indoor form fields (geocoding, categories, marker icon, tests); resolved merge conflict with main (HIGH_DETAIL_ZOOM + useRouter changes).
- #242 – Report discussion section (Comment model, GET/POST endpoint, redesigned detail screen, status history); fixed status-history reason parsing and photo display regression.
- #212 – Notifications tab and in-app notification list with profile toggle; added unit tests for NotificationsScreen.
- #211 – Saved places: profile screen, map quick-select, SavePlaceModal; surfaced save errors and added modal unit tests.
- #210 – Route summary panel added to MapView (native and web).
- #230 – Ensured route response fields; added 4 km/h fallback for estimatedTime and serialiser unit tests.
- #222 – Passive obstacle toggle added to map view.
- #214 – Toggle behaviour for upvote and flag interactions; fixed showAlert recursion on native.
- #149 – Choose-on-map location picker integrated into report form.
- #138 – Replaced OSRM hacky rerouting with Valhalla exclude_locations; reduced obstacle cache TTL for faster report visibility.
- #133 – Aligned frontend map API with backend response format; added obstacle prefetch on mount before map initialises.
- #252 – Map performance: debounced bounds fetch, cached icons, fixed popup flash on back-navigation, accumulated obstacles across fetches, deferred state updates to eliminate zoom-out marker glitch.
- #260 – Collapsed route inputs into compact bar once route is calculated.
- #276 – Stale-while-revalidate refresh strategy for obstacle layer.
- #277 – Push/in-app notification to reporter when their report is closed.
- #153 – UI aesthetics pass across web and mobile screens; fixed search bar collapse on mobile and enhanced premium map styling.
- #74 – Baran joke button with JokeAPI (Lab 5 stub-app task).
-
AI Transparency & Documentation:
-
Tool summary:
- Claude (claude.ai chat): Used for planning feature implementation steps, understanding unfamiliar APIs (Valhalla, Leaflet), and debugging tricky React Native issues like WebView re-render loops and optimistic update reconciliation.
- Claude Code: Used to scaffold unit test suites — generated initial failing test skeletons for InteractionBar, indoor form fields, and NotificationsScreen which were then reviewed, adjusted, and completed manually before committing.
-
Prompts:
- "I have a React Native component called InteractionBar that handles upvote and flag button taps. Can you write failing Jest unit tests for it? I want tests for: tap triggers API call, button is disabled for guest users, and count updates optimistically."
- "My WebView map is re-rendering on every state change and causing flicker. Here is the component, what is causing it and how do I fix it?"
- "Can you help me write a test for my SavePlaceModal that checks if the error message shows up when the save API call fails?"
- "I am replacing OSRM with Valhalla for routing. OSRM used a hacky waypoint workaround to avoid obstacles. How does Valhalla exclude_locations work and how should I restructure my API call?"
- "I need to add indoor-specific fields to my report form. When the user selects INDOOR context, buildingName and floor fields should appear. How should I structure the conditional rendering and what is the cleanest way to auto-fill buildingName from coordinates using reverse geocoding?"
- "My Jest test is failing because of a missing act() wrapper when testing async state updates in my form component. Here is the error and here is the test, how do I fix it?"
- "I want to implement stale-while-revalidate for my obstacle layer on the map. Right now I fetch fresh data every time bounds change. How can I show cached data immediately and refresh in the background?"
- "Can you write unit tests for my routing serializer? It should always return estimatedTime and if the backend does not provide it, it should fall back to distance divided by 4km/h walking speed."
- "I have a notifications screen that fetches a list from the API and renders it. Write me basic unit tests that check: list renders correctly, empty state shows a message, and loading spinner shows while fetching."
- "My map popup is flashing briefly when the user navigates back to the map screen. I think it is because markers re-mount. Here is my marker rendering logic, what is the best way to fix this?"
-
Tool summary:
-
Individual Testing Efforts:
- InteractionBar unit tests, commit 6991fc8 (#190) – Wrote failing tests for upvote tap, disabled state, and guest-user gating before implementing the component (TDD cycle).
- Indoor form field tests, commits 0180d65 & 282e84c (#192) – Added failing tests for indoor fields, then fixed act() wrapper, clearAllMocks, and auth mock to make them pass.
- NotificationsScreen unit tests, commit 1f1eaef (#212) – Covered notification list rendering and toggle behaviour.
- SavePlaceModal tests, commit a63ac1f (#211) – Validated save-error surfacing and modal interaction.
- Routing serialiser unit tests, commit 20dfbdd (#230) – Verified estimatedTime fallback and correct field serialisation.
-
Additional Information: Worked across both web and mobile platforms simultaneously, maintaining shared Leaflet-based map logic while handling React Native-specific rendering constraints (WebView re-render loops, loading bar jitter, marker flicker) separately — a non-trivial cross-platform balancing act. Contributions were not limited to frontend; backend work included the Comment model with GET/POST endpoints, routing serialiser with estimatedTime fallback, and Valhalla exclude_locations integration. Followed a TDD approach in multiple PRs by writing failing tests before implementing the feature (InteractionBar, indoor form fields, NotificationsScreen). Several contributions were infrastructure-level rather than feature-level — notably the Valhalla routing engine migration away from OSRM and the stale-while-revalidate obstacle refresh strategy — decisions that affected the reliability and correctness of the app as a whole.
-
Release Tag:
final-milestone - Live Deployment: bounswe2026group3-azure.vercel.app
- README Instructions: README.md
- Docker Setup: docker-compose.yml
- Mobile APK: final-milestone release
- Elicitation Questions
- Requirements
- Implementation Plan
- Test Plan & Coverage
- MVP Demo Plan
- Communication Plan
- Responsibility Assignment Matrix
- Use of Standards
- Project Retrospective
- Final Demo Plan
- Final Milestone Deliverables
- Report 1 - Requirements Elicitation & Repository Setup
- Report 2 - SRS Through Scenarios & Mock-ups
- Report 3 - From Scenarios to Use Case Diagrams
- Report 4 - Class Diagrams & Use-case Diagrams
- Report 5 - Git Workflow, Stub Application, and Planning
- Report 6 - Planning for Implementations & Tests
- Report 7 - Finalizing Plan for MVP Milestone Demo
- Report 8 - Standards & Plan Revision
- Report 9 - Requirements Review & Acceptance Testing
- Report 10 - Finalizing Plan for Final Milestone Demo
- 2026-02-18: Weekly Meeting #1
- 2026-02-18: Customer Meeting #1
- 2026-02-25: Stakeholder Meeting
- 2026-02-25: Weekly Meeting #2
- 2026-03-04: Weekly Meeting #3
- 2026-03-11: Weekly Meeting #4
- 2026-04-01: Weekly Meeting #5
- 2026-04-15: Weekly Meeting #6
- 2026-04-22: Weekly Meeting #7
- 2026-04-29: Weekly Meeting #8
- 2026-05-06: Weekly Meeting #9