179 lines
6.2 KiB
Markdown
179 lines
6.2 KiB
Markdown
# CasaDoc — mobile app
|
|
|
|
Mobile client for the CasaDoc property-document platform, for iOS and Android
|
|
from a single codebase.
|
|
|
|
**Stack:** Expo SDK 52 · React Native 0.76 · expo-router · TypeScript ·
|
|
React Query · expo-secure-store · i18n-js.
|
|
|
|
The app can run against the PHP backend or against in-memory demo data; the
|
|
choice is one constant in `src/api/config.ts`.
|
|
|
|
---
|
|
|
|
## Features
|
|
|
|
**Account**
|
|
|
|
- Login with email and password, bearer token kept in SecureStore, auto-login
|
|
on next launch.
|
|
- Registration with e-mail code verification.
|
|
- Password recovery (request a code, set a new password) and password change
|
|
from inside the app.
|
|
- Profile editing, avatar, account deletion.
|
|
- Interface in Italian and English, following the device language, with a
|
|
manual override in the profile.
|
|
|
|
**Properties**
|
|
|
|
- List with cover image, address and document counters.
|
|
- Detail screen with document categories as folders and recent documents.
|
|
- Create and edit, including a map picker for the address (react-native-maps).
|
|
|
|
**Documents**
|
|
|
|
- Per-property list, filtered by category and by status.
|
|
- Search across every document of every property.
|
|
- Expiry tracking: valid, expiring and expired badges, warning banners, and a
|
|
dedicated tab listing everything that needs attention.
|
|
- Detail screen with an inline preview for images and a card that hands PDFs to
|
|
the phone's own viewer; sharing and deletion.
|
|
- Editing of name, category and expiry date.
|
|
|
|
**Adding a document**
|
|
|
|
- From the file picker, from the photo library, or with the built-in scanner.
|
|
- The scanner uses the native document scanner (ML Kit on Android, VisionKit on
|
|
iOS) with edge detection and perspective correction, captures several pages
|
|
and combines them into one PDF (`src/scanner/scanToPdf.ts`).
|
|
|
|
**Offline**
|
|
|
|
- Responses are cached and persisted, so a previously opened screen still shows
|
|
its content without a connection; a banner appears while the device is
|
|
offline and the data refreshes as soon as it is back.
|
|
|
|
---
|
|
|
|
## Getting started
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
The scanner, the maps and the file viewer are native modules, so the app needs
|
|
a development build rather than Expo Go:
|
|
|
|
```bash
|
|
npx expo run:ios # or: npx expo run:android
|
|
npm start # subsequent runs
|
|
```
|
|
|
|
With EAS instead of a local build:
|
|
|
|
```bash
|
|
npx eas build --profile development --platform ios # or android
|
|
```
|
|
|
|
`npm run prebuild` regenerates the native projects (`expo prebuild --clean`);
|
|
`ios/` and `android/` are not kept in the repository because everything native
|
|
is declared by config plugins in `app.json`, and `npm install` applies
|
|
`patches/` through `patch-package`.
|
|
|
|
When the phone is connected over USB, `npm run reverse` forwards the Metro and
|
|
backend ports to it.
|
|
|
|
---
|
|
|
|
## Pointing the app at a backend
|
|
|
|
Everything goes through `src/api/config.ts`:
|
|
|
|
```ts
|
|
export const USE_MOCK = false; // true -> in-memory demo data, no server
|
|
```
|
|
|
|
- `USE_MOCK = true` uses `src/api/mock.ts`: every flow works offline on demo
|
|
data, and any credentials are accepted at login.
|
|
- `USE_MOCK = false` uses `src/api/real.ts`, mapped to the endpoints in
|
|
`openapi.yaml`.
|
|
|
|
The address of the server comes from two places: `DEV_HOST` in the same file
|
|
for development builds, and `expo.extra.apiUrl` in `app.json` for release
|
|
builds. A release build must use `https`, because both platforms block plain
|
|
HTTP traffic outside development.
|
|
|
|
The screens import `api` from `@/api` and never know which of the two is
|
|
active.
|
|
|
|
### How documents map to the backend
|
|
|
|
The screens work with a flat model: a property owns documents, each with a
|
|
category and an optional expiry date. The backend nests the same data one level
|
|
deeper, as page (slug) → section → document requirement → uploaded files.
|
|
`src/api/real.ts` holds that mapping. Reads flatten the structure for display;
|
|
writes stay faithful, because the upload screen has the user pick a real
|
|
requirement and sends its id.
|
|
|
|
Two consequences are worth knowing:
|
|
|
|
- A property's documents are gathered with one request per category page, since
|
|
the endpoint serves a single page at a time. The properties list does not pay
|
|
that cost — it uses the counters `homes.php` returns.
|
|
- There is no endpoint for a single file's metadata, so document screens read
|
|
from the list they were opened from.
|
|
|
|
---
|
|
|
|
## Project structure
|
|
|
|
```
|
|
app/ expo-router routes
|
|
_layout.tsx providers, auth gate
|
|
(auth)/ login, register, verify, forgot, reset
|
|
(tabs)/ properties · search · expiring · profile
|
|
property/[id].tsx property detail
|
|
property/add.tsx new property
|
|
property/edit/[id].tsx edit property
|
|
property/location.tsx map picker for the address
|
|
documents/[propertyId].tsx documents of a property
|
|
document/[id].tsx document detail and viewer
|
|
document/edit/[id].tsx edit a document
|
|
profile/edit.tsx profile
|
|
profile/password.tsx change password
|
|
upload.tsx add a document: file, gallery or scan
|
|
|
|
src/
|
|
api/ config.ts (backend switch), http.ts, types.ts, mock.ts, real.ts
|
|
auth/ AuthContext, token in SecureStore
|
|
i18n/ en.ts, it.ts, locale detection and override
|
|
scanner/ scanToPdf.ts
|
|
theme/ design tokens (colours, spacing, radii, typography)
|
|
components/ ui.tsx, domain.tsx, forms, AppBar, PdfView, OfflineBanner
|
|
lib/ formatting, permissions, files, network, query client
|
|
```
|
|
|
|
---
|
|
|
|
## Scripts
|
|
|
|
| | |
|
|
|---|---|
|
|
| `npm start` | Metro for a development build |
|
|
| `npm run ios` / `npm run android` | build and install on device or simulator |
|
|
| `npm run prebuild` | regenerate `ios/` and `android/` |
|
|
| `npm run typecheck` | TypeScript, no emit |
|
|
| `npm run lint` | ESLint |
|
|
| `npm run reverse` | forward ports 8081 and 8080 to a USB-connected Android device |
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- Design tokens live in `src/theme/tokens.ts` and are the single source for
|
|
colours, spacing, radii and typography. Typography currently maps to the
|
|
system font; loading Space Grotesk and Inter through `expo-font` is a change
|
|
in that one file.
|
|
- Sharing between owners, ownership transfer and reports exist in the backend
|
|
contract but are outside the scope of this app.
|