From 1ff6fc584eeb65338d2be17933c70913108b0777 Mon Sep 17 00:00:00 2001 From: BakoL2323 <142969559+ardiyanto1234@users.noreply.github.com> Date: Fri, 17 Apr 2026 11:36:58 +0700 Subject: [PATCH] update --- lib/api/api.dart | 4 +- lib/screens/kader/dashboardkader.dart | 2 +- lib/screens/kader/history_page.dart | 2 +- lib/screens/kader/profile_page.dart | 317 ++++++++++++++------------ 4 files changed, 180 insertions(+), 145 deletions(-) diff --git a/lib/api/api.dart b/lib/api/api.dart index 9d535f2..5410293 100644 --- a/lib/api/api.dart +++ b/lib/api/api.dart @@ -1,2 +1,2 @@ -const String baseUrl = 'http://192.168.1.6:8000/api'; -const String baseImageurl = 'http://192.168.1.6:8000/'; \ No newline at end of file +const String baseUrl = 'http://192.168.0.118:8000/api'; +const String baseImageurl = 'http://192.168.0.118:8000/'; \ No newline at end of file diff --git a/lib/screens/kader/dashboardkader.dart b/lib/screens/kader/dashboardkader.dart index 87dc33e..fe99751 100644 --- a/lib/screens/kader/dashboardkader.dart +++ b/lib/screens/kader/dashboardkader.dart @@ -55,7 +55,7 @@ class _DashboardPageState extends State { } final response = await http.get( - Uri.parse('http://192.168.1.6:8000/api/dashboard/$userId'), + Uri.parse('http://192.168.0.118:8000/api/dashboard/$userId'), ); print("STATUS: ${response.statusCode}"); diff --git a/lib/screens/kader/history_page.dart b/lib/screens/kader/history_page.dart index b3dc817..2ea0b25 100644 --- a/lib/screens/kader/history_page.dart +++ b/lib/screens/kader/history_page.dart @@ -20,7 +20,7 @@ class _HistoryPageState extends State { bool isLoading = true; - final String apiUrl = "http://192.168.1.6:8000/api/laporan"; + final String apiUrl = "http://192.168.0.118:8000/api/laporan"; @override void initState() { diff --git a/lib/screens/kader/profile_page.dart b/lib/screens/kader/profile_page.dart index dff36e7..8e19162 100644 --- a/lib/screens/kader/profile_page.dart +++ b/lib/screens/kader/profile_page.dart @@ -24,23 +24,33 @@ class _ProfilePageState extends State { // GET PROFILE // ========================== Future getProfile() async { - final response = await http.get( - Uri.parse("http://192.168.1.6:8000/api/profile"), - headers: {"Accept": "application/json"}, - ); + try { + final response = await http.get( + Uri.parse("http://192.168.0.118:8000/api/profile?user_id=4"), + headers: {"Accept": "application/json"}, + ); - print(response.statusCode); - print(response.body); + print(response.statusCode); + print(response.body); - if (response.statusCode == 200) { - final data = jsonDecode(response.body); + if (response.statusCode == 200) { + final data = jsonDecode(response.body); + setState(() { + user = data['user']; + isLoading = false; + }); + } else { + setState(() { + isLoading = false; + }); + print("Error API"); + } + } catch (e) { setState(() { - user = data['user']; isLoading = false; }); - } else { - print("Error API"); + print("Error: $e"); } } @@ -48,7 +58,8 @@ class _ProfilePageState extends State { // PICK IMAGE // ========================== Future _pickImage() async { - final XFile? picked = await _picker.pickImage(source: ImageSource.gallery); + final XFile? picked = + await _picker.pickImage(source: ImageSource.gallery); if (picked != null) { setState(() { @@ -63,26 +74,49 @@ class _ProfilePageState extends State { // UPLOAD PHOTO // ========================== Future uploadPhoto() async { - var request = http.MultipartRequest( - "POST", - Uri.parse("http://192.168.1.6:8000/api/upload-photo"), - ); - - request.headers['Accept'] = 'application/json'; - - request.fields['user_id'] = user!['id'].toString(); - - request.files.add( - await http.MultipartFile.fromPath('profile_photo', _imageFile!.path), - ); - - var response = await request.send(); - - if (response.statusCode == 200) { + try { setState(() { - _imageFile = null; // reset biar ambil dari server + isLoading = true; }); - getProfile(); + + var request = http.MultipartRequest( + "POST", + Uri.parse("http://192.168.0.118:8000/api/upload-photo"), + ); + + request.headers['Accept'] = 'application/json'; + request.fields['user_id'] = user?['id'].toString() ?? "0"; + + request.files.add( + await http.MultipartFile.fromPath( + 'profile_photo', + _imageFile!.path, + ), + ); + + var streamedResponse = await request.send(); + var response = await http.Response.fromStream(streamedResponse); + + print(response.statusCode); + print(response.body); + + if (response.statusCode == 200) { + setState(() { + _imageFile = null; + }); + + await getProfile(); // refresh + } else { + setState(() { + isLoading = false; + }); + print("Upload gagal"); + } + } catch (e) { + setState(() { + isLoading = false; + }); + print("Error upload: $e"); } } @@ -92,131 +126,132 @@ class _ProfilePageState extends State { getProfile(); } - // 🔥 Tambahan supaya refresh saat balik ke halaman ini - @override - void didChangeDependencies() { - super.didChangeDependencies(); - getProfile(); - } - @override Widget build(BuildContext context) { - if (isLoading) { - return const Center(child: CircularProgressIndicator()); + // 🔥 ANTI CRASH + if (isLoading || user == null) { + return const Scaffold( + body: Center(child: CircularProgressIndicator()), + ); } - return SingleChildScrollView( - padding: const EdgeInsets.all(16), - child: Column( - children: [ - // ====================== - // HEADER PROFILE - // ====================== - Container( - padding: const EdgeInsets.all(20), - decoration: BoxDecoration( - gradient: const LinearGradient( - colors: [AppColors.button, AppColors.button], + return Scaffold( + body: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + // ====================== + // HEADER PROFILE + // ====================== + Container( + padding: const EdgeInsets.all(20), + decoration: BoxDecoration( + gradient: const LinearGradient( + colors: [AppColors.button, AppColors.button], + ), + borderRadius: BorderRadius.circular(16), ), - borderRadius: BorderRadius.circular(16), - ), - child: Column( - children: [ - // PHOTO - CircleAvatar( - radius: 60, - backgroundColor: Colors.white, - backgroundImage: _imageFile != null - ? FileImage(File(_imageFile!.path)) - : user!['photo_url'] != null - // 🔥 CACHE BUSTER DI SINI - ? NetworkImage( - user!['photo_url'] + - "?t=${DateTime.now().millisecondsSinceEpoch}", - ) - : null, - child: user!['photo_url'] == null && _imageFile == null - ? const Icon(Icons.person, size: 60) - : null, - ), - - const SizedBox(height: 12), - - Text( - user!['name'], - style: const TextStyle( - fontSize: 22, - fontWeight: FontWeight.bold, - color: Colors.white, - ), - ), - - const SizedBox(height: 4), - - Text( - user!['role'], - style: const TextStyle(color: Colors.white70), - ), - - const SizedBox(height: 16), - - ElevatedButton.icon( - onPressed: _pickImage, - icon: const Icon(Icons.camera_alt), - label: const Text("Ubah Foto"), - style: ElevatedButton.styleFrom( + child: Column( + children: [ + // PHOTO + CircleAvatar( + radius: 60, backgroundColor: Colors.white, - foregroundColor: const Color(0xFF206E97), + backgroundImage: _imageFile != null + ? FileImage(File(_imageFile!.path)) + : (user?['photo_url'] != null + ? NetworkImage( + user!['photo_url'] + + "?t=${DateTime.now().millisecondsSinceEpoch}", + ) + : null), + child: (user?['photo_url'] == null && + _imageFile == null) + ? const Icon(Icons.person, size: 60) + : null, ), - ), - ], + + const SizedBox(height: 12), + + Text( + user?['name'] ?? "-", + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + color: Colors.white, + ), + ), + + const SizedBox(height: 4), + + Text( + user?['role'] ?? "-", + style: const TextStyle(color: Colors.white70), + ), + + const SizedBox(height: 16), + + ElevatedButton.icon( + onPressed: _pickImage, + icon: const Icon(Icons.camera_alt), + label: const Text("Ubah Foto"), + style: ElevatedButton.styleFrom( + backgroundColor: Colors.white, + foregroundColor: const Color(0xFF206E97), + ), + ), + ], + ), ), - ), - const SizedBox(height: 20), + const SizedBox(height: 20), - // ====================== - // DETAIL PROFILE - // ====================== - Card( - child: Column( - children: [ - ListTile( - leading: const Icon(Icons.email), - title: const Text("Email"), - subtitle: Text(user!['email']), - ), - - const Divider(), - - ListTile( - leading: const Icon(Icons.home), - title: const Text("Alamat"), - subtitle: Text(user!['address'] ?? "-"), - ), - ], + // ====================== + // DETAIL PROFILE + // ====================== + Card( + child: Column( + children: [ + ListTile( + leading: const Icon(Icons.email), + title: const Text("Email"), + subtitle: Text(user?['email'] ?? "-"), + ), + const Divider(), + ListTile( + leading: const Icon(Icons.home), + title: const Text("Alamat"), + subtitle: Text(user?['address'] ?? "-"), + ), + ], + ), ), - ), - const SizedBox(height: 20), + const SizedBox(height: 20), - // ====================== - // LOGOUT - // ====================== - Card( - child: ListTile( - leading: const Icon(Icons.logout, color: Colors.red), - title: const Text("Logout", style: TextStyle(color: Colors.red)), - onTap: () { - Navigator.pushAndRemoveUntil( - context, - MaterialPageRoute(builder: (context) => const LoginPage()), - (route) => false, - ); - }, + // ====================== + // LOGOUT + // ====================== + Card( + child: ListTile( + leading: const Icon(Icons.logout, color: Colors.red), + title: const Text( + "Logout", + style: TextStyle(color: Colors.red), + ), + onTap: () { + Navigator.pushAndRemoveUntil( + context, + MaterialPageRoute( + builder: (context) => const LoginPage(), + ), + (route) => false, + ); + }, + ), ), - ), - ], + ], + ), ), ); }