472 lines
18 KiB
Dart
472 lines
18 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:fluttertoast/fluttertoast.dart';
|
|
import 'package:get/get.dart';
|
|
import 'dart:async';
|
|
import 'dart:convert';
|
|
import 'package:http/http.dart' as http;
|
|
// import 'package:piring/dashboard/dashboard.dart';
|
|
// import 'package:piring/kalori/kalorirvisi.dart';
|
|
// import 'package:piring/model/user.dart';
|
|
import 'package:piring_baru/kalori/kalorirvisi.dart';
|
|
import 'package:piring_baru/model/user.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
|
|
class RevTambah extends StatefulWidget {
|
|
final String item;
|
|
const RevTambah({super.key, required this.item});
|
|
|
|
@override
|
|
State<RevTambah> createState() => _RevTambahState();
|
|
}
|
|
|
|
class _RevTambahState extends State<RevTambah> {
|
|
List<dynamic> data = [];
|
|
List<Map<String, dynamic>> selectedItems = [];
|
|
double totalEnergi = 0.0; // Tambahkan variabel total energi
|
|
List<String> makanan = []; // Array untuk nama makanan terpilih
|
|
List<int> jumlah = []; // Array untuk kuantitas makanan terpilih
|
|
String filterText = '';
|
|
String Id = '';
|
|
Map<String, List<Map<String, dynamic>>> groupedData = {};
|
|
|
|
// Fungsi untuk mendapatkan data dari API
|
|
Future<void> fetchData() async {
|
|
Uri url =
|
|
Uri.parse('https://isipiringku.esolusindo.com/api/Makanan/makanan');
|
|
final response = await http.get(url);
|
|
if (response.statusCode == 200) {
|
|
data = json.decode(response.body)['response'];
|
|
|
|
groupedData = groupData(data);
|
|
setState(() {
|
|
data = data;
|
|
});
|
|
} else {
|
|
throw Exception('Gagal memuat data');
|
|
}
|
|
}
|
|
|
|
void updateTotalEnergi() {
|
|
double newTotalEnergi = 0.0;
|
|
for (int i = 0; i < makanan.length; i++) {
|
|
int index = data.indexWhere((item) => item['id_makanan'] == makanan[i]);
|
|
if (index != -1) {
|
|
double energi = double.parse(data[index]['energi']);
|
|
newTotalEnergi += energi * jumlah[i];
|
|
}
|
|
}
|
|
setState(() {
|
|
totalEnergi = newTotalEnergi;
|
|
});
|
|
}
|
|
|
|
void addItem(Map<String, dynamic> item) {
|
|
String idMakanan = item['id_makanan'];
|
|
int index = makanan.indexOf(idMakanan);
|
|
if (index != -1) {
|
|
jumlah[index]++;
|
|
} else {
|
|
makanan.add(idMakanan);
|
|
jumlah.add(1);
|
|
}
|
|
updateTotalEnergi();
|
|
}
|
|
|
|
void removeItem(int index) {
|
|
makanan.removeAt(index);
|
|
jumlah.removeAt(index);
|
|
updateTotalEnergi();
|
|
}
|
|
|
|
void checkArrays() {
|
|
print('Array Makanan: $makanan');
|
|
print('Array Jumlah: $jumlah');
|
|
}
|
|
|
|
void showDetailDialog(Map<String, dynamic> item) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return AlertDialog(
|
|
title: Text(item['nama_makanan']),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text('Energi: ${item['energi']}'),
|
|
Text('Karbohidrat: ${item['karbohidrat']}'),
|
|
Text('Protein: ${item['protein']}'),
|
|
Text('Lemak: ${item['lemak']}'),
|
|
// Tambahkan detail lainnya sesuai kebutuhan
|
|
],
|
|
),
|
|
actions: <Widget>[
|
|
TextButton(
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
},
|
|
child: Text('Tutup'),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}
|
|
|
|
List filteredData() {
|
|
return data
|
|
.where((item) => item['nama_makanan']
|
|
.toLowerCase()
|
|
.contains(filterText.toLowerCase()))
|
|
.toList();
|
|
}
|
|
|
|
bool isAtLeastOneItemSelectedInEachCategory() {
|
|
Map<String, bool> categorySelectedStatus = {};
|
|
|
|
// Inisialisasi status seleksi kategori
|
|
for (String idMakanan in makanan) {
|
|
int index = data.indexWhere((item) => item['id_makanan'] == idMakanan);
|
|
if (index != -1) {
|
|
String kategori = data[index]['nama_kategori'];
|
|
categorySelectedStatus[kategori] = true;
|
|
}
|
|
}
|
|
|
|
// Periksa apakah setiap kategori memiliki setidaknya satu item yang dipilih
|
|
for (String kategori in groupedData.keys) {
|
|
if (categorySelectedStatus[kategori] != true) {
|
|
return false; // Ada kategori yang tidak memiliki item yang dipilih
|
|
}
|
|
}
|
|
|
|
return true; // Setiap kategori memiliki setidaknya satu item yang dipilih
|
|
}
|
|
|
|
Future<void> cekkirim() async {
|
|
if (!isAtLeastOneItemSelectedInEachCategory()) {
|
|
// Ada item yang tidak memiliki kategori
|
|
showDialog(
|
|
context: context,
|
|
builder: (BuildContext context) {
|
|
return AlertDialog(
|
|
title: Text('Peringatan'),
|
|
content:
|
|
Text('Ada Kategori makanan yang belum anda pilih. Lanjutkan?'),
|
|
actions: <Widget>[
|
|
TextButton(
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
},
|
|
child: Text('Batal'),
|
|
),
|
|
TextButton(
|
|
onPressed: () {
|
|
// Lanjutkan dengan mengirim data ke API
|
|
postDataToAPI();
|
|
Navigator.of(context).pop();
|
|
},
|
|
child: Text('Ya'),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
} else {
|
|
// Semua item memiliki kategori, lanjutkan dengan mengirim data ke API
|
|
postDataToAPI();
|
|
}
|
|
}
|
|
|
|
Future<void> postDataToAPI() async {
|
|
final String apiUrl =
|
|
"https://isipiringku.esolusindo.com/api/Konsumsi/Konsumsi";
|
|
|
|
// Membuat objek body yang berisi parameter yang akan dikirimkan ke API
|
|
final Map<String, dynamic> data = {
|
|
"id_user": Id,
|
|
"total_kalori": totalEnergi,
|
|
"keterangan": widget.item,
|
|
"bahan_makanan_nama_makanan": makanan,
|
|
"kuantitas": jumlah,
|
|
};
|
|
|
|
// Mengirim permintaan POST ke API
|
|
final response = await http.post(
|
|
Uri.parse(apiUrl),
|
|
body: jsonEncode(data),
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
);
|
|
|
|
if (response.statusCode == 200) {
|
|
print("Data berhasil dikirim ke API");
|
|
print("Respon API: ${response.body}");
|
|
Navigator.pushReplacement(
|
|
context,
|
|
MaterialPageRoute(
|
|
builder: (context) => RevKalori(),
|
|
));
|
|
Fluttertoast.showToast(
|
|
msg: "Berhasil Tambahkan Data",
|
|
backgroundColor: Colors.green,
|
|
toastLength: Toast.LENGTH_SHORT);
|
|
} else {
|
|
throw Exception("Gagal mengirim data ke API");
|
|
}
|
|
}
|
|
|
|
Future<void> loadUserData() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final userDataString = prefs.getString('user_data');
|
|
|
|
if (userDataString != null) {
|
|
final userData = UserData.fromJson(json.decode(userDataString));
|
|
print(userData.nama);
|
|
|
|
setState(() {
|
|
Id = userData.idUser.toString();
|
|
});
|
|
}
|
|
}
|
|
|
|
Map<String, List<Map<String, dynamic>>> groupData(List<dynamic> data) {
|
|
// Membuat map untuk mengelompokkan makanan berdasarkan kategori
|
|
Map<String, List<Map<String, dynamic>>> groupedData = {};
|
|
|
|
for (Map<String, dynamic> item in data) {
|
|
String kategori = item['nama_kategori'];
|
|
|
|
if (groupedData.containsKey(kategori)) {
|
|
groupedData[kategori]!.add(item);
|
|
} else {
|
|
groupedData[kategori] = [item];
|
|
}
|
|
}
|
|
|
|
return groupedData;
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
fetchData();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
body: SingleChildScrollView(
|
|
child: Stack(children: [
|
|
Container(
|
|
height: 130,
|
|
width: double.infinity,
|
|
decoration: BoxDecoration(
|
|
image: DecorationImage(
|
|
image: AssetImage('assets/images/head2.jpg'),
|
|
fit: BoxFit.cover)),
|
|
),
|
|
SafeArea(
|
|
child: Padding(
|
|
padding: EdgeInsets.symmetric(horizontal: 15.0),
|
|
child: Container(
|
|
width: MediaQuery.of(context).size.width,
|
|
child: Stack(
|
|
children: [
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(padding: EdgeInsets.only(top: 64)),
|
|
SizedBox(height: 20),
|
|
Center(
|
|
child: Container(
|
|
width: MediaQuery.of(context).size.height * 0.4,
|
|
height: 30,
|
|
decoration: BoxDecoration(
|
|
gradient: LinearGradient(
|
|
colors: [
|
|
Color.fromARGB(255, 250, 154, 0),
|
|
Color.fromARGB(255, 246, 80, 20),
|
|
Color.fromARGB(255, 235, 38, 16),
|
|
],
|
|
),
|
|
borderRadius: BorderRadius.circular(30),
|
|
boxShadow: kElevationToShadow[1],
|
|
),
|
|
padding: const EdgeInsets.symmetric(
|
|
horizontal: 5,
|
|
vertical: 0,
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
'Kalori Harian',
|
|
style: TextStyle(
|
|
color: Colors.white,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
Column(
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.all(10.0),
|
|
child: TextFormField(
|
|
decoration: InputDecoration(
|
|
labelText: 'Filter Nama Makanan',
|
|
),
|
|
onChanged: (value) {
|
|
setState(() {
|
|
filterText = value;
|
|
});
|
|
},
|
|
),
|
|
),
|
|
Container(
|
|
height: 200,
|
|
child: Expanded(
|
|
child: ListView.builder(
|
|
itemCount: groupedData.length,
|
|
itemBuilder: (context, index) {
|
|
String kategori =
|
|
groupedData.keys.elementAt(index);
|
|
List<Map<String, dynamic>>?
|
|
makananKategori =
|
|
groupedData[kategori];
|
|
|
|
return Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment.start,
|
|
children: [
|
|
Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Text(
|
|
kategori, // Menampilkan judul kategori
|
|
style: TextStyle(
|
|
fontSize: 18,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
),
|
|
ListView.builder(
|
|
shrinkWrap: true,
|
|
physics:
|
|
NeverScrollableScrollPhysics(),
|
|
itemCount: makananKategori?.length,
|
|
itemBuilder: (context, subIndex) {
|
|
Map<String, dynamic> item =
|
|
makananKategori![subIndex];
|
|
return Card(
|
|
child: ExpansionTile(
|
|
title: Text(
|
|
item['nama_makanan']),
|
|
children: [
|
|
ListTile(
|
|
title: Text(
|
|
'Energi: ${item['energi']}'),
|
|
subtitle: Column(
|
|
crossAxisAlignment:
|
|
CrossAxisAlignment
|
|
.start,
|
|
children: [
|
|
Text(
|
|
'Karbohidrat: ${item['karbohidrat']}'),
|
|
Text(
|
|
'Protein: ${item['protein']}'),
|
|
Text(
|
|
'Lemak: ${item['lemak']}'),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
trailing: Row(
|
|
mainAxisSize:
|
|
MainAxisSize.min,
|
|
children: [
|
|
IconButton(
|
|
icon: Icon(Icons.add),
|
|
onPressed: () {
|
|
addItem(item);
|
|
},
|
|
),
|
|
IconButton(
|
|
icon:
|
|
Icon(Icons.remove),
|
|
onPressed: () {
|
|
if (makanan
|
|
.isNotEmpty) {
|
|
removeItem(
|
|
makanan.length -
|
|
1);
|
|
}
|
|
},
|
|
),
|
|
IconButton(
|
|
icon: Icon(Icons
|
|
.remove_red_eye),
|
|
onPressed: () {
|
|
showDetailDialog(
|
|
item);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
);
|
|
},
|
|
),
|
|
),
|
|
),
|
|
SizedBox(
|
|
height: 16.0,
|
|
),
|
|
Text('Item yang Dipilih:'),
|
|
Column(
|
|
children: makanan.asMap().entries.map((entry) {
|
|
int index = entry.key;
|
|
String idMakanan = entry.value;
|
|
int qty = jumlah[index];
|
|
int dataIdx = data.indexWhere((item) =>
|
|
item['id_makanan'] == idMakanan);
|
|
if (dataIdx != -1) {
|
|
Map<String, dynamic> item = data[dataIdx];
|
|
return ListTile(
|
|
title: Text(
|
|
'${item['nama_makanan']} (${qty}x)'),
|
|
subtitle: Text(
|
|
'Energi: ${double.parse(item['energi']) * qty}'),
|
|
);
|
|
} else {
|
|
return SizedBox
|
|
.shrink(); // Item tidak ditemukan dalam data
|
|
}
|
|
}).toList(),
|
|
),
|
|
Text('Total Energi: $totalEnergi'),
|
|
SizedBox(
|
|
height: 16.0,
|
|
),
|
|
ElevatedButton(
|
|
onPressed: cekkirim,
|
|
child: Text('Simpan'),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
)),
|
|
),
|
|
]),
|
|
),
|
|
);
|
|
}
|
|
}
|