import 'package:json_annotation/json_annotation.dart'; import 'meal_type.dart'; part 'user.g.dart'; @JsonSerializable() class User { final String id; final String email; final String name; @JsonKey(name: 'avatar_url') final String? avatarUrl; @JsonKey(name: 'height_cm') final int? heightCm; @JsonKey(name: 'weight_kg') final double? weightKg; @JsonKey(name: 'date_of_birth') final String? dateOfBirth; final String? gender; final String? activity; final String? goal; @JsonKey(name: 'daily_calories') final int? dailyCalories; final String plan; @JsonKey(defaultValue: {}) final Map preferences; const User({ required this.id, required this.email, required this.name, this.avatarUrl, this.heightCm, this.weightKg, this.dateOfBirth, this.gender, this.activity, this.goal, this.dailyCalories, required this.plan, this.preferences = const {}, }); factory User.fromJson(Map json) => _$UserFromJson(json); Map toJson() => _$UserToJson(this); int? get age { if (dateOfBirth == null) return null; final dob = DateTime.tryParse(dateOfBirth!); if (dob == null) return null; final now = DateTime.now(); int years = now.year - dob.year; if (now.month < dob.month || (now.month == dob.month && now.day < dob.day)) { years--; } return years; } bool get hasCompletedOnboarding => heightCm != null && weightKg != null && dateOfBirth != null && gender != null && goal != null && activity != null; /// Returns the user's configured meal type IDs from preferences, /// falling back to the default set if not yet configured. List get mealTypes { final value = preferences['meal_types']; if (value is List && value.isNotEmpty) return List.from(value); return List.from(kDefaultMealTypeIds); } }