cashumit/lib/widgets/receipt_body.dart

216 lines
8.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:cashumit/widgets/store_info_widget.dart';
import 'package:cashumit/widgets/receipt_group_section.dart';
import 'package:cashumit/widgets/customer_name_field.dart';
import 'package:intl/intl.dart';
import 'package:cashumit/widgets/receipt_total.dart';
import 'package:cashumit/widgets/store_disclaimer.dart';
import 'package:cashumit/widgets/thank_you_pantun.dart';
import 'package:cashumit/widgets/dotted_line.dart';
import 'package:cashumit/widgets/horizontal_divider.dart';
import 'package:cashumit/widgets/dashed_border.dart';
import 'package:cashumit/utils/app_text_styles.dart';
import 'package:cashumit/models/receipt_group.dart';
class ReceiptBody extends StatelessWidget {
final List<ReceiptGroup> groups;
final DateTime transactionDate;
final VoidCallback onOpenStoreInfoConfig;
final VoidCallback onChangeDate;
final VoidCallback onOpenCustomTextConfig;
final double total;
final Function(String groupId, int index)? onEditItem;
final Function(String groupId, int index)? onRemoveItem;
final Function(String groupId)? onAddItem;
final Function(String groupId)? onRemoveGroup;
final Function(String groupId)? onSelectGroupSource;
final VoidCallback onAddGroup;
final VoidCallback? onSetTip;
final VoidCallback? onClearTip;
final String tagsText;
final List<String> availableTags;
final ValueChanged<String>? onTagsChanged;
final Function(String groupId)? onEditGroupTags;
final String customerName;
final ValueChanged<String>? onCustomerNameChanged;
const ReceiptBody({
super.key,
required this.groups,
required this.transactionDate,
required this.onOpenStoreInfoConfig,
required this.onChangeDate,
required this.onOpenCustomTextConfig,
required this.total,
this.onEditItem,
this.onRemoveItem,
this.onAddItem,
this.onRemoveGroup,
this.onSelectGroupSource,
required this.onAddGroup,
this.onSetTip,
this.onClearTip,
this.tagsText = '',
this.availableTags = const [],
this.onTagsChanged,
this.onEditGroupTags,
this.customerName = '',
this.onCustomerNameChanged,
});
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
decoration: const BoxDecoration(
color: Colors.white,
),
child: SingleChildScrollView(
physics: const NeverScrollableScrollPhysics(),
child: Column(
children: [
// Bagian atas - Header (akun tujuan di Config, bukan di sini)
Container(
padding: const EdgeInsets.all(8),
child: Column(
children: [
StoreInfoWidget(
onTap: onOpenStoreInfoConfig,
),
const DottedLine(),
const SizedBox(height: 8),
const HorizontalDivider(),
],
),
),
// Baris nama pembeli (75%) & tanggal (25%)
Padding(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
child: Row(
children: [
Expanded(
flex: 7,
child: CustomerNameField(
value: customerName,
onChanged: onCustomerNameChanged ?? (_) {},
),
),
const SizedBox(width: 8),
Expanded(
flex: 3,
child: InkWell(
onTap: onChangeDate,
borderRadius: BorderRadius.circular(4),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: 6, vertical: 8),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey[300]!),
borderRadius: BorderRadius.circular(4),
color: Colors.grey[50],
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
const Icon(Icons.calendar_today,
size: 14, color: Colors.grey),
const SizedBox(width: 4),
Text(
DateFormat('dd/MM').format(transactionDate),
style: const TextStyle(
fontSize: 11, fontWeight: FontWeight.w600),
),
const SizedBox(width: 2),
const Icon(Icons.edit,
size: 10, color: Colors.grey),
],
),
),
),
),
],
),
),
// Bagian tengah - Grup-grup dan total
Container(
padding: const EdgeInsets.all(8),
child: Column(
children: [
// Daftar grup
...groups.asMap().entries.map((entry) {
int gi = entry.key;
ReceiptGroup group = entry.value;
return ReceiptGroupSection(
group: group,
groupIndex: gi,
onSelectSource: () =>
onSelectGroupSource?.call(group.id),
onRemoveGroup: () => onRemoveGroup?.call(group.id),
onEditItem: (itemIndex) =>
onEditItem?.call(group.id, itemIndex),
onRemoveItem: (itemIndex) =>
onRemoveItem?.call(group.id, itemIndex),
onAddItem: () => onAddItem?.call(group.id),
onEditTags: () => onEditGroupTags?.call(group.id),
canRemove: groups.length > 1,
);
}),
// Tombol tambah grup sumber (gaya template card border putus-putus)
if (groups.length < 10)
Padding(
padding: const EdgeInsets.only(top: 4, bottom: 8),
child: GestureDetector(
onTap: onAddGroup,
child: DashedBorder(
color: Colors.grey,
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.add,
size: 16, color: Colors.grey[700]),
const SizedBox(width: 8),
Text(
'Tambah Sumber',
style: CourierStyles.bold
.copyWith(color: Colors.grey[700]),
),
],
),
),
),
),
const HorizontalDivider(),
ReceiptTotal(
total: total,
onSetTip: onSetTip,
onClearTip: onClearTip,
),
],
),
),
// Bagian bawah - Footer
Container(
padding: const EdgeInsets.all(8),
child: Column(
children: [
const DottedLine(),
StoreDisclaimer(onTap: onOpenCustomTextConfig),
ThankYouPantun(onTap: onOpenCustomTextConfig),
const SizedBox(height: 16),
],
),
),
],
),
),
);
}
}