push living room status

This commit is contained in:
ashrafzarkanisala
2024-08-25 04:03:46 +03:00
parent 2597cdc311
commit a1ebb930a2
95 changed files with 2283 additions and 86 deletions

View File

@ -12,7 +12,7 @@ class DynamicTable extends StatefulWidget {
final bool withCheckBox;
final bool isEmpty;
final void Function(bool?)? selectAll;
final void Function(int, bool?)? onRowCheckboxChanged;
final void Function(int, bool, dynamic)? onRowSelected;
final List<String>? initialSelectedIds;
const DynamicTable({
@ -25,7 +25,7 @@ class DynamicTable extends StatefulWidget {
this.headerDecoration,
this.cellDecoration,
this.selectAll,
this.onRowCheckboxChanged,
this.onRowSelected,
this.initialSelectedIds,
});
@ -35,7 +35,6 @@ class DynamicTable extends StatefulWidget {
class _DynamicTableState extends State<DynamicTable> {
late List<bool> _selected;
bool _selectAll = false;
@override
void initState() {
@ -44,25 +43,19 @@ class _DynamicTableState extends State<DynamicTable> {
return widget.initialSelectedIds != null &&
widget.initialSelectedIds!.contains(widget.data[index][1]);
});
_selectAll = _selected.every((element) => element == true);
}
void _toggleSelectAll(bool? value) {
void _toggleRowSelection(int index) {
setState(() {
_selectAll = value ?? false;
_selected = List<bool>.filled(widget.data.length, _selectAll);
if (widget.selectAll != null) {
widget.selectAll!(_selectAll);
// Deselect all rows
for (int i = 0; i < _selected.length; i++) {
_selected[i] = false;
}
});
}
// Select the clicked row
_selected[index] = true;
void _toggleRowSelection(int index, bool? value) {
setState(() {
_selected[index] = value ?? false;
_selectAll = _selected.every((element) => element == true);
if (widget.onRowCheckboxChanged != null) {
widget.onRowCheckboxChanged!(index, _selected[index]);
if (widget.onRowSelected != null) {
widget.onRowSelected!(index, true, widget.data[index]);
}
});
}
@ -108,7 +101,7 @@ class _DynamicTableState extends State<DynamicTable> {
height: 15,
),
Text(
'No Passwords',
'No Devices',
style: Theme.of(context)
.textTheme
.bodySmall!
@ -157,81 +150,104 @@ class _DynamicTableState extends State<DynamicTable> {
Widget _buildSelectAllCheckbox() {
return Container(
width: 50, // Fixed width to align with the checkbox column
padding: const EdgeInsets.all(8.0),
decoration: const BoxDecoration(
border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider))),
border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider),
),
),
child: Checkbox(
value: _selectAll,
onChanged: _toggleSelectAll,
value: _selected.every((element) => element == true),
onChanged: null, // Disabling the toggle as we're not using select all
),
);
}
Widget _buildRowCheckbox(int index, size) {
Widget _buildRowCheckbox(int index, double size) {
return Container(
padding: const EdgeInsets.all(8.0),
height: size,
decoration: const BoxDecoration(
border: Border(
width: 50, // Fixed width to align with the checkbox column
padding: const EdgeInsets.all(8.0),
height: size,
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: ColorsManager.boxDivider,
width: 1.0,
),
)),
alignment: Alignment.centerLeft,
child: Center(
child: Checkbox(
value: _selected[index],
onChanged: (bool? value) {
_toggleRowSelection(index, value);
},
),
));
),
),
alignment: Alignment.centerLeft,
child: Center(
child: Checkbox(
value: _selected[index],
onChanged: (bool? value) {
_toggleRowSelection(index);
},
),
),
);
}
Widget _buildTableHeaderCell(String title) {
return Expanded(
child: Container(
decoration: const BoxDecoration(
border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider))),
border: Border.symmetric(
vertical: BorderSide(color: ColorsManager.boxDivider),
),
),
alignment: Alignment.centerLeft,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(title,
style: const TextStyle(
fontWeight: FontWeight.w400,
fontSize: 13,
color: Color(0xFF999999))),
child: Text(
title,
style: const TextStyle(
fontWeight: FontWeight.w400,
fontSize: 13,
color: Color(0xFF999999),
),
),
),
),
);
}
Widget _buildTableCell(String content, size) {
Widget _buildTableCell(String content, double size) {
// Check if the content is a battery level percentage
bool isBatteryLevel = content.endsWith('%');
double? batteryLevel;
if (isBatteryLevel) {
batteryLevel = double.tryParse(content.replaceAll('%', '').trim());
}
return Expanded(
child: Container(
height: size,
padding: const EdgeInsets.all(5.0),
decoration: const BoxDecoration(
border: Border(
bottom: BorderSide(
color: ColorsManager.boxDivider,
width: 1.0,
border: Border(
bottom: BorderSide(
color: ColorsManager.boxDivider,
width: 1.0,
),
),
)),
),
alignment: Alignment.centerLeft,
child: Text(
content,
style: TextStyle(
color: content == 'Online'
? ColorsManager.green
: content == 'Offline'
? ColorsManager.red
: Colors.black,
fontSize: 12,
fontWeight: FontWeight.w400),
color: batteryLevel != null && batteryLevel < 20
? ColorsManager.red // Red color for low battery
: content == 'Online'
? ColorsManager.green // Green color for Online
: content == 'Offline'
? ColorsManager.red // Red color for Offline
: Colors.black,
fontSize: 12,
fontWeight: FontWeight.w400,
),
),
),
);

View File

@ -1,6 +1,6 @@
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/device_managment/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/services/devices_mang_api.dart';
part 'device_managment_event.dart';
@ -13,12 +13,14 @@ class DeviceManagementBloc
int _onlineCount = 0;
int _offlineCount = 0;
int _lowBatteryCount = 0;
AllDevicesModel? _selectedDevice;
DeviceManagementBloc() : super(DeviceManagementInitial()) {
on<FetchDevices>(_onFetchDevices);
on<FilterDevices>(_onFilterDevices);
on<SelectedFilterChanged>(_onSelectedFilterChanged);
on<SearchDevices>(_onSearchDevices);
on<SelectDevice>(_onSelectDevice);
}
Future<void> _onFetchDevices(
@ -71,6 +73,11 @@ class DeviceManagementBloc
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
}
void _onSelectDevice(
SelectDevice event, Emitter<DeviceManagementState> emit) {
_selectedDevice = event.selectedDevice;
}
void _calculateDeviceCounts() {
_onlineCount = _devices.where((device) => device.online == true).length;
_offlineCount = _devices.where((device) => device.online == false).length;
@ -127,4 +134,6 @@ class DeviceManagementBloc
));
}
}
AllDevicesModel? get selectedDevice => _selectedDevice;
}

View File

@ -41,3 +41,12 @@ class SearchDevices extends DeviceManagementEvent {
@override
List<Object?> get props => [community, unitName, productName];
}
class SelectDevice extends DeviceManagementEvent {
final AllDevicesModel selectedDevice;
const SelectDevice(this.selectedDevice);
@override
List<Object?> get props => [selectedDevice];
}

View File

@ -17,6 +17,7 @@ class DeviceManagementLoaded extends DeviceManagementState {
final int onlineCount;
final int offlineCount;
final int lowBatteryCount;
final AllDevicesModel? selectedDevice;
const DeviceManagementLoaded({
required this.devices,
@ -24,11 +25,18 @@ class DeviceManagementLoaded extends DeviceManagementState {
required this.onlineCount,
required this.offlineCount,
required this.lowBatteryCount,
this.selectedDevice,
});
@override
List<Object?> get props =>
[devices, selectedIndex, onlineCount, offlineCount, lowBatteryCount];
List<Object?> get props => [
devices,
selectedIndex,
onlineCount,
offlineCount,
lowBatteryCount,
selectedDevice
];
}
class DeviceManagementFiltered extends DeviceManagementState {
@ -37,6 +45,7 @@ class DeviceManagementFiltered extends DeviceManagementState {
final int onlineCount;
final int offlineCount;
final int lowBatteryCount;
final AllDevicesModel? selectedDevice;
const DeviceManagementFiltered({
required this.filteredDevices,
@ -44,6 +53,7 @@ class DeviceManagementFiltered extends DeviceManagementState {
required this.onlineCount,
required this.offlineCount,
required this.lowBatteryCount,
this.selectedDevice,
});
@override
@ -52,6 +62,7 @@ class DeviceManagementFiltered extends DeviceManagementState {
selectedIndex,
onlineCount,
offlineCount,
lowBatteryCount
lowBatteryCount,
selectedDevice
];
}

View File

@ -0,0 +1,5 @@
enum AcValuesEnums {
Cooling,
Heating,
Ventilation,
}

View File

@ -0,0 +1,9 @@
enum OperationDialogType {
countdown,
delay,
temperature,
onOff,
integerSteps,
listOfOptions,
none,
}

View File

@ -0,0 +1,24 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/living_room_switch/view/living_room_device_control.dart';
mixin RouteControlsBasedCode {
Widget routeControlsWidgets({required AllDevicesModel device}) {
switch (device.categoryName) {
case 'Switch':
return LivingRoomDeviceControl(
device: device,
);
case 'Gateway':
return const SizedBox();
case 'Residential Lock PRO':
return const SizedBox();
case 'Human Presence Sensor':
return const SizedBox();
case 'Thermostat':
return const SizedBox();
default:
return const SizedBox();
}
}
}

View File

@ -0,0 +1,63 @@
import 'dart:convert';
class DeviceStatus {
final String productUuid;
final String productType;
final List<Status> status;
DeviceStatus({
required this.productUuid,
required this.productType,
required this.status,
});
factory DeviceStatus.fromMap(Map<String, dynamic> map) {
return DeviceStatus(
productUuid: map['productUuid'] ?? '',
productType: map['productType'] ?? '',
status: List<Status>.from(
map['status']?.map((x) => Status.fromMap(x)) ?? const []),
);
}
Map<String, dynamic> toMap() {
return {
'productUuid': productUuid,
'productType': productType,
'status': status.map((x) => x.toMap()).toList(),
};
}
factory DeviceStatus.fromJson(Map<String, dynamic> json) =>
DeviceStatus.fromMap(json);
String toJson() => json.encode(toMap());
}
class Status {
final String code;
final dynamic value;
Status({
required this.code,
required this.value,
});
factory Status.fromMap(Map<String, dynamic> map) {
return Status(
code: map['code'] ?? '',
value: map['value'],
);
}
Map<String, dynamic> toMap() {
return {
'code': code,
'value': value,
};
}
factory Status.fromJson(String source) => Status.fromMap(json.decode(source));
String toJson() => json.encode(toMap());
}

View File

@ -1,5 +1,5 @@
import 'package:syncrow_web/pages/device_managment/models/room.dart';
import 'package:syncrow_web/pages/device_managment/models/unit.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/room.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart';
class AllDevicesModel {
/*

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/bloc/device_managment_bloc.dart';
import 'package:syncrow_web/pages/device_managment/widgets/device_managment_body.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_managment_body.dart';
import 'package:syncrow_web/web_layout/web_scaffold.dart';
class DeviceManagementPage extends StatelessWidget {

View File

@ -4,9 +4,10 @@ import 'package:syncrow_web/core/extension/build_context_x.dart';
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
import 'package:syncrow_web/pages/common/custom_table.dart';
import 'package:syncrow_web/pages/common/filter/filter_widget.dart';
import 'package:syncrow_web/pages/device_managment/bloc/device_managment_bloc.dart';
import 'package:syncrow_web/pages/device_managment/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/widgets/device_search_filters.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_control_dialog.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_search_filters.dart';
import 'package:syncrow_web/utils/format_date_time.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
import 'package:syncrow_web/utils/style.dart';
@ -78,7 +79,17 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
decoration: containerDecoration,
child: Center(
child: DefaultButton(
onPressed: () {},
onPressed: () {
final selectedDevice =
context.read<DeviceManagementBloc>().selectedDevice;
if (selectedDevice != null) {
showDialog(
context: context,
builder: (context) =>
DeviceControlDialog(device: selectedDevice),
);
}
},
borderRadius: 9,
child: const Text('Control'),
),
@ -90,15 +101,12 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
Expanded(
child: DynamicTable(
cellDecoration: containerDecoration,
selectAll: (p0) {
// visitorBloc.selectedDeviceIds.clear();
// for (var item in state.data) {
// visitorBloc.add(SelectDeviceEvent(item.uuid));
// }
},
onRowCheckboxChanged: (index, isSelected) {
// final deviceId = state.data[index].uuid;
// visitorBloc.add(SelectDeviceEvent(deviceId));
onRowSelected: (index, isSelected, row) {
if (isSelected) {
context
.read<DeviceManagementBloc>()
.add(SelectDevice(devicesToShow[index]));
}
},
withCheckBox: true,
size: context.screenSize,
@ -120,12 +128,14 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
device.uuid ?? '',
device.unit?.name ?? '',
device.room?.name ?? '',
device.batteryLevel?.toString() ?? '',
device.batteryLevel != null
? '${device.batteryLevel}%'
: '',
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
device.createTime ?? 0)),
(device.createTime ?? 0) * 1000)),
device.online == true ? 'Online' : 'Offline',
formatDateTime(DateTime.fromMillisecondsSinceEpoch(
device.updateTime ?? 0)),
(device.updateTime ?? 0) * 1000)),
];
}).toList(),
isEmpty: devicesToShow.isEmpty,

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/common/text_field/custom_text_field.dart';
import 'package:syncrow_web/pages/device_managment/bloc/device_managment_bloc.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_managment_bloc.dart';
import 'package:syncrow_web/pages/common/buttons/search_reset_buttons.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';

View File

@ -0,0 +1,42 @@
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
import 'package:syncrow_web/services/devices_mang_api.dart';
part 'living_room_event.dart';
part 'living_room_state.dart';
class LivingRoomBloc extends Bloc<LivingRoomEvent, LivingRoomState> {
LivingRoomBloc() : super(LivingRoomInitial()) {
on<LivingRoomFetchDeviceStatus>(_onFetchDeviceStatus);
on<LivingRoomControl>(_livingRoomControl);
}
FutureOr<void> _onFetchDeviceStatus(
LivingRoomFetchDeviceStatus event, Emitter<LivingRoomState> emit) async {
emit(LivingRoomDeviceStatusLoading());
try {
final status =
await DevicesManagementApi().getDeviceStatus(event.deviceId);
emit(LivingRoomDeviceStatusLoaded(status));
} catch (e) {
emit(LivingRoomDeviceManagementError(e.toString()));
}
}
FutureOr<void> _livingRoomControl(
LivingRoomControl event, Emitter<LivingRoomState> emit) async {
emit(LivingRoomControlLoading());
try {
final status = Status(code: event.code, value: event.value);
await DevicesManagementApi().deviceControl(event.deviceId, status);
emit(LivingRoomControlSuccess());
} catch (e) {
emit(LivingRoomControlError(e.toString()));
}
}
}

View File

@ -0,0 +1,29 @@
part of 'living_room_bloc.dart';
sealed class LivingRoomEvent extends Equatable {
const LivingRoomEvent();
@override
List<Object> get props => [];
}
class LivingRoomFetchDeviceStatus extends LivingRoomEvent {
final String deviceId;
const LivingRoomFetchDeviceStatus(this.deviceId);
@override
List<Object> get props => [deviceId];
}
class LivingRoomControl extends LivingRoomEvent {
final String deviceId;
final String code;
final bool value;
const LivingRoomControl(
{required this.deviceId, required this.code, required this.value});
@override
List<Object> get props => [deviceId, code, value];
}

View File

@ -0,0 +1,43 @@
part of 'living_room_bloc.dart';
sealed class LivingRoomState extends Equatable {
const LivingRoomState();
@override
List<Object> get props => [];
}
final class LivingRoomInitial extends LivingRoomState {}
class LivingRoomDeviceStatusLoading extends LivingRoomState {}
class LivingRoomDeviceStatusLoaded extends LivingRoomState {
final DeviceStatus status;
const LivingRoomDeviceStatusLoaded(this.status);
@override
List<Object> get props => [status];
}
class LivingRoomDeviceManagementError extends LivingRoomState {
final String message;
const LivingRoomDeviceManagementError(this.message);
@override
List<Object> get props => [message];
}
class LivingRoomControlSuccess extends LivingRoomState {}
class LivingRoomControlError extends LivingRoomState {
final String message;
const LivingRoomControlError(this.message);
@override
List<Object> get props => [message];
}
class LivingRoomControlLoading extends LivingRoomState {}

View File

@ -0,0 +1,70 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/pages/device_managment/living_room_switch/bloc/living_room_bloc.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
class CeilingLight extends StatelessWidget {
const CeilingLight(
{super.key,
required this.value,
required this.code,
required this.deviceId});
final bool value;
final String code;
final String deviceId;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ClipOval(
child: Container(
color: ColorsManager.whiteColors,
child: SvgPicture.asset(
Assets.lightPulp,
width: 60,
height: 60,
fit: BoxFit.cover,
),
)),
SizedBox(
height: 20,
width: 35,
child: CupertinoSwitch(
value: value,
onChanged: (newValue) {
context.read<LivingRoomBloc>().add(
LivingRoomControl(
deviceId: deviceId,
code: code,
value: newValue,
),
);
},
),
),
],
),
const Spacer(),
const Center(
child: Text(
'Ceiling Light',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
),
],
);
}
}

View File

@ -0,0 +1,70 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/pages/device_managment/living_room_switch/bloc/living_room_bloc.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
class SpotLight extends StatelessWidget {
const SpotLight(
{super.key,
required this.value,
required this.code,
required this.deviceId});
final bool value;
final String code;
final String deviceId;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ClipOval(
child: Container(
color: ColorsManager.whiteColors,
child: SvgPicture.asset(
Assets.lightPulp,
width: 60,
height: 60,
fit: BoxFit.cover,
),
)),
SizedBox(
height: 20,
width: 35,
child: CupertinoSwitch(
value: value,
onChanged: (newValue) {
context.read<LivingRoomBloc>().add(
LivingRoomControl(
deviceId: deviceId,
code: code,
value: newValue,
),
);
},
),
),
],
),
const Spacer(),
const Center(
child: Text(
'Spotlight',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
),
],
);
}
}

View File

@ -0,0 +1,70 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/pages/device_managment/living_room_switch/bloc/living_room_bloc.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
class WallLight extends StatelessWidget {
const WallLight(
{super.key,
required this.value,
required this.code,
required this.deviceId});
final bool value;
final String code;
final String deviceId;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ClipOval(
child: Container(
color: ColorsManager.whiteColors,
child: SvgPicture.asset(
Assets.lightPulp,
width: 60,
height: 60,
fit: BoxFit.cover,
),
)),
SizedBox(
height: 20,
width: 35,
child: CupertinoSwitch(
value: value,
onChanged: (newValue) {
context.read<LivingRoomBloc>().add(
LivingRoomControl(
deviceId: deviceId,
code: code,
value: newValue,
),
);
},
),
),
],
),
const Spacer(),
const Center(
child: Text(
'Wall Light',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 14,
),
),
),
],
);
}
}

View File

@ -0,0 +1,20 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/device_managment/living_room_switch/control_list/cieling_light.dart';
import 'package:syncrow_web/pages/device_managment/living_room_switch/control_list/spot_light.dart';
import 'package:syncrow_web/pages/device_managment/living_room_switch/control_list/wall_light.dart';
mixin LivingRoomHelper {
Widget livingRoomControlWidgets(
{required bool value, required String code, required String deviceId}) {
switch (code) {
case 'switch_1':
return WallLight(value: value, code: code, deviceId: deviceId);
case 'switch_2':
return CeilingLight(value: value, code: code, deviceId: deviceId);
case 'switch_3':
return SpotLight(value: value, code: code, deviceId: deviceId);
default:
return const SizedBox();
}
}
}

View File

@ -0,0 +1,70 @@
import 'package:flutter/material.dart';
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/all_devices/models/devices_model.dart';
import 'package:syncrow_web/pages/device_managment/living_room_switch/bloc/living_room_bloc.dart';
import 'package:syncrow_web/pages/device_managment/living_room_switch/helper/living_room_helper.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class LivingRoomDeviceControl extends StatelessWidget with LivingRoomHelper {
const LivingRoomDeviceControl({super.key, required this.device});
final AllDevicesModel device;
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) =>
LivingRoomBloc()..add(LivingRoomFetchDeviceStatus(device.uuid!)),
child: BlocListener<LivingRoomBloc, LivingRoomState>(
listener: (context, state) {
if (state is LivingRoomControlSuccess) {
context
.read<LivingRoomBloc>()
.add(LivingRoomFetchDeviceStatus(device.uuid!));
}
},
child: BlocBuilder<LivingRoomBloc, LivingRoomState>(
builder: (context, state) {
if (state is LivingRoomDeviceStatusLoading) {
return const Center(child: CircularProgressIndicator());
} else if (state is LivingRoomDeviceStatusLoaded) {
return _buildStatusControls(state.status.status);
} else {
return const Center(child: Text('Error fetching status'));
}
},
),
),
);
}
Widget _buildStatusControls(List<Status> statuses) {
return GridView.builder(
padding: const EdgeInsets.symmetric(horizontal: 40),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisExtent: 133,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
itemCount: 3,
itemBuilder: (context, index) {
final status = statuses[index];
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: ColorsManager.greyColor.withOpacity(0.2),
border: Border.all(color: ColorsManager.boxDivider),
),
padding: const EdgeInsets.all(16),
child: livingRoomControlWidgets(
value: status.value, code: status.code, deviceId: device.uuid!),
);
},
);
}
}

View File

@ -0,0 +1,275 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:syncrow_web/core/extension/build_context_x.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/helper/route_controls_based_code.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class DeviceControlDialog extends StatelessWidget with RouteControlsBasedCode {
final AllDevicesModel device;
const DeviceControlDialog({super.key, required this.device});
@override
Widget build(BuildContext context) {
return Dialog(
backgroundColor: Colors.white,
insetPadding: const EdgeInsets.all(20),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: SizedBox(
width: 798,
height: context.screenHeight * 0.7,
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Center(
child: Text(
device.categoryName ?? 'Device Control',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 22,
color: ColorsManager.dialogBlueTitle,
),
),
),
const SizedBox(height: 20),
_buildDeviceInfoSection(),
const SizedBox(height: 20),
//// BUILD DEVICE CONTROLS
///
//// ROUTE TO SPECIFIC CONTROL VIEW BASED ON DEVICE CATEGORY
routeControlsWidgets(device: device),
],
),
),
),
),
);
}
Widget _buildDeviceInfoSection() {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 40, horizontal: 50),
child: Table(
children: [
TableRow(
children: [
_buildInfoRow('Product Name:', device.categoryName ?? 'N/A'),
_buildInfoRow('Device ID:', device.uuid ?? ''),
],
),
TableRow(children: [
_buildInfoRow('Virtual Address:',
'Area - Street 1 - Building 1 - First Floor'),
const SizedBox.shrink(),
]),
TableRow(
children: [
_buildInfoRow('Unit Name:', device.unit?.name ?? 'N/A'),
_buildInfoRow('Room:', device.room?.name ?? 'N/A'),
],
),
TableRow(
children: [
_buildInfoRow('Installation Date and Time:', '09/08/2024 13:30'),
const SizedBox.shrink(),
],
),
TableRow(
children: [
_buildInfoRow('Status:', 'Online', statusColor: Colors.green),
_buildInfoRow('Last Offline Date and Time:', '-'),
],
),
],
),
);
}
Widget _buildInfoRow(String title, String value, {Color? statusColor}) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontWeight: FontWeight.normal,
fontSize: 12,
color: ColorsManager.lightGreyColor,
),
),
const SizedBox(width: 10),
Text(
value,
style: TextStyle(
fontSize: 16,
color: statusColor ?? Colors.black,
),
),
],
),
);
}
// ////// changing here for devices controls ////
// Widget _buildStatusControls(List<Status> statuses) {
// return GridView.builder(
// padding: const EdgeInsets.symmetric(horizontal: 40),
// shrinkWrap: true,
// physics: const NeverScrollableScrollPhysics(),
// gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 3,
// mainAxisExtent: 133,
// crossAxisSpacing: 12,
// mainAxisSpacing: 12,
// ),
// itemCount: statuses.length,
// itemBuilder: (context, index) {
// final status = statuses[index];
// return Container(
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(20),
// color: ColorsManager.greyColor.withOpacity(0.2),
// border: Border.all(color: ColorsManager.boxDivider),
// ),
// padding: const EdgeInsets.all(16),
// child: _buildControlForStatus(status),
// );
// },
// );
// }
// Widget _buildControlForStatus(Status status) {
// switch (status.type) {
// case OperationDialogType.onOff:
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Row(
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// if (status.icon.isNotEmpty)
// ClipOval(
// child: Container(
// color: ColorsManager.whiteColors,
// child: SvgPicture.asset(
// status.icon,
// width: 60,
// height: 60,
// fit: BoxFit.cover,
// ),
// )),
// SizedBox(
// height: 20,
// width: 35,
// child: CupertinoSwitch(
// value: status.value ?? false,
// onChanged: (newValue) {
// // Handle toggle change
// },
// ),
// ),
// ],
// ),
// const Spacer(),
// Center(
// child: Text(
// status.name,
// style: const TextStyle(
// fontWeight: FontWeight.bold,
// fontSize: 14,
// ),
// ),
// ),
// ],
// );
// case OperationDialogType.countdown:
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Center(
// child: Text(
// status.name,
// style: const TextStyle(
// fontWeight: FontWeight.bold,
// fontSize: 14,
// ),
// ),
// ),
// const Spacer(),
// IncrementDecrementWidget(
// value: status.value.toString(),
// description: 'hr',
// onIncrement: () {
// // Handle increment
// },
// onDecrement: () {
// // Handle decrement
// },
// ),
// ],
// );
// case OperationDialogType.integerSteps:
// return IncrementDecrementWidget(
// value: status.value.toString(),
// description: 'm',
// onIncrement: () {
// // Handle increment
// },
// onDecrement: () {
// // Handle decrement
// },
// );
// case OperationDialogType.listOfOptions:
// return Wrap(
// children: [
// ...status.options!.map((e) => ClipOval(
// child: SvgPicture.asset(
// e.icon,
// width: 40,
// height: 40,
// fit: BoxFit.cover,
// ),
// ))
// ],
// );
// default:
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// if (status.icon.isNotEmpty)
// ClipOval(
// child: Container(
// color: ColorsManager.whiteColors,
// child: SvgPicture.asset(
// status.icon,
// width: 60,
// height: 60,
// fit: BoxFit.cover,
// ),
// )),
// const Spacer(),
// Text(
// status.value.toString(),
// style: const TextStyle(
// fontSize: 14,
// color: Colors.black54,
// ),
// ),
// ],
// );
// }
// }
}

View File

@ -0,0 +1,87 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class IncrementDecrementWidget extends StatelessWidget {
final String value;
final String description;
final VoidCallback onIncrement;
final VoidCallback onDecrement;
const IncrementDecrementWidget({
super.key,
required this.value,
required this.description,
required this.onIncrement,
required this.onDecrement,
});
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Material(
type: MaterialType.transparency,
child: ClipRRect(
borderRadius: BorderRadius.circular(100),
child: InkWell(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: onDecrement,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.remove,
color: ColorsManager.greyColor,
size: 32,
),
),
),
),
),
RichText(
text: TextSpan(
text: '',
children: [
TextSpan(
text: value,
style: TextStyle(
fontSize: 38,
color: ColorsManager.dialogBlueTitle,
fontWeight: FontWeight.bold,
),
),
TextSpan(
text: description,
style: const TextStyle(
fontSize: 12,
color: ColorsManager.blackColor,
fontWeight: FontWeight.bold,
),
),
],
),
),
Material(
type: MaterialType.transparency,
child: ClipRRect(
borderRadius: BorderRadius.circular(100),
child: InkWell(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
onTap: onIncrement,
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.add,
color: ColorsManager.greyColor,
size: 32,
),
),
),
),
),
],
);
}
}

View File

@ -5,7 +5,7 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:graphview/GraphView.dart';
import 'package:syncrow_web/pages/access_management/view/access_management.dart';
import 'package:syncrow_web/pages/auth/model/user_model.dart';
import 'package:syncrow_web/pages/device_managment/view/device_managment_page.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/view/device_managment_page.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
import 'package:syncrow_web/pages/home/bloc/home_state.dart';
import 'package:syncrow_web/pages/home/home_model/home_item_model.dart';

View File

@ -178,7 +178,7 @@ class AddDeviceDialog extends StatelessWidget {
.add(SelectDeviceEvent(item.uuid));
}
},
onRowCheckboxChanged: (index, isSelected) {
onRowSelected: (index, isSelected, row) {
final deviceId = state.data[index].uuid;
visitorBloc.add(SelectDeviceEvent(deviceId));
},