reduce duplicated code

This commit is contained in:
hannathkadher
2024-09-10 22:57:34 +04:00
parent b362029424
commit b40998558e
7 changed files with 248 additions and 162 deletions

View File

@ -5,11 +5,15 @@ class CustomExpansionTile extends StatefulWidget {
final String title; final String title;
final List<Widget>? children; final List<Widget>? children;
final bool initiallyExpanded; final bool initiallyExpanded;
final bool? isExpanded; // New parameter to control expansion
final ValueChanged<bool>? onExpansionChanged; // Callback for expansion change
CustomExpansionTile({ CustomExpansionTile({
required this.title, required this.title,
this.children, this.children,
this.initiallyExpanded = false, this.initiallyExpanded = false,
this.isExpanded, // Allow external control over expansion
this.onExpansionChanged, // Notify when expansion changes
}); });
@override @override
@ -26,6 +30,16 @@ class CustomExpansionTileState extends State<CustomExpansionTile> {
_isExpanded = widget.initiallyExpanded; _isExpanded = widget.initiallyExpanded;
} }
@override
void didUpdateWidget(CustomExpansionTile oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.isExpanded != null && widget.isExpanded != _isExpanded) {
setState(() {
_isExpanded = widget.isExpanded!;
});
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Column(
@ -34,6 +48,7 @@ class CustomExpansionTileState extends State<CustomExpansionTile> {
onTap: () { onTap: () {
setState(() { setState(() {
_isExpanded = !_isExpanded; _isExpanded = !_isExpanded;
widget.onExpansionChanged?.call(_isExpanded);
}); });
}, },
child: Row( child: Row(
@ -47,28 +62,22 @@ class CustomExpansionTileState extends State<CustomExpansionTile> {
}); });
}, },
side: WidgetStateBorderSide.resolveWith((states) { side: WidgetStateBorderSide.resolveWith((states) {
if (states.contains(WidgetState.selected)) {
return const BorderSide(color: ColorsManager.grayBorder);
}
return const BorderSide(color: ColorsManager.grayBorder); return const BorderSide(color: ColorsManager.grayBorder);
}), }),
// Customize the color for different checkbox states
fillColor: WidgetStateProperty.resolveWith((states) { fillColor: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.selected)) { 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) if (widget.children != null && widget.children!.isNotEmpty)
Icon( Icon(
_isExpanded _isExpanded
? Icons.keyboard_arrow_down // Upward arrow when expanded ? Icons.keyboard_arrow_down
: Icons : Icons.keyboard_arrow_right,
.keyboard_arrow_right, // Right arrow when collapsed
color: Colors.grey, color: Colors.grey,
size: 16.0, // Reduced icon size size: 16.0, // Reduced icon size
), ),
@ -87,7 +96,6 @@ class CustomExpansionTileState extends State<CustomExpansionTile> {
], ],
), ),
), ),
// Display children if available and expanded
if (_isExpanded && if (_isExpanded &&
widget.children != null && widget.children != null &&
widget.children!.isNotEmpty) widget.children!.isNotEmpty)

View File

@ -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,
),
),
),
),
);
}
}

View File

@ -59,6 +59,7 @@ class MyApp extends StatelessWidget {
bodyLarge: TextStyle(fontSize: 16, color: Colors.white), bodyLarge: TextStyle(fontSize: 16, color: Colors.white),
headlineSmall: TextStyle(color: Colors.black87, fontSize: 18), headlineSmall: TextStyle(color: Colors.black87, fontSize: 18),
headlineMedium: TextStyle(color: Colors.black87, fontSize: 20), headlineMedium: TextStyle(color: Colors.black87, fontSize: 20),
titleMedium: TextStyle(color: Colors.black87, fontSize: 22, fontWeight: FontWeight.bold ),
headlineLarge: TextStyle( headlineLarge: TextStyle(
color: Colors.white, color: Colors.white,
fontSize: 24, fontSize: 24,

View File

@ -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<Widget>? 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,
);
}
}

View File

@ -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<SidebarWidget> {
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,
),
],
),
],
),
),
],
),
);
}
}

View File

@ -5,6 +5,7 @@ import 'package:flutter_svg/flutter_svg.dart';
import 'package:syncrow_web/common/custom_expansion_tile.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/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/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/color_manager.dart';
import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/constants/assets.dart';
@ -18,6 +19,11 @@ class SpaceManagementPageState extends State<SpaceManagementPage> {
List<SpaceData> spaces = []; List<SpaceData> spaces = [];
List<Connection> connections = []; List<Connection> connections = [];
void _handleCommunitySelection(String community) {
// Handle community selection here
print("Selected Community: $community");
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size; Size screenSize = MediaQuery.of(context).size;
@ -33,156 +39,9 @@ class SpaceManagementPageState extends State<SpaceManagementPage> {
Row( Row(
children: [ children: [
// Sidebar for navigation and community list // Sidebar for navigation and community list
Container( SidebarWidget(
width: 300, // Fixed width for sidebar onCommunitySelected: _handleCommunitySelection,
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),
],
),
],
),
),
],
),
),
// Right Side: Community Structure Area // Right Side: Community Structure Area
Expanded( Expanded(
child: Container( child: Container(

View File

@ -41,3 +41,15 @@ BoxDecoration containerDecoration = BoxDecoration(
], ],
color: ColorsManager.boxColor, color: ColorsManager.boxColor,
borderRadius: const BorderRadius.all(Radius.circular(10))); 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),
),
],
);