diff --git a/assets/icons/1_Gang_switch_icon.svg b/assets/icons/1_Gang_switch_icon.svg new file mode 100644 index 00000000..33a0755b --- /dev/null +++ b/assets/icons/1_Gang_switch_icon.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/assets/icons/2_Gang_Switch_icon.svg b/assets/icons/2_Gang_Switch_icon.svg new file mode 100644 index 00000000..e72fa4f7 --- /dev/null +++ b/assets/icons/2_Gang_Switch_icon.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/assets/icons/3_Gang_switch_icon.svg b/assets/icons/3_Gang_switch_icon.svg new file mode 100644 index 00000000..45dea511 --- /dev/null +++ b/assets/icons/3_Gang_switch_icon.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/assets/icons/add_icon.svg b/assets/icons/add_icon.svg new file mode 100644 index 00000000..e31d09ac --- /dev/null +++ b/assets/icons/add_icon.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/icons/door_lock.svg b/assets/icons/door_lock.svg new file mode 100644 index 00000000..2302d58d --- /dev/null +++ b/assets/icons/door_lock.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/presence_sensor.svg b/assets/icons/presence_sensor.svg new file mode 100644 index 00000000..f1bdfb90 --- /dev/null +++ b/assets/icons/presence_sensor.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/smart_gateway_icon.svg b/assets/icons/smart_gateway_icon.svg new file mode 100644 index 00000000..33207c58 --- /dev/null +++ b/assets/icons/smart_gateway_icon.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/smart_light_icon.svg b/assets/icons/smart_light_icon.svg new file mode 100644 index 00000000..a0013940 --- /dev/null +++ b/assets/icons/smart_light_icon.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/icons/smart_thermostat_icon.svg b/assets/icons/smart_thermostat_icon.svg new file mode 100644 index 00000000..d5782750 --- /dev/null +++ b/assets/icons/smart_thermostat_icon.svg @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/pages/device_managment/all_devices/models/device_type_model.dart b/lib/pages/device_managment/all_devices/models/device_type_model.dart new file mode 100644 index 00000000..da228d3b --- /dev/null +++ b/lib/pages/device_managment/all_devices/models/device_type_model.dart @@ -0,0 +1,22 @@ +class DeviceTypeModel { + final String name; + final String icon; + + DeviceTypeModel({required this.name, required this.icon}); + + // Factory method for creating a new DeviceTypeModel from JSON + factory DeviceTypeModel.fromJson(Map json) { + return DeviceTypeModel( + name: json['name'], + icon: json['icon'], + ); + } + + // Convert this model to JSON format + Map toJson() { + return { + 'name': name, + 'icon': icon, + }; + } +} diff --git a/lib/pages/spaces_management/view/dialogs/create_space_dialog.dart b/lib/pages/spaces_management/view/dialogs/create_space_dialog.dart index 8e766abb..faf31076 100644 --- a/lib/pages/spaces_management/view/dialogs/create_space_dialog.dart +++ b/lib/pages/spaces_management/view/dialogs/create_space_dialog.dart @@ -2,11 +2,11 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_web/pages/common/buttons/cancel_button.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; +import 'package:syncrow_web/pages/spaces_management/widgets/add_device_type_widget.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; class CreateSpaceDialog extends StatefulWidget { - // Add the onCreateSpace parameter as a required field final Function(String, String) onCreateSpace; const CreateSpaceDialog({super.key, required this.onCreateSpace}); @@ -16,8 +16,8 @@ class CreateSpaceDialog extends StatefulWidget { } class CreateSpaceDialogState extends State { - String selectedIcon = Assets.location; // Initially selected icon - String enteredName = ''; // Store entered space name + String selectedIcon = Assets.location; + String enteredName = ''; @override Widget build(BuildContext context) { @@ -25,7 +25,7 @@ class CreateSpaceDialogState extends State { title: const Text('Create New Space'), backgroundColor: ColorsManager.whiteColors, content: SizedBox( - width: 600, // Set width for the dialog + width: 600, child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, @@ -44,7 +44,7 @@ class CreateSpaceDialogState extends State { ), ), SvgPicture.asset( - selectedIcon, // Display the selected icon here + selectedIcon, width: 60, height: 60, ), @@ -52,8 +52,7 @@ class CreateSpaceDialogState extends State { top: 2, left: 2, child: InkWell( - onTap: () => - _showIconSelectionDialog(), // Open the icon selection dialog + onTap: () => _showIconSelectionDialog(), child: Container( width: 20, height: 20, @@ -70,40 +69,121 @@ class CreateSpaceDialogState extends State { ), const SizedBox(width: 16), Expanded( - child: TextField( - onChanged: (value) { - enteredName = value; // Capture entered name - }, - style: TextStyle( - color: ColorsManager.blackColor, - ), - decoration: InputDecoration( - hintText: 'Please enter the name', - hintStyle: const TextStyle( - fontSize: 14, // Set your desired font size - color: ColorsManager.lightGrayColor - , // Optional: Change the color of the hint text - fontWeight: - FontWeight.w400, // Optional: Adjust the font weight + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Name input field + TextField( + onChanged: (value) { + enteredName = value; + }, + style: const TextStyle(color: Colors.black), + decoration: InputDecoration( + hintText: 'Please enter the name', + hintStyle: const TextStyle( + fontSize: 14, + color: ColorsManager.lightGrayColor, + fontWeight: FontWeight.w400), + filled: true, + fillColor: const Color(0xFFF5F6F7), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color( + 0xFFF5F6F7), // Light gray color when enabled (not focused) + width: 1.5, + ), + ), + // Set border when focused + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color( + 0xFFF5F6F7), // Primary color when focused + width: 1.5, + ), + ), + // Set border for disabled state + disabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color( + 0xFFF5F6F7), // Light gray for disabled state + width: 1.5, + ), + ), + // Set border for error state + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color( + 0xFFF5F6F7), // Red border when there's an error + width: 1.5, + ), + ), + // Border for focused error state + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: const BorderSide( + color: Color( + 0xFFF5F6F7), // Red border when there's an error and it's focused + width: 1.5, + ), + ), + ), ), - filled: true, - fillColor: const Color(0xFFF5F6F7), - border: OutlineInputBorder( - borderSide: const BorderSide(color: Color(0xFFF5F6F7)), - borderRadius: BorderRadius.circular(10), + const SizedBox(height: 16), + // Add Devices or Space Model Button + ElevatedButton( + onPressed: () { + showDialog( + context: context, + builder: (context) => AddDeviceWidget(), + ); + // Logic to assign devices or select a model + }, + style: ElevatedButton.styleFrom( + backgroundColor: ColorsManager.textFieldGreyColor, + padding: const EdgeInsets.symmetric( + horizontal: 16, vertical: 20), + shape: RoundedRectangleBorder( + side: const BorderSide( + // Add border side here + color: Color( + 0xFFE5E5E5), // Define your desired border color + width: 2.0, // Define border width + ), + borderRadius: BorderRadius.circular(20)), + ), + child: Row( + mainAxisSize: MainAxisSize + .min, // Adjust the button size to fit the content + children: [ + SvgPicture.asset( + Assets + .addIcon, // Replace with your actual icon path + width: 20, // Set the size of the icon + height: 20, + ), + const SizedBox( + width: + 8), // Add spacing between the icon and text + const Text( + 'Add devices / Assign a space model', + style: TextStyle( + color: Colors.black, + fontSize: 16, + fontFamily: 'Aftika', + fontWeight: FontWeight.w400, + height: + 1.5, // Adjust line height for better spacing + ), + ), + const SizedBox(width: 8), + ], + ), ), - enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: Color(0xFFF5F6F7), - width: 1), // Default border - borderRadius: BorderRadius.circular(10), - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: - BorderSide(color: Color(0xFFF5F6F7), width: 1), - ), - ), + ], ), ), ], @@ -126,9 +206,9 @@ class CreateSpaceDialogState extends State { child: DefaultButton( onPressed: () { if (enteredName.isNotEmpty) { - widget.onCreateSpace( - enteredName, selectedIcon); // Pass name and icon back - Navigator.of(context).pop(); // Close dialog + widget.onCreateSpace(enteredName, + selectedIcon); // Pass the name and icon back + Navigator.of(context).pop(); // Close the dialog } }, child: const Text('OK'), @@ -142,7 +222,6 @@ class CreateSpaceDialogState extends State { ); } - // Icon selection dialog void _showIconSelectionDialog() { showDialog( context: context, @@ -151,8 +230,8 @@ class CreateSpaceDialogState extends State { title: const Text('Select Icon'), backgroundColor: Colors.white, content: Container( - width: 500, // Width of the icon selection dialog - height: 200, // Height of the dialog + width: 500, + height: 200, padding: const EdgeInsets.all(18), decoration: BoxDecoration( color: const Color(0xFFF5F6F7), @@ -160,24 +239,22 @@ class CreateSpaceDialogState extends State { ), child: GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 7, // Number of icons per row - crossAxisSpacing: 10, // Space between icons horizontally - mainAxisSpacing: 22, // Space between icons vertically + crossAxisCount: 7, + crossAxisSpacing: 10, + mainAxisSpacing: 22, ), itemCount: _iconList.length, itemBuilder: (BuildContext context, int index) { return GestureDetector( onTap: () { setState(() { - selectedIcon = - _iconList[index]; // Update the selected icon + selectedIcon = _iconList[index]; }); - Navigator.of(context) - .pop(); // Close the icon selection dialog + Navigator.of(context).pop(); }, child: SvgPicture.asset( _iconList[index], - width: 50, // Adjust size as needed + width: 50, height: 50, ), ); @@ -189,7 +266,6 @@ class CreateSpaceDialogState extends State { ); } - // Icon list containing SVG asset paths final List _iconList = [ Assets.location, Assets.villa, diff --git a/lib/pages/spaces_management/widgets/add_device_type_widget.dart b/lib/pages/spaces_management/widgets/add_device_type_widget.dart new file mode 100644 index 00000000..09abfadc --- /dev/null +++ b/lib/pages/spaces_management/widgets/add_device_type_widget.dart @@ -0,0 +1,135 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/models/device_type_model.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; + +class AddDeviceWidget extends StatefulWidget { + const AddDeviceWidget({Key? key}) : super(key: key); + + @override + _AddDeviceWidgetState createState() => _AddDeviceWidgetState(); +} + +// Create a static list of DeviceTypeModel +final List staticDeviceTypes = [ + DeviceTypeModel(name: 'Smart Light', icon: Assets.smartLightIcon), + DeviceTypeModel(name: 'Presence Sensor', icon: Assets.presenceSensor), + DeviceTypeModel(name: '3 Gang Smart switch', icon: Assets.Gang3SwitchIcon), + DeviceTypeModel(name: '2 Gang Smart switch', icon: Assets.Gang2SwitchIcon), + DeviceTypeModel(name: '1 Gang Smart switch', icon: Assets.Gang1SwitchIcon), + DeviceTypeModel(name: 'Smart Door Lock', icon: Assets.DoorLockIcon), + DeviceTypeModel(name: 'Smart Gateway', icon: Assets.SmartGatewayIcon) +]; + +class _AddDeviceWidgetState extends State { + @override + Widget build(BuildContext context) { + return AlertDialog( + title: const Text('Add Devices'), + backgroundColor: ColorsManager.whiteColors, + content: Container( + width: 800, // Set width for the dialog + height: 600, // Set height for the dialog + color: Color(0xFFF4F4F4), + child: Column( + children: [ + const SizedBox(height: 16.0), + Expanded( + child: GridView.builder( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, // Adjust number of items per row + mainAxisSpacing: 10, + crossAxisSpacing: 10, + childAspectRatio: 1.5, + ), + itemCount: staticDeviceTypes.length, + itemBuilder: (context, index) { + final deviceType = staticDeviceTypes[index]; + return _buildDeviceTypeTile(deviceType); + }, + ), + ), + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text('Cancel'), + ), + TextButton( + onPressed: () { + // Logic to save or confirm selected devices + Navigator.of(context).pop(); + }, + child: const Text('OK'), + ), + ], + ); + } + + Widget _buildDeviceTypeTile(DeviceTypeModel deviceType) { + return SizedBox( + width: 90, // Set desired width + height: 120, // Set desired height + child: Card( + elevation: 2, + color: ColorsManager.whiteColors, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 60, // Width for the circular container + height: 60, // Height for the circular container + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: ColorsManager.textFieldGreyColor, // Border color + width: 2, // Border width + ), + color: ColorsManager.textFieldGreyColor, + ), + child: Center( + child: SvgPicture.asset( + deviceType.icon, + width: 40, + height: 40, + ), + ), + ), + const SizedBox(height: 8), + Text( + deviceType.name, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + ), + ), + const SizedBox(height: 8), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconButton( + onPressed: () { + setState(() {}); + }, + icon: const Icon(Icons.remove_circle_outline), + ), + IconButton( + onPressed: () {}, + icon: const Icon(Icons.add_circle_outline), + ), + ], + ), + ], + ), + ), + )); + } +} diff --git a/lib/utils/constants/assets.dart b/lib/utils/constants/assets.dart index 7c01ddb4..5c605609 100644 --- a/lib/utils/constants/assets.dart +++ b/lib/utils/constants/assets.dart @@ -162,4 +162,14 @@ class Assets { static const String textFieldSearch = 'assets/icons/textfield_search_icon.svg'; static const String roundedAddIcon = 'assets/icons/rounded_add_icon.svg'; + static const String addIcon = 'assets/icons/add_icon.svg'; + static const String smartThermostatIcon = + 'assets/icons/smart_thermostat_icon.svg'; + static const String smartLightIcon = 'assets/icons/smart_light_icon.svg'; + static const String presenceSensor = 'assets/icons/presence_sensor.svg'; + static const String Gang3SwitchIcon = 'assets/icons/3_Gang_switch_icon.svg'; + static const String Gang2SwitchIcon = 'assets/icons/2_Gang_Switch_icon.svg'; + static const String Gang1SwitchIcon = 'assets/icons/1_Gang_switch_icon.svg'; + static const String DoorLockIcon = 'assets/icons/door_lock.svg'; + static const String SmartGatewayIcon = 'assets/icons/smart_gateway_icon.svg'; }