190 lines
5.2 KiB
Dart
190 lines
5.2 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:http/http.dart' as http;
|
|
import 'dart:convert';
|
|
import '../../../services/auth_service.dart';
|
|
|
|
|
|
class KelolaLokasiScreen extends StatefulWidget {
|
|
const KelolaLokasiScreen({super.key});
|
|
|
|
@override
|
|
State<KelolaLokasiScreen> createState() => _KelolaLokasiScreenState();
|
|
}
|
|
|
|
class _KelolaLokasiScreenState extends State<KelolaLokasiScreen> {
|
|
final String baseUrl = AuthService.baseUrl;
|
|
List<Map<String, dynamic>> lokasiList = [];
|
|
bool isLoading = false;
|
|
|
|
final TextEditingController namaController = TextEditingController();
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
fetchLokasi();
|
|
}
|
|
|
|
Future<void> fetchLokasi() async {
|
|
try {
|
|
final response = await http.get(Uri.parse("$baseUrl/lokasi"));
|
|
|
|
if (response.statusCode == 200) {
|
|
final data = jsonDecode(response.body);
|
|
setState(() {
|
|
lokasiList = List<Map<String, dynamic>>.from(data);
|
|
});
|
|
}
|
|
} catch (e) {
|
|
debugPrint("Error fetch lokasi: $e");
|
|
}
|
|
}
|
|
|
|
Future<void> tambahLokasi() async {
|
|
if (namaController.text.isEmpty) return;
|
|
|
|
setState(() => isLoading = true);
|
|
|
|
try {
|
|
final response = await http.post(
|
|
Uri.parse("$baseUrl/lokasi"),
|
|
headers: {"Content-Type": "application/json"},
|
|
body: jsonEncode({"nama_lokasi": namaController.text}),
|
|
);
|
|
|
|
if (response.statusCode == 201) {
|
|
Navigator.pop(context);
|
|
clearForm();
|
|
fetchLokasi();
|
|
}
|
|
} catch (e) {
|
|
debugPrint("Error tambah lokasi: $e");
|
|
}
|
|
|
|
setState(() => isLoading = false);
|
|
}
|
|
|
|
Future<void> updateLokasi(int id) async {
|
|
if (namaController.text.isEmpty) return;
|
|
|
|
setState(() => isLoading = true);
|
|
|
|
try {
|
|
final response = await http.put(
|
|
Uri.parse("$baseUrl/lokasi/$id"),
|
|
headers: {"Content-Type": "application/json"},
|
|
body: jsonEncode({"nama_lokasi": namaController.text}),
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
Navigator.pop(context);
|
|
clearForm();
|
|
fetchLokasi();
|
|
}
|
|
} catch (e) {
|
|
debugPrint("Error update lokasi: $e");
|
|
}
|
|
|
|
setState(() => isLoading = false);
|
|
}
|
|
|
|
Future<void> hapusLokasi(int id) async {
|
|
try {
|
|
await http.delete(Uri.parse("$baseUrl/lokasi/$id"));
|
|
fetchLokasi();
|
|
} catch (e) {
|
|
debugPrint("Error hapus lokasi: $e");
|
|
}
|
|
}
|
|
|
|
void clearForm() {
|
|
namaController.clear();
|
|
}
|
|
|
|
void showForm({Map<String, dynamic>? lokasi}) {
|
|
if (lokasi != null) {
|
|
namaController.text = lokasi['nama_lokasi'];
|
|
}
|
|
|
|
showDialog(
|
|
context: context,
|
|
builder:
|
|
(_) => AlertDialog(
|
|
title: Text(lokasi == null ? "Tambah Lokasi" : "Edit Lokasi"),
|
|
content: TextField(
|
|
controller: namaController,
|
|
decoration: const InputDecoration(
|
|
labelText: "Nama Lokasi",
|
|
border: OutlineInputBorder(),
|
|
),
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () {
|
|
Navigator.pop(context);
|
|
clearForm();
|
|
},
|
|
child: const Text("Batal"),
|
|
),
|
|
ElevatedButton(
|
|
onPressed:
|
|
isLoading
|
|
? null
|
|
: () {
|
|
if (lokasi == null) {
|
|
tambahLokasi();
|
|
} else {
|
|
updateLokasi(lokasi['id']);
|
|
}
|
|
},
|
|
child: Text(lokasi == null ? "Simpan" : "Update"),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: const Text("Kelola Lokasi"),
|
|
backgroundColor: const Color(0xFF2F5BEA),
|
|
),
|
|
body:
|
|
isLoading
|
|
? const Center(child: CircularProgressIndicator())
|
|
: ListView.builder(
|
|
padding: const EdgeInsets.all(16),
|
|
itemCount: lokasiList.length,
|
|
itemBuilder: (context, index) {
|
|
final lokasi = lokasiList[index];
|
|
|
|
return Card(
|
|
child: ListTile(
|
|
title: Text(lokasi['nama_lokasi']),
|
|
trailing: Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
IconButton(
|
|
icon: const Icon(Icons.edit, color: Colors.orange),
|
|
onPressed: () => showForm(lokasi: lokasi),
|
|
),
|
|
IconButton(
|
|
icon: const Icon(Icons.delete, color: Colors.red),
|
|
onPressed: () => hapusLokasi(lokasi['id']),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
floatingActionButton: FloatingActionButton(
|
|
backgroundColor: const Color(0xFF2F5BEA),
|
|
onPressed: () => showForm(),
|
|
child: const Icon(Icons.add),
|
|
),
|
|
);
|
|
}
|
|
}
|