import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import 'dart:convert'; class DataKaryawanPage extends StatefulWidget { final String token; const DataKaryawanPage({super.key, required this.token}); @override State createState() => _DataKaryawanPageState(); } class _DataKaryawanPageState extends State with SingleTickerProviderStateMixin { late TabController _tabController; List karyawan = []; bool loading = true; final TextEditingController nameController = TextEditingController(); final TextEditingController emailController = TextEditingController(); final TextEditingController passwordController = TextEditingController(); final Color primaryColor = const Color(0xFFF06292); // pink terang (hot pink) final Color backgroundColor = const Color(0xFFFFF6F9); // pink pucat banget @override void initState() { super.initState(); _tabController = TabController(length: 2, vsync: this); fetchKaryawan(); } @override void dispose() { _tabController.dispose(); super.dispose(); } Future fetchKaryawan() async { setState(() => loading = true); try { final response = await http.get( Uri.parse('http://angeliasalon.my.id/api/karyawan'), headers: { 'Authorization': 'Bearer ${widget.token}', 'Accept': 'application/json', }, ); if (response.statusCode == 200) { setState(() { karyawan = json.decode(response.body); loading = false; }); } else { throw Exception('Gagal memuat data'); } } catch (e) { setState(() => loading = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error: $e')), ); } } Future tambahKaryawan() async { try { final response = await http.post( Uri.parse('http://angeliasalon.my.id/api/karyawan'), headers: { 'Authorization': 'Bearer ${widget.token}', 'Accept': 'application/json', }, body: { 'name': nameController.text, 'email': emailController.text, 'password': passwordController.text, }, ); if (response.statusCode == 201) { fetchKaryawan(); nameController.clear(); emailController.clear(); passwordController.clear(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Karyawan berhasil ditambahkan')), ); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Gagal menambahkan karyawan')), ); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error: $e')), ); } } Future hapusKaryawan(int id) async { try { final response = await http.delete( Uri.parse('http://angeliasalon.my.id/api/karyawan/$id'), headers: { 'Authorization': 'Bearer ${widget.token}', 'Accept': 'application/json', }, ); if (response.statusCode == 200) { fetchKaryawan(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Karyawan berhasil dihapus')), ); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Gagal menghapus karyawan')), ); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error: $e')), ); } } Future setujuiKaryawan(int id) async { try { final response = await http.put( Uri.parse('http://angeliasalon.my.id/api/karyawan/$id/approve'), headers: { 'Authorization': 'Bearer ${widget.token}', 'Accept': 'application/json', }, ); if (response.statusCode == 200) { fetchKaryawan(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Karyawan berhasil disetujui')), ); } else { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Gagal menyetujui karyawan')), ); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error: $e')), ); } } Widget buildKaryawanCard(Map karyawan) { final bool isApproved = karyawan['is_approved'] == 1; return Container( margin: const EdgeInsets.symmetric(vertical: 8), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: const [ BoxShadow( color: Colors.black12, blurRadius: 8, offset: Offset(0, 3), ) ], ), child: ListTile( leading: CircleAvatar( backgroundColor: isApproved ? Colors.green : Colors.orange, child: Text( karyawan['name'] != null && karyawan['name'].isNotEmpty ? karyawan['name'][0].toUpperCase() : '?', style: const TextStyle(color: Colors.white, fontWeight: FontWeight.bold), ), ), title: Text( karyawan['name'] ?? '', style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(karyawan['email'] ?? ''), const SizedBox(height: 4), Text( isApproved ? 'Disetujui' : 'Menunggu Persetujuan', style: TextStyle( fontWeight: FontWeight.bold, color: isApproved ? Colors.green : Colors.orange, ), ), ], ), trailing: Row( mainAxisSize: MainAxisSize.min, children: [ if (!isApproved) IconButton( icon: const Icon(Icons.check_circle_outline, color: Colors.green), tooltip: 'Setujui', onPressed: () => setujuiKaryawan(karyawan['id']), ), IconButton( icon: const Icon(Icons.delete_outline, color: Colors.red), tooltip: 'Hapus', onPressed: () => hapusKaryawan(karyawan['id']), ), ], ), ), ); } Widget buildInputForm() { return Padding( padding: const EdgeInsets.all(24), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text( 'Form Tambah Karyawan', style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), ), const SizedBox(height: 20), TextField( controller: nameController, decoration: const InputDecoration( labelText: 'Nama', prefixIcon: Icon(Icons.person), border: OutlineInputBorder(), ), ), const SizedBox(height: 15), TextField( controller: emailController, decoration: const InputDecoration( labelText: 'Email', prefixIcon: Icon(Icons.email), border: OutlineInputBorder(), ), ), const SizedBox(height: 15), TextField( controller: passwordController, obscureText: true, decoration: const InputDecoration( labelText: 'Password', prefixIcon: Icon(Icons.lock), border: OutlineInputBorder(), ), ), const SizedBox(height: 20), Center( child: ElevatedButton.icon( onPressed: tambahKaryawan, icon: const Icon(Icons.person_add), label: const Text('Tambah Karyawan'), style: ElevatedButton.styleFrom( backgroundColor: primaryColor, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), ), ), ), ), ], ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: backgroundColor, appBar: AppBar( title: const Text('Manajemen Karyawan'), backgroundColor: primaryColor, bottom: TabBar( controller: _tabController, indicatorColor: Colors.white, tabs: const [ Tab(icon: Icon(Icons.people), text: 'Daftar Karyawan'), Tab(icon: Icon(Icons.person_add_alt_1), text: 'Tambah Karyawan'), ], ), ), body: TabBarView( controller: _tabController, children: [ loading ? const Center(child: CircularProgressIndicator()) : RefreshIndicator( onRefresh: fetchKaryawan, child: ListView.builder( padding: const EdgeInsets.all(16), itemCount: karyawan.length, itemBuilder: (context, index) { final k = karyawan[index]; return buildKaryawanCard(k); }, ), ), SingleChildScrollView(child: buildInputForm()), ], ), ); } }