fix : bug di riwayat user
This commit is contained in:
parent
6d87d8d0a1
commit
f2af845287
|
@ -133,6 +133,7 @@ exports.diagnosa = async (req, res) => {
|
||||||
...sortedHama.map(h => ({ type: 'hama', ...h }))
|
...sortedHama.map(h => ({ type: 'hama', ...h }))
|
||||||
].sort((a, b) => b.probabilitas_persen - a.probabilitas_persen);
|
].sort((a, b) => b.probabilitas_persen - a.probabilitas_persen);
|
||||||
|
|
||||||
|
// Simpan histori diagnosa jika ada user yang login dan ada hasil diagnosa
|
||||||
// Simpan histori diagnosa jika ada user yang login dan ada hasil diagnosa
|
// Simpan histori diagnosa jika ada user yang login dan ada hasil diagnosa
|
||||||
if (!userId) {
|
if (!userId) {
|
||||||
console.error('ID user tidak ditemukan. Histori tidak dapat disimpan.');
|
console.error('ID user tidak ditemukan. Histori tidak dapat disimpan.');
|
||||||
|
@ -144,9 +145,13 @@ exports.diagnosa = async (req, res) => {
|
||||||
return current.probabilitas_persen > max.probabilitas_persen ? current : max;
|
return current.probabilitas_persen > max.probabilitas_persen ? current : max;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Dapatkan waktu saat ini dalam zona waktu Indonesia (GMT+7)
|
||||||
|
const now = new Date();
|
||||||
|
const jakartaTime = new Date(now.getTime() + (7 * 60 * 60 * 1000)); // GMT+7 (WIB)
|
||||||
|
|
||||||
const baseHistoriData = {
|
const baseHistoriData = {
|
||||||
userId: userId, // harus ada
|
userId: userId, // harus ada
|
||||||
tanggal_diagnosa: tanggal_diagnosa, // harus ada
|
tanggal_diagnosa: jakartaTime, // Menggunakan waktu real-time Indonesia
|
||||||
hasil: hasilTerbesar.nilai_bayes, // harus ada, harus tipe FLOAT
|
hasil: hasilTerbesar.nilai_bayes, // harus ada, harus tipe FLOAT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,7 +171,7 @@ exports.diagnosa = async (req, res) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
await Promise.all(historiPromises);
|
await Promise.all(historiPromises);
|
||||||
console.log(`Histori berhasil disimpan untuk ${gejala.length} gejala.`);
|
console.log(`Histori berhasil disimpan untuk ${gejala.length} gejala dengan waktu: ${jakartaTime.toISOString()}`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Gagal menyimpan histori:', error.message);
|
console.error('Gagal menyimpan histori:', error.message);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,16 @@ class AdminHistoriPage extends StatefulWidget {
|
||||||
class _AdminHistoriPageState extends State<AdminHistoriPage> {
|
class _AdminHistoriPageState extends State<AdminHistoriPage> {
|
||||||
final ApiService apiService = ApiService();
|
final ApiService apiService = ApiService();
|
||||||
List<Map<String, dynamic>> historiData = [];
|
List<Map<String, dynamic>> historiData = [];
|
||||||
|
List<Map<String, dynamic>> groupedHistoriData = [];
|
||||||
bool isLoading = true;
|
bool isLoading = true;
|
||||||
String? error;
|
String? error;
|
||||||
|
|
||||||
|
// Pagination variables
|
||||||
|
int _rowsPerPage = 10;
|
||||||
|
int _currentPage = 0;
|
||||||
|
int _totalPages = 0;
|
||||||
|
List<Map<String, dynamic>> _currentPageData = [];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
@ -33,13 +40,20 @@ class _AdminHistoriPageState extends State<AdminHistoriPage> {
|
||||||
List<Map<String, dynamic>> detailedHistori = [];
|
List<Map<String, dynamic>> detailedHistori = [];
|
||||||
for (var histori in allHistori) {
|
for (var histori in allHistori) {
|
||||||
if (histori['userId'] != null) {
|
if (histori['userId'] != null) {
|
||||||
final userHistori = await apiService.fetchHistoriDenganDetail(histori['userId'].toString());
|
final userHistori = await apiService.fetchHistoriDenganDetail(
|
||||||
|
histori['userId'].toString(),
|
||||||
|
);
|
||||||
detailedHistori.addAll(userHistori);
|
detailedHistori.addAll(userHistori);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Kelompokkan data berdasarkan user, diagnosa, dan waktu yang sama
|
||||||
|
final groupedData = _groupHistoriData(detailedHistori);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
historiData = detailedHistori;
|
historiData = detailedHistori; // Simpan data asli jika perlu
|
||||||
|
groupedHistoriData = groupedData; // Data yang sudah dikelompokkan
|
||||||
|
_updatePagination(0); // Set halaman pertama
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -50,6 +64,100 @@ class _AdminHistoriPageState extends State<AdminHistoriPage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fungsi untuk mengelompokkan data berdasarkan userId, diagnosa, dan waktu
|
||||||
|
|
||||||
|
// Fungsi untuk mengelompokkan data berdasarkan userId, diagnosa, dan waktu
|
||||||
|
List<Map<String, dynamic>> _groupHistoriData(
|
||||||
|
List<Map<String, dynamic>> data,
|
||||||
|
) {
|
||||||
|
Map<String, Map<String, dynamic>> groupedMap = {};
|
||||||
|
|
||||||
|
for (var item in data) {
|
||||||
|
if (item['userId'] == null || item['tanggal_diagnosa'] == null) continue;
|
||||||
|
|
||||||
|
// Parse tanggal
|
||||||
|
DateTime dateTime;
|
||||||
|
try {
|
||||||
|
dateTime = DateTime.parse(item['tanggal_diagnosa']);
|
||||||
|
} catch (e) {
|
||||||
|
print("Error parsing date: $e");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format tanggal untuk pengelompokan (menit, bukan detik)
|
||||||
|
String formattedTime = DateFormat('yyyy-MM-dd HH:mm').format(dateTime);
|
||||||
|
|
||||||
|
// Identifikasi diagnosa
|
||||||
|
String diagnosa = '';
|
||||||
|
if (item['penyakit_nama'] != null &&
|
||||||
|
item['penyakit_nama'].toString().isNotEmpty) {
|
||||||
|
diagnosa = 'Penyakit: ${item['penyakit_nama']}';
|
||||||
|
} else if (item['hama_nama'] != null &&
|
||||||
|
item['hama_nama'].toString().isNotEmpty) {
|
||||||
|
diagnosa = 'Hama: ${item['hama_nama']}';
|
||||||
|
} else {
|
||||||
|
diagnosa = 'Tidak ada diagnosa';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambil nama user dari kolom 'nama' atau 'name' (sesuaikan dengan struktur data Anda)
|
||||||
|
String userName = item['name']?.toString() ?? 'User ID: ${item['userId']}';
|
||||||
|
|
||||||
|
// Buat composite key: userId + waktu + diagnosa
|
||||||
|
String key = '${item['userId']}_${formattedTime}_$diagnosa';
|
||||||
|
|
||||||
|
if (!groupedMap.containsKey(key)) {
|
||||||
|
// Format tanggal yang lebih ramah untuk tampilan
|
||||||
|
String displayDate = DateFormat('dd/MM/yyyy HH:mm').format(dateTime);
|
||||||
|
|
||||||
|
groupedMap[key] = {
|
||||||
|
'userId': item['userId'],
|
||||||
|
'userName': userName, // Menampilkan nama user, bukan ID
|
||||||
|
'diagnosa': diagnosa,
|
||||||
|
'tanggal_diagnosa': item['tanggal_diagnosa'],
|
||||||
|
'tanggal_display': displayDate,
|
||||||
|
'gejala': [],
|
||||||
|
'hasil': item['hasil'],
|
||||||
|
'penyakit_nama': item['penyakit_nama'],
|
||||||
|
'hama_nama': item['hama_nama'],
|
||||||
|
'sortTime': dateTime.millisecondsSinceEpoch, // untuk pengurutan
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tambahkan gejala jika belum ada dalam list
|
||||||
|
if (item['gejala_nama'] != null &&
|
||||||
|
!groupedMap[key]!['gejala'].contains(item['gejala_nama'])) {
|
||||||
|
groupedMap[key]!['gejala'].add(item['gejala_nama']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Konversi map ke list dan urutkan berdasarkan waktu terbaru
|
||||||
|
List<Map<String, dynamic>> result = groupedMap.values.toList();
|
||||||
|
result.sort(
|
||||||
|
(a, b) => (b['sortTime'] as int).compareTo(a['sortTime'] as int),
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update pagination
|
||||||
|
void _updatePagination(int page) {
|
||||||
|
_currentPage = page;
|
||||||
|
_totalPages = (groupedHistoriData.length / _rowsPerPage).ceil();
|
||||||
|
|
||||||
|
int startIndex = page * _rowsPerPage;
|
||||||
|
int endIndex = (page + 1) * _rowsPerPage;
|
||||||
|
|
||||||
|
if (endIndex > groupedHistoriData.length) {
|
||||||
|
endIndex = groupedHistoriData.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startIndex >= groupedHistoriData.length) {
|
||||||
|
_currentPageData = [];
|
||||||
|
} else {
|
||||||
|
_currentPageData = groupedHistoriData.sublist(startIndex, endIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
@ -57,19 +165,20 @@ class _AdminHistoriPageState extends State<AdminHistoriPage> {
|
||||||
title: Text('Riwayat Diagnosa'),
|
title: Text('Riwayat Diagnosa'),
|
||||||
backgroundColor: Color(0xFF9DC08D),
|
backgroundColor: Color(0xFF9DC08D),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(icon: Icon(Icons.refresh), onPressed: _loadHistoriData),
|
||||||
icon: Icon(Icons.refresh),
|
|
||||||
onPressed: _loadHistoriData,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: isLoading
|
body:
|
||||||
|
isLoading
|
||||||
? Center(child: CircularProgressIndicator())
|
? Center(child: CircularProgressIndicator())
|
||||||
: error != null
|
: error != null
|
||||||
? Center(child: Text('Error: $error'))
|
? Center(child: Text('Error: $error'))
|
||||||
: historiData.isEmpty
|
: groupedHistoriData.isEmpty
|
||||||
? Center(child: Text('Tidak ada data riwayat diagnosa'))
|
? Center(child: Text('Tidak ada data riwayat diagnosa'))
|
||||||
: SingleChildScrollView(
|
: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: SingleChildScrollView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: DataTable(
|
child: DataTable(
|
||||||
|
@ -78,23 +187,60 @@ class _AdminHistoriPageState extends State<AdminHistoriPage> {
|
||||||
Color(0xFF9DC08D).withOpacity(0.3),
|
Color(0xFF9DC08D).withOpacity(0.3),
|
||||||
),
|
),
|
||||||
columns: [
|
columns: [
|
||||||
DataColumn(label: Text('Nama User', style: TextStyle(fontWeight: FontWeight.bold))),
|
DataColumn(
|
||||||
DataColumn(label: Text('Gejala', style: TextStyle(fontWeight: FontWeight.bold))),
|
label: Text(
|
||||||
DataColumn(label: Text('Diagnosa', style: TextStyle(fontWeight: FontWeight.bold))),
|
'Nama User',
|
||||||
DataColumn(label: Text('Hasil', style: TextStyle(fontWeight: FontWeight.bold))),
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
DataColumn(label: Text('Tanggal', style: TextStyle(fontWeight: FontWeight.bold))),
|
),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text(
|
||||||
|
'Gejala',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text(
|
||||||
|
'Diagnosa',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text(
|
||||||
|
'Hasil',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DataColumn(
|
||||||
|
label: Text(
|
||||||
|
'Tanggal',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
rows: historiData.map((histori) {
|
rows:
|
||||||
|
_currentPageData.map((histori) {
|
||||||
|
// Gabungkan semua gejala menjadi satu string dengan koma
|
||||||
|
String gejalaText = "Tidak ada gejala";
|
||||||
|
if (histori['gejala'] != null &&
|
||||||
|
(histori['gejala'] as List).isNotEmpty) {
|
||||||
|
gejalaText = (histori['gejala'] as List).join(
|
||||||
|
', ',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return DataRow(
|
return DataRow(
|
||||||
cells: [
|
cells: [
|
||||||
DataCell(Text(histori['name'] ?? 'Unknown')), // Changed 'name' to 'user_name'
|
DataCell(Text(histori['userName'] ?? 'User tidak ditemukan')),
|
||||||
DataCell(
|
DataCell(
|
||||||
Container(
|
Container(
|
||||||
constraints: BoxConstraints(maxWidth: 200),
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: 200,
|
||||||
|
),
|
||||||
child: Tooltip(
|
child: Tooltip(
|
||||||
message: histori['gejala_nama'] ?? 'Tidak ada gejala',
|
message: gejalaText,
|
||||||
child: Text(
|
child: Text(
|
||||||
histori['gejala_nama'] ?? 'Tidak ada gejala',
|
gejalaText,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -102,45 +248,131 @@ class _AdminHistoriPageState extends State<AdminHistoriPage> {
|
||||||
),
|
),
|
||||||
DataCell(
|
DataCell(
|
||||||
Text(
|
Text(
|
||||||
_getDiagnosaText(histori),
|
histori['diagnosa'] ??
|
||||||
// Removed style with color formatting
|
'Tidak ada diagnosa',
|
||||||
)
|
style: TextStyle(
|
||||||
|
color: _getDiagnosaColor(histori),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
DataCell(
|
||||||
|
Text(_formatHasil(histori['hasil'])),
|
||||||
|
),
|
||||||
|
DataCell(
|
||||||
|
Text(histori['tanggal_display'] ?? ''),
|
||||||
),
|
),
|
||||||
DataCell(Text(_formatHasil(histori['hasil']))),
|
|
||||||
DataCell(Text(_formatDate(histori['tanggal_diagnosa']))),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
// Pagination controls
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.all(16),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.first_page),
|
||||||
|
onPressed:
|
||||||
|
_currentPage > 0
|
||||||
|
? () {
|
||||||
|
setState(() {
|
||||||
|
_updatePagination(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.chevron_left),
|
||||||
|
onPressed:
|
||||||
|
_currentPage > 0
|
||||||
|
? () {
|
||||||
|
setState(() {
|
||||||
|
_updatePagination(_currentPage - 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
SizedBox(width: 20),
|
||||||
|
Text(
|
||||||
|
'Halaman ${_currentPage + 1} dari $_totalPages',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
SizedBox(width: 20),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.chevron_right),
|
||||||
|
onPressed:
|
||||||
|
_currentPage < _totalPages - 1
|
||||||
|
? () {
|
||||||
|
setState(() {
|
||||||
|
_updatePagination(_currentPage + 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.last_page),
|
||||||
|
onPressed:
|
||||||
|
_currentPage < _totalPages - 1
|
||||||
|
? () {
|
||||||
|
setState(() {
|
||||||
|
_updatePagination(_totalPages - 1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Rows per page selector
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.only(bottom: 16),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text('Rows per page: '),
|
||||||
|
DropdownButton<int>(
|
||||||
|
value: _rowsPerPage,
|
||||||
|
items:
|
||||||
|
[10, 20, 50, 100].map((value) {
|
||||||
|
return DropdownMenuItem<int>(
|
||||||
|
value: value,
|
||||||
|
child: Text('$value'),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_rowsPerPage = value!;
|
||||||
|
_updatePagination(
|
||||||
|
0,
|
||||||
|
); // Kembali ke halaman pertama
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getDiagnosaText(Map<String, dynamic> histori) {
|
Color _getDiagnosaColor(Map<String, dynamic> histori) {
|
||||||
if (histori['penyakit_nama'] != null) {
|
if (histori['penyakit_nama'] != null) {
|
||||||
return 'Penyakit: ${histori['penyakit_nama']}';
|
return Colors.red[700]!;
|
||||||
} else if (histori['hama_nama'] != null) {
|
} else if (histori['hama_nama'] != null) {
|
||||||
return 'Hama: ${histori['hama_nama']}';
|
return Colors.amber[800]!;
|
||||||
}
|
}
|
||||||
return 'Tidak ada diagnosa';
|
return Colors.black;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removed _getDiagnosaColor method as it's no longer needed
|
|
||||||
|
|
||||||
String _formatHasil(dynamic hasil) {
|
String _formatHasil(dynamic hasil) {
|
||||||
if (hasil == null) return '0%';
|
if (hasil == null) return '0%';
|
||||||
double hasilValue = double.tryParse(hasil.toString()) ?? 0.0;
|
double hasilValue = double.tryParse(hasil.toString()) ?? 0.0;
|
||||||
return '${(hasilValue * 100).toStringAsFixed(2)}%';
|
return '${(hasilValue * 100).toStringAsFixed(2)}%';
|
||||||
}
|
}
|
||||||
|
|
||||||
String _formatDate(dynamic tanggal) {
|
|
||||||
if (tanggal == null) return '';
|
|
||||||
try {
|
|
||||||
DateTime date = DateTime.parse(tanggal.toString());
|
|
||||||
return DateFormat('dd/MM/yyyy HH:mm').format(date);
|
|
||||||
} catch (e) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -170,15 +170,15 @@ class _AdminPageState extends State<AdminPage> {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
// ListTile(
|
ListTile(
|
||||||
// title: Text('Halaman Histori User'),
|
title: Text('Halaman Histori User'),
|
||||||
// onTap: () {
|
onTap: () {
|
||||||
// Navigator.push(
|
Navigator.push(
|
||||||
// context,
|
context,
|
||||||
// MaterialPageRoute(builder: (context) => AdminHistoriPage()),
|
MaterialPageRoute(builder: (context) => AdminHistoriPage()),
|
||||||
// );
|
);
|
||||||
// },
|
},
|
||||||
// ),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: Text('Data Pengguna'),
|
title: Text('Data Pengguna'),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|
|
@ -150,20 +150,23 @@ class _RiwayatDiagnosaPageState extends State<RiwayatDiagnosaPage> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fungsi baru untuk mengelompokkan berdasarkan diagnosis dan waktu yang sama
|
||||||
List<Map<String, dynamic>> _groupHistoriByDiagnosis(
|
List<Map<String, dynamic>> _groupHistoriByDiagnosis(
|
||||||
List<Map<String, dynamic>> data,
|
List<Map<String, dynamic>> data,
|
||||||
) {
|
) {
|
||||||
final Map<String, Map<String, dynamic>> groupedData = {};
|
final Map<String, Map<String, dynamic>> groupedData = {};
|
||||||
print("Data mentah dari API: $data");
|
print("Data mentah dari API (setelah filter userId): $data");
|
||||||
|
|
||||||
for (var item in data) {
|
for (var item in data) {
|
||||||
final String? penyakitNama = item['penyakit_nama'];
|
final String? penyakitNama = item['penyakit_nama'];
|
||||||
final String? hamaNama = item['hama_nama'];
|
final String? hamaNama = item['hama_nama'];
|
||||||
|
final String? tanggalDiagnosa = item['tanggal_diagnosa'];
|
||||||
|
|
||||||
final int? idPenyakit = item['id_penyakit'];
|
final int? idPenyakit = item['id_penyakit'];
|
||||||
final int? idHama = item['id_hama'];
|
final int? idHama = item['id_hama'];
|
||||||
|
|
||||||
final hasPenyakit = penyakitNama != null && penyakitNama.toString().isNotEmpty;
|
final hasPenyakit =
|
||||||
|
penyakitNama != null && penyakitNama.toString().isNotEmpty;
|
||||||
final hasHama = hamaNama != null && hamaNama.toString().isNotEmpty;
|
final hasHama = hamaNama != null && hamaNama.toString().isNotEmpty;
|
||||||
|
|
||||||
if (!hasPenyakit && !hasHama) {
|
if (!hasPenyakit && !hasHama) {
|
||||||
|
@ -171,6 +174,11 @@ class _RiwayatDiagnosaPageState extends State<RiwayatDiagnosaPage> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tanggalDiagnosa == null) {
|
||||||
|
print("Item dilewati karena tidak memiliki tanggal diagnosa: $item");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Gabungkan nama penyakit dan hama jika keduanya ada
|
// Gabungkan nama penyakit dan hama jika keduanya ada
|
||||||
String diagnosisKey = '';
|
String diagnosisKey = '';
|
||||||
if (hasPenyakit && hasHama) {
|
if (hasPenyakit && hasHama) {
|
||||||
|
@ -181,7 +189,7 @@ class _RiwayatDiagnosaPageState extends State<RiwayatDiagnosaPage> {
|
||||||
diagnosisKey = hamaNama!;
|
diagnosisKey = hamaNama!;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tentukan diagnosis_type hanya sebagai referensi
|
// Tentukan diagnosis_type
|
||||||
String diagnosisType =
|
String diagnosisType =
|
||||||
hasPenyakit && hasHama
|
hasPenyakit && hasHama
|
||||||
? 'penyakit & hama'
|
? 'penyakit & hama'
|
||||||
|
@ -189,34 +197,75 @@ class _RiwayatDiagnosaPageState extends State<RiwayatDiagnosaPage> {
|
||||||
? 'penyakit'
|
? 'penyakit'
|
||||||
: 'hama';
|
: 'hama';
|
||||||
|
|
||||||
|
// Format tanggal waktu ke format Indonesia
|
||||||
|
String formattedDateTime = '';
|
||||||
|
String rawDateTime = '';
|
||||||
|
DateTime dateTime;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Parsing tanggal dari string yang datang dari API
|
||||||
|
dateTime = DateTime.parse(tanggalDiagnosa);
|
||||||
|
|
||||||
|
// Buat format tanggal dan waktu yang lebih ramah pengguna
|
||||||
|
String day = dateTime.day.toString().padLeft(2, '0');
|
||||||
|
String month = dateTime.month.toString().padLeft(2, '0');
|
||||||
|
String year = dateTime.year.toString();
|
||||||
|
String hour = dateTime.hour.toString().padLeft(2, '0');
|
||||||
|
String minute = dateTime.minute.toString().padLeft(2, '0');
|
||||||
|
String second = dateTime.second.toString().padLeft(2, '0');
|
||||||
|
|
||||||
|
formattedDateTime = '$day-$month-$year $hour:$minute:$second WIB';
|
||||||
|
|
||||||
|
// Format timestamp untuk pengelompokan (tanpa detik untuk mengelompokkan waktu yang "sama")
|
||||||
|
rawDateTime = '$year-$month-$day $hour:$minute';
|
||||||
|
} catch (e) {
|
||||||
|
print("Error parsing date: $e for date: $tanggalDiagnosa");
|
||||||
|
formattedDateTime = 'Tanggal tidak valid';
|
||||||
|
rawDateTime = 'invalid';
|
||||||
|
continue; // Skip item with invalid date
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buat composite key untuk pengelompokan (gabungan diagnosa dan waktu)
|
||||||
|
final compositeKey = '$diagnosisKey##$rawDateTime';
|
||||||
|
|
||||||
// Inisialisasi grup jika belum ada
|
// Inisialisasi grup jika belum ada
|
||||||
if (!groupedData.containsKey(diagnosisKey)) {
|
if (!groupedData.containsKey(compositeKey)) {
|
||||||
groupedData[diagnosisKey] = {
|
groupedData[compositeKey] = {
|
||||||
'diagnosis': diagnosisKey,
|
'diagnosis': diagnosisKey,
|
||||||
'diagnosis_type': diagnosisType,
|
'diagnosis_type': diagnosisType,
|
||||||
'gejala': <String>[],
|
'gejala': <String>[],
|
||||||
'hasil': item['hasil'],
|
'hasil': item['hasil'],
|
||||||
'tanggal_diagnosa': item['tanggal_diagnosa'],
|
'tanggal_diagnosa': formattedDateTime,
|
||||||
|
'tanggal_diagnosa_raw': tanggalDiagnosa,
|
||||||
'id_penyakit': idPenyakit,
|
'id_penyakit': idPenyakit,
|
||||||
'id_hama': idHama,
|
'id_hama': idHama,
|
||||||
|
'timestamp': rawDateTime, // menyimpan waktu untuk sorting
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tambahkan gejala jika belum ada
|
// Tambahkan gejala jika belum ada
|
||||||
if (item['gejala_nama'] != null) {
|
if (item['gejala_nama'] != null) {
|
||||||
final gejalaNama = item['gejala_nama'];
|
final gejalaNama = item['gejala_nama'];
|
||||||
if (!groupedData[diagnosisKey]!['gejala'].contains(gejalaNama)) {
|
if (!groupedData[compositeKey]!['gejala'].contains(gejalaNama)) {
|
||||||
groupedData[diagnosisKey]!['gejala'].add(gejalaNama);
|
groupedData[compositeKey]!['gejala'].add(gejalaNama);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Konversi ke list dan urutkan berdasarkan timestamp terbaru
|
||||||
final result = groupedData.values.toList();
|
final result = groupedData.values.toList();
|
||||||
print("Hasil pengelompokan: $result");
|
result.sort((a, b) {
|
||||||
|
final String timestampA = a['timestamp'] ?? '';
|
||||||
|
final String timestampB = b['timestamp'] ?? '';
|
||||||
|
return timestampB.compareTo(timestampA); // descending (terbaru dulu)
|
||||||
|
});
|
||||||
|
|
||||||
|
print(
|
||||||
|
"Hasil pengelompokan berdasarkan diagnosa dan waktu: ${result.length} entries",
|
||||||
|
);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Future<void> _fetchHistoriData() async {
|
Future<void> _fetchHistoriData() async {
|
||||||
try {
|
try {
|
||||||
print("Fetching histori dengan userId: $_userId");
|
print("Fetching histori dengan userId: $_userId");
|
||||||
|
@ -333,13 +382,95 @@ class _RiwayatDiagnosaPageState extends State<RiwayatDiagnosaPage> {
|
||||||
? "Tidak ada gejala tercatat"
|
? "Tidak ada gejala tercatat"
|
||||||
: gejalaList.join(', ');
|
: gejalaList.join(', ');
|
||||||
|
|
||||||
|
// Mendapatkan jenis diagnosis (penyakit/hama/keduanya)
|
||||||
|
final String diagnosisType =
|
||||||
|
riwayat['diagnosis_type'] ?? 'Tidak diketahui';
|
||||||
|
|
||||||
|
// Mendapatkan badge warna berdasarkan jenis diagnosis
|
||||||
|
Color badgeColor;
|
||||||
|
switch (diagnosisType) {
|
||||||
|
case 'penyakit':
|
||||||
|
badgeColor = Color(0xFF9DC08D); // Warna untuk penyakit
|
||||||
|
break;
|
||||||
|
case 'hama':
|
||||||
|
badgeColor = Color(
|
||||||
|
0xFF7A9A6D,
|
||||||
|
); // Warna lebih gelap untuk hama
|
||||||
|
break;
|
||||||
|
case 'penyakit & hama':
|
||||||
|
badgeColor = Color(
|
||||||
|
0xFF5C7452,
|
||||||
|
); // Warna paling gelap untuk kombinasi
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
badgeColor = Colors.grey[300]!;
|
||||||
|
}
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
margin: EdgeInsets.only(bottom: 12.0),
|
margin: EdgeInsets.only(bottom: 12.0),
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
elevation: 3,
|
elevation: 3,
|
||||||
child: Padding(
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// Header dengan waktu diagnosa
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Color(0xFFE1EDD5),
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(12),
|
||||||
|
topRight: Radius.circular(12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.access_time,
|
||||||
|
size: 18,
|
||||||
|
color: Colors.grey[700],
|
||||||
|
),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'${riwayat['tanggal_diagnosa'] ?? "Tanggal tidak tersedia"}',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Colors.grey[700],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Badge jenis diagnosis
|
||||||
|
Container(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: badgeColor,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
diagnosisType,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Content
|
||||||
|
Padding(
|
||||||
padding: const EdgeInsets.all(12.0),
|
padding: const EdgeInsets.all(12.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -361,20 +492,14 @@ class _RiwayatDiagnosaPageState extends State<RiwayatDiagnosaPage> {
|
||||||
'Hasil: ${(riwayat['hasil'] as num?)?.toStringAsFixed(2) ?? "-"}',
|
'Hasil: ${(riwayat['hasil'] as num?)?.toStringAsFixed(2) ?? "-"}',
|
||||||
style: TextStyle(fontSize: 14),
|
style: TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
SizedBox(height: 8),
|
|
||||||
Text(
|
|
||||||
'Tanggal: ${riwayat['tanggal_diagnosa'] ?? "-"}',
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 12,
|
|
||||||
color: Colors.grey[600],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(height: 12),
|
SizedBox(height: 12),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
print("Navigating to DetailRiwayatPage with data: $riwayat");
|
print(
|
||||||
|
"Navigating to DetailRiwayatPage with data: $riwayat",
|
||||||
|
);
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
|
@ -396,6 +521,8 @@ class _RiwayatDiagnosaPageState extends State<RiwayatDiagnosaPage> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue