mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
updated grid view
This commit is contained in:
@ -1,38 +1,75 @@
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_state.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_type_model_event.dart';
|
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_type_model_event.dart';
|
||||||
|
|
||||||
class AddDeviceTypeModelBloc
|
class AddDeviceTypeModelBloc
|
||||||
extends Bloc<AddDeviceTypeModelEvent, List<SelectedProduct>> {
|
extends Bloc<AddDeviceTypeModelEvent, AddDeviceModelState> {
|
||||||
AddDeviceTypeModelBloc(List<SelectedProduct> initialProducts)
|
AddDeviceTypeModelBloc() : super(AddDeviceModelInitial()) {
|
||||||
: super(initialProducts) {
|
on<InitializeDeviceTypeModel>(_onInitializeTagModels);
|
||||||
on<UpdateProductCountEvent>(_onUpdateProductCount);
|
on<UpdateProductCountEvent>(_onUpdateProductCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onUpdateProductCount(
|
void _onInitializeTagModels(
|
||||||
UpdateProductCountEvent event, Emitter<List<SelectedProduct>> emit) {
|
InitializeDeviceTypeModel event, Emitter<AddDeviceModelState> emit) {
|
||||||
final existingProduct = state.firstWhere(
|
emit(AddDeviceModelLoaded(
|
||||||
(p) => p.productId == event.productId,
|
selectedProducts: event.addedProducts,
|
||||||
orElse: () => SelectedProduct(productId: event.productId, count: 0,productName: event.productName,product: event.product ),
|
initialTag: event.initialTags,
|
||||||
);
|
));
|
||||||
|
}
|
||||||
|
|
||||||
if (event.count > 0) {
|
void _onUpdateProductCount(
|
||||||
if (!state.contains(existingProduct)) {
|
UpdateProductCountEvent event, Emitter<AddDeviceModelState> emit) {
|
||||||
emit([
|
final currentState = state;
|
||||||
...state,
|
|
||||||
SelectedProduct(productId: event.productId, count: event.count, productName: event.productName, product: event.product)
|
if (currentState is AddDeviceModelLoaded) {
|
||||||
]);
|
final existingProduct = currentState.selectedProducts.firstWhere(
|
||||||
|
(p) => p.productId == event.productId,
|
||||||
|
orElse: () => SelectedProduct(
|
||||||
|
productId: event.productId,
|
||||||
|
count: 0,
|
||||||
|
productName: event.productName,
|
||||||
|
product: event.product,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
List<SelectedProduct> updatedProducts;
|
||||||
|
|
||||||
|
if (event.count > 0) {
|
||||||
|
if (!currentState.selectedProducts.contains(existingProduct)) {
|
||||||
|
updatedProducts = [
|
||||||
|
...currentState.selectedProducts,
|
||||||
|
SelectedProduct(
|
||||||
|
productId: event.productId,
|
||||||
|
count: event.count,
|
||||||
|
productName: event.productName,
|
||||||
|
product: event.product,
|
||||||
|
),
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
updatedProducts = currentState.selectedProducts.map((p) {
|
||||||
|
if (p.productId == event.productId) {
|
||||||
|
return SelectedProduct(
|
||||||
|
productId: p.productId,
|
||||||
|
count: event.count,
|
||||||
|
productName: p.productName,
|
||||||
|
product: p.product,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
final updatedList = state.map((p) {
|
// Remove the product if the count is 0
|
||||||
if (p.productId == event.productId) {
|
updatedProducts = currentState.selectedProducts
|
||||||
return SelectedProduct(productId: p.productId, count: event.count, productName: p.productName,product: p.product);
|
.where((p) => p.productId != event.productId)
|
||||||
}
|
.toList();
|
||||||
return p;
|
|
||||||
}).toList();
|
|
||||||
emit(updatedList);
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
emit(state.where((p) => p.productId != event.productId).toList());
|
// Emit the updated state
|
||||||
|
emit(AddDeviceModelLoaded(
|
||||||
|
selectedProducts: updatedProducts,
|
||||||
|
initialTag: currentState.initialTag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
import 'package:equatable/equatable.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
||||||
|
|
||||||
|
abstract class AddDeviceModelState extends Equatable {
|
||||||
|
const AddDeviceModelState();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddDeviceModelInitial extends AddDeviceModelState {}
|
||||||
|
|
||||||
|
class AddDeviceModelLoading extends AddDeviceModelState {}
|
||||||
|
|
||||||
|
class AddDeviceModelLoaded extends AddDeviceModelState {
|
||||||
|
final List<SelectedProduct> selectedProducts;
|
||||||
|
final List<TagModel> initialTag;
|
||||||
|
|
||||||
|
const AddDeviceModelLoaded({
|
||||||
|
required this.selectedProducts,
|
||||||
|
required this.initialTag,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [selectedProducts, initialTag];
|
||||||
|
}
|
||||||
|
|
||||||
|
class AddDeviceModelError extends AddDeviceModelState {
|
||||||
|
final String errorMessage;
|
||||||
|
|
||||||
|
const AddDeviceModelError(this.errorMessage);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [errorMessage];
|
||||||
|
}
|
@ -1,11 +1,16 @@
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.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';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
||||||
|
|
||||||
abstract class AddDeviceTypeModelEvent extends Equatable {
|
abstract class AddDeviceTypeModelEvent extends Equatable {
|
||||||
|
const AddDeviceTypeModelEvent();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [];
|
List<Object> get props => [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class UpdateProductCountEvent extends AddDeviceTypeModelEvent {
|
class UpdateProductCountEvent extends AddDeviceTypeModelEvent {
|
||||||
final String productId;
|
final String productId;
|
||||||
final int count;
|
final int count;
|
||||||
@ -17,3 +22,17 @@ class UpdateProductCountEvent extends AddDeviceTypeModelEvent {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [productId, count];
|
List<Object> get props => [productId, count];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class InitializeDeviceTypeModel extends AddDeviceTypeModelEvent {
|
||||||
|
final List<TagModel> initialTags;
|
||||||
|
final List<SelectedProduct> addedProducts;
|
||||||
|
|
||||||
|
const InitializeDeviceTypeModel({
|
||||||
|
this.initialTags = const [],
|
||||||
|
required this.addedProducts,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [initialTags, addedProducts];
|
||||||
|
}
|
||||||
|
@ -9,6 +9,8 @@ import 'package:syncrow_web/pages/spaces_management/space_model/models/subspace_
|
|||||||
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/models/tag_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart';
|
import 'package:syncrow_web/pages/spaces_management/space_model/widgets/dialog/create_space_model_dialog.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_state.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_type_model_event.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/action_button_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/action_button_widget.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/scrollable_grid_view_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/scrollable_grid_view_widget.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
@ -21,14 +23,15 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
final List<String>? allTags;
|
final List<String>? allTags;
|
||||||
final String spaceName;
|
final String spaceName;
|
||||||
|
|
||||||
const AddDeviceTypeModelWidget(
|
const AddDeviceTypeModelWidget({
|
||||||
{super.key,
|
super.key,
|
||||||
this.products,
|
this.products,
|
||||||
this.initialSelectedProducts,
|
this.initialSelectedProducts,
|
||||||
this.subspaces,
|
this.subspaces,
|
||||||
this.allTags,
|
this.allTags,
|
||||||
this.spaceTagModels,
|
this.spaceTagModels,
|
||||||
required this.spaceName});
|
required this.spaceName,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -40,91 +43,108 @@ class AddDeviceTypeModelWidget extends StatelessWidget {
|
|||||||
: 3;
|
: 3;
|
||||||
|
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (_) => AddDeviceTypeModelBloc(initialSelectedProducts ?? []),
|
create: (_) => AddDeviceTypeModelBloc()
|
||||||
child: Builder(
|
..add(InitializeDeviceTypeModel(
|
||||||
builder: (context) => AlertDialog(
|
initialTags: spaceTagModels ?? [],
|
||||||
title: const Text('Add Devices'),
|
addedProducts: initialSelectedProducts ?? [],
|
||||||
backgroundColor: ColorsManager.whiteColors,
|
)),
|
||||||
content: SingleChildScrollView(
|
child: Builder(
|
||||||
child: Container(
|
builder: (context) => AlertDialog(
|
||||||
width: size.width * 0.9,
|
title: const Text('Add Devices'),
|
||||||
height: size.height * 0.65,
|
backgroundColor: ColorsManager.whiteColors,
|
||||||
color: ColorsManager.textFieldGreyColor,
|
content: BlocBuilder<AddDeviceTypeModelBloc, AddDeviceModelState>(
|
||||||
child: Column(
|
builder: (context, state) {
|
||||||
children: [
|
if (state is AddDeviceModelLoading) {
|
||||||
const SizedBox(height: 16),
|
return const Center(child: CircularProgressIndicator());
|
||||||
Expanded(
|
}
|
||||||
child: Padding(
|
if (state is AddDeviceModelLoaded) {
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
return SingleChildScrollView(
|
||||||
child: ScrollableGridViewWidget(
|
child: Container(
|
||||||
products: products, crossAxisCount: crossAxisCount),
|
width: size.width * 0.9,
|
||||||
),
|
height: size.height * 0.65,
|
||||||
|
color: ColorsManager.textFieldGreyColor,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||||
|
child: ScrollableGridViewWidget(
|
||||||
|
products: products,
|
||||||
|
crossAxisCount: crossAxisCount,
|
||||||
|
initialProductCounts: state.selectedProducts,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return const SizedBox();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
CancelButton(
|
||||||
|
label: 'Cancel',
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
await showDialog(
|
||||||
|
barrierDismissible: false,
|
||||||
|
context: context,
|
||||||
|
builder: (context) => CreateSpaceModelDialog(
|
||||||
|
products: products,
|
||||||
|
allTags: allTags,
|
||||||
|
spaceModel: SpaceTemplateModel(
|
||||||
|
modelName: spaceName,
|
||||||
|
subspaceModels: subspaces,
|
||||||
|
tags: spaceTagModels,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
),
|
ActionButton(
|
||||||
),
|
label: 'Continue',
|
||||||
actions: [
|
backgroundColor: ColorsManager.secondaryColor,
|
||||||
Row(
|
foregroundColor: ColorsManager.whiteColors,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
onPressed: () async {
|
||||||
children: [
|
final state = context.read<AddDeviceTypeModelBloc>().state;
|
||||||
CancelButton(
|
if (state is AddDeviceModelLoaded &&
|
||||||
label: 'Cancel',
|
state.selectedProducts.isNotEmpty) {
|
||||||
onPressed: () async {
|
final initialTags = generateInitialTags(
|
||||||
Navigator.of(context).pop();
|
spaceTagModels: spaceTagModels,
|
||||||
await showDialog(
|
subspaces: subspaces,
|
||||||
|
);
|
||||||
|
|
||||||
|
final dialogTitle = initialTags.isNotEmpty
|
||||||
|
? 'Edit Device'
|
||||||
|
: 'Assign Tags';
|
||||||
|
await showDialog<bool>(
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => CreateSpaceModelDialog(
|
builder: (context) => AssignTagModelsDialog(
|
||||||
products: products,
|
products: products,
|
||||||
allTags: allTags,
|
|
||||||
spaceModel: SpaceTemplateModel(
|
|
||||||
modelName: spaceName,
|
|
||||||
subspaceModels: subspaces,
|
|
||||||
tags: spaceTagModels,
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
ActionButton(
|
|
||||||
label: 'Continue',
|
|
||||||
backgroundColor: ColorsManager.secondaryColor,
|
|
||||||
foregroundColor: ColorsManager.whiteColors,
|
|
||||||
onPressed: () async {
|
|
||||||
final currentState =
|
|
||||||
context.read<AddDeviceTypeModelBloc>().state;
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
|
|
||||||
if (currentState.isNotEmpty) {
|
|
||||||
final initialTags = generateInitialTags(
|
|
||||||
spaceTagModels: spaceTagModels,
|
|
||||||
subspaces: subspaces,
|
subspaces: subspaces,
|
||||||
);
|
addedProducts: state.selectedProducts,
|
||||||
|
allTags: allTags,
|
||||||
final dialogTitle = initialTags.isNotEmpty
|
spaceName: spaceName,
|
||||||
? 'Edit Device'
|
initialTags: state.initialTag,
|
||||||
: 'Assign Tags';
|
title: dialogTitle,
|
||||||
await showDialog<bool>(
|
),
|
||||||
barrierDismissible: false,
|
);
|
||||||
context: context,
|
}
|
||||||
builder: (context) => AssignTagModelsDialog(
|
},
|
||||||
products: products,
|
),
|
||||||
subspaces: subspaces,
|
],
|
||||||
addedProducts: currentState,
|
),
|
||||||
allTags: allTags,
|
],
|
||||||
spaceName: spaceName,
|
),
|
||||||
initialTags: initialTags,
|
),
|
||||||
title: dialogTitle,
|
);
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TagModel> generateInitialTags({
|
List<TagModel> generateInitialTags({
|
||||||
|
@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.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';
|
||||||
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
import 'package:syncrow_web/pages/spaces_management/all_spaces/model/selected_product_model.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_bloc.dart';
|
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_bloc.dart';
|
||||||
|
import 'package:syncrow_web/pages/spaces_management/tag_model/bloc/add_device_model_state.dart';
|
||||||
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/device_type_tile_widget.dart';
|
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/device_type_tile_widget.dart';
|
||||||
|
|
||||||
class ScrollableGridViewWidget extends StatelessWidget {
|
class ScrollableGridViewWidget extends StatelessWidget {
|
||||||
@ -24,8 +25,12 @@ class ScrollableGridViewWidget extends StatelessWidget {
|
|||||||
return Scrollbar(
|
return Scrollbar(
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
thumbVisibility: true,
|
thumbVisibility: true,
|
||||||
child: BlocBuilder<AddDeviceTypeModelBloc, List<SelectedProduct>>(
|
child: BlocBuilder<AddDeviceTypeModelBloc, AddDeviceModelState>(
|
||||||
builder: (context, productCounts) {
|
builder: (context, state) {
|
||||||
|
final productCounts = state is AddDeviceModelLoaded
|
||||||
|
? state.selectedProducts
|
||||||
|
: <SelectedProduct>[];
|
||||||
|
|
||||||
return GridView.builder(
|
return GridView.builder(
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
|
Reference in New Issue
Block a user