NIM_E31222534/Androidnya/lib/screens/dashboard/anak_form_screen.dart

442 lines
15 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:intl/intl.dart';
import 'package:posyandu/services/anak_service.dart';
class AnakFormScreen extends StatefulWidget {
final int? anakId; // Jika tidak null, berarti edit data yang sudah ada
const AnakFormScreen({Key? key, this.anakId}) : super(key: key);
@override
_AnakFormScreenState createState() => _AnakFormScreenState();
}
class _AnakFormScreenState extends State<AnakFormScreen> {
final _formKey = GlobalKey<FormState>();
final TextEditingController _namaController = TextEditingController();
final TextEditingController _tempatLahirController = TextEditingController();
final TextEditingController _tanggalLahirController = TextEditingController();
DateTime? _selectedDate;
String _jenisKelamin = 'Laki-laki'; // Default value
bool _isLoading = false;
bool _isEdit = false;
final AnakService _anakService = AnakService();
@override
void initState() {
super.initState();
_isEdit = widget.anakId != null;
if (_isEdit) {
// Jika mode edit, load data anak
_loadAnakData();
}
}
Future<void> _loadAnakData() async {
setState(() {
_isLoading = true;
});
try {
if (widget.anakId != null) {
final anak = await _anakService.getAnakDetail(widget.anakId!);
_namaController.text = anak['nama_anak'];
_tempatLahirController.text = anak['tempat_lahir'];
// Format tanggal
final DateTime tanggalLahir = DateTime.parse(anak['tanggal_lahir']);
_selectedDate = tanggalLahir;
_tanggalLahirController.text = DateFormat('dd-MM-yyyy').format(tanggalLahir);
setState(() {
_jenisKelamin = anak['jenis_kelamin'];
});
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Gagal memuat data anak: $e')),
);
} finally {
setState(() {
_isLoading = false;
});
}
}
Future<void> _selectDate(BuildContext context) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: _selectedDate ?? DateTime.now(),
firstDate: DateTime(2000),
lastDate: DateTime.now(),
helpText: 'Pilih Tanggal Lahir',
cancelText: 'BATAL',
confirmText: 'PILIH',
fieldLabelText: 'Tanggal Lahir Anak',
fieldHintText: 'DD/MM/YYYY',
builder: (context, child) {
return Theme(
data: Theme.of(context).copyWith(
colorScheme: ColorScheme.light(
primary: Colors.teal.shade700,
onPrimary: Colors.white,
onSurface: Colors.black,
),
textButtonTheme: TextButtonThemeData(
style: TextButton.styleFrom(
foregroundColor: Colors.teal.shade700,
),
),
),
child: child!,
);
},
);
if (picked != null && picked != _selectedDate) {
setState(() {
_selectedDate = picked;
_tanggalLahirController.text = DateFormat('dd-MM-yyyy').format(picked);
});
}
}
Future<void> _saveData() async {
if (_formKey.currentState!.validate()) {
setState(() {
_isLoading = true;
});
try {
Map<String, dynamic> response;
if (_selectedDate == null) {
throw Exception('Tanggal lahir harus diisi');
}
print('Menyimpan data anak...');
try {
if (_isEdit && widget.anakId != null) {
// Update existing data
response = await _anakService.updateAnak(
anakId: widget.anakId!,
namaAnak: _namaController.text,
tempatLahir: _tempatLahirController.text,
tanggalLahir: _selectedDate!,
jenisKelamin: _jenisKelamin,
);
} else {
// Create new data
response = await _anakService.createAnak(
namaAnak: _namaController.text,
tempatLahir: _tempatLahirController.text,
tanggalLahir: _selectedDate!,
jenisKelamin: _jenisKelamin,
);
}
print('Response dari server: $response');
} catch (e) {
print('Error dari API: $e');
throw Exception('Gagal mengirim data ke server: $e');
}
if (!mounted) return;
setState(() {
_isLoading = false;
});
if (response['success'] == true || response['status'] == 'success') {
// Go back to previous screen with result=true to trigger reload
// Navigator.pop(context, true);
// Tambahkan notifikasi sukses DI LAYAR SENDIRI sebelum kembali
// Buat overlay yang terlihat jelas
showDialog(
context: context,
barrierDismissible: false,
builder: (context) => WillPopScope(
onWillPop: () async => false, // Prevent back button
child: Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Container(
padding: EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Container(
padding: EdgeInsets.all(15),
decoration: BoxDecoration(
color: Colors.green.shade100,
shape: BoxShape.circle,
),
child: Icon(
Icons.check_circle,
color: Colors.green.shade700,
size: 60,
),
),
SizedBox(height: 20),
Text(
response.containsKey('is_local_only') && response['is_local_only'] == true
? 'Data berhasil disimpan secara lokal'
: 'Data anak berhasil disimpan',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.green.shade800,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10),
Text(
_namaController.text,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
textAlign: TextAlign.center,
),
SizedBox(height: 25),
ElevatedButton(
onPressed: () {
// Tutup dialog dan kembali ke halaman anak
Navigator.pop(context); // Tutup dialog
Navigator.pop(context, true); // Kembali ke halaman anak
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.green.shade700,
padding: EdgeInsets.symmetric(vertical: 15, horizontal: 30),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),
),
child: Text(
'OK, LANJUTKAN',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
),
],
),
),
),
),
);
// Jika user menonaktifkan dialog, tambahkan auto-navigasi setelah 2 detik
Future.delayed(Duration(seconds: 2), () {
if (mounted) {
// Pop dialog jika masih ada
if (Navigator.of(context).canPop()) {
Navigator.of(context).pop(); // Tutup dialog jika masih terbuka
}
// Pop form screen
if (Navigator.of(context).canPop()) {
Navigator.of(context).pop(true); // Kembali ke halaman anak
}
}
});
} else {
// Show error message
String errorMsg = response['message'] ?? 'Terjadi kesalahan';
if (response.containsKey('errors')) {
errorMsg += ': ${response['errors']}';
}
print('Error dari server: $errorMsg');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(errorMsg),
backgroundColor: Colors.red,
),
);
}
} catch (e) {
print('Error saat menyimpan: $e');
setState(() {
_isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error: ${e.toString()}'),
backgroundColor: Colors.red,
),
);
}
}
}
@override
void dispose() {
_namaController.dispose();
_tempatLahirController.dispose();
_tanggalLahirController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_isEdit ? 'Edit Data Anak' : 'Tambah Data Anak'),
backgroundColor: Colors.teal.shade700,
foregroundColor: Colors.white,
elevation: 0,
),
body: _isLoading
? Center(child: CircularProgressIndicator())
: SingleChildScrollView(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Informasi Anak
_buildSectionTitle('Informasi Anak'),
SizedBox(height: 16),
// Nama Anak
TextFormField(
controller: _namaController,
decoration: InputDecoration(
labelText: 'Nama Anak',
hintText: 'Masukkan nama lengkap anak',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.person),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Nama anak harus diisi';
}
return null;
},
),
SizedBox(height: 16),
// Tempat Lahir
TextFormField(
controller: _tempatLahirController,
decoration: InputDecoration(
labelText: 'Tempat Lahir',
hintText: 'Masukkan tempat lahir anak',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.location_city),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Tempat lahir harus diisi';
}
return null;
},
),
SizedBox(height: 16),
// Tanggal Lahir
TextFormField(
controller: _tanggalLahirController,
readOnly: true,
decoration: InputDecoration(
labelText: 'Tanggal Lahir',
hintText: 'Pilih tanggal lahir anak',
border: OutlineInputBorder(),
prefixIcon: Icon(Icons.calendar_today),
suffixIcon: IconButton(
icon: Icon(Icons.date_range),
onPressed: () => _selectDate(context),
),
),
validator: (value) {
if (value == null || value.isEmpty) {
return 'Tanggal lahir harus diisi';
}
return null;
},
onTap: () => _selectDate(context),
),
SizedBox(height: 16),
// Jenis Kelamin
_buildSectionTitle('Jenis Kelamin'),
SizedBox(height: 8),
Row(
children: [
Expanded(
child: RadioListTile<String>(
title: Text('Laki-laki'),
value: 'Laki-laki',
groupValue: _jenisKelamin,
activeColor: Colors.teal.shade700,
onChanged: (value) {
setState(() {
_jenisKelamin = value!;
});
},
),
),
Expanded(
child: RadioListTile<String>(
title: Text('Perempuan'),
value: 'Perempuan',
groupValue: _jenisKelamin,
activeColor: Colors.teal.shade700,
onChanged: (value) {
setState(() {
_jenisKelamin = value!;
});
},
),
),
],
),
SizedBox(height: 32),
// Submit Button
Container(
width: double.infinity,
child: ElevatedButton(
onPressed: _isLoading ? null : _saveData,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.teal.shade700,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 16),
textStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
child: Text(_isEdit ? 'PERBARUI DATA' : 'SIMPAN DATA'),
),
),
],
),
),
),
);
}
Widget _buildSectionTitle(String title) {
return Text(
title,
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.teal.shade800,
),
);
}
}