From 056e7372e08ff3777ead092f27ba0cac5255f4ae Mon Sep 17 00:00:00 2001 From: Rafeek Alkhoudare Date: Tue, 27 May 2025 01:15:30 -0500 Subject: [PATCH] use assign table as widget --- .../assign_tag/views/assign_tag_dialog.dart | 178 +++--------- .../views/assign_tag_models_dialog.dart | 29 ++ .../widgets/assign_tags_tables_widget.dart | 275 ++++++++---------- 3 files changed, 201 insertions(+), 281 deletions(-) diff --git a/lib/pages/spaces_management/assign_tag/views/assign_tag_dialog.dart b/lib/pages/spaces_management/assign_tag/views/assign_tag_dialog.dart index fd1454e5..a244d235 100644 --- a/lib/pages/spaces_management/assign_tag/views/assign_tag_dialog.dart +++ b/lib/pages/spaces_management/assign_tag/views/assign_tag_dialog.dart @@ -12,6 +12,7 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_bloc.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_event.dart'; import 'package:syncrow_web/pages/spaces_management/assign_tag/bloc/assign_tag_state.dart'; +import 'package:syncrow_web/pages/spaces_management/assign_tag_models/views/widgets/assign_tags_tables_widget.dart'; import 'package:syncrow_web/pages/spaces_management/helper/tag_helper.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:uuid/uuid.dart'; @@ -44,8 +45,10 @@ class AssignTagDialog extends StatelessWidget { @override Widget build(BuildContext context) { - final List locations = - (subspaces ?? []).map((subspace) => subspace.subspaceName).toList()..add('Main Space'); + final List locations = (subspaces ?? []) + .map((subspace) => subspace.subspaceName) + .toList() + ..add('Main Space'); return BlocProvider( create: (_) => AssignTagBloc(projectTags) @@ -67,131 +70,31 @@ class AssignTagDialog extends StatelessWidget { content: SingleChildScrollView( child: Column( children: [ - ClipRRect( - borderRadius: BorderRadius.circular(20), - child: DataTable( - headingRowColor: WidgetStateProperty.all(ColorsManager.dataHeaderGrey), - key: ValueKey(state.tags.length), - border: TableBorder.all( - color: ColorsManager.dataHeaderGrey, - width: 1, - borderRadius: BorderRadius.circular(20), - ), - columns: [ - DataColumn( - label: Text('#', style: Theme.of(context).textTheme.bodyMedium)), - DataColumn( - label: Text('Device', style: Theme.of(context).textTheme.bodyMedium)), - DataColumn( - numeric: false, - label: Text('Tag', style: Theme.of(context).textTheme.bodyMedium)), - DataColumn( - label: - Text('Location', style: Theme.of(context).textTheme.bodyMedium)), - ], - rows: state.tags.isEmpty - ? [ - DataRow(cells: [ - DataCell( - Center( - child: Text('No Data Available', - style: Theme.of(context).textTheme.bodyMedium?.copyWith( - color: ColorsManager.lightGrayColor, - )), - ), - ), - const DataCell(SizedBox()), - const DataCell(SizedBox()), - const DataCell(SizedBox()), - ]) - ] - : List.generate(state.tags.length, (index) { - final tag = state.tags[index]; - final controller = controllers[index]; + AssignTagsTable( + controllers: controllers, + locations: locations, + tags: state.tags, + updatedTags: state.updatedTags, + onDeleteDevice: ({required index, required tag}) { + context + .read() + .add(DeleteTag(tagToDelete: tag, tags: state.tags)); - return DataRow( - cells: [ - DataCell(Text((index + 1).toString())), - DataCell( - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - tag.product?.name ?? 'Unknown', - overflow: TextOverflow.ellipsis, - )), - const SizedBox(width: 10), - Container( - width: 20.0, - height: 20.0, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: ColorsManager.lightGrayColor, - width: 1.0, - ), - ), - child: IconButton( - icon: const Icon( - Icons.close, - color: ColorsManager.lightGreyColor, - size: 16, - ), - onPressed: () { - context.read().add( - DeleteTag(tagToDelete: tag, tags: state.tags)); - - controllers.removeAt(index); - }, - tooltip: 'Delete Tag', - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - ), - ), - ], - ), - ), - DataCell( - Container( - alignment: - Alignment.centerLeft, // Align cell content to the left - child: SizedBox( - width: double.infinity, - child: TagDialogTextfieldDropdown( - key: ValueKey('dropdown_${const Uuid().v4()}_$index'), - items: state.updatedTags, - product: tag.product?.uuid ?? 'Unknown', - initialValue: tag, - onSelected: (value) { - controller.text = value.tag ?? ''; - context.read().add(UpdateTagEvent( - index: index, - tag: value, - )); - }, - ), - ), - ), - ), - DataCell( - SizedBox( - width: double.infinity, - child: DialogDropdown( - items: locations, - selectedValue: tag.location ?? 'Main Space', - onSelected: (value) { - context.read().add(UpdateLocation( - index: index, - location: value, - )); - }, - )), - ), - ], - ); - }), - ), + controllers.removeAt(index); + }, + onTagDropDownSelected: ({required index, required tag}) { + context.read().add(UpdateTagEvent( + index: index, + tag: tag, + )); + }, + onLocationDropDownSelected: ( + {required index, required location}) { + context.read().add(UpdateLocation( + index: index, + location: location, + )); + }, ), if (state.errorMessage != null) Text(state.errorMessage!, @@ -213,11 +116,13 @@ class AssignTagDialog extends StatelessWidget { label: 'Add New Device', onPressed: () async { final updatedTags = List.from(state.tags); - final result = TagHelper.processTags(updatedTags, subspaces); + final result = + TagHelper.processTags(updatedTags, subspaces); - final processedTags = result['updatedTags'] as List; - final processedSubspaces = - List.from(result['subspaces'] as List); + final processedTags = + result['updatedTags'] as List; + final processedSubspaces = List.from( + result['subspaces'] as List); Navigator.of(context).pop(); @@ -227,8 +132,8 @@ class AssignTagDialog extends StatelessWidget { products: products, subspaces: processedSubspaces, projectTags: projectTags, - initialSelectedProducts: - TagHelper.createInitialSelectedProductsForTags( + initialSelectedProducts: TagHelper + .createInitialSelectedProductsForTags( processedTags, processedSubspaces), spaceName: spaceName, spaceTags: processedTags, @@ -252,11 +157,14 @@ class AssignTagDialog extends StatelessWidget { onPressed: state.isSaveEnabled ? () async { final updatedTags = List.from(state.tags); - final result = TagHelper.processTags(updatedTags, subspaces); + final result = TagHelper.processTags( + updatedTags, subspaces); - final processedTags = result['updatedTags'] as List; + final processedTags = + result['updatedTags'] as List; final processedSubspaces = - List.from(result['subspaces'] as List); + List.from( + result['subspaces'] as List); onSave?.call(processedTags, processedSubspaces); Navigator.of(context).pop(); } diff --git a/lib/pages/spaces_management/assign_tag_models/views/assign_tag_models_dialog.dart b/lib/pages/spaces_management/assign_tag_models/views/assign_tag_models_dialog.dart index 6343782c..57ed93df 100644 --- a/lib/pages/spaces_management/assign_tag_models/views/assign_tag_models_dialog.dart +++ b/lib/pages/spaces_management/assign_tag_models/views/assign_tag_models_dialog.dart @@ -78,6 +78,35 @@ class AssignTagModelsDialog extends StatelessWidget { AssignTagsTable( controllers: controllers, locations: locations, + tags: state.tags, + updatedTags: state.updatedTags, + onDeleteDevice: ({required index, required tag}) { + context + .read() + .add(DeleteTagModel( + tagToDelete: tag, + tags: state.tags, + )); + controllers.removeAt(index); + }, + onTagDropDownSelected: ( + {required index, required tag}) { + context.read().add( + UpdateTag( + index: index, + tag: tag, + ), + ); + }, + onLocationDropDownSelected: ( + {required index, required location}) { + context.read().add( + UpdateLocation( + index: index, + location: location, + ), + ); + }, ), if (state.errorMessage != null) Text(state.errorMessage!, diff --git a/lib/pages/spaces_management/assign_tag_models/views/widgets/assign_tags_tables_widget.dart b/lib/pages/spaces_management/assign_tag_models/views/widgets/assign_tags_tables_widget.dart index eaddc26c..0e17a0d7 100644 --- a/lib/pages/spaces_management/assign_tag_models/views/widgets/assign_tags_tables_widget.dart +++ b/lib/pages/spaces_management/assign_tag_models/views/widgets/assign_tags_tables_widget.dart @@ -1,172 +1,155 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart'; import 'package:uuid/uuid.dart'; import '../../../../../common/dialog_dropdown.dart'; import '../../../../../common/tag_dialog_textfield_dropdown.dart'; import '../../../../../utils/color_manager.dart'; -import '../../bloc/assign_tag_model_bloc.dart'; -import '../../bloc/assign_tag_model_event.dart'; -import '../../bloc/assign_tag_model_state.dart'; class AssignTagsTable extends StatelessWidget { const AssignTagsTable({ super.key, required this.controllers, required this.locations, + required this.tags, + required this.updatedTags, + required this.onDeleteDevice, + required this.onLocationDropDownSelected, + required this.onTagDropDownSelected, }); - + final void Function({required Tag tag, required int index}) + onTagDropDownSelected; + final void Function({required String location, required int index}) + onLocationDropDownSelected; + final void Function({required Tag tag, required int index}) onDeleteDevice; + final List tags; + final List updatedTags; final List controllers; final List locations; @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - if (state is AssignTagModelLoaded) { - return ClipRRect( - borderRadius: BorderRadius.circular(20), - child: DataTable( - headingRowColor: - WidgetStateProperty.all(ColorsManager.dataHeaderGrey), - key: ValueKey(state.tags.length), - border: TableBorder.all( - color: ColorsManager.dataHeaderGrey, - width: 1, - borderRadius: BorderRadius.circular(20), - ), - columns: [ - DataColumn( - label: Text('#', - style: Theme.of(context).textTheme.bodyMedium)), - DataColumn( - label: Text('Device', - style: Theme.of(context).textTheme.bodyMedium)), - DataColumn( - numeric: false, - label: Text('Tag', - style: Theme.of(context).textTheme.bodyMedium)), - DataColumn( - label: Text('Location', - style: Theme.of(context).textTheme.bodyMedium)), - ], - rows: state.tags.isEmpty - ? [ - DataRow(cells: [ - DataCell( - Center( - child: Text('No Devices Available', - style: Theme.of(context) - .textTheme - .bodyMedium - ?.copyWith( - color: ColorsManager.lightGrayColor, - )), - ), - ), - const DataCell(SizedBox()), - const DataCell(SizedBox()), - const DataCell(SizedBox()), - ]) - ] - : List.generate(state.tags.length, (index) { - final tag = state.tags[index]; - final controller = controllers[index]; + return ClipRRect( + borderRadius: BorderRadius.circular(20), + child: DataTable( + headingRowColor: WidgetStateProperty.all(ColorsManager.dataHeaderGrey), + key: ValueKey(tags.length), + border: TableBorder.all( + color: ColorsManager.dataHeaderGrey, + width: 1, + borderRadius: BorderRadius.circular(20), + ), + columns: [ + DataColumn( + label: Text('#', style: Theme.of(context).textTheme.bodyMedium)), + DataColumn( + label: Text('Device', + style: Theme.of(context).textTheme.bodyMedium)), + DataColumn( + numeric: false, + label: + Text('Tag', style: Theme.of(context).textTheme.bodyMedium)), + DataColumn( + label: Text('Location', + style: Theme.of(context).textTheme.bodyMedium)), + ], + rows: tags.isEmpty + ? [ + DataRow(cells: [ + DataCell( + Center( + child: Text('No Devices Available', + style: + Theme.of(context).textTheme.bodyMedium?.copyWith( + color: ColorsManager.lightGrayColor, + )), + ), + ), + const DataCell(SizedBox()), + const DataCell(SizedBox()), + const DataCell(SizedBox()), + ]) + ] + : List.generate(tags.length, (index) { + final tag = tags[index]; + final controller = controllers[index]; - return DataRow( - cells: [ - DataCell(Text((index + 1).toString())), - DataCell( - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: Text( - tag.product?.name ?? 'Unknown', - overflow: TextOverflow.ellipsis, - )), - const SizedBox(width: 10), - Container( - width: 20.0, - height: 20.0, - decoration: BoxDecoration( - shape: BoxShape.circle, - border: Border.all( - color: ColorsManager.lightGrayColor, - width: 1.0, - ), - ), - child: IconButton( - icon: const Icon( - Icons.close, - color: ColorsManager.lightGreyColor, - size: 16, - ), - onPressed: () { - context.read().add( - DeleteTagModel( - tagToDelete: tag, - tags: state.tags)); - controllers.removeAt(index); - }, - tooltip: 'Delete Tag', - padding: EdgeInsets.zero, - constraints: const BoxConstraints(), - ), - ), - ], - ), - ), - DataCell( - Container( - alignment: Alignment - .centerLeft, // Align cell content to the left - child: SizedBox( - width: double.infinity, - child: TagDialogTextfieldDropdown( - key: ValueKey( - 'dropdown_${const Uuid().v4()}_$index'), - product: tag.product?.uuid ?? 'Unknown', - items: state.updatedTags, - initialValue: tag, - onSelected: (value) { - controller.text = value.tag ?? ''; - context - .read() - .add(UpdateTag( - index: index, - tag: value, - )); - }, - ), + return DataRow( + cells: [ + DataCell(Text((index + 1).toString())), + DataCell( + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Text( + tag.product?.name ?? 'Unknown', + overflow: TextOverflow.ellipsis, + )), + const SizedBox(width: 10), + Container( + width: 20.0, + height: 20.0, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all( + color: ColorsManager.lightGrayColor, + width: 1.0, ), ), - ), - DataCell( - SizedBox( - width: double.infinity, - child: DialogDropdown( - items: locations, - selectedValue: tag.location ?? 'Main Space', - onSelected: (value) { - context - .read() - .add(UpdateLocation( - index: index, - location: value, - )); - }, - )), + child: IconButton( + icon: const Icon( + Icons.close, + color: ColorsManager.lightGreyColor, + size: 16, + ), + onPressed: () { + onDeleteDevice(tag: tag, index: index); + }, + tooltip: 'Delete Tag', + padding: EdgeInsets.zero, + constraints: const BoxConstraints(), + ), ), ], - ); - }), - ), - ); - } else { - return const SizedBox(); - } - }, + ), + ), + DataCell( + Container( + alignment: Alignment + .centerLeft, // Align cell content to the left + child: SizedBox( + width: double.infinity, + child: TagDialogTextfieldDropdown( + key: ValueKey( + 'dropdown_${const Uuid().v4()}_$index'), + product: tag.product?.uuid ?? 'Unknown', + items: updatedTags, + initialValue: tag, + onSelected: (value) { + controller.text = value.tag ?? ''; + onTagDropDownSelected(tag: value, index: index); + }, + ), + ), + ), + ), + DataCell( + SizedBox( + width: double.infinity, + child: DialogDropdown( + items: locations, + selectedValue: tag.location ?? 'Main Space', + onSelected: (value) { + onLocationDropDownSelected( + location: value, index: index); + }, + )), + ), + ], + ); + }), + ), ); } }