diff --git a/lib/common/custom_expansion_tile.dart b/lib/common/custom_expansion_tile.dart index cc140263..5876ae31 100644 --- a/lib/common/custom_expansion_tile.dart +++ b/lib/common/custom_expansion_tile.dart @@ -5,11 +5,15 @@ class CustomExpansionTile extends StatefulWidget { final String title; final List? children; final bool initiallyExpanded; + final bool? isExpanded; // New parameter to control expansion + final ValueChanged? onExpansionChanged; // Callback for expansion change CustomExpansionTile({ required this.title, this.children, this.initiallyExpanded = false, + this.isExpanded, // Allow external control over expansion + this.onExpansionChanged, // Notify when expansion changes }); @override @@ -26,6 +30,16 @@ class CustomExpansionTileState extends State { _isExpanded = widget.initiallyExpanded; } + @override + void didUpdateWidget(CustomExpansionTile oldWidget) { + super.didUpdateWidget(oldWidget); + if (widget.isExpanded != null && widget.isExpanded != _isExpanded) { + setState(() { + _isExpanded = widget.isExpanded!; + }); + } + } + @override Widget build(BuildContext context) { return Column( @@ -34,6 +48,7 @@ class CustomExpansionTileState extends State { onTap: () { setState(() { _isExpanded = !_isExpanded; + widget.onExpansionChanged?.call(_isExpanded); }); }, child: Row( @@ -47,28 +62,22 @@ class CustomExpansionTileState extends State { }); }, side: WidgetStateBorderSide.resolveWith((states) { - if (states.contains(WidgetState.selected)) { - return const BorderSide(color: ColorsManager.grayBorder); - } return const BorderSide(color: ColorsManager.grayBorder); }), - // Customize the color for different checkbox states fillColor: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { - return ColorsManager.grayBorder; // Checked state color + return ColorsManager.grayBorder; + } else { + return ColorsManager.checkBoxFillColor; } - return ColorsManager - .checkBoxFillColor; // Unchecked state color }), - checkColor: ColorsManager.whiteColors, // Checkmark color + checkColor: ColorsManager.whiteColors, ), - // Expand/Collapse Icon with reduced size if (widget.children != null && widget.children!.isNotEmpty) Icon( _isExpanded - ? Icons.keyboard_arrow_down // Upward arrow when expanded - : Icons - .keyboard_arrow_right, // Right arrow when collapsed + ? Icons.keyboard_arrow_down + : Icons.keyboard_arrow_right, color: Colors.grey, size: 16.0, // Reduced icon size ), @@ -87,7 +96,6 @@ class CustomExpansionTileState extends State { ], ), ), - // Display children if available and expanded if (_isExpanded && widget.children != null && widget.children!.isNotEmpty) diff --git a/lib/common/search_bar.dart b/lib/common/search_bar.dart new file mode 100644 index 00000000..073957b2 --- /dev/null +++ b/lib/common/search_bar.dart @@ -0,0 +1,70 @@ +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'; + +class CustomSearchBar extends StatelessWidget { + final TextEditingController? controller; + final String hintText; + + const CustomSearchBar({ + Key? key, + this.controller, + this.hintText = 'Search', + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: ColorsManager.whiteColors, + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.2), + spreadRadius: 0, + blurRadius: 8, + offset: const Offset(0, 4), + ), + ], + ), + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Container( + padding: const EdgeInsets.symmetric(vertical: 20.0), + width: double.infinity, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(12), + ), + child: TextField( + controller: controller, + style: const TextStyle( + color: Colors.black, + ), + decoration: InputDecoration( + filled: true, + fillColor: ColorsManager.textFieldGreyColor, + hintText: hintText, + hintStyle: TextStyle( + color: Colors.grey[400], + ), + suffixIcon: Padding( + padding: const EdgeInsets.only(right: 16), + child: SvgPicture.asset( + Assets.textFieldSearch, + width: 24, + height: 24, + ), + ), + border: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(12), + ), + contentPadding: const EdgeInsets.symmetric( + vertical: 14, + horizontal: 16, + ), + ), + ), + ), + ); + } +} diff --git a/lib/main.dart b/lib/main.dart index 90c643cc..1bd86775 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -59,6 +59,7 @@ class MyApp extends StatelessWidget { bodyLarge: TextStyle(fontSize: 16, color: Colors.white), headlineSmall: TextStyle(color: Colors.black87, fontSize: 18), headlineMedium: TextStyle(color: Colors.black87, fontSize: 20), + titleMedium: TextStyle(color: Colors.black87, fontSize: 22, fontWeight: FontWeight.bold ), headlineLarge: TextStyle( color: Colors.white, fontSize: 24, diff --git a/lib/pages/spaces_management/view/community_tile.dart b/lib/pages/spaces_management/view/community_tile.dart new file mode 100644 index 00000000..5530ea13 --- /dev/null +++ b/lib/pages/spaces_management/view/community_tile.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:syncrow_web/common/custom_expansion_tile.dart'; + +class CommunityTile extends StatelessWidget { + final String title; + final String expandedTile; + final Function(String, bool) onExpansionChanged; + final List? children; + + const CommunityTile({ + Key? key, + required this.title, + required this.expandedTile, + required this.onExpansionChanged, + this.children, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return CustomExpansionTile( + title: title, + isExpanded: expandedTile == title, + onExpansionChanged: (bool expanded) { + onExpansionChanged(title, expanded); + }, + children: children, + ); + } +} diff --git a/lib/pages/spaces_management/view/sidebar_widget.dart b/lib/pages/spaces_management/view/sidebar_widget.dart new file mode 100644 index 00000000..8572c63c --- /dev/null +++ b/lib/pages/spaces_management/view/sidebar_widget.dart @@ -0,0 +1,107 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_web/common/search_bar.dart'; +import 'package:syncrow_web/pages/spaces_management/view/community_tile.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/utils/style.dart'; + +class SidebarWidget extends StatefulWidget { + final Function(String)? onCommunitySelected; + + SidebarWidget({this.onCommunitySelected}); + + @override + _SidebarWidgetState createState() => _SidebarWidgetState(); +} + +class _SidebarWidgetState extends State { + String? _expandedTile; + + // A helper method to handle the expansion logic for CustomExpansionTile + void _handleExpansionChange(String title, bool expanded) { + setState(() { + _expandedTile = expanded ? title : null; + }); + widget.onCommunitySelected?.call(title); + } + + @override + Widget build(BuildContext context) { + return Container( + width: 300, + decoration: subSectionContainerDecoration, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Communities title with the add button + Container( + decoration: subSectionContainerDecoration, + padding: const EdgeInsets.all(16.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + 'Communities', + style: Theme.of(context).textTheme.titleMedium, + ), + GestureDetector( + onTap: () { + // Handle add button action + }, + child: Container( + width: 30, + height: 30, + decoration: const BoxDecoration( + color: ColorsManager.whiteColors, + shape: BoxShape.circle, + ), + child: Center( + child: SvgPicture.asset( + Assets.roundedAddIcon, + width: 24, + height: 24, + ), + ), + ), + ), + ], + ), + ), + // Search bar + const CustomSearchBar(), + const SizedBox(height: 16), + // Community list with one item expanded at a time + Expanded( + child: ListView( + children: [ + CommunityTile( + title: "Downtown Dubai", + expandedTile: _expandedTile ?? '', + onExpansionChanged: _handleExpansionChange, + ), + CommunityTile( + title: 'Dubai Creek Harbour', + expandedTile: _expandedTile ?? '', + onExpansionChanged: _handleExpansionChange, + ), + CommunityTile( + title: 'Dubai Hills Estate', + expandedTile: _expandedTile ?? '', + onExpansionChanged: _handleExpansionChange, + children: [ + CommunityTile( + title: 'South Side', + expandedTile: _expandedTile ?? '', + onExpansionChanged: _handleExpansionChange, + ), + ], + ), + ], + ), + ), + ], + ), + ); + } +} diff --git a/lib/pages/spaces_management/view/spaces_management_page.dart b/lib/pages/spaces_management/view/spaces_management_page.dart index 6a7f177e..e5f6eedf 100644 --- a/lib/pages/spaces_management/view/spaces_management_page.dart +++ b/lib/pages/spaces_management/view/spaces_management_page.dart @@ -5,6 +5,7 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_web/common/custom_expansion_tile.dart'; import 'package:syncrow_web/pages/common/buttons/add_space_button.dart'; import 'package:syncrow_web/pages/spaces_management/view/dialogs/create_space_dialog.dart'; +import 'package:syncrow_web/pages/spaces_management/view/sidebar_widget.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; @@ -18,6 +19,11 @@ class SpaceManagementPageState extends State { List spaces = []; List connections = []; + void _handleCommunitySelection(String community) { + // Handle community selection here + print("Selected Community: $community"); + } + @override Widget build(BuildContext context) { Size screenSize = MediaQuery.of(context).size; @@ -33,156 +39,9 @@ class SpaceManagementPageState extends State { Row( children: [ // Sidebar for navigation and community list - Container( - width: 300, // Fixed width for sidebar - decoration: BoxDecoration( - color: Colors.white, // No gradient inside - ), - - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // "Communities" title with the add button - Container( - decoration: BoxDecoration( - color: Colors.white, // Background color - - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.1), - blurRadius: 10, - spreadRadius: 1, - offset: Offset(0, 2), // Adjust the shadow position - ), - ], - ), - padding: const EdgeInsets.all( - 16.0), // Apply padding inside the container - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - 'Communities', - style: TextStyle( - fontSize: 22, - fontWeight: FontWeight.bold, - ), - ), - // Plus Button (+) - GestureDetector( - onTap: () { - // Handle the button tap action - }, - child: Container( - width: 30, - height: 30, - decoration: const BoxDecoration( - color: Colors.white, - shape: BoxShape.circle, - ), - child: Center( - child: SvgPicture.asset( - Assets - .roundedAddIcon, // Path to your SVG asset - width: 24, // Set the width - height: 24, // Set the height - ), - ), - ), - ), - ], - ), - ), - - // Search bar - // Search bar - Container( - decoration: BoxDecoration( - color: ColorsManager.whiteColors, - boxShadow: [ - BoxShadow( - color: - Colors.black.withOpacity(0.2), // Subtle shadow - spreadRadius: 0, // No spread - blurRadius: 8, // Softer shadow edges - offset: Offset(0, 4), // Shadow only on the bottom - ), - ], - ), - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: Container( - padding: const EdgeInsets.symmetric(vertical: 20.0), - width: double - .infinity, // Make the container take the full width of its parent - decoration: BoxDecoration( - borderRadius: BorderRadius.circular( - 12), // Smooth rounded corners - ), - child: TextField( - style: const TextStyle( - color: Colors.black, // Set the text color to black - ), - decoration: InputDecoration( - filled: true, - fillColor: ColorsManager - .textFieldGreyColor, // Background color for the text field itself - hintText: 'Search', - hintStyle: TextStyle( - color: Colors.grey[400], // Gray hint text color - ), - suffixIcon: Padding( - padding: const EdgeInsets.only( - right: - 16), // Add padding to avoid icon sticking to the edge - child: SvgPicture.asset( - Assets - .textFieldSearch, // Path to your SVG asset - width: 24, // Set the width - height: 24, // Set the height - ), - ), // Search icon - border: OutlineInputBorder( - borderSide: BorderSide.none, // Remove border - borderRadius: BorderRadius.circular( - 12), // Rounded corners for text field - ), - contentPadding: const EdgeInsets.symmetric( - vertical: - 14, // Vertical padding for proper text alignment - horizontal: - 16, // Add space between the text and the left edge - ), // Proper padding for alignment - ), - ), - ), - ), - - const SizedBox(height: 16), - // Example of community list - Expanded( - child: ListView( - children: [ - CustomExpansionTile( - title: "Downtown Dubai", - ), - CustomExpansionTile( - title: 'Dubai Creek Harbour', - ), - CustomExpansionTile( - title: 'Dubai Hills Estate', - children: [ - CustomExpansionTile( - title: 'South Side', - initiallyExpanded: false), - ], - ), - ], - ), - ), - ], - ), + SidebarWidget( + onCommunitySelected: _handleCommunitySelection, ), - // Right Side: Community Structure Area Expanded( child: Container( diff --git a/lib/utils/style.dart b/lib/utils/style.dart index 3f31f9d7..bdc4eb3f 100644 --- a/lib/utils/style.dart +++ b/lib/utils/style.dart @@ -41,3 +41,15 @@ BoxDecoration containerDecoration = BoxDecoration( ], color: ColorsManager.boxColor, borderRadius: const BorderRadius.all(Radius.circular(10))); + +BoxDecoration subSectionContainerDecoration = BoxDecoration( + color: ColorsManager.whiteColors, + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.1), + blurRadius: 10, + spreadRadius: 1, + offset: const Offset(0, 2), + ), + ], +);