From 16dd95c8d1654300fadcb799b511c61008abcb16 Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Sat, 16 Nov 2024 23:58:33 +0300 Subject: [PATCH] added devices --- assets/icons/routine/delay.svg | 24 ++ assets/icons/routine/map.svg | 17 ++ assets/icons/routine/notification.svg | 10 + assets/icons/routine/schedule.svg | 17 ++ assets/icons/routine/tab_to_run.svg | 9 + assets/icons/routine/weather.svg | 242 ++++++++++++++++++ .../common/text_field/custom_text_field.dart | 109 +++++--- .../all_devices/models/devices_model.dart | 136 +++++++--- .../view/device_managment_page.dart | 49 ++-- lib/pages/routiens/bloc/routine_bloc.dart | 13 + lib/pages/routiens/bloc/routine_event.dart | 4 + lib/pages/routiens/bloc/routine_state.dart | 6 + .../view/create_new_routine_view.dart | 74 +++++- .../conditions_routines_devices_view.dart | 106 ++++++++ lib/pages/routiens/widgets/dragable_card.dart | 63 +++++ .../widgets/routine_search_and_buttons.dart | 193 ++++++++++++++ .../widgets/routines_title_widget.dart | 38 +++ .../widgets/search_bar_condition_title.dart | 62 +++++ lib/utils/color_manager.dart | 2 +- lib/utils/constants/assets.dart | 18 ++ lib/utils/enum/device_types.dart | 6 +- lib/utils/style.dart | 32 ++- pubspec.yaml | 1 + 23 files changed, 1117 insertions(+), 114 deletions(-) create mode 100644 assets/icons/routine/delay.svg create mode 100644 assets/icons/routine/map.svg create mode 100644 assets/icons/routine/notification.svg create mode 100644 assets/icons/routine/schedule.svg create mode 100644 assets/icons/routine/tab_to_run.svg create mode 100644 assets/icons/routine/weather.svg create mode 100644 lib/pages/routiens/bloc/routine_bloc.dart create mode 100644 lib/pages/routiens/bloc/routine_event.dart create mode 100644 lib/pages/routiens/bloc/routine_state.dart create mode 100644 lib/pages/routiens/widgets/conditions_routines_devices_view.dart create mode 100644 lib/pages/routiens/widgets/dragable_card.dart create mode 100644 lib/pages/routiens/widgets/routine_search_and_buttons.dart create mode 100644 lib/pages/routiens/widgets/routines_title_widget.dart create mode 100644 lib/pages/routiens/widgets/search_bar_condition_title.dart diff --git a/assets/icons/routine/delay.svg b/assets/icons/routine/delay.svg new file mode 100644 index 00000000..49a8d31c --- /dev/null +++ b/assets/icons/routine/delay.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/routine/map.svg b/assets/icons/routine/map.svg new file mode 100644 index 00000000..595a0d8c --- /dev/null +++ b/assets/icons/routine/map.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/icons/routine/notification.svg b/assets/icons/routine/notification.svg new file mode 100644 index 00000000..f196f466 --- /dev/null +++ b/assets/icons/routine/notification.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/icons/routine/schedule.svg b/assets/icons/routine/schedule.svg new file mode 100644 index 00000000..423eb577 --- /dev/null +++ b/assets/icons/routine/schedule.svg @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/assets/icons/routine/tab_to_run.svg b/assets/icons/routine/tab_to_run.svg new file mode 100644 index 00000000..c8660bb8 --- /dev/null +++ b/assets/icons/routine/tab_to_run.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/routine/weather.svg b/assets/icons/routine/weather.svg new file mode 100644 index 00000000..49ed9408 --- /dev/null +++ b/assets/icons/routine/weather.svg @@ -0,0 +1,242 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/pages/common/text_field/custom_text_field.dart b/lib/pages/common/text_field/custom_text_field.dart index b695da4a..23f033b6 100644 --- a/lib/pages/common/text_field/custom_text_field.dart +++ b/lib/pages/common/text_field/custom_text_field.dart @@ -1,59 +1,97 @@ import 'package:flutter/material.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/style.dart'; class StatefulTextField extends StatefulWidget { - const StatefulTextField( - {super.key, - required this.title, - this.hintText = 'Please enter', - required this.width, - this.elevation = 0, - required this.controller, - this.onSubmitted}); + const StatefulTextField({ + super.key, + required this.title, + this.hintText = 'Please enter', + required this.width, + this.elevation, + required this.controller, + this.onSubmitted, + this.boxDecoration, + this.borderRadius, + this.height, + this.padding, + this.icon, + this.hintColor, + }); final String title; final String hintText; final double width; - final double elevation; + final double? elevation; final TextEditingController controller; final Function? onSubmitted; + final BoxDecoration? boxDecoration; + final double? borderRadius; + final double? height; + final double? padding; + final IconData? icon; + final Color? hintColor; @override State createState() => _StatefulTextFieldState(); } class _StatefulTextFieldState extends State { + @override + void dispose() { + widget.controller.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { - return Container( - child: CustomTextField( - title: widget.title, - controller: widget.controller, - hintText: widget.hintText, - width: widget.width, - elevation: widget.elevation, - onSubmittedFun: widget.onSubmitted), + return CustomTextField( + title: widget.title, + controller: widget.controller, + hintText: widget.hintText, + width: widget.width, + elevation: widget.elevation, + onSubmittedFun: widget.onSubmitted, + boxDecoration: widget.boxDecoration, + borderRadius: widget.borderRadius, + height: widget.height, + padding: widget.padding, + icon: widget.icon, + hintColor: widget.hintColor, ); } } class CustomTextField extends StatelessWidget { - const CustomTextField( - {super.key, - required this.title, - required this.controller, - this.hintText = 'Please enter', - required this.width, - this.elevation = 0, - this.onSubmittedFun}); + const CustomTextField({ + super.key, + required this.title, + required this.controller, + this.hintText = 'Please enter', + required this.width, + this.elevation, + this.onSubmittedFun, + this.boxDecoration, + this.borderRadius, + this.height, + this.padding, + this.icon, + this.hintColor, + }); final String title; final TextEditingController controller; final String hintText; final double width; - final double elevation; + final double? elevation; final Function? onSubmittedFun; + final BoxDecoration? boxDecoration; + final double? borderRadius; + final double? height; + final double? padding; + final IconData? icon; + final Color? hintColor; @override Widget build(BuildContext context) { @@ -71,26 +109,21 @@ class CustomTextField extends StatelessWidget { ), const SizedBox(height: 8), Material( - elevation: elevation, - borderRadius: BorderRadius.circular(8), + elevation: elevation ?? 0, + borderRadius: BorderRadius.circular(borderRadius ?? 8), child: Container( width: width, - height: 45, - decoration: containerDecoration, - - // decoration: BoxDecoration( - // color: Colors.white, - // borderRadius: BorderRadius.circular(8), - // ), + height: height ?? 45, + decoration: boxDecoration ?? containerDecoration, child: TextFormField( controller: controller, style: const TextStyle(color: Colors.black), decoration: InputDecoration( hintText: hintText, - hintStyle: const TextStyle(fontSize: 12), - contentPadding: - const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + hintStyle: TextStyle(fontSize: 12, color: hintColor ?? ColorsManager.blackColor), + contentPadding: EdgeInsets.symmetric(horizontal: 12, vertical: padding ?? 10), border: InputBorder.none, + suffixIcon: icon != null ? Icon(icon, color: ColorsManager.greyColor) : null, ), onFieldSubmitted: (_) { onSubmittedFun!(); diff --git a/lib/pages/device_managment/all_devices/models/devices_model.dart b/lib/pages/device_managment/all_devices/models/devices_model.dart index df80c3e7..50e588b0 100644 --- a/lib/pages/device_managment/all_devices/models/devices_model.dart +++ b/lib/pages/device_managment/all_devices/models/devices_model.dart @@ -3,6 +3,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/device_spa import 'package:syncrow_web/pages/device_managment/all_devices/models/room.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/unit.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/enum/device_types.dart'; class AllDevicesModel { /* @@ -100,12 +101,8 @@ class AllDevicesModel { this.spaces, }); AllDevicesModel.fromJson(Map json) { - room = (json['room'] != null && (json['room'] is Map)) - ? DevicesModelRoom.fromJson(json['room']) - : null; - unit = (json['unit'] != null && (json['unit'] is Map)) - ? DevicesModelUnit.fromJson(json['unit']) - : null; + room = (json['room'] != null && (json['room'] is Map)) ? DevicesModelRoom.fromJson(json['room']) : null; + unit = (json['unit'] != null && (json['unit'] is Map)) ? DevicesModelUnit.fromJson(json['unit']) : null; community = (json['community'] != null && (json['community'] is Map)) ? DeviceCommunityModel.fromJson(json['community']) : null; @@ -117,7 +114,7 @@ class AllDevicesModel { categoryName = json['categoryName']?.toString(); createTime = int.tryParse(json['createTime']?.toString() ?? ''); gatewayId = json['gatewayId']?.toString(); - icon = json['icon'] ?? _getDefaultIcon(productType); + icon = json['icon'] ?? getDefaultIcon(productType); ip = json['ip']?.toString(); lat = json['lat']?.toString(); localKey = json['localKey']?.toString(); @@ -134,38 +131,88 @@ class AllDevicesModel { batteryLevel = int.tryParse(json['battery']?.toString() ?? ''); productName = json['productName']?.toString(); if (json['spaces'] != null && json['spaces'] is List) { - spaces = (json['spaces'] as List) - .map((space) => DeviceSpaceModel.fromJson(space)) - .toList(); + spaces = (json['spaces'] as List).map((space) => DeviceSpaceModel.fromJson(space)).toList(); } } - String _getDefaultIcon(String? productType) { - switch (productType) { - case 'LightBulb': - return Assets.lightBulb; - case 'CeilingSensor': - case 'WallSensor': - return Assets.sensors; - case 'AC': - return Assets.ac; - case 'DoorLock': - return Assets.doorLock; - case 'Curtain': - return Assets.curtain; - case '3G': - case '2G': - case '1G': - return Assets.gangSwitch; - case 'Gateway': - return Assets.gateway; - case 'WH': - return Assets.blackLogo; - case 'DS': - return Assets.sensors; - default: - return Assets.logo; + String getDefaultIcon(String? productType) { + /* + AC +GD +3G +3G +GW +DL +WPS +CPS +AC +CPS +WPS +GW +AC +CUR +DS +1GT +2GT +3GT +1G +1G +2G +2G +DS +WH +1GT +2GT +3GT +GD +WL +WL +3G +CUR +GW +PC +PC +SOS + + */ + DeviceType type = devicesTypesMap[productType] ?? DeviceType.Other; + String tempIcon = ''; + if (type == DeviceType.LightBulb) { + tempIcon = Assets.lightBulb; + } else if (type == DeviceType.CeilingSensor || type == DeviceType.WallSensor) { + tempIcon = Assets.sensors; + } else if (type == DeviceType.AC) { + tempIcon = Assets.ac; + } else if (type == DeviceType.DoorLock) { + tempIcon = Assets.doorLock; + } else if (type == DeviceType.Curtain) { + tempIcon = Assets.curtain; + } else if (type == DeviceType.ThreeGang) { + tempIcon = Assets.gangSwitch; + } else if (type == DeviceType.Gateway) { + tempIcon = Assets.gateway; + } else if (type == DeviceType.OneGang) { + tempIcon = Assets.oneGang; + } else if (type == DeviceType.TwoGang) { + tempIcon = Assets.twoGang; + } else if (type == DeviceType.WH) { + tempIcon = Assets.waterHeater; + } else if (type == DeviceType.DS) { + // tempIcon = Assets.mainDoor; + } else if (type == DeviceType.OneTouch) { + // tempIcon = Assets.oneGang; + } else if (type == DeviceType.TowTouch) { + // tempIcon = Assets.twoGang; + } else if (type == DeviceType.GarageDoor) { + //tempIcon = Assets.; + } else if (type == DeviceType.ThreeTouch) { + // tempIcon = Assets.gang3touch; + } else if (type == DeviceType.WaterLeak) { + tempIcon = Assets.waterLeakNormal; + } else { + tempIcon = Assets.logoHorizontal; } + return tempIcon; } Map toJson() { @@ -271,4 +318,23 @@ class AllDevicesModel { productName.hashCode ^ batteryLevel.hashCode; } + + Map devicesTypesMap = { + "AC": DeviceType.AC, + "GW": DeviceType.Gateway, + "CPS": DeviceType.CeilingSensor, + "DL": DeviceType.DoorLock, + "WPS": DeviceType.WallSensor, + "3G": DeviceType.ThreeGang, + "2G": DeviceType.TwoGang, + "1G": DeviceType.OneGang, + "CUR": DeviceType.Curtain, + "WH": DeviceType.WH, + "DS": DeviceType.DS, + "1GT": DeviceType.OneTouch, + "2GT": DeviceType.TowTouch, + "3GT": DeviceType.ThreeTouch, + "GD": DeviceType.GarageDoor, + "WL": DeviceType.WaterLeak, + }; } diff --git a/lib/pages/device_managment/all_devices/view/device_managment_page.dart b/lib/pages/device_managment/all_devices/view/device_managment_page.dart index d163a718..e0661b50 100644 --- a/lib/pages/device_managment/all_devices/view/device_managment_page.dart +++ b/lib/pages/device_managment/all_devices/view/device_managment_page.dart @@ -2,10 +2,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.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/bloc/switch_tabs/switch_tabs_bloc.dart'; -import 'package:syncrow_web/pages/device_managment/all_devices/widgets/device_managment_body.dart'; import 'package:syncrow_web/pages/device_managment/shared/navigate_home_grid_view.dart'; import 'package:syncrow_web/pages/routiens/view/create_new_routine_view.dart'; -import 'package:syncrow_web/pages/routiens/view/routines_view.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; @@ -76,29 +74,30 @@ class DeviceManagementPage extends StatelessWidget with HelperResponsiveLayout { ); }), rightBody: const NavigateHomeGridView(), - scaffoldBody: BlocBuilder(builder: (context, state) { - if (state is SelectedTabState && state.selectedTab) { - return const RoutinesView(); - } - if (state is ShowCreateRoutineState && state.showCreateRoutine) { - return const CreateNewRoutineView(); - } - - return BlocBuilder( - builder: (context, deviceState) { - if (deviceState is DeviceManagementLoading) { - return const Center(child: CircularProgressIndicator()); - } else if (deviceState is DeviceManagementLoaded || deviceState is DeviceManagementFiltered) { - final devices = - (deviceState as dynamic).devices ?? (deviceState as DeviceManagementFiltered).filteredDevices; - - return DeviceManagementBody(devices: devices); - } else { - return const Center(child: Text('Error fetching Devices')); - } - }, - ); - }), + scaffoldBody: CreateNewRoutineView(), + // BlocBuilder(builder: (context, state) { + // if (state is SelectedTabState && state.selectedTab) { + // return const RoutinesView(); + // } + // if (state is ShowCreateRoutineState && state.showCreateRoutine) { + // return const CreateNewRoutineView(); + // } + // + // return BlocBuilder( + // builder: (context, deviceState) { + // if (deviceState is DeviceManagementLoading) { + // return const Center(child: CircularProgressIndicator()); + // } else if (deviceState is DeviceManagementLoaded || deviceState is DeviceManagementFiltered) { + // final devices = + // (deviceState as dynamic).devices ?? (deviceState as DeviceManagementFiltered).filteredDevices; + // + // return DeviceManagementBody(devices: devices); + // } else { + // return const Center(child: Text('Error fetching Devices')); + // } + // }, + // ); + // }), ), ); } diff --git a/lib/pages/routiens/bloc/routine_bloc.dart b/lib/pages/routiens/bloc/routine_bloc.dart new file mode 100644 index 00000000..c0b2b5c5 --- /dev/null +++ b/lib/pages/routiens/bloc/routine_bloc.dart @@ -0,0 +1,13 @@ +import 'package:bloc/bloc.dart'; +import 'package:meta/meta.dart'; + +part 'routine_event.dart'; +part 'routine_state.dart'; + +class RoutineBloc extends Bloc { + RoutineBloc() : super(RoutineInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/pages/routiens/bloc/routine_event.dart b/lib/pages/routiens/bloc/routine_event.dart new file mode 100644 index 00000000..52ca0690 --- /dev/null +++ b/lib/pages/routiens/bloc/routine_event.dart @@ -0,0 +1,4 @@ +part of 'routine_bloc.dart'; + +@immutable +sealed class RoutineEvent {} diff --git a/lib/pages/routiens/bloc/routine_state.dart b/lib/pages/routiens/bloc/routine_state.dart new file mode 100644 index 00000000..aaf5cb97 --- /dev/null +++ b/lib/pages/routiens/bloc/routine_state.dart @@ -0,0 +1,6 @@ +part of 'routine_bloc.dart'; + +@immutable +sealed class RoutineState {} + +final class RoutineInitial extends RoutineState {} diff --git a/lib/pages/routiens/view/create_new_routine_view.dart b/lib/pages/routiens/view/create_new_routine_view.dart index dc770946..764eb374 100644 --- a/lib/pages/routiens/view/create_new_routine_view.dart +++ b/lib/pages/routiens/view/create_new_routine_view.dart @@ -1,10 +1,82 @@ import 'package:flutter/material.dart'; +import 'package:syncrow_web/pages/routiens/widgets/conditions_routines_devices_view.dart'; +import 'package:syncrow_web/pages/routiens/widgets/routine_search_and_buttons.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; class CreateNewRoutineView extends StatelessWidget { const CreateNewRoutineView({super.key}); @override Widget build(BuildContext context) { - return const Placeholder(); + return Container( + alignment: Alignment.topLeft, + padding: const EdgeInsets.all(16), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const RoutineSearchAndButtons(), + const SizedBox(height: 20), + Flexible( + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: Card( + child: Container( + decoration: BoxDecoration( + color: ColorsManager.whiteColors, + borderRadius: BorderRadius.circular(15), + ), + child: const ConditionsRoutinesDevicesView()), + ), + ), + const SizedBox( + width: 10, + ), + Expanded( + child: Column( + children: [ + Expanded( + child: Card( + margin: EdgeInsets.zero, + child: Container( + decoration: const BoxDecoration( + color: ColorsManager.whiteColors, + borderRadius: BorderRadius.only( + topLeft: Radius.circular(15), + topRight: Radius.circular(15), + ), + ), + ), + ), + ), + Container( + height: 2, + width: double.infinity, + color: ColorsManager.dialogBlueTitle, + ), + Expanded( + child: Card( + margin: EdgeInsets.zero, + child: Container( + decoration: const BoxDecoration( + color: ColorsManager.boxColor, + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(15), + bottomRight: Radius.circular(15), + ), + ), + ), + ), + ), + ], + ), + ), + ], + ), + ), + ], + ), + ); } } diff --git a/lib/pages/routiens/widgets/conditions_routines_devices_view.dart b/lib/pages/routiens/widgets/conditions_routines_devices_view.dart new file mode 100644 index 00000000..6e6ef4a2 --- /dev/null +++ b/lib/pages/routiens/widgets/conditions_routines_devices_view.dart @@ -0,0 +1,106 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart'; +import 'package:syncrow_web/pages/routiens/widgets/dragable_card.dart'; +import 'package:syncrow_web/pages/routiens/widgets/routines_title_widget.dart'; +import 'package:syncrow_web/pages/routiens/widgets/search_bar_condition_title.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; + +class ConditionsRoutinesDevicesView extends StatelessWidget { + const ConditionsRoutinesDevicesView({super.key}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 8.0), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const ConditionTitleAndSearchBar(), + const SizedBox( + height: 10, + ), + const Wrap( + spacing: 10, + runSpacing: 10, + children: [ + DraggableCard( + imagePath: Assets.tabToRun, + title: 'Tab to run', + ), + DraggableCard( + imagePath: Assets.map, + title: 'Location', + ), + DraggableCard( + imagePath: Assets.weather, + title: 'Weather', + ), + DraggableCard( + imagePath: Assets.schedule, + title: 'Schedule', + ), + ], + ), + const SizedBox( + height: 10, + ), + const TitleRoutine( + title: 'Conditions', + subtitle: '(THEN)', + ), + const Wrap( + spacing: 10, + runSpacing: 10, + children: [ + DraggableCard( + imagePath: Assets.notification, + title: 'Send Notification', + ), + DraggableCard( + imagePath: Assets.delay, + title: 'Delay the action', + ), + ], + ), + const SizedBox( + height: 10, + ), + const TitleRoutine( + title: 'Routines', + subtitle: '(THEN)', + ), + const TitleRoutine( + title: 'Devices', + subtitle: '', + ), + BlocProvider( + create: (context) => DeviceManagementBloc() + ..add( + FetchDevices(), + ), + child: BlocBuilder( + builder: (context, state) { + if (state is DeviceManagementLoaded) { + return Wrap( + spacing: 10, + runSpacing: 10, + children: state.devices + .map((device) => DraggableCard( + imagePath: device.getDefaultIcon(device.productType), + title: device.name ?? '', + )) + .toList(), + ); + } + return const Center(child: CircularProgressIndicator()); + }, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/routiens/widgets/dragable_card.dart b/lib/pages/routiens/widgets/dragable_card.dart new file mode 100644 index 00000000..490dd570 --- /dev/null +++ b/lib/pages/routiens/widgets/dragable_card.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; + +class DraggableCard extends StatelessWidget { + const DraggableCard({ + super.key, + required this.imagePath, + required this.title, + this.titleColor, + }); + + final String imagePath; + final String title; + final Color? titleColor; + + @override + Widget build(BuildContext context) { + return Card( + color: ColorsManager.whiteColors, + child: SizedBox( + height: 123, + width: 90, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + height: 50, + width: 50, + decoration: BoxDecoration( + color: ColorsManager.CircleImageBackground, + borderRadius: BorderRadius.circular(90), + border: Border.all( + color: ColorsManager.graysColor, + ), + ), + padding: const EdgeInsets.all(8), + child: imagePath.contains('.svg') + ? SvgPicture.asset( + imagePath, + ) + : Image.network(imagePath), + ), + const SizedBox( + height: 8, + ), + Text( + title, + textAlign: TextAlign.center, + overflow: TextOverflow.ellipsis, + maxLines: 2, + style: context.textTheme.bodySmall?.copyWith( + color: titleColor ?? ColorsManager.blackColor, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/pages/routiens/widgets/routine_search_and_buttons.dart b/lib/pages/routiens/widgets/routine_search_and_buttons.dart new file mode 100644 index 00000000..1acce727 --- /dev/null +++ b/lib/pages/routiens/widgets/routine_search_and_buttons.dart @@ -0,0 +1,193 @@ +import 'package:flutter/material.dart'; +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/utils/color_manager.dart'; +import 'package:syncrow_web/utils/style.dart'; + +class RoutineSearchAndButtons extends StatelessWidget { + const RoutineSearchAndButtons({ + super.key, + }); + + @override + Widget build(BuildContext context) { + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return Wrap( + runSpacing: 16, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded( + child: Wrap( + spacing: 12, + runSpacing: 12, + crossAxisAlignment: WrapCrossAlignment.end, + children: [ + ConstrainedBox( + constraints: + BoxConstraints(maxWidth: constraints.maxWidth > 700 ? 450 : constraints.maxWidth - 32), + child: StatefulTextField( + title: 'Routine Name', + height: 40, + controller: TextEditingController(), + hintText: 'Please enter the name', + boxDecoration: containerWhiteDecoration, + elevation: 0, + borderRadius: 15, + width: 450, + ), + ), + (constraints.maxWidth <= 1000) + ? const SizedBox() + : SizedBox( + height: 40, + width: 200, + child: Center( + child: DefaultButton( + onPressed: () {}, + borderRadius: 15, + elevation: 0, + borderColor: ColorsManager.greyColor, + backgroundColor: ColorsManager.boxColor, + child: const Text( + 'Settings', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + color: ColorsManager.primaryColor, + ), + ), + ), + ), + ), + ], + ), + ), + if (constraints.maxWidth > 1000) + Row( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 40, + width: 200, + child: Center( + child: DefaultButton( + onPressed: () {}, + borderRadius: 15, + elevation: 0, + borderColor: ColorsManager.greyColor, + backgroundColor: ColorsManager.boxColor, + child: const Text( + 'Cancel', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + color: ColorsManager.blackColor, + ), + ), + ), + ), + ), + const SizedBox(width: 12), + SizedBox( + height: 40, + width: 200, + child: Center( + child: DefaultButton( + onPressed: () {}, + borderRadius: 15, + elevation: 0, + backgroundColor: ColorsManager.primaryColor, + child: const Text( + 'Save', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + color: ColorsManager.whiteColors, + ), + ), + ), + ), + ), + ], + ), + ], + ), + if (constraints.maxWidth <= 1000) + Wrap( + runSpacing: 12, + children: [ + SizedBox( + height: 40, + width: 200, + child: Center( + child: DefaultButton( + onPressed: () {}, + borderRadius: 15, + elevation: 0, + borderColor: ColorsManager.greyColor, + backgroundColor: ColorsManager.boxColor, + child: const Text( + 'Settings', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + color: ColorsManager.primaryColor, + ), + ), + ), + ), + ), + const SizedBox(width: 12), + SizedBox( + height: 40, + width: 200, + child: Center( + child: DefaultButton( + onPressed: () {}, + borderRadius: 15, + elevation: 0, + borderColor: ColorsManager.greyColor, + backgroundColor: ColorsManager.boxColor, + child: const Text( + 'Cancel', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + color: ColorsManager.blackColor, + ), + ), + ), + ), + ), + const SizedBox(width: 12), + SizedBox( + height: 40, + width: 200, + child: Center( + child: DefaultButton( + onPressed: () {}, + borderRadius: 15, + elevation: 0, + backgroundColor: ColorsManager.primaryColor, + child: const Text( + 'Save', + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 12, + color: ColorsManager.whiteColors, + ), + ), + ), + ), + ), + ], + ), + ], + ); + }, + ); + } +} diff --git a/lib/pages/routiens/widgets/routines_title_widget.dart b/lib/pages/routiens/widgets/routines_title_widget.dart new file mode 100644 index 00000000..7d2a272f --- /dev/null +++ b/lib/pages/routiens/widgets/routines_title_widget.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; + +class TitleRoutine extends StatelessWidget { + const TitleRoutine({ + super.key, + required this.title, + required this.subtitle, + }); + + final String title; + final String subtitle; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + title, + style: context.textTheme.titleLarge?.copyWith( + color: ColorsManager.greyColor, + ), + ), + const SizedBox( + width: 4, + ), + Text( + subtitle, + style: context.textTheme.titleLarge?.copyWith( + color: ColorsManager.greyColor, + ), + ), + ], + ); + } +} diff --git a/lib/pages/routiens/widgets/search_bar_condition_title.dart b/lib/pages/routiens/widgets/search_bar_condition_title.dart new file mode 100644 index 00000000..40d6b575 --- /dev/null +++ b/lib/pages/routiens/widgets/search_bar_condition_title.dart @@ -0,0 +1,62 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/pages/common/text_field/custom_text_field.dart'; +import 'package:syncrow_web/pages/routiens/widgets/routines_title_widget.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; + +class ConditionTitleAndSearchBar extends StatelessWidget with HelperResponsiveLayout { + const ConditionTitleAndSearchBar({ + super.key, + }); + + @override + Widget build(BuildContext context) { + final isMedium = isMediumScreenSize(context); + final isSmall = isSmallScreenSize(context); + return isMedium || isSmall + ? Wrap( + spacing: 10, + runSpacing: 10, + children: [ + const TitleRoutine(title: 'Conditions', subtitle: '(IF)'), + StatefulTextField( + title: '', + width: 250, + height: 40, + hintText: 'Search', + elevation: 0, + borderRadius: 15, + icon: Icons.search, + hintColor: ColorsManager.grayColor, + boxDecoration: BoxDecoration( + color: ColorsManager.boxColor, + borderRadius: BorderRadius.circular(15), + ), + controller: TextEditingController(), + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + const TitleRoutine(title: 'Conditions', subtitle: '(IF)'), + StatefulTextField( + title: '', + width: 250, + height: 40, + hintText: 'Search', + elevation: 0, + borderRadius: 15, + icon: Icons.search, + hintColor: ColorsManager.grayColor, + boxDecoration: BoxDecoration( + color: ColorsManager.boxColor, + borderRadius: BorderRadius.circular(15), + ), + controller: TextEditingController(), + ), + ], + ); + } +} diff --git a/lib/utils/color_manager.dart b/lib/utils/color_manager.dart index 481fb2fa..140ed370 100644 --- a/lib/utils/color_manager.dart +++ b/lib/utils/color_manager.dart @@ -41,6 +41,6 @@ abstract class ColorsManager { static const Color blue4 = Color(0xFF001E7E); static const Color textGreen = Color(0xFF008905); static const Color yaGreen = Color(0xFFFFBF44); + static const Color CircleImageBackground = Color(0xFFF4F4F4); } //background: #background: #5D5D5D; - diff --git a/lib/utils/constants/assets.dart b/lib/utils/constants/assets.dart index dad9b261..2c0c526f 100644 --- a/lib/utils/constants/assets.dart +++ b/lib/utils/constants/assets.dart @@ -192,4 +192,22 @@ class Assets { //assets/icons/sos_normal.svg static const String sosNormal = 'assets/icons/sos_normal.svg'; + + //assets/icons/routine/tab_to_run.svg + static const String tabToRun = 'assets/icons/routine/tab_to_run.svg'; + + //assets/icons/routine/schedule.svg + static const String schedule = 'assets/icons/routine/schedule.svg'; + + //assets/icons/routine/map.svg + static const String map = 'assets/icons/routine/map.svg'; + + //assets/icons/routine/weather.svg + static const String weather = 'assets/icons/routine/weather.svg'; + + //assets/icons/routine/notification.svg + static const String notification = 'assets/icons/routine/notification.svg'; + + //assets/icons/routine/delay.svg + static const String delay = 'assets/icons/routine/delay.svg'; } diff --git a/lib/utils/enum/device_types.dart b/lib/utils/enum/device_types.dart index 2b1ce8a5..7050f13a 100644 --- a/lib/utils/enum/device_types.dart +++ b/lib/utils/enum/device_types.dart @@ -11,9 +11,13 @@ enum DeviceType { CeilingSensor, WallSensor, WH, - DoorSensor, + DS, + OneTouch, + TowTouch, + ThreeTouch, GarageDoor, WaterLeak, + DoorSensor, Other, } /* diff --git a/lib/utils/style.dart b/lib/utils/style.dart index 145cf8a1..04108333 100644 --- a/lib/utils/style.dart +++ b/lib/utils/style.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; + import 'color_manager.dart'; -InputDecoration? textBoxDecoration({bool suffixIcon = false}) => - InputDecoration( +InputDecoration? textBoxDecoration({bool suffixIcon = false}) => InputDecoration( focusColor: ColorsManager.grayColor, suffixIcon: suffixIcon ? const Icon(Icons.search) : null, hintText: 'Search', @@ -30,14 +30,20 @@ InputDecoration? textBoxDecoration({bool suffixIcon = false}) => ), ); -BoxDecoration containerDecoration = BoxDecoration( - boxShadow: [ - BoxShadow( - color: Colors.grey.withOpacity(0.3), - spreadRadius: 2, - blurRadius: 4, - offset: const Offset(0, 5), // changes position of shadow - ), - ], - color: ColorsManager.boxColor, - borderRadius: const BorderRadius.all(Radius.circular(10))); +BoxDecoration containerDecoration = BoxDecoration(boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.3), + spreadRadius: 2, + blurRadius: 4, + offset: const Offset(0, 5), // changes position of shadow + ), +], color: ColorsManager.boxColor, borderRadius: const BorderRadius.all(Radius.circular(10))); + +BoxDecoration containerWhiteDecoration = BoxDecoration(boxShadow: [ + BoxShadow( + color: Colors.grey.withOpacity(0.3), + spreadRadius: 2, + blurRadius: 4, + offset: const Offset(0, 5), // changes position of shadow + ), +], color: ColorsManager.whiteColors, borderRadius: const BorderRadius.all(Radius.circular(15))); diff --git a/pubspec.yaml b/pubspec.yaml index 7742e4da..9e35e58f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -76,6 +76,7 @@ flutter: # To add assets to your application, add an assets section, like this: assets: - assets/icons/automation_functions/ + - assets/icons/routine/ - assets/icons/ - assets/images/ - assets/