100 lines
3.1 KiB
Dart
100 lines
3.1 KiB
Dart
|
|
import 'package:flutter/material.dart';
|
||
|
|
|
||
|
|
/// Tampilan nama pembeli (untuk invoice). Teks dapat di-tap untuk membuka
|
||
|
|
/// popup pengisian nama pembeli.
|
||
|
|
class CustomerNameField extends StatelessWidget {
|
||
|
|
final String value;
|
||
|
|
final ValueChanged<String> onChanged;
|
||
|
|
|
||
|
|
const CustomerNameField({
|
||
|
|
super.key,
|
||
|
|
required this.value,
|
||
|
|
required this.onChanged,
|
||
|
|
});
|
||
|
|
|
||
|
|
Future<void> _openDialog(BuildContext context) async {
|
||
|
|
final controller = TextEditingController(text: value);
|
||
|
|
final result = await showDialog<String>(
|
||
|
|
context: context,
|
||
|
|
builder: (ctx) => AlertDialog(
|
||
|
|
title: const Row(
|
||
|
|
children: [
|
||
|
|
Icon(Icons.person_outline, size: 22),
|
||
|
|
SizedBox(width: 8),
|
||
|
|
Text('Nama Pembeli'),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
content: TextField(
|
||
|
|
controller: controller,
|
||
|
|
autofocus: true,
|
||
|
|
decoration: const InputDecoration(
|
||
|
|
labelText: 'Nama Pembeli (untuk Invoice)',
|
||
|
|
hintText: 'Contoh: Budi Santoso',
|
||
|
|
border: OutlineInputBorder(),
|
||
|
|
isDense: true,
|
||
|
|
),
|
||
|
|
textCapitalization: TextCapitalization.words,
|
||
|
|
),
|
||
|
|
actions: [
|
||
|
|
TextButton(
|
||
|
|
onPressed: () => Navigator.of(ctx).pop(),
|
||
|
|
child: const Text('Batal'),
|
||
|
|
),
|
||
|
|
ElevatedButton(
|
||
|
|
onPressed: () => Navigator.of(ctx).pop(controller.text.trim()),
|
||
|
|
child: const Text('Simpan'),
|
||
|
|
),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
);
|
||
|
|
if (result != null) {
|
||
|
|
// Defer agar tidak rebuild saat dialog sedang di-deactivate
|
||
|
|
// (mencegah assertion dependents.isEmpty).
|
||
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||
|
|
onChanged(result);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
// Dispose controller setelah dialog benar-benar dihapus dari tree.
|
||
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||
|
|
controller.dispose();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
@override
|
||
|
|
Widget build(BuildContext context) {
|
||
|
|
final display = value.trim().isEmpty ? 'Tap untuk isi nama pembeli' : value;
|
||
|
|
final isPlaceholder = value.trim().isEmpty;
|
||
|
|
return InkWell(
|
||
|
|
onTap: () => _openDialog(context),
|
||
|
|
borderRadius: BorderRadius.circular(4),
|
||
|
|
child: Container(
|
||
|
|
width: double.infinity,
|
||
|
|
padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 8.0),
|
||
|
|
decoration: BoxDecoration(
|
||
|
|
border: Border.all(color: Colors.grey[300]!),
|
||
|
|
borderRadius: BorderRadius.circular(4),
|
||
|
|
color: Colors.grey[50],
|
||
|
|
),
|
||
|
|
child: Row(
|
||
|
|
children: [
|
||
|
|
const Icon(Icons.person_outline, size: 18, color: Colors.grey),
|
||
|
|
const SizedBox(width: 8),
|
||
|
|
Expanded(
|
||
|
|
child: Text(
|
||
|
|
'Pembeli: $display',
|
||
|
|
style: TextStyle(
|
||
|
|
fontSize: 13,
|
||
|
|
color: isPlaceholder ? Colors.grey[600] : Colors.black,
|
||
|
|
fontStyle: isPlaceholder ? FontStyle.italic : FontStyle.normal,
|
||
|
|
),
|
||
|
|
overflow: TextOverflow.ellipsis,
|
||
|
|
),
|
||
|
|
),
|
||
|
|
const Icon(Icons.edit, size: 16, color: Colors.grey),
|
||
|
|
],
|
||
|
|
),
|
||
|
|
),
|
||
|
|
);
|
||
|
|
}
|
||
|
|
}
|