import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:salonbooking/main.dart'; import 'package:salonbooking/karyawan/home_karyawan.dart'; import 'package:salonbooking/pemilik/home_pemilik.dart'; import 'package:salonbooking/pelanggan/main_navigation.dart'; class Service { final int id; final String name; final int price; final String? imageUrl; Service({ required this.id, required this.name, required this.price, this.imageUrl, }); factory Service.fromJson(Map json) { return Service( id: json['id'], name: json['name'], price: json['price'], imageUrl: json['image'], ); } } class PelangganHomePage extends StatefulWidget { final String name; final String token; final Future Function() onCartUpdated; const PelangganHomePage( this.name, { super.key, required this.token, required this.onCartUpdated, }); @override State createState() => _PelangganHomePageState(); } class _PelangganHomePageState extends State { List categories = []; Map> servicesByCategory = {}; int? selectedCategoryId; bool loadingCategories = true; bool loadingServices = false; @override void initState() { super.initState(); fetchCategories(); } Future fetchCategories() async { setState(() => loadingCategories = true); try { final response = await http.get( Uri.parse('http://angeliasalon.my.id/api/categories'), headers: { 'Authorization': 'Bearer ${widget.token}', 'Accept': 'application/json', }, ); if (response.statusCode == 200) { final data = json.decode(response.body); setState(() { categories = data is List ? data : data['categories']; if (categories.isNotEmpty) { selectedCategoryId = categories[0]['id']; fetchServicesByCategory(selectedCategoryId!); } }); } } catch (e) { print(e); } finally { setState(() => loadingCategories = false); } } Future fetchServicesByCategory(int categoryId) async { setState(() => loadingServices = true); try { final response = await http.get( Uri.parse('http://angeliasalon.my.id/api/services?category_id=$categoryId'), headers: { 'Authorization': 'Bearer ${widget.token}', 'Accept': 'application/json', }, ); if (response.statusCode == 200) { final data = json.decode(response.body); final List services = (data as List) .map((item) => Service.fromJson(item)) .toList(); setState(() { servicesByCategory[categoryId] = services; }); } } catch (e) { print(e); } finally { setState(() => loadingServices = false); } } void selectCategory(int categoryId) async { if (selectedCategoryId == categoryId) return; setState(() => selectedCategoryId = categoryId); await fetchServicesByCategory(categoryId); } void toggleCart(Service service) async { try { final response = await http.post( Uri.parse('http://angeliasalon.my.id/api/cart'), headers: { 'Authorization': 'Bearer ${widget.token}', 'Accept': 'application/json', 'Content-Type': 'application/json', }, body: json.encode({ 'service_id': service.id, 'quantity': 1, }), ); if (response.statusCode == 200 || response.statusCode == 201) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Berhasil ditambahkan ke keranjang')), ); widget.onCartUpdated(); } else { print(response.body); throw Exception('Gagal menambahkan ke keranjang'); } } catch (e) { print(e); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Terjadi kesalahan')), ); } } /// Fungsi Logout void logout() async { final prefs = await SharedPreferences.getInstance(); await prefs.remove('token'); Navigator.pushAndRemoveUntil( context, MaterialPageRoute( builder: (_) => HomeSelector( onLoginSuccess: (token, user) { final navigator = navigatorKey.currentState!; switch (user['role']) { case 'pelanggan': navigator.pushAndRemoveUntil( MaterialPageRoute( builder: (_) => MainNavigation( userName: user['name'] ?? 'User', token: token, user: user, ), ), (route) => false, ); break; case 'karyawan': navigator.pushAndRemoveUntil( MaterialPageRoute( builder: (_) => KaryawanHomePage( user['name'] ?? 'User', token: token, user: user, ), ), (route) => false, ); break; case 'pemilik': navigator.pushAndRemoveUntil( MaterialPageRoute( builder: (_) => PemilikHomePage( name: user['name'] ?? 'User', token: token, ), ), (route) => false, ); break; default: navigator.pushAndRemoveUntil( MaterialPageRoute( builder: (_) => const Scaffold( body: Center(child: Text('Role tidak dikenal')), ), ), (route) => false, ); } }, ), ), (route) => false, ); } @override Widget build(BuildContext context) { final primaryColor = const Color(0xFFF06292); final backgroundColor = const Color(0xFFFFF6F9); final services = selectedCategoryId != null ? (servicesByCategory[selectedCategoryId!] ?? []) : []; return Scaffold( backgroundColor: backgroundColor, appBar: AppBar( title: Text('Halo, ${widget.name}'), backgroundColor: primaryColor, actions: [ IconButton( icon: const Icon(Icons.logout), onPressed: () { showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Konfirmasi Logout'), content: const Text('Apakah Anda yakin ingin logout?'), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('Batal'), ), TextButton( onPressed: () { Navigator.pop(context); logout(); }, child: const Text( 'Logout', style: TextStyle(color: Colors.red), ), ), ], ), ); }, ) ], ), body: Column( children: [ SizedBox( height: 60, child: loadingCategories ? const Center(child: CircularProgressIndicator()) : ListView.builder( scrollDirection: Axis.horizontal, itemCount: categories.length, itemBuilder: (context, index) { final category = categories[index]; final isSelected = category['id'] == selectedCategoryId; return GestureDetector( onTap: () => selectCategory(category['id']), child: Container( margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 10), padding: const EdgeInsets.symmetric(horizontal: 20), decoration: BoxDecoration( color: isSelected ? primaryColor : Colors.pink.shade100, borderRadius: BorderRadius.circular(20), ), child: Center( child: Text( category['name'], style: TextStyle( color: isSelected ? Colors.white : Colors.black, fontWeight: FontWeight.bold, ), ), ), ), ); }, ), ), const Divider(), Expanded( child: loadingServices ? const Center(child: CircularProgressIndicator()) : ListView.builder( itemCount: services.length, itemBuilder: (context, index) { final service = services[index]; return Card( child: ListTile( leading: service.imageUrl != null && service.imageUrl!.isNotEmpty ? Image.network( service.imageUrl!, width: 60, height: 60, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) => const Icon(Icons.broken_image, size: 60), ) : const Icon(Icons.image, size: 60), title: Text(service.name), subtitle: Text("Rp ${service.price}"), trailing: IconButton( icon: const Icon(Icons.add_shopping_cart), onPressed: () => toggleCart(service), ), ), ); }, ), ), ], ), ); } }