mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-11-27 04:04:56 +00:00
push main door device design
This commit is contained in:
@ -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();
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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});
|
||||
}
|
||||
@ -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];
|
||||
}
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user