import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import '../../core/theme/app_theme.dart'; import '../../core/widgets/loading_button.dart'; import '../../core/api/api_client.dart'; import '../../shared/providers/lookup_providers.dart'; import 'surat_provider.dart'; class SuratFormScreen extends ConsumerStatefulWidget { final int? editId; final int? prefillTaskId; const SuratFormScreen({super.key, this.editId, this.prefillTaskId}); @override ConsumerState createState() => _SuratFormScreenState(); } class _SuratFormScreenState extends ConsumerState { final _formKey = GlobalKey(); final _subjectCtrl = TextEditingController(); final _perihalCtrl = TextEditingController(); final _bodyCtrl = TextEditingController(); DateTime? _tanggal; int? _companyId; int? _vendorId; int? _categoryId; bool _loading = false; bool _initDone = false; bool get isEdit => widget.editId != null; @override void initState() { super.initState(); if (widget.prefillTaskId != null) _loadPrefill(); } @override void dispose() { _subjectCtrl.dispose(); _perihalCtrl.dispose(); _bodyCtrl.dispose(); super.dispose(); } Future _loadPrefill() async { try { final resp = await apiDio.get('/tasks/${widget.prefillTaskId}/letter-prefill'); setState(() { _subjectCtrl.text = resp.data['subject'] ?? ''; if (resp.data['body'] != null) _bodyCtrl.text = resp.data['body']; }); } catch (_) {} } Future _initEdit() async { if (!isEdit || _initDone) return; _initDone = true; try { final resp = await apiDio.get('/surat/${widget.editId}'); final d = resp.data as Map; setState(() { _subjectCtrl.text = d['subject'] ?? ''; _perihalCtrl.text = d['perihal'] ?? ''; _bodyCtrl.text = (d['body'] ?? '').replaceAll(RegExp(r'<[^>]*>'), ''); _companyId = d['company_id']; _vendorId = d['vendor_id']; _categoryId = d['category_id']; if (d['tanggal'] != null) _tanggal = DateTime.tryParse(d['tanggal']); }); } catch (_) {} } Future _submit() async { if (!_formKey.currentState!.validate()) return; setState(() => _loading = true); try { final data = { 'subject': _subjectCtrl.text.trim(), 'perihal': _perihalCtrl.text.trim(), 'body': _bodyCtrl.text.trim(), 'company_id': _companyId, 'vendor_id': _vendorId, 'category_id': _categoryId, if (_tanggal != null) 'tanggal': DateFormat('yyyy-MM-dd').format(_tanggal!), if (widget.prefillTaskId != null && !isEdit) 'task_id': widget.prefillTaskId, }; if (isEdit) { await updateSurat(widget.editId!, data); } else { await createSurat(data); } if (mounted) context.pop(); } on ApiException catch (e) { if (mounted) ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(e.message), backgroundColor: AppColors.danger)); } finally { if (mounted) setState(() => _loading = false); } } Future _pickDate() async { final picked = await showDatePicker( context: context, initialDate: _tanggal ?? DateTime.now(), firstDate: DateTime(2020), lastDate: DateTime(2030), ); if (picked != null) setState(() => _tanggal = picked); } @override Widget build(BuildContext context) { if (isEdit) _initEdit(); final companiesAsync = ref.watch(companiesProvider); final vendorsAsync = ref.watch(vendorsProvider); final categoriesAsync = ref.watch(categoriesProvider); return Scaffold( appBar: AppBar(title: Text(isEdit ? 'Edit Letter' : 'Create Letter')), body: Form( key: _formKey, child: ListView( padding: const EdgeInsets.all(16), children: [ _label('Subject'), TextFormField( controller: _subjectCtrl, decoration: const InputDecoration(hintText: 'Letter subject'), validator: (v) => (v == null || v.isEmpty) ? 'Subject is required' : null, ), const SizedBox(height: 16), _label('Notes (optional)'), TextFormField(controller: _perihalCtrl, decoration: const InputDecoration(hintText: 'Additional notes')), const SizedBox(height: 16), _label('Company'), companiesAsync.when( loading: () => const LinearProgressIndicator(), error: (_, __) => const Text('Failed to load companies'), data: (list) => DropdownButtonFormField( value: _companyId, decoration: const InputDecoration(hintText: 'Select company'), items: list.map((c) => DropdownMenuItem(value: c.id, child: Text(c.name))).toList(), onChanged: (v) => setState(() => _companyId = v), validator: (v) => v == null ? 'Company is required' : null, ), ), const SizedBox(height: 16), _label('Vendor (optional)'), vendorsAsync.when( loading: () => const LinearProgressIndicator(), error: (_, __) => const Text('Failed to load vendors'), data: (list) => DropdownButtonFormField( value: _vendorId, decoration: const InputDecoration(hintText: 'Select vendor'), items: [ const DropdownMenuItem(value: null, child: Text('None')), ...list.map((v) => DropdownMenuItem(value: v.id, child: Text(v.name))), ], onChanged: (v) => setState(() => _vendorId = v), ), ), const SizedBox(height: 16), _label('Category'), categoriesAsync.when( loading: () => const LinearProgressIndicator(), error: (_, __) => const Text('Failed to load categories'), data: (list) => DropdownButtonFormField( value: _categoryId, decoration: const InputDecoration(hintText: 'Select category'), items: list.map((c) => DropdownMenuItem(value: c.id, child: Text(c.name))).toList(), onChanged: (v) => setState(() => _categoryId = v), validator: (v) => v == null ? 'Category is required' : null, ), ), const SizedBox(height: 16), _label('Letter Date'), GestureDetector( onTap: _pickDate, child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), decoration: BoxDecoration( color: AppColors.surface, border: Border.all(color: AppColors.border), borderRadius: BorderRadius.circular(10), ), child: Row(children: [ const Icon(Icons.calendar_today_outlined, size: 16, color: AppColors.textSub), const SizedBox(width: 10), Text( _tanggal != null ? DateFormat('d MMMM yyyy').format(_tanggal!) : 'Select date', style: TextStyle(color: _tanggal != null ? AppColors.text : AppColors.textSub, fontSize: 14), ), ]), ), ), const SizedBox(height: 16), _label('Letter Content'), TextFormField( controller: _bodyCtrl, maxLines: 8, decoration: const InputDecoration( hintText: 'Write letter content here...', alignLabelWithHint: true, ), ), const SizedBox(height: 32), LoadingButton(loading: _loading, label: isEdit ? 'Save' : 'Create Letter', onPressed: _submit), ], ), ), ); } Widget _label(String text) => Padding( padding: const EdgeInsets.only(bottom: 6), child: Text(text, style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: AppColors.text)), ); }