Refactor memory event handling: replace MemoryBookableSpaceService with a new implementation and integrate caching logic in CalendarEventsBloc

This commit is contained in:
mohammad
2025-07-17 12:38:58 +03:00
parent c9b8fbb0c2
commit fe2f4a872b
5 changed files with 79 additions and 70 deletions

View File

@ -0,0 +1,63 @@
import 'package:syncrow_web/pages/access_management/booking_system/data/services/remote_calendar_service.dart';
import 'package:syncrow_web/pages/access_management/booking_system/domain/LoadEventsParam.dart';
import 'package:syncrow_web/pages/access_management/booking_system/domain/models/calendar_event_booking.dart';
import 'package:syncrow_web/pages/access_management/booking_system/domain/services/calendar_system_service.dart';
class MemoryBookableSpaceService implements CalendarSystemService {
final Map<String, CalendarEventsResponse> _eventsCache = {};
@override
Future<CalendarEventsResponse> getCalendarEvents({
required LoadEventsParam params,
}) async {
final key = params.generateKey();
return _eventsCache[key]!;
}
void setEvents(
LoadEventsParam param,
CalendarEventsResponse events,
) {
final key = param.generateKey();
_eventsCache[key] = events;
}
void addEvent(LoadEventsParam param, CalendarEventsResponse event) {
final key = param.generateKey();
_eventsCache[key] = event;
}
void clear() {
_eventsCache.clear();
}
}
class MemoryCalendarServiceWithRemoteFallback implements CalendarSystemService {
final MemoryBookableSpaceService memoryService;
final RemoteCalendarService remoteService;
MemoryCalendarServiceWithRemoteFallback({
required this.memoryService,
required this.remoteService,
});
@override
Future<CalendarEventsResponse> getCalendarEvents({
required LoadEventsParam params,
}) async {
final key = params.generateKey();
final doesExistInMemory = memoryService._eventsCache.containsKey(key);
if (doesExistInMemory) {
return memoryService.getCalendarEvents(params: params);
} else {
final remoteResult =
await remoteService.getCalendarEvents(params: params);
memoryService.setEvents(params, remoteResult);
return remoteResult;
}
}
}

View File

@ -26,3 +26,9 @@ class LoadEventsParam extends Equatable {
); );
} }
} }
extension KeyGenerator on LoadEventsParam {
String generateKey() {
return '$id-${startDate.year}-${startDate.month.toString().padLeft(2, '0')}';
}
}

View File

@ -5,21 +5,16 @@ import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/access_management/booking_system/domain/LoadEventsParam.dart'; import 'package:syncrow_web/pages/access_management/booking_system/domain/LoadEventsParam.dart';
import 'package:syncrow_web/pages/access_management/booking_system/domain/models/calendar_event_booking.dart'; import 'package:syncrow_web/pages/access_management/booking_system/domain/models/calendar_event_booking.dart';
import 'package:syncrow_web/pages/access_management/booking_system/domain/services/calendar_system_service.dart'; import 'package:syncrow_web/pages/access_management/booking_system/domain/services/calendar_system_service.dart';
import 'package:syncrow_web/pages/access_management/booking_system/presentation/model/memory_bookable_space_service.dart'; import 'package:syncrow_web/pages/access_management/booking_system/data/services/memory_bookable_space_service.dart';
part 'events_event.dart'; part 'events_event.dart';
part 'events_state.dart'; part 'events_state.dart';
class CalendarEventsBloc extends Bloc<CalendarEventsEvent, CalendarEventState> { class CalendarEventsBloc extends Bloc<CalendarEventsEvent, CalendarEventState> {
final EventController eventController = EventController(); final EventController eventController = EventController();
final CalendarSystemService calendarService; final CalendarSystemService calendarService;
final Map<String, List<CalendarEventData>> _eventsCache = {};
final MemoryBookableSpaceService memoryService;
CalendarEventsBloc({ CalendarEventsBloc({
required this.calendarService, required this.calendarService,
required this.memoryService,
}) : super(EventsInitial()) { }) : super(EventsInitial()) {
on<LoadEvents>(_onLoadEvents); on<LoadEvents>(_onLoadEvents);
on<AddEvent>(_onAddEvent); on<AddEvent>(_onAddEvent);
@ -34,24 +29,12 @@ class CalendarEventsBloc extends Bloc<CalendarEventsEvent, CalendarEventState> {
final month = param.endDate.month; final month = param.endDate.month;
final year = param.endDate.year; final year = param.endDate.year;
final spaceId = param.id; final spaceId = param.id;
final cachedEvents = memoryService.getEvents(spaceId, year, month);
if (cachedEvents != null) {
eventController.addAll(cachedEvents);
emit(EventsLoaded(
events: cachedEvents,
spaceId: spaceId,
month: month,
year: year,
));
return;
}
emit(EventsLoading()); emit(EventsLoading());
try { try {
final response = await calendarService.getCalendarEvents(params: param); final response = await calendarService.getCalendarEvents(params: param);
final events = response.data.map(_toCalendarEventData).toList(); final events = response.data.map(_toCalendarEventData).toList();
memoryService.setEvents(spaceId, year, month, events);
eventController.addAll(events); eventController.addAll(events);
emit(EventsLoaded( emit(EventsLoaded(
events: events, events: events,
@ -69,15 +52,6 @@ class CalendarEventsBloc extends Bloc<CalendarEventsEvent, CalendarEventState> {
if (state is EventsLoaded) { if (state is EventsLoaded) {
final loaded = state as EventsLoaded; final loaded = state as EventsLoaded;
final cacheKey =
'${loaded.spaceId}-${loaded.year}-${loaded.month.toString().padLeft(2, '0')}';
if (_eventsCache.containsKey(cacheKey)) {
final cachedEvents =
List<CalendarEventData>.from(_eventsCache[cacheKey]!);
cachedEvents.add(event.event);
_eventsCache[cacheKey] = cachedEvents;
}
emit(EventsLoaded( emit(EventsLoaded(
events: [...eventController.events], events: [...eventController.events],

View File

@ -1,35 +0,0 @@
import 'package:calendar_view/calendar_view.dart';
class MemoryBookableSpaceService {
final Map<String, List<CalendarEventData>> _eventsCache = {};
List<CalendarEventData>? getEvents(String spaceId, int year, int month) {
final key = _generateKey(spaceId, year, month);
return _eventsCache[key];
}
void setEvents(
String spaceId,
int year,
int month,
List<CalendarEventData> events,
) {
final key = _generateKey(spaceId, year, month);
_eventsCache[key] = events;
}
void addEvent(String spaceId, int year, int month, CalendarEventData event) {
final key = _generateKey(spaceId, year, month);
final events = _eventsCache[key] ?? [];
events.add(event);
_eventsCache[key] = events;
}
void clear() {
_eventsCache.clear();
}
String _generateKey(String spaceId, int year, int month) {
return '$spaceId-$year-${month.toString().padLeft(2, '0')}';
}
}

View File

@ -8,7 +8,7 @@ import 'package:syncrow_web/pages/access_management/booking_system/presentation/
import 'package:syncrow_web/pages/access_management/booking_system/presentation/bloc/date_selection/date_selection_event.dart'; import 'package:syncrow_web/pages/access_management/booking_system/presentation/bloc/date_selection/date_selection_event.dart';
import 'package:syncrow_web/pages/access_management/booking_system/presentation/bloc/date_selection/date_selection_state.dart'; import 'package:syncrow_web/pages/access_management/booking_system/presentation/bloc/date_selection/date_selection_state.dart';
import 'package:syncrow_web/pages/access_management/booking_system/presentation/bloc/selected_bookable_space_bloc/selected_bookable_space_bloc.dart'; import 'package:syncrow_web/pages/access_management/booking_system/presentation/bloc/selected_bookable_space_bloc/selected_bookable_space_bloc.dart';
import 'package:syncrow_web/pages/access_management/booking_system/presentation/model/memory_bookable_space_service.dart'; import 'package:syncrow_web/pages/access_management/booking_system/data/services/memory_bookable_space_service.dart';
import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/booking_sidebar.dart'; import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/booking_sidebar.dart';
import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/custom_calendar_page.dart'; import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/custom_calendar_page.dart';
import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/icon_text_button.dart'; import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/icon_text_button.dart';
@ -65,13 +65,14 @@ class _BookingPageState extends State<BookingPage> {
BlocProvider(create: (_) => SelectedBookableSpaceBloc()), BlocProvider(create: (_) => SelectedBookableSpaceBloc()),
BlocProvider(create: (_) => DateSelectionBloc()), BlocProvider(create: (_) => DateSelectionBloc()),
BlocProvider( BlocProvider(
create: (_) => CalendarEventsBloc( create: (_) => CalendarEventsBloc(
memoryService: MemoryBookableSpaceService(), calendarService: MemoryCalendarServiceWithRemoteFallback(
calendarService: RemoteCalendarService( remoteService: RemoteCalendarService(
HTTPService(), HTTPService(),
), ),
), memoryService: MemoryBookableSpaceService(),
), ),
)),
], ],
child: Builder( child: Builder(
builder: (context) => builder: (context) =>