enum SuggestionStatus { pending, reviewed, implemented } class Suggestion { const Suggestion({ required this.id, required this.text, required this.isAnonymous, required this.submittedAt, required this.status, this.userId, this.displayName, }); final String id; final String text; final bool isAnonymous; final String? userId; final String? displayName; final DateTime submittedAt; final SuggestionStatus status; Suggestion copyWith({ String? id, String? text, bool? isAnonymous, String? userId, String? displayName, DateTime? submittedAt, SuggestionStatus? status, }) { return Suggestion( id: id ?? this.id, text: text ?? this.text, isAnonymous: isAnonymous ?? this.isAnonymous, userId: userId ?? this.userId, displayName: displayName ?? this.displayName, submittedAt: submittedAt ?? this.submittedAt, status: status ?? this.status, ); } factory Suggestion.fromJson(Map data) { return Suggestion( id: (data['id'] as String?) ?? '', text: (data['text'] as String?) ?? '', isAnonymous: _parseBool(data['is_anonymous']), userId: data['user_id'] as String?, displayName: data['display_name'] as String?, submittedAt: _parseDate(data['submitted_at']) ?? DateTime.now(), status: _parseStatus(data['status'] as String?), ); } Map toJson() { return { 'text': text, 'is_anonymous': isAnonymous, 'user_id': isAnonymous ? null : userId, 'display_name': isAnonymous ? null : displayName, 'status': status.name, }; } static DateTime? _parseDate(Object? v) { if (v is String && v.isNotEmpty) return DateTime.tryParse(v); return null; } static bool _parseBool(Object? v) { if (v is bool) return v; if (v is int) return v != 0; if (v is String) return v == '1' || v.toLowerCase() == 'true'; return false; } static SuggestionStatus _parseStatus(String? raw) { switch (raw) { case 'reviewed': return SuggestionStatus.reviewed; case 'implemented': return SuggestionStatus.implemented; default: return SuggestionStatus.pending; } } @override bool operator ==(Object other) { if (identical(this, other)) return true; return other is Suggestion && other.id == id && other.text == text && other.isAnonymous == isAnonymous && other.userId == userId && other.displayName == displayName && other.submittedAt == submittedAt && other.status == status; } @override int get hashCode => Object.hash( id, text, isAnonymous, userId, displayName, submittedAt, status, ); @override String toString() => 'Suggestion(id: $id, status: ${status.name}, anonymous: $isAnonymous)'; }