import 'dart:convert'; /// Represents a document attached to a trip (billet, passeport, assurance, etc.). /// /// The model stores a human-friendly [title], a [category] to filter in the UI, /// an optional [downloadUrl] when the file is hosted remotely, and an optional /// [expiresAt] date for reminders (ex: passeport ou ESTA). class TripDocument { /// Unique identifier for the document entry. final String id; /// Display name chosen by the user (ex: « Billet retour AF763 »). final String title; /// Type/category (ex: `billet`, `passeport`, `assurance`, `hebergement`). final String category; /// Optional URL to open/download the document (cloud storage or external). final String? downloadUrl; /// Optional local file path when offline-only; kept for future sync. final String? localPath; /// Optional expiration date to trigger reminders. final DateTime? expiresAt; /// Creation timestamp used for stable ordering. final DateTime createdAt; /// Creates a trip document entry. const TripDocument({ required this.id, required this.title, required this.category, required this.createdAt, this.downloadUrl, this.localPath, this.expiresAt, }); /// Builds a new entry with defaults. factory TripDocument.newEntry({ required String id, required String title, required String category, String? downloadUrl, String? localPath, DateTime? expiresAt, }) { return TripDocument( id: id, title: title, category: category, downloadUrl: downloadUrl, localPath: localPath, expiresAt: expiresAt, createdAt: DateTime.now().toUtc(), ); } /// Returns a copy with updated fields. TripDocument copyWith({ String? id, String? title, String? category, String? downloadUrl, String? localPath, DateTime? expiresAt, DateTime? createdAt, }) { return TripDocument( id: id ?? this.id, title: title ?? this.title, category: category ?? this.category, downloadUrl: downloadUrl ?? this.downloadUrl, localPath: localPath ?? this.localPath, expiresAt: expiresAt ?? this.expiresAt, createdAt: createdAt ?? this.createdAt, ); } /// Serializes the entry to JSON for persistence. Map toJson() { return { 'id': id, 'title': title, 'category': category, 'downloadUrl': downloadUrl, 'localPath': localPath, 'expiresAt': expiresAt?.toIso8601String(), 'createdAt': createdAt.toIso8601String(), }; } /// Deserializes a trip document from JSON. factory TripDocument.fromJson(Map json) { return TripDocument( id: json['id'] as String, title: json['title'] as String, category: json['category'] as String, downloadUrl: json['downloadUrl'] as String?, localPath: json['localPath'] as String?, expiresAt: json['expiresAt'] != null ? DateTime.tryParse(json['expiresAt'] as String) : null, createdAt: DateTime.parse(json['createdAt'] as String), ); } /// Encodes a list of documents to a JSON string. static String encodeList(List docs) { return json.encode(docs.map((d) => d.toJson()).toList()); } /// Decodes a list of documents from a JSON string. static List decodeList(String raw) { final decoded = json.decode(raw) as List; return decoded .cast>() .map(TripDocument.fromJson) .toList(); } }