feat(api,ui,db): add address, guest users, image URLs; update API
- Backend:
- Add address column to tickets and migration script
- Create guest users when user_id is missing; accept user_name and address
- Normalize stored image paths and expose absolute image_url
- Introduce utils for path normalization and ticket serialization
- Add CORS configuration for dashboard/emulator origins
- Tickets API:
- Serialize via ticket_to_dict with consistent schema
- Change status update to PATCH /api/tickets/{id}/status with JSON body
- Add DELETE /api/tickets/{id} with safe file removal
- Dashboard:
- Fetch tickets from backend, show thumbnails, absolute image URLs
- Status select + PATCH updates, toasts for feedback
- Add i18n key btn.viewDetails
- Mobile app:
- Persist device user_id via SharedPreferences
- Fetch and merge API tickets; prefer network imageUrl
- Submit user_name and address; delete via API when available
- Make location acquisition robust with fallbacks and non-blocking UX
- Android/deps:
- Disable Geolocator NMEA listener to prevent crashes
- Downgrade geolocator to ^11.0.0 for stability
BREAKING CHANGE:
- Status endpoint changed from PATCH /api/tickets/{id}?new_status=... to
PATCH /api/tickets/{id}/status with JSON body: {"status":"in_progress"}.
- /api/tickets and /api/tickets/{id} responses now use "id" (replacing
"ticket_id"), include "image_url", and normalize fields for clients. Update
consumers to use the new schema.
This commit is contained in:
@@ -21,6 +21,9 @@ class Report {
|
||||
/// Base64 encoded photo for web platform
|
||||
final String? base64Photo;
|
||||
|
||||
/// Remote image URL provided by backend (absolute URL)
|
||||
final String? imageUrl;
|
||||
|
||||
/// Geographic location where the issue was reported
|
||||
final LocationData location;
|
||||
|
||||
@@ -38,6 +41,8 @@ class Report {
|
||||
|
||||
/// Address or location description (placeholder for future use)
|
||||
final String? address;
|
||||
/// Name of the user who submitted the report (API reports)
|
||||
final String? submittedBy;
|
||||
|
||||
/// Source of the photo ("camera" or "gallery")
|
||||
final String source;
|
||||
@@ -61,12 +66,14 @@ class Report {
|
||||
required this.status,
|
||||
this.photoPath,
|
||||
this.base64Photo,
|
||||
this.imageUrl,
|
||||
required this.location,
|
||||
required this.createdAt,
|
||||
required this.updatedAt,
|
||||
required this.deviceId,
|
||||
this.notes,
|
||||
this.address,
|
||||
this.submittedBy,
|
||||
required this.source,
|
||||
this.editable = true,
|
||||
this.deletable = true,
|
||||
@@ -89,6 +96,8 @@ class Report {
|
||||
String? photoPath,
|
||||
String? base64Photo,
|
||||
String? notes,
|
||||
String? submittedBy,
|
||||
String? address,
|
||||
required String source,
|
||||
required String deviceId,
|
||||
required AISuggestion aiSuggestion,
|
||||
@@ -106,6 +115,8 @@ class Report {
|
||||
updatedAt: now,
|
||||
deviceId: deviceId,
|
||||
notes: notes,
|
||||
address: address,
|
||||
submittedBy: submittedBy,
|
||||
source: source,
|
||||
aiSuggestion: aiSuggestion,
|
||||
);
|
||||
@@ -118,6 +129,7 @@ class Report {
|
||||
Status? status,
|
||||
String? photoPath,
|
||||
String? base64Photo,
|
||||
String? imageUrl,
|
||||
LocationData? location,
|
||||
String? updatedAt,
|
||||
String? notes,
|
||||
@@ -133,6 +145,7 @@ class Report {
|
||||
status: status ?? this.status,
|
||||
photoPath: photoPath ?? this.photoPath,
|
||||
base64Photo: base64Photo ?? this.base64Photo,
|
||||
imageUrl: imageUrl ?? this.imageUrl,
|
||||
location: location ?? this.location,
|
||||
createdAt: createdAt,
|
||||
updatedAt: updatedAt ?? this.updatedAt,
|
||||
@@ -156,6 +169,7 @@ class Report {
|
||||
'status': status.key,
|
||||
'photoPath': photoPath,
|
||||
'base64Photo': base64Photo,
|
||||
'imageUrl': imageUrl,
|
||||
'location': {
|
||||
'lat': location.lat,
|
||||
'lng': location.lng,
|
||||
@@ -166,6 +180,7 @@ class Report {
|
||||
'deviceId': deviceId,
|
||||
'notes': notes,
|
||||
'address': address,
|
||||
'submittedBy': submittedBy,
|
||||
'source': source,
|
||||
'editable': editable,
|
||||
'deletable': deletable,
|
||||
@@ -187,6 +202,7 @@ class Report {
|
||||
status: (json['status'] as String).toStatus() ?? Status.submitted,
|
||||
photoPath: json['photoPath'] as String?,
|
||||
base64Photo: json['base64Photo'] as String?,
|
||||
imageUrl: json['imageUrl'] as String?,
|
||||
location: LocationData(
|
||||
lat: (json['location']['lat'] as num).toDouble(),
|
||||
lng: (json['location']['lng'] as num).toDouble(),
|
||||
@@ -199,6 +215,7 @@ class Report {
|
||||
deviceId: json['deviceId'] as String,
|
||||
notes: json['notes'] as String?,
|
||||
address: json['address'] as String?,
|
||||
submittedBy: json['submittedBy'] as String?,
|
||||
source: json['source'] as String,
|
||||
editable: json['editable'] as bool? ?? true,
|
||||
deletable: json['deletable'] as bool? ?? true,
|
||||
|
||||
Reference in New Issue
Block a user