mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 22:57:21 +00:00
updated tag dialogue selection
This commit is contained in:
185
lib/common/tag_dialog_textfield_dropdown.dart
Normal file
185
lib/common/tag_dialog_textfield_dropdown.dart
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/tag.dart';
|
||||||
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
|
class TagDialogTextfieldDropdown extends StatefulWidget {
|
||||||
|
final List<Tag> items;
|
||||||
|
final ValueChanged<Tag> onSelected;
|
||||||
|
final Tag? initialValue;
|
||||||
|
final String product;
|
||||||
|
|
||||||
|
const TagDialogTextfieldDropdown({
|
||||||
|
Key? key,
|
||||||
|
required this.items,
|
||||||
|
required this.onSelected,
|
||||||
|
this.initialValue,
|
||||||
|
required this.product,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_DialogTextfieldDropdownState createState() => _DialogTextfieldDropdownState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DialogTextfieldDropdownState extends State<TagDialogTextfieldDropdown> {
|
||||||
|
bool _isOpen = false;
|
||||||
|
OverlayEntry? _overlayEntry;
|
||||||
|
final TextEditingController _controller = TextEditingController();
|
||||||
|
final FocusNode _focusNode = FocusNode();
|
||||||
|
List<Tag> _filteredItems = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_controller.text = widget.initialValue?.tag ?? '';
|
||||||
|
|
||||||
|
_filterItems();
|
||||||
|
|
||||||
|
_focusNode.addListener(() {
|
||||||
|
if (!_focusNode.hasFocus) {
|
||||||
|
_closeDropdown();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _filterItems() {
|
||||||
|
setState(() {
|
||||||
|
_filteredItems = widget.items.where((tag) => tag.product?.uuid == widget.product).toList();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _toggleDropdown() {
|
||||||
|
if (_isOpen) {
|
||||||
|
_closeDropdown();
|
||||||
|
} else {
|
||||||
|
_openDropdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _openDropdown() {
|
||||||
|
_overlayEntry = _createOverlayEntry();
|
||||||
|
Overlay.of(context).insert(_overlayEntry!);
|
||||||
|
_isOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _closeDropdown() {
|
||||||
|
if (_isOpen && _overlayEntry != null) {
|
||||||
|
_overlayEntry!.remove();
|
||||||
|
_overlayEntry = null;
|
||||||
|
_isOpen = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
OverlayEntry _createOverlayEntry() {
|
||||||
|
final renderBox = context.findRenderObject() as RenderBox;
|
||||||
|
final size = renderBox.size;
|
||||||
|
final offset = renderBox.localToGlobal(Offset.zero);
|
||||||
|
|
||||||
|
return OverlayEntry(
|
||||||
|
builder: (context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: _closeDropdown,
|
||||||
|
behavior: HitTestBehavior.translucent,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
left: offset.dx,
|
||||||
|
top: offset.dy + size.height,
|
||||||
|
width: size.width,
|
||||||
|
child: Material(
|
||||||
|
elevation: 4.0,
|
||||||
|
child: Container(
|
||||||
|
color: ColorsManager.whiteColors,
|
||||||
|
constraints: const BoxConstraints(maxHeight: 200.0),
|
||||||
|
child: StatefulBuilder(
|
||||||
|
builder: (context, setStateDropdown) {
|
||||||
|
return ListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
itemCount: _filteredItems.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final tag = _filteredItems[index];
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
decoration: const BoxDecoration(
|
||||||
|
border: Border(
|
||||||
|
bottom: BorderSide(
|
||||||
|
color: ColorsManager.lightGrayBorderColor,
|
||||||
|
width: 1.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: ListTile(
|
||||||
|
title: Text(tag.tag ?? '',
|
||||||
|
style: Theme.of(context)
|
||||||
|
.textTheme
|
||||||
|
.bodyMedium
|
||||||
|
?.copyWith(color: ColorsManager.textPrimaryColor)),
|
||||||
|
onTap: () {
|
||||||
|
_controller.text = tag.tag ?? '';
|
||||||
|
widget.onSelected(tag);
|
||||||
|
setState(() {
|
||||||
|
_filteredItems.remove(tag);
|
||||||
|
});
|
||||||
|
_closeDropdown();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
onTap: () => FocusScope.of(context).unfocus(),
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
|
child: Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(color: ColorsManager.transparentColor),
|
||||||
|
borderRadius: BorderRadius.circular(8.0),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
controller: _controller,
|
||||||
|
focusNode: _focusNode,
|
||||||
|
onFieldSubmitted: (value) {
|
||||||
|
final selectedTag = _filteredItems.firstWhere((tag) => tag.tag == value,
|
||||||
|
orElse: () => Tag(tag: value));
|
||||||
|
widget.onSelected(selectedTag);
|
||||||
|
_closeDropdown();
|
||||||
|
},
|
||||||
|
onTapOutside: (event) {
|
||||||
|
widget.onSelected(_filteredItems.firstWhere((tag) => tag.tag == _controller.text,
|
||||||
|
orElse: () => Tag(tag: _controller.text)));
|
||||||
|
_closeDropdown();
|
||||||
|
},
|
||||||
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: 'Enter or Select a tag',
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
GestureDetector(
|
||||||
|
onTap: _toggleDropdown,
|
||||||
|
child: const Icon(Icons.arrow_drop_down),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -60,7 +60,7 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
_cachedSpaceModels = await fetchSpaceModels();
|
_cachedSpaceModels = await fetchSpaceModels();
|
||||||
}
|
}
|
||||||
|
|
||||||
await fetchSpaceModels();
|
await fetchTags();
|
||||||
|
|
||||||
emit(SpaceModelLoaded(
|
emit(SpaceModelLoaded(
|
||||||
communities:
|
communities:
|
||||||
@ -78,7 +78,7 @@ class SpaceManagementBloc extends Bloc<SpaceManagementEvent, SpaceManagementStat
|
|||||||
} else {
|
} else {
|
||||||
_cachedSpaceModels = await fetchSpaceModels();
|
_cachedSpaceModels = await fetchSpaceModels();
|
||||||
}
|
}
|
||||||
await fetchSpaceModels();
|
await fetchTags();
|
||||||
|
|
||||||
emit(SpaceModelLoaded(
|
emit(SpaceModelLoaded(
|
||||||
communities:
|
communities:
|
||||||
|
@ -25,7 +25,7 @@ class Tag extends BaseTag {
|
|||||||
return Tag(
|
return Tag(
|
||||||
uuid: json['uuid'] ?? '',
|
uuid: json['uuid'] ?? '',
|
||||||
internalId: internalId,
|
internalId: internalId,
|
||||||
tag: json['tag'] ?? '',
|
tag: json['name'] ?? '',
|
||||||
product: json['product'] != null
|
product: json['product'] != null
|
||||||
? ProductModel.fromMap(json['product'])
|
? ProductModel.fromMap(json['product'])
|
||||||
: null,
|
: null,
|
||||||
@ -34,6 +34,7 @@ class Tag extends BaseTag {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Tag copyWith({
|
Tag copyWith({
|
||||||
|
String? uuid,
|
||||||
String? tag,
|
String? tag,
|
||||||
ProductModel? product,
|
ProductModel? product,
|
||||||
String? location,
|
String? location,
|
||||||
@ -60,7 +61,7 @@ class Tag extends BaseTag {
|
|||||||
extension TagModelExtensions on Tag {
|
extension TagModelExtensions on Tag {
|
||||||
TagBodyModel toTagBodyModel() {
|
TagBodyModel toTagBodyModel() {
|
||||||
return TagBodyModel()
|
return TagBodyModel()
|
||||||
..uuid = uuid ?? ''
|
..uuid = uuid
|
||||||
..tag = tag ?? ''
|
..tag = tag ?? ''
|
||||||
..productUuid = product?.uuid;
|
..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_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_state.dart';
|
import 'package:syncrow_web/pages/spaces_management/assign_tag_models/bloc/assign_tag_model_state.dart';
|
||||||
|
|
||||||
class AssignTagModelBloc
|
class AssignTagModelBloc extends Bloc<AssignTagModelEvent, AssignTagModelState> {
|
||||||
extends Bloc<AssignTagModelEvent, AssignTagModelState> {
|
|
||||||
final List<String> allTags;
|
|
||||||
final List<Tag> projectTags;
|
final List<Tag> projectTags;
|
||||||
|
|
||||||
AssignTagModelBloc(this.allTags, this.projectTags) : super(AssignTagModelInitial()) {
|
AssignTagModelBloc(this.projectTags) : super(AssignTagModelInitial()) {
|
||||||
on<InitializeTagModels>((event, emit) {
|
on<InitializeTagModels>((event, emit) {
|
||||||
final initialTags = event.initialTags ?? [];
|
final initialTags = event.initialTags ?? [];
|
||||||
|
|
||||||
final existingTagCounts = <String, int>{};
|
final existingTagCounts = <String, int>{};
|
||||||
for (var tag in initialTags) {
|
for (var tag in initialTags) {
|
||||||
if (tag.product != null) {
|
if (tag.product != null) {
|
||||||
existingTagCounts[tag.product!.uuid] =
|
existingTagCounts[tag.product!.uuid] = (existingTagCounts[tag.product!.uuid] ?? 0) + 1;
|
||||||
(existingTagCounts[tag.product!.uuid] ?? 0) + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,17 +22,14 @@ class AssignTagModelBloc
|
|||||||
for (var selectedProduct in event.addedProducts) {
|
for (var selectedProduct in event.addedProducts) {
|
||||||
final existingCount = existingTagCounts[selectedProduct.productId] ?? 0;
|
final existingCount = existingTagCounts[selectedProduct.productId] ?? 0;
|
||||||
|
|
||||||
if (selectedProduct.count == 0 ||
|
if (selectedProduct.count == 0 || selectedProduct.count <= existingCount) {
|
||||||
selectedProduct.count <= existingCount) {
|
tags.addAll(initialTags.where((tag) => tag.product?.uuid == selectedProduct.productId));
|
||||||
tags.addAll(initialTags
|
|
||||||
.where((tag) => tag.product?.uuid == selectedProduct.productId));
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
final missingCount = selectedProduct.count - existingCount;
|
final missingCount = selectedProduct.count - existingCount;
|
||||||
|
|
||||||
tags.addAll(initialTags
|
tags.addAll(initialTags.where((tag) => tag.product?.uuid == selectedProduct.productId));
|
||||||
.where((tag) => tag.product?.uuid == selectedProduct.productId));
|
|
||||||
|
|
||||||
if (missingCount > 0) {
|
if (missingCount > 0) {
|
||||||
tags.addAll(List.generate(
|
tags.addAll(List.generate(
|
||||||
@ -49,7 +43,7 @@ class AssignTagModelBloc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final updatedTags = _calculateAvailableTags(allTags, tags);
|
final updatedTags = _calculateAvailableTags(projectTags, tags);
|
||||||
|
|
||||||
emit(AssignTagModelLoaded(
|
emit(AssignTagModelLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
@ -60,11 +54,20 @@ class AssignTagModelBloc
|
|||||||
|
|
||||||
on<UpdateTag>((event, emit) {
|
on<UpdateTag>((event, emit) {
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
if (currentState is AssignTagModelLoaded &&
|
if (currentState is AssignTagModelLoaded && currentState.tags.isNotEmpty) {
|
||||||
currentState.tags.isNotEmpty) {
|
|
||||||
final tags = List<Tag>.from(currentState.tags);
|
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(
|
emit(AssignTagModelLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
@ -78,15 +81,13 @@ class AssignTagModelBloc
|
|||||||
on<UpdateLocation>((event, emit) {
|
on<UpdateLocation>((event, emit) {
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
|
|
||||||
if (currentState is AssignTagModelLoaded &&
|
if (currentState is AssignTagModelLoaded && currentState.tags.isNotEmpty) {
|
||||||
currentState.tags.isNotEmpty) {
|
|
||||||
final tags = List<Tag>.from(currentState.tags);
|
final tags = List<Tag>.from(currentState.tags);
|
||||||
|
|
||||||
// Use copyWith for immutability
|
// Use copyWith for immutability
|
||||||
tags[event.index] =
|
tags[event.index] = tags[event.index].copyWith(location: event.location);
|
||||||
tags[event.index].copyWith(location: event.location);
|
|
||||||
|
|
||||||
final updatedTags = _calculateAvailableTags(allTags, tags);
|
final updatedTags = _calculateAvailableTags(projectTags, tags);
|
||||||
|
|
||||||
emit(AssignTagModelLoaded(
|
emit(AssignTagModelLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
@ -100,13 +101,12 @@ class AssignTagModelBloc
|
|||||||
on<ValidateTagModels>((event, emit) {
|
on<ValidateTagModels>((event, emit) {
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
|
|
||||||
if (currentState is AssignTagModelLoaded &&
|
if (currentState is AssignTagModelLoaded && currentState.tags.isNotEmpty) {
|
||||||
currentState.tags.isNotEmpty) {
|
|
||||||
final tags = List<Tag>.from(currentState.tags);
|
final tags = List<Tag>.from(currentState.tags);
|
||||||
|
|
||||||
emit(AssignTagModelLoaded(
|
emit(AssignTagModelLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
updatedTags: _calculateAvailableTags(allTags, tags),
|
updatedTags: _calculateAvailableTags(projectTags, tags),
|
||||||
isSaveEnabled: _validateTags(tags),
|
isSaveEnabled: _validateTags(tags),
|
||||||
errorMessage: _getValidationError(tags),
|
errorMessage: _getValidationError(tags),
|
||||||
));
|
));
|
||||||
@ -116,12 +116,10 @@ class AssignTagModelBloc
|
|||||||
on<DeleteTagModel>((event, emit) {
|
on<DeleteTagModel>((event, emit) {
|
||||||
final currentState = state;
|
final currentState = state;
|
||||||
|
|
||||||
if (currentState is AssignTagModelLoaded &&
|
if (currentState is AssignTagModelLoaded && currentState.tags.isNotEmpty) {
|
||||||
currentState.tags.isNotEmpty) {
|
final tags = List<Tag>.from(currentState.tags)..remove(event.tagToDelete);
|
||||||
final tags = List<Tag>.from(currentState.tags)
|
|
||||||
..remove(event.tagToDelete);
|
|
||||||
|
|
||||||
final updatedTags = _calculateAvailableTags(allTags, tags);
|
final updatedTags = _calculateAvailableTags(projectTags, tags);
|
||||||
|
|
||||||
emit(AssignTagModelLoaded(
|
emit(AssignTagModelLoaded(
|
||||||
tags: tags,
|
tags: tags,
|
||||||
@ -143,10 +141,8 @@ class AssignTagModelBloc
|
|||||||
String? _getValidationError(List<Tag> tags) {
|
String? _getValidationError(List<Tag> tags) {
|
||||||
// Check for duplicate tags
|
// Check for duplicate tags
|
||||||
|
|
||||||
final nonEmptyTags = tags
|
final nonEmptyTags =
|
||||||
.map((tag) => tag.tag?.trim() ?? '')
|
tags.map((tag) => tag.tag?.trim() ?? '').where((tag) => tag.isNotEmpty).toList();
|
||||||
.where((tag) => tag.isNotEmpty)
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
final duplicateTags = nonEmptyTags
|
final duplicateTags = nonEmptyTags
|
||||||
.fold<Map<String, int>>({}, (map, tag) {
|
.fold<Map<String, int>>({}, (map, tag) {
|
||||||
@ -165,15 +161,16 @@ class AssignTagModelBloc
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> _calculateAvailableTags(
|
List<Tag> _calculateAvailableTags(List<Tag> allTags, List<Tag> selectedTags) {
|
||||||
List<String> allTags, List<Tag> tags) {
|
final selectedTagSet = selectedTags
|
||||||
final selectedTags = tags
|
|
||||||
.where((tag) => (tag.tag?.trim().isNotEmpty ?? false))
|
.where((tag) => (tag.tag?.trim().isNotEmpty ?? false))
|
||||||
.map((tag) => tag.tag!.trim())
|
.map((tag) => tag.tag!.trim())
|
||||||
.toSet();
|
.toSet();
|
||||||
|
|
||||||
final availableTags =
|
final availableTags = allTags
|
||||||
allTags.where((tag) => !selectedTags.contains(tag.trim())).toList();
|
.where((tag) => tag.tag != null && !selectedTagSet.contains(tag.tag!.trim()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
return availableTags;
|
return availableTags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ class InitializeTagModels extends AssignTagModelEvent {
|
|||||||
|
|
||||||
class UpdateTag extends AssignTagModelEvent {
|
class UpdateTag extends AssignTagModelEvent {
|
||||||
final int index;
|
final int index;
|
||||||
final String tag;
|
final Tag tag;
|
||||||
|
|
||||||
const UpdateTag({required this.index, required this.tag});
|
const UpdateTag({required this.index, required this.tag});
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class AssignTagModelLoaded extends AssignTagModelState {
|
|||||||
final bool isSaveEnabled;
|
final bool isSaveEnabled;
|
||||||
final String? errorMessage;
|
final String? errorMessage;
|
||||||
|
|
||||||
final List<String> updatedTags;
|
final List<Tag> updatedTags;
|
||||||
|
|
||||||
const AssignTagModelLoaded({
|
const AssignTagModelLoaded({
|
||||||
required this.tags,
|
required this.tags,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/common/dialog_dropdown.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/cancel_button.dart';
|
||||||
import 'package:syncrow_web/pages/common/buttons/default_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';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/product_model.dart';
|
||||||
@ -53,12 +53,11 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
print(projectTags);
|
|
||||||
final List<String> locations =
|
final List<String> locations =
|
||||||
(subspaces ?? []).map((subspace) => subspace.subspaceName).toList()..add('Main Space');
|
(subspaces ?? []).map((subspace) => subspace.subspaceName).toList()..add('Main Space');
|
||||||
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (_) => AssignTagModelBloc(allTags ?? [], projectTags)
|
create: (_) => AssignTagModelBloc( projectTags)
|
||||||
..add(InitializeTagModels(
|
..add(InitializeTagModels(
|
||||||
initialTags: initialTags,
|
initialTags: initialTags,
|
||||||
addedProducts: addedProducts,
|
addedProducts: addedProducts,
|
||||||
@ -174,12 +173,14 @@ class AssignTagModelsDialog extends StatelessWidget {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width:
|
width:
|
||||||
double.infinity, // Ensure full width for dropdown
|
double.infinity, // Ensure full width for dropdown
|
||||||
child: DialogTextfieldDropdown(
|
child: TagDialogTextfieldDropdown(
|
||||||
key: ValueKey('dropdown_${Uuid().v4()}_$index'),
|
key: ValueKey(
|
||||||
|
'dropdown_${const Uuid().v4()}_$index'),
|
||||||
|
product: tag.product?.uuid ?? 'Unknown',
|
||||||
items: state.updatedTags,
|
items: state.updatedTags,
|
||||||
initialValue: tag.tag,
|
initialValue: tag,
|
||||||
onSelected: (value) {
|
onSelected: (value) {
|
||||||
controller.text = value;
|
controller.text = value.tag ?? '';
|
||||||
context.read<AssignTagModelBloc>().add(UpdateTag(
|
context.read<AssignTagModelBloc>().add(UpdateTag(
|
||||||
index: index,
|
index: index,
|
||||||
tag: value,
|
tag: value,
|
||||||
|
@ -6,7 +6,7 @@ class TagBodyModel {
|
|||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return {
|
return {
|
||||||
'uuid': uuid,
|
'uuid': uuid,
|
||||||
'tag': tag,
|
'name': tag,
|
||||||
'productUuid': productUuid,
|
'productUuid': productUuid,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user