mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-08-25 21:09:41 +00:00
Refactor calendar event loading: replace parameters with LoadEventsParam class and implement memory caching for improved performance
This commit is contained in:
@ -1,4 +1,5 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.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/services/api/api_exception.dart';
|
import 'package:syncrow_web/services/api/api_exception.dart';
|
||||||
@ -13,17 +14,17 @@ class RemoteCalendarService implements CalendarSystemService {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<CalendarEventsResponse> getCalendarEvents({
|
Future<CalendarEventsResponse> getCalendarEvents({
|
||||||
required String spaceId,
|
required LoadEventsParam params,
|
||||||
required String month,
|
|
||||||
required String year,
|
|
||||||
}) async {
|
}) async {
|
||||||
|
final month = params.startDate.month.toString().padLeft(2, '0');
|
||||||
|
final year = params.startDate.year.toString();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await _httpService.get<CalendarEventsResponse>(
|
return await _httpService.get<CalendarEventsResponse>(
|
||||||
path: ApiEndpoints.getBookings
|
path: ApiEndpoints.getBookings
|
||||||
.replaceAll('{mm}', month)
|
.replaceAll('{mm}', month)
|
||||||
.replaceAll('{yyyy}', year)
|
.replaceAll('{yyyy}', year)
|
||||||
.replaceAll('{space}', spaceId),
|
.replaceAll('{space}', params.id),
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
return CalendarEventsResponse.fromJson(json as Map<String, dynamic>);
|
return CalendarEventsResponse.fromJson(json as Map<String, dynamic>);
|
||||||
},
|
},
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
|
||||||
|
class LoadEventsParam extends Equatable {
|
||||||
|
final DateTime startDate;
|
||||||
|
final DateTime endDate;
|
||||||
|
final String id;
|
||||||
|
|
||||||
|
const LoadEventsParam({
|
||||||
|
required this.startDate,
|
||||||
|
required this.endDate,
|
||||||
|
required this.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object?> get props => [startDate, endDate, id];
|
||||||
|
|
||||||
|
LoadEventsParam copyWith({
|
||||||
|
DateTime? startDate,
|
||||||
|
DateTime? endDate,
|
||||||
|
String? id,
|
||||||
|
}) {
|
||||||
|
return LoadEventsParam(
|
||||||
|
startDate: startDate ?? this.startDate,
|
||||||
|
endDate: endDate ?? this.endDate,
|
||||||
|
id: id ?? this.id,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,8 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
abstract class CalendarSystemService {
|
abstract class CalendarSystemService {
|
||||||
Future<CalendarEventsResponse> getCalendarEvents({
|
Future<CalendarEventsResponse> getCalendarEvents({
|
||||||
required String spaceId,
|
required LoadEventsParam params,
|
||||||
required String month,
|
|
||||||
required String year,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,10 @@ import 'dart:async';
|
|||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:calendar_view/calendar_view.dart';
|
import 'package:calendar_view/calendar_view.dart';
|
||||||
import 'package:flutter/material.dart';
|
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/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';
|
||||||
part 'events_event.dart';
|
part 'events_event.dart';
|
||||||
part 'events_state.dart';
|
part 'events_state.dart';
|
||||||
|
|
||||||
@ -11,12 +13,14 @@ 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 Map<String, List<CalendarEventData>> _eventsCache = {};
|
||||||
|
final MemoryBookableSpaceService memoryService;
|
||||||
|
|
||||||
String? _lastSpaceId;
|
|
||||||
int? _lastMonth;
|
|
||||||
int? _lastYear;
|
|
||||||
|
|
||||||
CalendarEventsBloc({required this.calendarService}) : super(EventsInitial()) {
|
|
||||||
|
CalendarEventsBloc({
|
||||||
|
required this.calendarService,
|
||||||
|
required this.memoryService,
|
||||||
|
}) : super(EventsInitial()) {
|
||||||
on<LoadEvents>(_onLoadEvents);
|
on<LoadEvents>(_onLoadEvents);
|
||||||
on<AddEvent>(_onAddEvent);
|
on<AddEvent>(_onAddEvent);
|
||||||
on<DisposeResources>(_onDisposeResources);
|
on<DisposeResources>(_onDisposeResources);
|
||||||
@ -26,45 +30,32 @@ class CalendarEventsBloc extends Bloc<CalendarEventsEvent, CalendarEventState> {
|
|||||||
LoadEvents event,
|
LoadEvents event,
|
||||||
Emitter<CalendarEventState> emit,
|
Emitter<CalendarEventState> emit,
|
||||||
) async {
|
) async {
|
||||||
final month = event.weekEnd.month;
|
final param = event.param;
|
||||||
final year = event.weekEnd.year;
|
final month = param.endDate.month;
|
||||||
final cacheKey =
|
final year = param.endDate.year;
|
||||||
'${event.spaceId}-$year-${month.toString().padLeft(2, '0')}';
|
final spaceId = param.id;
|
||||||
|
final cachedEvents = memoryService.getEvents(spaceId, year, month);
|
||||||
if (_eventsCache.containsKey(cacheKey)) {
|
if (cachedEvents != null) {
|
||||||
final cachedEvents = _eventsCache[cacheKey]!;
|
|
||||||
eventController.addAll(cachedEvents);
|
eventController.addAll(cachedEvents);
|
||||||
emit(EventsLoaded(
|
emit(EventsLoaded(
|
||||||
events: cachedEvents,
|
events: cachedEvents,
|
||||||
spaceId: event.spaceId,
|
spaceId: spaceId,
|
||||||
month: month,
|
month: month,
|
||||||
year: year,
|
year: year,
|
||||||
));
|
));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (_lastSpaceId == event.spaceId &&
|
|
||||||
_lastMonth == month &&
|
|
||||||
_lastYear == year) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit(EventsLoading());
|
emit(EventsLoading());
|
||||||
try {
|
try {
|
||||||
final response = await calendarService.getCalendarEvents(
|
final response = await calendarService.getCalendarEvents(params: param);
|
||||||
month: month.toString().padLeft(2, '0'),
|
|
||||||
year: year.toString(),
|
|
||||||
spaceId: event.spaceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
final events = response.data.map(_toCalendarEventData).toList();
|
final events = response.data.map(_toCalendarEventData).toList();
|
||||||
_eventsCache[cacheKey] = events;
|
memoryService.setEvents(spaceId, year, month, events);
|
||||||
eventController.addAll(events);
|
eventController.addAll(events);
|
||||||
_lastSpaceId = event.spaceId;
|
|
||||||
_lastMonth = month;
|
|
||||||
_lastYear = year;
|
|
||||||
emit(EventsLoaded(
|
emit(EventsLoaded(
|
||||||
events: events,
|
events: events,
|
||||||
spaceId: event.spaceId,
|
spaceId: spaceId,
|
||||||
month: month,
|
month: month,
|
||||||
year: year,
|
year: year,
|
||||||
));
|
));
|
||||||
|
@ -6,17 +6,11 @@ abstract class CalendarEventsEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class LoadEvents extends CalendarEventsEvent {
|
class LoadEvents extends CalendarEventsEvent {
|
||||||
final String spaceId;
|
final LoadEventsParam param;
|
||||||
final DateTime weekStart;
|
const LoadEvents(this.param);
|
||||||
final DateTime weekEnd;
|
|
||||||
|
|
||||||
const LoadEvents({
|
|
||||||
required this.spaceId,
|
|
||||||
required this.weekStart,
|
|
||||||
required this.weekEnd,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class AddEvent extends CalendarEventsEvent {
|
class AddEvent extends CalendarEventsEvent {
|
||||||
final CalendarEventData event;
|
final CalendarEventData event;
|
||||||
const AddEvent(this.event);
|
const AddEvent(this.event);
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
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')}';
|
||||||
|
}
|
||||||
|
}
|
@ -2,11 +2,13 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:calendar_view/calendar_view.dart';
|
import 'package:calendar_view/calendar_view.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/booking_system/data/services/remote_calendar_service.dart';
|
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/presentation/bloc/calendar/events_bloc.dart';
|
import 'package:syncrow_web/pages/access_management/booking_system/presentation/bloc/calendar/events_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/booking_system/presentation/bloc/date_selection/date_selection_bloc.dart';
|
import 'package:syncrow_web/pages/access_management/booking_system/presentation/bloc/date_selection/date_selection_bloc.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_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/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';
|
||||||
@ -46,9 +48,11 @@ class _BookingPageState extends State<BookingPage> {
|
|||||||
if (selectedRoom != null) {
|
if (selectedRoom != null) {
|
||||||
context.read<CalendarEventsBloc>().add(
|
context.read<CalendarEventsBloc>().add(
|
||||||
LoadEvents(
|
LoadEvents(
|
||||||
spaceId: selectedRoom.uuid,
|
LoadEventsParam(
|
||||||
weekStart: dateState.weekStart,
|
startDate: dateState.weekStart,
|
||||||
weekEnd: dateState.weekStart.add(const Duration(days: 6)),
|
endDate: dateState.weekStart.add(const Duration(days: 6)),
|
||||||
|
id: selectedRoom.uuid,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -62,6 +66,7 @@ class _BookingPageState extends State<BookingPage> {
|
|||||||
BlocProvider(create: (_) => DateSelectionBloc()),
|
BlocProvider(create: (_) => DateSelectionBloc()),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => CalendarEventsBloc(
|
create: (_) => CalendarEventsBloc(
|
||||||
|
memoryService: MemoryBookableSpaceService(),
|
||||||
calendarService: RemoteCalendarService(
|
calendarService: RemoteCalendarService(
|
||||||
HTTPService(),
|
HTTPService(),
|
||||||
),
|
),
|
||||||
|
@ -24,7 +24,7 @@ class WeeklyCalendarPage extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
static const double timeLineWidth = 65;
|
static const double timeLineWidth = 65;
|
||||||
static const int totalDays = 7;
|
static const int totalDays = 7;
|
||||||
static const double dayColumnWidth = 220; // or any width you want
|
static const double dayColumnWidth = 220;
|
||||||
|
|
||||||
final double calendarContentWidth =
|
final double calendarContentWidth =
|
||||||
timeLineWidth + (totalDays * dayColumnWidth);
|
timeLineWidth + (totalDays * dayColumnWidth);
|
||||||
|
Reference in New Issue
Block a user