build UI and integrate with back

This commit is contained in:
Rafeek-Khoudare
2025-06-25 16:28:15 +03:00
parent eee6a80c50
commit 4e9bcbdcea
15 changed files with 1118 additions and 1 deletions

View File

@ -0,0 +1,71 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/batch/curtain_module_batch_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/curtain_movment_widget.dart';
import 'package:syncrow_web/pages/device_managment/shared/icon_name_status_container.dart';
import 'package:syncrow_web/services/control_device_service.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
class CurtainModuleBatchView extends StatelessWidget {
final List<String> devicesIds;
const CurtainModuleBatchView({
super.key,
required this.devicesIds,
});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CurtainModuleBatchBloc(RemoteControlDeviceService())
..add(CutrainModuleFetchBatchStatusEvent(devicesIds: devicesIds)),
child: _buildStatusControls(context),
);
}
Widget _buildStatusControls(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ControlCurtainMovementWidget(
deviceId: devicesIds.first,
),
const SizedBox(
height: 10,
),
SizedBox(
height: 120,
width: 350,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: IconNameStatusContainer(
isFullIcon: false,
name: 'Factory Reset',
icon: Assets.factoryReset,
onTap: () {},
status: false,
textColor: ColorsManager.blackColor,
),
),
Expanded(
child: IconNameStatusContainer(
isFullIcon: false,
name: 'Firmware Update',
icon: Assets.firmware,
onTap: () {},
status: false,
textColor: ColorsManager.blackColor,
),
),
],
),
),
],
),
);
}
}

View File

@ -0,0 +1,98 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/curtain_movment_widget.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/prefrences_dialog.dart';
import 'package:syncrow_web/pages/device_managment/shared/icon_name_status_container.dart';
import 'package:syncrow_web/services/control_device_service.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart';
class CurtainModuleItems extends StatelessWidget with HelperResponsiveLayout {
final String deviceId;
const CurtainModuleItems({
super.key,
required this.deviceId,
});
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => CurtainModuleBloc(RemoteControlDeviceService())
..add(FetchCurtainModuleStatusEvent(deviceId: deviceId)),
child: _buildStatusControls(context),
);
}
Widget _buildStatusControls(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 30),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ControlCurtainMovementWidget(
deviceId: deviceId,
),
const SizedBox(
height: 10,
),
SizedBox(
height: 120,
width: 350,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: IconNameStatusContainer(
isFullIcon: false,
name: 'Schedules',
icon: Assets.schedule,
onTap: () {},
status: false,
textColor: ColorsManager.blackColor,
),
),
const SizedBox(
width: 10,
),
Expanded(
child: BlocBuilder<CurtainModuleBloc, CurtainModuleState>(
builder: (context, state) {
if (state is CurtainModuleLoading) {
return const Center(
child: CircularProgressIndicator(),
);
} else if (state is CurtainModuleStatusLoaded) {
return IconNameStatusContainer(
isFullIcon: false,
name: 'Preferences',
icon: Assets.preferences,
onTap: () => showDialog(
context: context,
builder: (_) => BlocProvider.value(
value: context.watch<CurtainModuleBloc>(),
child: CurtainModulePrefrencesDialog(
deviceId: deviceId,
curtainModuleStatusModel:
state.curtainModuleStatus,
),
),
),
status: false,
textColor: ColorsManager.blackColor,
);
} else {
return const SizedBox();
}
},
),
),
],
),
),
],
),
);
}
}

View File

@ -0,0 +1,48 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/calibrate_completed_dialog.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart';
class AccurteCalibratingDialog extends StatelessWidget {
final String deviceId;
final BuildContext parentContext;
const AccurteCalibratingDialog({
super.key,
required this.deviceId,
required this.parentContext,
});
@override
Widget build(_) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: AccurateDialogWidget(
title: 'Calibrating',
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.',
),
leftOnTap: () => Navigator.of(parentContext).pop(),
rightOnTap: () {
parentContext.read<CurtainModuleBloc>().add(
CurCalibrationEvent(
deviceId: deviceId,
),
);
Navigator.of(parentContext).pop();
showDialog(
context: parentContext,
builder: (_) => CalibrateCompletedDialog(
parentContext: parentContext,
deviceId: deviceId,
),
);
},
),
);
}
}

View File

@ -0,0 +1,40 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_calibrating_dialog.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart';
class AccurateCalibrationDialog extends StatelessWidget {
final String deviceId;
final BuildContext parentContext;
const AccurateCalibrationDialog({
super.key,
required this.deviceId,
required this.parentContext,
});
@override
Widget build(_) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: AccurateDialogWidget(
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.',
),
leftOnTap: () => Navigator.of(parentContext).pop(),
rightOnTap: () {
Navigator.of(parentContext).pop();
showDialog(
context: parentContext,
builder: (_) => AccurteCalibratingDialog(
deviceId: deviceId,
parentContext: parentContext,
),
);
},
),
);
}
}

View File

@ -0,0 +1,97 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class AccurateDialogWidget extends StatelessWidget {
final String title;
final Widget body;
final void Function() leftOnTap;
final void Function() rightOnTap;
const AccurateDialogWidget({
super.key,
required this.title,
required this.body,
required this.leftOnTap,
required this.rightOnTap,
});
@override
Widget build(BuildContext context) {
return SizedBox(
height: 300,
width: 400,
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(10),
child: Text(
title,
style: const TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: ColorsManager.blueColor,
),
),
),
const SizedBox(height: 5),
const Divider(
indent: 10,
endIndent: 10,
),
Padding(
padding: const EdgeInsets.all(10),
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,
),
),
),
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,
),
),
),
child: const Text(
'Next',
style: TextStyle(
color: ColorsManager.blueColor,
),
),
),
),
)
],
)
],
),
);
}
}

View File

@ -0,0 +1,77 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class CalibrateCompletedDialog extends StatelessWidget {
final BuildContext parentContext;
final String deviceId;
const CalibrateCompletedDialog({
super.key,
required this.parentContext,
required this.deviceId,
});
@override
Widget build(_) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: SizedBox(
height: 250,
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,
),
),
),
const SizedBox(height: 5),
const Divider(
indent: 10,
endIndent: 10,
),
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,
),
),
),
)
],
),
),
);
}
}

View File

@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class CurtainActionWidget extends StatelessWidget {
final String icon;
final void Function() onTap;
const CurtainActionWidget({
super.key,
required this.icon,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onTap,
child: ClipOval(
child: Container(
height: 60,
width: 60,
padding: const EdgeInsets.all(8),
color: ColorsManager.whiteColors,
child: ClipOval(
child: Container(
height: 60,
width: 60,
padding: const EdgeInsets.all(8),
color: ColorsManager.graysColor,
child: SvgPicture.asset(
icon,
width: 35,
height: 35,
fit: BoxFit.contain,
),
),
),
)),
);
}
}

View File

@ -0,0 +1,190 @@
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/curtain_module/bloc/curtain_module_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/models/curtain_module_model.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/curtain_action_widget.dart';
import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
class ControlCurtainMovementWidget extends StatelessWidget {
final String deviceId;
const ControlCurtainMovementWidget({
super.key,
required this.deviceId,
});
@override
Widget build(BuildContext context) {
return SizedBox(
width: 550,
child: DeviceControlsContainer(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CurtainActionWidget(
icon: Assets.openCurtain,
onTap: () {
context.read<CurtainModuleBloc>().add(
OpenCurtainEvent(deviceId: deviceId),
);
},
),
const SizedBox(
width: 30,
),
CurtainActionWidget(
icon: Assets.pauseCurtain,
onTap: () {
context.read<CurtainModuleBloc>().add(
StopCurtainEvent(deviceId: deviceId),
);
},
),
const SizedBox(
width: 30,
),
CurtainActionWidget(
icon: Assets.closeCurtain,
onTap: () {
context.read<CurtainModuleBloc>().add(
CloseCurtainEvent(deviceId: deviceId),
);
},
),
BlocBuilder<CurtainModuleBloc, CurtainModuleState>(
builder: (context, state) {
if (state is CurtainModuleError) {
return Center(
child: Text(
state.message,
style: const TextStyle(
color: ColorsManager.minBlueDot,
fontSize: 16,
),
),
);
} else if (state is CurtainModuleLoading) {
return const Center(
child: CircularProgressIndicator(
color: ColorsManager.minBlueDot,
),
);
} else if (state is CurtainModuleInitial) {
return const Center(
child: Text(
'No data available',
style: TextStyle(
color: ColorsManager.minBlueDot,
fontSize: 16,
),
),
);
} else if (state is CurtainModuleStatusLoaded) {
return CurtainSliderWidget(
status: state.curtainModuleStatus,
deviceId: deviceId,
);
} else {
return const Center(
child: Text(
'Unknown state',
style: TextStyle(
color: ColorsManager.minBlueDot,
fontSize: 16,
),
),
);
}
},
)
],
),
),
);
}
}
class CurtainSliderWidget extends StatefulWidget {
final CurtainModuleStatusModel status;
final String deviceId;
const CurtainSliderWidget({
super.key,
required this.status,
required this.deviceId,
});
@override
State<CurtainSliderWidget> createState() => _CurtainSliderWidgetState();
}
class _CurtainSliderWidgetState extends State<CurtainSliderWidget> {
double? _localValue; // For temporary drag state
@override
Widget build(BuildContext context) {
// If user is dragging, use local value. Otherwise, use Firebase-synced state
final double currentSliderValue =
_localValue ?? widget.status.percentControl / 100;
return Column(
children: [
Text(
'${(currentSliderValue * 100).round()}%',
style: const TextStyle(
color: ColorsManager.minBlueDot,
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
Slider(
value: currentSliderValue,
min: 0,
max: 1,
divisions: 10, // 10% step
activeColor: ColorsManager.minBlueDot,
thumbColor: ColorsManager.primaryColor,
inactiveColor: ColorsManager.whiteColors,
// Start dragging — use local control
onChangeStart: (_) {
setState(() {
_localValue = currentSliderValue;
});
},
// While dragging — update temporary value
onChanged: (value) {
final steppedValue = (value * 10).roundToDouble() / 10;
setState(() {
_localValue = steppedValue;
});
},
// On release — send API and return to Firebase-controlled state
onChangeEnd: (value) {
final int targetPercent = (value * 100).round();
// Dispatch API call
context.read<CurtainModuleBloc>().add(
SendCurtainPercentToApiEvent(
deviceId: widget.deviceId,
status: Status(
code: 'percent_control',
value: targetPercent,
),
),
);
// Revert back to Firebase-synced stream
setState(() {
_localValue = null;
});
},
),
],
);
}
}

View File

@ -0,0 +1,42 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class NormalTextBodyForDialog extends StatelessWidget {
final String title;
final String step1;
final String step2;
const NormalTextBodyForDialog({
super.key,
required this.title,
required this.step1,
required this.step2,
});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
color: ColorsManager.grayColor,
),
),
Text(
step1,
style: const TextStyle(
color: ColorsManager.grayColor,
),
),
Text(
step2,
style: const TextStyle(
color: ColorsManager.grayColor,
),
)
],
);
}
}

View File

@ -0,0 +1,27 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class NumberInputField extends StatelessWidget {
final TextEditingController controller;
const NumberInputField({super.key, required this.controller});
@override
Widget build(BuildContext context) {
return TextField(
controller: controller,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
decoration: const InputDecoration(
border: InputBorder.none,
isDense: true,
contentPadding: EdgeInsets.zero,
),
style: const TextStyle(
fontSize: 20,
color: ColorsManager.blackColor,
),
);
}
}

View File

@ -0,0 +1,79 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart';
import 'package:syncrow_web/web_layout/default_container.dart';
class PrefReversCardWidget extends StatelessWidget {
final void Function() onTap;
final String title;
final String body;
const PrefReversCardWidget({
super.key,
required this.title,
required this.body,
required this.onTap,
});
@override
Widget build(BuildContext context) {
return DefaultContainer(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 8,
child: Text(
title,
style: const TextStyle(
color: ColorsManager.grayBorder,
fontSize: 15,
),
),
),
const SizedBox(
width: 20,
),
Expanded(
flex: 2,
child: InkWell(
onTap: onTap,
child: Container(
padding: const EdgeInsets.all(3),
decoration: BoxDecoration(
color: ColorsManager.whiteColors,
borderRadius: const BorderRadius.horizontal(
left: Radius.circular(10),
right: Radius.circular(10)),
border: Border.all(color: ColorsManager.grayBorder)),
child: SvgPicture.asset(
Assets.reverseArrows,
height: 15,
),
),
),
)
],
),
SizedBox(
width: 100,
child: Text(
body,
style: const TextStyle(
color: ColorsManager.blackColor,
fontWeight: FontWeight.w500,
fontSize: 18,
),
),
),
],
),
);
}
}

View File

@ -0,0 +1,137 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/models/curtain_module_model.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_calibration_dialog.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/pref_revers_card_widget.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/quick_calibration_dialog.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/web_layout/default_container.dart';
class CurtainModulePrefrencesDialog extends StatelessWidget {
final CurtainModuleStatusModel curtainModuleStatusModel;
final String deviceId;
const CurtainModulePrefrencesDialog({
super.key,
required this.curtainModuleStatusModel,
required this.deviceId,
});
@override
Widget build(_) {
return AlertDialog(
backgroundColor: ColorsManager.CircleImageBackground,
contentPadding: const EdgeInsets.all(30),
title: const Center(
child: Text(
'Preferences',
style: TextStyle(
color: ColorsManager.blueColor,
fontSize: 24,
fontWeight: FontWeight.bold,
),
)),
content: BlocBuilder<CurtainModuleBloc, CurtainModuleState>(
builder: (context, state) {
if (state is CurtainModuleLoading) {
return const Center(
child: CircularProgressIndicator(),
);
} else if (state is CurtainModuleStatusLoaded) {
return SizedBox(
height: 300,
width: 400,
child: GridView(
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
childAspectRatio: 1.5,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
children: [
PrefReversCardWidget(
title: state.curtainModuleStatus.controlBack,
body: 'Motor Steering',
onTap: () {
context.read<CurtainModuleBloc>().add(
ChangeControlBackEvent(
deviceId: deviceId,
controlBack:
state.curtainModuleStatus.controlBack ==
'forward'
? 'back'
: 'forward',
),
);
},
),
PrefReversCardWidget(
title: state.curtainModuleStatus.elecMachineryMode,
body: 'Motor Mode',
onTap: () => context.read<CurtainModuleBloc>().add(
ChangeElecMachineryModeEvent(
deviceId: deviceId,
elecMachineryMode:
state.curtainModuleStatus.elecMachineryMode ==
'dry_contact'
? 'strong_power'
: 'dry_contact',
),
),
),
DefaultContainer(
padding: const EdgeInsets.all(12),
child: InkWell(
onTap: () => showDialog(
context: context,
builder: (_) => AccurateCalibrationDialog(
deviceId: deviceId,
parentContext: context,
),
),
child: const Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('Accurte Calibration',
style: TextStyle(
fontSize: 18,
color: ColorsManager.blackColor,
)),
],
),
),
),
DefaultContainer(
padding: const EdgeInsets.all(12),
child: InkWell(
onTap: () => showDialog(
context: context,
builder: (_) => QuickCalibrationDialog(
timControl: state.curtainModuleStatus.trTimeControl,
deviceId: deviceId,
parentContext: context),
),
child: const Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Text('Quick Calibration',
style: TextStyle(
fontSize: 18,
color: ColorsManager.blackColor,
)),
],
),
),
),
],
),
);
} else {
return const SizedBox();
}
},
),
);
}
}

View File

@ -0,0 +1,122 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/calibrate_completed_dialog.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/number_input_textfield.dart';
import 'package:syncrow_web/utils/color_manager.dart';
class QuickCalibratingDialog extends StatefulWidget {
final int timControl;
final String deviceId;
final BuildContext parentContext;
const QuickCalibratingDialog({
super.key,
required this.timControl,
required this.deviceId,
required this.parentContext,
});
@override
State<QuickCalibratingDialog> createState() => _QuickCalibratingDialogState();
}
class _QuickCalibratingDialogState extends State<QuickCalibratingDialog> {
late TextEditingController _controller;
String? _errorText;
void _onRightTap() {
final value = int.tryParse(_controller.text);
if (value == null || value < 10 || value > 120) {
setState(() {
_errorText = 'Number should be between 10 and 120';
});
return;
}
setState(() {
_errorText = null;
});
widget.parentContext.read<CurtainModuleBloc>().add(
ChangeTimerControlEvent(
deviceId: widget.deviceId,
timControl: value,
),
);
Navigator.of(widget.parentContext).pop();
showDialog(
context: widget.parentContext,
builder: (_) => CalibrateCompletedDialog(
parentContext: widget.parentContext,
deviceId: widget.deviceId,
),
);
}
@override
void initState() {
_controller = TextEditingController(text: widget.timControl.toString());
super.initState();
}
@override
Widget build(_) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: AccurateDialogWidget(
title: 'Calibrating',
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,
),
),
),
],
),
leftOnTap: () => Navigator.of(widget.parentContext).pop(),
rightOnTap: _onRightTap,
),
);
}
}

View File

@ -0,0 +1,44 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart';
import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/quick_calibrating_dialog.dart';
class QuickCalibrationDialog extends StatelessWidget {
final int timControl;
final String deviceId;
final BuildContext parentContext;
const QuickCalibrationDialog({
super.key,
required this.timControl,
required this.deviceId,
required this.parentContext,
});
@override
Widget build(_) {
return AlertDialog(
contentPadding: EdgeInsets.zero,
content: AccurateDialogWidget(
title: 'Quick Calibration',
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.',
),
leftOnTap: () => Navigator.of(parentContext).pop(),
rightOnTap: () {
Navigator.of(parentContext).pop();
showDialog(
context: parentContext,
builder: (_) => QuickCalibratingDialog(
timControl: timControl,
deviceId: deviceId,
parentContext: parentContext,
),
);
},
),
);
}
}

View File

@ -124,7 +124,11 @@ class Assets {
//assets/icons/AC.svg
static const String ac = "assets/icons/AC.svg";
//assets/icons/Curtain.svg
static const String curtain = "assets/icons/Curtain.svg";
static const String curtain = 'assets/icons/Curtain.svg';
static const String openCurtain = 'assets/icons/open_curtain.svg';
static const String pauseCurtain = 'assets/icons/pause_curtain.svg';
static const String closeCurtain = 'assets/icons/close_curtain.svg';
static const String reverseArrows = 'assets/icons/reverse_arrows.svg';
//assets/icons/doorLock.svg
static const String doorLock = "assets/icons/doorLock.svg";
//assets/icons/Gateway.svg