push main door device design

This commit is contained in:
ashrafzarkanisala
2024-09-18 01:36:17 +03:00
parent 7d5b5340db
commit 9876ff2e03
10 changed files with 520 additions and 1 deletions

View File

@ -11,6 +11,7 @@ import 'package:syncrow_web/pages/device_managment/door_lock/view/door_lock_batc
import 'package:syncrow_web/pages/device_managment/door_lock/view/door_lock_control_view.dart';
import 'package:syncrow_web/pages/device_managment/gateway/view/gateway_batch_control.dart';
import 'package:syncrow_web/pages/device_managment/gateway/view/gateway_view.dart';
import 'package:syncrow_web/pages/device_managment/main_door_sensor/view/main_door_control_view.dart';
import 'package:syncrow_web/pages/device_managment/one_gang_switch/view/wall_light_batch_control.dart';
import 'package:syncrow_web/pages/device_managment/one_gang_switch/view/wall_light_device_control.dart';
import 'package:syncrow_web/pages/device_managment/three_gang_switch/view/living_room_batch_controls.dart';
@ -55,7 +56,11 @@ mixin RouteControlsBasedCode {
case 'AC':
return AcDeviceControlsView(device: device);
case 'WH':
return WaterHeaterDeviceControl(device: device,);
return WaterHeaterDeviceControl(
device: device,
);
case 'DS':
return MainDoorSensorControlView(device: device);
default:
return const SizedBox();
}

View File

@ -0,0 +1,139 @@
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
import 'package:syncrow_web/pages/device_managment/main_door_sensor/bloc/main_door_sensor_event.dart';
import 'package:syncrow_web/pages/device_managment/main_door_sensor/bloc/main_door_sensor_state.dart';
import 'package:syncrow_web/pages/device_managment/main_door_sensor/models/main_door_status_model.dart';
import 'package:syncrow_web/services/devices_mang_api.dart';
class MainDoorSensorBloc
extends Bloc<MainDoorSensorEvent, MainDoorSensorState> {
MainDoorSensorBloc() : super(MainDoorSensorInitial()) {
on<MainDoorSensorFetchDeviceEvent>(_onFetchDeviceStatus);
on<MainDoorSensorControl>(_onControl);
on<MainDoorSensorFetchBatchEvent>(_onFetchBatchStatus);
on<MainDoorSensorReportsEvent>(_fetchReports);
}
late MainDoorSensorStatusModel deviceStatus;
Timer? _timer;
FutureOr<void> _onFetchDeviceStatus(MainDoorSensorFetchDeviceEvent event,
Emitter<MainDoorSensorState> emit) async {
emit(MainDoorSensorLoadingState());
try {
final status = await DevicesManagementApi()
.getDeviceStatus(event.deviceId)
.then((value) => value.status);
deviceStatus = MainDoorSensorStatusModel.fromJson(event.deviceId, status);
emit(MainDoorSensorDeviceStatusLoaded(deviceStatus));
} catch (e) {
emit(MainDoorSensorFailedState(error: e.toString()));
}
}
FutureOr<void> _onControl(
MainDoorSensorControl event, Emitter<MainDoorSensorState> emit) async {
final oldValue = _getValueByCode(event.code);
_updateLocalValue(event.code, event.value);
emit(MainDoorSensorDeviceStatusLoaded(deviceStatus));
await _runDebounce(
deviceId: event.deviceId,
code: event.code,
value: event.value,
oldValue: oldValue,
emit: emit,
);
}
Future<void> _runDebounce({
required String deviceId,
required String code,
required bool value,
required bool oldValue,
required Emitter<MainDoorSensorState> emit,
}) async {
if (_timer != null) {
_timer!.cancel();
}
_timer = Timer(const Duration(milliseconds: 500), () async {
try {
final status = await DevicesManagementApi()
.deviceControl(deviceId, Status(code: code, value: value));
if (!status) {
_revertValueAndEmit(deviceId, code, oldValue, emit);
}
emit(MainDoorSensorDeviceStatusLoaded(deviceStatus));
} catch (e) {
emit(MainDoorSensorFailedState(error: e.toString()));
}
});
}
void _revertValueAndEmit(String deviceId, String code, bool oldValue,
Emitter<MainDoorSensorState> emit) {
_updateLocalValue(code, oldValue);
emit(MainDoorSensorDeviceStatusLoaded(deviceStatus));
}
void _updateLocalValue(String code, bool value) {
switch (code) {
case 'doorcontact_state':
deviceStatus = deviceStatus.copyWith(doorContactState: value);
break;
default:
break;
}
}
// Retrieve the current value by code
bool _getValueByCode(String code) {
switch (code) {
case 'doorcontact_state':
return deviceStatus.doorContactState;
default:
return false;
}
}
// Fetch batch status for multiple devices (if needed)
FutureOr<void> _onFetchBatchStatus(MainDoorSensorFetchBatchEvent event,
Emitter<MainDoorSensorState> emit) async {
emit(MainDoorSensorLoadingState());
try {
// final batchStatus =
// await DevicesManagementApi().getBatchDeviceStatus(event.deviceIds);
// Assuming you need to update multiple devices status here
// You might need a list or map of MainDoorSensorStatusModel for batch processing
// emit(MainDoorSensorBatchStatusLoaded(batchStatus));
} catch (e) {
emit(MainDoorSensorBatchFailedState(error: e.toString()));
}
}
// Fetch reports related to the main door sensor
FutureOr<void> _fetchReports(MainDoorSensorReportsEvent event,
Emitter<MainDoorSensorState> emit) async {
emit(MainDoorSensorLoadingState());
try {
final reports = await DevicesManagementApi.getDeviceReports(
event.deviceId, event.code);
emit(MainDoorSensorReportLoaded(reports));
} catch (e) {
emit(MainDoorSensorFailedState(error: e.toString()));
}
}
@override
Future<void> close() {
_timer?.cancel();
return super.close();
}
}

View File

@ -0,0 +1,55 @@
import 'package:equatable/equatable.dart';
class MainDoorSensorEvent extends Equatable {
@override
List<Object?> get props => [];
}
class MainDoorSensorFetchDeviceEvent extends MainDoorSensorEvent {
final String deviceId;
MainDoorSensorFetchDeviceEvent(this.deviceId);
@override
List<Object> get props => [deviceId];
}
class MainDoorSensorFetchBatchEvent extends MainDoorSensorEvent {
final String deviceId;
MainDoorSensorFetchBatchEvent(this.deviceId);
@override
List<Object> get props => [deviceId];
}
class MainDoorSensorControl extends MainDoorSensorEvent {
final String deviceId;
final String code;
final bool value;
MainDoorSensorControl(
{required this.deviceId, required this.code, required this.value});
@override
List<Object> get props => [deviceId, code, value];
}
class MainDoorSensorBatchControl extends MainDoorSensorEvent {
final List<String> deviceId;
final String code;
final bool value;
MainDoorSensorBatchControl(
{required this.deviceId, required this.code, required this.value});
@override
List<Object> get props => [deviceId, code, value];
}
class MainDoorSensorReportsEvent extends MainDoorSensorEvent {
final String deviceId;
final String code;
MainDoorSensorReportsEvent({required this.deviceId, required this.code});
}

View File

@ -0,0 +1,68 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_reports.dart';
import 'package:syncrow_web/pages/device_managment/main_door_sensor/models/main_door_status_model.dart';
class MainDoorSensorState extends Equatable {
@override
List<Object?> get props => [];
}
class MainDoorSensorInitial extends MainDoorSensorState {}
class MainDoorSensorLoadingState extends MainDoorSensorState {}
class MainDoorSensorDeviceStatusLoaded extends MainDoorSensorState {
final MainDoorSensorStatusModel status;
MainDoorSensorDeviceStatusLoaded(this.status);
@override
List<Object?> get props => [status];
}
class MainDoorSensorFailedState extends MainDoorSensorState {
final String error;
MainDoorSensorFailedState({required this.error});
@override
List<Object?> get props => [error];
}
class MainDoorSensorBatchFailedState extends MainDoorSensorState {
final String error;
MainDoorSensorBatchFailedState({required this.error});
@override
List<Object?> get props => [error];
}
class MainDoorSensorBatchStatusLoaded extends MainDoorSensorState {
final List<MainDoorSensorStatusModel> status;
MainDoorSensorBatchStatusLoaded(this.status);
@override
List<Object?> get props => [status];
}
class MainDoorSensorReportLoaded extends MainDoorSensorState {
final DeviceReport deviceReport;
MainDoorSensorReportLoaded(this.deviceReport);
@override
List<Object?> get props => [deviceReport];
}
class MainDoorSensorReportsLoadingState extends MainDoorSensorState {}
class MainDoorSensorReportsFailedState extends MainDoorSensorState {
final String error;
MainDoorSensorReportsFailedState({required this.error});
@override
List<Object?> get props => [error];
}

View File

@ -0,0 +1,47 @@
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
class MainDoorSensorStatusModel {
final String uuid;
final bool doorContactState;
final int batteryPercentage;
MainDoorSensorStatusModel({
required this.uuid,
required this.doorContactState,
required this.batteryPercentage,
});
factory MainDoorSensorStatusModel.fromJson(String id, List<Status> jsonList) {
late bool doorContactState = false;
late int batteryPercentage = 0;
for (var status in jsonList) {
switch (status.code) {
case 'doorcontact_state':
doorContactState = status.value ?? false;
break;
case 'battery_percentage':
batteryPercentage = status.value ?? 0;
break;
}
}
return MainDoorSensorStatusModel(
uuid: id,
doorContactState: doorContactState,
batteryPercentage: batteryPercentage,
);
}
MainDoorSensorStatusModel copyWith({
String? uuid,
bool? doorContactState,
int? batteryPercentage,
}) {
return MainDoorSensorStatusModel(
uuid: uuid ?? this.uuid,
doorContactState: doorContactState ?? this.doorContactState,
batteryPercentage: batteryPercentage ?? this.batteryPercentage,
);
}
}

View File

@ -0,0 +1,148 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/main_door_sensor/bloc/main_door_sensor_bloc.dart';
import 'package:syncrow_web/pages/device_managment/main_door_sensor/bloc/main_door_sensor_event.dart';
import 'package:syncrow_web/pages/device_managment/main_door_sensor/bloc/main_door_sensor_state.dart';
import 'package:syncrow_web/pages/device_managment/main_door_sensor/models/main_door_status_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class MainDoorSensorControlView extends StatelessWidget
with HelperResponsiveLayout {
const MainDoorSensorControlView({super.key, required this.device});
final AllDevicesModel device;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => MainDoorSensorBloc()
..add(MainDoorSensorFetchDeviceEvent(device.uuid!)),
child: BlocBuilder<MainDoorSensorBloc, MainDoorSensorState>(
builder: (context, state) {
if (state is MainDoorSensorLoadingState) {
return const Center(child: CircularProgressIndicator());
} else if (state is MainDoorSensorDeviceStatusLoaded) {
return _buildStatusControls(context, state.status);
} else if (state is MainDoorSensorFailedState ||
state is MainDoorSensorBatchFailedState) {
return const Center(child: Text('Error fetching status'));
} else {
return const Center(child: CircularProgressIndicator());
}
},
));
}
Widget _buildStatusControls(
BuildContext context, MainDoorSensorStatusModel status) {
final isExtraLarge = isExtraLargeScreenSize(context);
final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context);
return GridView(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge || isExtraLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 140,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
children: [
IconNameStatusContainer(
name: 'Open',
icon: Assets.mainDoor,
onTap: () {},
status: status.doorContactState,
textColor: ColorsManager.red,
paddingAmount: 8,
),
IconNameStatusContainer(
name: 'Open/Close\n Record',
icon: Assets.mainDoorReports,
onTap: () {},
status: false,
textColor: ColorsManager.blackColor,
),
IconNameStatusContainer(
name: 'Notifications\n Settings',
icon: Assets.mainDoorNotifi,
onTap: () {},
status: false,
textColor: ColorsManager.blackColor,
),
],
);
}
}
class IconNameStatusContainer extends StatelessWidget {
const IconNameStatusContainer({
super.key,
required this.name,
required this.icon,
required this.onTap,
required this.status,
required this.textColor,
this.paddingAmount = 12,
});
final String name;
final String icon;
final GestureTapCallback onTap;
final bool status;
final Color textColor;
final double? paddingAmount;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: DeviceControlsContainer(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
width: 60,
height: 60,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: ColorsManager.whiteColors,
),
margin: const EdgeInsets.symmetric(horizontal: 4),
padding: EdgeInsets.all(paddingAmount ?? 12),
child: ClipOval(
child: SvgPicture.asset(
icon,
fit: BoxFit.fill,
),
),
),
const Spacer(),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 6),
child: Text(
name,
textAlign: TextAlign.start,
style: context.textTheme.titleMedium!.copyWith(
fontWeight: FontWeight.w400,
color: textColor,
),
),
),
],
),
),
);
}
}