mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-11-26 12:24:55 +00:00
Compare commits
2 Commits
enhancemen
...
fix-schedu
| Author | SHA1 | Date | |
|---|---|---|---|
| d3bd363b70 | |||
| 076c80fe44 |
@ -1,63 +0,0 @@
|
|||||||
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 MemoryCalendarService 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 MemoryCalendarService 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,5 +1,4 @@
|
|||||||
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';
|
||||||
@ -14,21 +13,147 @@ class RemoteCalendarService implements CalendarSystemService {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Future<CalendarEventsResponse> getCalendarEvents({
|
Future<CalendarEventsResponse> getCalendarEvents({
|
||||||
required LoadEventsParam params,
|
required String spaceId,
|
||||||
}) async {
|
}) async {
|
||||||
final month = params.startDate.month.toString().padLeft(2, '0');
|
|
||||||
final year = params.startDate.year.toString();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await _httpService.get<CalendarEventsResponse>(
|
final response = await _httpService.get(
|
||||||
path: ApiEndpoints.getBookings
|
path: ApiEndpoints.getCalendarEvents,
|
||||||
.replaceAll('{mm}', month)
|
queryParameters: {
|
||||||
.replaceAll('{yyyy}', year)
|
'spaceId': 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>,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return CalendarEventsResponse.fromJson(response as Map<String, dynamic>);
|
||||||
|
} on DioException catch (e) {
|
||||||
|
final responseData = e.response?.data;
|
||||||
|
if (responseData is Map<String, dynamic>) {
|
||||||
|
final errorMessage = responseData['error']?['message'] as String? ??
|
||||||
|
responseData['message'] as String? ??
|
||||||
|
_defaultErrorMessage;
|
||||||
|
throw APIException(errorMessage);
|
||||||
|
}
|
||||||
|
throw APIException(_defaultErrorMessage);
|
||||||
|
} catch (e) {
|
||||||
|
throw APIException('$_defaultErrorMessage: ${e.toString()}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeRemoteCalendarService implements CalendarSystemService {
|
||||||
|
const FakeRemoteCalendarService(this._httpService, {this.useDummy = false});
|
||||||
|
|
||||||
|
final HTTPService _httpService;
|
||||||
|
final bool useDummy;
|
||||||
|
static const _defaultErrorMessage = 'Failed to load Calendar';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<CalendarEventsResponse> getCalendarEvents({
|
||||||
|
required String spaceId,
|
||||||
|
}) async {
|
||||||
|
if (useDummy) {
|
||||||
|
final dummyJson = {
|
||||||
|
'statusCode': 200,
|
||||||
|
'message': 'Successfully fetched all bookings',
|
||||||
|
'data': [
|
||||||
|
{
|
||||||
|
'uuid': 'd4553fa6-a0c9-4f42-81c9-99a13a57bf80',
|
||||||
|
'date': '2025-07-11T10:22:00.626Z',
|
||||||
|
'startTime': '09:00:00',
|
||||||
|
'endTime': '12:00:00',
|
||||||
|
'cost': 10,
|
||||||
|
'user': {
|
||||||
|
'uuid': '784394ff-3197-4c39-9f07-48dc44920b1e',
|
||||||
|
'firstName': 'salsabeel',
|
||||||
|
'lastName': 'abuzaid',
|
||||||
|
'email': 'test@test.com',
|
||||||
|
'companyName': null
|
||||||
|
},
|
||||||
|
'space': {
|
||||||
|
'uuid': '000f4d81-43e4-4ad7-865c-0f8b04b7081e',
|
||||||
|
'spaceName': '2(1)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'uuid': 'e9b27af0-b963-4d98-9657-454c4ba78561',
|
||||||
|
'date': '2025-07-11T10:22:00.626Z',
|
||||||
|
'startTime': '12:00:00',
|
||||||
|
'endTime': '13:00:00',
|
||||||
|
'cost': 10,
|
||||||
|
'user': {
|
||||||
|
'uuid': '784394ff-3197-4c39-9f07-48dc44920b1e',
|
||||||
|
'firstName': 'salsabeel',
|
||||||
|
'lastName': 'abuzaid',
|
||||||
|
'email': 'test@test.com',
|
||||||
|
'companyName': null
|
||||||
|
},
|
||||||
|
'space': {
|
||||||
|
'uuid': '000f4d81-43e4-4ad7-865c-0f8b04b7081e',
|
||||||
|
'spaceName': '2(1)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'uuid': 'e9b27af0-b963-4d98-9657-454c4ba78561',
|
||||||
|
'date': '2025-07-13T10:22:00.626Z',
|
||||||
|
'startTime': '15:30:00',
|
||||||
|
'endTime': '19:00:00',
|
||||||
|
'cost': 20,
|
||||||
|
'user': {
|
||||||
|
'uuid': '784394ff-3197-4c39-9f07-48dc44920b1e',
|
||||||
|
'firstName': 'salsabeel',
|
||||||
|
'lastName': 'abuzaid',
|
||||||
|
'email': 'test@test.com',
|
||||||
|
'companyName': null
|
||||||
|
},
|
||||||
|
'space': {
|
||||||
|
'uuid': '000f4d81-43e4-4ad7-865c-0f8b04b7081e',
|
||||||
|
'spaceName': '2(1)'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
'success': true
|
||||||
|
};
|
||||||
|
final response = CalendarEventsResponse.fromJson(dummyJson);
|
||||||
|
|
||||||
|
// Filter events by spaceId
|
||||||
|
final filteredData = response.data.where((event) {
|
||||||
|
return event.space.uuid == spaceId;
|
||||||
|
}).toList();
|
||||||
|
print('Filtering events for spaceId: $spaceId');
|
||||||
|
print('Found ${filteredData.length} matching events');
|
||||||
|
return filteredData.isNotEmpty
|
||||||
|
? CalendarEventsResponse(
|
||||||
|
statusCode: response.statusCode,
|
||||||
|
message: response.message,
|
||||||
|
data: filteredData,
|
||||||
|
success: response.success,
|
||||||
|
)
|
||||||
|
: CalendarEventsResponse(
|
||||||
|
statusCode: 404,
|
||||||
|
message: 'No events found for spaceId: $spaceId',
|
||||||
|
data: [],
|
||||||
|
success: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final response = await _httpService.get(
|
||||||
|
path: ApiEndpoints.getCalendarEvents,
|
||||||
|
queryParameters: {
|
||||||
|
'spaceId': spaceId,
|
||||||
|
},
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return CalendarEventsResponse.fromJson(
|
||||||
|
json as Map<String, dynamic>,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return CalendarEventsResponse.fromJson(response as Map<String, dynamic>);
|
||||||
} on DioException catch (e) {
|
} on DioException catch (e) {
|
||||||
final responseData = e.response?.data;
|
final responseData = e.response?.data;
|
||||||
if (responseData is Map<String, dynamic>) {
|
if (responseData is Map<String, dynamic>) {
|
||||||
|
|||||||
@ -1,34 +0,0 @@
|
|||||||
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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension KeyGenerator on LoadEventsParam {
|
|
||||||
String generateKey() {
|
|
||||||
return '$id-${startDate.year}-${startDate.month.toString().padLeft(2, '0')}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,8 +1,7 @@
|
|||||||
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 LoadEventsParam params,
|
required String spaceId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,10 +2,9 @@ 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/data/services/memory_bookable_space_service.dart';
|
|
||||||
part 'events_event.dart';
|
part 'events_event.dart';
|
||||||
part 'events_state.dart';
|
part 'events_state.dart';
|
||||||
|
|
||||||
@ -13,35 +12,27 @@ class CalendarEventsBloc extends Bloc<CalendarEventsEvent, CalendarEventState> {
|
|||||||
final EventController eventController = EventController();
|
final EventController eventController = EventController();
|
||||||
final CalendarSystemService calendarService;
|
final CalendarSystemService calendarService;
|
||||||
|
|
||||||
CalendarEventsBloc({
|
CalendarEventsBloc({required this.calendarService}) : super(EventsInitial()) {
|
||||||
required this.calendarService,
|
|
||||||
}) : super(EventsInitial()) {
|
|
||||||
on<LoadEvents>(_onLoadEvents);
|
on<LoadEvents>(_onLoadEvents);
|
||||||
on<AddEvent>(_onAddEvent);
|
on<AddEvent>(_onAddEvent);
|
||||||
|
on<StartTimer>(_onStartTimer);
|
||||||
on<DisposeResources>(_onDisposeResources);
|
on<DisposeResources>(_onDisposeResources);
|
||||||
on<GoToWeek>(_onGoToWeek);
|
on<GoToWeek>(_onGoToWeek);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _onLoadEvents(
|
Future<void> _onLoadEvents(
|
||||||
LoadEvents event,
|
LoadEvents event,
|
||||||
Emitter<CalendarEventState> emit,
|
Emitter<CalendarEventState> emit,
|
||||||
) async {
|
) async {
|
||||||
final param = event.param;
|
|
||||||
final month = param.endDate.month;
|
|
||||||
final year = param.endDate.year;
|
|
||||||
final spaceId = param.id;
|
|
||||||
|
|
||||||
emit(EventsLoading());
|
emit(EventsLoading());
|
||||||
try {
|
try {
|
||||||
final response = await calendarService.getCalendarEvents(params: param);
|
final response = await calendarService.getCalendarEvents(
|
||||||
|
spaceId: event.spaceId,
|
||||||
final events = response.data.map(_toCalendarEventData).toList();
|
);
|
||||||
|
final events =
|
||||||
|
response.data.map<CalendarEventData>(_toCalendarEventData).toList();
|
||||||
eventController.addAll(events);
|
eventController.addAll(events);
|
||||||
emit(EventsLoaded(
|
emit(EventsLoaded(events: events));
|
||||||
events: events,
|
|
||||||
spaceId: spaceId,
|
|
||||||
month: month,
|
|
||||||
year: year,
|
|
||||||
));
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(EventsError('Failed to load events'));
|
emit(EventsError('Failed to load events'));
|
||||||
}
|
}
|
||||||
@ -49,19 +40,16 @@ class CalendarEventsBloc extends Bloc<CalendarEventsEvent, CalendarEventState> {
|
|||||||
|
|
||||||
void _onAddEvent(AddEvent event, Emitter<CalendarEventState> emit) {
|
void _onAddEvent(AddEvent event, Emitter<CalendarEventState> emit) {
|
||||||
eventController.add(event.event);
|
eventController.add(event.event);
|
||||||
|
|
||||||
if (state is EventsLoaded) {
|
if (state is EventsLoaded) {
|
||||||
final loaded = state as EventsLoaded;
|
final loaded = state as EventsLoaded;
|
||||||
|
|
||||||
emit(EventsLoaded(
|
emit(EventsLoaded(
|
||||||
events: [...eventController.events],
|
events: [...eventController.events],
|
||||||
spaceId: loaded.spaceId,
|
|
||||||
month: loaded.month,
|
|
||||||
year: loaded.year,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onStartTimer(StartTimer event, Emitter<CalendarEventState> emit) {}
|
||||||
|
|
||||||
void _onDisposeResources(
|
void _onDisposeResources(
|
||||||
DisposeResources event, Emitter<CalendarEventState> emit) {
|
DisposeResources event, Emitter<CalendarEventState> emit) {
|
||||||
eventController.dispose();
|
eventController.dispose();
|
||||||
@ -73,9 +61,6 @@ class CalendarEventsBloc extends Bloc<CalendarEventsEvent, CalendarEventState> {
|
|||||||
final newWeekDays = _getWeekDays(event.weekDate);
|
final newWeekDays = _getWeekDays(event.weekDate);
|
||||||
emit(EventsLoaded(
|
emit(EventsLoaded(
|
||||||
events: loaded.events,
|
events: loaded.events,
|
||||||
spaceId: loaded.spaceId,
|
|
||||||
month: loaded.month,
|
|
||||||
year: loaded.year,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -108,7 +93,8 @@ class CalendarEventsBloc extends Bloc<CalendarEventsEvent, CalendarEventState> {
|
|||||||
date: startTime,
|
date: startTime,
|
||||||
startTime: startTime,
|
startTime: startTime,
|
||||||
endTime: endTime,
|
endTime: endTime,
|
||||||
title: '${booking.user.firstName} ${booking.user.lastName}',
|
title:
|
||||||
|
'${booking.space.spaceName} - ${booking.user.firstName} ${booking.user.lastName}',
|
||||||
description: 'Cost: ${booking.cost}',
|
description: 'Cost: ${booking.cost}',
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
event: booking,
|
event: booking,
|
||||||
|
|||||||
@ -6,10 +6,16 @@ abstract class CalendarEventsEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class LoadEvents extends CalendarEventsEvent {
|
class LoadEvents extends CalendarEventsEvent {
|
||||||
final LoadEventsParam param;
|
final String spaceId;
|
||||||
const LoadEvents(this.param);
|
final DateTime weekStart;
|
||||||
}
|
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;
|
||||||
|
|||||||
@ -7,17 +7,11 @@ class EventsInitial extends CalendarEventState {}
|
|||||||
|
|
||||||
class EventsLoading extends CalendarEventState {}
|
class EventsLoading extends CalendarEventState {}
|
||||||
|
|
||||||
final class EventsLoaded extends CalendarEventState {
|
class EventsLoaded extends CalendarEventState {
|
||||||
final List<CalendarEventData> events;
|
final List<CalendarEventData> events;
|
||||||
final String spaceId;
|
|
||||||
final int month;
|
|
||||||
final int year;
|
|
||||||
|
|
||||||
EventsLoaded({
|
EventsLoaded({
|
||||||
required this.events,
|
required this.events,
|
||||||
required this.spaceId,
|
|
||||||
required this.month,
|
|
||||||
required this.year,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,13 +2,11 @@ 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/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';
|
||||||
@ -48,11 +46,9 @@ class _BookingPageState extends State<BookingPage> {
|
|||||||
if (selectedRoom != null) {
|
if (selectedRoom != null) {
|
||||||
context.read<CalendarEventsBloc>().add(
|
context.read<CalendarEventsBloc>().add(
|
||||||
LoadEvents(
|
LoadEvents(
|
||||||
LoadEventsParam(
|
spaceId: selectedRoom.uuid,
|
||||||
startDate: dateState.weekStart,
|
weekStart: dateState.weekStart,
|
||||||
endDate: dateState.weekStart.add(const Duration(days: 6)),
|
weekEnd: dateState.weekStart.add(const Duration(days: 6)),
|
||||||
id: selectedRoom.uuid,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -66,13 +62,10 @@ class _BookingPageState extends State<BookingPage> {
|
|||||||
BlocProvider(create: (_) => DateSelectionBloc()),
|
BlocProvider(create: (_) => DateSelectionBloc()),
|
||||||
BlocProvider(
|
BlocProvider(
|
||||||
create: (_) => CalendarEventsBloc(
|
create: (_) => CalendarEventsBloc(
|
||||||
calendarService: MemoryCalendarServiceWithRemoteFallback(
|
calendarService:
|
||||||
remoteService: RemoteCalendarService(
|
FakeRemoteCalendarService(HTTPService(), useDummy: true),
|
||||||
HTTPService(),
|
|
||||||
),
|
),
|
||||||
memoryService: MemoryCalendarService(),
|
|
||||||
),
|
),
|
||||||
)),
|
|
||||||
],
|
],
|
||||||
child: Builder(
|
child: Builder(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
@ -145,7 +138,7 @@ class _BookingPageState extends State<BookingPage> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 5,
|
flex: 4,
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(20.0),
|
padding: const EdgeInsets.all(20.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
@ -194,7 +187,6 @@ class _BookingPageState extends State<BookingPage> {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 5,
|
|
||||||
child: BlocBuilder<SelectedBookableSpaceBloc,
|
child: BlocBuilder<SelectedBookableSpaceBloc,
|
||||||
SelectedBookableSpaceState>(
|
SelectedBookableSpaceState>(
|
||||||
builder: (context, roomState) {
|
builder: (context, roomState) {
|
||||||
|
|||||||
@ -72,7 +72,11 @@ class __SidebarContentState extends State<_SidebarContent> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocConsumer<SidebarBloc, SidebarState>(
|
return BlocConsumer<SidebarBloc, SidebarState>(
|
||||||
listener: (context, state) {},
|
listener: (context, state) {
|
||||||
|
if (state.currentPage == 1 && searchController.text.isNotEmpty) {
|
||||||
|
searchController.clear();
|
||||||
|
}
|
||||||
|
},
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
@ -143,7 +147,6 @@ class __SidebarContentState extends State<_SidebarContent> {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.close),
|
icon: const Icon(Icons.close),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
searchController.clear();
|
|
||||||
context.read<SidebarBloc>().add(ResetSearch());
|
context.read<SidebarBloc>().add(ResetSearch());
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@ -1,15 +1,16 @@
|
|||||||
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:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/booking_system/domain/models/calendar_event_booking.dart';
|
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class EventTileWidget extends StatelessWidget {
|
class EventTileWidget extends StatelessWidget {
|
||||||
final List<CalendarEventData<Object?>> events;
|
final List<CalendarEventData<Object?>> events;
|
||||||
|
|
||||||
const EventTileWidget({
|
const EventTileWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.events,
|
required this.events,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
@ -17,85 +18,38 @@ class EventTileWidget extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: events.map((event) {
|
children: events.map((event) {
|
||||||
final booking = event.event is CalendarEventBooking
|
final bool isEventEnded =
|
||||||
? event.event! as CalendarEventBooking
|
|
||||||
: null;
|
|
||||||
|
|
||||||
final companyName = booking?.user.companyName ?? 'Unknown Company';
|
|
||||||
final startTime = DateFormat('hh:mm a').format(event.startTime!);
|
|
||||||
final endTime = DateFormat('hh:mm a').format(event.endTime!);
|
|
||||||
final isEventEnded =
|
|
||||||
event.endTime != null && event.endTime!.isBefore(DateTime.now());
|
event.endTime != null && event.endTime!.isBefore(DateTime.now());
|
||||||
|
|
||||||
final duration = event.endTime!.difference(event.startTime!);
|
|
||||||
final bool isLongEnough = duration.inMinutes >= 31;
|
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Container(
|
child: Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: EdgeInsets.all(5),
|
padding: const EdgeInsets.all(6),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isEventEnded
|
color: isEventEnded
|
||||||
? ColorsManager.grayColor.withOpacity(0.1)
|
? ColorsManager.lightGrayBorderColor
|
||||||
: ColorsManager.blue1.withOpacity(0.1),
|
: ColorsManager.blue1.withOpacity(0.25),
|
||||||
borderRadius: BorderRadius.circular(6),
|
borderRadius: BorderRadius.circular(6),
|
||||||
border: const Border(
|
|
||||||
left: BorderSide(
|
|
||||||
color: ColorsManager.grayColor,
|
|
||||||
width: 4,
|
|
||||||
),
|
),
|
||||||
),
|
child: Column(
|
||||||
),
|
|
||||||
child: isLongEnough
|
|
||||||
? Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
'$startTime - $endTime',
|
DateFormat('h:mm a').format(event.startTime!),
|
||||||
overflow: TextOverflow.ellipsis,
|
style: const TextStyle(
|
||||||
style: TextStyle(
|
fontWeight: FontWeight.bold,
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: isEventEnded
|
color: Colors.black87,
|
||||||
? ColorsManager.grayColor.withOpacity(0.9)
|
|
||||||
: ColorsManager.blackColor,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Text(
|
Text(
|
||||||
event.title,
|
event.title,
|
||||||
overflow: TextOverflow.ellipsis,
|
style: const TextStyle(
|
||||||
style: TextStyle(
|
fontSize: 12,
|
||||||
fontSize: 14,
|
color: ColorsManager.blackColor,
|
||||||
color: isEventEnded
|
|
||||||
? ColorsManager.grayColor
|
|
||||||
: ColorsManager.blackColor,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 2),
|
|
||||||
Text(
|
|
||||||
companyName,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: isEventEnded
|
|
||||||
? ColorsManager.grayColor.withOpacity(0.9)
|
|
||||||
: ColorsManager.blackColor,
|
|
||||||
fontWeight: FontWeight.w400,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
|
||||||
: Text(
|
|
||||||
event.title,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
color: isEventEnded
|
|
||||||
? ColorsManager.grayColor
|
|
||||||
: ColorsManager.blackColor,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -24,21 +24,17 @@ class RoomListItem extends StatelessWidget {
|
|||||||
activeColor: ColorsManager.primaryColor,
|
activeColor: ColorsManager.primaryColor,
|
||||||
title: Text(
|
title: Text(
|
||||||
room.spaceName,
|
room.spaceName,
|
||||||
maxLines: 2,
|
|
||||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
color: ColorsManager.lightGrayColor,
|
color: ColorsManager.lightGrayColor,
|
||||||
fontWeight: FontWeight.w700,
|
fontWeight: FontWeight.w700,
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
fontSize: 12),
|
fontSize: 12),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
room.virtualLocation,
|
room.virtualLocation,
|
||||||
maxLines: 2,
|
|
||||||
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
style: Theme.of(context).textTheme.bodySmall?.copyWith(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
color: ColorsManager.textGray,
|
color: ColorsManager.textGray,
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:calendar_view/calendar_view.dart';
|
import 'package:calendar_view/calendar_view.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/event_tile_widget.dart';
|
import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/event_tile_widget.dart';
|
||||||
|
import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/hatched_column_background.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/time_line_widget.dart';
|
import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/time_line_widget.dart';
|
||||||
import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/week_day_header.dart';
|
import 'package:syncrow_web/pages/access_management/booking_system/presentation/view/widgets/week_day_header.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
@ -22,12 +23,6 @@ class WeeklyCalendarPage extends StatelessWidget {
|
|||||||
this.endTime,
|
this.endTime,
|
||||||
this.selectedDateFromSideBarCalender,
|
this.selectedDateFromSideBarCalender,
|
||||||
});
|
});
|
||||||
static const double timeLineWidth = 65;
|
|
||||||
static const int totalDays = 7;
|
|
||||||
static const double dayColumnWidth = 220;
|
|
||||||
|
|
||||||
final double calendarContentWidth =
|
|
||||||
timeLineWidth + (totalDays * dayColumnWidth);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -57,31 +52,33 @@ class WeeklyCalendarPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final weekDays = _getWeekDays(weekStart);
|
||||||
|
|
||||||
|
final selectedDayIndex =
|
||||||
|
weekDays.indexWhere((d) => isSameDay(d, selectedDate));
|
||||||
|
final selectedSidebarIndex = selectedDateFromSideBarCalender == null
|
||||||
|
? -1
|
||||||
|
: weekDays
|
||||||
|
.indexWhere((d) => isSameDay(d, selectedDateFromSideBarCalender!));
|
||||||
|
|
||||||
const double timeLineWidth = 65;
|
const double timeLineWidth = 80;
|
||||||
|
const int totalDays = 7;
|
||||||
|
final DateTime highlightStart = DateTime(2025, 7, 10);
|
||||||
|
final DateTime highlightEnd = DateTime(2025, 7, 19);
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
|
final double calendarWidth = constraints.maxWidth;
|
||||||
|
final double dayColumnWidth =
|
||||||
|
(calendarWidth - timeLineWidth) / totalDays - 0.1;
|
||||||
bool isInRange(DateTime date, DateTime start, DateTime end) {
|
bool isInRange(DateTime date, DateTime start, DateTime end) {
|
||||||
!date.isBefore(start) && !date.isAfter(end);
|
return !date.isBefore(start) && !date.isAfter(end);
|
||||||
// remove this line and Check if the date is within the range
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SingleChildScrollView(
|
return Padding(
|
||||||
scrollDirection: Axis.horizontal,
|
padding: const EdgeInsets.only(left: 25.0, right: 25.0, top: 25),
|
||||||
child: SizedBox(
|
|
||||||
width: calendarContentWidth,
|
|
||||||
child: Padding(
|
|
||||||
padding:
|
|
||||||
const EdgeInsets.only(left: 25.0, right: 25.0, top: 25),
|
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
WeekView(
|
||||||
child: WeekView(
|
|
||||||
minuteSlotSize: MinuteSlotSize.minutes15,
|
|
||||||
weekDetectorBuilder: ({
|
weekDetectorBuilder: ({
|
||||||
required date,
|
required date,
|
||||||
required height,
|
required height,
|
||||||
@ -89,64 +86,28 @@ class WeeklyCalendarPage extends StatelessWidget {
|
|||||||
required minuteSlotSize,
|
required minuteSlotSize,
|
||||||
required width,
|
required width,
|
||||||
}) {
|
}) {
|
||||||
final isSelected = isSameDay(date, selectedDate);
|
return isInRange(date, highlightStart, highlightEnd)
|
||||||
final isSidebarSelected =
|
? HatchedColumnBackground(
|
||||||
selectedDateFromSideBarCalender != null &&
|
backgroundColor: ColorsManager.grey800,
|
||||||
isSameDay(
|
lineColor: ColorsManager.textGray,
|
||||||
date, selectedDateFromSideBarCalender!);
|
opacity: 0.3,
|
||||||
if (isSidebarSelected && !isSelected) {
|
stripeSpacing: 12,
|
||||||
return Container(
|
|
||||||
height: height,
|
|
||||||
width: width,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.orange.withOpacity(0.13),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
)
|
||||||
);
|
: const SizedBox();
|
||||||
} else if (isSelected) {
|
|
||||||
return Container(
|
|
||||||
height: height,
|
|
||||||
width: width,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color:
|
|
||||||
ColorsManager.spaceColor.withOpacity(0.07),
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// weekDetectorBuilder: ({
|
|
||||||
// required date,
|
|
||||||
// required height,
|
|
||||||
// required heightPerMinute,
|
|
||||||
// required minuteSlotSize,
|
|
||||||
// required width,
|
|
||||||
// }) {
|
|
||||||
// return isInRange(date, highlightStart, highlightEnd)
|
|
||||||
// ? HatchedColumnBackground(
|
|
||||||
// backgroundColor: ColorsManager.grey800,
|
|
||||||
// lineColor: ColorsManager.textGray,
|
|
||||||
// opacity: 0.3,
|
|
||||||
// stripeSpacing: 12,
|
|
||||||
// borderRadius: BorderRadius.circular(8),
|
|
||||||
// )
|
|
||||||
// : const SizedBox();
|
|
||||||
// },
|
|
||||||
pageViewPhysics: const NeverScrollableScrollPhysics(),
|
pageViewPhysics: const NeverScrollableScrollPhysics(),
|
||||||
key: ValueKey(weekStart),
|
key: ValueKey(weekStart),
|
||||||
controller: eventController,
|
controller: eventController,
|
||||||
initialDay: weekStart,
|
initialDay: weekStart,
|
||||||
startHour: startHour - 1,
|
startHour: startHour - 1,
|
||||||
endHour: endHour,
|
endHour: endHour,
|
||||||
heightPerMinute: 1.7,
|
heightPerMinute: 1.1,
|
||||||
showLiveTimeLineInAllDays: false,
|
showLiveTimeLineInAllDays: false,
|
||||||
showVerticalLines: true,
|
showVerticalLines: true,
|
||||||
emulateVerticalOffsetBy: -80,
|
emulateVerticalOffsetBy: -80,
|
||||||
startDay: WeekDays.monday,
|
startDay: WeekDays.monday,
|
||||||
liveTimeIndicatorSettings:
|
liveTimeIndicatorSettings: const LiveTimeIndicatorSettings(
|
||||||
const LiveTimeIndicatorSettings(
|
|
||||||
showBullet: false,
|
showBullet: false,
|
||||||
height: 0,
|
height: 0,
|
||||||
),
|
),
|
||||||
@ -169,12 +130,8 @@ class WeeklyCalendarPage extends StatelessWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
firstDayOfWeek.timeZoneName
|
firstDayOfWeek.timeZoneName.replaceAll(':00', ''),
|
||||||
.replaceAll(':00', ''),
|
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||||
style: Theme.of(context)
|
|
||||||
.textTheme
|
|
||||||
.bodyMedium
|
|
||||||
?.copyWith(
|
|
||||||
fontSize: 12,
|
fontSize: 12,
|
||||||
color: ColorsManager.blackColor,
|
color: ColorsManager.blackColor,
|
||||||
fontWeight: FontWeight.w400,
|
fontWeight: FontWeight.w400,
|
||||||
@ -189,6 +146,36 @@ class WeeklyCalendarPage extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (selectedDayIndex >= 0)
|
||||||
|
Positioned(
|
||||||
|
left: (timeLineWidth + 3) +
|
||||||
|
(dayColumnWidth - 8) * (selectedDayIndex - 0.01),
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
width: dayColumnWidth,
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.symmetric(
|
||||||
|
vertical: 0, horizontal: 4),
|
||||||
|
color: ColorsManager.spaceColor.withOpacity(0.07),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (selectedSidebarIndex >= 0 &&
|
||||||
|
selectedSidebarIndex != selectedDayIndex)
|
||||||
|
Positioned(
|
||||||
|
left: (timeLineWidth + 3) +
|
||||||
|
(dayColumnWidth - 8) * (selectedSidebarIndex - 0.01),
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
width: dayColumnWidth,
|
||||||
|
child: IgnorePointer(
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.symmetric(
|
||||||
|
vertical: 0, horizontal: 4),
|
||||||
|
color: Colors.orange.withOpacity(0.14),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
right: 0,
|
right: 0,
|
||||||
@ -203,13 +190,16 @@ class WeeklyCalendarPage extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
));
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<DateTime> _getWeekDays(DateTime date) {
|
||||||
|
final int weekday = date.weekday;
|
||||||
|
final DateTime monday = date.subtract(Duration(days: weekday - 1));
|
||||||
|
return List.generate(7, (i) => monday.add(Duration(days: i)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isSameDay(DateTime d1, DateTime d2) {
|
bool isSameDay(DateTime d1, DateTime d2) {
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_
|
|||||||
import 'package:syncrow_web/pages/device_managment/garage_door/helper/garage_door_helper.dart';
|
import 'package:syncrow_web/pages/device_managment/garage_door/helper/garage_door_helper.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/garage_door/models/garage_door_model.dart';
|
import 'package:syncrow_web/pages/device_managment/garage_door/models/garage_door_model.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/garage_door/schedule_view/schedule_garage_view.dart';
|
import 'package:syncrow_web/pages/device_managment/garage_door/schedule_view/schedule_garage_view.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/schedule_device/schedule_widgets/schedual_view.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/icon_name_status_container.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/icon_name_status_container.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/table/report_table.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/table/report_table.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
|
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
|
||||||
@ -94,11 +95,18 @@ class GarageDoorControlView extends StatelessWidget
|
|||||||
FetchGarageDoorSchedulesEvent(
|
FetchGarageDoorSchedulesEvent(
|
||||||
deviceId: deviceId, category: 'doorcontact_state'),
|
deviceId: deviceId, category: 'doorcontact_state'),
|
||||||
);
|
);
|
||||||
showDialog(
|
|
||||||
|
showDialog<void>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (ctx) => BlocProvider.value(
|
builder: (ctx) => BlocProvider.value(
|
||||||
value: BlocProvider.of<GarageDoorBloc>(context),
|
value: BlocProvider.of<GarageDoorBloc>(context),
|
||||||
child: BuildGarageDoorScheduleView(status: status),
|
child: BuildScheduleView(
|
||||||
|
deviceUuid: deviceId,
|
||||||
|
category: 'Timer',
|
||||||
|
code: 'doorcontact_state',
|
||||||
|
countdownCode: 'Timer',
|
||||||
|
deviceType: 'GD',
|
||||||
|
),
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
name: 'Scheduling',
|
name: 'Scheduling',
|
||||||
|
|||||||
@ -287,7 +287,8 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
|||||||
try {
|
try {
|
||||||
if (state is ScheduleLoaded) {
|
if (state is ScheduleLoaded) {
|
||||||
Status status = Status(code: '', value: '');
|
Status status = Status(code: '', value: '');
|
||||||
if (event.deviceType == 'CUR_2') {
|
if (event.deviceType == 'CUR_2' ||
|
||||||
|
event.deviceType == 'GD' ) {
|
||||||
status = status.copyWith(
|
status = status.copyWith(
|
||||||
code: 'control',
|
code: 'control',
|
||||||
value: event.functionOn == true ? 'open' : 'close');
|
value: event.functionOn == true ? 'open' : 'close');
|
||||||
|
|||||||
@ -69,7 +69,7 @@ class CountdownModeButtons extends StatelessWidget {
|
|||||||
countDownCode: countDownCode),
|
countDownCode: countDownCode),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
backgroundColor: ColorsManager.primaryColorWithOpacity,
|
backgroundColor: ColorsManager.secondaryColor,
|
||||||
child: const Text('Save'),
|
child: const Text('Save'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -63,7 +63,7 @@ class InchingModeButtons extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
backgroundColor: ColorsManager.primaryColor,
|
backgroundColor: ColorsManager.secondaryColor,
|
||||||
child: const Text('Save'),
|
child: const Text('Save'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -31,11 +31,12 @@ class BuildScheduleView extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (_) => ScheduleBloc(deviceId: deviceUuid,)
|
create: (_) => ScheduleBloc(
|
||||||
|
deviceId: deviceUuid,
|
||||||
|
)
|
||||||
..add(ScheduleGetEvent(category: category))
|
..add(ScheduleGetEvent(category: category))
|
||||||
..add(ScheduleFetchStatusEvent(
|
..add(ScheduleFetchStatusEvent(
|
||||||
deviceId: deviceUuid,
|
deviceId: deviceUuid, countdownCode: countdownCode ?? '')),
|
||||||
countdownCode: countdownCode ?? '')),
|
|
||||||
child: Dialog(
|
child: Dialog(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
insetPadding: const EdgeInsets.all(20),
|
insetPadding: const EdgeInsets.all(20),
|
||||||
@ -56,7 +57,7 @@ class BuildScheduleView extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
const ScheduleHeader(),
|
const ScheduleHeader(),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
if (deviceType == 'CUR_2')
|
if (deviceType == 'CUR_2' || deviceType == 'GD')
|
||||||
const SizedBox()
|
const SizedBox()
|
||||||
else
|
else
|
||||||
ScheduleModeSelector(
|
ScheduleModeSelector(
|
||||||
@ -76,8 +77,7 @@ class BuildScheduleView extends StatelessWidget {
|
|||||||
category: category,
|
category: category,
|
||||||
time: '',
|
time: '',
|
||||||
function: Status(
|
function: Status(
|
||||||
code: code.toString(),
|
code: code.toString(), value: true),
|
||||||
value: true),
|
|
||||||
days: [],
|
days: [],
|
||||||
),
|
),
|
||||||
isEdit: false,
|
isEdit: false,
|
||||||
@ -96,7 +96,7 @@ class BuildScheduleView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (deviceType != 'CUR_2')
|
if (deviceType != 'CUR_2'|| deviceType != 'GD')
|
||||||
if (state.scheduleMode == ScheduleModes.countdown ||
|
if (state.scheduleMode == ScheduleModes.countdown ||
|
||||||
state.scheduleMode == ScheduleModes.inching)
|
state.scheduleMode == ScheduleModes.inching)
|
||||||
CountdownInchingView(
|
CountdownInchingView(
|
||||||
|
|||||||
@ -24,12 +24,13 @@ class ScheduleManagementUI extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 170,
|
width: 177,
|
||||||
height: 40,
|
height: 40,
|
||||||
child: DefaultButton(
|
child: DefaultButton(
|
||||||
borderColor: ColorsManager.grayColor.withOpacity(0.5),
|
borderWidth: 4,
|
||||||
padding: 2,
|
borderColor: ColorsManager.neutralGray,
|
||||||
backgroundColor: ColorsManager.graysColor,
|
padding: 8,
|
||||||
|
backgroundColor: ColorsManager.textFieldGreyColor,
|
||||||
borderRadius: 15,
|
borderRadius: 15,
|
||||||
onPressed: onAddSchedule,
|
onPressed: onAddSchedule,
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|||||||
@ -39,7 +39,7 @@ class ScheduleModeButtons extends StatelessWidget {
|
|||||||
borderRadius: 8,
|
borderRadius: 8,
|
||||||
height: 40,
|
height: 40,
|
||||||
onPressed: onSave,
|
onPressed: onSave,
|
||||||
backgroundColor: ColorsManager.primaryColorWithOpacity,
|
backgroundColor: ColorsManager.secondaryColor,
|
||||||
child: const Text('Save'),
|
child: const Text('Save'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -194,7 +194,7 @@ class _ScheduleTableView extends StatelessWidget {
|
|||||||
child: Text(_getSelectedDays(
|
child: Text(_getSelectedDays(
|
||||||
ScheduleModel.parseSelectedDays(schedule.days)))),
|
ScheduleModel.parseSelectedDays(schedule.days)))),
|
||||||
Center(child: Text(formatIsoStringToTime(schedule.time, context))),
|
Center(child: Text(formatIsoStringToTime(schedule.time, context))),
|
||||||
if (deviceType == 'CUR_2')
|
if (deviceType == 'CUR_2' || deviceType == 'GD')
|
||||||
Center(
|
Center(
|
||||||
child: Text(schedule.function.value == true ? 'open' : 'close'))
|
child: Text(schedule.function.value == true ? 'open' : 'close'))
|
||||||
else
|
else
|
||||||
|
|||||||
@ -23,7 +23,7 @@ class ScheduleDialogHelper {
|
|||||||
required String deviceType,
|
required String deviceType,
|
||||||
}) {
|
}) {
|
||||||
bool temp;
|
bool temp;
|
||||||
if (deviceType == 'CUR_2') {
|
if (deviceType == 'CUR_2' || deviceType == 'GD') {
|
||||||
temp = schedule!.function.value == 'open' ? true : false;
|
temp = schedule!.function.value == 'open' ? true : false;
|
||||||
} else {
|
} else {
|
||||||
temp = schedule!.function.value;
|
temp = schedule!.function.value;
|
||||||
@ -116,7 +116,7 @@ class ScheduleDialogHelper {
|
|||||||
ScheduleModeButtons(
|
ScheduleModeButtons(
|
||||||
onSave: () {
|
onSave: () {
|
||||||
dynamic temp;
|
dynamic temp;
|
||||||
if (deviceType == 'CUR_2') {
|
if (deviceType == 'CUR_2' || deviceType == 'GD') {
|
||||||
temp = functionOn! ? 'open' : 'close';
|
temp = functionOn! ? 'open' : 'close';
|
||||||
} else {
|
} else {
|
||||||
temp = functionOn;
|
temp = functionOn;
|
||||||
@ -202,18 +202,23 @@ class ScheduleDialogHelper {
|
|||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Radio<bool>(
|
Radio<bool>(
|
||||||
|
activeColor: ColorsManager.secondaryColor,
|
||||||
|
focusColor: ColorsManager.secondaryColor,
|
||||||
value: true,
|
value: true,
|
||||||
groupValue: isOn,
|
groupValue: isOn,
|
||||||
onChanged: (val) => onChanged(true),
|
onChanged: (val) => onChanged(true),
|
||||||
),
|
),
|
||||||
Text(categor == 'CUR_2' ? 'open' : 'On'),
|
Text(categor == 'CUR_2' || categor == 'GD' ? 'open' : 'On'),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Radio<bool>(
|
Radio<bool>(
|
||||||
|
activeColor: ColorsManager.secondaryColor,
|
||||||
|
focusColor: ColorsManager.secondaryColor,
|
||||||
|
|
||||||
value: false,
|
value: false,
|
||||||
groupValue: isOn,
|
groupValue: isOn,
|
||||||
onChanged: (val) => onChanged(false),
|
onChanged: (val) => onChanged(false),
|
||||||
),
|
),
|
||||||
Text(categor == 'CUR_2' ? 'close' : 'Off'),
|
Text(categor == 'CUR_2' || categor == 'GD' ? 'close' : 'Off'),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -140,6 +140,5 @@ abstract class ApiEndpoints {
|
|||||||
static const String saveSchedule = '/schedule/{deviceUuid}';
|
static const String saveSchedule = '/schedule/{deviceUuid}';
|
||||||
|
|
||||||
static const String getBookableSpaces = '/bookable-spaces';
|
static const String getBookableSpaces = '/bookable-spaces';
|
||||||
static const String getBookings =
|
static const String getCalendarEvents = '/api';
|
||||||
'/bookings?month={mm}%2F{yyyy}&space={space}';
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user