enum UserRole { admin, group_manager, member } extension UserRoleExtension on UserRole { String get label { switch (this) { case UserRole.admin: return 'Admin'; case UserRole.group_manager: return 'Group Manager'; case UserRole.member: return 'Member'; } } String get apiValue => name; } class UserModel { final String id; final String username; final UserRole role; final bool isActive; final DateTime? createdAt; /// Only available immediately after creation or secret reset final String? secret; const UserModel({ required this.id, required this.username, required this.role, required this.isActive, this.createdAt, this.secret, }); factory UserModel.fromJson(Map json) { return UserModel( id: json['id'] as String, username: json['username'] as String, role: UserRole.values.firstWhere( (r) => r.name == (json['role'] as String), orElse: () => UserRole.member, ), isActive: (json['is_active'] as bool?) ?? true, createdAt: json['created_at'] != null ? DateTime.tryParse(json['created_at'] as String) : null, ); } Map toJson() => { 'id': id, 'username': username, 'role': role.apiValue, 'is_active': isActive, if (createdAt != null) 'created_at': createdAt!.toIso8601String(), }; UserModel copyWith({ String? id, String? username, UserRole? role, bool? isActive, DateTime? createdAt, String? secret, }) { return UserModel( id: id ?? this.id, username: username ?? this.username, role: role ?? this.role, isActive: isActive ?? this.isActive, createdAt: createdAt ?? this.createdAt, secret: secret ?? this.secret, ); } }