finished AC

This commit is contained in:
ashrafzarkanisala
2024-08-26 19:32:11 +03:00
parent afee0eb5b1
commit 2777dc1a5f
14 changed files with 445 additions and 446 deletions

View File

@ -1,31 +1,21 @@
import 'dart:async'; import 'dart:async';
import 'package:bloc/bloc.dart'; import 'package:dio/dio.dart';
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/ac/bloc/ac_event.dart'; import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_state.dart'; import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_state.dart';
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart'; import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
import 'package:syncrow_web/services/devices_mang_api.dart'; import 'package:syncrow_web/services/devices_mang_api.dart';
class AcBloc extends Bloc<AcsEvent, AcsState> { class AcBloc extends Bloc<AcsEvent, AcsState> {
AcStatusModel deviceStatus = AcStatusModel( late AcStatusModel deviceStatus;
uuid: '', final String deviceId;
acSwitch: true, Timer? _timer;
modeString: 'hot',
tempSet: 300,
currentTemp: 315,
fanSpeedsString: 'low',
childLock: false,
);
AcBloc() : super(AcsInitialState()) { AcBloc({required this.deviceId}) : super(AcsInitialState()) {
on<AcFetchDeviceStatus>(_onFetchAcStatus); on<AcFetchDeviceStatus>(_onFetchAcStatus);
on<AcControl>(_onAcControl); on<AcControl>(_onAcControl);
on<AcSwitch>(_changeAcSwitch);
on<IncreaseCoolToTemp>(_increaseCoolTo);
on<DecreaseCoolToTemp>(_decreaseCoolTo);
on<ChangeLock>(_changeLockValue);
on<ChangeAcMode>(_changeAcMode);
on<ChangeFanSpeed>(_changeFanSpeed);
} }
FutureOr<void> _onFetchAcStatus( FutureOr<void> _onFetchAcStatus(
@ -34,7 +24,7 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
try { try {
final status = final status =
await DevicesManagementApi().getDeviceStatus(event.deviceId); await DevicesManagementApi().getDeviceStatus(event.deviceId);
deviceStatus = AcStatusModel.fromJson(status.productUuid, status.status); deviceStatus = AcStatusModel.fromJson(event.deviceId, status.status);
emit(ACStatusLoaded(deviceStatus)); emit(ACStatusLoaded(deviceStatus));
} catch (e) { } catch (e) {
emit(AcsFailedState(error: e.toString())); emit(AcsFailedState(error: e.toString()));
@ -45,47 +35,86 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
final oldValue = _getValueByCode(event.code); final oldValue = _getValueByCode(event.code);
_updateLocalValue(event.code, event.value); _updateLocalValue(event.code, event.value);
emit(ACStatusLoaded(deviceStatus)); emit(ACStatusLoaded(deviceStatus));
try { await _runDebounce(
final status = Status(code: event.code, value: event.value); deviceId: event.deviceId,
final response = code: event.code,
await DevicesManagementApi().deviceControl(event.deviceId, status); value: event.value,
oldValue: oldValue,
emit: emit,
);
}
if (!response) { Future<void> _runDebounce({
_updateLocalValue(event.code, oldValue); required String deviceId,
emit(ACStatusLoaded(deviceStatus)); required String code,
emit(AcsFailedState(error: 'Failed to control the device.')); required dynamic value,
} required dynamic oldValue,
} catch (e) { required Emitter<AcsState> emit,
_updateLocalValue(event.code, oldValue); }) async {
emit(ACStatusLoaded(deviceStatus)); if (_timer != null) {
emit(AcsFailedState(error: 'Error controlling the device: $e')); _timer!.cancel();
} }
_timer = Timer(const Duration(seconds: 1), () async {
try {
final response = await DevicesManagementApi()
.deviceControl(deviceId, Status(code: code, value: value));
if (!response) {
_revertValueAndEmit(deviceId, code, oldValue, emit);
}
} catch (e) {
if (e is DioException && e.response != null) {
debugPrint('Error response: ${e.response?.data}');
}
_revertValueAndEmit(deviceId, code, oldValue, emit);
}
});
}
void _revertValueAndEmit(
String deviceId, String code, dynamic oldValue, Emitter<AcsState> emit) {
_updateLocalValue(code, oldValue);
emit(ACStatusLoaded(deviceStatus));
emit(const AcsFailedState(error: 'Failed to control the device.'));
} }
void _updateLocalValue(String code, dynamic value) { void _updateLocalValue(String code, dynamic value) {
switch (code) { switch (code) {
case 'switch': case 'switch':
deviceStatus.acSwitch = value; if (value is bool) {
deviceStatus = deviceStatus.copyWith(acSwitch: value);
}
break; break;
case 'temp_set': case 'temp_set':
deviceStatus.tempSet = value; if (value is int) {
deviceStatus = deviceStatus.copyWith(tempSet: value);
}
break; break;
case 'mode': case 'mode':
deviceStatus.modeString = value; if (value is String) {
deviceStatus.acMode = AcStatusModel.getACMode(value); deviceStatus = deviceStatus.copyWith(
modeString: value,
);
}
break; break;
case 'level': case 'level':
deviceStatus.fanSpeedsString = value; if (value is String) {
deviceStatus.acFanSpeed = AcStatusModel.getFanSpeed(value); deviceStatus = deviceStatus.copyWith(
fanSpeedsString: value,
);
}
break; break;
case 'child_lock': case 'child_lock':
deviceStatus.childLock = value; if (value is bool) {
deviceStatus = deviceStatus.copyWith(childLock: value);
}
break; break;
default: default:
break; break;
} }
emit(ACStatusLoaded(deviceStatus));
} }
dynamic _getValueByCode(String code) { dynamic _getValueByCode(String code) {
@ -104,50 +133,4 @@ class AcBloc extends Bloc<AcsEvent, AcsState> {
return null; return null;
} }
} }
FutureOr<void> _changeAcSwitch(AcSwitch event, Emitter<AcsState> emit) async {
final newValue = !event.acSwitch;
add(AcControl(deviceId: event.deviceId, code: 'switch', value: newValue));
}
FutureOr<void> _increaseCoolTo(
IncreaseCoolToTemp event, Emitter<AcsState> emit) async {
final newValue = (event.value * 10).toInt() + 5;
if (_isValidTemperature(newValue)) {
add(AcControl(
deviceId: event.deviceId, code: 'temp_set', value: newValue));
}
}
FutureOr<void> _decreaseCoolTo(
DecreaseCoolToTemp event, Emitter<AcsState> emit) async {
final newValue = (event.value * 10).toInt() - 5;
if (_isValidTemperature(newValue)) {
add(AcControl(
deviceId: event.deviceId, code: 'temp_set', value: newValue));
}
}
FutureOr<void> _changeLockValue(
ChangeLock event, Emitter<AcsState> emit) async {
final newValue = !event.lockBool;
add(AcControl(
deviceId: event.deviceId, code: 'child_lock', value: newValue));
}
FutureOr<void> _changeAcMode(
ChangeAcMode event, Emitter<AcsState> emit) async {
final newValue = AcStatusModel.getACMode(event.tempModes.name);
add(AcControl(deviceId: event.deviceId, code: 'mode', value: newValue));
}
FutureOr<void> _changeFanSpeed(
ChangeFanSpeed event, Emitter<AcsState> emit) async {
final newValue = AcStatusModel.getFanSpeed(event.fanSpeeds.name);
add(AcControl(deviceId: event.deviceId, code: 'level', value: newValue));
}
bool _isValidTemperature(int value) {
return value >= 200 && value <= 300;
}
} }

View File

@ -1,5 +1,4 @@
import 'package:equatable/equatable.dart'; import 'package:equatable/equatable.dart';
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
sealed class AcsEvent extends Equatable { sealed class AcsEvent extends Equatable {
const AcsEvent(); const AcsEvent();
@ -31,63 +30,3 @@ class AcControl extends AcsEvent {
@override @override
List<Object> get props => [deviceId, code, value]; List<Object> get props => [deviceId, code, value];
} }
class AcSwitch extends AcsEvent {
final bool acSwitch;
final String deviceId;
const AcSwitch({required this.acSwitch, required this.deviceId});
@override
List<Object> get props => [acSwitch, deviceId];
}
class IncreaseCoolToTemp extends AcsEvent {
final double value;
final String deviceId;
const IncreaseCoolToTemp({required this.value, required this.deviceId});
@override
List<Object> get props => [value, deviceId];
}
class DecreaseCoolToTemp extends AcsEvent {
final double value;
final String deviceId;
const DecreaseCoolToTemp({required this.value, required this.deviceId});
@override
List<Object> get props => [value, deviceId];
}
class ChangeLock extends AcsEvent {
final bool lockBool;
final String deviceId;
const ChangeLock({required this.lockBool, required this.deviceId});
@override
List<Object> get props => [lockBool, deviceId];
}
class ChangeAcMode extends AcsEvent {
final TempModes tempModes;
final String deviceId;
const ChangeAcMode({required this.tempModes, required this.deviceId});
@override
List<Object> get props => [tempModes, deviceId];
}
class ChangeFanSpeed extends AcsEvent {
final FanSpeeds fanSpeeds;
final String deviceId;
const ChangeFanSpeed({required this.fanSpeeds, required this.deviceId});
@override
List<Object> get props => [fanSpeeds, deviceId];
}

View File

@ -14,56 +14,12 @@ class AcsLoadingState extends AcsState {}
class ACStatusLoaded extends AcsState { class ACStatusLoaded extends AcsState {
final AcStatusModel status; final AcStatusModel status;
final DateTime timestamp;
const ACStatusLoaded(this.status); ACStatusLoaded(this.status) : timestamp = DateTime.now();
@override @override
List<Object> get props => [status]; List<Object> get props => [status, timestamp];
}
class AcSwitchChanged extends AcsState {
final bool acSwitch;
const AcSwitchChanged(this.acSwitch);
@override
List<Object> get props => [acSwitch];
}
class AcTempChanged extends AcsState {
final double tempSet;
const AcTempChanged(this.tempSet);
@override
List<Object> get props => [tempSet];
}
class AcModeChanged extends AcsState {
final TempModes mode;
const AcModeChanged(this.mode);
@override
List<Object> get props => [mode];
}
class AcFanSpeedChanged extends AcsState {
final FanSpeeds fanSpeed;
const AcFanSpeedChanged(this.fanSpeed);
@override
List<Object> get props => [fanSpeed];
}
class AcLockChanged extends AcsState {
final bool lock;
const AcLockChanged(this.lock);
@override
List<Object> get props => [lock];
} }
class AcsFailedState extends AcsState { class AcsFailedState extends AcsState {

View File

@ -5,83 +5,114 @@ enum TempModes { hot, cold, wind }
enum FanSpeeds { auto, low, middle, high } enum FanSpeeds { auto, low, middle, high }
class AcStatusModel { class AcStatusModel {
String uuid; final String uuid;
bool acSwitch; final bool acSwitch;
String modeString; final String modeString;
int tempSet; final int tempSet;
int currentTemp; final int currentTemp;
String fanSpeedsString; final String fanSpeedsString;
bool childLock; final bool childLock;
late TempModes acMode; final TempModes acMode;
late FanSpeeds acFanSpeed; final FanSpeeds acFanSpeed;
AcStatusModel( AcStatusModel({
{required this.uuid, required this.uuid,
required this.acSwitch, required this.acSwitch,
required this.modeString, required this.modeString,
required this.tempSet, required this.tempSet,
required this.currentTemp, required this.currentTemp,
required this.fanSpeedsString, required this.fanSpeedsString,
required this.childLock}) { required this.childLock,
acMode = getACMode(modeString); }) : acMode = getACMode(modeString),
acFanSpeed = getFanSpeed(fanSpeedsString); acFanSpeed = getFanSpeed(fanSpeedsString);
}
factory AcStatusModel.fromJson(String id, List<Status> jsonList) { factory AcStatusModel.fromJson(String id, List<Status> jsonList) {
late bool _acSwitch; late bool acSwitch;
late String _mode; late String mode;
late int _tempSet; late int tempSet;
late int _currentTemp; late int currentTemp;
late String _fanSpeeds; late String fanSpeeds;
late bool _childLock; late bool childLock;
for (int i = 0; i < jsonList.length; i++) {
if (jsonList[i].code == 'switch') { for (var status in jsonList) {
_acSwitch = jsonList[i].value ?? false; switch (status.code) {
} else if (jsonList[i].code == 'mode') { case 'switch':
_mode = jsonList[i].value ?? TempModes.cold; acSwitch = status.value ?? false;
} else if (jsonList[i].code == 'temp_set') { break;
_tempSet = jsonList[i].value ?? 210; case 'mode':
} else if (jsonList[i].code == 'temp_current') { mode = status.value ?? 'cold'; // default to 'cold' if null
_currentTemp = jsonList[i].value ?? 210; break;
} else if (jsonList[i].code == 'level') { case 'temp_set':
_fanSpeeds = jsonList[i].value ?? 210; tempSet = status.value ?? 210; // default value if null
} else if (jsonList[i].code == 'child_lock') { break;
_childLock = jsonList[i].value ?? false; case 'temp_current':
currentTemp = status.value ?? 210; // default value if null
break;
case 'level':
fanSpeeds = status.value ?? 'low'; // default value if null
break;
case 'child_lock':
childLock = status.value ?? false;
break;
} }
} }
return AcStatusModel( return AcStatusModel(
uuid: id, uuid: id,
acSwitch: _acSwitch, acSwitch: acSwitch,
modeString: _mode, modeString: mode,
tempSet: _tempSet, tempSet: tempSet,
currentTemp: _currentTemp, currentTemp: currentTemp,
fanSpeedsString: _fanSpeeds, fanSpeedsString: fanSpeeds,
childLock: _childLock); childLock: childLock,
);
}
AcStatusModel copyWith({
String? uuid,
bool? acSwitch,
String? modeString,
int? tempSet,
int? currentTemp,
String? fanSpeedsString,
bool? childLock,
}) {
return AcStatusModel(
uuid: uuid ?? this.uuid,
acSwitch: acSwitch ?? this.acSwitch,
modeString: modeString ?? this.modeString,
tempSet: tempSet ?? this.tempSet,
currentTemp: currentTemp ?? this.currentTemp,
fanSpeedsString: fanSpeedsString ?? this.fanSpeedsString,
childLock: childLock ?? this.childLock,
);
} }
static TempModes getACMode(String value) { static TempModes getACMode(String value) {
if (value == 'cold') { switch (value) {
return TempModes.cold; case 'cold':
} else if (value == 'hot') { return TempModes.cold;
return TempModes.hot; case 'hot':
} else if (value == 'wind') { return TempModes.hot;
return TempModes.wind; case 'wind':
} else { return TempModes.wind;
return TempModes.cold; default:
return TempModes.cold;
} }
} }
static FanSpeeds getFanSpeed(String value) { static FanSpeeds getFanSpeed(String value) {
if (value == 'low') { switch (value) {
return FanSpeeds.low; case 'low':
} else if (value == 'middle') { return FanSpeeds.low;
return FanSpeeds.middle; case 'middle':
} else if (value == 'high') { return FanSpeeds.middle;
return FanSpeeds.high; case 'high':
} else if (value == 'auto') { return FanSpeeds.high;
return FanSpeeds.auto; case 'auto':
} else { return FanSpeeds.auto;
return FanSpeeds.auto; default:
return FanSpeeds.auto;
} }
} }
} }

View File

@ -6,8 +6,9 @@ import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_state.dart';
import 'package:syncrow_web/pages/device_managment/ac/view/control_list/ac_mode.dart'; import 'package:syncrow_web/pages/device_managment/ac/view/control_list/ac_mode.dart';
import 'package:syncrow_web/pages/device_managment/ac/view/control_list/ac_toggle.dart'; import 'package:syncrow_web/pages/device_managment/ac/view/control_list/ac_toggle.dart';
import 'package:syncrow_web/pages/device_managment/ac/view/control_list/current_temp.dart'; import 'package:syncrow_web/pages/device_managment/ac/view/control_list/current_temp.dart';
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart'; import 'package:syncrow_web/pages/device_managment/ac/view/control_list/fan_speed.dart';
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class AcDeviceControl extends StatelessWidget with HelperResponsiveLayout { class AcDeviceControl extends StatelessWidget with HelperResponsiveLayout {
@ -20,13 +21,58 @@ class AcDeviceControl extends StatelessWidget with HelperResponsiveLayout {
final isLarge = isLargeScreenSize(context); final isLarge = isLargeScreenSize(context);
final isMedium = isMediumScreenSize(context); final isMedium = isMediumScreenSize(context);
return BlocProvider( return BlocProvider(
create: (context) => AcBloc()..add(AcFetchDeviceStatus(device.uuid!)), create: (context) => AcBloc(deviceId: device.uuid!)
..add(AcFetchDeviceStatus(device.uuid!)),
child: BlocBuilder<AcBloc, AcsState>( child: BlocBuilder<AcBloc, AcsState>(
builder: (context, state) { builder: (context, state) {
if (state is AcsLoadingState) { if (state is ACStatusLoaded) {
return GridView(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 133,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
children: [
AcToggle(
value: state.status.acSwitch,
code: 'switch',
deviceId: device.uuid!,
),
CurrentTemp(
currentTemp: state.status.currentTemp,
tempSet: state.status.tempSet,
code: 'temp_set',
deviceId: device.uuid!,
),
AcMode(
value: state.status.acMode,
code: 'mode',
deviceId: device.uuid!,
),
FanSpeedControl(
value: state.status.acFanSpeed,
code: 'level',
deviceId: device.uuid!,
),
AcToggle(
value: state.status.childLock,
code: 'child_lock',
deviceId: device.uuid!,
description: 'Child Lock',
icon: Assets.childLock,
),
],
);
} else if (state is AcsLoadingState) {
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} else if (state is ACStatusLoaded) {
return _buildStatusControls(state.status, isLarge, isMedium);
} else { } else {
return const Center(child: Text('Error fetching status')); return const Center(child: Text('Error fetching status'));
} }
@ -34,40 +80,4 @@ class AcDeviceControl extends StatelessWidget with HelperResponsiveLayout {
), ),
); );
} }
Widget _buildStatusControls(AcStatusModel statuses, bool isLarge, bool isMedium) {
return GridView(
padding: const EdgeInsets.symmetric(horizontal: 50),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isLarge
? 3
: isMedium
? 2
: 1,
mainAxisExtent: 133,
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
children: [
AcToggle(
value: statuses.acSwitch,
code: 'switch',
deviceId: statuses.uuid,
),
AcMode(
value: statuses.acMode,
code: 'mode',
deviceId: statuses.uuid,
),
CurrentTemp(
currentTemp: statuses.currentTemp,
tempSet: statuses.tempSet,
code: 'temp_set',
deviceId: statuses.uuid,
),
],
);
}
} }

View File

@ -19,12 +19,6 @@ class AcMode extends StatelessWidget {
final String code; final String code;
final String deviceId; final String deviceId;
void _onModeSelected(BuildContext context, TempModes mode) {
context.read<AcBloc>().add(
ChangeAcMode(tempModes: mode, deviceId: deviceId),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
@ -54,7 +48,13 @@ class AcMode extends StatelessWidget {
return Flexible( return Flexible(
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
_onModeSelected(context, mode); context.read<AcBloc>().add(
AcControl(
deviceId: deviceId,
code: code,
value: mode.name,
),
);
}, },
child: Container( child: Container(
width: 50, width: 50,

View File

@ -53,7 +53,7 @@ class _CurrentTempState extends State<CurrentTemp> {
AcControl( AcControl(
deviceId: widget.deviceId, deviceId: widget.deviceId,
code: widget.code, code: widget.code,
value: newValue * 10, value: (newValue * 10).toInt(),
), ),
); );
}); });

View File

@ -0,0 +1,91 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart';
import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart';
class FanSpeedControl extends StatelessWidget {
const FanSpeedControl({
super.key,
required this.value,
required this.code,
required this.deviceId,
});
final FanSpeeds value;
final String code;
final String deviceId;
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(20),
color: ColorsManager.greyColor.withOpacity(0.2),
border: Border.all(color: ColorsManager.boxDivider),
),
padding: const EdgeInsets.all(8),
child: Column(
children: [
Wrap(
runSpacing: 8,
spacing: 8,
children: [
_buildIconContainer(context, FanSpeeds.auto, Assets.acFanAuto,
value == FanSpeeds.auto),
_buildIconContainer(context, FanSpeeds.low, Assets.acFanLow,
value == FanSpeeds.low),
],
),
Wrap(
runSpacing: 8,
spacing: 8,
children: [
_buildIconContainer(context, FanSpeeds.middle, Assets.acFanMiddle,
value == FanSpeeds.middle),
_buildIconContainer(context, FanSpeeds.high, Assets.acFanHigh,
value == FanSpeeds.high),
],
)
],
),
);
}
Widget _buildIconContainer(BuildContext context, FanSpeeds speed,
String assetPath, bool isSelected) {
return GestureDetector(
onTap: () {
context.read<AcBloc>().add(
AcControl(
deviceId: deviceId,
code: code,
value: speed.name,
),
);
},
child: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: ColorsManager.whiteColors,
border: Border.all(
color: isSelected ? Colors.blue : Colors.transparent,
width: 2.0,
),
),
padding: const EdgeInsets.all(8),
child: ClipOval(
child: SvgPicture.asset(
assetPath,
fit: BoxFit.contain,
),
),
),
);
}
}

View File

@ -24,20 +24,18 @@ class IncrementDecrementWidget extends StatelessWidget {
children: [ children: [
Material( Material(
type: MaterialType.transparency, type: MaterialType.transparency,
child: Flexible( child: ClipRRect(
child: ClipRRect( borderRadius: BorderRadius.circular(100),
borderRadius: BorderRadius.circular(100), child: InkWell(
child: InkWell( splashColor: Colors.transparent,
splashColor: Colors.transparent, highlightColor: Colors.transparent,
highlightColor: Colors.transparent, onTap: onDecrement,
onTap: onDecrement, child: const Padding(
child: const Padding( padding: EdgeInsets.all(8.0),
padding: EdgeInsets.all(8.0), child: Icon(
child: Icon( Icons.remove,
Icons.remove, color: ColorsManager.greyColor,
color: ColorsManager.greyColor, size: 28,
size: 28,
),
), ),
), ),
), ),
@ -73,20 +71,18 @@ class IncrementDecrementWidget extends StatelessWidget {
), ),
Material( Material(
type: MaterialType.transparency, type: MaterialType.transparency,
child: Flexible( child: ClipRRect(
child: ClipRRect( borderRadius: BorderRadius.circular(100),
borderRadius: BorderRadius.circular(100), child: InkWell(
child: InkWell( splashColor: Colors.transparent,
splashColor: Colors.transparent, highlightColor: Colors.transparent,
highlightColor: Colors.transparent, onTap: onIncrement,
onTap: onIncrement, child: const Padding(
child: const Padding( padding: EdgeInsets.all(8.0),
padding: EdgeInsets.all(8.0), child: Icon(
child: Icon( Icons.add,
Icons.add, color: ColorsManager.greyColor,
color: ColorsManager.greyColor, size: 28,
size: 28,
),
), ),
), ),
), ),

View File

@ -13,38 +13,36 @@ class PresenceDisplayValue extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DeviceControlsContainer( return DeviceControlsContainer(
child: Expanded( child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
children: [ Row(
Row( crossAxisAlignment: CrossAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end, children: [
children: [ Text(
Text( value,
value, style: Theme.of(context).textTheme.bodyLarge!.copyWith(
style: Theme.of(context).textTheme.bodyLarge!.copyWith( color: ColorsManager.dialogBlueTitle,
color: ColorsManager.dialogBlueTitle, fontSize: 40,
fontSize: 40, fontWeight: FontWeight.w700),
fontWeight: FontWeight.w700), ),
Padding(
padding: const EdgeInsets.only(bottom: 10),
child: Text(
postfix,
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.blackColor, fontSize: 16, fontWeight: FontWeight.w700),
), ),
Padding( ),
padding: const EdgeInsets.only(bottom: 10), ],
child: Text( ),
postfix, Text(
style: Theme.of(context).textTheme.bodySmall!.copyWith( description,
color: ColorsManager.blackColor, fontSize: 16, fontWeight: FontWeight.w700), style: Theme.of(context).textTheme.bodySmall!.copyWith(
), color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16),
), ),
], ],
),
Text(
description,
style: Theme.of(context).textTheme.bodySmall!.copyWith(
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16),
),
],
),
), ),
); );
} }

View File

@ -11,23 +11,21 @@ class PresenceStaticWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DeviceControlsContainer( return DeviceControlsContainer(
child: Expanded( child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
children: [ SvgPicture.asset(
SvgPicture.asset( icon,
icon, width: 60,
width: 60, height: 60,
height: 60, ),
), Text(
Text( description,
description, style: Theme.of(context).textTheme.bodySmall!.copyWith(
style: Theme.of(context).textTheme.bodySmall!.copyWith( color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16),
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16), ),
), ],
],
),
), ),
); );
} }

View File

@ -15,37 +15,35 @@ class PresenceState extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DeviceControlsContainer( return DeviceControlsContainer(
child: Expanded( child: Column(
child: Column( crossAxisAlignment: CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [
children: [ Row(
Row( mainAxisAlignment: MainAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start, children: [
children: [ Text(
Text( 'Status:',
'Status:', style: Theme.of(context).textTheme.bodySmall!.copyWith(
style: Theme.of(context).textTheme.bodySmall!.copyWith( color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 10),
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 10), ),
), ],
], ),
), SvgPicture.asset(
SvgPicture.asset( value.toLowerCase() == 'motion'
value.toLowerCase() == 'motion' ? Assets.sensorMotionIcon
? Assets.sensorMotionIcon : value.toLowerCase() == 'presence'
: value.toLowerCase() == 'presence' ? Assets.sensorPresenceIcon
? Assets.sensorPresenceIcon : Assets.sensorVacantIcon,
: Assets.sensorVacantIcon, width: 60,
width: 60, height: 60,
height: 60, ),
), Text(
Text( value,
value, style: Theme.of(context).textTheme.bodySmall!.copyWith(
style: Theme.of(context).textTheme.bodySmall!.copyWith( color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16),
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 16), ),
), ],
],
),
), ),
); );
} }

View File

@ -56,38 +56,36 @@ class _CurrentTempState extends State<PresenceUpdateData> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return DeviceControlsContainer( return DeviceControlsContainer(
child: Expanded( child: Column(
child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start, children: [
children: [ Text(
Text( widget.title,
widget.title, style: Theme.of(context).textTheme.bodySmall!.copyWith(
style: Theme.of(context).textTheme.bodySmall!.copyWith( color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 10),
color: ColorsManager.blackColor, fontWeight: FontWeight.w400, fontSize: 10), ),
), IncrementDecrementWidget(
IncrementDecrementWidget( value: widget.value.toString(),
value: widget.value.toString(), description: widget.description ?? '',
description: widget.description ?? '', descriptionColor: ColorsManager.blackColor,
descriptionColor: ColorsManager.blackColor, onIncrement: () {
onIncrement: () { if (_adjustedValue < widget.maxValue) {
if (_adjustedValue < widget.maxValue) { setState(() {
setState(() { _adjustedValue = _adjustedValue + widget.steps;
_adjustedValue = _adjustedValue + widget.steps; });
}); _onValueChanged(_adjustedValue);
_onValueChanged(_adjustedValue); }
} },
}, onDecrement: () {
onDecrement: () { if (_adjustedValue > widget.minValue) {
if (_adjustedValue > widget.minValue) { setState(() {
setState(() { _adjustedValue = _adjustedValue - widget.steps;
_adjustedValue = _adjustedValue - widget.steps; });
}); _onValueChanged(_adjustedValue);
_onValueChanged(_adjustedValue); }
} }),
}), ],
],
),
), ),
); );
} }

View File

@ -29,7 +29,8 @@ abstract class ApiEndpoints {
////// Devices Management //////////////// ////// Devices Management ////////////////
static const String getAllDevices = '$baseUrl/device'; static const String getAllDevices = '$baseUrl/device';
static const String getDeviceStatus = '$baseUrl/device/{uuid}/functions/status'; static const String getDeviceStatus =
'$baseUrl/device/{uuid}/functions/status';
static const String deviceControl = '$baseUrl/device/{uuid}/control'; static const String deviceControl = '$baseUrl/device/{uuid}/control';
} }