Merge branch 'dev' into SP-1660-fe-ui-enhancement-update-confirmation-dialog-on-create-visitor-password-flow

This commit is contained in:
Faris Armoush
2025-06-29 16:10:43 +03:00
committed by GitHub
31 changed files with 689 additions and 360 deletions

View File

@ -46,11 +46,11 @@ class AirQualityDistributionBloc
}
}
Future<void> _onClearAirQualityDistribution(
void _onClearAirQualityDistribution(
ClearAirQualityDistribution event,
Emitter<AirQualityDistributionState> emit,
) async {
emit(const AirQualityDistributionState());
) {
emit(AirQualityDistributionState(selectedAqiType: state.selectedAqiType));
}
void _onUpdateAqiTypeEvent(

View File

@ -75,6 +75,6 @@ class RangeOfAqiBloc extends Bloc<RangeOfAqiEvent, RangeOfAqiState> {
ClearRangeOfAqiEvent event,
Emitter<RangeOfAqiState> emit,
) {
emit(const RangeOfAqiState());
emit(RangeOfAqiState(selectedAqiType: state.selectedAqiType));
}
}

View File

@ -34,6 +34,7 @@ class AqiDistributionChartTitle extends StatelessWidget {
alignment: AlignmentDirectional.centerEnd,
fit: BoxFit.scaleDown,
child: AqiTypeDropdown(
selectedAqiType: context.watch<AirQualityDistributionBloc>().state.selectedAqiType,
onChanged: (value) {
if (value != null) {
final bloc = context.read<AirQualityDistributionBloc>();

View File

@ -18,19 +18,20 @@ enum AqiType {
}
class AqiTypeDropdown extends StatefulWidget {
const AqiTypeDropdown({super.key, required this.onChanged});
const AqiTypeDropdown({
required this.onChanged,
this.selectedAqiType,
super.key,
});
final ValueChanged<AqiType?> onChanged;
final AqiType? selectedAqiType;
@override
State<AqiTypeDropdown> createState() => _AqiTypeDropdownState();
}
class _AqiTypeDropdownState extends State<AqiTypeDropdown> {
AqiType? _selectedItem = AqiType.aqi;
void _updateSelectedItem(AqiType? item) => setState(() => _selectedItem = item);
@override
Widget build(BuildContext context) {
return Container(
@ -41,8 +42,8 @@ class _AqiTypeDropdownState extends State<AqiTypeDropdown> {
width: 1,
),
),
child: DropdownButton<AqiType?>(
value: _selectedItem,
child: DropdownButton<AqiType>(
value: widget.selectedAqiType,
isDense: true,
borderRadius: BorderRadius.circular(16),
dropdownColor: ColorsManager.whiteColors,
@ -59,10 +60,7 @@ class _AqiTypeDropdownState extends State<AqiTypeDropdown> {
items: AqiType.values
.map((e) => DropdownMenuItem(value: e, child: Text(e.value)))
.toList(),
onChanged: (value) {
_updateSelectedItem(value);
widget.onChanged(value);
},
onChanged: widget.onChanged,
),
);
}

View File

@ -63,15 +63,15 @@ class RangeOfAqiChartTitle extends StatelessWidget {
fit: BoxFit.scaleDown,
alignment: AlignmentDirectional.centerEnd,
child: AqiTypeDropdown(
selectedAqiType: context.watch<RangeOfAqiBloc>().state.selectedAqiType,
onChanged: (value) {
final spaceTreeState = context.read<SpaceTreeBloc>().state;
final spaceUuid = spaceTreeState.selectedSpaces.firstOrNull;
if (spaceUuid == null) return;
if (value != null) {
context.read<RangeOfAqiBloc>().add(UpdateAqiTypeEvent(value));
}
if (spaceUuid == null) return;
},
),
),

View File

@ -16,11 +16,12 @@ class DeviceManagementBloc
int _onlineCount = 0;
int _offlineCount = 0;
int _lowBatteryCount = 0;
List<AllDevicesModel> _selectedDevices = [];
final List<AllDevicesModel> _selectedDevices = [];
List<AllDevicesModel> _filteredDevices = [];
String currentProductName = '';
String? currentCommunity;
String? currentUnitName;
String subSpaceName = '';
DeviceManagementBloc() : super(DeviceManagementInitial()) {
on<FetchDevices>(_onFetchDevices);
@ -31,24 +32,29 @@ class DeviceManagementBloc
on<ResetFilters>(_onResetFilters);
on<ResetSelectedDevices>(_onResetSelectedDevices);
on<UpdateSelection>(_onUpdateSelection);
on<UpdateDeviceName>(_onUpdateDeviceName);
on<UpdateSubSpaceName>(_onUpdateSubSpaceName);
}
Future<void> _onFetchDevices(
FetchDevices event, Emitter<DeviceManagementState> emit) async {
emit(DeviceManagementLoading());
try {
List<AllDevicesModel> devices = [];
var devices = <AllDevicesModel>[];
_devices.clear();
var spaceBloc = event.context.read<SpaceTreeBloc>();
final spaceBloc = event.context.read<SpaceTreeBloc>();
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
if (spaceBloc.state.selectedCommunities.isEmpty) {
devices = await DevicesManagementApi().fetchDevices(projectUuid);
devices = await DevicesManagementApi().fetchDevices('', '', projectUuid);
} else {
for (var community in spaceBloc.state.selectedCommunities) {
List<String> spacesList =
for (final community in spaceBloc.state.selectedCommunities) {
final spacesList =
spaceBloc.state.selectedCommunityAndSpaces[community] ?? [];
devices.addAll(await DevicesManagementApi()
.fetchDevices(projectUuid, spacesId: spacesList));
for (final space in spacesList) {
devices.addAll(await DevicesManagementApi()
.fetchDevices(community, space, projectUuid));
}
}
}
@ -70,7 +76,7 @@ class DeviceManagementBloc
}
}
void _onFilterDevices(
Future<void> _onFilterDevices(
FilterDevices event, Emitter<DeviceManagementState> emit) async {
if (_devices.isNotEmpty) {
_filteredDevices = List.from(_devices.where((device) {
@ -152,8 +158,7 @@ class DeviceManagementBloc
add(FilterDevices(_getFilterFromIndex(_selectedIndex)));
}
void _onSelectDevice(
SelectDevice event, Emitter<DeviceManagementState> emit) {
void _onSelectDevice(SelectDevice event, Emitter<DeviceManagementState> emit) {
final selectedUuid = event.selectedDevice.uuid;
if (_selectedDevices.any((device) => device.uuid == selectedUuid)) {
@ -162,9 +167,9 @@ class DeviceManagementBloc
_selectedDevices.add(event.selectedDevice);
}
List<AllDevicesModel> clonedSelectedDevices = List.from(_selectedDevices);
final clonedSelectedDevices = List<AllDevicesModel>.from(_selectedDevices);
bool isControlButtonEnabled =
final isControlButtonEnabled =
_checkIfControlButtonEnabled(clonedSelectedDevices);
if (state is DeviceManagementLoaded) {
@ -194,8 +199,8 @@ class DeviceManagementBloc
void _onUpdateSelection(
UpdateSelection event, Emitter<DeviceManagementState> emit) {
List<AllDevicesModel> selectedDevices = [];
List<AllDevicesModel> devicesToSelectFrom = [];
final selectedDevices = <AllDevicesModel>[];
var devicesToSelectFrom = <AllDevicesModel>[];
if (state is DeviceManagementLoaded) {
devicesToSelectFrom = (state as DeviceManagementLoaded).devices;
@ -203,7 +208,7 @@ class DeviceManagementBloc
devicesToSelectFrom = (state as DeviceManagementFiltered).filteredDevices;
}
for (int i = 0; i < event.selectedRows.length; i++) {
for (var i = 0; i < event.selectedRows.length; i++) {
if (event.selectedRows[i]) {
selectedDevices.add(devicesToSelectFrom[i]);
}
@ -249,8 +254,7 @@ class DeviceManagementBloc
_onlineCount = _devices.where((device) => device.online == true).length;
_offlineCount = _devices.where((device) => device.online == false).length;
_lowBatteryCount = _devices
.where((device) =>
device.batteryLevel != null && device.batteryLevel! < 20)
.where((device) => device.batteryLevel != null && device.batteryLevel! < 20)
.length;
}
@ -267,8 +271,7 @@ class DeviceManagementBloc
}
}
void _onSearchDevices(
SearchDevices event, Emitter<DeviceManagementState> emit) {
void _onSearchDevices(SearchDevices event, Emitter<DeviceManagementState> emit) {
if ((event.community == null || event.community!.isEmpty) &&
(event.unitName == null || event.unitName!.isEmpty) &&
(event.deviceNameOrProductName == null ||
@ -297,7 +300,7 @@ class DeviceManagementBloc
currentCommunity = event.community;
currentUnitName = event.unitName;
List<AllDevicesModel> devicesToSearch = _devices;
final devicesToSearch = _devices;
if (devicesToSearch.isNotEmpty) {
final searchText = event.deviceNameOrProductName?.toLowerCase() ?? '';
@ -340,5 +343,134 @@ class DeviceManagementBloc
}
}
void _onUpdateDeviceName(
UpdateDeviceName event, Emitter<DeviceManagementState> emit) {
final devices = _devices.map((device) {
if (device.uuid == event.deviceId) {
final modifiedDevice = device.copyWith(name: event.newName);
_selectedDevices.removeWhere((device) => device.uuid == event.deviceId);
_selectedDevices.add(modifiedDevice);
return modifiedDevice;
}
return device;
}).toList();
final filteredDevices = _filteredDevices.map((device) {
if (device.uuid == event.deviceId) {
final modifiedDevice = device.copyWith(name: event.newName);
_selectedDevices.removeWhere((device) => device.uuid == event.deviceId);
_selectedDevices.add(modifiedDevice);
return modifiedDevice;
}
return device;
}).toList();
_devices = devices;
_filteredDevices = filteredDevices;
if (state is DeviceManagementLoaded) {
final loaded = state as DeviceManagementLoaded;
final selectedDevices01 = _selectedDevices.map((device) {
if (device.uuid == event.deviceId) {
final modifiedDevice = device.copyWith(name: event.newName);
return modifiedDevice;
}
return device;
}).toList();
emit(DeviceManagementLoaded(
devices: devices,
selectedIndex: loaded.selectedIndex,
onlineCount: loaded.onlineCount,
offlineCount: loaded.offlineCount,
lowBatteryCount: loaded.lowBatteryCount,
selectedDevice: selectedDevices01,
isControlButtonEnabled: loaded.isControlButtonEnabled,
));
} else if (state is DeviceManagementFiltered) {
final filtered = state as DeviceManagementFiltered;
final selectedDevices01 = filtered.selectedDevice?.map((device) {
if (device.uuid == event.deviceId) {
final modifiedDevice = device.copyWith(name: event.newName);
return modifiedDevice;
}
return device;
}).toList();
emit(DeviceManagementFiltered(
filteredDevices: filteredDevices,
selectedIndex: filtered.selectedIndex,
onlineCount: filtered.onlineCount,
offlineCount: filtered.offlineCount,
lowBatteryCount: filtered.lowBatteryCount,
selectedDevice: selectedDevices01,
isControlButtonEnabled: filtered.isControlButtonEnabled,
));
}
}
void _onUpdateSubSpaceName(
UpdateSubSpaceName event, Emitter<DeviceManagementState> emit) {
final devices = _devices.map((device) {
if (device.uuid == event.deviceId) {
return device.copyWith(
subspace:
device.subspace?.copyWith(subspaceName: event.newSubSpaceName));
}
return device;
}).toList();
final filteredDevices = _filteredDevices.map((device) {
if (device.uuid == event.deviceId) {
return device.copyWith(
subspace:
device.subspace?.copyWith(subspaceName: event.newSubSpaceName));
}
return device;
}).toList();
_devices = devices;
_filteredDevices = filteredDevices;
if (state is DeviceManagementLoaded) {
final loaded = state as DeviceManagementLoaded;
final selectedDevices = loaded.selectedDevice?.map((device) {
if (device.uuid == event.deviceId) {
return device.copyWith(
subspace:
device.subspace?.copyWith(subspaceName: event.newSubSpaceName));
}
return device;
}).toList();
emit(DeviceManagementLoaded(
devices: _devices,
selectedIndex: loaded.selectedIndex,
onlineCount: loaded.onlineCount,
offlineCount: loaded.offlineCount,
lowBatteryCount: loaded.lowBatteryCount,
selectedDevice: selectedDevices,
isControlButtonEnabled: loaded.isControlButtonEnabled,
));
} else if (state is DeviceManagementFiltered) {
// final filtered = state as DeviceManagementFiltered;
// emit(DeviceManagementFiltered(
// filteredDevices: _filteredDevices,
// selectedIndex: filtered.selectedIndex,
// onlineCount: filtered.onlineCount,
// offlineCount: filtered.offlineCount,
// lowBatteryCount: filtered.lowBatteryCount,
// selectedDevice: filtered.selectedDevice,
// isControlButtonEnabled: filtered.isControlButtonEnabled,
// ));
}
}
void changeSubspaceName(
String deviceId, String newSubSpaceName, String subspaceId) {
add(UpdateSubSpaceName(
deviceId: deviceId,
newSubSpaceName: newSubSpaceName,
subspaceId: subspaceId,
));
}
List<AllDevicesModel> get selectedDevices => _selectedDevices;
}

View File

@ -70,3 +70,21 @@ class UpdateSelection extends DeviceManagementEvent {
const UpdateSelection(this.selectedRows);
}
class UpdateDeviceName extends DeviceManagementEvent {
final String deviceId;
final String newName;
const UpdateDeviceName({required this.deviceId, required this.newName});
}
class UpdateSubSpaceName extends DeviceManagementEvent {
final String deviceId;
final String newSubSpaceName;
final String subspaceId;
const UpdateSubSpaceName(
{required this.deviceId,
required this.newSubSpaceName,
required this.subspaceId});
}

View File

@ -44,4 +44,20 @@ class DeviceSubspace {
static List<Map<String, dynamic>> listToJson(List<DeviceSubspace> subspaces) {
return subspaces.map((subspace) => subspace.toJson()).toList();
}
DeviceSubspace copyWith({
String? uuid,
DateTime? createdAt,
DateTime? updatedAt,
String? subspaceName,
bool? disabled,
}) {
return DeviceSubspace(
uuid: uuid ?? this.uuid,
createdAt: createdAt ?? this.createdAt,
updatedAt: updatedAt ?? this.updatedAt,
subspaceName: subspaceName ?? this.subspaceName,
disabled: disabled ?? this.disabled,
);
}
}

View File

@ -588,4 +588,72 @@ SOS
"NCPS": DeviceType.NCPS,
"PC": DeviceType.PC,
};
AllDevicesModel copyWith({
DevicesModelRoom? room,
DeviceSubspace? subspace,
DevicesModelUnit? unit,
DeviceCommunityModel? community,
String? productUuid,
String? productType,
String? permissionType,
int? activeTime,
String? category,
String? categoryName,
int? createTime,
String? gatewayId,
String? icon,
String? ip,
String? lat,
String? localKey,
String? lon,
String? model,
String? name,
String? nodeId,
bool? online,
String? ownerId,
bool? sub,
String? timeZone,
int? updateTime,
String? uuid,
int? batteryLevel,
String? productName,
List<DeviceSpaceModel>? spaces,
List<DeviceTagModel>? deviceTags,
DeviceSubSpace? deviceSubSpace,
}) {
return AllDevicesModel(
room: room ?? this.room,
subspace: subspace ?? this.subspace,
unit: unit ?? this.unit,
community: community ?? this.community,
productUuid: productUuid ?? this.productUuid,
productType: productType ?? this.productType,
permissionType: permissionType ?? this.permissionType,
activeTime: activeTime ?? this.activeTime,
category: category ?? this.category,
categoryName: categoryName ?? this.categoryName,
createTime: createTime ?? this.createTime,
gatewayId: gatewayId ?? this.gatewayId,
icon: icon ?? this.icon,
ip: ip ?? this.ip,
lat: lat ?? this.lat,
localKey: localKey ?? this.localKey,
lon: lon ?? this.lon,
model: model ?? this.model,
name: name ?? this.name,
nodeId: nodeId ?? this.nodeId,
online: online ?? this.online,
ownerId: ownerId ?? this.ownerId,
sub: sub ?? this.sub,
timeZone: timeZone ?? this.timeZone,
updateTime: updateTime ?? this.updateTime,
uuid: uuid ?? this.uuid,
batteryLevel: batteryLevel ?? this.batteryLevel,
productName: productName ?? this.productName,
spaces: spaces ?? this.spaces,
deviceTags: deviceTags ?? this.deviceTags,
deviceSubSpace: deviceSubSpace ?? this.deviceSubSpace,
);
}
}

View File

@ -23,6 +23,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
@override
Widget build(BuildContext context) {
return BlocBuilder<DeviceManagementBloc, DeviceManagementState>(
buildWhen: (previous, current) => previous != current,
builder: (context, state) {
List<AllDevicesModel> devicesToShow = [];
int selectedIndex = 0;
@ -31,7 +32,6 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
int lowBatteryCount = 0;
bool isControlButtonEnabled = false;
List<AllDevicesModel> selectedDevices = [];
if (state is DeviceManagementLoaded) {
devicesToShow = state.devices;
selectedIndex = state.selectedIndex;
@ -111,6 +111,8 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
onPressed: isControlButtonEnabled
? () {
if (isAnyDeviceOffline) {
ScaffoldMessenger.of(context)
.clearSnackBars();
ScaffoldMessenger.of(context)
.showSnackBar(
const SnackBar(
@ -190,7 +192,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
'Product Name',
'Device ID',
'Space Name',
'location',
'Location',
'Battery Level',
'Installation Date and Time',
'Status',
@ -242,7 +244,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
.map((device) => device.uuid!)
.toList(),
isEmpty: devicesToShow.isEmpty,
onSettingsPressed: (rowIndex) {
onSettingsPressed: (rowIndex) async {
final device = devicesToShow[rowIndex];
showDeviceSettingsSidebar(context, device);
},
@ -264,7 +266,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
barrierDismissible: true,
barrierLabel: "Device Settings",
transitionDuration: const Duration(milliseconds: 300),
pageBuilder: (context, anim1, anim2) {
pageBuilder: (_, anim1, anim2) {
return Align(
alignment: Alignment.centerRight,
child: Material(
@ -274,6 +276,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout {
child: DeviceSettingsPanel(
device: device,
onClose: () => Navigator.of(context).pop(),
deviceManagementBloc: context.read<DeviceManagementBloc>(),
),
),
),

View File

@ -23,8 +23,8 @@ class AccurteCalibratingDialog extends StatelessWidget {
body: const NormalTextBodyForDialog(
title: '',
step1:
'1. Click Close Button to make the Curtain run to Full Close and Position.',
step2: '2. click Next to complete the Calibration.',
'Click Close Button to make the Curtain run to Full Close and Position.',
step2: 'click Next to complete the Calibration.',
),
leftOnTap: () => Navigator.of(parentContext).pop(),
rightOnTap: () {

View File

@ -20,8 +20,8 @@ class AccurateCalibrationDialog extends StatelessWidget {
title: 'Accurate Calibration',
body: const NormalTextBodyForDialog(
title: 'Prepare Calibration:',
step1: '1. Run The Curtain to the Fully Open Position,and pause.',
step2: '2. click Next to Start accurate calibration.',
step1: 'Run The Curtain to the Fully Open Position,and pause.',
step2: 'click Next to Start accurate calibration.',
),
leftOnTap: () => Navigator.of(parentContext).pop(),
rightOnTap: () {

View File

@ -17,78 +17,87 @@ class AccurateDialogWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SizedBox(
height: 300,
width: 400,
height: 250,
width: 500,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Text(
title,
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: ColorsManager.blueColor,
),
Expanded(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Text(
title,
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: ColorsManager.dialogBlueTitle,
),
),
),
const Divider(
indent: 60,
endIndent: 60,
),
],
),
),
const SizedBox(height: 5),
const Divider(
indent: 10,
endIndent: 10,
),
Padding(
padding: const EdgeInsets.all(10),
Expanded(
child: body,
),
const SizedBox(height: 20),
const Spacer(),
const Divider(),
Row(
children: [
Expanded(
child: InkWell(
onTap: leftOnTap,
child: Container(
height: 60,
alignment: Alignment.center,
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.grayBorder,
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const Divider(),
Row(
children: [
Expanded(
child: InkWell(
onTap: leftOnTap,
child: Container(
height: 40,
alignment: Alignment.center,
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.grayBorder,
),
),
),
child: const Text(
'Cancel',
style: TextStyle(color: ColorsManager.grayBorder),
),
),
),
),
child: const Text(
'Cancel',
style: TextStyle(color: ColorsManager.grayBorder),
),
),
),
),
Expanded(
child: InkWell(
onTap: rightOnTap,
child: Container(
height: 60,
alignment: Alignment.center,
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.grayBorder,
Expanded(
child: InkWell(
onTap: rightOnTap,
child: Container(
height: 40,
alignment: Alignment.center,
decoration: const BoxDecoration(
border: Border(
right: BorderSide(
color: ColorsManager.grayBorder,
),
),
),
child: const Text(
'Next',
style: TextStyle(
color: ColorsManager.blueColor,
),
),
),
),
),
child: const Text(
'Next',
style: TextStyle(
color: ColorsManager.blueColor,
),
),
),
),
)
],
)
],
)
],
),
)
],
),

View File

@ -1,7 +1,9 @@
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/curtain_module/bloc/curtain_module_bloc.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
class CalibrateCompletedDialog extends StatelessWidget {
final BuildContext parentContext;
@ -21,52 +23,62 @@ class CalibrateCompletedDialog extends StatelessWidget {
width: 400,
child: Column(
children: [
const Padding(
padding: EdgeInsets.all(10),
child: Text(
'Calibration Completed',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: ColorsManager.blueColor,
),
Expanded(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Text(
'Calibration Completed',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: ColorsManager.dialogBlueTitle,
),
),
),
const SizedBox(height: 5),
const Divider(
indent: 10,
endIndent: 10,
),
],
),
),
const SizedBox(height: 5),
const Divider(
indent: 10,
endIndent: 10,
Expanded(
child: SvgPicture.asset(Assets.completedDoneIcon),
),
const Icon(
Icons.check_circle,
size: 100,
color: ColorsManager.blueColor,
),
const Spacer(),
const Divider(
indent: 10,
endIndent: 10,
),
InkWell(
onTap: () {
parentContext.read<CurtainModuleBloc>().add(
FetchCurtainModuleStatusEvent(
deviceId: deviceId,
),
);
Navigator.of(parentContext).pop();
Navigator.of(parentContext).pop();
},
child: Container(
height: 40,
width: double.infinity,
alignment: Alignment.center,
child: const Text(
'Close',
style: TextStyle(
color: ColorsManager.grayBorder,
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const Divider(
indent: 10,
endIndent: 10,
),
),
InkWell(
onTap: () {
parentContext.read<CurtainModuleBloc>().add(
FetchCurtainModuleStatusEvent(
deviceId: deviceId,
),
);
Navigator.of(parentContext).pop();
Navigator.of(parentContext).pop();
},
child: Container(
height: 40,
width: double.infinity,
alignment: Alignment.center,
child: const Text(
'Close',
style: TextStyle(
color: ColorsManager.grayBorder,
),
),
),
)
],
),
)
],

View File

@ -15,28 +15,72 @@ class NormalTextBodyForDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
color: ColorsManager.grayColor,
return Padding(
padding: EdgeInsetsGeometry.only(left: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (title.isEmpty)
const SizedBox()
else
Expanded(
child: Text(
title,
style: const TextStyle(
color: ColorsManager.grayColor,
fontSize: 17,
),
),
),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
width: 10,
),
const Text('1. ',
style: TextStyle(
color: ColorsManager.grayColor,
fontSize: 17,
)),
SizedBox(
width: 450,
child: Text(
step1,
style: const TextStyle(
color: ColorsManager.grayColor,
fontSize: 17,
),
),
),
],
),
),
),
Text(
step1,
style: const TextStyle(
color: ColorsManager.grayColor,
),
),
Text(
step2,
style: const TextStyle(
color: ColorsManager.grayColor,
),
)
],
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(
width: 10,
),
const Text('2. ',
style: TextStyle(
color: ColorsManager.grayColor,
fontSize: 17,
)),
Text(
step2,
style: const TextStyle(
color: ColorsManager.grayColor,
fontSize: 17,
),
),
],
),
)
],
),
);
}
}

View File

@ -19,7 +19,7 @@ class NumberInputField extends StatelessWidget {
contentPadding: EdgeInsets.zero,
),
style: const TextStyle(
fontSize: 20,
fontSize: 15,
color: ColorsManager.blackColor,
),
);

View File

@ -18,7 +18,7 @@ class PrefReversCardWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return DefaultContainer(
padding: const EdgeInsets.all(12),
padding: const EdgeInsets.all(18),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,

View File

@ -23,12 +23,12 @@ class CurtainModulePrefrencesDialog extends StatelessWidget {
Widget build(_) {
return AlertDialog(
backgroundColor: ColorsManager.CircleImageBackground,
contentPadding: const EdgeInsets.all(30),
title: const Center(
contentPadding: const EdgeInsets.all(20),
title: Center(
child: Text(
'Preferences',
style: TextStyle(
color: ColorsManager.blueColor,
color: ColorsManager.dialogBlueTitle,
fontSize: 24,
fontWeight: FontWeight.bold,
),

View File

@ -69,49 +69,71 @@ class _QuickCalibratingDialogState extends State<QuickCalibratingDialog> {
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'1. please Enter the Travel Time:',
style: TextStyle(color: ColorsManager.grayBorder),
),
const SizedBox(height: 10),
Container(
width: 150,
height: 40,
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: ColorsManager.whiteColors,
borderRadius: BorderRadius.circular(12),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: NumberInputField(controller: _controller),
),
const Expanded(
child: Text(
'seconds',
style: TextStyle(
fontSize: 15,
color: ColorsManager.blueColor,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
if (_errorText != null)
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
_errorText!,
style: const TextStyle(
color: ColorsManager.red,
fontSize: 14,
const Expanded(
child: Align(
alignment: Alignment.center,
child: Padding(
padding: EdgeInsets.only(right: 75),
child: Text(
'1.please Enter the Travel Time:',
style: TextStyle(color: ColorsManager.lightGrayColor),
),
),
),
),
Expanded(
child: Align(
alignment: Alignment.center,
child: Container(
width: 110,
padding: const EdgeInsets.all(5),
decoration: BoxDecoration(
color: ColorsManager.whiteColors,
borderRadius: BorderRadius.circular(12),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: NumberInputField(controller: _controller),
),
Expanded(
child: Text(
'seconds',
style: TextStyle(
fontSize: 12,
color: ColorsManager.dialogBlueTitle,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
),
),
if (_errorText != null)
Expanded(
child: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
_errorText!,
style: const TextStyle(
color: ColorsManager.red,
fontSize: 14,
),
),
),
),
const Expanded(
child: Align(
alignment: Alignment.center,
child: Text(
'2.click Next to Complete the calibration',
style: TextStyle(color: ColorsManager.lightGrayColor),
),
),
)
],
),
leftOnTap: () => Navigator.of(widget.parentContext).pop(),

View File

@ -23,8 +23,8 @@ class QuickCalibrationDialog extends StatelessWidget {
body: const NormalTextBodyForDialog(
title: 'Prepare Calibration:',
step1:
'1. Confirm that the curtain is in the fully closed and suspended state.',
step2: '2. click Next to Start calibration.',
'Confirm that the curtain is in the fully closed and suspended state.',
step2: 'click Next to Start calibration.',
),
leftOnTap: () => Navigator.of(parentContext).pop(),
rightOnTap: () {

View File

@ -19,11 +19,14 @@ class DeviceManagementContent extends StatelessWidget {
required this.device,
required this.subSpaces,
required this.deviceInfo,
required this.deviceManagementBloc,
});
final AllDevicesModel device;
final List<SubSpaceModel> subSpaces;
final DeviceInfoModel deviceInfo;
final DeviceManagementBloc deviceManagementBloc;
@override
Widget build(BuildContext context) {
@ -87,6 +90,11 @@ class DeviceManagementContent extends StatelessWidget {
),
);
});
deviceManagementBloc.add(UpdateSubSpaceName(
subspaceId: selectedSubSpace.id!,
deviceId: device.uuid!,
newSubSpaceName: selectedSubSpace.name ?? ''));
}
},
child: infoRow(

View File

@ -1,13 +1,15 @@
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_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/device_setting/bloc/setting_bloc_bloc.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_state.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/device_icon_type_helper.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/device_management_content.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/remove_device_widget.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/device_info_model.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_bloc.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_state.dart';
import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/sub_space_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
@ -17,7 +19,13 @@ import 'package:syncrow_web/web_layout/default_container.dart';
class DeviceSettingsPanel extends StatelessWidget {
final VoidCallback? onClose;
final AllDevicesModel device;
const DeviceSettingsPanel({super.key, this.onClose, required this.device});
final DeviceManagementBloc deviceManagementBloc;
const DeviceSettingsPanel({
super.key,
this.onClose,
required this.device,
required this.deviceManagementBloc,
});
@override
Widget build(BuildContext context) {
@ -71,10 +79,10 @@ class DeviceSettingsPanel extends StatelessWidget {
'Device Settings',
style: context.theme.textTheme.titleLarge!
.copyWith(
fontWeight: FontWeight.w700,
fontWeight: FontWeight.w700,
color: ColorsManager.vividBlue
.withOpacity(0.7),
fontSize: 24),
fontSize: 24),
),
],
),
@ -134,8 +142,14 @@ class DeviceSettingsPanel extends StatelessWidget {
onFieldSubmitted: (value) {
_bloc.add(const ChangeNameEvent(
value: false));
deviceManagementBloc
..add(UpdateDeviceName(
deviceId: device.uuid!,
newName: _bloc
.nameController
.text))..add(ResetSelectedDevices());
},
decoration: InputDecoration(
decoration:const InputDecoration(
isDense: true,
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
@ -157,7 +171,7 @@ class DeviceSettingsPanel extends StatelessWidget {
onTap: () {
_bloc.add(
const ChangeNameEvent(
value: true));
value: true));
},
child: SvgPicture.asset(
Assets
@ -190,6 +204,7 @@ class DeviceSettingsPanel extends StatelessWidget {
device: device,
subSpaces: subSpaces.cast<SubSpaceModel>(),
deviceInfo: deviceInfo,
deviceManagementBloc: deviceManagementBloc,
),
const SizedBox(height: 32),
RemoveDeviceWidget(bloc: _bloc),

View File

@ -195,10 +195,10 @@ class _ScheduleTableView extends StatelessWidget {
child: Text(_getSelectedDays(
ScheduleModel.parseSelectedDays(schedule.days)))),
Center(child: Text(formatIsoStringToTime(schedule.time, context))),
schedule.category == 'CUR_2'
? Center(
child: Text(schedule.function.value == true ? 'open' : 'close'))
: Center(child: Text(schedule.function.value ? 'On' : 'Off')),
if (schedule.category == 'CUR_2')
Center(child: Text(schedule.function.value))
else
Center(child: Text(schedule.function.value ? 'On' : 'Off')),
Center(
child: Wrap(
runAlignment: WrapAlignment.center,

View File

@ -19,13 +19,19 @@ class ScheduleDialogHelper {
bool isEdit = false,
String? code,
}) {
bool temp;
if (schedule?.category == 'CUR_2') {
temp = schedule!.function.value == 'open' ? true : false;
} else {
temp = schedule!.function.value;
}
final initialTime = schedule != null
? _convertStringToTimeOfDay(schedule.time)
: TimeOfDay.now();
final initialDays = schedule != null
? _convertDaysStringToBooleans(schedule.days)
: List.filled(7, false);
bool? functionOn = schedule?.function.value ?? true;
bool? functionOn = temp;
TimeOfDay selectedTime = initialTime;
List<bool> selectedDays = List.of(initialDays);

View File

@ -170,45 +170,45 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
}
}
Future<void> _onLoadScenes(
LoadScenes event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null));
List<ScenesModel> scenes = [];
try {
BuildContext context = NavigationService.navigatorKey.currentContext!;
var createRoutineBloc = context.read<CreateRoutineBloc>();
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
if (createRoutineBloc.selectedSpaceId == '' &&
createRoutineBloc.selectedCommunityId == '') {
var spaceBloc = context.read<SpaceTreeBloc>();
for (var communityId in spaceBloc.state.selectedCommunities) {
List<String> spacesList =
spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
for (var spaceId in spacesList) {
scenes.addAll(
await SceneApi.getScenes(spaceId, communityId, projectUuid));
}
Future<void> _onLoadScenes(
LoadScenes event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null));
List<ScenesModel> scenes = [];
try {
BuildContext context = NavigationService.navigatorKey.currentContext!;
var createRoutineBloc = context.read<CreateRoutineBloc>();
final projectUuid = await ProjectManager.getProjectUUID() ?? '';
if (createRoutineBloc.selectedSpaceId == '' &&
createRoutineBloc.selectedCommunityId == '') {
var spaceBloc = context.read<SpaceTreeBloc>();
for (var communityId in spaceBloc.state.selectedCommunities) {
List<String> spacesList =
spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
for (var spaceId in spacesList) {
scenes.addAll(
await SceneApi.getScenes(spaceId, communityId, projectUuid));
}
} else {
scenes.addAll(await SceneApi.getScenes(
createRoutineBloc.selectedSpaceId,
createRoutineBloc.selectedCommunityId,
projectUuid));
}
emit(state.copyWith(
scenes: scenes,
isLoading: false,
));
} catch (e) {
emit(state.copyWith(
isLoading: false,
loadScenesErrorMessage: 'Failed to load scenes',
errorMessage: '',
loadAutomationErrorMessage: '',
scenes: scenes));
} else {
scenes.addAll(await SceneApi.getScenes(
createRoutineBloc.selectedSpaceId,
createRoutineBloc.selectedCommunityId,
projectUuid));
}
emit(state.copyWith(
scenes: scenes,
isLoading: false,
));
} catch (e) {
emit(state.copyWith(
isLoading: false,
loadScenesErrorMessage: 'Failed to load scenes',
errorMessage: '',
loadAutomationErrorMessage: '',
scenes: scenes));
}
}
Future<void> _onLoadAutomation(
LoadAutomation event, Emitter<RoutineState> emit) async {
@ -936,12 +936,16 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
for (var communityId in spaceBloc.state.selectedCommunities) {
List<String> spacesList =
spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
devices.addAll(await DevicesManagementApi()
.fetchDevices(projectUuid, spacesId: spacesList));
for (var spaceId in spacesList) {
devices.addAll(await DevicesManagementApi()
.fetchDevices(communityId, spaceId, projectUuid));
}
}
} else {
devices.addAll(await DevicesManagementApi().fetchDevices(projectUuid,
spacesId: [createRoutineBloc.selectedSpaceId]));
devices.addAll(await DevicesManagementApi().fetchDevices(
createRoutineBloc.selectedCommunityId,
createRoutineBloc.selectedSpaceId,
projectUuid));
}
emit(state.copyWith(isLoading: false, devices: devices));

View File

@ -58,7 +58,9 @@ class CurtainHelper {
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const DialogHeader('AC Functions'),
DialogHeader(dialogType == 'THEN'
? 'Curtain Functions'
: 'Curtain Conditions'),
Expanded(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,

View File

@ -2,10 +2,8 @@ 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/common/bloc/project_manager.dart';
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
import 'package:syncrow_web/pages/common/date_time_widget.dart';
import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart';
import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart';
@ -23,8 +21,8 @@ class VisitorPasswordDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;
var text = Theme.of(context)
final size = MediaQuery.of(context).size;
final text = Theme.of(context)
.textTheme
.bodySmall!
.copyWith(color: Colors.black, fontSize: 13);
@ -41,8 +39,7 @@ class VisitorPasswordDialog extends StatelessWidget {
title: 'Sent Successfully',
widgeta: Column(
children: [
if (visitorBloc
.passwordStatus!.failedOperations.isNotEmpty)
if (visitorBloc.passwordStatus!.failedOperations.isNotEmpty)
Column(
children: [
const Text('Failed Devices'),
@ -56,22 +53,19 @@ class VisitorPasswordDialog extends StatelessWidget {
.passwordStatus!.failedOperations.length,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.all(5),
margin: const EdgeInsets.all(5),
decoration: containerDecoration,
height: 45,
child: Center(
child: Text(visitorBloc
.passwordStatus!
.failedOperations[index]
.deviceName)),
child: Text(visitorBloc.passwordStatus!
.failedOperations[index].deviceName)),
);
},
),
),
],
),
if (visitorBloc
.passwordStatus!.successOperations.isNotEmpty)
if (visitorBloc.passwordStatus!.successOperations.isNotEmpty)
Column(
children: [
const Text('Success Devices'),
@ -85,14 +79,12 @@ class VisitorPasswordDialog extends StatelessWidget {
.passwordStatus!.successOperations.length,
itemBuilder: (context, index) {
return Container(
margin: EdgeInsets.all(5),
margin: const EdgeInsets.all(5),
decoration: containerDecoration,
height: 45,
child: Center(
child: Text(visitorBloc
.passwordStatus!
.successOperations[index]
.deviceName)),
child: Text(visitorBloc.passwordStatus!
.successOperations[index].deviceName)),
);
},
),
@ -115,16 +107,14 @@ class VisitorPasswordDialog extends StatelessWidget {
child: BlocBuilder<VisitorPasswordBloc, VisitorPasswordState>(
builder: (BuildContext context, VisitorPasswordState state) {
final visitorBloc = BlocProvider.of<VisitorPasswordBloc>(context);
bool isRepeat =
final isRepeat =
state is IsRepeatState ? state.repeat : visitorBloc.repeat;
return AlertDialog(
backgroundColor: Colors.white,
title: Text(
'Create visitor password',
style: Theme.of(context).textTheme.headlineLarge!.copyWith(
fontWeight: FontWeight.w400,
fontSize: 24,
color: Colors.black),
fontWeight: FontWeight.w400, fontSize: 24, color: Colors.black),
),
content: state is LoadingInitialState
? const Center(child: CircularProgressIndicator())
@ -310,14 +300,12 @@ class VisitorPasswordDialog extends StatelessWidget {
visitorBloc.accessTypeSelected ==
'Offline Password') {
visitorBloc.add(SelectTimeEvent(
context: context,
isEffective: false));
context: context, isEffective: false));
} else {
visitorBloc.add(
SelectTimeVisitorPassword(
context: context,
isStart: false,
isRepeat: false));
visitorBloc.add(SelectTimeVisitorPassword(
context: context,
isStart: false,
isRepeat: false));
}
},
startTime: () {
@ -326,31 +314,28 @@ class VisitorPasswordDialog extends StatelessWidget {
visitorBloc.accessTypeSelected ==
'Offline Password') {
visitorBloc.add(SelectTimeEvent(
context: context,
isEffective: true));
context: context, isEffective: true));
} else {
visitorBloc.add(
SelectTimeVisitorPassword(
context: context,
isStart: true,
isRepeat: false));
visitorBloc.add(SelectTimeVisitorPassword(
context: context,
isStart: true,
isRepeat: false));
}
},
firstString: (visitorBloc
.usageFrequencySelected ==
'Periodic' &&
visitorBloc.accessTypeSelected ==
'Offline Password')
? visitorBloc.effectiveTime
: visitorBloc.startTimeAccess
.toString(),
firstString:
(visitorBloc.usageFrequencySelected ==
'Periodic' &&
visitorBloc.accessTypeSelected ==
'Offline Password')
? visitorBloc.effectiveTime
: visitorBloc.startTimeAccess,
secondString: (visitorBloc
.usageFrequencySelected ==
'Periodic' &&
visitorBloc.accessTypeSelected ==
'Offline Password')
? visitorBloc.expirationTime
: visitorBloc.endTimeAccess.toString(),
: visitorBloc.endTimeAccess,
icon: Assets.calendarIcon),
const SizedBox(
height: 10,
@ -410,8 +395,7 @@ class VisitorPasswordDialog extends StatelessWidget {
child: CupertinoSwitch(
value: visitorBloc.repeat,
onChanged: (value) {
visitorBloc
.add(ToggleRepeatEvent());
visitorBloc.add(ToggleRepeatEvent());
},
applyTheme: true,
),
@ -442,8 +426,7 @@ class VisitorPasswordDialog extends StatelessWidget {
},
).then((listDevice) {
if (listDevice != null) {
visitorBloc.selectedDevices =
listDevice;
visitorBloc.selectedDevices = listDevice;
}
});
},
@ -455,8 +438,7 @@ class VisitorPasswordDialog extends StatelessWidget {
.bodySmall!
.copyWith(
fontWeight: FontWeight.w400,
color:
ColorsManager.whiteColors,
color: ColorsManager.whiteColors,
fontSize: 12),
),
),
@ -495,37 +477,30 @@ class VisitorPasswordDialog extends StatelessWidget {
onPressed: () {
if (visitorBloc.forgetFormKey.currentState!.validate()) {
if (visitorBloc.selectedDevices.isNotEmpty) {
if (visitorBloc.usageFrequencySelected ==
'One-Time' &&
visitorBloc.accessTypeSelected ==
'Offline Password') {
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
visitorBloc.accessTypeSelected == 'Offline Password') {
setPasswordFunction(context, size, visitorBloc);
} else if (visitorBloc.usageFrequencySelected ==
'Periodic' &&
visitorBloc.accessTypeSelected ==
'Offline Password') {
visitorBloc.accessTypeSelected == 'Offline Password') {
if (visitorBloc.expirationTime != 'End Time' &&
visitorBloc.effectiveTime != 'Start Time') {
setPasswordFunction(context, size, visitorBloc);
} else {
visitorBloc.stateDialog(
context: context,
message:
'Please select Access Period to continue',
message: 'Please select Access Period to continue',
title: 'Access Period');
}
} else if (visitorBloc.endTimeAccess.toString() !=
'End Time' &&
visitorBloc.startTimeAccess.toString() !=
'Start Time') {
} else if (visitorBloc.endTimeAccess != 'End Time' &&
visitorBloc.startTimeAccess != 'Start Time') {
if (visitorBloc.effectiveTimeTimeStamp != null &&
visitorBloc.expirationTimeTimeStamp != null) {
if (isRepeat == true) {
if (visitorBloc.expirationTime != 'End Time' &&
visitorBloc.effectiveTime != 'Start Time' &&
visitorBloc.selectedDays.isNotEmpty) {
setPasswordFunction(
context, size, visitorBloc);
setPasswordFunction(context, size, visitorBloc);
} else {
visitorBloc.stateDialog(
context: context,
@ -539,15 +514,13 @@ class VisitorPasswordDialog extends StatelessWidget {
} else {
visitorBloc.stateDialog(
context: context,
message:
'Please select Access Period to continue',
message: 'Please select Access Period to continue',
title: 'Access Period');
}
} else {
visitorBloc.stateDialog(
context: context,
message:
'Please select Access Period to continue',
message: 'Please select Access Period to continue',
title: 'Access Period');
}
} else {
@ -593,9 +566,8 @@ class VisitorPasswordDialog extends StatelessWidget {
alignment: Alignment.center,
content: SizedBox(
height: size.height * 0.25,
child: Center(
child:
CircularProgressIndicator(), // Display a loading spinner
child: const Center(
child: CircularProgressIndicator(), // Display a loading spinner
),
),
);
@ -668,8 +640,7 @@ class VisitorPasswordDialog extends StatelessWidget {
onPressed: () {
Navigator.pop(context);
if (visitorBloc.usageFrequencySelected == 'One-Time' &&
visitorBloc.accessTypeSelected ==
'Online Password') {
visitorBloc.accessTypeSelected == 'Online Password') {
visitorBloc.add(OnlineOneTimePasswordEvent(
context: context,
passwordName: visitorBloc.userNameController.text,
@ -677,8 +648,7 @@ class VisitorPasswordDialog extends StatelessWidget {
));
} else if (visitorBloc.usageFrequencySelected ==
'Periodic' &&
visitorBloc.accessTypeSelected ==
'Online Password') {
visitorBloc.accessTypeSelected == 'Online Password') {
visitorBloc.add(OnlineMultipleTimePasswordEvent(
passwordName: visitorBloc.userNameController.text,
email: visitorBloc.emailController.text,
@ -689,8 +659,7 @@ class VisitorPasswordDialog extends StatelessWidget {
));
} else if (visitorBloc.usageFrequencySelected ==
'One-Time' &&
visitorBloc.accessTypeSelected ==
'Offline Password') {
visitorBloc.accessTypeSelected == 'Offline Password') {
visitorBloc.add(OfflineOneTimePasswordEvent(
context: context,
passwordName: visitorBloc.userNameController.text,
@ -698,8 +667,7 @@ class VisitorPasswordDialog extends StatelessWidget {
));
} else if (visitorBloc.usageFrequencySelected ==
'Periodic' &&
visitorBloc.accessTypeSelected ==
'Offline Password') {
visitorBloc.accessTypeSelected == 'Offline Password') {
visitorBloc.add(OfflineMultipleTimePasswordEvent(
passwordName: visitorBloc.userNameController.text,
email: visitorBloc.emailController.text,

View File

@ -13,13 +13,15 @@ import 'package:syncrow_web/utils/constants/api_const.dart';
class DevicesManagementApi {
Future<List<AllDevicesModel>> fetchDevices(
String projectId, {
List<String>? spacesId,
}) async {
String communityId, String spaceId, String projectId) async {
try {
final response = await HTTPService().get(
queryParameters: {if (spacesId != null) 'spaces': spacesId},
path: ApiEndpoints.getAllDevices.replaceAll('{projectId}', projectId),
path: communityId.isNotEmpty && spaceId.isNotEmpty
? ApiEndpoints.getSpaceDevices
.replaceAll('{spaceUuid}', spaceId)
.replaceAll('{communityUuid}', communityId)
.replaceAll('{projectId}', projectId)
: ApiEndpoints.getAllDevices.replaceAll('{projectId}', projectId),
showServerMessage: true,
expectedResponseModel: (json) {
List<dynamic> jsonData = json['data'];
@ -414,4 +416,5 @@ class DevicesManagementApi {
);
return response;
}
}

View File

@ -83,7 +83,5 @@ abstract class ColorsManager {
static const Color maxPurpleDot = Color(0xFF5F00BD);
static const Color minBlue = Color(0xFF93AAFD);
static const Color minBlueDot = Color(0xFF023DFE);
static const Color grey25 = Color(0xFFF9F9F9);
static const Color grey25 = Color(0xFFF9F9F9);
}

View File

@ -18,7 +18,7 @@ abstract class ApiEndpoints {
static const String getAllDevices = '/projects/{projectId}/devices';
static const String getSpaceDevices =
'/projects/{projectId}/devices';
'/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/devices';
static const String getDeviceStatus = '/devices/{uuid}/functions/status';
static const String getBatchStatus = '/devices/batch';

View File

@ -394,6 +394,7 @@ class Assets {
static const String emptyBox = 'assets/icons/empty_box.png';
static const String completeProcessIcon =
'assets/icons/compleate_process_icon.svg';
static const String completedDoneIcon = 'assets/images/completed_done.svg';
static const String currentProcessIcon =
'assets/icons/current_process_icon.svg';
static const String uncomplete_ProcessIcon =
@ -505,5 +506,6 @@ class Assets {
static const String aqiAirQuality = 'assets/icons/aqi_air_quality.svg';
static const String temperatureAqiSidebar = 'assets/icons/thermometer.svg';
static const String humidityAqiSidebar = 'assets/icons/humidity.svg';
static const String autocadOccupancyImage = 'assets/images/autocad_occupancy_image.png';
static const String autocadOccupancyImage =
'assets/images/autocad_occupancy_image.png';
}