diff --git a/lib/pages/access_management/booking_system/presentation/bloc/calendar/events_bloc.dart b/lib/pages/access_management/booking_system/presentation/bloc/calendar/events_bloc.dart index b42947bd..59a1aa28 100644 --- a/lib/pages/access_management/booking_system/presentation/bloc/calendar/events_bloc.dart +++ b/lib/pages/access_management/booking_system/presentation/bloc/calendar/events_bloc.dart @@ -10,7 +10,7 @@ part 'events_event.dart'; part 'events_state.dart'; class CalendarEventsBloc extends Bloc { - final EventController eventController = EventController(); + EventController eventController = EventController(); final CalendarSystemService calendarService; CalendarEventsBloc({ @@ -20,7 +20,9 @@ class CalendarEventsBloc extends Bloc { on(_onAddEvent); on(_onDisposeResources); on(_onGoToWeek); + on(_onResetEvents); } + Future _onLoadEvents( LoadEvents event, Emitter emit, @@ -126,4 +128,18 @@ class CalendarEventsBloc extends Bloc { eventController.dispose(); return super.close(); } + + void _onResetEvents( + ResetEvents event, + Emitter emit, + ) { + if (calendarService is MemoryCalendarServiceWithRemoteFallback) { + (calendarService as MemoryCalendarServiceWithRemoteFallback) + .memoryService + .clear(); + } + eventController.dispose(); + eventController = EventController(); + emit(EventsInitial()); + } } diff --git a/lib/pages/access_management/booking_system/presentation/bloc/calendar/events_event.dart b/lib/pages/access_management/booking_system/presentation/bloc/calendar/events_event.dart index 6a368e17..ecd7f975 100644 --- a/lib/pages/access_management/booking_system/presentation/bloc/calendar/events_event.dart +++ b/lib/pages/access_management/booking_system/presentation/bloc/calendar/events_event.dart @@ -29,3 +29,10 @@ class CheckWeekHasEvents extends CalendarEventsEvent { final DateTime weekStart; const CheckWeekHasEvents(this.weekStart); } + +class ResetEvents extends CalendarEventsEvent { + const ResetEvents(); + + @override + List get props => []; +} \ No newline at end of file diff --git a/lib/pages/access_management/booking_system/presentation/view/booking_page.dart b/lib/pages/access_management/booking_system/presentation/view/booking_page.dart index aac5c5b7..68934ddc 100644 --- a/lib/pages/access_management/booking_system/presentation/view/booking_page.dart +++ b/lib/pages/access_management/booking_system/presentation/view/booking_page.dart @@ -1,3 +1,4 @@ +// booking_page.dart import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:calendar_view/calendar_view.dart'; @@ -26,7 +27,33 @@ class BookingPage extends StatefulWidget { } class _BookingPageState extends State { - late final EventController _eventController; + @override + Widget build(BuildContext context) { + return MultiBlocProvider( + providers: [ + BlocProvider(create: (_) => SelectedBookableSpaceBloc()), + BlocProvider(create: (_) => DateSelectionBloc()), + BlocProvider( + create: (_) => CalendarEventsBloc( + calendarService: MemoryCalendarServiceWithRemoteFallback( + remoteService: RemoteCalendarService(HTTPService()), + memoryService: MemoryCalendarService(), + ), + ), + ), + ], + child: _BookingPageContent(), + ); + } +} + +class _BookingPageContent extends StatefulWidget { + @override + State<_BookingPageContent> createState() => _BookingPageContentState(); +} + +class _BookingPageContentState extends State<_BookingPageContent> { + late EventController _eventController; @override void initState() { @@ -40,7 +67,7 @@ class _BookingPageState extends State { super.dispose(); } - void _dispatchLoadEvents(BuildContext context) { + void _loadEvents(BuildContext context) { final selectedRoom = context.read().state.selectedBookableSpace; final dateState = context.read().state; @@ -60,186 +87,170 @@ class _BookingPageState extends State { @override Widget build(BuildContext context) { - return MultiBlocProvider( - providers: [ - BlocProvider(create: (_) => SelectedBookableSpaceBloc()), - BlocProvider(create: (_) => DateSelectionBloc()), - BlocProvider( - create: (_) => CalendarEventsBloc( - calendarService: MemoryCalendarServiceWithRemoteFallback( - remoteService: RemoteCalendarService( - HTTPService(), - ), - memoryService: MemoryCalendarService(), - ), - )), - ], - child: Builder( - builder: (context) => - BlocListener( - listenWhen: (prev, curr) => curr is EventsLoaded, + return BlocListener( + listener: (context, state) { + if (state.selectedBookableSpace != null) { + // Reset events and clear cache when room changes + context.read().add(ResetEvents()); + _loadEvents(context); + } + }, + child: BlocListener( + listener: (context, state) { + _loadEvents(context); + }, + child: BlocListener( listener: (context, state) { if (state is EventsLoaded) { _eventController.removeWhere((_) => true); _eventController.addAll(state.events); } }, - child: BlocListener( - listener: (context, state) => _dispatchLoadEvents(context), - child: BlocListener( - listener: (context, state) => _dispatchLoadEvents(context), - child: Row( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Container( - decoration: BoxDecoration( - color: ColorsManager.whiteColors, - boxShadow: [ - BoxShadow( - color: ColorsManager.blackColor.withOpacity(0.1), - offset: const Offset(3, 0), - blurRadius: 6, - spreadRadius: 0, - ), - ], + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Container( + decoration: BoxDecoration( + color: ColorsManager.whiteColors, + boxShadow: [ + BoxShadow( + color: ColorsManager.blackColor.withOpacity(0.1), + offset: const Offset(3, 0), + blurRadius: 6, + spreadRadius: 0, ), - child: Column( - children: [ - Expanded( - flex: 2, - child: BlocBuilder( - builder: (context, state) { - return BookingSidebar( - onRoomSelected: (selectedRoom) { - context - .read() - .add(SelectBookableSpace(selectedRoom)); - }, - ); - }, - ), - ), - Expanded( - child: BlocBuilder( - builder: (context, dateState) { - return CustomCalendarPage( - selectedDate: dateState.selectedDate, - onDateChanged: (day, month, year) { - final newDate = DateTime(year, month, day); - context - .read() - .add(SelectDate(newDate)); - context.read().add( - SelectDateFromSidebarCalendar(newDate)); - }, - ); - }, - ), - ), - ], - ), - ), + ], ), - Expanded( - flex: 5, - child: Padding( - padding: const EdgeInsets.all(20.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, + child: Column( + children: [ + Expanded( + flex: 2, + child: BlocBuilder( + builder: (context, state) { + return BookingSidebar( + onRoomSelected: (selectedRoom) { + context + .read() + .add(SelectBookableSpace(selectedRoom)); + }, + ); + }, + ), + ), + Expanded( + child: + BlocBuilder( + builder: (context, dateState) { + return CustomCalendarPage( + selectedDate: dateState.selectedDate, + onDateChanged: (day, month, year) { + final newDate = DateTime(year, month, day); + context + .read() + .add(SelectDate(newDate)); + context.read().add( + SelectDateFromSidebarCalendar(newDate)); + }, + ); + }, + ), + ), + ], + ), + ), + ), + Expanded( + flex: 5, + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Row( - children: [ - SvgTextButton( - svgAsset: Assets.homeIcon, - label: 'Manage Bookable Spaces', - onPressed: () {}, - ), - const SizedBox(width: 20), - SvgTextButton( - svgAsset: Assets.groupIcon, - label: 'Manage Users', - onPressed: () {}, - ), - ], + SvgTextButton( + svgAsset: Assets.homeIcon, + label: 'Manage Bookable Spaces', + onPressed: () {}, ), - BlocBuilder( - builder: (context, state) { - final weekStart = state.weekStart; - final weekEnd = - weekStart.add(const Duration(days: 6)); - return WeekNavigation( - weekStart: weekStart, - weekEnd: weekEnd, - onPreviousWeek: () { - context - .read() - .add(PreviousWeek()); - }, - onNextWeek: () { - context - .read() - .add(NextWeek()); - }, - ); - }, + const SizedBox(width: 20), + SvgTextButton( + svgAsset: Assets.groupIcon, + label: 'Manage Users', + onPressed: () {}, ), ], ), - Expanded( - flex: 5, - child: BlocBuilder( - builder: (context, roomState) { - final selectedRoom = - roomState.selectedBookableSpace; - return BlocBuilder( - builder: (context, dateState) { - return BlocListener( - listenWhen: (prev, curr) => - curr is EventsLoaded, - listener: (context, state) { - if (state is EventsLoaded) { - _eventController - .removeWhere((_) => true); - _eventController.addAll(state.events); - } - }, - child: WeeklyCalendarPage( - startTime: selectedRoom - ?.bookableConfig.startTime, - endTime: selectedRoom - ?.bookableConfig.endTime, - weekStart: dateState.weekStart, - selectedDate: dateState.selectedDate, - eventController: _eventController, - selectedDateFromSideBarCalender: context - .watch() - .state - .selectedDateFromSideBarCalender, - ), + BlocBuilder( + builder: (context, state) { + final weekStart = state.weekStart; + final weekEnd = + weekStart.add(const Duration(days: 6)); + return WeekNavigation( + weekStart: weekStart, + weekEnd: weekEnd, + onPreviousWeek: () { + context + .read() + .add(PreviousWeek()); + }, + onNextWeek: () { + context + .read() + .add(NextWeek()); + }, + ); + }, + ), + ], + ), + const SizedBox(height: 20), + Expanded( + flex: 5, + child: BlocBuilder( + builder: (context, roomState) { + final selectedRoom = + roomState.selectedBookableSpace; + return BlocBuilder( + builder: (context, dateState) { + return BlocBuilder( + builder: (context, eventState) { + return WeeklyCalendarPage( + key: ValueKey( + selectedRoom?.uuid ?? 'no-room'), + startTime: selectedRoom + ?.bookableConfig.startTime, + endTime: + selectedRoom?.bookableConfig.endTime, + weekStart: dateState.weekStart, + selectedDate: dateState.selectedDate, + eventController: _eventController, + selectedDateFromSideBarCalender: context + .watch() + .state + .selectedDateFromSideBarCalender, + // isLoading: eventState is EventsLoading, ); }, ); }, - ), - ), - ], + ); + }, + ), ), - ), + ], ), - ], + ), ), - ), + ], ), ), ), diff --git a/lib/pages/access_management/booking_system/presentation/view/widgets/booking_sidebar.dart b/lib/pages/access_management/booking_system/presentation/view/widgets/booking_sidebar.dart index 666df3bb..bd051a94 100644 --- a/lib/pages/access_management/booking_system/presentation/view/widgets/booking_sidebar.dart +++ b/lib/pages/access_management/booking_system/presentation/view/widgets/booking_sidebar.dart @@ -76,21 +76,29 @@ class __SidebarContentState extends State<_SidebarContent> { builder: (context, state) { return Column( children: [ - const _SidebarHeader(title: 'Spaces'), + Padding( + padding: const EdgeInsets.only(top: 10.0, bottom: 10.0), + child: Container( + decoration: BoxDecoration( + color: ColorsManager.whiteColors, + boxShadow: [ + BoxShadow( + color: ColorsManager.blackColor.withOpacity(0.1), + offset: const Offset(0, 4), + blurRadius: 4, + spreadRadius: 0, + ), + ], + ), + child: _SidebarHeader(title: 'Spaces')), + ), Container( decoration: BoxDecoration( color: ColorsManager.whiteColors, - borderRadius: BorderRadius.circular(8.0), boxShadow: [ BoxShadow( color: ColorsManager.blackColor.withOpacity(0.1), - offset: const Offset(0, -2), - blurRadius: 4, - spreadRadius: 0, - ), - BoxShadow( - color: ColorsManager.blackColor.withOpacity(0.1), - offset: const Offset(0, 2), + offset: const Offset(0, 4), blurRadius: 4, spreadRadius: 0, ), @@ -220,7 +228,7 @@ class _SidebarHeader extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.all(16.0), + padding: const EdgeInsets.all(10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ diff --git a/lib/pages/access_management/booking_system/presentation/view/widgets/custom_calendar_page.dart b/lib/pages/access_management/booking_system/presentation/view/widgets/custom_calendar_page.dart index eb758311..21dfe646 100644 --- a/lib/pages/access_management/booking_system/presentation/view/widgets/custom_calendar_page.dart +++ b/lib/pages/access_management/booking_system/presentation/view/widgets/custom_calendar_page.dart @@ -66,18 +66,28 @@ class _CustomCalendarPageState extends State { weekdayLabels: const ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'], ); - return CalendarDatePicker2( - config: config, - value: [_selectedDate], - onValueChanged: (dates) { - final picked = dates.first; - if (picked != null) { - setState(() { - _selectedDate = picked; - }); - widget.onDateChanged(picked.day, picked.month, picked.year); - } - }, + return Container( + decoration: const BoxDecoration( + border: Border( + top: BorderSide( + color: ColorsManager.textGray, + width: 1.0, + ), + ), + ), + child: CalendarDatePicker2( + config: config, + value: [_selectedDate], + onValueChanged: (dates) { + final picked = dates.first; + if (picked != null) { + setState(() { + _selectedDate = picked; + }); + widget.onDateChanged(picked.day, picked.month, picked.year); + } + }, + ), ); } } diff --git a/lib/pages/access_management/booking_system/presentation/view/widgets/event_tile_widget.dart b/lib/pages/access_management/booking_system/presentation/view/widgets/event_tile_widget.dart index b7e942d6..87c10a81 100644 --- a/lib/pages/access_management/booking_system/presentation/view/widgets/event_tile_widget.dart +++ b/lib/pages/access_management/booking_system/presentation/view/widgets/event_tile_widget.dart @@ -32,15 +32,17 @@ class EventTileWidget extends StatelessWidget { return Expanded( child: Container( width: double.infinity, - padding: EdgeInsets.all(5), + padding: const EdgeInsets.all(5), decoration: BoxDecoration( color: isEventEnded ? ColorsManager.grayColor.withOpacity(0.1) : ColorsManager.blue1.withOpacity(0.1), borderRadius: BorderRadius.circular(6), - border: const Border( + border: Border( left: BorderSide( - color: ColorsManager.grayColor, + color: isEventEnded + ? ColorsManager.grayColor + : ColorsManager.secondaryColor, width: 4, ), ), diff --git a/lib/pages/access_management/booking_system/presentation/view/widgets/room_list_item.dart b/lib/pages/access_management/booking_system/presentation/view/widgets/room_list_item.dart index 83eda16b..57a14002 100644 --- a/lib/pages/access_management/booking_system/presentation/view/widgets/room_list_item.dart +++ b/lib/pages/access_management/booking_system/presentation/view/widgets/room_list_item.dart @@ -21,7 +21,7 @@ class RoomListItem extends StatelessWidget { groupValue: isSelected ? room.uuid : null, visualDensity: const VisualDensity(vertical: -4), onChanged: (value) => onTap(), - activeColor: ColorsManager.primaryColor, + activeColor: ColorsManager.secondaryColor, title: Text( room.spaceName, maxLines: 2, diff --git a/lib/pages/access_management/booking_system/presentation/view/widgets/week_day_header.dart b/lib/pages/access_management/booking_system/presentation/view/widgets/week_day_header.dart index 57e35c6d..325ce582 100644 --- a/lib/pages/access_management/booking_system/presentation/view/widgets/week_day_header.dart +++ b/lib/pages/access_management/booking_system/presentation/view/widgets/week_day_header.dart @@ -14,26 +14,33 @@ class WeekDayHeader extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( - children: [ - Text( - DateFormat('EEE').format(date).toUpperCase(), - style: TextStyle( - fontWeight: FontWeight.w400, - fontSize: 14, - color: isSelectedDay ? Colors.blue : Colors.black, + return ColoredBox( + color: isSelectedDay + ? ColorsManager.secondaryColor.withOpacity(0.1) + : Colors.transparent, + child: Column( + children: [ + const SizedBox( + height: 10, ), - ), - Text( - DateFormat('d').format(date), - style: TextStyle( - fontWeight: FontWeight.w700, - fontSize: 20, - color: - isSelectedDay ? ColorsManager.blue1 : ColorsManager.blackColor, + Text( + DateFormat('EEE').format(date).toUpperCase(), + style: const TextStyle( + fontWeight: FontWeight.w400, + fontSize: 14, + color: ColorsManager.blackColor, + ), ), - ), - ], + Text( + DateFormat('d').format(date), + style: const TextStyle( + fontWeight: FontWeight.w700, + fontSize: 30, + color: ColorsManager.blackColor, + ), + ), + ], + ), ); } } diff --git a/lib/pages/access_management/booking_system/presentation/view/widgets/weekly_calendar_page.dart b/lib/pages/access_management/booking_system/presentation/view/widgets/weekly_calendar_page.dart index 2bfd5429..931746b7 100644 --- a/lib/pages/access_management/booking_system/presentation/view/widgets/weekly_calendar_page.dart +++ b/lib/pages/access_management/booking_system/presentation/view/widgets/weekly_calendar_page.dart @@ -24,7 +24,7 @@ class WeeklyCalendarPage extends StatelessWidget { }); static const double timeLineWidth = 65; static const int totalDays = 7; - static const double dayColumnWidth = 220; + static const double dayColumnWidth = 220; final double calendarContentWidth = timeLineWidth + (totalDays * dayColumnWidth); @@ -57,13 +57,10 @@ class WeeklyCalendarPage extends StatelessWidget { ); } - - - const double timeLineWidth = 65; + const double timeLineWidth = 90; return LayoutBuilder( builder: (context, constraints) { - bool isInRange(DateTime date, DateTime start, DateTime end) { !date.isBefore(start) && !date.isAfter(end); // remove this line and Check if the date is within the range @@ -100,7 +97,6 @@ class WeeklyCalendarPage extends StatelessWidget { width: width, decoration: BoxDecoration( color: Colors.orange.withOpacity(0.13), - borderRadius: BorderRadius.circular(8), ), ); } else if (isSelected) { @@ -110,7 +106,6 @@ class WeeklyCalendarPage extends StatelessWidget { decoration: BoxDecoration( color: ColorsManager.spaceColor.withOpacity(0.07), - borderRadius: BorderRadius.circular(8), ), ); } @@ -143,7 +138,7 @@ class WeeklyCalendarPage extends StatelessWidget { heightPerMinute: 1.7, showLiveTimeLineInAllDays: false, showVerticalLines: true, - emulateVerticalOffsetBy: -80, + emulateVerticalOffsetBy: -95, startDay: WeekDays.monday, liveTimeIndicatorSettings: const LiveTimeIndicatorSettings( @@ -161,7 +156,7 @@ class WeeklyCalendarPage extends StatelessWidget { }, timeLineWidth: timeLineWidth, weekPageHeaderBuilder: (start, end) => Container(), - weekTitleHeight: 60, + weekTitleHeight: 90, weekNumberBuilder: (firstDayOfWeek) => Padding( padding: const EdgeInsets.only(right: 15, bottom: 10), child: Column( @@ -208,8 +203,6 @@ class WeeklyCalendarPage extends StatelessWidget { }, ); } - - } bool isSameDay(DateTime d1, DateTime d2) { diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index e99f4796..a53582be 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -140,6 +140,5 @@ abstract class ApiEndpoints { static const String saveSchedule = '/schedule/{deviceUuid}'; static const String getBookableSpaces = '/bookable-spaces'; - static const String getBookings = - '/bookings?month={mm}%2F{yyyy}&space={space}'; + static const String getBookings = '/bookings?month={mm}-{yyyy}&space={space}'; }