# Features — datafy_app (Datafy Ai)

Evidence date: 2026-10-18. Source: `git@bitbucket.org:overdrive/datafy_app.git`, `main` at `dba98cc`.

Status words used here: **Current** (present on `main`), **Unrouted** (source exists, not exported by `lib/index.dart`), **Unknown**. Nothing in the repository is labelled planned, in development, or deprecated by a document. Git has no feature branch.

## Current — identity and shell

| Feature | What it does | Where | Provenance |
|---|---|---|---|
| Datafy Ai shell | MaterialApp titled Datafy Ai, path URLs, English and Afrikaans locales | `lib/main.dart`, `lib/flutter_flow/internationalization.dart` | **Implemented** |
| Splash stand-in | While auth is loading, routes paint a bundled background image, then stop after 1 second | `nav.dart` `stopShowingSplashImage` | **Implemented** |
| Version asset | `environment.json` exposes `appVersion` `1.0.38`. Package version is `1.0.54+84` | `assets/environment_values/environment.json`, `pubspec.yaml` | **Implemented**. The two numbers disagree |
| Launcher icon | `flutter_launcher_icons` points at `assets/images/app_launcher_icon.png` for Android, iOS, and web | `pubspec.yaml` | **Implemented** as config. Whether the generated icons match was not visually checked |

## Current — access

| Feature | What it does | Where | Provenance |
|---|---|---|---|
| Email sign-in | Password sign-in, then `app_user` load, role default `Rep` | `lib/pages/includes/auth/login/login_widget.dart` | **Implemented** |
| Mobile-number sign-in | Same `signInWithEmail` API, phone field as the email argument, role not defaulted | same file | **Implemented** |
| Location gate | Blocks Brands until permission is granted and GPS services are on | login widget, `check_gps_status.dart`, `open_location_settings.dart` | **Implemented** |
| Brand picker | Swipeable cards of `customer_user` for this user. Tap stores the customer and brand | `lib/pages/rep/dashboard/brands/` | **Implemented** |
| Sign-out | Profile screens call Supabase sign-out | `profile_new_widget.dart`, `profile_new_admin_widget.dart` | **Implemented** |
| Password reset screen | `lib/pages/login/verify/` calls `resetPassword`. A second verify widget is the one the router exports | both verify widgets | **Implemented** files. Which one users reach is **Unknown / Requires Confirmation** |
| Account creation | `createAccountWithEmail` exists on the unexported `lib/pages/login/login/login_widget.dart` and on `supabase_auth_manager.dart` | those files | **Unrouted** relative to `lib/index.dart` |

`sign_in_with_apple` is in `pubspec.yaml`. The routed login file that was read does not call it. **Unknown** whether another widget does.

## Current — Rep work

Routes are the `routePath` on each widget. Admin twins use the same path with an `Admin` suffix unless noted.

| Feature | Rep route | Notes | Provenance |
|---|---|---|---|
| Dashboard | `/dashboard` | Starts PowerSync and attachments | **Implemented** |
| Stores | `/storePageMain` | Role `Rep` on the nav store icon | **Implemented** |
| Store items | `/storeItems` | | **Implemented** |
| All items | `/allItemsOverview` | Spar twin `/allItemsOverviewSpar` | **Implemented** |
| Category | `/categoryPage` | Spar twin `/categoryPageSpar` | **Implemented** |
| Tasks | `/tasksList`, `/tasksListAll`, `/taskDetails`, `/taskDetailsCategory`, `/taskGallery` | Spar twins `/tasksListSpar`, `/tasksListAllSpar` | **Implemented** |
| Promos | `/promosList`, `/promosStoresList`, `/storePromos`, `/taskDetailsPromo`, `/taskDetailsPromoInstore` | | **Implemented** |
| KaChing | `/kachingList`, `/kachingStoresList`, `/taskDetailsKachinga` | The KaChing detail path ends in `a` (`taskDetailsKachinga`). That spelling is the route string | **Implemented** |
| Surveys | `/formList`, `/surveyQ1` | Custom survey widgets under `lib/custom_code/widgets/` | **Implemented** |
| Profile | `/profileNew` | | **Implemented** |
| Notifications | `/notifications` | Nav shows this only when role is `Rep` | **Implemented** |

Rep nav home icon is also Rep-only (`nav_bar_widget.dart`).

## Current — Admin work

| Feature | Route | Provenance |
|---|---|---|
| Admin dashboard | `/dashboardAdmin` | **Implemented**. Sampled queries use `AppUserTable().queryRows`, not PowerSync |
| Admin stores, items, categories, tasks, promos, KaChing, surveys, profile | `/storePageMainAdmin`, `/storeItemsAdmin`, `/allItemsOverviewAdmin`, `/allItemsOverviewSparAdmin`, `/categoryPageAdmin`, `/categoryPageSparAdmin`, `/tasksListAdmin`, `/tasksListAllAdmin`, `/tasksListSparAdmin`, `/tasksListAllSparAdmin`, `/taskDetailsAdmin`, `/taskDetailsCategoryAdmin`, `/taskGalleryAdmin`, `/storePromosAdmin`, `/taskDetailsPromoAdmin`, `/taskDetailsPromoInstoreAdmin`, `/kachingListAdmin`, `/taskDetailsKachingAdmin`, `/formListAdmin`, `/surveyQ1Admin`, `/profileNewAdmin` | **Implemented** as routed screens |

Admin task update SQL that was read sets `status` only. Rep task update SQL also sets `archived = 1`. See `business-rules.md`.

## Current — offline and media

| Feature | What it does | Where | Provenance |
|---|---|---|---|
| PowerSync | Schema embedded in `main.dart`. URL is a JourneyApps host. `attachments_queue` is `local_only` | `lib/main.dart`, `dependencies/power_sync_b0w5r9` | **Implemented** |
| Connectivity widgets | Rep task lists embed `PowerSyncConnectivityWidget` and `PowerSyncStateUpdaterWidget` | `lib/pages/rep/tasks/` | **Implemented** |
| Offline placeholder | `NotAvailableOfflineYetWidget` exists as a component | `lib/pages/includes/not_available_offline_yet/` | **Implemented** as a widget. Which screens show it was not fully traced |
| Photo capture and upload | `image_picker` and Supabase `uploads` / `profile` buckets, public URL | `pubspec.yaml`, `storage.dart` | **Implemented** |
| PDF export | Product, promo, and KaChing image export actions | `lib/custom_code/actions/export_*` | **Implemented** as actions. Call sites were not all listed |
| WhatsApp share | Web uses a `wa.me` link. Mobile uses the share sheet | `share_to_whats_app.dart` | **Implemented** |
| Task picture helpers | `setTaskPicture`, `resolveTaskPicture`, `setTempImageFromUrl`, `setUpAttachments` | `lib/custom_code/actions/` | **Implemented** |

## Current — platform and engineering

| Feature | What it does | Where | Provenance |
|---|---|---|---|
| Android, iOS, web projects | Standard Flutter folders. No `windows/`, `macos/`, or `linux/` runner was in the top-level tree | repo root | **Implemented** |
| iOS notification extension folder | `ios/ImageNotification/` | that directory | **Implemented** as a target folder. Push provider (APNs payload, Firebase) was not found in Android manifests |
| SonarQube on main | Pipe `sonarsource/sonarqube-scan:2.0.1`. Project key `overdrive_datafy_app_9e753313-caf8-4d55-b614-caad76ec84e1` | `bitbucket-pipelines.yml`, `sonar-project.properties` | **Implemented** |
| Widget test stub | Pumps `MyApp`, asserts nothing | `test/widget_test.dart` | **Implemented** |

## Unrouted source still in the tree

These directories exist under `lib/pages/` and are not exported from `lib/index.dart`:

- `login/` (includes a login widget that can create an account)
- `news/`
- `profile/` (separate from `includes/profile/`)
- `sites/`
- `task/` (separate from `rep/tasks/` and `admin/tasks/`)
- `dashboard/`
- `sub_channel_list_admin/` is imported by `profile_new_admin_widget.dart`, so it is a component, not a route

`sites` and `task` widgets contain hardcoded place names such as "Spar Wellington" and "Spar Paarl". Provenance: **Implemented** strings inside unexported pages. Whether those screens are leftover FlutterFlow pages is **Inferred**.

`lib/pages/rep/tasks/r_f_g_categories/` is a widget that navigates to the Spar category route. It has no `routeName` of its own in the route grep. Provenance: **Implemented** as a called screen or component. Its entry point was not fully mapped.

## Not found in this repository

| Item | Evidence | Status |
|---|---|---|
| Fastlane, Play, or TestFlight deploy | No Fastfile. Pipeline is Sonar only | Absent on `main` |
| Written roadmap or changelog | README is the Flutter stub | Absent |
| Feature flags | Not searched exhaustively. No flag file was seen at the root | **Unknown** |
| Removal of a named feature | Five commits, no message that says a feature was removed | **Unknown** |

## Recently changed

The only application-sized change after the 2024-04-22 `alpha deploy` is `dba98cc` ("latest update", 2026-01-19, 432 files). The commit message does not name a feature. Provenance: **Implemented** as git history. Which screens that commit added is **Unknown** without a file-level review of the diff.

## Relationship to other Datafy docs

`silicon_ark/flutter_app/` describes a later Datafy Ai client (version `1.0.79+100103` on `develop`). Similar screens exist there. This feature list is only what `datafy_app` at `dba98cc` contains. Do not mark a `flutter_app` feature as current here unless this tree has it.

`datafy_web` is a separate Flutter web client against the same Supabase host. It is not this app's `web/` folder.
