MIF_E31222854_MOBILE/lib/view/pengajar/kemajuan/kemajuan.dart

387 lines
14 KiB
Dart

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:go_router/go_router.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:ta_tahsin/core/baseurl/base_url.dart';
import 'package:ta_tahsin/core/theme.dart';
class ProgressBar extends StatelessWidget {
final double progress;
const ProgressBar({super.key, required this.progress});
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 5),
Stack(
alignment: Alignment.center,
children: [
// Linear Progress Bar with rounded corners
SizedBox(
height: 20,
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: LinearProgressIndicator(
value: progress,
backgroundColor: Colors.grey[300],
color: secondPrimaryColor,
minHeight: 5,
),
),
),
// Percentage text overlaying the progress bar
Positioned(
child: Text(
'${(progress * 100).toStringAsFixed(1)}%',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
],
),
],
);
}
}
class KemajuanPage extends StatefulWidget {
const KemajuanPage({super.key});
@override
State<KemajuanPage> createState() => _KemajuanPageState();
}
class _KemajuanPageState extends State<KemajuanPage> {
List<dynamic> kemajuanList = []; // Menyimpan list kemajuan
List<dynamic> filteredKemajuanList = []; // Menyimpan list hasil filter
bool isLoading = true; // Menandakan apakah data sedang dimuat
String searchQuery = ""; // Menyimpan query pencarian
// Menyimpan status progres yang sudah dimuat
Set<int> loadedUserIds = Set();
// Fungsi untuk mengambil data kemajuan
Future<void> fetchKemajuanData() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? token = prefs.getString('token');
try {
final response = await http.get(
Uri.parse('${BaseUrl.baseUrl}/users/progres'),
headers: {
'Authorization': 'Bearer $token',
},
);
if (response.statusCode == 200) {
var data = json.decode(response.body);
if (data['data'] == null || (data['data'] as List).isEmpty) {
// If no data found, show a warning message
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
const Icon(Icons.warning, color: Colors.white),
const SizedBox(width: 10),
Expanded(
child: Text(
'Tidak ada santri yang menyelesaikan latihan.',
style: const TextStyle(color: Colors.white),
),
),
],
),
backgroundColor: Colors.orange, // Set the background color for warning
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
bottomLeft: Radius.zero,
bottomRight: Radius.zero,
),
),
),
);
} else {
setState(() {
kemajuanList = data['data']; // Menyimpan data kemajuan
filteredKemajuanList = kemajuanList;
isLoading = false;
});
// Setelah data kemajuan berhasil dimuat, panggil fetchProgressData untuk setiap user yang belum dimuat
for (var kemajuan in kemajuanList) {
if (!loadedUserIds.contains(kemajuan['user_id'])) {
fetchProgressData(kemajuan['user_id']);
loadedUserIds.add(kemajuan['user_id']); // Tandai user_id yang sudah dimuat
}
}
}
} else {
setState(() {
isLoading = false;
});
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
const Icon(Icons.error, color: Colors.white),
const SizedBox(width: 10),
Expanded(
child: Text(
'Gagal memuat data kemajuan: ${response.body}',
style: const TextStyle(color: Colors.white),
),
),
],
),
backgroundColor: Colors.red, // Set the background color for error
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
bottomLeft: Radius.zero,
bottomRight: Radius.zero,
),
),
),
);
}
} catch (e) {
setState(() {
isLoading = false;
});
print('Error occurred: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
const Icon(Icons.error, color: Colors.white),
const SizedBox(width: 10),
Expanded(
child: Text(
'Terjadi kesalahan saat mengambil data: $e',
style: const TextStyle(color: Colors.white),
),
),
],
),
backgroundColor: Colors.red, // Set the background color for error
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(10),
topRight: Radius.circular(10),
bottomLeft: Radius.zero,
bottomRight: Radius.zero,
),
),
),
);
}
}
// Fungsi untuk mengambil data progres berdasarkan userId
Future<void> fetchProgressData(int userId) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String? authToken = prefs.getString('token');
debugPrint("Token yang diambil: $authToken");
final response = await http.get(
Uri.parse('${BaseUrl.baseUrl}/progres/$userId'), // API URL yang sesuai
headers: {
'Authorization': 'Bearer $authToken',
},
);
if (response.statusCode == 200) {
final data = json.decode(response.body);
setState(() {
// Menyimpan progress untuk setiap user
final index = kemajuanList.indexWhere((item) => item['user_id'] == userId);
if (index != -1) {
kemajuanList[index]['progress_percentage'] = data['progress_percentage']; // Menambahkan progres
}
});
} else {
print('Failed to load progress data');
}
}
// Fungsi untuk memfilter data berdasarkan nama
void filterKemajuan(String query) {
final filtered = kemajuanList.where((kemajuan) {
final nama = kemajuan['nama_lengkap'].toLowerCase();
final search = query.toLowerCase();
return nama.contains(search); // Pencarian berdasarkan nama lengkap
}).toList();
setState(() {
filteredKemajuanList = filtered; // Update list yang ditampilkan
});
}
@override
void initState() {
super.initState();
fetchKemajuanData(); // Memanggil fungsi saat halaman pertama kali dibuka
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Kemajuan'),
automaticallyImplyLeading: false,
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Search bar
TextField(
onChanged: (query) {
setState(() {
searchQuery = query;
filterKemajuan(searchQuery);
});
},
decoration: InputDecoration(
prefixIcon: const Icon(Icons.search),
hintText: 'Cari Santri...',
hintStyle: TextStyle(color: Colors.grey),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(12),
borderSide: BorderSide(color: secondPrimaryColor),
),
),
),
const SizedBox(height: 20),
// Judul Pilih Santri
Text(
'Pilih Santri',
style: TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
color: secondPrimaryColor,
),
),
const SizedBox(height: 10),
// Jika loading, tampilkan loading indicator
if (isLoading)
Center(child: CircularProgressIndicator())
else if (filteredKemajuanList.isEmpty)
Center(child: Text('Tidak ada progres latihan yang ditemukan.'))
else
// Menggunakan SliverList dengan kemajuanList yang sudah difilter
Expanded(
child: CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
var kemajuan = filteredKemajuanList[index];
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(bottom: 0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
contentPadding: const EdgeInsets.symmetric(vertical: 5.0),
leading: Container(
width: 60,
height: 60,
decoration: BoxDecoration(
shape: BoxShape.circle,
image: DecorationImage(
image: AssetImage(
'assets/icon/defaultprofile.jpeg',
),
fit: BoxFit.cover,
),
),
),
title: Row(
children: [
Expanded(
child: Text(
kemajuan['nama_lengkap'],
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
),
],
),
subtitle: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
kemajuan['no_telp_wali'],
style: const TextStyle(
fontSize: 14,
color: Colors.grey,
),
),
// Menggunakan widget ProgressBar
ProgressBar(
progress: kemajuan['progress_percentage'] != null
? kemajuan['progress_percentage'] / 100
: 0.0,
),
],
),
onTap: () {
context.go('/detail_kemajuan', extra: {
'nama': kemajuan['nama_lengkap'],
'user_id': kemajuan['user_id'],
});
},
),
Divider(
color: Colors.grey.withOpacity(0.5),
thickness: 1,
indent: 40,
),
],
),
),
],
),
);
},
childCount: filteredKemajuanList.length,
),
),
],
),
),
],
),
),
);
}
}