MIF_E31221388/salonbooking/lib/pelanggan/keranjang_page.dart

254 lines
8.4 KiB
Dart

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
class KeranjangPage extends StatefulWidget {
final String token;
final Function onCartUpdated;
const KeranjangPage({
super.key,
required this.token,
required this.onCartUpdated,
});
@override
State<KeranjangPage> createState() => _KeranjangPageState();
}
class _KeranjangPageState extends State<KeranjangPage> {
List cartItems = [];
bool loading = true;
DateTime? selectedDate;
TimeOfDay? selectedTime;
@override
void initState() {
super.initState();
fetchCart();
}
Future<void> fetchCart() async {
setState(() => loading = true);
try {
final response = await http.get(
Uri.parse('http://angeliasalon.my.id/api/cart'),
headers: {
'Authorization': 'Bearer ${widget.token}',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
setState(() {
cartItems = data is List ? data : data['cart'] ?? [];
});
widget.onCartUpdated(); // Update jumlah cart
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Gagal mengambil keranjang')),
);
}
} catch (e) {
print(e);
}
setState(() => loading = false);
}
Future<void> deleteItem(int id) async {
try {
final response = await http.delete(
Uri.parse('http://angeliasalon.my.id/api/cart/$id'),
headers: {
'Authorization': 'Bearer ${widget.token}',
'Accept': 'application/json',
},
);
if (response.statusCode == 200) {
await fetchCart(); // Panggil fetchCart agar jumlah update
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Gagal menghapus item')),
);
}
} catch (e) {
print(e);
}
}
int getTotalHarga() {
return cartItems.fold(
0,
(total, item) => total + (item['service']['price'] as int),
);
}
Future<void> pickDate() async {
final picked = await showDatePicker(
context: context,
initialDate: selectedDate ?? DateTime.now(),
firstDate: DateTime.now(),
lastDate: DateTime.now().add(const Duration(days: 365)),
);
if (picked != null) setState(() => selectedDate = picked);
}
Future<void> pickTime() async {
final picked = await showTimePicker(
context: context,
initialTime: selectedTime ?? TimeOfDay.now(),
builder: (context, child) {
return MediaQuery(
data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: true),
child: child!,
);
},
);
if (picked != null) setState(() => selectedTime = picked);
}
Future<void> checkout() async {
if (selectedDate == null || selectedTime == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Harap pilih tanggal dan waktu booking")),
);
return;
}
final tanggalBooking =
"${selectedDate!.year}-${selectedDate!.month.toString().padLeft(2, '0')}-${selectedDate!.day.toString().padLeft(2, '0')}";
final jamBooking =
"${selectedTime!.hour.toString().padLeft(2, '0')}:${selectedTime!.minute.toString().padLeft(2, '0')}";
try {
final response = await http.post(
Uri.parse('http://angeliasalon.my.id/api/cart/checkout'),
headers: {
'Authorization': 'Bearer ${widget.token}',
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: json.encode({
'tanggal_booking': tanggalBooking,
'jam': jamBooking,
}),
);
if (response.statusCode == 200 || response.statusCode == 201) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Booking berhasil!")),
);
setState(() {
cartItems.clear();
selectedDate = null;
selectedTime = null;
});
widget.onCartUpdated(); // Update jumlah cart setelah checkout
} else if (response.statusCode == 409) {
final message = jsonDecode(response.body)['message'];
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Gagal booking: $message")),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Terjadi kesalahan saat booking")),
);
}
} catch (e) {
print(e);
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text("Terjadi error jaringan")),
);
}
}
@override
Widget build(BuildContext context) {
final primaryColor = const Color(0xFFF06292);
return Scaffold(
appBar: AppBar(
title: const Text("Keranjang Anda"),
backgroundColor: primaryColor,
),
body: loading
? const Center(child: CircularProgressIndicator())
: cartItems.isEmpty
? const Center(child: Text("Keranjang kosong"))
: Column(
children: [
Expanded(
child: ListView.builder(
itemCount: cartItems.length,
itemBuilder: (context, index) {
final item = cartItems[index];
final service = item['service'];
return Card(
margin: const EdgeInsets.symmetric(
horizontal: 12, vertical: 6),
child: ListTile(
title: Text(service['name'] ?? 'Layanan'),
subtitle: Text(
"Harga: Rp ${service['price'] ?? 0}"),
trailing: IconButton(
icon: const Icon(Icons.delete,
color: Colors.red),
onPressed: () => deleteItem(item['id']),
),
),
);
},
),
),
const Divider(),
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 16, vertical: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
"Total: Rp ${getTotalHarga()}",
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
ElevatedButton.icon(
onPressed: pickDate,
icon: const Icon(Icons.date_range),
label: Text(selectedDate == null
? 'Pilih Tanggal Booking'
: 'Tanggal: ${selectedDate!.year}-${selectedDate!.month.toString().padLeft(2, '0')}-${selectedDate!.day.toString().padLeft(2, '0')}'),
),
const SizedBox(height: 8),
ElevatedButton.icon(
onPressed: pickTime,
icon: const Icon(Icons.access_time),
label: Text(selectedTime == null
? 'Pilih Waktu Booking'
: 'Waktu: ${selectedTime!.hour.toString().padLeft(2, '0')}:${selectedTime!.minute.toString().padLeft(2, '0')}'),
),
const SizedBox(height: 16),
ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: primaryColor,
padding:
const EdgeInsets.symmetric(vertical: 14),
),
onPressed: checkout,
child: const Text("Checkout",
style: TextStyle(fontSize: 16)),
)
],
),
),
],
),
);
}
}