Phone App: add Charging screen + Settings integration tabs

Brings the Flutter app to parity with the recent Web App changes, which
touched features the Phone App did not yet have — so this builds the
Charging and Integrations subsystems, then applies the tab/fold structure.

Charging (new nav destination): split into "Public chargers" (stylized
discovery map + demo session + nearby public stations) and "Home chargers"
(the real Anker Solix OCPP control card — serial refresh, connector/energy
tiles, start/stop, current limit, password step-up on reset — plus the
user's home charger list). Gated by the per-user control mode, degrading to
a Settings hint when off.

Settings: split into "Personal settings" (the existing account/appearance/
profile/security/privacy/danger sections) and "Integrations". The latter
holds foldable Toyota and Anker Solix cards over the superadmin -> org ->
user cascade: locked fields with "inherited from" notes, org-admin scope
switch, enable toggle, save/test with health result, and Anker OCPP token
provisioning. Both tabs stay mounted (IndexedStack) so in-flight edits
survive a switch.

Adds the integration + OCPP control endpoints to api.dart, the resolved
IntegrationView/Scope/Field, IntegrationHealth and AnkerControl models, and
charging.*/settings.tabs.*/nav.charging strings (en/pl/da) plus
settings.integrations.* (en) — mirroring the Web App's own pl/da coverage,
which leaves integrations and charger control untranslated as an English
fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
tajniak81
2026-07-19 22:03:52 +02:00
co-authored by Claude Opus 4.8
parent 30c9cdebe9
commit 13f50aa9a4
8 changed files with 2286 additions and 51 deletions
+115
View File
@@ -13,6 +13,7 @@
"nav": {
"garage": "Garage",
"charging": "Charging",
"settings": "Settings",
"users": "Users"
},
@@ -76,9 +77,123 @@
}
},
"charging": {
"eyebrow": "CHARGING & MAP",
"title": "Nearby chargers",
"tabs": {
"public": "Public chargers",
"home": "Home chargers"
},
"liveMap": "Live map",
"youAreHere": "You are here",
"session": {
"chargingNow": "Charging now",
"rate": "Rate",
"added": "Added",
"cost": "Cost",
"done": "Done",
"stop": "Stop charging",
"idle": "Not charging",
"idleHint": "Plug in at a station to start a session."
},
"control": {
"title": "Charger control",
"connected": "Connected",
"disconnected": "Offline",
"serialPlaceholder": "Charger serial (e.g. A5191-XXXXXXXX)",
"refresh": "Refresh",
"status": "Connector",
"meter": "Energy",
"start": "Start charging",
"stop": "Stop charging",
"limit": "Current limit",
"applyLimit": "Apply limit",
"clearLimit": "Clear limit",
"reset": "Reset charger",
"resetConfirm": "Reboot this charger now? Any active charging session will be interrupted. Re-enter your password to confirm.",
"resetPassword": "Your account password",
"connectHint": "Enter your charger's serial and refresh. The charger must be connected to DriverVault's OCPP backend (set up in Settings → Integrations)."
},
"stations": {
"heading": "Nearby",
"homeHeading": "Your chargers",
"noControlHint": "Turn on Own or Proxy CSMS in Settings → Integrations to control your home charger here.",
"count": {
"one": "{n} station",
"other": "{n} stations"
},
"free": "{avail} of {total} free",
"full": "Full",
"offPeak": "off-peak",
"homeCharger": "Home charger"
}
},
"settings": {
"title": "Settings",
"tabs": {
"personal": "Personal settings",
"integrations": "Integrations"
},
"integrations": {
"title": "Integrations",
"subtitle": "Connect external services to your account.",
"toyota": "Toyota Connected (MyToyota)",
"toyotaDesc": "Sign in with your MyToyota account to pull vehicle data from Toyota Connected Europe. Europe only.",
"enable": "Enable for my account",
"enableOrg": "Enable for the organization",
"unavailable": "This integration is turned off by the administrator.",
"orgDisabled": "This integration is turned off for your organization.",
"scopeMy": "My settings",
"scopeOrg": "Organization",
"scopeHint": "Organization settings apply to everyone in your organization who leaves a field blank.",
"readOnly": "You manage this integration's shared settings in the API Server panel; here it is read-only.",
"email": "MyToyota email",
"password": "MyToyota password",
"brand": "Brand",
"brandToyota": "Toyota",
"brandLexus": "Lexus",
"inherited": "Set above your level",
"inheritedFrom": "Inherited from {source}",
"sourceGlobal": "the administrator",
"sourceOrg": "your organization",
"sourceUser": "you",
"passwordKeep": "Leave blank to keep the saved password.",
"test": "Test connection",
"testing": "Testing…",
"save": "Save",
"saved": "Saved ✓",
"connected": "Connected",
"notConnected": "Not connected",
"ankerSolix": "Anker Solix (V1 Smart EV Charger)",
"ankerSolixDesc": "Sign in with your Anker account to pull EV charger data from the Anker Solix cloud.",
"ankerEmail": "Anker account email",
"ankerPassword": "Anker account password",
"country": "Country",
"countryHint": "Two-letter country code of your Anker account (e.g. DE, GB, US).",
"controlMode": "Control mode",
"controlModeHint": "How DriverVault controls the charger over OCPP.",
"controlOff": "Off (monitoring only)",
"controlOwn": "Own CSMS (full control)",
"controlProxy": "Proxy CSMS (relay + control)",
"controlTitle": "Charger control (OCPP)",
"controlOwnHint": "The charger connects directly to DriverVault as its Central System. Point the charger's OCPP backend at the endpoint below.",
"controlProxyHint": "DriverVault relays to Anker's cloud and can inject commands. Point the charger's OCPP backend at the endpoint below.",
"controlProvisionSteps": "In the Anker app (or the charger's OCPP settings), set the OCPP backend URL to the endpoint and the authorization key to the token above.",
"chargerSerial": "Charger serial",
"controlCheck": "Check status",
"controlGenerate": "Generate token",
"controlEndpoint": "OCPP endpoint",
"controlToken": "Auth token",
"controlTokenOnce": "Copy this token now — it's shown only once and can't be retrieved later.",
"controlRevoke": "Revoke token",
"controlRevokeConfirm": "Revoke this charger's control token? It will disconnect and can't reconnect until you generate a new one.",
"controlConnected": "Connected to control backend",
"controlDisconnected": "Not connected"
},
"account": {
"title": "Account",
"name": "Name",