-
Notifications
You must be signed in to change notification settings - Fork 3
Implement My Festival favourites feature #200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
ee613bb
6a55f26
5c8624a
ec480b3
d182620
91ba27f
db8a05b
a476cf6
39d7fe4
2b33128
0bcdf54
706bc44
9ff3b44
a74d841
bfad100
6ea9e49
8bbc70c
42af7a3
20580ca
9305945
f726d39
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| /// Represents a drink in the user's festival log. | ||
| /// | ||
| /// Tracks whether a drink is on the 'want to try' list or has been tasted, | ||
| /// along with timestamps of tastings and optional notes. | ||
| class FavoriteItem { | ||
| /// Creates a favorite item. | ||
| const FavoriteItem({ | ||
| required this.id, | ||
| required this.status, | ||
| required this.tries, | ||
| this.notes, | ||
| required this.createdAt, | ||
| required this.updatedAt, | ||
| }); | ||
|
|
||
| /// Drink ID. | ||
| final String id; | ||
|
|
||
| /// Status: 'want_to_try' or 'tasted'. | ||
| final String status; | ||
|
|
||
| /// List of tasting timestamps (empty if want_to_try). | ||
| final List<DateTime> tries; | ||
|
|
||
| /// Optional user notes. | ||
| final String? notes; | ||
|
|
||
| /// When this item was added to the log. | ||
| final DateTime createdAt; | ||
|
|
||
| /// When this item was last updated. | ||
| final DateTime updatedAt; | ||
|
|
||
| /// Creates a FavoriteItem from JSON. | ||
| factory FavoriteItem.fromJson(Map<String, dynamic> json) { | ||
| return FavoriteItem( | ||
| id: json['id'] as String, | ||
| status: json['status'] as String? ?? 'want_to_try', | ||
| tries: (json['tries'] as List?) | ||
| ?.map((e) => DateTime.parse(e as String)) | ||
| .toList() ?? | ||
| [], | ||
| notes: json['notes'] as String?, | ||
| createdAt: DateTime.parse(json['createdAt'] as String), | ||
| updatedAt: DateTime.parse(json['updatedAt'] as String), | ||
| ); | ||
| } | ||
|
|
||
| /// Converts this item to JSON. | ||
| Map<String, dynamic> toJson() { | ||
| return { | ||
| 'id': id, | ||
| 'status': status, | ||
| 'tries': tries.map((t) => t.toIso8601String()).toList(), | ||
| if (notes != null) 'notes': notes, | ||
| 'createdAt': createdAt.toIso8601String(), | ||
| 'updatedAt': updatedAt.toIso8601String(), | ||
| }; | ||
| } | ||
|
|
||
| /// Creates a copy with updated fields. | ||
| /// | ||
| /// To explicitly clear notes, pass an empty Optional: `notes: Optional.value(null)`. | ||
| /// To keep existing notes, omit the parameter: `copyWith(status: 'tasted')`. | ||
| FavoriteItem copyWith({ | ||
| String? id, | ||
| String? status, | ||
| List<DateTime>? tries, | ||
| Optional<String?>? notes, | ||
| DateTime? createdAt, | ||
| DateTime? updatedAt, | ||
| }) { | ||
| return FavoriteItem( | ||
| id: id ?? this.id, | ||
| status: status ?? this.status, | ||
| tries: tries ?? this.tries, | ||
| notes: notes != null ? notes.value : this.notes, | ||
| createdAt: createdAt ?? this.createdAt, | ||
| updatedAt: updatedAt ?? this.updatedAt, | ||
| ); | ||
| } | ||
|
|
||
| @override | ||
| bool operator ==(Object other) => | ||
| identical(this, other) || | ||
| other is FavoriteItem && | ||
| runtimeType == other.runtimeType && | ||
| id == other.id; | ||
|
|
||
| @override | ||
| int get hashCode => id.hashCode; | ||
|
Comment on lines
+114
to
+122
|
||
| } | ||
|
|
||
| /// Wrapper class for explicitly passing null values in copyWith methods. | ||
| class Optional<T> { | ||
| const Optional.value(this.value); | ||
|
|
||
| final T value; | ||
| } | ||
|
Comment on lines
+125
to
+147
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| export 'drink.dart'; | ||
| export 'favorite_item.dart'; | ||
| export 'festival.dart'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The status field uses string literals ('want_to_try' and 'tasted') instead of type-safe constants or an enum. This creates potential for typos and inconsistencies. Consider defining an enum or string constants for these values to improve type safety and maintainability. For example:
Or at minimum, define string constants in the FavoriteItem class.