Files
TravelMate/lib/blocs/activity/activity_state.dart
Dayron 8ff9e12fd4 feat: Implement activity management feature with Firestore integration
- Added AddActivityBottomSheet for adding custom activities to trips.
- Created Activity model to represent tourist activities.
- Developed ActivityRepository for managing activities in Firestore.
- Integrated ActivityPlacesService for searching activities via Google Places API.
- Updated ShowTripDetailsContent to navigate to activities page.
- Enhanced main.dart to include ActivityBloc and necessary repositories.
2025-11-03 16:40:33 +01:00

240 lines
5.7 KiB
Dart

import 'package:equatable/equatable.dart';
import '../../models/activity.dart';
/// Base class for all activity-related states
abstract class ActivityState extends Equatable {
const ActivityState();
@override
List<Object?> get props => [];
}
/// Initial state when no activities have been loaded
class ActivityInitial extends ActivityState {
const ActivityInitial();
}
/// State when activities are being loaded
class ActivityLoading extends ActivityState {
const ActivityLoading();
}
/// State when activities are being searched
class ActivitySearching extends ActivityState {
const ActivitySearching();
}
/// State when activities have been loaded successfully
class ActivityLoaded extends ActivityState {
final List<Activity> activities;
final List<Activity> filteredActivities;
final String? activeFilter;
final double? minRating;
final bool showVotedOnly;
const ActivityLoaded({
required this.activities,
required this.filteredActivities,
this.activeFilter,
this.minRating,
this.showVotedOnly = false,
});
@override
List<Object?> get props => [
activities,
filteredActivities,
activeFilter,
minRating,
showVotedOnly,
];
/// Creates a copy of the current state with optional modifications
ActivityLoaded copyWith({
List<Activity>? activities,
List<Activity>? filteredActivities,
String? activeFilter,
double? minRating,
bool? showVotedOnly,
}) {
return ActivityLoaded(
activities: activities ?? this.activities,
filteredActivities: filteredActivities ?? this.filteredActivities,
activeFilter: activeFilter ?? this.activeFilter,
minRating: minRating ?? this.minRating,
showVotedOnly: showVotedOnly ?? this.showVotedOnly,
);
}
/// Gets activities by category
List<Activity> getActivitiesByCategory(String category) {
return activities.where((activity) => activity.category == category).toList();
}
/// Gets top rated activities
List<Activity> getTopRatedActivities({int limit = 10}) {
final sorted = List<Activity>.from(activities);
sorted.sort((a, b) {
final aScore = a.totalVotes;
final bScore = b.totalVotes;
if (aScore != bScore) {
return bScore.compareTo(aScore);
}
return (b.rating ?? 0).compareTo(a.rating ?? 0);
});
return sorted.take(limit).toList();
}
}
/// State when search results are available
class ActivitySearchResults extends ActivityState {
final List<Activity> searchResults;
final String query;
final bool isLoading;
const ActivitySearchResults({
required this.searchResults,
required this.query,
this.isLoading = false,
});
@override
List<Object> get props => [searchResults, query, isLoading];
/// Creates a copy with optional modifications
ActivitySearchResults copyWith({
List<Activity>? searchResults,
String? query,
bool? isLoading,
}) {
return ActivitySearchResults(
searchResults: searchResults ?? this.searchResults,
query: query ?? this.query,
isLoading: isLoading ?? this.isLoading,
);
}
}
/// State when an operation has completed successfully
class ActivityOperationSuccess extends ActivityState {
final String message;
final String? operationType;
const ActivityOperationSuccess(
this.message, {
this.operationType,
});
@override
List<Object?> get props => [message, operationType];
}
/// State when an error has occurred
class ActivityError extends ActivityState {
final String message;
final String? errorCode;
final dynamic error;
const ActivityError(
this.message, {
this.errorCode,
this.error,
});
@override
List<Object?> get props => [message, errorCode, error];
}
/// State when voting is in progress
class ActivityVoting extends ActivityState {
final String activityId;
final List<Activity> activities;
const ActivityVoting({
required this.activityId,
required this.activities,
});
@override
List<Object> get props => [activityId, activities];
}
/// State when activity is being updated
class ActivityUpdating extends ActivityState {
final String activityId;
final List<Activity> activities;
const ActivityUpdating({
required this.activityId,
required this.activities,
});
@override
List<Object> get props => [activityId, activities];
}
/// State when activities are being added in batch
class ActivityBatchAdding extends ActivityState {
final List<Activity> activitiesToAdd;
final int progress;
final int total;
const ActivityBatchAdding({
required this.activitiesToAdd,
required this.progress,
required this.total,
});
@override
List<Object> get props => [activitiesToAdd, progress, total];
/// Gets the progress as a percentage
double get progressPercentage => total > 0 ? progress / total : 0.0;
}
/// State when an activity has been successfully added
class ActivityAdded extends ActivityState {
final Activity activity;
final String message;
const ActivityAdded({
required this.activity,
required this.message,
});
@override
List<Object> get props => [activity, message];
}
/// State when an activity has been successfully deleted
class ActivityDeleted extends ActivityState {
final String activityId;
final String message;
const ActivityDeleted({
required this.activityId,
required this.message,
});
@override
List<Object> get props => [activityId, message];
}
/// State when vote has been successfully recorded
class ActivityVoteRecorded extends ActivityState {
final String activityId;
final int vote;
final String userId;
const ActivityVoteRecorded({
required this.activityId,
required this.vote,
required this.userId,
});
@override
List<Object> get props => [activityId, vote, userId];
}