updated tag dialogue selection

This commit is contained in:
hannathkadher
2025-03-05 22:24:45 +04:00
parent 5cea8eddb3
commit d2ff909bf2
8 changed files with 237 additions and 53 deletions
@@ -60,7 +60,7 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
_cachedSpaceModels = await fetchSpaceModels();
}
await fetchSpaceModels();
await fetchTags();
emit(SpaceModelLoaded(
communities:
@@ -78,7 +78,7 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
} else {
_cachedSpaceModels = await fetchSpaceModels();
}
await fetchSpaceModels();
await fetchTags();
emit(SpaceModelLoaded(
communities:
@@ -25,7 +25,7 @@ class Tag extends BaseTag {
return Tag(
uuid: json['uuid'] ?? '',
internalId: internalId,
tag: json['tag'] ?? '',
tag: json['name'] ?? '',
product: json['product'] != null
? ProductModel.fromMap(json['product'])
: null,
@@ -34,6 +34,7 @@ class Tag extends BaseTag {
@override
Tag copyWith({
String? uuid,
String? tag,
ProductModel? product,
String? location,
@@ -60,7 +61,7 @@ class Tag extends BaseTag {
extension TagModelExtensions on Tag {
TagBodyModel toTagBodyModel() {
return TagBodyModel()
..uuid = uuid ?? ''
..uuid = uuid
..tag = tag ?? ''
..productUuid = product?.uuid;
}
@@ -3,20 +3,17 @@ import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart';
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_event.dart';
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_state.dart';
class AssignTagModelBloc
extends Bloc<AssignTagModelEvent, AssignTagModelState> {
final List<String> allTags;
class AssignTagModelBloc extends Bloc<AssignTagModelEvent, AssignTagModelState> {
final List<Tag> projectTags;
AssignTagModelBloc(this.allTags, this.projectTags) : super(AssignTagModelInitial()) {
AssignTagModelBloc(this.projectTags) : super(AssignTagModelInitial()) {
on<InitializeTagModels>((event, emit) {
final initialTags = event.initialTags ?? [];
final existingTagCounts = <String, int>{};
for (var tag in initialTags) {
if (tag.product != null) {
existingTagCounts[tag.product!.uuid] =
(existingTagCounts[tag.product!.uuid] ?? 0) + 1;
existingTagCounts[tag.product!.uuid] = (existingTagCounts[tag.product!.uuid] ?? 0) + 1;
}
}
@@ -25,17 +22,14 @@ class AssignTagModelBloc
for (var selectedProduct in event.addedProducts) {
final existingCount = existingTagCounts[selectedProduct.productId] ?? 0;
if (selectedProduct.count == 0 ||
selectedProduct.count <= existingCount) {
tags.addAll(initialTags
.where((tag) => tag.product?.uuid == selectedProduct.productId));
if (selectedProduct.count == 0 || selectedProduct.count <= existingCount) {
tags.addAll(initialTags.where((tag) => tag.product?.uuid == selectedProduct.productId));
continue;
}
final missingCount = selectedProduct.count - existingCount;
tags.addAll(initialTags
.where((tag) => tag.product?.uuid == selectedProduct.productId));
tags.addAll(initialTags.where((tag) => tag.product?.uuid == selectedProduct.productId));
if (missingCount > 0) {
tags.addAll(List.generate(
@@ -49,7 +43,7 @@ class AssignTagModelBloc
}
}
final updatedTags = _calculateAvailableTags(allTags, tags);
final updatedTags = _calculateAvailableTags(projectTags, tags);
emit(AssignTagModelLoaded(
tags: tags,
@@ -60,11 +54,20 @@ class AssignTagModelBloc
on<UpdateTag>((event, emit) {
final currentState = state;
if (currentState is AssignTagModelLoaded &&
currentState.tags.isNotEmpty) {
if (currentState is AssignTagModelLoaded && currentState.tags.isNotEmpty) {
final tags = List<Tag>.from(currentState.tags);
tags[event.index] = tags[event.index].copyWith(tag: event.tag);
final updatedTags = _calculateAvailableTags(allTags, tags);
if (event.index < 0 || event.index >= tags.length) return;
tags[event.index] = tags[event.index].copyWith(
tag: event.tag.tag,
uuid: event.tag.uuid,
product: event.tag.product,
internalId: event.tag.internalId,
location: event.tag.location,
);
final updatedTags = _calculateAvailableTags(projectTags ?? [], tags);
emit(AssignTagModelLoaded(
tags: tags,
@@ -78,15 +81,13 @@ class AssignTagModelBloc
on<UpdateLocation>((event, emit) {
final currentState = state;
if (currentState is AssignTagModelLoaded &&
currentState.tags.isNotEmpty) {
if (currentState is AssignTagModelLoaded && currentState.tags.isNotEmpty) {
final tags = List<Tag>.from(currentState.tags);
// Use copyWith for immutability
tags[event.index] =
tags[event.index].copyWith(location: event.location);
tags[event.index] = tags[event.index].copyWith(location: event.location);
final updatedTags = _calculateAvailableTags(allTags, tags);
final updatedTags = _calculateAvailableTags(projectTags, tags);
emit(AssignTagModelLoaded(
tags: tags,
@@ -100,13 +101,12 @@ class AssignTagModelBloc
on<ValidateTagModels>((event, emit) {
final currentState = state;
if (currentState is AssignTagModelLoaded &&
currentState.tags.isNotEmpty) {
if (currentState is AssignTagModelLoaded && currentState.tags.isNotEmpty) {
final tags = List<Tag>.from(currentState.tags);
emit(AssignTagModelLoaded(
tags: tags,
updatedTags: _calculateAvailableTags(allTags, tags),
updatedTags: _calculateAvailableTags(projectTags, tags),
isSaveEnabled: _validateTags(tags),
errorMessage: _getValidationError(tags),
));
@@ -116,12 +116,10 @@ class AssignTagModelBloc
on<DeleteTagModel>((event, emit) {
final currentState = state;
if (currentState is AssignTagModelLoaded &&
currentState.tags.isNotEmpty) {
final tags = List<Tag>.from(currentState.tags)
..remove(event.tagToDelete);
if (currentState is AssignTagModelLoaded && currentState.tags.isNotEmpty) {
final tags = List<Tag>.from(currentState.tags)..remove(event.tagToDelete);
final updatedTags = _calculateAvailableTags(allTags, tags);
final updatedTags = _calculateAvailableTags(projectTags, tags);
emit(AssignTagModelLoaded(
tags: tags,
@@ -143,10 +141,8 @@ class AssignTagModelBloc
String? _getValidationError(List<Tag> tags) {
// Check for duplicate tags
final nonEmptyTags = tags
.map((tag) => tag.tag?.trim() ?? '')
.where((tag) => tag.isNotEmpty)
.toList();
final nonEmptyTags =
tags.map((tag) => tag.tag?.trim() ?? '').where((tag) => tag.isNotEmpty).toList();
final duplicateTags = nonEmptyTags
.fold<Map<String, int>>({}, (map, tag) {
@@ -165,15 +161,16 @@ class AssignTagModelBloc
return null;
}
List<String> _calculateAvailableTags(
List<String> allTags, List<Tag> tags) {
final selectedTags = tags
List<Tag> _calculateAvailableTags(List<Tag> allTags, List<Tag> selectedTags) {
final selectedTagSet = selectedTags
.where((tag) => (tag.tag?.trim().isNotEmpty ?? false))
.map((tag) => tag.tag!.trim())
.toSet();
final availableTags =
allTags.where((tag) => !selectedTags.contains(tag.trim())).toList();
final availableTags = allTags
.where((tag) => tag.tag != null && !selectedTagSet.contains(tag.tag!.trim()))
.toList();
return availableTags;
}
}
@@ -24,7 +24,7 @@ class InitializeTagModels extends AssignTagModelEvent {
class UpdateTag extends AssignTagModelEvent {
final int index;
final String tag;
final Tag tag;
const UpdateTag({required this.index, required this.tag});
@@ -17,7 +17,7 @@ class AssignTagModelLoaded extends AssignTagModelState {
final bool isSaveEnabled;
final String? errorMessage;
final List<String> updatedTags;
final List<Tag> updatedTags;
const AssignTagModelLoaded({
required this.tags,
@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/common/dialog_dropdown.dart';
import 'package:syncrow_web/common/dialog_textfield_dropdown.dart';
import 'package:syncrow_web/common/tag_dialog_textfield_dropdown.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/all_spaces/model/product_model.dart';
@@ -53,12 +53,11 @@ class AssignTagModelsDialog extends StatelessWidget {
@override
Widget build(BuildContext context) {
print(projectTags);
final List<String> locations =
(subspaces ?? []).map((subspace) => subspace.subspaceName).toList()..add('Main Space');
return BlocProvider(
create: (_) => AssignTagModelBloc(allTags ?? [], projectTags)
create: (_) => AssignTagModelBloc( projectTags)
..add(InitializeTagModels(
initialTags: initialTags,
addedProducts: addedProducts,
@@ -174,12 +173,14 @@ class AssignTagModelsDialog extends StatelessWidget {
child: SizedBox(
width:
double.infinity, // Ensure full width for dropdown
child: DialogTextfieldDropdown(
key: ValueKey('dropdown_${Uuid().v4()}_$index'),
child: TagDialogTextfieldDropdown(
key: ValueKey(
'dropdown_${const Uuid().v4()}_$index'),
product: tag.product?.uuid ?? 'Unknown',
items: state.updatedTags,
initialValue: tag.tag,
initialValue: tag,
onSelected: (value) {
controller.text = value;
controller.text = value.tag ?? '';
context.read<AssignTagModelBloc>().add(UpdateTag(
index: index,
tag: value,
@@ -6,7 +6,7 @@ class TagBodyModel {
Map<String, dynamic> toJson() {
return {
'uuid': uuid,
'tag': tag,
'name': tag,
'productUuid': productUuid,
};
}