2025-08-20 13:52:49 +07:00

162 lines
5.3 KiB
Dart

import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:line_icons/line_icons.dart';
import '../../../application/customer/customer_loader/customer_loader_bloc.dart';
import '../../../common/extension/extension.dart';
import '../../../common/theme/theme.dart';
import '../../../domain/customer/customer.dart';
import '../../../injection.dart';
import '../../components/appbar/appbar.dart';
import '../../components/button/button.dart';
import 'widgets/customer_card.dart';
import 'widgets/customer_tile.dart';
@RoutePage()
class CustomerPage extends StatefulWidget implements AutoRouteWrapper {
const CustomerPage({super.key});
@override
State<CustomerPage> createState() => _CustomerPageState();
@override
Widget wrappedRoute(BuildContext context) => BlocProvider(
create: (context) =>
getIt<CustomerLoaderBloc>()
..add(CustomerLoaderEvent.fetched(isRefresh: true)),
child: this,
);
}
class _CustomerPageState extends State<CustomerPage>
with TickerProviderStateMixin {
final TextEditingController _searchController = TextEditingController();
final ScrollController _scrollController = ScrollController();
bool _isGridView = false;
@override
initState() {
super.initState();
}
@override
void dispose() {
_searchController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.background,
body: BlocBuilder<CustomerLoaderBloc, CustomerLoaderState>(
builder: (context, state) {
return NotificationListener<ScrollNotification>(
onNotification: (notification) {
if (notification is ScrollEndNotification &&
_scrollController.position.extentAfter == 0) {
context.read<CustomerLoaderBloc>().add(
CustomerLoaderEvent.fetched(),
);
return true;
}
return true;
},
child: CustomScrollView(
controller: _scrollController,
slivers: [
// SliverAppBar with gradient
SliverAppBar(
expandedHeight: 120.0,
floating: false,
pinned: true,
backgroundColor: AppColor.primary,
flexibleSpace: CustomAppBar(title: context.lang.customer),
actions: [
ActionIconButton(onTap: () {}, icon: LineIcons.search),
],
),
// Search and Filter Section
SliverToBoxAdapter(
child: Container(
color: AppColor.white,
child: Column(
children: [
// View toggle and sort
Padding(
padding: EdgeInsets.only(
left: 16,
right: 16,
bottom: 0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
children: [
IconButton(
icon: Icon(
_isGridView
? Icons.list
: Icons.grid_view,
color: AppColor.primary,
),
onPressed: () {
setState(() {
_isGridView = !_isGridView;
});
},
),
],
),
],
),
),
],
),
),
),
// Customer List
_isGridView
? _buildCustomerGrid(state.customers)
: _buildCustomerList(state.customers),
],
),
);
},
),
);
}
Widget _buildCustomerList(List<Customer> customers) {
return SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
final customer = customers[index];
return CustomerTile(customer: customer);
}, childCount: customers.length),
);
}
Widget _buildCustomerGrid(List<Customer> customers) {
return SliverPadding(
padding: EdgeInsets.all(16),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
childAspectRatio: 0.65,
),
delegate: SliverChildBuilderDelegate((context, index) {
final customer = customers[index];
return CustomerCard(customer: customer);
}, childCount: customers.length),
),
);
}
}