- EquipmentDetail: collapsible node groups (clients grouped by mesh node) - Signal strength as RSSI % (0-255 per 802.11-2020) with 10-tone color scale - Management IP clickable link to device web GUI (/superadmin/) - Fibre status compact top bar (status + Rx/Tx power when available) - targo-hub: WAN IP detection across all VLAN interfaces - targo-hub: full WiFi client count (direct + EasyMesh mesh repeaters) - targo-hub: /devices/:id/hosts endpoint with client-to-node mapping - ClientsPage: start empty, load only on search (no auto-load all) - nginx: dynamic ollama resolver (won't crash if ollama is down) - Cleanup: remove unused BillingKPIs.vue and TagInput.vue - New docs and migration scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
15 KiB
15 KiB
Field Tech App — Wizard UX & Form Customizer
Design Principles
- Minimal inputs per screen — Techs are manual workers, not desk jockeys. Max 2-3 fields per step.
- Carousel/swipe navigation — Next/Back with swipe gestures, not scrolling a long form.
- Big touch targets — Fat fingers in work gloves. Buttons 48px+ height, inputs 56px+.
- Auto-advance — When a field is selected (like equipment_type), auto-advance to next step.
- Offline-first — Everything queued if no signal. Sync indicator always visible.
- Customizable — Admin can add/remove/reorder steps via an Odoo Studio-like builder.
Wizard Component Architecture
Core: WizardCarousel.vue
A reusable carousel-based wizard that renders steps from a JSON definition:
<WizardCarousel
:steps="wizardSteps"
:context="{ job, customer, location }"
@complete="onComplete"
@cancel="onCancel"
/>
Each step is a self-contained screen rendered in a q-carousel-slide:
- Swipe left/right to navigate
- Bottom progress dots
- "Suivant" / "Précédent" buttons (large, thumb-friendly)
- Step counter: "Étape 2/5"
Step Definition Schema
{
"id": "equipment_type",
"title": "Type d'équipement",
"icon": "router",
"fields": [
{
"name": "equipment_type",
"type": "select-cards",
"label": "Quel équipement?",
"options": [
{ "value": "ONT", "label": "ONT", "icon": "settings_input_hdmi", "color": "blue" },
{ "value": "Routeur", "label": "Routeur WiFi", "icon": "wifi", "color": "green" },
{ "value": "Décodeur TV", "label": "Décodeur TV", "icon": "tv", "color": "purple" },
{ "value": "Téléphone IP", "label": "Téléphone", "icon": "phone", "color": "orange" }
],
"auto_advance": true
}
],
"visible_if": null,
"required": true
}
Field Types
| Type | Render | Use Case |
|---|---|---|
select-cards |
Big tappable cards with icons | Equipment type, status, connection type |
text |
Single large input | Serial number, name |
scan |
Camera button → barcode scanner | Serial, MAC address |
photo |
Camera button → photo capture | Equipment photo, site photo |
signature |
Touch signature pad | Customer sign-off |
toggle |
Large yes/no toggle | Signal OK?, WiFi working? |
notes |
Textarea (expandable) | Completion notes |
date |
Date picker | Schedule date |
search |
Autocomplete search | Customer lookup |
checklist |
List of checkable items | Installation checklist |
info |
Read-only display card | Summary, confirmation |
Example Wizards
1. Installation Completion Wizard
When tech taps "Compléter" on a Dispatch Job:
Step 1: "Équipements installés" [checklist]
☐ ONT branché et signal OK
☐ Routeur WiFi configuré
☐ Décodeur TV branché (if TV service)
☐ Téléphone IP testé (if phone service)
Step 2: "Numéros de série" [scan]
→ Camera opens, scan ONT barcode
→ Auto-detected: RCMG19E0AB57
→ "Suivant" button
Step 3: "Signal ONT" [toggle + text]
Signal OK? [OUI / NON]
Niveau signal: [-20 dBm] (optional)
Step 4: "WiFi" [toggle]
Client connecté au WiFi? [OUI / NON]
SSID affiché: "Gigafibre-Tremblay"
Step 5: "Photo du boîtier" [photo]
📸 Prendre une photo
Step 6: "Signature client" [signature]
Le client confirme que le service fonctionne
Step 7: "Résumé" [info]
✓ ONT: RCMG19E0AB57
✓ Signal: -18.5 dBm
✓ WiFi: OK
✓ Photo: 1 prise
✓ Signé par: Jean Tremblay
[Confirmer l'installation]
2. Equipment Scan & Link Wizard
When tech scans a barcode (from ScanPage or Job context):
Step 1: "Scanner" [scan]
📸 Scanner le code-barres
→ Detected: RCMG19E0AB57
Step 2: "Type" [select-cards]
ONT / Routeur / Décodeur / Téléphone
→ Tap "ONT" → auto-advance
Step 3: "Confirmer" [info]
Serial: RCMG19E0AB57
Type: ONT
Client: Jean Tremblay (from job context)
Adresse: 123 rue Principale
[Lier à ce client]
3. Repair/Diagnostic Wizard
Step 1: "Problème signalé" [info]
Ticket: "Pas d'internet depuis hier"
Client: Jean Tremblay
Adresse: 123 rue Principale
Step 2: "Signal ONT" [toggle + text]
Signal présent? [OUI / NON]
Niveau: [-XX dBm]
Step 3: "Test WiFi" [toggle]
WiFi fonctionne? [OUI / NON]
Step 4: "Action prise" [select-cards]
Redémarrage / Remplacement ONT / Remplacement routeur / Reconnexion fibre / Autre
Step 5: "Nouvel équipement" [scan] (if replacement)
Scanner le nouveau serial
Step 6: "Notes" [notes]
Détails supplémentaires...
Step 7: "Résultat" [toggle]
Service rétabli? [OUI / NON]
[Fermer le ticket]
Form Customizer (Odoo Studio-like)
Concept
An admin page in the Ops app (/ops/form-builder) that lets managers customize the tech wizard steps without code changes.
How It Works
- Wizard Templates stored as JSON documents in ERPNext (new doctype:
Wizard Template) - Each template = ordered list of steps with field definitions
- Admin UI = drag-and-drop step editor:
- Add step (from field type library)
- Reorder steps (drag handle)
- Edit step properties (label, options, required, visibility condition)
- Remove step
- Preview on mock phone screen
- Templates linked to job types: Installation, Réparation, Maintenance, Retrait, etc.
- Field app fetches the template for the current job type and renders it dynamically
Wizard Template Doctype
Wizard Template
name: "Installation FTTH"
job_type: "Installation"
is_active: Check
steps: (child table: Wizard Template Step)
- step_order: 1
step_id: "equipment_checklist"
title: "Équipements installés"
field_type: "checklist"
field_config: '{"items":["ONT branché","Routeur configuré","Décodeur branché"]}'
required: 1
visible_condition: null
- step_order: 2
step_id: "ont_scan"
title: "Scanner ONT"
field_type: "scan"
field_config: '{"placeholder":"Scanner le code-barres ONT"}'
required: 1
- ...
Admin Builder UI
┌─ Form Builder: Installation FTTH ─────────────────────────┐
│ │
│ ┌─ Step 1 ─────────────────────────── [≡] [✏️] [🗑] ──┐ │
│ │ 📋 Checklist: "Équipements installés" │ │
│ │ Items: ONT, Routeur, Décodeur, Téléphone │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─ Step 2 ─────────────────────────── [≡] [✏️] [🗑] ──┐ │
│ │ 📷 Scan: "Scanner ONT" │ │
│ │ Required: Oui │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ ┌─ Step 3 ─────────────────────────── [≡] [✏️] [🗑] ──┐ │
│ │ ✅ Toggle: "Signal ONT OK?" │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ [+ Ajouter une étape] │
│ │
│ ┌─ Aperçu téléphone ──┐ │
│ │ ┌────────────────┐ │ │
│ │ │ Étape 1/7 │ │ │
│ │ │ │ │ │
│ │ │ ☐ ONT branché │ │ │
│ │ │ ☐ Routeur │ │ │
│ │ │ ☐ Décodeur │ │ │
│ │ │ │ │ │
│ │ │ [Suivant →] │ │ │
│ │ │ ● ○ ○ ○ ○ ○ ○ │ │ │
│ │ └────────────────┘ │ │
│ └──────────────────────┘ │
│ │
│ [Sauvegarder] [Publier] │
└─────────────────────────────────────────────────────────────┘
4. Equipment Swap Wizard (Defective → Replacement)
When tech taps "Remplacer" on a device or from the "Plus" menu:
Step 1: "Équipement défectueux" [search/scan]
Scan le code-barres de l'ancien équipement
→ OU chercher par numéro de série
→ Affiche: RCMG19E0AB57 — ONT Raisecom HT803G-WS2
Client: Jean Tremblay
Adresse: 123 rue Principale
Step 2: "Raison du remplacement" [select-cards]
🔴 Défectueux (ne s'allume plus)
🟡 Performance dégradée
🔵 Mise à niveau (upgrade)
⚪ Autre
Step 3: "Nouvel équipement" [scan]
📸 Scanner le code-barres du remplacement
→ Detected: TPLGA1E7FB90
→ Auto-detect type: XX230v (ONT)
Step 4: "Confirmer le remplacement" [info]
❌ Ancien: RCMG19E0AB57 → sera marqué "Défectueux"
✅ Nouveau: TPLGA1E7FB90 → sera activé
Données transférées automatiquement:
• WiFi SSID/mot de passe ✓
• SIP (VoIP) credentials ✓
• Port OLT: 0/3/2 ONT:12 ✓
• VLANs: inet/mgmt/tel/tv ✓
⚠️ L'OLT sera reconfiguré (ancien ONT supprimé, nouveau enregistré)
[Confirmer le remplacement]
Step 5: "Vérification" [toggle]
Nouveau ONT en ligne? [OUI / NON]
Signal OK? [OUI / NON]
Services fonctionnels? [OUI / NON]
[Terminer]
Backend flow (POST /provision/swap):
- Marks old equipment as "Défectueux" in ERPNext
- Creates new Service Equipment with transferred WiFi/VoIP/OLT data
- Generates OLT swap commands (delete old ONT, register new)
- n8n executes OLT commands via SSH
- ACS pushes config to new device on bootstrap
- Ops team notified via SSE
5. Quick Actions Menu (field app "Plus" page)
┌──────────────────────────────────────────┐
│ Actions rapides │
│ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ 📷 │ │ 🔄 │ │ 🔧 │ │
│ │ Scan │ │ Swap │ │ Diag │ │
│ │ équip. │ │ équip. │ │ réseau │ │
│ └────────┘ └────────┘ └────────┘ │
│ │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ 📋 │ │ 📸 │ │ ✏️ │ │
│ │ Check │ │ Photo │ │ Note │ │
│ │ -list │ │ site │ │ rapide │ │
│ └────────┘ └────────┘ └────────┘ │
└──────────────────────────────────────────┘
Each action opens the corresponding wizard flow.
Implementation Plan
Phase 1: WizardCarousel Component
- Create
apps/field/src/components/WizardCarousel.vue— carousel renderer - Create
apps/field/src/components/wizard-fields/— one component per field type:SelectCards.vue(big tappable cards)ScanField.vue(camera + barcode)ToggleField.vue(yes/no)PhotoField.vue(camera capture)SignatureField.vue(touch pad)ChecklistField.vue(checkable items)TextField.vue(single input)NotesField.vue(textarea)InfoField.vue(read-only summary)
- Create
apps/field/src/composables/useWizard.js— step state, validation, submission
Phase 2: Hardcoded Wizards
- Build "Installation Complete" wizard (7 steps as above)
- Build "Equipment Scan & Link" wizard (3 steps)
- Integrate into TasksPage "Complete Job" action
- Replace current ScanPage equipment creation dialog with wizard flow
Phase 3: Wizard Template Doctype
- Create
Wizard Template+Wizard Template Stepdoctypes in ERPNext - Seed with Installation, Repair, Maintenance templates
- Field app fetches template by job_type on wizard open
- WizardCarousel renders dynamically from template
Phase 4: Admin Form Builder (Ops App)
- Build
/ops/form-builderpage - Drag-and-drop step editor (vue-draggable)
- Step property editor (sidebar panel)
- Phone preview panel
- Publish → saves to ERPNext Wizard Template
CSS / Styling Notes
// Wizard slide — full height, centered content
.wizard-slide {
display: flex;
flex-direction: column;
justify-content: center;
padding: 24px 16px;
min-height: calc(100vh - 160px); // account for header + progress bar
}
// Select cards — large touch targets
.select-card {
min-height: 80px;
border-radius: 16px;
font-size: 18px;
margin-bottom: 12px;
transition: transform 0.15s, box-shadow 0.15s;
&:active { transform: scale(0.97); }
&.selected {
border: 3px solid var(--q-primary);
box-shadow: 0 0 0 4px rgba(var(--q-primary-rgb), 0.2);
}
}
// Progress dots
.wizard-dots {
display: flex;
justify-content: center;
gap: 8px;
padding: 16px;
.dot {
width: 10px; height: 10px;
border-radius: 50%;
background: #ccc;
&.active { background: var(--q-primary); width: 24px; border-radius: 5px; }
&.done { background: var(--q-positive); }
}
}
// Navigation buttons — thumb-friendly
.wizard-nav {
display: flex;
gap: 12px;
padding: 16px;
.q-btn { min-height: 56px; font-size: 16px; flex: 1; border-radius: 12px; }
}