mirror of
https://github.com/SyncrowIOT/web.git
synced 2026-10-25 17:07:55 +00:00
push design and missing view and folder structure
This commit is contained in:
@@ -109,13 +109,25 @@ class CustomTextField extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: context.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: const Color(0xff000000),
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Visibility(
|
||||
visible: isRequired == true,
|
||||
child: Text('* ',
|
||||
style: context.textTheme.bodyMedium!
|
||||
.copyWith(color: Colors.red, fontSize: 13)),
|
||||
),
|
||||
Text(
|
||||
title,
|
||||
style: context.textTheme.bodyMedium!.copyWith(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: const Color(0xff000000),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Material(
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/ac_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/one_gang_switch_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/three_gang_switch_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/two_gang_switch_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/ac_dialog.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/one_gang_switch_dialog.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/three_gang_switch_dialog.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/two_gang_switch_dialog.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||
|
||||
class DeviceDialogHelper {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
class DurationFormatMixin {
|
||||
static String formatDuration(int seconds) {
|
||||
if (seconds >= 3600) {
|
||||
final hours = (seconds / 3600).floor();
|
||||
final remainingMinutes = ((seconds % 3600) / 60).floor();
|
||||
final remainingSeconds = seconds % 60;
|
||||
return '$hours h ${remainingMinutes}m ${remainingSeconds}s';
|
||||
} else if (seconds >= 60) {
|
||||
final minutes = (seconds / 60).floor();
|
||||
final remainingSeconds = seconds % 60;
|
||||
return '$minutes m ${remainingSeconds}s';
|
||||
}
|
||||
return '${seconds}s';
|
||||
}
|
||||
}
|
||||
@@ -73,9 +73,9 @@ class TempSetFunction extends ACFunction {
|
||||
final int step;
|
||||
|
||||
TempSetFunction({required super.deviceId, required super.deviceName})
|
||||
: min = 200,
|
||||
: min = 160,
|
||||
max = 300,
|
||||
step = 5,
|
||||
step = 1,
|
||||
super(
|
||||
code: 'temp_set',
|
||||
operationName: 'Set Temperature',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
class ScenesModel {
|
||||
final String id;
|
||||
final String name;
|
||||
@@ -13,12 +15,16 @@ class ScenesModel {
|
||||
this.icon,
|
||||
});
|
||||
|
||||
factory ScenesModel.fromJson(Map<String, dynamic> json) => ScenesModel(
|
||||
factory ScenesModel.fromJson(Map<String, dynamic> json,
|
||||
{bool? isAutomation}) =>
|
||||
ScenesModel(
|
||||
id: json["id"],
|
||||
name: json["name"] ?? '',
|
||||
status: json["status"] ?? '',
|
||||
type: json["type"] ?? '',
|
||||
icon: json["icon"] as String?,
|
||||
icon: (isAutomation ?? false)
|
||||
? Assets.automation
|
||||
: json["icon"] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/effictive_period_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/effictive_period_dialog.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/period_option.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/repeat_days.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
@@ -16,7 +16,7 @@ class ConditionsRoutinesDevicesView extends StatelessWidget {
|
||||
return BlocBuilder<RoutineBloc, RoutineState>(
|
||||
builder: (context, state) {
|
||||
return const Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
padding: EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
@@ -65,13 +65,13 @@ class ConditionsRoutinesDevicesView extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const TitleRoutine(
|
||||
SizedBox(height: 10),
|
||||
TitleRoutine(
|
||||
title: 'Conditions',
|
||||
subtitle: '(THEN)',
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const Wrap(
|
||||
SizedBox(height: 10),
|
||||
Wrap(
|
||||
spacing: 10,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
@@ -96,20 +96,20 @@ class ConditionsRoutinesDevicesView extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const TitleRoutine(
|
||||
SizedBox(height: 10),
|
||||
TitleRoutine(
|
||||
title: 'Routines',
|
||||
subtitle: '(THEN)',
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const ScenesAndAutomations(),
|
||||
const SizedBox(height: 10),
|
||||
const TitleRoutine(
|
||||
SizedBox(height: 10),
|
||||
ScenesAndAutomations(),
|
||||
SizedBox(height: 10),
|
||||
TitleRoutine(
|
||||
title: 'Devices',
|
||||
subtitle: '',
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
const RoutineDevices(),
|
||||
SizedBox(height: 10),
|
||||
RoutineDevices(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -106,7 +106,7 @@ class DraggableCard extends StatelessWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
'${function.operationName}: ${function.value}',
|
||||
'${function.operationName}: ${_formatFunctionValue(function)}',
|
||||
style: context.textTheme.bodySmall?.copyWith(
|
||||
fontSize: 9,
|
||||
color: ColorsManager.textGray,
|
||||
@@ -144,6 +144,27 @@ class DraggableCard extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
String _formatFunctionValue(DeviceFunctionData function) {
|
||||
if (function.functionCode == 'temp_set' ||
|
||||
function.functionCode == 'temp_current') {
|
||||
return '${(function.value / 10).toStringAsFixed(0)}°C';
|
||||
} else if (function.functionCode.contains('countdown')) {
|
||||
final seconds = function.value.toInt();
|
||||
if (seconds >= 3600) {
|
||||
final hours = (seconds / 3600).floor();
|
||||
final remainingMinutes = ((seconds % 3600) / 60).floor();
|
||||
final remainingSeconds = seconds % 60;
|
||||
return '$hours h ${remainingMinutes}m ${remainingSeconds}s';
|
||||
} else if (seconds >= 60) {
|
||||
final minutes = (seconds / 60).floor();
|
||||
final remainingSeconds = seconds % 60;
|
||||
return '$minutes m ${remainingSeconds}s';
|
||||
}
|
||||
return '${seconds}s';
|
||||
}
|
||||
return function.value.toString();
|
||||
}
|
||||
|
||||
Widget _buildGreyContainer() {
|
||||
return Container(
|
||||
height: 123,
|
||||
|
||||
@@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_event.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/effective_period/effect_period_state.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/effictive_period_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/effictive_period_dialog.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/constants/app_enum.dart';
|
||||
|
||||
@@ -21,9 +21,12 @@ class PeriodOptions extends StatelessWidget {
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
children: [
|
||||
_buildRadioOption(context, EnumEffectivePeriodOptions.allDay, '24 Hours'),
|
||||
_buildRadioOption(context, EnumEffectivePeriodOptions.daytime, 'Sunrise to Sunset'),
|
||||
_buildRadioOption(context, EnumEffectivePeriodOptions.night, 'Sunset to Sunrise'),
|
||||
_buildRadioOption(
|
||||
context, EnumEffectivePeriodOptions.allDay, '24 Hours'),
|
||||
_buildRadioOption(context, EnumEffectivePeriodOptions.daytime,
|
||||
'Sunrise to Sunset'),
|
||||
_buildRadioOption(
|
||||
context, EnumEffectivePeriodOptions.night, 'Sunset to Sunrise'),
|
||||
ListTile(
|
||||
contentPadding: EdgeInsets.zero,
|
||||
onTap: () => showCustomTimePicker(context),
|
||||
@@ -34,7 +37,8 @@ class PeriodOptions extends StatelessWidget {
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 14),
|
||||
),
|
||||
subtitle: state.customStartTime != null && state.customEndTime != null
|
||||
subtitle: state.customStartTime != null &&
|
||||
state.customEndTime != null
|
||||
? Text(
|
||||
'${"${state.customStartTime}"} - ${"${state.customEndTime}"}',
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
@@ -79,7 +83,9 @@ class PeriodOptions extends StatelessWidget {
|
||||
subtitle: Text(
|
||||
subtitle,
|
||||
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
|
||||
color: ColorsManager.textPrimaryColor, fontWeight: FontWeight.w400, fontSize: 10),
|
||||
color: ColorsManager.textPrimaryColor,
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 10),
|
||||
),
|
||||
trailing: Radio<EnumEffectivePeriodOptions>(
|
||||
value: value,
|
||||
|
||||
+2
-2
@@ -327,11 +327,11 @@ class ACHelper {
|
||||
String selectCode,
|
||||
) {
|
||||
return Slider(
|
||||
value: initialValue is int ? initialValue.toDouble() : 200.0,
|
||||
value: initialValue is int ? initialValue.toDouble() : 160.0,
|
||||
min: 160,
|
||||
max: 300,
|
||||
divisions: 14,
|
||||
label: '${((initialValue ?? 200) / 10).toInt()}°C',
|
||||
label: '${((initialValue ?? 160) / 10).toInt()}°C',
|
||||
onChanged: (value) {
|
||||
context.read<FunctionBloc>().add(
|
||||
AddFunction(
|
||||
+2
-1
@@ -4,6 +4,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/functions_bloc/functions_bloc_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/duration_format_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart';
|
||||
@@ -277,7 +278,7 @@ class OneGangSwitchHelper {
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Text(
|
||||
'${initialValue ?? 0} sec',
|
||||
DurationFormatMixin.formatDuration(initialValue?.toInt() ?? 0),
|
||||
style: context.textTheme.headlineMedium!.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
),
|
||||
+2
-1
@@ -4,6 +4,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/functions_bloc/functions_bloc_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/duration_format_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart';
|
||||
@@ -279,7 +280,7 @@ class ThreeGangSwitchHelper {
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Text(
|
||||
'${initialValue ?? 0} sec',
|
||||
DurationFormatMixin.formatDuration(initialValue?.toInt() ?? 0),
|
||||
style: context.textTheme.headlineMedium!.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
),
|
||||
+2
-1
@@ -4,6 +4,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/functions_bloc/functions_bloc_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/duration_format_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/device_functions.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/gang_switches/base_switch_function.dart';
|
||||
import 'package:syncrow_web/pages/routiens/models/gang_switches/switch_operational_value.dart';
|
||||
@@ -278,7 +279,7 @@ class TwoGangSwitchHelper {
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Text(
|
||||
'${initialValue ?? 0} sec',
|
||||
DurationFormatMixin.formatDuration(initialValue?.toInt() ?? 0),
|
||||
style: context.textTheme.headlineMedium!.copyWith(
|
||||
color: ColorsManager.primaryColorWithOpacity,
|
||||
),
|
||||
@@ -4,7 +4,7 @@ import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||
import 'package:syncrow_web/pages/common/text_field/custom_text_field.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/save_routine_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/setting_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/setting_dialog.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/style.dart';
|
||||
|
||||
@@ -31,7 +31,9 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
||||
children: [
|
||||
ConstrainedBox(
|
||||
constraints: BoxConstraints(
|
||||
maxWidth: constraints.maxWidth > 700 ? 450 : constraints.maxWidth - 32),
|
||||
maxWidth: constraints.maxWidth > 700
|
||||
? 450
|
||||
: constraints.maxWidth - 32),
|
||||
child: StatefulTextField(
|
||||
title: 'Routine Name',
|
||||
height: 40,
|
||||
@@ -55,11 +57,14 @@ class RoutineSearchAndButtons extends StatelessWidget {
|
||||
child: Center(
|
||||
child: DefaultButton(
|
||||
onPressed: () async {
|
||||
final result = await SettingHelper.showSettingDialog(
|
||||
final result =
|
||||
await SettingHelper.showSettingDialog(
|
||||
context: context,
|
||||
);
|
||||
if (result != null) {
|
||||
context.read<RoutineBloc>().add(AddSelectedIcon(result));
|
||||
context
|
||||
.read<RoutineBloc>()
|
||||
.add(AddSelectedIcon(result));
|
||||
}
|
||||
},
|
||||
borderRadius: 15,
|
||||
|
||||
@@ -34,7 +34,9 @@ class _ScenesAndAutomationsState extends State<ScenesAndAutomations> {
|
||||
children: scenes.asMap().entries.map((entry) {
|
||||
final scene = entry.value;
|
||||
if (state.searchText != null && state.searchText!.isNotEmpty) {
|
||||
return scene.name.toLowerCase().contains(state.searchText!.toLowerCase())
|
||||
return scene.name
|
||||
.toLowerCase()
|
||||
.contains(state.searchText!.toLowerCase())
|
||||
? DraggableCard(
|
||||
imagePath: Assets.logo,
|
||||
title: scene.name,
|
||||
@@ -49,7 +51,7 @@ class _ScenesAndAutomationsState extends State<ScenesAndAutomations> {
|
||||
: Container();
|
||||
} else {
|
||||
return DraggableCard(
|
||||
imagePath: Assets.logo,
|
||||
imagePath: scene.icon ?? Assets.loginLogo,
|
||||
title: scene.name,
|
||||
deviceData: {
|
||||
'deviceId': scene.id,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/bloc/routine_bloc/routine_bloc.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/delay_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/routine_dialogs/delay_dialog.dart';
|
||||
import 'package:syncrow_web/pages/routiens/helper/dialog_helper/device_dialog_helper.dart';
|
||||
import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart';
|
||||
import 'package:syncrow_web/utils/constants/assets.dart';
|
||||
|
||||
Reference in New Issue
Block a user