Refactor AddDeviceTypeWidget and ProductTypeCard Components:

- Replaced ProductTypeCard with ProductsGrid in AddDeviceTypeWidget for improved layout and maintainability.
- Converted ProductTypeCardCounter from StatefulWidget to StatelessWidget, simplifying its implementation.
- Updated ProductTypeCard to accept count and increment/decrement callbacks, enhancing its reusability and interaction.
- Introduced ProductsGrid to manage product display in a grid format, improving UI organization and responsiveness.
This commit is contained in:
Faris Armoush
2025-07-07 10:15:33 +03:00
parent f0bfe085a4
commit df87e41d61
4 changed files with 93 additions and 80 deletions

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/products/data/services/remote_products_service.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/products/data/services/remote_products_service.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/products/presentation/bloc/products_bloc.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/products/presentation/bloc/products_bloc.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/tags/presentation/widgets/product_type_card.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/tags/presentation/widgets/products_grid.dart';
import 'package:syncrow_web/services/api/http_service.dart'; import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
@ -12,13 +12,6 @@ class AddDeviceTypeWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final crossAxisCount = switch (context.screenWidth) {
> 1200 => 8,
> 800 => 5,
_ => 3,
};
return BlocProvider( return BlocProvider(
create: (_) => ProductsBloc(RemoteProductsService(HTTPService())) create: (_) => ProductsBloc(RemoteProductsService(HTTPService()))
..add(const LoadProducts()), ..add(const LoadProducts()),
@ -27,47 +20,15 @@ class AddDeviceTypeWidget extends StatelessWidget {
title: const Text('Add Devices'), title: const Text('Add Devices'),
backgroundColor: ColorsManager.whiteColors, backgroundColor: ColorsManager.whiteColors,
content: BlocBuilder<ProductsBloc, ProductsState>( content: BlocBuilder<ProductsBloc, ProductsState>(
builder: (context, state) { builder: (context, state) => switch (state) {
return switch (state) {
ProductsInitial() => const Center( ProductsInitial() => const Center(
child: CircularProgressIndicator(), child: CircularProgressIndicator(),
), ),
ProductsLoading() => const Center( ProductsLoading() => const Center(
child: CircularProgressIndicator(), child: CircularProgressIndicator(),
), ),
ProductsLoaded(:final products) => SingleChildScrollView( ProductsLoaded(:final products) => ProductsGrid(
child: Container( products: products,
width: size.width * 0.9,
height: size.height * 0.65,
decoration: BoxDecoration(
color: ColorsManager.textFieldGreyColor,
borderRadius: BorderRadius.circular(8),
),
child: Column(
children: [
const SizedBox(height: 16),
Expanded(
child: GridView.builder(
padding: const EdgeInsets.symmetric(
horizontal: 20,
),
shrinkWrap: true,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
mainAxisSpacing: 6,
crossAxisSpacing: 4,
childAspectRatio: 0.8,
),
itemCount: products.length,
itemBuilder: (context, index) => ProductTypeCard(
product: products[index],
),
),
),
],
),
),
), ),
ProductsFailure(:final errorMessage) => Center( ProductsFailure(:final errorMessage) => Center(
child: Text( child: Text(
@ -77,7 +38,6 @@ class AddDeviceTypeWidget extends StatelessWidget {
), ),
), ),
), ),
};
}, },
), ),
), ),

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product.dart';
import 'package:syncrow_web/pages/spaces_management/all_spaces/widgets/counter_widget.dart'; import 'package:syncrow_web/pages/space_management_v2/modules/tags/presentation/widgets/product_type_card_counter.dart';
import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/device_icon_widget.dart'; import 'package:syncrow_web/pages/spaces_management/tag_model/widgets/device_icon_widget.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart';
@ -8,9 +8,16 @@ import 'package:syncrow_web/utils/extension/build_context_x.dart';
class ProductTypeCard extends StatelessWidget { class ProductTypeCard extends StatelessWidget {
const ProductTypeCard({ const ProductTypeCard({
required this.product, required this.product,
required this.count,
required this.onIncrement,
required this.onDecrement,
super.key, super.key,
}); });
final Product product; final Product product;
final int count;
final void Function() onIncrement;
final void Function() onDecrement;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -27,16 +34,12 @@ class ProductTypeCard extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ children: [
Expanded( Expanded(child: DeviceIconWidget(icon: product.icon)),
child: DeviceIconWidget(
icon: product.icon,
),
),
_buildName(context, product.name), _buildName(context, product.name),
CounterWidget( ProductTypeCardCounter(
isCreate: false, onIncrement: onIncrement,
initialCount: 0, onDecrement: onDecrement,
onCountChanged: (newCount) {}, count: count,
), ),
const SizedBox(height: 4), const SizedBox(height: 4),
], ],

View File

@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class ProductTypeCardCounter extends StatefulWidget { class ProductTypeCardCounter extends StatelessWidget {
const ProductTypeCardCounter({ const ProductTypeCardCounter({
super.key, super.key,
required this.onIncrement, required this.onIncrement,
@ -10,19 +11,11 @@ class ProductTypeCardCounter extends StatefulWidget {
}); });
final int count; final int count;
final void Function() onIncrement; final void Function() onIncrement;
final void Function() onDecrement; final void Function() onDecrement;
@override
State<ProductTypeCardCounter> createState() => _ProductTypeCardCounterState();
}
class _ProductTypeCardCounterState extends State<ProductTypeCardCounter> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = Theme.of(context);
return Container( return Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -35,15 +28,15 @@ class _ProductTypeCardCounterState extends State<ProductTypeCardCounter> {
children: [ children: [
_buildCounterButton( _buildCounterButton(
Icons.remove, Icons.remove,
widget.onDecrement, onDecrement,
), ),
Text( Text(
widget.count.toString(), count.toString(),
style: theme.textTheme.bodyLarge?.copyWith( style: context.textTheme.bodyLarge?.copyWith(
color: ColorsManager.spaceColor, color: ColorsManager.spaceColor,
), ),
), ),
_buildCounterButton(Icons.add, widget.onIncrement), _buildCounterButton(Icons.add, onIncrement),
], ],
), ),
); );

View File

@ -0,0 +1,57 @@
import 'package:flutter/material.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/products/domain/models/product.dart';
import 'package:syncrow_web/pages/space_management_v2/modules/tags/presentation/widgets/product_type_card.dart';
import 'package:syncrow_web/utils/color_manager.dart';
import 'package:syncrow_web/utils/extension/build_context_x.dart';
class ProductsGrid extends StatelessWidget {
const ProductsGrid({required this.products, super.key});
final List<Product> products;
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size;
final crossAxisCount = switch (context.screenWidth) {
> 1200 => 8,
> 800 => 5,
_ => 3,
};
return SingleChildScrollView(
child: Container(
width: size.width * 0.9,
height: size.height * 0.65,
decoration: BoxDecoration(
color: ColorsManager.textFieldGreyColor,
borderRadius: BorderRadius.circular(8),
),
child: Column(
children: [
const SizedBox(height: 16),
Expanded(
child: GridView.builder(
padding: const EdgeInsets.symmetric(
horizontal: 20,
),
shrinkWrap: true,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: crossAxisCount,
mainAxisSpacing: 6,
crossAxisSpacing: 4,
childAspectRatio: 0.8,
),
itemCount: products.length,
itemBuilder: (context, index) => ProductTypeCard(
product: products[index],
count: 0,
onIncrement: () {},
onDecrement: () {},
),
),
),
],
),
),
);
}
}