apskel-pos-flutter/lib/presentation/home/widgets/customer_auto_complete_field.dart
2025-08-04 14:08:13 +07:00

120 lines
4.4 KiB
Dart

import 'package:enaklo_pos/core/components/spaces.dart';
import 'package:enaklo_pos/core/constants/colors.dart';
import 'package:enaklo_pos/core/extensions/build_context_ext.dart';
import 'package:enaklo_pos/data/models/response/customer_response_model.dart';
import 'package:enaklo_pos/presentation/customer/bloc/customer_loader/customer_loader_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class CustomerAutocomplete extends StatefulWidget {
final TextEditingController controller;
final Customer? selectedCustomer;
final ValueChanged<Customer?>? onSelected;
const CustomerAutocomplete({
super.key,
required this.controller,
this.selectedCustomer,
this.onSelected,
});
@override
State<CustomerAutocomplete> createState() => _CustomerAutocompleteState();
}
class _CustomerAutocompleteState extends State<CustomerAutocomplete> {
final FocusNode _focusNode = FocusNode();
@override
void initState() {
super.initState();
context.read<CustomerLoaderBloc>().add(CustomerLoaderEvent.getCustomer());
}
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Pelanggan',
style: TextStyle(
color: AppColors.black,
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
const SpaceHeight(6.0),
BlocBuilder<CustomerLoaderBloc, CustomerLoaderState>(
builder: (context, state) {
return state.maybeWhen(
orElse: () => const SizedBox.shrink(),
loading: () => const Center(child: CircularProgressIndicator()),
loaded: (customers, totalCustomer) => RawAutocomplete<Customer>(
textEditingController: widget.controller,
focusNode: _focusNode,
optionsBuilder: (TextEditingValue textEditingValue) {
if (textEditingValue.text.isEmpty) {
return const Iterable<Customer>.empty();
}
return customers.where((Customer customer) {
return customer.name?.toLowerCase().contains(
textEditingValue.text.toLowerCase(),
) ??
false;
});
},
displayStringForOption: (Customer option) => option.name ?? "",
onSelected: (Customer selection) {
widget.controller.text = selection.name ?? "";
if (widget.onSelected != null) {
widget.onSelected!(selection);
}
},
fieldViewBuilder:
(context, controller, focusNode, onFieldSubmitted) {
return TextFormField(
controller: controller,
focusNode: focusNode,
decoration: const InputDecoration(
hintText: 'Nama Pelanggan',
),
onChanged: (value) {
if (widget.onSelected != null) {
widget.onSelected!(null); // reset jika ketik manual
}
},
);
},
optionsViewBuilder: (context, onSelected, options) {
return Material(
elevation: 1,
borderRadius: BorderRadius.circular(8),
color: Colors.white,
child: SizedBox(
height: context.deviceHeight * 0.4,
child: ListView.separated(
padding: EdgeInsets.zero,
itemCount: options.length,
separatorBuilder: (_, __) => const Divider(height: 1),
itemBuilder: (BuildContext context, int index) {
final Customer option = options.elementAt(index);
return ListTile(
title: Text(option.name ?? ""),
onTap: () {
onSelected(option);
},
);
},
),
),
);
},
),
);
},
),
],
);
}
}