6.3 KiB
KoolTap Flutter App — Remote Backoffice Integration (Improved Pairing Flow)
You are implementing the device-side integration for the KoolTap remote tab control system. The Flutter app (bar POS terminal) needs to register with a remote backend, sync open tabs, and process remote close-tab commands.
Project Location
C:\Users\bram\StudioProjects\kooltap
Architecture Overview
- State management:
provider(ChangeNotifier pattern) - Routing:
go_router - Local DB:
drift(SQLite ORM) - HTTP:
httppackage - Auth tokens stored in
flutter_secure_storage - MVVM pattern: views → viewmodels → services
- Models in
lib/models/ - Services in
lib/services/ - ViewModels in
lib/viewmodels/ - Views in
lib/views/ - Config constants in
lib/utils/app_config.dart - Main app bootstrap in
lib/app/app_bootstrap.dart
Pairing Flow (improved)
Instead of typing a UUID venueId, the flow is:
- Tablet calls
GET https://api.kooltap.com/api/v1/venues/(public, no auth) - Gets list of
[{id, name}]— admin picks venue from a dropdown - Admin enters device name (e.g. "Bar terminal 1")
- Admin enters the 6-character registration code (generated from dashboard)
- Tablet calls
POST /devices/registerwith venueId + name + code - Stores deviceId + token + venueId + serverUrl in secure storage
- Sync starts automatically
Existing Sync Infrastructure (already built)
Do NOT rewrite these files, just modify as needed:
lib/services/remote_sync_service.dart(410 lines) —setCredentials(),startSync(),stopSync(), sync loop, command processing, ACKslib/viewmodels/remote_sync_view_model.dart(90 lines) — ChangeNotifier wrapperlib/models/remote_command.dart(135 lines) — DTOs:RemoteCommand,SyncRequest,SyncResponse,SnapshotTab,CommandAcklib/utils/app_config.dart— URL constantslib/models/payment_method.dart— payment enums
What to Build
1. Update Server URL
In lib/utils/app_config.dart:
const kRemoteServerUrl = 'https://api.kooltap.com/api/v1/';
2. Add Venue Model
Create lib/models/venue.dart:
class Venue {
final String id;
final String name;
Venue({required this.id, required this.name});
factory Venue.fromJson(Map<String, dynamic> json) => Venue(id: json['id'], name: json['name']);
}
3. Update RemoteSyncService — Add venueId Storage
In lib/services/remote_sync_service.dart:
- Add
venueIdparameter tosetCredentials()signature - Store venueId in FlutterSecureStorage alongside deviceId/token/serverUrl
- Add
String? get venueIdgetter - Update
isConfiguredto also check venueId exists - Add
clearCredentials()method (clears all stored credentials)
4. Registration ViewModel
Create lib/viewmodels/registration_view_model.dart:
Future<List<Venue>> fetchVenues()— callsGET /api/v1/venues/Future<void> registerDevice(String venueId, String name, String code)— callsPOST /devices/register, then stores credentials viaRemoteSyncService.setCredentials()- States:
initial,loading,venuesLoaded,error,registered - Expose as ChangeNotifier
5. Registration UI
Create lib/views/registration_view.dart — a full-screen registration flow with steps:
Step 1 — Select venue:
- Dropdown list of venues fetched from API
- Show loading spinner while fetching
- Show error + retry if fetch fails
- "Next" button when venue selected
Step 2 — Device details:
- Device name text field (with default "Bar terminal 1")
- Registration code text field (6 characters)
- "Register" button
- Loading state while registering
- Error display if registration fails
Step 3 — Success screen:
- Success animation/message
- "Start using KoolTap" button → navigates to main bar screen and triggers sync
6. Wire Registration into Navigation
In lib/app/app_bootstrap.dart:
- On app startup, check
remoteSyncService.isConfigured - If NOT configured: show registration screen instead of main bar screen
- If configured: proceed to main bar screen as normal
In lib/app/router.dart:
- Add route for registration screen as initial route when not configured
7. Disconnect Option
In the Settings screen (lib/views/settings_view.dart) or Admin screen:
- If configured, show "Connected to [venue name]" with device name
- "Disconnect" button → calls
clearCredentials(), navigates back to registration screen
API Endpoints Summary
| Method | Endpoint | Auth | Purpose |
|---|---|---|---|
| GET | /api/v1/venues/ |
None | List venues (returns [{id, name}]) |
| POST | /api/v1/devices/register |
None | Register device (body: venueId, name, registrationCode) |
| POST | /api/v1/devices/:id/sync |
Bearer token | Sync tabs, receive commands |
| POST | /api/v1/devices/:id/commands/:cmdId/ack |
Bearer token | Acknowledge command |
Registration API Details
Venues list:
GET https://api.kooltap.com/api/v1/venues/
Response: [{"id": "uuid", "name": "KoolTap Demo Bar"}, ...]
Device registration:
POST https://api.kooltap.com/api/v1/devices/register
{
"venueId": "uuid-from-venue-list",
"name": "Bar terminal 1",
"registrationCode": "A8F3C2"
}
Response 201:
{
"deviceId": "uuid",
"token": "dev_abc123...",
"tokenExpiresAt": "2026-..."
}
The registration code is generated from the dashboard (Devices → Add Device → generates 6-char code valid for 10 minutes).
Files to Create
lib/models/venue.dartlib/viewmodels/registration_view_model.dartlib/views/registration_view.dart
Files to Modify
lib/utils/app_config.dart— update URLlib/services/remote_sync_service.dart— add venueId + clearCredentialslib/app/app_bootstrap.dart— check isConfigured, route to registration if notlib/app/router.dart— add registration routelib/views/admin_screen_view.dartorlib/views/settings_view.dart— add disconnect option
Important Notes
- Do NOT break the existing sync loop — registration only configures credentials
- The existing sync sends
SnapshotTaband processesclose_tabcommands stays unchanged - Use
flutter_secure_storagefor persisting credentials - Handle loading/error states in the UI
- After registration, call
remoteSyncViewModel.start()to begin syncing - Tabs appear on the dashboard within ~90 seconds of first sync