enum AdminAiTraceSource { receipt, flyer } enum AdminAiTraceStatus { success, warning, error } extension AdminAiTraceSourceX on AdminAiTraceSource { String get apiValue => this == AdminAiTraceSource.receipt ? 'receipt' : 'flyer'; String get label => this == AdminAiTraceSource.receipt ? 'Kvitto' : 'Flyer'; static AdminAiTraceSource fromApi(String? value) { if (value == 'receipt') return AdminAiTraceSource.receipt; return AdminAiTraceSource.flyer; } } extension AdminAiTraceStatusX on AdminAiTraceStatus { String get label => switch (this) { AdminAiTraceStatus.success => 'OK', AdminAiTraceStatus.warning => 'Varning', AdminAiTraceStatus.error => 'Fel', }; static AdminAiTraceStatus fromApi(String? value) { return switch (value) { 'error' => AdminAiTraceStatus.error, 'warning' => AdminAiTraceStatus.warning, _ => AdminAiTraceStatus.success, }; } } class AdminAiTraceListItem { final String id; final AdminAiTraceSource source; final AdminAiTraceStatus status; final DateTime createdAt; final int userId; final String userLabel; final int? sessionId; final String? fileName; final String? model; final int? durationMs; final int warningsCount; final bool hasPrompt; final bool hasOutput; final String? error; const AdminAiTraceListItem({ required this.id, required this.source, required this.status, required this.createdAt, required this.userId, required this.userLabel, required this.sessionId, required this.fileName, required this.model, required this.durationMs, required this.warningsCount, required this.hasPrompt, required this.hasOutput, required this.error, }); factory AdminAiTraceListItem.fromJson(Map json) { return AdminAiTraceListItem( id: (json['id'] ?? '').toString(), source: AdminAiTraceSourceX.fromApi(json['source']?.toString()), status: AdminAiTraceStatusX.fromApi(json['status']?.toString()), createdAt: DateTime.tryParse((json['createdAt'] ?? '').toString()) ?? DateTime.fromMillisecondsSinceEpoch(0), userId: (json['userId'] as num?)?.toInt() ?? 0, userLabel: (json['userLabel'] ?? '').toString(), sessionId: (json['sessionId'] as num?)?.toInt(), fileName: json['fileName']?.toString(), model: json['model']?.toString(), durationMs: (json['durationMs'] as num?)?.toInt(), warningsCount: (json['warningsCount'] as num?)?.toInt() ?? 0, hasPrompt: json['hasPrompt'] == true, hasOutput: json['hasOutput'] == true, error: json['error']?.toString(), ); } } class AdminAiTraceListResponse { final List items; final String? nextCursor; const AdminAiTraceListResponse({ required this.items, required this.nextCursor, }); factory AdminAiTraceListResponse.fromJson(Map json) { final rawItems = (json['items'] as List?) ?? const []; return AdminAiTraceListResponse( items: rawItems .whereType() .map((entry) => AdminAiTraceListItem.fromJson(Map.from(entry))) .toList(), nextCursor: json['nextCursor']?.toString(), ); } }