schedule for one gang and two gang and three gange

This commit is contained in:
mohammad
2024-09-18 12:59:28 +03:00
parent ddaf36797d
commit 42b5ff105f
24 changed files with 1872 additions and 631 deletions

View File

@ -1,16 +1,20 @@
import 'dart:async'; import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart'; import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.dart'; import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/one_gang_model.dart'; import 'package:syncrow_app/features/devices/model/one_gang_model.dart';
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart'; import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart'; import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
import 'one_gang_event.dart'; import 'one_gang_event.dart';
class OneGangBloc extends Bloc<OneGangEvent, OneGangState> { class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
final String oneGangId; final String oneGangId;
final String switchCode;
OneGangModel deviceStatus = OneGangModel( OneGangModel deviceStatus = OneGangModel(
firstSwitch: false, firstSwitch: false,
firstCountDown: 0, firstCountDown: 0,
@ -21,7 +25,7 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
List<DeviceModel> devicesList = []; List<DeviceModel> devicesList = [];
bool allSwitchesOn = true; bool allSwitchesOn = true;
OneGangBloc({required this.oneGangId}) : super(InitialState()) { OneGangBloc({required this.oneGangId,required this.switchCode}) : super(InitialState()) {
on<InitialEvent>(_fetchTwoGangStatus); on<InitialEvent>(_fetchTwoGangStatus);
on<OneGangUpdated>(_oneGangUpdated); on<OneGangUpdated>(_oneGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch); on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -30,6 +34,15 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
on<GetCounterEvent>(_getCounterValue); on<GetCounterEvent>(_getCounterValue);
on<TickTimer>(_onTickTimer); on<TickTimer>(_onTickTimer);
on<OnClose>(_onClose); on<OnClose>(_onClose);
on<ToggleDaySelectionEvent>(toggleDaySelection);
on<ThreeGangSave>(saveSchedule);
on<GetScheduleEvent>(getSchedule);
on<ToggleScheduleEvent>(toggleChange);
on<DeleteScheduleEvent>(deleteSchedule);
} }
void _fetchTwoGangStatus(InitialEvent event, Emitter<OneGangState> emit) async { void _fetchTwoGangStatus(InitialEvent event, Emitter<OneGangState> emit) async {
@ -176,4 +189,141 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
emit(TimerRunComplete()); emit(TimerRunComplete());
} }
} }
List<Map<String, String>> days = [
{"day": "Sun", "key": "Sun"},
{"day": "Mon", "key": "Mon"},
{"day": "Tue", "key": "Tue"},
{"day": "Wed", "key": "Wed"},
{"day": "Thu", "key": "Thu"},
{"day": "Fri", "key": "Fri"},
{"day": "Sat", "key": "Sat"},
];
Future<void> saveSchedule(ThreeGangSave event, Emitter<OneGangState> emit,) async {
try {
if(selectedDays.isNotEmpty) {
emit(LoadingInitialState());
final response = await DevicesAPI.postSchedule(
category: switchCode,
deviceId: oneGangId,
time: getTimeStampWithoutSeconds(selectedTime).toString(),
code: switchCode,
value: toggleSchedule,
days: selectedDays);
CustomSnackBar.displaySnackBar('Save Successfully');
add(GetScheduleEvent());
emit(ThreeGangSaveSchedule());
toggleCreateSchedule();
}else{
CustomSnackBar.displaySnackBar('Please select days');
}
} catch (e) {
emit(FailedState(error: e.toString()));
}
}
Future<void> getSchedule(GetScheduleEvent event, Emitter<OneGangState> emit,) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.getSchedule(
category: switchCode,
deviceId: oneGangId ,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
emit(FailedState(error: errorMessage.toString()));
}
}
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
print(dateTime);
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(
ToggleScheduleEvent event, Emitter<OneGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
scheduleId: event.id, deviceUuid: oneGangId, enable: event.toggle);
if (response == true) {
add(GetScheduleEvent());
toggleSchedule = event.toggle;
return toggleSchedule;
}
emit(IsToggleState(onOff: toggleSchedule));
add(const ChangeSlidingSegment(value: 1));
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
// debugPrint('errorMessage=${errorMessage}');
emit(FailedState(error: errorMessage.toString()));
}
}
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<OneGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
scheduleId: event.id,
deviceUuid: oneGangId, );
if (response == true) {
add(GetScheduleEvent());
return toggleSchedule;
}
emit(IsToggleState(onOff: toggleSchedule));
add(const ChangeSlidingSegment(value: 1));
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
emit(FailedState(error: errorMessage.toString()));
}
}
void toggleCreateSchedule() {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
selectedTime=DateTime.now();
emit(UpdateCreateScheduleState(createSchedule));
emit(ChangeSlidingSegmentState(value: 1));
}
bool toggleSchedule = true;
List<String> selectedDays = [];
bool createSchedule = false;
List<ScheduleModel> listSchedule = [];
DateTime? selectedTime=DateTime.now();
Future<void> toggleDaySelection(
ToggleDaySelectionEvent event,
Emitter<OneGangState> emit,
) async {
emit(LoadingInitialState());
if (selectedDays.contains(event.key)) {
selectedDays.remove(event.key);
} else {
selectedDays.add(event.key);
}
emit(ChangeTimeState());
add(ChangeSlidingSegment(value: 1));
}
int selectedTabIndex = 0;
void toggleSelectedIndex(index) {
emit(LoadingInitialState());
selectedTabIndex = index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
} }

View File

@ -86,3 +86,31 @@ class TickTimer extends OneGangEvent {
class StopTimer extends OneGangEvent {} class StopTimer extends OneGangEvent {}
class OnClose extends OneGangEvent {} class OnClose extends OneGangEvent {}
//------------------- Schedule ----------=---------
class GetScheduleEvent extends OneGangEvent {}
class ThreeGangSave extends OneGangEvent {}
class ToggleScheduleEvent extends OneGangEvent {
final String id;
final bool toggle;
const ToggleScheduleEvent({required this.toggle,required this.id});
@override
List<Object> get props => [toggle,id];
}
class ToggleDaySelectionEvent extends OneGangEvent {
final String key;
const ToggleDaySelectionEvent({required this.key});
@override
List<Object> get props => [key];
}
class DeleteScheduleEvent extends OneGangEvent {
final String id;
const DeleteScheduleEvent({required this.id});
@override
List<Object> get props => [id];
}

View File

@ -77,3 +77,13 @@ class TimerRunInProgress extends OneGangState {
} }
class TimerRunComplete extends OneGangState {} class TimerRunComplete extends OneGangState {}
class ThreeGangSaveSchedule extends OneGangState {}
class IsToggleState extends OneGangState {
final bool? onOff;
const IsToggleState({this.onOff});
}
class ChangeTimeState extends OneGangState {}
class UpdateCreateScheduleState extends OneGangState {
final bool createSchedule;
UpdateCreateScheduleState(this.createSchedule);
}

View File

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart'; import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
@ -7,12 +8,16 @@ import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_sta
import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart'; import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart';
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart'; import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/features/devices/model/three_gang_model.dart'; import 'package:syncrow_app/features/devices/model/three_gang_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart'; import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> { class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
final String threeGangId; final String threeGangId;
final String switchCode;
ThreeGangModel deviceStatus = ThreeGangModel( ThreeGangModel deviceStatus = ThreeGangModel(
firstSwitch: false, firstSwitch: false,
secondSwitch: false, secondSwitch: false,
@ -30,7 +35,7 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
List<GroupThreeGangModel> groupThreeGangList = []; List<GroupThreeGangModel> groupThreeGangList = [];
bool allSwitchesOn = true; bool allSwitchesOn = true;
ThreeGangBloc({required this.threeGangId}) : super(InitialState()) { ThreeGangBloc({required this.threeGangId,required this.switchCode}) : super(InitialState()) {
on<InitialEvent>(_fetchThreeGangStatus); on<InitialEvent>(_fetchThreeGangStatus);
on<ThreeGangUpdated>(_threeGangUpdated); on<ThreeGangUpdated>(_threeGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch); on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -45,6 +50,14 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
on<OnClose>(_onClose); on<OnClose>(_onClose);
on<GroupAllOnEvent>(_groupAllOn); on<GroupAllOnEvent>(_groupAllOn);
on<GroupAllOffEvent>(_groupAllOff); on<GroupAllOffEvent>(_groupAllOff);
on<ToggleDaySelectionEvent>(toggleDaySelection);
on<ThreeGangSave>(saveSchedule);
on<GetScheduleEvent>(getSchedule);
on<ToggleScheduleEvent>(toggleChange);
on<DeleteScheduleEvent>(deleteSchedule);
} }
void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async { void _fetchThreeGangStatus(InitialEvent event, Emitter<ThreeGangState> emit) async {
@ -479,4 +492,145 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
emit(TimerRunComplete()); emit(TimerRunComplete());
} }
} }
List<Map<String, String>> days = [
{"day": "Sun", "key": "Sun"},
{"day": "Mon", "key": "Mon"},
{"day": "Tue", "key": "Tue"},
{"day": "Wed", "key": "Wed"},
{"day": "Thu", "key": "Thu"},
{"day": "Fri", "key": "Fri"},
{"day": "Sat", "key": "Sat"},
];
Future<void> toggleDaySelection(
ToggleDaySelectionEvent event,
Emitter<ThreeGangState> emit,
) async {
emit(LoadingInitialState());
if (selectedDays.contains(event.key)) {
selectedDays.remove(event.key);
} else {
selectedDays.add(event.key);
}
emit(ChangeTimeState());
add(ChangeSlidingSegment(value: 1));
}
Future<void> saveSchedule(ThreeGangSave event, Emitter<ThreeGangState> emit,) async {
try {
if(selectedDays.isNotEmpty) {
emit(LoadingInitialState());
final response = await DevicesAPI.postSchedule(
category: switchCode,
deviceId: threeGangId,
time: getTimeStampWithoutSeconds(selectedTime).toString(),
code: switchCode,
value: toggleSchedule,
days: selectedDays);
CustomSnackBar.displaySnackBar('Save Successfully');
add(GetScheduleEvent());
emit(ThreeGangSaveSchedule());
toggleCreateSchedule();
}else{
CustomSnackBar.displaySnackBar('Please select days');
}
} catch (e) {
emit(FailedState(error: e.toString()));
}
}
Future<void> getSchedule(GetScheduleEvent event, Emitter<ThreeGangState> emit,) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.getSchedule(
category: switchCode,
deviceId: threeGangId ,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
emit(FailedState(error: errorMessage.toString()));
}
}
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
print(dateTime);
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleChange(
ToggleScheduleEvent event, Emitter<ThreeGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
scheduleId: event.id, deviceUuid: threeGangId, enable: event.toggle);
if (response == true) {
add(GetScheduleEvent());
toggleSchedule = event.toggle;
return toggleSchedule;
}
emit(IsToggleState(onOff: toggleSchedule));
add(const ChangeSlidingSegment(value: 1));
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
// debugPrint('errorMessage=${errorMessage}');
emit(FailedState(error: errorMessage.toString()));
}
}
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<ThreeGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
scheduleId: event.id,
deviceUuid: threeGangId, );
if (response == true) {
add(GetScheduleEvent());
return toggleSchedule;
}
emit(IsToggleState(onOff: toggleSchedule));
add(const ChangeSlidingSegment(value: 1));
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
emit(FailedState(error: errorMessage.toString()));
}
}
void toggleCreateSchedule() {
emit(LoadingInitialState());
createSchedule = !createSchedule;
selectedDays.clear();
selectedTime=DateTime.now();
emit(UpdateCreateScheduleState(createSchedule));
emit(ChangeSlidingSegmentState(value: 1));
}
int selectedTabIndex = 0;
void toggleSelectedIndex(index) {
emit(LoadingInitialState());
selectedTabIndex = index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
bool toggleSchedule = true;
List<String> selectedDays = [];
bool createSchedule = false;
List<ScheduleModel> listSchedule = [];
DateTime? selectedTime=DateTime.now();
} }

View File

@ -93,3 +93,29 @@ class TickTimer extends ThreeGangEvent {
class StopTimer extends ThreeGangEvent {} class StopTimer extends ThreeGangEvent {}
class OnClose extends ThreeGangEvent {} class OnClose extends ThreeGangEvent {}
//------------------- Schedule ----------=---------
class GetScheduleEvent extends ThreeGangEvent {}
class ThreeGangSave extends ThreeGangEvent {}
class ToggleScheduleEvent extends ThreeGangEvent {
final String id;
final bool toggle;
const ToggleScheduleEvent({required this.toggle,required this.id});
@override
List<Object> get props => [toggle,id];
}
class ToggleDaySelectionEvent extends ThreeGangEvent {
final String key;
const ToggleDaySelectionEvent({required this.key});
@override
List<Object> get props => [key];
}
class DeleteScheduleEvent extends ThreeGangEvent {
final String id;
const DeleteScheduleEvent({required this.id});
@override
List<Object> get props => [id];
}

View File

@ -75,3 +75,15 @@ class TimerRunInProgress extends ThreeGangState {
} }
class TimerRunComplete extends ThreeGangState {} class TimerRunComplete extends ThreeGangState {}
class ThreeGangSaveSchedule extends ThreeGangState {}
class IsToggleState extends ThreeGangState {
final bool? onOff;
const IsToggleState({this.onOff});
}
class ChangeTimeState extends ThreeGangState {}
class UpdateCreateScheduleState extends ThreeGangState {
final bool createSchedule;
UpdateCreateScheduleState(this.createSchedule);
}

View File

@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart'; import 'package:firebase_database/firebase_database.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart';
@ -11,9 +12,11 @@ import 'package:syncrow_app/features/devices/model/schedule_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart'; import 'package:syncrow_app/features/devices/model/status_model.dart';
import 'package:syncrow_app/features/devices/model/two_gang_model.dart'; import 'package:syncrow_app/features/devices/model/two_gang_model.dart';
import 'package:syncrow_app/services/api/devices_api.dart'; import 'package:syncrow_app/services/api/devices_api.dart';
import 'package:syncrow_app/utils/helpers/snack_bar.dart';
class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> { class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
final String twoGangId; final String twoGangId;
final String switchCode;
TwoGangModel deviceStatus = TwoGangModel( TwoGangModel deviceStatus = TwoGangModel(
firstSwitch: false, firstSwitch: false,
secondSwitch: false, secondSwitch: false,
@ -21,30 +24,18 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
secondCountDown: 0, secondCountDown: 0,
); );
Timer? _timer; Timer? _timer;
// Timer? _firstSwitchTimer;
// Timer? _secondSwitchTimer;
// Timer? _thirdSwitchTimer;
bool twoGangGroup = false; bool twoGangGroup = false;
List<DeviceModel> devicesList = []; List<DeviceModel> devicesList = [];
List<GroupTwoGangModel> groupTwoGangList = []; List<GroupTwoGangModel> groupTwoGangList = [];
bool allSwitchesOn = true; bool allSwitchesOn = true;
bool toggleSchedule = true;
List<String> selectedDays = []; List<String> selectedDays = [];
bool createSchedule = false; bool createSchedule = false;
List<ScheduleModel> listSchedule = [ List<ScheduleModel> listSchedule = [];
ScheduleModel(
id: '1',
category: 'category',
enable: true,
function: FunctionModel(code: 'code', value: true),
time: 'time',
timerId: 'timerId',
timezoneId: 'timezoneId',
days: ['S'])
];
TwoGangBloc({required this.twoGangId}) : super(InitialState()) { TwoGangBloc({required this.twoGangId,required this.switchCode}) : super(InitialState()) {
on<InitialEvent>(_fetchTwoGangStatus); on<InitialEvent>(_fetchTwoGangStatus);
on<TwoGangUpdated>(_twoGangUpdated); on<TwoGangUpdated>(_twoGangUpdated);
on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch); on<ChangeFirstSwitchStatusEvent>(_changeFirstSwitch);
@ -59,19 +50,32 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
on<GroupAllOnEvent>(_groupAllOn); on<GroupAllOnEvent>(_groupAllOn);
on<GroupAllOffEvent>(_groupAllOff); on<GroupAllOffEvent>(_groupAllOff);
on<ToggleDaySelectionEvent>(toggleDaySelection); on<ToggleDaySelectionEvent>(toggleDaySelection);
on<TwoGangSave>(saveSchedule);
on<GetScheduleEvent>(getSchedule);
on<ToggleScheduleEvent>(toggleRepeat);
on<DeleteScheduleEvent>(deleteSchedule);
} }
DateTime? selectedTime; DateTime? selectedTime = DateTime.now();
void toggleCreateSchedule() { void toggleCreateSchedule() {
emit(LoadingInitialState()); emit(LoadingInitialState());
createSchedule = !createSchedule; createSchedule = !createSchedule;
selectedDays.clear();
selectedTime=DateTime.now();
emit(UpdateCreateScheduleState(createSchedule)); emit(UpdateCreateScheduleState(createSchedule));
emit(ChangeSlidingSegmentState(value: 1)); emit(ChangeSlidingSegmentState(value: 1));
} }
int selectedTabIndex = 0;
void _fetchTwoGangStatus( void toggleSelectedIndex(index) {
InitialEvent event, Emitter<TwoGangState> emit) async { emit(LoadingInitialState());
selectedTabIndex = index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void _fetchTwoGangStatus(InitialEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
twoGangGroup = event.groupScreen; twoGangGroup = event.groupScreen;
@ -359,13 +363,16 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
seconds = event.duration.inSeconds; seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice( final response = await DevicesAPI.controlDevice(
DeviceControlModel( DeviceControlModel(
deviceId: twoGangId, code: event.deviceCode, value: seconds), deviceId: twoGangId,
code: event.deviceCode,
value: seconds),
twoGangId); twoGangId);
if (response['success'] ?? false) { if (response['success'] ?? false) {
if (event.deviceCode == 'countdown_1') { if (event.deviceCode == 'countdown_1') {
deviceStatus.firstCountDown = seconds; deviceStatus.firstCountDown = seconds;
} else if (event.deviceCode == 'countdown_2') { }
else if (event.deviceCode == 'countdown_2') {
deviceStatus.secondCountDown = seconds; deviceStatus.secondCountDown = seconds;
} }
} else { } else {
@ -388,6 +395,7 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
GetCounterEvent event, Emitter<TwoGangState> emit) async { GetCounterEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState()); emit(LoadingInitialState());
try { try {
add(GetScheduleEvent());
var response = await DevicesAPI.getDeviceStatus(twoGangId); var response = await DevicesAPI.getDeviceStatus(twoGangId);
List<StatusModel> statusModelList = []; List<StatusModel> statusModelList = [];
for (var status in response['status']) { for (var status in response['status']) {
@ -457,13 +465,96 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
add(ChangeSlidingSegment(value: 1)); add(ChangeSlidingSegment(value: 1));
} }
saveSchedule() async { Future<void> saveSchedule(TwoGangSave event, Emitter<TwoGangState> emit,) async {
final response = await DevicesAPI.postSchedule( try {
category: 'switch_1', if(selectedDays.isNotEmpty) {
emit(LoadingInitialState());
final response = await DevicesAPI.postSchedule(
category: switchCode,
deviceId: twoGangId,
time: getTimeStampWithoutSeconds(selectedTime).toString(),
code: switchCode,
value: toggleSchedule,
days: selectedDays);
CustomSnackBar.displaySnackBar('Save Successfully');
add(GetScheduleEvent());
emit(TwoGangSaveSchedule());
toggleCreateSchedule();
}else{
CustomSnackBar.displaySnackBar('Please select days');
}
} catch (e) {
emit(FailedState(error: e.toString()));
}
}
Future<void> getSchedule(GetScheduleEvent event, Emitter<TwoGangState> emit,) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.getSchedule(
category: switchCode,
deviceId: twoGangId, deviceId: twoGangId,
time: 'selectedTime', );
code: 'switch_1', List<dynamic> jsonData = response;
value: true, listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
days: selectedDays); emit(InitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
emit(FailedState(error: errorMessage.toString()));
}
}
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
print(dateTime);
if (dateTime == null) return null;
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
dateTime.day, dateTime.hour, dateTime.minute);
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
}
Future toggleRepeat(
ToggleScheduleEvent event, Emitter<TwoGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.changeSchedule(
scheduleId: event.id,
deviceUuid: twoGangId,
enable: event.toggle);
if (response == true) {
add(GetScheduleEvent());
toggleSchedule = event.toggle;
return toggleSchedule;
}
emit(IsToggleState(onOff: toggleSchedule));
add(const ChangeSlidingSegment(value: 1));
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
// debugPrint('errorMessage=${errorMessage}');
emit(FailedState(error: errorMessage.toString()));
}
}
Future deleteSchedule(
DeleteScheduleEvent event, Emitter<TwoGangState> emit) async {
try {
emit(LoadingInitialState());
final response = await DevicesAPI.deleteSchedule(
scheduleId: event.id,
deviceUuid: twoGangId, );
if (response == true) {
add(GetScheduleEvent());
// toggleSchedule = event.id;
return toggleSchedule;
}
emit(IsToggleState(onOff: toggleSchedule));
add(const ChangeSlidingSegment(value: 1));
} on DioException catch (e) {
final errorData = e.response!.data;
String errorMessage = errorData['message'];
print('errorMessage=${errorMessage}');
emit(FailedState(error: errorMessage.toString()));
}
} }
} }

View File

@ -10,6 +10,15 @@ abstract class TwoGangEvent extends Equatable {
class LoadingEvent extends TwoGangEvent {} class LoadingEvent extends TwoGangEvent {}
class TwoGangUpdated extends TwoGangEvent {} class TwoGangUpdated extends TwoGangEvent {}
class TwoGangSave extends TwoGangEvent {}
class ToggleScheduleEvent extends TwoGangEvent {
final String id;
final bool toggle;
const ToggleScheduleEvent({required this.toggle,required this.id});
@override
List<Object> get props => [toggle,id];
}
class errorMessage extends TwoGangEvent {}
class ToggleDaySelectionEvent extends TwoGangEvent { class ToggleDaySelectionEvent extends TwoGangEvent {
final String key; final String key;
@ -101,3 +110,21 @@ class TickTimer extends TwoGangEvent {
class StopTimer extends TwoGangEvent {} class StopTimer extends TwoGangEvent {}
class OnClose extends TwoGangEvent {} class OnClose extends TwoGangEvent {}
class GetScheduleEvent extends TwoGangEvent {}
class DeleteScheduleEvent extends TwoGangEvent {
final String id;
const DeleteScheduleEvent({required this.id});
@override
List<Object> get props => [id];
}
class TabChangedEvent extends TwoGangEvent {
final int index;
TabChangedEvent({required this.index});
}

View File

@ -11,6 +11,7 @@ class TwoGangState extends Equatable {
} }
class InitialState extends TwoGangState {} class InitialState extends TwoGangState {}
class TwoGangSaveSchedule extends TwoGangState {}
class ChangeTimeState extends TwoGangState {} class ChangeTimeState extends TwoGangState {}
class LoadingInitialState extends TwoGangState {} class LoadingInitialState extends TwoGangState {}
@ -77,6 +78,10 @@ class TimerRunInProgress extends TwoGangState {
} }
class TimerRunComplete extends TwoGangState {} class TimerRunComplete extends TwoGangState {}
class IsToggleState extends TwoGangState {
final bool? onOff;
const IsToggleState({this.onOff});
}

View File

@ -1,21 +1,69 @@
class FunctionModel { import 'package:intl/intl.dart';
final String code;
final bool value;
FunctionModel({ class ScheduleModel {
String category;
bool enable;
ScheduleFunctionData function;
String time;
String scheduleId;
String timezoneId;
List<String> days;
ScheduleModel({
required this.category,
required this.enable,
required this.function,
required this.time,
required this.scheduleId,
required this.timezoneId,
required this.days,
});
// Factory method to create an instance from JSON
factory ScheduleModel.fromJson(Map<String, dynamic> json) {
return ScheduleModel(
category: json['category'],
enable: json['enable'],
function: ScheduleFunctionData.fromJson(json['function']),
time:getTimeIn12HourFormat( json['time']),
scheduleId: json['scheduleId'],
timezoneId: json['timezoneId'],
days: List<String>.from(json['days']),
);
}
// Method to convert an instance into JSON
Map<String, dynamic> toJson() {
return {
'category': category,
'enable': enable,
'function': function.toJson(),
'time': time,
'scheduleId': scheduleId,
'timezoneId': timezoneId,
'days': days,
};
}
}
class ScheduleFunctionData {
String code;
bool value;
ScheduleFunctionData({
required this.code, required this.code,
required this.value, required this.value,
}); });
// Convert a JSON object to a FunctionModel instance // Factory method to create an instance from JSON
factory FunctionModel.fromJson(Map<String, dynamic> json) { factory ScheduleFunctionData.fromJson(Map<String, dynamic> json) {
return FunctionModel( return ScheduleFunctionData(
code: json['code'], code: json['code'],
value: json['value'], value: json['value'],
); );
} }
// Convert a FunctionModel instance to a JSON object // Method to convert an instance into JSON
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { return {
'code': code, 'code': code,
@ -24,51 +72,12 @@ class FunctionModel {
} }
} }
class ScheduleModel { String getTimeIn12HourFormat(time) {
final String id; // Parse the time string (in HH:mm format)
final String category; final DateFormat inputFormat = DateFormat("HH:mm");
final bool enable; final DateFormat outputFormat = DateFormat("h:mm a"); // 12-hour format with AM/PM
final FunctionModel function;
final String time;
final String timerId;
final String timezoneId;
final List<String> days;
ScheduleModel({ // Convert the time string
required this.id, DateTime parsedTime = inputFormat.parse(time);
required this.category, return outputFormat.format(parsedTime);
required this.enable, }
required this.function,
required this.time,
required this.timerId,
required this.timezoneId,
required this.days,
});
// Convert a JSON object to a Schedule instance
factory ScheduleModel.fromJson(Map<String, dynamic> json) {
return ScheduleModel(
id: json['id'],
category: json['category'],
enable: json['enable'],
function: FunctionModel.fromJson(json['function']),
time: json['time'],
timerId: json['timerId'],
timezoneId: json['timezoneId'],
days: List<String>.from(json['days']),
);
}
// Convert a Schedule instance to a JSON object
Map<String, dynamic> toJson() {
return {
'category': category,
'enable': enable,
'function': function.toJson(),
'time': time,
'timerId': timerId,
'timezoneId': timezoneId,
'days': days,
};
}
}

View File

@ -20,7 +20,9 @@ class OneGangScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => OneGangBloc(oneGangId : device?.uuid ?? '') create: (context) => OneGangBloc(
switchCode: 'switch_1',
oneGangId : device?.uuid ?? '')
..add(const InitialEvent(groupScreen:false)), ..add(const InitialEvent(groupScreen:false)),
child: BlocBuilder<OneGangBloc, OneGangState>( child: BlocBuilder<OneGangBloc, OneGangState>(
builder: (context, state) { builder: (context, state) {
@ -104,8 +106,9 @@ class OneGangScreen extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
PageRouteBuilder( PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => OneGangTimerScreen( pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
device: device, switchCode:'switch_1' ,
device: device!,
deviceCode: 'countdown_1', deviceCode: 'countdown_1',
))); )));
}, },

View File

@ -7,7 +7,10 @@ import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_bloc.da
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_event.dart'; import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_event.dart';
import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.dart'; import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/shared_widgets/create_schedule.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/schedule_list.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
@ -15,10 +18,186 @@ import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class OneGangTimerScreen extends StatelessWidget { // class OneGangTimerScreen extends StatelessWidget {
final DeviceModel? device; // final DeviceModel? device;
final String? deviceCode; // final String? deviceCode;
const OneGangTimerScreen({super.key,this.device,this.deviceCode}); // const OneGangTimerScreen({super.key,this.device,this.deviceCode});
//
// @override
// Widget build(BuildContext context) {
// return AnnotatedRegion(
// value: SystemUiOverlayStyle(
// statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
// statusBarIconBrightness: Brightness.light,
// ),
// child: Scaffold(
// backgroundColor: ColorsManager.backgroundColor,
// extendBodyBehindAppBar: true,
// extendBody: true,
// appBar: AppBar(
// backgroundColor: Colors.transparent,
// centerTitle: true,
// title: const BodyLarge(
// text: 'Schedule',
// fontColor: ColorsManager.primaryColor,
// fontWeight: FontsManager.bold,
// ),
// ),
// body: SafeArea(
// child: BlocProvider(
// create: (context) => OneGangBloc(
// switchCode: 'switch_1',
// oneGangId: device!.uuid ?? '')..
// ..add(GetCounterEvent(deviceCode: deviceCode!)),
// child: BlocBuilder<OneGangBloc, OneGangState>(
// builder: (context, state) {
// Duration duration = Duration.zero;
// int countNum = 0;
// int tabNum = 0;
// if (state is UpdateTimerState) {
// countNum = state.seconds;
// } else if (state is TimerRunInProgress) {
// countNum = state.remainingTime;
// } else if (state is TimerRunComplete) {
// countNum = 0;
// } else if (state is LoadingNewSate) {
// countNum = 0;
// }
//
// if (state is ChangeSlidingSegmentState) {
// tabNum = state.value;
// }
// return PopScope(
// canPop: false,
// onPopInvoked: (didPop) {
// if (!didPop) {
// BlocProvider.of<OneGangBloc>(context).add(OnClose());
// Navigator.pop(context);
// }
// },
// child: Container(
// width: MediaQuery.sizeOf(context).width,
// height: MediaQuery.sizeOf(context).height,
// padding: const EdgeInsets.all(24),
// decoration: const BoxDecoration(
// image: DecorationImage(
// image: AssetImage(
// Assets.assetsImagesBackground,
// ),
// fit: BoxFit.cover,
// opacity: 0.4,
// ),
// ),
// child: state is LoadingInitialState || state is LoadingNewSate
// ? const Center(
// child: DefaultContainer(
// width: 50, height: 50, child: CircularProgressIndicator()),
// )
// : Column(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// Container(
// width: MediaQuery.sizeOf(context).width,
// decoration: const ShapeDecoration(
// color: ColorsManager.slidingBlueColor,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.all(Radius.circular(20)),
// ),
// ),
// child: CupertinoSlidingSegmentedControl<int>(
// thumbColor: ColorsManager.slidingBlueColor,
// onValueChanged: (value) {
// BlocProvider.of<OneGangBloc>(context)
// .add(ChangeSlidingSegment(value: value ?? 0));
// },
// groupValue:
// state is ChangeSlidingSegmentState ? state.value : 0,
// backgroundColor: Colors.white,
// children: <int, Widget>{
// 0: Container(
// padding: const EdgeInsets.symmetric(vertical: 10),
// child: BodySmall(
// text: 'Countdown',
// style: context.bodySmall.copyWith(
// color: ColorsManager.blackColor,
// fontSize: 12,
// fontWeight: FontWeight.w400,
// ),
// ),
// ),
// 1: Container(
// padding: const EdgeInsets.symmetric(vertical: 10),
// child: Text(
// 'Schedule',
// style: context.bodySmall.copyWith(
// color: ColorsManager.blackColor,
// fontSize: 12,
// fontWeight: FontWeight.w400,
// ),
// ),
// ),
// },
// ),
// ),
// if (tabNum == 0)
// countNum > 0
// ? BodyLarge(
// text: _formatDuration(countNum),
// fontColor: ColorsManager.slidingBlueColor,
// fontSize: 40,
// )
// : CupertinoTimerPicker(
// mode: CupertinoTimerPickerMode.hm,
// onTimerDurationChanged: (Duration newDuration) {
// duration = newDuration;
// },
// ),
// if (tabNum == 0)
// GestureDetector(
// onTap: () {
// if (state is LoadingNewSate) {
// return;
// }
// if (countNum > 0) {
// BlocProvider.of<OneGangBloc>(context).add(
// SetCounterValue(
// deviceCode: deviceCode!,
// duration: Duration.zero));
// } else if (duration != Duration.zero) {
// BlocProvider.of<OneGangBloc>(context).add(
// SetCounterValue(
// deviceCode: deviceCode!, duration: duration));
// }
// },
// child: SvgPicture.asset(
// countNum > 0 ? Assets.pauseIcon : Assets.playIcon))
// ],
// )));
// },
// ),
// ),
// ),
// ),
// );
// }
// String _formatDuration(int seconds) {
// final hours = (seconds ~/ 3600).toString().padLeft(2, '0');
// final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');
// final secs = (seconds % 60).toString().padLeft(2, '0');
// return '$hours:$minutes:$secs';
// }
// }
class TimerScheduleScreen extends StatelessWidget {
final DeviceModel device;
final String deviceCode;
final String switchCode;
const TimerScheduleScreen(
{required this.device,
required this.deviceCode,
required this.switchCode,
super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -27,90 +206,102 @@ class OneGangTimerScreen extends StatelessWidget {
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5), statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
statusBarIconBrightness: Brightness.light, statusBarIconBrightness: Brightness.light,
), ),
child: Scaffold( child: BlocProvider(
backgroundColor: ColorsManager.backgroundColor, create: (context) =>
extendBodyBehindAppBar: true, OneGangBloc(switchCode: switchCode, oneGangId: device.uuid ?? '')
extendBody: true, ..add(GetCounterEvent(deviceCode: deviceCode))
appBar: AppBar( ..add(GetScheduleEvent()),
backgroundColor: Colors.transparent, child: BlocBuilder<OneGangBloc, OneGangState>(
centerTitle: true, builder: (context, state) {
title: const BodyLarge( final oneGangBloc = BlocProvider.of<OneGangBloc>(context);
text: 'Schedule', Duration duration = Duration.zero;
fontColor: ColorsManager.primaryColor, int countNum = 0;
fontWeight: FontsManager.bold, if (state is UpdateTimerState) {
), countNum = state.seconds;
), } else if (state is TimerRunInProgress) {
body: SafeArea( countNum = state.remainingTime;
child: BlocProvider( } else if (state is TimerRunComplete) {
create: (context) => OneGangBloc(oneGangId: device!.uuid ?? '') countNum = 0;
..add(GetCounterEvent(deviceCode: deviceCode!)), } else if (state is LoadingNewSate) {
child: BlocBuilder<OneGangBloc, OneGangState>( countNum = 0;
builder: (context, state) { }
Duration duration = Duration.zero; return PopScope(
int countNum = 0; canPop: false,
int tabNum = 0; onPopInvoked: (didPop) {
if (state is UpdateTimerState) { if (!didPop) {
countNum = state.seconds; oneGangBloc.add(OnClose());
} else if (state is TimerRunInProgress) { Navigator.pop(context);
countNum = state.remainingTime; }
} else if (state is TimerRunComplete) { },
countNum = 0; child: DefaultTabController(
} else if (state is LoadingNewSate) { length: 2,
countNum = 0; child: DefaultScaffold(
} appBar: AppBar(
backgroundColor: Colors.transparent,
if (state is ChangeSlidingSegmentState) { centerTitle: true,
tabNum = state.value; title: const BodyLarge(
} text: 'Schedule',
return PopScope( fontColor: ColorsManager.primaryColor,
canPop: false, fontWeight: FontsManager.bold,
onPopInvoked: (didPop) {
if (!didPop) {
BlocProvider.of<OneGangBloc>(context).add(OnClose());
Navigator.pop(context);
}
},
child: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
padding: const EdgeInsets.all(24),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
Assets.assetsImagesBackground,
),
fit: BoxFit.cover,
opacity: 0.4,
),
), ),
child: state is LoadingInitialState || state is LoadingNewSate actions: [
? const Center( oneGangBloc.createSchedule == true ?
child: DefaultContainer( TextButton(
width: 50, height: 50, child: CircularProgressIndicator()), onPressed: () {
) oneGangBloc.add(ThreeGangSave());
: Column( },
mainAxisAlignment: MainAxisAlignment.spaceBetween, child: const Text('Save')
children: [ ) :
Container( oneGangBloc.selectedTabIndex==1? IconButton(
width: MediaQuery.sizeOf(context).width, onPressed: () {
decoration: const ShapeDecoration( oneGangBloc.toggleCreateSchedule();
},
icon: const Icon(Icons.add),
):SizedBox(),
],
),
child:
state is LoadingInitialState?
const Center(child: CircularProgressIndicator()):
Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
decoration: const ShapeDecoration(
color: ColorsManager.onPrimaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(30)),
),
),
child: TabBar(
onTap: (value) {
if(value==0){
if(oneGangBloc.createSchedule == true){
oneGangBloc.toggleCreateSchedule();
}
oneGangBloc.toggleSelectedIndex(0);
}else{
oneGangBloc.toggleSelectedIndex(1);
}
},
indicatorColor: Colors.white, // Customize the indicator
dividerHeight: 0,
// indicatorWeight: MediaQuery.of(context).size.width,
// indicatorSize: ,
indicatorSize: TabBarIndicatorSize.tab,
indicator: const ShapeDecoration(
color: ColorsManager.slidingBlueColor, color: ColorsManager.slidingBlueColor,
shape: RoundedRectangleBorder( shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20)), borderRadius:
BorderRadius.all(Radius.circular(20)),
), ),
), ),
child: CupertinoSlidingSegmentedControl<int>( tabs: [
thumbColor: ColorsManager.slidingBlueColor, Tab(
onValueChanged: (value) { child: Container(
BlocProvider.of<OneGangBloc>(context) padding: const EdgeInsets.symmetric(
.add(ChangeSlidingSegment(value: value ?? 0)); vertical: 10),
},
groupValue:
state is ChangeSlidingSegmentState ? state.value : 0,
backgroundColor: Colors.white,
children: <int, Widget>{
0: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
child: BodySmall( child: BodySmall(
text: 'Countdown', text: 'Countdown',
style: context.bodySmall.copyWith( style: context.bodySmall.copyWith(
@ -120,7 +311,9 @@ class OneGangTimerScreen extends StatelessWidget {
), ),
), ),
), ),
1: Container( ),
Tab(
child: Container(
padding: const EdgeInsets.symmetric(vertical: 10), padding: const EdgeInsets.symmetric(vertical: 10),
child: Text( child: Text(
'Schedule', 'Schedule',
@ -131,50 +324,106 @@ class OneGangTimerScreen extends StatelessWidget {
), ),
), ),
), ),
}, ),
), ],
), ),
if (tabNum == 0)
countNum > 0 ),
? BodyLarge( Expanded(
text: _formatDuration(countNum), child: TabBarView(
fontColor: ColorsManager.slidingBlueColor, children: [
fontSize: 40, Center(
) child: Container(
: CupertinoTimerPicker( child: Column(
mode: CupertinoTimerPickerMode.hm, mainAxisAlignment: MainAxisAlignment.center,
onTimerDurationChanged: (Duration newDuration) { children: [
duration = newDuration; countNum > 0
}, ? BodyLarge(
), text: _formatDuration(countNum),
if (tabNum == 0) fontColor:
GestureDetector( ColorsManager.slidingBlueColor,
onTap: () { fontSize: 40,
if (state is LoadingNewSate) { )
return; : CupertinoTimerPicker(
} mode: CupertinoTimerPickerMode.hm,
if (countNum > 0) { onTimerDurationChanged:
BlocProvider.of<OneGangBloc>(context).add( (Duration newDuration) {
SetCounterValue( duration = newDuration;
deviceCode: deviceCode!, },
duration: Duration.zero)); ),
} else if (duration != Duration.zero) { GestureDetector(
BlocProvider.of<OneGangBloc>(context).add( onTap: () {
SetCounterValue( if (state is LoadingNewSate) {
deviceCode: deviceCode!, duration: duration)); return;
} }
}, if (countNum > 0) {
child: SvgPicture.asset( oneGangBloc.add(SetCounterValue(
countNum > 0 ? Assets.pauseIcon : Assets.playIcon)) deviceCode: deviceCode,
], duration: Duration.zero));
))); } else if (duration != Duration.zero) {
}, oneGangBloc.add(SetCounterValue(
), deviceCode: deviceCode,
), duration: duration));
}
},
child: SvgPicture.asset(countNum > 0
? Assets.pauseIcon
: Assets.playIcon)),
],
),
),
),
Column(
mainAxisAlignment:oneGangBloc.listSchedule.isNotEmpty?
MainAxisAlignment.start:MainAxisAlignment.center,
children: [
SizedBox(
child: oneGangBloc.createSchedule == true ?
CreateSchedule(
onToggleChanged: (bool isOn) {
oneGangBloc.toggleSchedule = isOn;
},
onDateTimeChanged: (DateTime dateTime) {
oneGangBloc.selectedTime=dateTime;
},
days: oneGangBloc.days,
selectDays: (List<String> selectedDays) {
oneGangBloc.selectedDays = selectedDays;
},
)
:
Padding(
padding: const EdgeInsets.only(top: 10),
child: ScheduleListView(
listSchedule: oneGangBloc.listSchedule, // Pass the schedule list here
onDismissed: (scheduleId) {
oneGangBloc.listSchedule.removeWhere((schedule) => schedule.scheduleId == scheduleId);
oneGangBloc.add(DeleteScheduleEvent(id: scheduleId));
},
onToggleSchedule: (scheduleId, isEnabled) {
oneGangBloc.add(ToggleScheduleEvent(
id: scheduleId,
toggle: isEnabled,
));
},
),
),
),
],
),
],
),
),
],
),
))
);
},
), ),
), ),
); );
} }
String _formatDuration(int seconds) { String _formatDuration(int seconds) {
final hours = (seconds ~/ 3600).toString().padLeft(2, '0'); final hours = (seconds ~/ 3600).toString().padLeft(2, '0');
final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0'); final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');

View File

@ -63,7 +63,8 @@ class ScheduleScreen extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
PageRouteBuilder( PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => TimerScreen( pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
switchCode :"switch_1",
device: device, device: device,
deviceCode: 'countdown_1', deviceCode: 'countdown_1',
))); )));
@ -99,10 +100,11 @@ class ScheduleScreen extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
PageRouteBuilder( PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => TimerScreen( pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
device: device, switchCode :"switch_2",
deviceCode: 'countdown_2', device: device,
))); deviceCode: 'countdown_2',
)));
}, },
child: Container( child: Container(
padding: padding:
@ -135,8 +137,9 @@ class ScheduleScreen extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
PageRouteBuilder( PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => TimerScreen( pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
device: device, switchCode :"switch_3",
device: device,
deviceCode: 'countdown_3', deviceCode: 'countdown_3',
))); )));
}, },

View File

@ -22,7 +22,9 @@ class ThreeGangScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => ThreeGangBloc(threeGangId: device?.uuid ?? '') create: (context) => ThreeGangBloc(
switchCode: '',
threeGangId: device?.uuid ?? '')
..add(InitialEvent(groupScreen: device != null ? false : true)), ..add(InitialEvent(groupScreen: device != null ? false : true)),
child: BlocBuilder<ThreeGangBloc, ThreeGangState>( child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
builder: (context, state) { builder: (context, state) {

View File

@ -7,7 +7,10 @@ import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_blo
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart'; import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart'; import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/shared_widgets/create_schedule.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/schedule_list.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
@ -15,10 +18,254 @@ import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
class TimerScreen extends StatelessWidget { // class TimerScreen extends StatelessWidget {
// final DeviceModel device;
// final String deviceCode;
// final String switchCode;
// const TimerScreen(
// {required this.device,
// required this.deviceCode,
// required this.switchCode,
// super.key});
//
// @override
// Widget build(BuildContext context) {
// return AnnotatedRegion(
// value: SystemUiOverlayStyle(
// statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
// statusBarIconBrightness: Brightness.light,
// ),
// child:
//
// BlocProvider(
// create: (context) => ThreeGangBloc(
// switchCode: switchCode, threeGangId: device.uuid ?? '')..add(GetScheduleEvent())
// ..add(GetCounterEvent(deviceCode: deviceCode)),
// child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
// builder: (context, state) {
// final threeGangBloc = BlocProvider.of<ThreeGangBloc>(context);
//
// Duration duration = Duration.zero;
// int countNum = 0;
// int tabNum = 0;
// if (state is UpdateTimerState) {
// countNum = state.seconds;
// } else if (state is TimerRunInProgress) {
// countNum = state.remainingTime;
// } else if (state is TimerRunComplete) {
// countNum = 0;
// } else if (state is LoadingNewSate) {
// countNum = 0;
// }
//
// if (state is ChangeSlidingSegmentState) {
// tabNum = state.value;
// }
// return Scaffold(
// backgroundColor: ColorsManager.backgroundColor,
// extendBodyBehindAppBar: true,
// extendBody: true,
// appBar: AppBar(
// backgroundColor: Colors.transparent,
// centerTitle: true,
// title: const BodyLarge(
// text: 'Schedule',
// fontColor: ColorsManager.primaryColor,
// fontWeight: FontsManager.bold,
// ),
// actions: [
// if (tabNum == 1)
// threeGangBloc.createSchedule == true
// ? TextButton(onPressed: () {
// threeGangBloc.add(ThreeGangSave() );
// }, child: const Text('Save'))
// : IconButton(
// onPressed: () {
// threeGangBloc.toggleCreateSchedule();
// },
// icon: const Icon(Icons.add),
// ),
// ],
// ),
// body: SafeArea(
// child:PopScope(
// canPop: false,
// onPopInvoked: (didPop) {
// if (!didPop) {
// BlocProvider.of<ThreeGangBloc>(context).add(OnClose());
// Navigator.pop(context);
// }
// },
// child: Container(
// width: MediaQuery.sizeOf(context).width,
// padding: const EdgeInsets.all(24),
// decoration: const BoxDecoration(
// image: DecorationImage(
// image: AssetImage(
// Assets.assetsImagesBackground,
// ),
// fit: BoxFit.cover,
// opacity: 0.4,
// ),
// ),
// child: state is LoadingInitialState ||
// state is LoadingNewSate
// ? const Center(
// child: DefaultContainer(
// width: 50,
// height: 50,
// child: CircularProgressIndicator()),
// )
// : Column(
// children: [
// Container(
// width: MediaQuery.sizeOf(context).width,
// decoration: const ShapeDecoration(
// color: ColorsManager.slidingBlueColor,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.all(
// Radius.circular(20)),
// ),
// ),
// child:
// CupertinoSlidingSegmentedControl<int>(
// thumbColor:
// ColorsManager.slidingBlueColor,
// onValueChanged: (value) {
// BlocProvider.of<ThreeGangBloc>(context)
// .add(ChangeSlidingSegment(
// value: value ?? 0));
// },
// groupValue:
// state is ChangeSlidingSegmentState
// ? state.value
// : 0,
// backgroundColor: Colors.white,
// children: <int, Widget>{
// 0: Container(
// padding: const EdgeInsets.symmetric(
// vertical: 10),
// child: BodySmall(
// text: 'Countdown',
// style: context.bodySmall.copyWith(
// color: ColorsManager.blackColor,
// fontSize: 12,
// fontWeight: FontWeight.w400,
// ),
// ),
// ),
// 1: Container(
// padding: const EdgeInsets.symmetric(
// vertical: 10),
// child: Text(
// 'Schedule',
// style: context.bodySmall.copyWith(
// color: ColorsManager.blackColor,
// fontSize: 12,
// fontWeight: FontWeight.w400,
// ),
// ),
// ),
// },
// ),
// ),
// if (tabNum == 0)
// countNum > 0
// ? BodyLarge(
// text: _formatDuration(countNum),
// fontColor:
// ColorsManager.slidingBlueColor,
// fontSize: 40,
// )
// : CupertinoTimerPicker(
// mode: CupertinoTimerPickerMode.hm,
// onTimerDurationChanged:
// (Duration newDuration) {
// duration = newDuration;
// },
// ),
// if (tabNum == 0)
// GestureDetector(
// onTap: () {
// if (state is LoadingNewSate) {
// return;
// }
// if (countNum > 0) {
// BlocProvider.of<ThreeGangBloc>(
// context)
// .add(SetCounterValue(
// deviceCode: deviceCode,
// duration: Duration.zero));
// } else if (duration !=
// Duration.zero) {
// BlocProvider.of<ThreeGangBloc>(
// context)
// .add(SetCounterValue(
// deviceCode: deviceCode,
// duration: duration));
// }
// },
// child: SvgPicture.asset(countNum > 0
// ? Assets.pauseIcon
// : Assets.playIcon)),
// if (tabNum == 1)
// SizedBox(
// child: threeGangBloc.createSchedule == true
// ? CreateSchedule(
// onToggleChanged: (bool isOn) {
// threeGangBloc.toggleSchedule = isOn;
// },
// onDateTimeChanged: (DateTime dateTime) {
// threeGangBloc.selectedTime = dateTime;
// },
// days: threeGangBloc.days,
// selectDays: (List<String>selectedDays) {
// threeGangBloc.selectedDays = selectedDays;
// },
// ) : SizedBox(
// height: MediaQuery.of(context).size.height/1.9,
// child: ScheduleListView(
// listSchedule: threeGangBloc.listSchedule, // Pass the schedule list here
// onDismissed: (scheduleId) {
// threeGangBloc.listSchedule.removeWhere((schedule) => schedule.scheduleId == scheduleId);
// threeGangBloc.add(DeleteScheduleEvent(id: scheduleId));
// },
// onToggleSchedule: (scheduleId, isEnabled) {
// threeGangBloc.add(ToggleScheduleEvent(
// id: scheduleId,
// toggle: isEnabled,
// ));
// },
// ),
// ))
// ],
// )))
// ),
// );
// },
// ),
// ),
// );
// }
//
// String _formatDuration(int seconds) {
// final hours = (seconds ~/ 3600).toString().padLeft(2, '0');
// final minutes = ((seconds % 3600) ~/ 60).toString().padLeft(2, '0');
// final secs = (seconds % 60).toString().padLeft(2, '0');
// return '$hours:$minutes:$secs';
// }
// }
class TimerScheduleScreen extends StatelessWidget {
final DeviceModel device; final DeviceModel device;
final String deviceCode; final String deviceCode;
const TimerScreen({required this.device, required this.deviceCode, super.key}); final String switchCode;
const TimerScheduleScreen(
{required this.device,
required this.deviceCode,
required this.switchCode,
super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -27,150 +274,219 @@ class TimerScreen extends StatelessWidget {
statusBarColor: ColorsManager.primaryColor.withOpacity(0.5), statusBarColor: ColorsManager.primaryColor.withOpacity(0.5),
statusBarIconBrightness: Brightness.light, statusBarIconBrightness: Brightness.light,
), ),
child: Scaffold( child: BlocProvider(
backgroundColor: ColorsManager.backgroundColor, create: (context) =>
extendBodyBehindAppBar: true, ThreeGangBloc(switchCode: switchCode, threeGangId: device.uuid ?? '')
extendBody: true, ..add(GetCounterEvent(deviceCode: deviceCode))
appBar: AppBar( ..add(GetScheduleEvent()),
backgroundColor: Colors.transparent, child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
centerTitle: true, builder: (context, state) {
title: const BodyLarge( final threeGangBloc = BlocProvider.of<ThreeGangBloc>(context);
text: 'Schedule', Duration duration = Duration.zero;
fontColor: ColorsManager.primaryColor, int countNum = 0;
fontWeight: FontsManager.bold, if (state is UpdateTimerState) {
), countNum = state.seconds;
), } else if (state is TimerRunInProgress) {
body: SafeArea( countNum = state.remainingTime;
child: BlocProvider( } else if (state is TimerRunComplete) {
create: (context) => ThreeGangBloc(threeGangId: device.uuid ?? '') countNum = 0;
..add(GetCounterEvent(deviceCode: deviceCode)), } else if (state is LoadingNewSate) {
child: BlocBuilder<ThreeGangBloc, ThreeGangState>( countNum = 0;
builder: (context, state) { }
Duration duration = Duration.zero; return PopScope(
int countNum = 0; canPop: false,
int tabNum = 0; onPopInvoked: (didPop) {
if (state is UpdateTimerState) { if (!didPop) {
countNum = state.seconds; threeGangBloc.add(OnClose());
} else if (state is TimerRunInProgress) { Navigator.pop(context);
countNum = state.remainingTime; }
} else if (state is TimerRunComplete) { },
countNum = 0; child: DefaultTabController(
} else if (state is LoadingNewSate) { length: 2,
countNum = 0; child: DefaultScaffold(
} appBar: AppBar(
backgroundColor: Colors.transparent,
if (state is ChangeSlidingSegmentState) { centerTitle: true,
tabNum = state.value; title: const BodyLarge(
} text: 'Schedule',
return PopScope( fontColor: ColorsManager.primaryColor,
canPop: false, fontWeight: FontsManager.bold,
onPopInvoked: (didPop) {
if (!didPop) {
BlocProvider.of<ThreeGangBloc>(context).add(OnClose());
Navigator.pop(context);
}
},
child: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
padding: const EdgeInsets.all(24),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(
Assets.assetsImagesBackground,
),
fit: BoxFit.cover,
opacity: 0.4,
),
), ),
child: state is LoadingInitialState || state is LoadingNewSate actions: [
? const Center( threeGangBloc.createSchedule == true ?
child: DefaultContainer( TextButton(
width: 50, height: 50, child: CircularProgressIndicator()), onPressed: () {
) threeGangBloc.add(ThreeGangSave());
: Column( },
mainAxisAlignment: MainAxisAlignment.spaceBetween, child: const Text('Save')
children: [ ) :
Container( threeGangBloc.selectedTabIndex==1? IconButton(
width: MediaQuery.sizeOf(context).width, onPressed: () {
decoration: const ShapeDecoration( threeGangBloc.toggleCreateSchedule();
color: ColorsManager.slidingBlueColor, },
shape: RoundedRectangleBorder( icon: const Icon(Icons.add),
borderRadius: BorderRadius.all(Radius.circular(20)), ):SizedBox(),
],
),
child:
state is LoadingInitialState?
const Center(child: CircularProgressIndicator()):
Column(
children: [
Container(
width: MediaQuery.of(context).size.width,
decoration: const ShapeDecoration(
color: ColorsManager.onPrimaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(30)),
),
),
child: TabBar(
onTap: (value) {
if(value==0){
if(threeGangBloc.createSchedule == true){
threeGangBloc.toggleCreateSchedule();
}
threeGangBloc.toggleSelectedIndex(0);
}else{
threeGangBloc.toggleSelectedIndex(1);
}
},
indicatorColor: Colors.white, // Customize the indicator
dividerHeight: 0,
// indicatorWeight: MediaQuery.of(context).size.width,
// indicatorSize: ,
indicatorSize: TabBarIndicatorSize.tab,
indicator: const ShapeDecoration(
color: ColorsManager.slidingBlueColor,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.all(Radius.circular(20)),
),
),
tabs: [
Tab(
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 10),
child: BodySmall(
text: 'Countdown',
style: context.bodySmall.copyWith(
color: ColorsManager.blackColor,
fontSize: 12,
fontWeight: FontWeight.w400,
), ),
), ),
child: CupertinoSlidingSegmentedControl<int>( ),
thumbColor: ColorsManager.slidingBlueColor, ),
onValueChanged: (value) { Tab(
BlocProvider.of<ThreeGangBloc>(context) child: Container(
.add(ChangeSlidingSegment(value: value ?? 0)); padding: const EdgeInsets.symmetric(vertical: 10),
}, child: Text(
groupValue: 'Schedule',
state is ChangeSlidingSegmentState ? state.value : 0, style: context.bodySmall.copyWith(
backgroundColor: Colors.white, color: ColorsManager.blackColor,
children: <int, Widget>{ fontSize: 12,
0: Container( fontWeight: FontWeight.w400,
padding: const EdgeInsets.symmetric(vertical: 10), ),
child: BodySmall(
text: 'Countdown',
style: context.bodySmall.copyWith(
color: ColorsManager.blackColor,
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
),
1: Container(
padding: const EdgeInsets.symmetric(vertical: 10),
child: Text(
'Schedule',
style: context.bodySmall.copyWith(
color: ColorsManager.blackColor,
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
),
},
), ),
), ),
if (tabNum == 0) ),
countNum > 0 ],
? BodyLarge( ),
text: _formatDuration(countNum),
fontColor: ColorsManager.slidingBlueColor, ),
fontSize: 40, Expanded(
) child: TabBarView(
: CupertinoTimerPicker( children: [
mode: CupertinoTimerPickerMode.hm, Center(
onTimerDurationChanged: (Duration newDuration) { child: Container(
duration = newDuration; child: Column(
}, mainAxisAlignment: MainAxisAlignment.center,
), children: [
if (tabNum == 0) countNum > 0
GestureDetector( ? BodyLarge(
onTap: () { text: _formatDuration(countNum),
if (state is LoadingNewSate) { fontColor:
return; ColorsManager.slidingBlueColor,
} fontSize: 40,
if (countNum > 0) { )
BlocProvider.of<ThreeGangBloc>(context).add( : CupertinoTimerPicker(
SetCounterValue( mode: CupertinoTimerPickerMode.hm,
onTimerDurationChanged:
(Duration newDuration) {
duration = newDuration;
},
),
GestureDetector(
onTap: () {
if (state is LoadingNewSate) {
return;
}
if (countNum > 0) {
threeGangBloc.add(SetCounterValue(
deviceCode: deviceCode, deviceCode: deviceCode,
duration: Duration.zero)); duration: Duration.zero));
} else if (duration != Duration.zero) { } else if (duration != Duration.zero) {
BlocProvider.of<ThreeGangBloc>(context).add( threeGangBloc.add(SetCounterValue(
SetCounterValue( deviceCode: deviceCode,
deviceCode: deviceCode, duration: duration)); duration: duration));
} }
},
child: SvgPicture.asset(countNum > 0
? Assets.pauseIcon
: Assets.playIcon)),
],
),
),
),
Column(
mainAxisAlignment:threeGangBloc.listSchedule.isNotEmpty?
MainAxisAlignment.start:MainAxisAlignment.center,
children: [
SizedBox(
child: threeGangBloc.createSchedule == true ?
CreateSchedule(
onToggleChanged: (bool isOn) {
threeGangBloc.toggleSchedule = isOn;
}, },
child: SvgPicture.asset( onDateTimeChanged: (DateTime dateTime) {
countNum > 0 ? Assets.pauseIcon : Assets.playIcon)) threeGangBloc.selectedTime=dateTime;
], },
))); days: threeGangBloc.days,
}, selectDays: (List<String> selectedDays) {
), threeGangBloc.selectedDays = selectedDays;
), },
)
:
Padding(
padding: const EdgeInsets.only(top: 10),
child: ScheduleListView(
listSchedule: threeGangBloc.listSchedule, // Pass the schedule list here
onDismissed: (scheduleId) {
threeGangBloc.listSchedule.removeWhere((schedule) => schedule.scheduleId == scheduleId);
threeGangBloc.add(DeleteScheduleEvent(id: scheduleId));
},
onToggleSchedule: (scheduleId, isEnabled) {
threeGangBloc.add(ToggleScheduleEvent(
id: scheduleId,
toggle: isEnabled,
));
},
),
),
),
],
),
],
),
),
],
),
))
);
},
), ),
), ),
); );

View File

@ -15,14 +15,16 @@ import 'package:syncrow_app/utils/context_extension.dart';
import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class TwoGangScreen extends StatelessWidget { class TwoGangScreen extends StatelessWidget {
const TwoGangScreen({super.key, this.device}); const TwoGangScreen({super.key, this.device, this.switchCode});
final DeviceModel? device; final DeviceModel? device;
final String? switchCode;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (context) => TwoGangBloc(twoGangId: device?.uuid ?? '') create: (context) => TwoGangBloc(
switchCode: switchCode??'',
twoGangId: device?.uuid ?? '')
..add(InitialEvent(groupScreen: device != null ? false : true)), ..add(InitialEvent(groupScreen: device != null ? false : true)),
child: BlocBuilder<TwoGangBloc, TwoGangState>( child: BlocBuilder<TwoGangBloc, TwoGangState>(
builder: (context, state) { builder: (context, state) {
@ -35,7 +37,6 @@ class TwoGangScreen extends StatelessWidget {
List<GroupTwoGangModel> groupTwoGangModel = []; List<GroupTwoGangModel> groupTwoGangModel = [];
bool allSwitchesOn = false; bool allSwitchesOn = false;
if (state is LoadingNewSate) { if (state is LoadingNewSate) {
twoGangModel = state.twoGangModel; twoGangModel = state.twoGangModel;
} else if (state is UpdateState) { } else if (state is UpdateState) {
@ -46,9 +47,7 @@ class TwoGangScreen extends StatelessWidget {
} }
return state is LoadingInitialState return state is LoadingInitialState
? const Center( ? const Center(
child: child: DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),)
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: device == null : device == null
? TwoGangList( ? TwoGangList(
twoGangList: groupTwoGangModel, twoGangList: groupTwoGangModel,

View File

@ -63,9 +63,10 @@ class TwoGangScheduleScreen extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
PageRouteBuilder( PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => TwoTimerScreen( pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
device: device, device: device,
deviceCode: 'countdown_1', deviceCode: 'countdown_1',
switchCode:'switch_1' ,
))); )));
}, },
child: Container( child: Container(
@ -75,7 +76,7 @@ class TwoGangScheduleScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
BodySmall( BodySmall(
text: "Bedside Light", text: "Cove Light",
style: context.bodyMedium.copyWith( style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor, color: ColorsManager.textPrimaryColor,
fontSize: 15, fontSize: 15,
@ -99,9 +100,10 @@ class TwoGangScheduleScreen extends StatelessWidget {
Navigator.push( Navigator.push(
context, context,
PageRouteBuilder( PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => TwoTimerScreen( pageBuilder: (context, animation1, animation2) => TimerScheduleScreen(
device: device, device: device,
deviceCode: 'countdown_2', deviceCode: 'countdown_2',
switchCode:'switch_2' ,
))); )));
}, },
child: Container( child: Container(
@ -111,7 +113,7 @@ class TwoGangScheduleScreen extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
BodySmall( BodySmall(
text: "Ceiling Light", text: "Chandelier",
style: context.bodyMedium.copyWith( style: context.bodyMedium.copyWith(
color: ColorsManager.textPrimaryColor, color: ColorsManager.textPrimaryColor,
fontSize: 15, fontSize: 15,

View File

@ -7,10 +7,9 @@ import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_bloc.da
import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_state.dart'; import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/shared_widgets/create_schedule.dart'; import 'package:syncrow_app/features/shared_widgets/create_schedule.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
import 'package:syncrow_app/features/shared_widgets/empty_schedule.dart'; import 'package:syncrow_app/features/shared_widgets/schedule_list.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/generated/assets.dart';
import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/context_extension.dart';
@ -18,11 +17,15 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_event.dart'; import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_event.dart';
class TwoTimerScreen extends StatelessWidget { class TimerScheduleScreen extends StatelessWidget {
final DeviceModel device; final DeviceModel device;
final String deviceCode; final String deviceCode;
const TwoTimerScreen( final String switchCode;
{required this.device, required this.deviceCode, super.key}); const TimerScheduleScreen(
{required this.device,
required this.deviceCode,
required this.switchCode,
super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -32,15 +35,15 @@ class TwoTimerScreen extends StatelessWidget {
statusBarIconBrightness: Brightness.light, statusBarIconBrightness: Brightness.light,
), ),
child: BlocProvider( child: BlocProvider(
create: (context) => TwoGangBloc(twoGangId: device.uuid ?? '') create: (context) =>
..add(GetCounterEvent(deviceCode: deviceCode)), TwoGangBloc(switchCode: switchCode, twoGangId: device.uuid ?? '')
..add(GetCounterEvent(deviceCode: deviceCode))
..add(GetScheduleEvent()),
child: BlocBuilder<TwoGangBloc, TwoGangState>( child: BlocBuilder<TwoGangBloc, TwoGangState>(
builder: (context, state) { builder: (context, state) {
final twoGangBloc = BlocProvider.of<TwoGangBloc>(context); final twoGangBloc = BlocProvider.of<TwoGangBloc>(context);
Duration duration = Duration.zero; Duration duration = Duration.zero;
int countNum = 0; int countNum = 0;
int tabNum = 0;
if (state is UpdateTimerState) { if (state is UpdateTimerState) {
countNum = state.seconds; countNum = state.seconds;
} else if (state is TimerRunInProgress) { } else if (state is TimerRunInProgress) {
@ -49,228 +52,197 @@ class TwoTimerScreen extends StatelessWidget {
countNum = 0; countNum = 0;
} else if (state is LoadingNewSate) { } else if (state is LoadingNewSate) {
countNum = 0; countNum = 0;
} else if (state is ChangeSlidingSegmentState) {
tabNum = state.value;
} }
return Scaffold( return PopScope(
backgroundColor: ColorsManager.backgroundColor, canPop: false,
extendBodyBehindAppBar: true, onPopInvoked: (didPop) {
extendBody: true, if (!didPop) {
appBar: AppBar( twoGangBloc.add(OnClose());
backgroundColor: Colors.transparent, Navigator.pop(context);
centerTitle: true, }
title: const BodyLarge( },
text: 'Schedule', child: DefaultTabController(
fontColor: ColorsManager.primaryColor, length: 2,
fontWeight: FontsManager.bold, child: DefaultScaffold(
), appBar: AppBar(
actions: [ backgroundColor: Colors.transparent,
if (tabNum == 1) centerTitle: true,
twoGangBloc.createSchedule == true title: const BodyLarge(
? TextButton(onPressed: () {}, child: const Text('Save')) text: 'Schedule',
: IconButton( fontColor: ColorsManager.primaryColor,
fontWeight: FontsManager.bold,
),
actions: [
twoGangBloc.createSchedule == true ?
TextButton(
onPressed: () {
twoGangBloc.add(TwoGangSave());
},
child: const Text('Save')
) :
twoGangBloc.selectedTabIndex==1? IconButton(
onPressed: () { onPressed: () {
twoGangBloc.toggleCreateSchedule(); twoGangBloc.toggleCreateSchedule();
}, },
icon: const Icon(Icons.add), icon: const Icon(Icons.add),
), ):SizedBox(),
], ],
),
body: SafeArea(
child: PopScope(
canPop: false,
onPopInvoked: (didPop) {
if (!didPop) {
BlocProvider.of<TwoGangBloc>(context).add(OnClose());
Navigator.pop(context);
}
},
child: Container(
width: MediaQuery.sizeOf(context).width,
height: MediaQuery.sizeOf(context).height,
padding: const EdgeInsets.all(24),
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage(Assets.assetsImagesBackground),
fit: BoxFit.cover,
opacity: 0.4,
), ),
), child:
child: state is LoadingInitialState || state is LoadingInitialState?
state is LoadingNewSate const Center(child: CircularProgressIndicator()):
? const Center( Column(
child: DefaultContainer( children: [
width: 50, Container(
height: 50, width: MediaQuery.of(context).size.width,
child: CircularProgressIndicator(), decoration: const ShapeDecoration(
color: ColorsManager.onPrimaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(30)),
),
), ),
) child: TabBar(
: Column( onTap: (value) {
mainAxisAlignment: MainAxisAlignment.spaceBetween, print(value);
children: [ if(value==0){
Container( if(twoGangBloc.createSchedule == true){
width: MediaQuery.sizeOf(context).width, twoGangBloc.toggleCreateSchedule();
decoration: const ShapeDecoration( }
color: ColorsManager.slidingBlueColor, twoGangBloc.toggleSelectedIndex(0);
shape: RoundedRectangleBorder(
borderRadius: }else{
BorderRadius.all(Radius.circular(20)), twoGangBloc.toggleSelectedIndex(1);
), }
), },
child: CupertinoSlidingSegmentedControl<int>( indicatorColor: Colors.white, // Customize the indicator
thumbColor: ColorsManager.slidingBlueColor, dividerHeight: 0,
onValueChanged: (value) { indicatorSize: TabBarIndicatorSize.tab,
BlocProvider.of<TwoGangBloc>(context).add( indicator: const ShapeDecoration(
ChangeSlidingSegment( color: ColorsManager.slidingBlueColor,
value: value ?? 0)); shape: RoundedRectangleBorder(
}, borderRadius:
groupValue: state is ChangeSlidingSegmentState BorderRadius.all(Radius.circular(20)),
? state.value
: 0,
backgroundColor: Colors.white,
children: <int, Widget>{
0: Container(
padding: const EdgeInsets.symmetric(
vertical: 10),
child: BodySmall(
text: 'Countdown',
style: context.bodySmall.copyWith(
color: ColorsManager.blackColor,
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
),
1: Container(
padding: const EdgeInsets.symmetric(
vertical: 10),
child: Text(
'Schedule',
style: context.bodySmall.copyWith(
color: ColorsManager.blackColor,
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
),
},
), ),
), ),
if (tabNum == 0) tabs: [
countNum > 0 Tab(
? BodyLarge( child: Container(
text: _formatDuration(countNum), padding: const EdgeInsets.symmetric(
fontColor: vertical: 10),
ColorsManager.slidingBlueColor, child: BodySmall(
fontSize: 40, text: 'Countdown',
) style: context.bodySmall.copyWith(
: CupertinoTimerPicker( color: ColorsManager.blackColor,
mode: CupertinoTimerPickerMode.hm, fontSize: 12,
onTimerDurationChanged: fontWeight: FontWeight.w400,
(Duration newDuration) {
duration = newDuration;
},
), ),
if (tabNum == 0) ),
GestureDetector( ),
onTap: () { ),
if (state is LoadingNewSate) { Tab(
return; child: Container(
} padding: const EdgeInsets.symmetric(vertical: 10),
if (countNum > 0) { child: Text(
BlocProvider.of<TwoGangBloc>(context) 'Schedule',
.add(SetCounterValue( style: context.bodySmall.copyWith(
deviceCode: deviceCode, color: ColorsManager.blackColor,
duration: Duration.zero)); fontSize: 12,
} else if (duration != Duration.zero) { fontWeight: FontWeight.w400,
BlocProvider.of<TwoGangBloc>(context) ),
.add(SetCounterValue( ),
deviceCode: deviceCode, ),
duration: duration)); ),
} ],
}, ),
child: SvgPicture.asset(countNum > 0
? Assets.pauseIcon
: Assets.playIcon)),
if (tabNum == 1)
SizedBox(
height:
MediaQuery.of(context).size.height / 2,
child: twoGangBloc.createSchedule == true
? CreateSchedule(
onToggleChanged: (bool isOn) {
print(
'Toggle is now: ${isOn ? "ON" : "OFF"}');
},
onDateTimeChanged:
(DateTime dateTime) {
print('Selected Time: $dateTime');
},
days: twoGangBloc.days,
selectDays:
(List<String> selectedDays) {
twoGangBloc.selectedDays =
selectedDays;
print(
'Selected Days: ${twoGangBloc.selectedDays}');
},
)
: Center(
child: twoGangBloc.listSchedule.isNotEmpty?
Container(
height: MediaQuery.of(context).size.height / 2,
child: ListView.builder(
itemCount: twoGangBloc.listSchedule.length,
itemBuilder: (context, index) {
return
Dismissible(
key: Key( twoGangBloc.listSchedule[index].id),
child: InkWell(
onTap: () {},
child:
DefaultContainer(
padding: EdgeInsets.all(20),
height: MediaQuery.of(context).size.height / 8,
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(twoGangBloc.listSchedule[index].time),
Text(twoGangBloc.listSchedule[index].days.toString()),
Text(twoGangBloc.listSchedule[index].enable.toString())
],
),
),
Expanded(child:ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: '',
fontWeight: FontWeight.normal,
),
trailing: Transform.scale(
scale: .8,
child: CupertinoSwitch(
value: true,
onChanged: (value) {
// smartDoorBloc.add(ToggleRepeatEvent());
},
applyTheme: true,
)),
),)
],
))));
},),
):
EmptySchedule()),
)
],
), ),
), Expanded(
), child: TabBarView(
), children: [
Center(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
countNum > 0
? BodyLarge(
text: _formatDuration(countNum),
fontColor:
ColorsManager.slidingBlueColor,
fontSize: 40,
)
: CupertinoTimerPicker(
mode: CupertinoTimerPickerMode.hm,
onTimerDurationChanged:
(Duration newDuration) {
duration = newDuration;
},
),
GestureDetector(
onTap: () {
if (state is LoadingNewSate) {
return;
}
if (countNum > 0) {
twoGangBloc.add(SetCounterValue(
deviceCode: deviceCode,
duration: Duration.zero));
} else if (duration != Duration.zero) {
twoGangBloc.add(SetCounterValue(
deviceCode: deviceCode,
duration: duration));
}
},
child: SvgPicture.asset(countNum > 0
? Assets.pauseIcon
: Assets.playIcon)),
],
),
),
),
Column(
mainAxisAlignment:twoGangBloc.listSchedule.isNotEmpty?
MainAxisAlignment.start:MainAxisAlignment.center,
children: [
SizedBox(
child: twoGangBloc.createSchedule == true ?
CreateSchedule(
onToggleChanged: (bool isOn) {
twoGangBloc.toggleSchedule = isOn;
},
onDateTimeChanged: (DateTime dateTime) {
twoGangBloc.selectedTime=dateTime;
},
days: twoGangBloc.days,
selectDays: (List<String> selectedDays) {
twoGangBloc.selectedDays = selectedDays;
},
)
:
Padding(
padding: const EdgeInsets.only(top: 10),
child: ScheduleListView(
listSchedule: twoGangBloc.listSchedule, // Pass the schedule list here
onDismissed: (scheduleId) {
twoGangBloc.listSchedule.removeWhere((schedule) => schedule.scheduleId == scheduleId);
twoGangBloc.add(DeleteScheduleEvent(id: scheduleId));
},
onToggleSchedule: (scheduleId, isEnabled) {
twoGangBloc.add(ToggleScheduleEvent(
id: scheduleId,
toggle: isEnabled,
));
},
),
),
),
],
),
],
),
),
],
),
))
); );
}, },
), ),

View File

@ -23,7 +23,7 @@ class CreateSchedule extends StatefulWidget {
class _CreateScheduleState extends State<CreateSchedule> { class _CreateScheduleState extends State<CreateSchedule> {
List<String> selectedDays = []; // List of selected days List<String> selectedDays = []; // List of selected days
bool isOn = false; // Boolean state for the ON/OFF toggle bool isOn = true; // Boolean state for the ON/OFF toggle
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -114,19 +114,18 @@ class _CreateScheduleState extends State<CreateSchedule> {
children: [ children: [
Text( Text(
isOn ? 'ON' : 'OFF', // Change text based on state isOn ? 'ON' : 'OFF', // Change text based on state
style: TextStyle( style: const TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
color: isOn ? Colors.green : Colors.red, // Change color based on state
), ),
), ),
CircleAvatar( CircleAvatar(
backgroundColor: isOn backgroundColor: isOn
? ColorsManager.secondaryColor.withOpacity(0.6) ? ColorsManager.secondaryColor.withOpacity(0.6)
: Colors.red.withOpacity(0.6), // Change background color based on state : Colors.red.withOpacity(0.6), // Change background color based on state
child: Icon( child: const Icon(
Icons.power_settings_new, Icons.power_settings_new,
color: isOn ? Colors.green : Colors.red, // Change icon color color: ColorsManager.onPrimaryColor, // Change icon color
), ),
), ),
], ],

View File

@ -9,43 +9,43 @@ class EmptySchedule extends StatelessWidget {
const EmptySchedule({super.key}); const EmptySchedule({super.key});
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Center(child: Column( return SizedBox(
mainAxisAlignment: height: 180,
MainAxisAlignment.center, width: 180,
crossAxisAlignment: child: Center(child: Column(
CrossAxisAlignment.center, children: [
children: [ Center(
Center( child: SvgPicture.asset(
child: SvgPicture.asset( height: 100,
height: 100, width: 100,
width: 100, Assets.emptySchedule),
Assets.emptySchedule), ),
), Column(
Column( children: [
children: [ Center(
Center( child: Text(
child: Text( 'Please add',
'Please add', style: context.displaySmall
style: context.displaySmall .copyWith(
.copyWith( color: const Color(
color: const Color( 0XFFD5D5D5),
0XFFD5D5D5), ),
), ),
), ),
), Center(
Center( child: Text(
child: Text( 'a new schedule',
'a new schedule', style: context.displaySmall
style: context.displaySmall .copyWith(
.copyWith( color: const Color(
color: const Color( 0XFFD5D5D5),
0XFFD5D5D5), ),
), ),
), ),
), ],
], ),
), ],
], ),),
),); );
} }
} }

View File

@ -0,0 +1,120 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
import 'package:syncrow_app/features/shared_widgets/default_button.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
import 'package:syncrow_app/generated/assets.dart';
import 'empty_schedule.dart'; // for SVG icons
class ScheduleListView extends StatelessWidget {
final List<ScheduleModel> listSchedule;
final Function(String) onDismissed;
final Function(String, bool) onToggleSchedule;
const ScheduleListView({
Key? key,
required this.listSchedule,
required this.onDismissed,
required this.onToggleSchedule,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Center(
child: listSchedule.isNotEmpty
? SizedBox(
child: ListView.builder(
shrinkWrap: true,
itemCount: listSchedule.length,
itemBuilder: (context, index) {
return Dismissible(
key: Key(listSchedule[index].scheduleId),
background: Container(
padding: const EdgeInsets.only(right: 10),
alignment: AlignmentDirectional.centerEnd,
decoration: const ShapeDecoration(
color: Color(0xFFFF0000),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
child: Padding(
padding: const EdgeInsets.only(bottom: 10, right: 10),
child: SvgPicture.asset(
Assets.assetsDeleteIcon,
width: 20,
height: 22,
),
),
),
direction: DismissDirection.endToStart,
onDismissed: (direction) {
onDismissed(listSchedule[index].scheduleId);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Schedule removed')),
);
},
child: InkWell(
onTap: () {
},
child: DefaultContainer(
padding: const EdgeInsets.all(20),
height: MediaQuery.of(context).size.height / 6.4,
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
BodyLarge(
text: listSchedule[index].time,
fontWeight: FontWeight.w500,
fontColor: Colors.black,
fontSize: 22,
),
Text(listSchedule[index].days.join(' ')),
Text('Function ${listSchedule[index].enable ? "ON" : "OFF"}'),
],
),
),
Expanded(
child: ListTile(
contentPadding: EdgeInsets.zero,
leading: const BodyMedium(
text: '',
fontWeight: FontWeight.normal,
),
trailing: Transform.scale(
scale: .8,
child: CupertinoSwitch(
value: listSchedule[index].enable,
onChanged: (value) {
onToggleSchedule(
listSchedule[index].scheduleId,
value,
);
},
applyTheme: true,
),
),
),
),
],
),
),
),
);
},
),
)
: const EmptySchedule()
);
}
}

View File

@ -14,7 +14,7 @@ void main() {
//to catch all the errors in the app and send them to firebase //to catch all the errors in the app and send them to firebase
runZonedGuarded(() async { runZonedGuarded(() async {
//to load the environment variables //to load the environment variables
const environment = String.fromEnvironment('FLAVOR', defaultValue: 'development'); const environment = String.fromEnvironment('FLAVOR', defaultValue: 'production');
await dotenv.load(fileName: '.env.$environment'); await dotenv.load(fileName: '.env.$environment');
// //this is to make the app work with the self-signed certificate // //this is to make the app work with the self-signed certificate

View File

@ -175,4 +175,12 @@ abstract class ApiEndpoints {
//multiple-time offline //multiple-time offline
static const String deleteTemporaryPassword = static const String deleteTemporaryPassword =
'/door-lock/temporary-password/online/{doorLockUuid}/{passwordId}'; '/door-lock/temporary-password/online/{doorLockUuid}/{passwordId}';
static const String saveSchedule = '/schedule/{deviceUuid}';
static const String getSchedule = '/schedule/{deviceUuid}?category={category}';
static const String changeSchedule = '/schedule/enable/{deviceUuid}';
static const String deleteSchedule = '/schedule/{deviceUuid}/{scheduleId}';
} }

View File

@ -1,11 +1,11 @@
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'package:syncrow_app/features/devices/model/device_category_model.dart'; import 'package:syncrow_app/features/devices/model/device_category_model.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/function_model.dart'; import 'package:syncrow_app/features/devices/model/function_model.dart';
import 'package:syncrow_app/services/api/api_links_endpoints.dart'; import 'package:syncrow_app/services/api/api_links_endpoints.dart';
import 'package:syncrow_app/services/api/http_service.dart'; import 'package:syncrow_app/services/api/http_service.dart';
import '../../features/devices/model/create_temporary_password_model.dart'; import '../../features/devices/model/create_temporary_password_model.dart';
class DevicesAPI { class DevicesAPI {
@ -280,11 +280,20 @@ class DevicesAPI {
required List<String> days, required List<String> days,
}) async { }) async {
print( {
"category": category,
"time": time,
"function":{
"code": code,
"value":value,
},
"days": days
});
final response = await _httpService.post( final response = await _httpService.post(
path: ApiEndpoints.deleteTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), path: ApiEndpoints.saveSchedule.replaceAll('{deviceUuid}', deviceId),
showServerMessage: false, showServerMessage: false,
body: body:
{ jsonEncode({
"category": category, "category": category,
"time": time, "time": time,
"function":{ "function":{
@ -292,7 +301,54 @@ class DevicesAPI {
"value":value, "value":value,
}, },
"days": days "days": days
},),
expectedResponseModel: (json) {
return json;
}, },
);
return response;
}
static Future getSchedule({
required String category,
required String deviceId,
}) async {
final response = await _httpService.get(
path: ApiEndpoints.getSchedule.replaceAll('{deviceUuid}', deviceId).replaceAll('{category}', category),
showServerMessage: false,
expectedResponseModel: (json) {
return json;
},
);
return response;
}
static Future<bool> changeSchedule({
required String deviceUuid,
required String scheduleId,
required bool enable,
}) async {
final response = await _httpService.put(
path: ApiEndpoints.changeSchedule.replaceAll('{deviceUuid}', deviceUuid),
body: {
"scheduleId": scheduleId,
"enable": enable
},
expectedResponseModel: (json) {
print('object===-=-=-$json');
return json['success'];
},
);
return response;
}
static Future deleteSchedule({
required String deviceUuid,
required String scheduleId,
}) async {
print( ApiEndpoints.deleteSchedule.replaceAll('{deviceUuid}', deviceUuid).replaceAll('{scheduleId}', scheduleId));
final response = await _httpService.delete(
path: ApiEndpoints.deleteSchedule.replaceAll('{deviceUuid}', deviceUuid).replaceAll('{scheduleId}', scheduleId),
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json; return json;
}, },