161 lines
5.2 KiB
Dart
Raw Normal View History

2025-08-15 16:31:29 +07:00
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
2025-08-18 00:30:17 +07:00
import 'package:flutter_bloc/flutter_bloc.dart';
2025-08-15 16:31:29 +07:00
import 'package:line_icons/line_icons.dart';
2025-08-18 00:30:17 +07:00
import '../../../application/customer/customer_loader/customer_loader_bloc.dart';
2025-08-15 16:31:29 +07:00
import '../../../common/theme/theme.dart';
2025-08-18 00:30:17 +07:00
import '../../../domain/customer/customer.dart';
import '../../../injection.dart';
2025-08-16 00:39:09 +07:00
import '../../components/appbar/appbar.dart';
2025-08-15 16:31:29 +07:00
import '../../components/button/button.dart';
import 'widgets/customer_card.dart';
import 'widgets/customer_tile.dart';
@RoutePage()
2025-08-18 00:30:17 +07:00
class CustomerPage extends StatefulWidget implements AutoRouteWrapper {
2025-08-15 16:31:29 +07:00
const CustomerPage({super.key});
@override
State<CustomerPage> createState() => _CustomerPageState();
2025-08-18 00:30:17 +07:00
@override
Widget wrappedRoute(BuildContext context) => BlocProvider(
create: (context) =>
getIt<CustomerLoaderBloc>()
..add(CustomerLoaderEvent.fetched(isRefresh: true)),
child: this,
);
2025-08-15 16:31:29 +07:00
}
class _CustomerPageState extends State<CustomerPage>
with TickerProviderStateMixin {
final TextEditingController _searchController = TextEditingController();
2025-08-18 00:30:17 +07:00
ScrollController _scrollController = ScrollController();
2025-08-15 16:31:29 +07:00
bool _isGridView = false;
@override
initState() {
super.initState();
}
@override
void dispose() {
_searchController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppColor.background,
2025-08-18 00:30:17 +07:00
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: 'Pelanggan'),
actions: [
ActionIconButton(onTap: () {}, icon: LineIcons.search),
],
),
// Search and Filter Section
SliverToBoxAdapter(
child: Container(
color: AppColor.white,
child: Column(
2025-08-15 16:31:29 +07:00
children: [
2025-08-18 00:30:17 +07:00
// View toggle and sort
Padding(
padding: EdgeInsets.only(
left: 16,
right: 16,
bottom: 0,
2025-08-15 16:31:29 +07:00
),
2025-08-18 00:30:17 +07:00
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
children: [
IconButton(
icon: Icon(
_isGridView
? Icons.list
: Icons.grid_view,
color: AppColor.primary,
),
onPressed: () {
setState(() {
_isGridView = !_isGridView;
});
},
),
],
2025-08-15 16:31:29 +07:00
),
2025-08-18 00:30:17 +07:00
],
),
2025-08-15 16:31:29 +07:00
),
],
),
),
2025-08-18 00:30:17 +07:00
),
2025-08-15 16:31:29 +07:00
2025-08-18 00:30:17 +07:00
// Customer List
_isGridView
? _buildCustomerGrid(state.customers)
: _buildCustomerList(state.customers),
],
),
);
},
2025-08-15 16:31:29 +07:00
),
);
}
2025-08-18 00:30:17 +07:00
Widget _buildCustomerList(List<Customer> customers) {
2025-08-15 16:31:29 +07:00
return SliverList(
delegate: SliverChildBuilderDelegate((context, index) {
2025-08-18 00:30:17 +07:00
final customer = customers[index];
2025-08-15 16:31:29 +07:00
return CustomerTile(customer: customer);
2025-08-18 00:30:17 +07:00
}, childCount: customers.length),
2025-08-15 16:31:29 +07:00
);
}
2025-08-18 00:30:17 +07:00
Widget _buildCustomerGrid(List<Customer> customers) {
2025-08-15 16:31:29 +07:00
return SliverPadding(
padding: EdgeInsets.all(16),
sliver: SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 16,
mainAxisSpacing: 16,
childAspectRatio: 0.8,
),
delegate: SliverChildBuilderDelegate((context, index) {
2025-08-18 00:30:17 +07:00
final customer = customers[index];
2025-08-15 16:31:29 +07:00
return CustomerCard(customer: customer);
2025-08-18 00:30:17 +07:00
}, childCount: customers.length),
2025-08-15 16:31:29 +07:00
),
);
}
}