added cetak laporan
This commit is contained in:
@ -53,7 +53,7 @@ class AddSiswaDialogView extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Tambah Siswa',
|
||||
'Tambah Anak Panti',
|
||||
style: boldTextStyle.copyWith(
|
||||
fontSize: 16,
|
||||
),
|
||||
|
||||
@ -67,12 +67,13 @@ class AdminIndexTrackingView extends StatelessWidget {
|
||||
? sixthGrey
|
||||
: backgroundColor),
|
||||
title: Text(
|
||||
item['name'],
|
||||
model.otherFunction.capitalizeEachWord(item['name']),
|
||||
style: regularTextStyle.copyWith(
|
||||
color: model.currentIndex ==
|
||||
model.bottomNavBarList.indexOf(item)
|
||||
? sixthGrey
|
||||
: Colors.grey,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
backgroundColor: model.currentIndex ==
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:panti_asuhan/services/other_function.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:stacked/stacked.dart';
|
||||
import 'package:stacked_services/stacked_services.dart';
|
||||
@ -12,14 +13,16 @@ class AdminIndexTrackingViewModel extends IndexTrackingViewModel {
|
||||
final _navigationService = locator<NavigationService>();
|
||||
final _dialogService = locator<DialogService>();
|
||||
final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
|
||||
final otherFunction = locator<OtherFunction>();
|
||||
|
||||
final _bottomNavBarList = [
|
||||
{
|
||||
'name': 'Siswa',
|
||||
'name': 'List',
|
||||
'icon': Icons.people_alt_outlined,
|
||||
'header': 'List Siswa'
|
||||
'header': 'List Anak Panti'
|
||||
},
|
||||
{'name': 'Dana', 'icon': Icons.money, 'header': 'Dana Sosial'},
|
||||
// {'name': 'Dana', 'icon': Icons.money, 'header': 'Dana Sosial Khusus'},
|
||||
{
|
||||
'name': 'Profil',
|
||||
'icon': Icons.person_4_outlined,
|
||||
@ -39,6 +42,7 @@ class AdminIndexTrackingViewModel extends IndexTrackingViewModel {
|
||||
final List<String> _views = [
|
||||
AdminIndexTrackingViewRoutes.dataSiswaView,
|
||||
AdminIndexTrackingViewRoutes.danaSosialAdminView,
|
||||
// AdminIndexTrackingViewRoutes.danaSosialKhususView,
|
||||
AdminIndexTrackingViewRoutes.profilView,
|
||||
AdminIndexTrackingViewRoutes.visiMisiView,
|
||||
AdminIndexTrackingViewRoutes.sejarahView,
|
||||
|
||||
@ -22,86 +22,18 @@ class DanaSosialAdminView extends StatelessWidget {
|
||||
Widget? child,
|
||||
) {
|
||||
return Scaffold(
|
||||
body: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 15, vertical: 10),
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: mainColor,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: mainGrey.withOpacity(0.5),
|
||||
spreadRadius: 5,
|
||||
blurRadius: 7,
|
||||
offset: const Offset(
|
||||
0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Dana Sosial Bulan Ini',
|
||||
style: boldTextStyle.copyWith(
|
||||
color: Colors.white,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Total Dana Sosial',
|
||||
style: regularTextStyle.copyWith(
|
||||
color: Colors.white,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'Rp. ${OtherFunction().commaFormat(model.jumlahDonasi)}',
|
||||
style: regularTextStyle.copyWith(
|
||||
color: Colors.white,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: const BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: mainColor,
|
||||
),
|
||||
child: IconButton(
|
||||
icon: const Icon(
|
||||
Icons.filter_list,
|
||||
color: Colors.white,
|
||||
),
|
||||
onPressed: () {
|
||||
model.filterDialog(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Expanded(
|
||||
child: Container(
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
"Laporan Harian",
|
||||
style:
|
||||
boldTextStyle.copyWith(fontSize: 15, color: Colors.black),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
height: MediaQuery.of(context).size.height * 0.45,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
@ -124,25 +56,384 @@ class DanaSosialAdminView extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
)
|
||||
: const TheData(),
|
||||
: const TheDataNewly(),
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Text(
|
||||
"Laporan Bulanan",
|
||||
style:
|
||||
boldTextStyle.copyWith(fontSize: 15, color: Colors.black),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(15),
|
||||
width: double.infinity,
|
||||
height: MediaQuery.of(context).size.height * 0.25,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: mainGrey.withOpacity(0.5),
|
||||
spreadRadius: 5,
|
||||
blurRadius: 7,
|
||||
offset:
|
||||
const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
child: model.monthIncomeOutcome.isEmpty
|
||||
? const Center(
|
||||
child: Text(
|
||||
'Tidak ada data',
|
||||
))
|
||||
: const HasilIncomeOutcome(),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Text(
|
||||
"Laporan Tahunan",
|
||||
style:
|
||||
boldTextStyle.copyWith(fontSize: 15, color: Colors.black),
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(15),
|
||||
width: double.infinity,
|
||||
height: MediaQuery.of(context).size.height * 0.25,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: mainGrey.withOpacity(0.5),
|
||||
spreadRadius: 5,
|
||||
blurRadius: 7,
|
||||
offset:
|
||||
const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
child: model.yearIncomeOutcome.isNotEmpty
|
||||
? const TahunanWidget()
|
||||
: const Center(
|
||||
child: Text(
|
||||
'Tidak ada data',
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: mainGrey.withOpacity(0.5),
|
||||
spreadRadius: 5,
|
||||
blurRadius: 7,
|
||||
offset:
|
||||
const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Total Pemasukan :',
|
||||
),
|
||||
const Expanded(child: SizedBox()),
|
||||
Text(
|
||||
'Rp. ${OtherFunction().commaFormat(model.totalIncome)}',
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Total Pengeluaran :',
|
||||
),
|
||||
const Expanded(child: SizedBox()),
|
||||
Text(
|
||||
'Rp. ${OtherFunction().commaFormat(model.totalOutcome)}',
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: model.role == 'admin'
|
||||
? FloatingActionButton(
|
||||
floatingActionButton: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
if (model.role == 'admin')
|
||||
FloatingActionButton(
|
||||
mini: true,
|
||||
heroTag: 'btn11',
|
||||
onPressed: () {
|
||||
model.goToTambahDanaSosial();
|
||||
},
|
||||
child: const Icon(Icons.add),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
FloatingActionButton(
|
||||
mini: true,
|
||||
heroTag: 'btn22',
|
||||
onPressed: () {
|
||||
model.filterDialog(context);
|
||||
},
|
||||
child: const Icon(Icons.filter_list),
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.miniEndTop,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TahunanWidget extends ViewModelWidget<DanaSosialAdminViewModel> {
|
||||
const TahunanWidget({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, DanaSosialAdminViewModel viewModel) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (int i = 0; i < viewModel.yearIncomeOutcome.length; i++)
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"Tahun ${viewModel.yearIncomeOutcome[i]['tahun']}",
|
||||
style: boldTextStyle.copyWith(
|
||||
decoration: TextDecoration.underline,
|
||||
fontSize: 17,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
if (viewModel.role == 'admin' ||
|
||||
viewModel.role == 'pimpinan')
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
color: mainColor,
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () async {
|
||||
// sini untuk laporan bulanan
|
||||
await viewModel.goToLaporanTahunan(
|
||||
viewModel.yearIncomeOutcome[i]['tahun']);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.list_alt_outlined,
|
||||
color: Colors.white,
|
||||
size: 15,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Table(
|
||||
border: TableBorder.all(
|
||||
color: Colors.grey,
|
||||
),
|
||||
children: [
|
||||
const TableRow(children: [
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Pemasukan',
|
||||
style: boldTextStyle,
|
||||
))),
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Pengeluaran',
|
||||
style: boldTextStyle,
|
||||
)))
|
||||
]),
|
||||
TableRow(children: [
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Rp. ${OtherFunction().commaFormat(viewModel.yearIncomeOutcome[i]['pemasukan'])}',
|
||||
style: italicTextStyle,
|
||||
))),
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Rp. ${OtherFunction().commaFormat(viewModel.yearIncomeOutcome[i]['pengeluaran'])}',
|
||||
style: italicTextStyle,
|
||||
)))
|
||||
]),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
const Divider(
|
||||
color: Colors.grey,
|
||||
thickness: 1,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HasilIncomeOutcome extends ViewModelWidget<DanaSosialAdminViewModel> {
|
||||
const HasilIncomeOutcome({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, DanaSosialAdminViewModel viewModel) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (int i = 0; i < viewModel.monthIncomeOutcome.length; i++)
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
viewModel.otherFunction.changeMonthYear(
|
||||
viewModel.monthIncomeOutcome[i]['month']),
|
||||
style: boldTextStyle.copyWith(
|
||||
decoration: TextDecoration.underline,
|
||||
fontSize: 17,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
if (viewModel.role == 'admin' ||
|
||||
viewModel.role == 'pimpinan')
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
width: 30,
|
||||
height: 30,
|
||||
decoration: BoxDecoration(
|
||||
color: mainColor,
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () async {
|
||||
// sini untuk laporan bulanan
|
||||
await viewModel.goToLaporanBulanan(
|
||||
viewModel.monthIncomeOutcome[i]['month']);
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.list_alt_outlined,
|
||||
color: Colors.white,
|
||||
size: 15,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Table(
|
||||
border: TableBorder.all(
|
||||
color: Colors.grey,
|
||||
),
|
||||
children: [
|
||||
const TableRow(children: [
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Pemasukan',
|
||||
style: boldTextStyle,
|
||||
))),
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Pengeluaran',
|
||||
style: boldTextStyle,
|
||||
)))
|
||||
]),
|
||||
TableRow(children: [
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Rp. ${OtherFunction().commaFormat(viewModel.monthIncomeOutcome[i]['income'])}',
|
||||
style: italicTextStyle,
|
||||
))),
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Rp. ${OtherFunction().commaFormat(viewModel.monthIncomeOutcome[i]['outcome'])}',
|
||||
style: italicTextStyle,
|
||||
)))
|
||||
]),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
const Divider(
|
||||
color: Colors.grey,
|
||||
thickness: 1,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TheData extends ViewModelWidget<DanaSosialAdminViewModel> {
|
||||
const TheData({
|
||||
super.key,
|
||||
@ -154,6 +445,8 @@ class TheData extends ViewModelWidget<DanaSosialAdminViewModel> {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||
itemCount: viewModel.danaSosialModelList.length,
|
||||
itemBuilder: (context, index) {
|
||||
// viewModel.log.i(viewModel.danaSosialModelList[index].tanggal);
|
||||
|
||||
String jumlahDonasi = viewModel
|
||||
.danaSosialModelList[index].jenisDonasi !=
|
||||
'Barang'
|
||||
@ -278,3 +571,329 @@ class TheData extends ViewModelWidget<DanaSosialAdminViewModel> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TheDataNewly extends ViewModelWidget<DanaSosialAdminViewModel> {
|
||||
const TheDataNewly({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, DanaSosialAdminViewModel viewModel) {
|
||||
return ListView.builder(
|
||||
itemCount: viewModel.filteredByDateData.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 30),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${viewModel.otherFunction.changeMonthYear(viewModel.filteredByDateData[index]['month'])} ',
|
||||
style: boldTextStyle.copyWith(
|
||||
decoration: TextDecoration.underline,
|
||||
fontSize: 17,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
for (int i = 0;
|
||||
i < viewModel.filteredByDateData[index]['data'].length;
|
||||
i++)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'${viewModel.filteredByDateData[index]['data'][i]['date']} : ${viewModel.otherFunction.getDayOfWeek(viewModel.filteredByDateData[index]['data'][i]['date'])}',
|
||||
style: italicTextStyle.copyWith(
|
||||
fontWeight: FontWeight.bold, fontSize: 15),
|
||||
),
|
||||
const SizedBox(
|
||||
width: 10,
|
||||
),
|
||||
if (viewModel.role == 'admin' ||
|
||||
viewModel.role == 'pimpinan')
|
||||
Container(
|
||||
alignment: Alignment.center,
|
||||
width: 35,
|
||||
height: 35,
|
||||
decoration: BoxDecoration(
|
||||
color: mainColor,
|
||||
borderRadius: BorderRadius.circular(35),
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
viewModel.getLaporanHarian(
|
||||
viewModel.filteredByDateData[index]
|
||||
['data'][i]['date'],
|
||||
viewModel.otherFunction.getDayOfWeek(
|
||||
viewModel.filteredByDateData[index]
|
||||
['data'][i]['date']));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.list_alt_outlined,
|
||||
color: Colors.white,
|
||||
size: 20,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Table(
|
||||
border: TableBorder.all(
|
||||
color: Colors.grey,
|
||||
),
|
||||
columnWidths: viewModel.role == 'admin'
|
||||
? const {
|
||||
0: FlexColumnWidth(
|
||||
1), // 1/3 of the available width
|
||||
1: FlexColumnWidth(
|
||||
1.5), // 2/3 of the available width
|
||||
2: FlexColumnWidth(
|
||||
2.5), // 2/3 of the available width
|
||||
3: FlexColumnWidth(
|
||||
3), // 2/3 of the available width
|
||||
4: FlexColumnWidth(
|
||||
2), // 2/3 of the available width
|
||||
}
|
||||
: const {
|
||||
0: FlexColumnWidth(
|
||||
1), // 1/3 of the available width
|
||||
1: FlexColumnWidth(
|
||||
2), // 2/3 of the available width
|
||||
2: FlexColumnWidth(
|
||||
2), // 2/3 of the available width
|
||||
3: FlexColumnWidth(
|
||||
3), // 2/3 of the available width
|
||||
},
|
||||
children: [
|
||||
TableRow(
|
||||
children: [
|
||||
const TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'No',
|
||||
style: boldTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
const TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Jenis',
|
||||
style: boldTextStyle,
|
||||
))),
|
||||
const TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Donatur',
|
||||
style: boldTextStyle,
|
||||
))),
|
||||
const TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Jumlah /\nKeterangan',
|
||||
style: boldTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (viewModel.role == 'admin')
|
||||
const TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Aksi',
|
||||
style: boldTextStyle,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
for (int j = 0;
|
||||
j <
|
||||
viewModel
|
||||
.filteredByDateData[index]['data'][i]
|
||||
['data_dana']
|
||||
.length;
|
||||
j++)
|
||||
TableRow(
|
||||
children: [
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${j + 1}',
|
||||
style: regularTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
child: Center(
|
||||
// circle icon
|
||||
child: viewModel
|
||||
.filteredByDateData[index]
|
||||
['data'][i]['data_dana']
|
||||
[j]
|
||||
.bentuk ==
|
||||
'Pemasukan'
|
||||
? const JenisIconContainer(
|
||||
color: Colors.green,
|
||||
icon: Icons.arrow_upward,
|
||||
)
|
||||
: const JenisIconContainer(
|
||||
color: Colors.red,
|
||||
icon: Icons.arrow_downward,
|
||||
)),
|
||||
),
|
||||
),
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${viewModel.filteredByDateData[index]['data'][i]['data_dana'][j].nama == '' ? '-' : viewModel.filteredByDateData[index]['data'][i]['data_dana'][j].nama}',
|
||||
style: regularTextStyle,
|
||||
)),
|
||||
)),
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
viewModel
|
||||
.filteredByDateData[index]
|
||||
['data'][i]['data_dana']
|
||||
[j]
|
||||
.jenisDonasi ==
|
||||
'Uang'
|
||||
? 'Rp. ${viewModel.otherFunction.commaFormat(int.parse(viewModel.filteredByDateData[index]['data'][i]['data_dana'][j].jumlah))}'
|
||||
: viewModel
|
||||
.filteredByDateData[index]
|
||||
['data'][i]['data_dana'][j]
|
||||
.keterangan,
|
||||
style: regularTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (viewModel.role == 'admin')
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
child: Wrap(
|
||||
spacing: 5,
|
||||
runSpacing: 10,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
viewModel.goToEditDanaSosial(
|
||||
int.parse(viewModel
|
||||
.filteredByDateData[
|
||||
index]['data'][i]
|
||||
['data_dana'][j]
|
||||
.idDanaSosial));
|
||||
},
|
||||
child: JenisIconContainer(
|
||||
color: Colors.blue[600]!,
|
||||
icon: Icons.edit,
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
viewModel.deleteData(
|
||||
int.parse(viewModel
|
||||
.filteredByDateData[index]
|
||||
['data'][i]
|
||||
['data_dana'][j]
|
||||
.idDanaSosial!),
|
||||
);
|
||||
},
|
||||
child: const JenisIconContainer(
|
||||
color: Colors.red,
|
||||
icon: Icons.delete,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
// create a horizontal line
|
||||
const Divider(
|
||||
color: Colors.grey,
|
||||
thickness: 1.0,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class JenisIconContainer extends StatelessWidget {
|
||||
const JenisIconContainer({
|
||||
super.key,
|
||||
required this.color,
|
||||
required this.icon,
|
||||
});
|
||||
|
||||
final Color color;
|
||||
final IconData icon;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 20,
|
||||
height: 20,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: color,
|
||||
shape: BoxShape.circle,
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
color: Colors.white,
|
||||
size: 15,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_dotenv/flutter_dotenv.dart';
|
||||
import 'package:flutter_file_downloader/flutter_file_downloader.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../../../app/app.dialogs.dart';
|
||||
@ -16,15 +18,23 @@ class DanaSosialAdminViewModel extends CustomBaseViewModel {
|
||||
final log = getLogger('DanaSosialAdminViewModel');
|
||||
final _httpService = locator<MyHttpServices>();
|
||||
final easyLoading = locator<MyEasyLoading>();
|
||||
// final otherF
|
||||
String url = dotenv.env['url']!;
|
||||
|
||||
int bulan = DateTime.now().month;
|
||||
|
||||
List<DanaSosialModel> danaSosialModelList = [];
|
||||
List<Map<String, dynamic>> filteredByDateData = []; // newly added
|
||||
List<Map<String, dynamic>> monthIncomeOutcome = []; // newly added
|
||||
List<Map<String, dynamic>> yearIncomeOutcome = []; // newly added
|
||||
int totalIncome = 0; // newly added
|
||||
int totalOutcome = 0; // newly added
|
||||
|
||||
String? role;
|
||||
bool? isLogin;
|
||||
|
||||
int jumlahDonasi = 0;
|
||||
int jumlahPengeluaran = 0;
|
||||
|
||||
Future<void> init() async {
|
||||
await getData();
|
||||
@ -41,15 +51,16 @@ class DanaSosialAdminViewModel extends CustomBaseViewModel {
|
||||
easyLoading.showLoading();
|
||||
// get the month
|
||||
var bulan = DateTime.now().month;
|
||||
log.i(bulan);
|
||||
// log.i(bulan);
|
||||
// change bulan to string and add 0 if it is less than 10
|
||||
String bulanString = bulan.toString().length == 1 ? '0$bulan' : '$bulan';
|
||||
log.i(bulanString);
|
||||
// log.i(bulanString);
|
||||
try {
|
||||
var response = await _httpService.get('pemasukan?bulan=$bulanString');
|
||||
log.i(response.data['jumlah']);
|
||||
// log.i(response.data['jumlah']);
|
||||
// var theJumlahDonasi = response.data['jumlah'];
|
||||
jumlahDonasi = response.data['jumlah'];
|
||||
jumlahPengeluaran = response.data['jumlah_pengeluaran'];
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
} finally {
|
||||
@ -74,17 +85,110 @@ class DanaSosialAdminViewModel extends CustomBaseViewModel {
|
||||
}
|
||||
}
|
||||
|
||||
setBusy(false);
|
||||
changeByDate(danaSosialModelList);
|
||||
getTahunan();
|
||||
notifyListeners();
|
||||
log.i(danaSosialModelList);
|
||||
// log.i(danaSosialModelList.length);
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
setBusy(false);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
easyLoading.dismissLoading();
|
||||
}
|
||||
}
|
||||
|
||||
getTahunan() async {
|
||||
try {
|
||||
var response = await _httpService.get('data_tahunan');
|
||||
|
||||
var datanya = response.data['data'];
|
||||
log.i(datanya.length);
|
||||
for (int i = 0; i < datanya.length; i++) {
|
||||
log.i(datanya[i]);
|
||||
yearIncomeOutcome.add(datanya[i]);
|
||||
}
|
||||
notifyListeners();
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
}
|
||||
}
|
||||
|
||||
//newly added
|
||||
changeByDate(List<DanaSosialModel> data) {
|
||||
filteredByDateData = [];
|
||||
|
||||
for (var item in data) {
|
||||
var monthKey =
|
||||
item.tanggal!.substring(0, 7); // Extracting the year and month
|
||||
var dateKey = item.tanggal; // The full date
|
||||
|
||||
var monthData = filteredByDateData.firstWhere(
|
||||
(element) => element['month'] == monthKey,
|
||||
orElse: () => {
|
||||
'month': monthKey,
|
||||
'data': [],
|
||||
});
|
||||
|
||||
var dateData =
|
||||
monthData['data'].firstWhere((element) => element['date'] == dateKey,
|
||||
orElse: () => {
|
||||
'date': dateKey,
|
||||
'data_dana': [],
|
||||
});
|
||||
|
||||
dateData['data_dana'].add(item);
|
||||
|
||||
if (!monthData['data'].contains(dateData)) {
|
||||
monthData['data'].add(dateData);
|
||||
}
|
||||
|
||||
if (!filteredByDateData.contains(monthData)) {
|
||||
filteredByDateData.add(monthData);
|
||||
}
|
||||
}
|
||||
filteredByDateData.sort((a, b) => a['month'].compareTo(b['month']));
|
||||
// log.i(filteredByDateData);
|
||||
|
||||
// group the data by month
|
||||
|
||||
monthIncomeOutcome = [];
|
||||
|
||||
for (var item in filteredByDateData) {
|
||||
var income = 0;
|
||||
var outcome = 0;
|
||||
|
||||
for (var dateData in item['data']) {
|
||||
for (var danaSosialModel in dateData['data_dana']) {
|
||||
if (danaSosialModel.bentuk == 'Pemasukan' &&
|
||||
danaSosialModel.jenisDonasi == 'Uang') {
|
||||
income += int.parse(danaSosialModel.jumlah ?? '0');
|
||||
} else if (danaSosialModel.bentuk == 'Pengeluaran' &&
|
||||
danaSosialModel.jenisDonasi == 'Uang') {
|
||||
outcome += int.parse(danaSosialModel.jumlah ?? '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
monthIncomeOutcome.add({
|
||||
'month': item['month'],
|
||||
'income': income,
|
||||
'outcome': outcome,
|
||||
});
|
||||
}
|
||||
|
||||
// log.i(monthIncomeOutcome);
|
||||
totalIncome = 0;
|
||||
totalOutcome = 0;
|
||||
|
||||
for (var item in monthIncomeOutcome) {
|
||||
totalIncome += int.parse(item['income'].toString());
|
||||
totalOutcome += int.parse(item['outcome'].toString());
|
||||
}
|
||||
|
||||
log.i(totalIncome);
|
||||
log.i(totalOutcome);
|
||||
}
|
||||
|
||||
goToTambahDanaSosial() {
|
||||
navigationService.navigateTo(Routes.tambahDanaSosialView);
|
||||
}
|
||||
@ -104,6 +208,8 @@ class DanaSosialAdminViewModel extends CustomBaseViewModel {
|
||||
danaSosialModelList = [];
|
||||
|
||||
var datanya = response.data['data'];
|
||||
jumlahDonasi = response.data['jumlah_donasi'];
|
||||
jumlahPengeluaran = response.data['jumlah_pengeluaran'];
|
||||
// log.i(datanya.length);
|
||||
if (datanya.length > 0) {
|
||||
for (var item in datanya) {
|
||||
@ -112,8 +218,9 @@ class DanaSosialAdminViewModel extends CustomBaseViewModel {
|
||||
}
|
||||
|
||||
setBusy(false);
|
||||
changeByDate(danaSosialModelList);
|
||||
notifyListeners();
|
||||
log.i(danaSosialModelList);
|
||||
// log.i(danaSosialModelList);
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
setBusy(false);
|
||||
@ -163,7 +270,7 @@ class DanaSosialAdminViewModel extends CustomBaseViewModel {
|
||||
sql = sql.substring(0, sql.length - 4);
|
||||
}
|
||||
|
||||
log.i(sql);
|
||||
// log.i(sql);
|
||||
|
||||
getFilter(sql);
|
||||
}
|
||||
@ -194,12 +301,12 @@ class DanaSosialAdminViewModel extends CustomBaseViewModel {
|
||||
easyLoading.showLoading();
|
||||
setBusy(true);
|
||||
try {
|
||||
var response = await _httpService.postWithFormData(
|
||||
await _httpService.postWithFormData(
|
||||
'hapus_dana_sosial',
|
||||
FormData.fromMap({
|
||||
'id_dana_sosial': parse,
|
||||
}));
|
||||
log.i(response.data);
|
||||
// log.i(response.data);
|
||||
easyLoading.dismissLoading();
|
||||
easyLoading.showSuccess('Data berhasil dihapus');
|
||||
getData();
|
||||
@ -213,10 +320,152 @@ class DanaSosialAdminViewModel extends CustomBaseViewModel {
|
||||
easyLoading.dismissLoading();
|
||||
}
|
||||
} else {
|
||||
log.i('cancel');
|
||||
// log.i('cancel');
|
||||
return;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
goToLaporanBulanan(data) async {
|
||||
// seeperate by "-", the first index is year, the second index is month
|
||||
String year = data.substring(0, data.indexOf('-'));
|
||||
String month = data.substring(data.indexOf('-') + 1);
|
||||
|
||||
try {
|
||||
setBusy(true);
|
||||
easyLoading.customLoading("Mengunduh Laporan Bulanan...");
|
||||
await _httpService.get('laporan_bulanan?tahun=$year&bulan=$month');
|
||||
|
||||
// if (response.data) {
|
||||
|
||||
String urlPdf = '${url}assets/pdf/laporan_bulanan_$month,$year.pdf';
|
||||
log.i(urlPdf);
|
||||
FileDownloader.downloadFile(
|
||||
url: urlPdf,
|
||||
// name: "THE FILE NAME AFTER DOWNLOADING", //(optional)
|
||||
onProgress: (fileName, progress) {
|
||||
// change progress to 0-1
|
||||
double progressPercent = progress / 100;
|
||||
|
||||
easyLoading.showProgress(
|
||||
progressPercent,
|
||||
"Downloading: $progress%",
|
||||
);
|
||||
},
|
||||
onDownloadCompleted: (String path) {
|
||||
easyLoading.dismissLoading();
|
||||
snackbarService.showSnackbar(
|
||||
message: "Laporan Bulanan Berhasil Tersimpan di $path",
|
||||
duration: const Duration(seconds: 3),
|
||||
);
|
||||
},
|
||||
onDownloadError: (String error) {
|
||||
// log.i('DOWNLOAD ERROR: $error');
|
||||
snackbarService.showSnackbar(
|
||||
message: "Laporan Bulanan Gagal Tersimpan: $error",
|
||||
duration: const Duration(seconds: 3),
|
||||
);
|
||||
});
|
||||
// }
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
easyLoading.dismissLoading();
|
||||
}
|
||||
}
|
||||
|
||||
getLaporanHarian(String filteredByDateData, String dayOfWeek) async {
|
||||
String date = filteredByDateData;
|
||||
String day = dayOfWeek;
|
||||
|
||||
try {
|
||||
setBusy(true);
|
||||
easyLoading.customLoading("Mengunduh Laporan Harian...");
|
||||
await _httpService.get('laporan_harian?tanggal=$date&hari=$day');
|
||||
|
||||
String urlPdf = '${url}assets/pdf/laporan_harian_$day,$date.pdf';
|
||||
log.i(urlPdf);
|
||||
|
||||
FileDownloader.downloadFile(
|
||||
url: urlPdf,
|
||||
// name: "THE FILE NAME AFTER DOWNLOADING", //(optional)
|
||||
onProgress: (fileName, progress) {
|
||||
// change progress to 0-1
|
||||
double progressPercent = progress / 100;
|
||||
|
||||
easyLoading.showProgress(
|
||||
progressPercent,
|
||||
"Downloading: $progress%",
|
||||
);
|
||||
},
|
||||
onDownloadCompleted: (String path) {
|
||||
easyLoading.dismissLoading();
|
||||
snackbarService.showSnackbar(
|
||||
message: "Laporan Harian Berhasil Tersimpan di $path",
|
||||
duration: const Duration(seconds: 3),
|
||||
);
|
||||
},
|
||||
onDownloadError: (String error) {
|
||||
// log.i('DOWNLOAD ERROR: $error');
|
||||
snackbarService.showSnackbar(
|
||||
message: "Laporan Harian Gagal Tersimpan: $error",
|
||||
duration: const Duration(seconds: 3),
|
||||
);
|
||||
});
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
easyLoading.dismissLoading();
|
||||
}
|
||||
}
|
||||
|
||||
goToLaporanTahunan(String yearIncomeOutcome) async {
|
||||
// log.i(yearIncomeOutcome);
|
||||
|
||||
try {
|
||||
setBusy(true);
|
||||
easyLoading.customLoading("Mengunduh Laporan Tahun...");
|
||||
await _httpService.get('laporan_tahunan?tahun=$yearIncomeOutcome');
|
||||
|
||||
// if (response.data) {
|
||||
|
||||
String urlPdf = '${url}assets/pdf/laporan_tahunan_$yearIncomeOutcome.pdf';
|
||||
log.i(urlPdf);
|
||||
FileDownloader.downloadFile(
|
||||
url: urlPdf,
|
||||
// name: "THE FILE NAME AFTER DOWNLOADING", //(optional)
|
||||
onProgress: (fileName, progress) {
|
||||
// change progress to 0-1
|
||||
double progressPercent = progress / 100;
|
||||
|
||||
easyLoading.showProgress(
|
||||
progressPercent,
|
||||
"Downloading: $progress%",
|
||||
);
|
||||
},
|
||||
onDownloadCompleted: (String path) {
|
||||
easyLoading.dismissLoading();
|
||||
snackbarService.showSnackbar(
|
||||
message: "Laporan Tahunan Berhasil Tersimpan di $path",
|
||||
duration: const Duration(seconds: 3),
|
||||
);
|
||||
},
|
||||
onDownloadError: (String error) {
|
||||
// log.i('DOWNLOAD ERROR: $error');
|
||||
snackbarService.showSnackbar(
|
||||
message: "Laporan Tahunan Gagal Tersimpan: $error",
|
||||
duration: const Duration(seconds: 3),
|
||||
);
|
||||
});
|
||||
// }
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
easyLoading.dismissLoading();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stacked/stacked.dart';
|
||||
import 'package:stacked_services/stacked_services.dart';
|
||||
import 'package:validatorless/validatorless.dart';
|
||||
|
||||
import '../../../../widgets/my_button.dart';
|
||||
import '../../../../widgets/my_textformfield.dart';
|
||||
import './add_donatur_dialog_view_model.dart';
|
||||
|
||||
class AddDonaturDialogView extends StatelessWidget {
|
||||
final DialogRequest? request;
|
||||
final Function(DialogResponse)? completer;
|
||||
|
||||
const AddDonaturDialogView({
|
||||
Key? key,
|
||||
this.request,
|
||||
this.completer,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ViewModelBuilder<AddDonaturDialogViewModel>.reactive(
|
||||
viewModelBuilder: () => AddDonaturDialogViewModel(),
|
||||
onViewModelReady: (AddDonaturDialogViewModel model) async {
|
||||
await model.init();
|
||||
},
|
||||
builder: (
|
||||
BuildContext context,
|
||||
AddDonaturDialogViewModel model,
|
||||
Widget? child,
|
||||
) {
|
||||
return Dialog(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Form(
|
||||
key: model.formKey,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
'Tambah Donatur',
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
MyTextFormField(
|
||||
controller: model.namaController,
|
||||
hintText: 'Masukkan Nama Donatur',
|
||||
labelText: 'Nama Donatur',
|
||||
validator: Validatorless.required(
|
||||
'Nama Donatur tidak boleh kosong'),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(
|
||||
width: 200,
|
||||
child: MyButton(
|
||||
text: 'Tambah',
|
||||
onPressed: () async {
|
||||
if (model.formKey.currentState!.validate()) {
|
||||
// hide keyboard
|
||||
FocusScope.of(context).unfocus();
|
||||
bool res = await model.addDonatur();
|
||||
if (res) {
|
||||
completer!(DialogResponse(confirmed: true));
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../../../app/app.locator.dart';
|
||||
import '../../../../../app/app.logger.dart';
|
||||
import '../../../../../app/core/custom_base_view_model.dart';
|
||||
import '../../../../../services/http_services.dart';
|
||||
import '../../../../../services/my_easyloading.dart';
|
||||
|
||||
class AddDonaturDialogViewModel extends CustomBaseViewModel {
|
||||
final log = getLogger('AddDonaturDialogViewModel');
|
||||
final _httpService = locator<MyHttpServices>();
|
||||
final easyLoading = locator<MyEasyLoading>();
|
||||
|
||||
final formKey = GlobalKey<FormState>();
|
||||
TextEditingController namaController = TextEditingController();
|
||||
|
||||
Future<void> init() async {}
|
||||
|
||||
Future<bool> addDonatur() async {
|
||||
setBusy(true);
|
||||
easyLoading.showLoading();
|
||||
try {
|
||||
await _httpService.postWithFormData(
|
||||
'donatur',
|
||||
FormData.fromMap({
|
||||
'nama_donatur': namaController.text,
|
||||
}));
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
return false;
|
||||
} finally {
|
||||
setBusy(false);
|
||||
easyLoading.dismissLoading();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,737 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:stacked/stacked.dart';
|
||||
|
||||
import '../../../../app/themes/app_colors.dart';
|
||||
import '../../../../app/themes/app_text.dart';
|
||||
import '../../../../services/other_function.dart';
|
||||
import '../dana_sosial_admin/dana_sosial_admin_view.dart';
|
||||
import './dana_sosial_khusus_view_model.dart';
|
||||
|
||||
class DanaSosialKhususView extends StatelessWidget {
|
||||
const DanaSosialKhususView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ViewModelBuilder<DanaSosialKhususViewModel>.reactive(
|
||||
viewModelBuilder: () => DanaSosialKhususViewModel(),
|
||||
onViewModelReady: (DanaSosialKhususViewModel model) async {
|
||||
await model.init();
|
||||
},
|
||||
builder: (
|
||||
BuildContext context,
|
||||
DanaSosialKhususViewModel model,
|
||||
Widget? child,
|
||||
) {
|
||||
return Scaffold(
|
||||
body: Column(
|
||||
children: [
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: Container(
|
||||
// padding: const EdgeInsets.symmetric(
|
||||
// horizontal: 15, vertical: 10),
|
||||
// width: double.infinity,
|
||||
// decoration: BoxDecoration(
|
||||
// color: mainColor,
|
||||
// borderRadius: BorderRadius.circular(10),
|
||||
// boxShadow: [
|
||||
// BoxShadow(
|
||||
// color: mainGrey.withOpacity(0.5),
|
||||
// spreadRadius: 5,
|
||||
// blurRadius: 7,
|
||||
// offset: const Offset(
|
||||
// 0, 3), // changes position of shadow
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Text(
|
||||
// 'Dana Sosial Bulan Ini',
|
||||
// style: boldTextStyle.copyWith(
|
||||
// color: Colors.white,
|
||||
// fontSize: 20,
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(height: 10),
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// Text(
|
||||
// 'Total Dana Sosial',
|
||||
// style: regularTextStyle.copyWith(
|
||||
// color: Colors.white,
|
||||
// fontSize: 15,
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// 'Rp. ${OtherFunction().commaFormat(model.jumlahDonasi)}',
|
||||
// style: regularTextStyle.copyWith(
|
||||
// color: Colors.white,
|
||||
// fontSize: 15,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// const SizedBox(height: 10),
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// Text(
|
||||
// 'Pengeluaran Dana Sosial',
|
||||
// style: regularTextStyle.copyWith(
|
||||
// color: Colors.white,
|
||||
// fontSize: 15,
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// 'Rp. ${OtherFunction().commaFormat(model.jumlahPengeluaran)}',
|
||||
// style: regularTextStyle.copyWith(
|
||||
// color: Colors.white,
|
||||
// fontSize: 15,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// const SizedBox(width: 10),
|
||||
// Container(
|
||||
// width: 50,
|
||||
// height: 50,
|
||||
// decoration: const BoxDecoration(
|
||||
// shape: BoxShape.circle,
|
||||
// color: mainColor,
|
||||
// ),
|
||||
// child: IconButton(
|
||||
// icon: const Icon(
|
||||
// Icons.filter_list,
|
||||
// color: Colors.white,
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// model.filterDialog(context);
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
const SizedBox(height: 10),
|
||||
Expanded(
|
||||
flex: 4,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: mainGrey.withOpacity(0.5),
|
||||
spreadRadius: 5,
|
||||
blurRadius: 7,
|
||||
offset:
|
||||
const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
child: (model.danaSosialModelList.isEmpty)
|
||||
? Center(
|
||||
child: Text(
|
||||
'Tidak ada data',
|
||||
style: boldTextStyle.copyWith(
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
)
|
||||
: const TheDataNewly(),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Expanded(
|
||||
flex: 2,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(15),
|
||||
width: double.infinity,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: mainGrey.withOpacity(0.5),
|
||||
spreadRadius: 5,
|
||||
blurRadius: 7,
|
||||
offset:
|
||||
const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
child: model.monthIncomeOutcome.isEmpty
|
||||
? const Center(
|
||||
child: Text(
|
||||
'Tidak ada data',
|
||||
))
|
||||
: const HasilIncomeOutcome(),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: mainGrey.withOpacity(0.5),
|
||||
spreadRadius: 5,
|
||||
blurRadius: 7,
|
||||
offset: const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Total Pemasukan :',
|
||||
),
|
||||
const Expanded(child: SizedBox()),
|
||||
Text(
|
||||
'Rp. ${OtherFunction().commaFormat(model.totalIncome)}',
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
floatingActionButton: model.role == 'admin'
|
||||
? Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: [
|
||||
if (model.role == 'admin')
|
||||
FloatingActionButton(
|
||||
heroTag: 'btn1',
|
||||
onPressed: () {
|
||||
model.goToTambahDanaSosial();
|
||||
},
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
if (model.role == 'admin') const SizedBox(width: 10),
|
||||
if (model.role == 'admin')
|
||||
FloatingActionButton(
|
||||
heroTag: 'btn2',
|
||||
onPressed: () async {
|
||||
bool res = await model.addDonatur();
|
||||
model.log.i(res);
|
||||
},
|
||||
child: const Icon(Icons.person_add_alt),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
FloatingActionButton(
|
||||
heroTag: 'btn3',
|
||||
onPressed: () {
|
||||
model.filterDialog(context);
|
||||
},
|
||||
child: const Icon(Icons.filter_list),
|
||||
),
|
||||
],
|
||||
)
|
||||
: null,
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.miniEndTop,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TheData extends ViewModelWidget<DanaSosialKhususViewModel> {
|
||||
const TheData({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, DanaSosialKhususViewModel viewModel) {
|
||||
return ListView.builder(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10),
|
||||
itemCount: viewModel.danaSosialModelList.length,
|
||||
itemBuilder: (context, index) {
|
||||
String jumlahDonasi = viewModel
|
||||
.danaSosialModelList[index].jenisDonasi !=
|
||||
'Barang'
|
||||
? OtherFunction().commaFormat(
|
||||
int.parse(viewModel.danaSosialModelList[index].jumlah ?? '0'))
|
||||
: '0';
|
||||
return Card(
|
||||
child: ListTile(
|
||||
title: Text(viewModel.danaSosialModelList[index].tanggal ?? '',
|
||||
style: boldTextStyle.copyWith(fontSize: 13, color: mainColor)),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
viewModel.danaSosialModelList[index].bentuk == 'Pemasukan'
|
||||
? 'Pemasukan'
|
||||
: 'Pengeluaran',
|
||||
style: boldTextStyle.copyWith(
|
||||
fontSize: 14,
|
||||
color: viewModel.danaSosialModelList[index].bentuk ==
|
||||
'Pemasukan'
|
||||
? Colors.green
|
||||
: Colors.red,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
viewModel.danaSosialModelList[index].nama ?? '-',
|
||||
style: regularTextStyle.copyWith(
|
||||
fontSize: 13,
|
||||
color: viewModel.danaSosialModelList[index].bentuk ==
|
||||
'Pemasukan'
|
||||
? Colors.green
|
||||
: Colors.red,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
// viewModel.danaSosialModelList[index].jenisDonasi == 'Uang'
|
||||
// ? (viewModel.isLogin == true ? 'Rp. $jumlahDonasi' : '-')
|
||||
// : 'Donasi Barang',
|
||||
viewModel.danaSosialModelList[index].bentuk == 'Pemasukan'
|
||||
? (viewModel.danaSosialModelList[index].jenisDonasi ==
|
||||
'Uang'
|
||||
? (viewModel.isLogin == true
|
||||
? 'Rp. $jumlahDonasi'
|
||||
: '-')
|
||||
: 'Donasi Barang')
|
||||
: (viewModel.danaSosialModelList[index].jenisDonasi ==
|
||||
'Uang'
|
||||
? (viewModel.isLogin == true
|
||||
? 'Rp. $jumlahDonasi'
|
||||
: '-')
|
||||
: 'Pengeluaran Barang'),
|
||||
style: regularTextStyle.copyWith(
|
||||
fontSize: 13,
|
||||
color: viewModel.danaSosialModelList[index].bentuk ==
|
||||
'Pemasukan'
|
||||
? Colors.green
|
||||
: Colors.red,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
viewModel.danaSosialModelList[index].status ?? '',
|
||||
style: regularTextStyle.copyWith(
|
||||
fontSize: 13,
|
||||
color: viewModel.danaSosialModelList[index].status ==
|
||||
'Belum Dikonfirmasi'
|
||||
? Colors.red
|
||||
: Colors.green,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
trailing: viewModel.isLogin == null
|
||||
? null
|
||||
: (viewModel.isLogin == true
|
||||
? Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: mainColor,
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
viewModel.goToEditDanaSosial(int.parse(viewModel
|
||||
.danaSosialModelList[index].idDanaSosial!));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.edit,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Container(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red,
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
child: IconButton(
|
||||
onPressed: () {
|
||||
viewModel.deleteData(int.parse(viewModel
|
||||
.danaSosialModelList[index].idDanaSosial!));
|
||||
},
|
||||
icon: const Icon(
|
||||
Icons.delete,
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
: null),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TheDataNewly extends ViewModelWidget<DanaSosialKhususViewModel> {
|
||||
const TheDataNewly({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, DanaSosialKhususViewModel viewModel) {
|
||||
return ListView.builder(
|
||||
itemCount: viewModel.filteredByDateData.length,
|
||||
itemBuilder: (context, index) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(bottom: 30),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: mainGrey.withOpacity(0.2),
|
||||
spreadRadius: 5,
|
||||
blurRadius: 7,
|
||||
offset: const Offset(0, 3), // changes position of shadow
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${viewModel.otherFunction.changeMonthYear(viewModel.filteredByDateData[index]['month'])} ',
|
||||
style: boldTextStyle.copyWith(
|
||||
decoration: TextDecoration.underline,
|
||||
fontSize: 17,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
for (int i = 0;
|
||||
i < viewModel.filteredByDateData[index]['data'].length;
|
||||
i++)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'${viewModel.filteredByDateData[index]['data'][i]['date']} : ${viewModel.otherFunction.getDayOfWeek(viewModel.filteredByDateData[index]['data'][i]['date'])}',
|
||||
style: italicTextStyle.copyWith(
|
||||
fontWeight: FontWeight.bold, fontSize: 15),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
Table(
|
||||
border: TableBorder.all(
|
||||
color: Colors.grey,
|
||||
),
|
||||
columnWidths: viewModel.role == 'admin'
|
||||
? const {
|
||||
0: FlexColumnWidth(
|
||||
1), // 1/3 of the available width
|
||||
1: FlexColumnWidth(
|
||||
1.5), // 2/3 of the available width
|
||||
2: FlexColumnWidth(
|
||||
2.5), // 2/3 of the available width
|
||||
3: FlexColumnWidth(
|
||||
3), // 2/3 of the available width
|
||||
4: FlexColumnWidth(
|
||||
2), // 2/3 of the available width
|
||||
}
|
||||
: const {
|
||||
0: FlexColumnWidth(
|
||||
1), // 1/3 of the available width
|
||||
1: FlexColumnWidth(
|
||||
2), // 2/3 of the available width
|
||||
2: FlexColumnWidth(
|
||||
2), // 2/3 of the available width
|
||||
3: FlexColumnWidth(
|
||||
3), // 2/3 of the available width
|
||||
},
|
||||
children: [
|
||||
TableRow(
|
||||
children: [
|
||||
const TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'No',
|
||||
style: boldTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
const TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Jenis',
|
||||
style: boldTextStyle,
|
||||
))),
|
||||
const TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Donatur',
|
||||
style: boldTextStyle,
|
||||
))),
|
||||
const TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Jumlah /\nKeterangan',
|
||||
style: boldTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (viewModel.role == 'admin')
|
||||
const TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Aksi',
|
||||
style: boldTextStyle,
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
for (int j = 0;
|
||||
j <
|
||||
viewModel
|
||||
.filteredByDateData[index]['data'][i]
|
||||
['data_dana']
|
||||
.length;
|
||||
j++)
|
||||
TableRow(
|
||||
children: [
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${j + 1}',
|
||||
style: regularTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
child: Center(
|
||||
// circle icon
|
||||
child: viewModel
|
||||
.filteredByDateData[index]
|
||||
['data'][i]['data_dana']
|
||||
[j]
|
||||
.bentuk ==
|
||||
'Pemasukan'
|
||||
? const JenisIconContainer(
|
||||
color: Colors.green,
|
||||
icon: Icons.arrow_upward,
|
||||
)
|
||||
: const JenisIconContainer(
|
||||
color: Colors.red,
|
||||
icon: Icons.arrow_downward,
|
||||
)),
|
||||
),
|
||||
),
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
'${viewModel.filteredByDateData[index]['data'][i]['data_dana'][j].nama == '' ? '-' : viewModel.filteredByDateData[index]['data'][i]['data_dana'][j].nama}',
|
||||
style: regularTextStyle,
|
||||
)),
|
||||
)),
|
||||
TableCell(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
child: Center(
|
||||
child: Text(
|
||||
viewModel
|
||||
.filteredByDateData[index]
|
||||
['data'][i]['data_dana']
|
||||
[j]
|
||||
.jenisDonasi ==
|
||||
'Uang'
|
||||
? 'Rp. ${viewModel.otherFunction.commaFormat(int.parse(viewModel.filteredByDateData[index]['data'][i]['data_dana'][j].jumlah))}'
|
||||
: viewModel
|
||||
.filteredByDateData[index]
|
||||
['data'][i]['data_dana'][j]
|
||||
.keterangan,
|
||||
style: regularTextStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (viewModel.role == 'admin')
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 4,
|
||||
horizontal: 4,
|
||||
),
|
||||
child: Wrap(
|
||||
runSpacing: 10,
|
||||
spacing: 5,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
viewModel.goToEditDanaSosial(
|
||||
int.parse(viewModel
|
||||
.filteredByDateData[
|
||||
index]['data'][i]
|
||||
['data_dana'][j]
|
||||
.idDanaSosial));
|
||||
},
|
||||
child: JenisIconContainer(
|
||||
color: Colors.blue[600]!,
|
||||
icon: Icons.edit,
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
viewModel.deleteData(
|
||||
int.parse(viewModel
|
||||
.filteredByDateData[index]
|
||||
['data'][i]
|
||||
['data_dana'][j]
|
||||
.idDanaSosial!),
|
||||
);
|
||||
},
|
||||
child: const JenisIconContainer(
|
||||
color: Colors.red,
|
||||
icon: Icons.delete,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
// create a horizontal line
|
||||
const Divider(
|
||||
color: Colors.grey,
|
||||
thickness: 1.0,
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class HasilIncomeOutcome extends ViewModelWidget<DanaSosialKhususViewModel> {
|
||||
const HasilIncomeOutcome({
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, DanaSosialKhususViewModel viewModel) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (int i = 0; i < viewModel.monthIncomeOutcome.length; i++)
|
||||
Column(
|
||||
children: [
|
||||
Text(
|
||||
viewModel.otherFunction.changeMonthYear(
|
||||
viewModel.monthIncomeOutcome[i]['month']),
|
||||
style: boldTextStyle.copyWith(
|
||||
decoration: TextDecoration.underline,
|
||||
fontSize: 17,
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
Table(
|
||||
border: TableBorder.all(
|
||||
color: Colors.grey,
|
||||
),
|
||||
children: [
|
||||
const TableRow(children: [
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Pemasukan',
|
||||
style: boldTextStyle,
|
||||
))),
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Pengeluaran',
|
||||
style: boldTextStyle,
|
||||
)))
|
||||
]),
|
||||
TableRow(children: [
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Rp. ${OtherFunction().commaFormat(viewModel.monthIncomeOutcome[i]['income'])}',
|
||||
style: italicTextStyle,
|
||||
))),
|
||||
TableCell(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Rp. ${OtherFunction().commaFormat(viewModel.monthIncomeOutcome[i]['outcome'])}',
|
||||
style: italicTextStyle,
|
||||
)))
|
||||
]),
|
||||
],
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
const Divider(
|
||||
color: Colors.grey,
|
||||
thickness: 1,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 5,
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,327 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../../../app/app.dialogs.dart';
|
||||
import '../../../../app/app.locator.dart';
|
||||
import '../../../../app/app.logger.dart';
|
||||
import '../../../../app/app.router.dart';
|
||||
import '../../../../app/core/custom_base_view_model.dart';
|
||||
import '../../../../model/dana_sosial_model.dart';
|
||||
import '../../../../services/http_services.dart';
|
||||
import '../../../../services/my_easyloading.dart';
|
||||
import '../../../../services/other_function.dart';
|
||||
|
||||
class DanaSosialKhususViewModel extends CustomBaseViewModel {
|
||||
final log = getLogger('DanaSosialKhususViewModel');
|
||||
final _httpService = locator<MyHttpServices>();
|
||||
final easyLoading = locator<MyEasyLoading>();
|
||||
|
||||
int bulan = DateTime.now().month;
|
||||
|
||||
List<DanaSosialModel> danaSosialModelList = [];
|
||||
List<Map<String, dynamic>> filteredByDateData = []; // newly added
|
||||
List<Map<String, dynamic>> monthIncomeOutcome = []; // newly added
|
||||
int totalIncome = 0; // newly added
|
||||
int totalOutcome = 0; // newly added
|
||||
|
||||
String? role;
|
||||
bool? isLogin;
|
||||
|
||||
int jumlahDonasi = 0;
|
||||
int jumlahPengeluaran = 0;
|
||||
|
||||
Future<void> init() async {
|
||||
await getData();
|
||||
await getJumlahDonasi();
|
||||
prefs.then((SharedPreferences prefs) {
|
||||
role = prefs.getString('role');
|
||||
isLogin = prefs.getBool('isLogin');
|
||||
});
|
||||
// log.i(bulan);
|
||||
}
|
||||
|
||||
getJumlahDonasi() async {
|
||||
setBusy(true);
|
||||
easyLoading.showLoading();
|
||||
// get the month
|
||||
var bulan = DateTime.now().month;
|
||||
log.i(bulan);
|
||||
// change bulan to string and add 0 if it is less than 10
|
||||
String bulanString = bulan.toString().length == 1 ? '0$bulan' : '$bulan';
|
||||
log.i(bulanString);
|
||||
try {
|
||||
var response =
|
||||
await _httpService.get('pemasukan_khusus?bulan=$bulanString');
|
||||
log.i(response.data['jumlah']);
|
||||
// var theJumlahDonasi = response.data['jumlah'];
|
||||
jumlahDonasi = response.data['jumlah'];
|
||||
jumlahPengeluaran = response.data['jumlah_pengeluaran'];
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
} finally {
|
||||
setBusy(false);
|
||||
easyLoading.dismissLoading();
|
||||
}
|
||||
}
|
||||
|
||||
getData() async {
|
||||
setBusy(true);
|
||||
easyLoading.showLoading();
|
||||
try {
|
||||
var response = await _httpService.get('dana_sosial_khusus');
|
||||
// log.i(response.data);
|
||||
danaSosialModelList = [];
|
||||
|
||||
var datanya = response.data['data'];
|
||||
// log.i(datanya.length);
|
||||
if (datanya.length > 0) {
|
||||
for (var item in datanya) {
|
||||
danaSosialModelList.add(DanaSosialModel.fromJson(item));
|
||||
}
|
||||
}
|
||||
|
||||
setBusy(false);
|
||||
notifyListeners();
|
||||
// log.i(danaSosialModelList.length);
|
||||
changeByDate(danaSosialModelList);
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
setBusy(false);
|
||||
} finally {
|
||||
easyLoading.dismissLoading();
|
||||
}
|
||||
}
|
||||
|
||||
//newly added
|
||||
changeByDate(List<DanaSosialModel> data) {
|
||||
filteredByDateData = [];
|
||||
|
||||
for (var item in data) {
|
||||
var monthKey =
|
||||
item.tanggal!.substring(0, 7); // Extracting the year and month
|
||||
var dateKey = item.tanggal; // The full date
|
||||
|
||||
var monthData = filteredByDateData.firstWhere(
|
||||
(element) => element['month'] == monthKey,
|
||||
orElse: () => {
|
||||
'month': monthKey,
|
||||
'data': [],
|
||||
});
|
||||
|
||||
var dateData =
|
||||
monthData['data'].firstWhere((element) => element['date'] == dateKey,
|
||||
orElse: () => {
|
||||
'date': dateKey,
|
||||
'data_dana': [],
|
||||
});
|
||||
|
||||
dateData['data_dana'].add(item);
|
||||
|
||||
if (!monthData['data'].contains(dateData)) {
|
||||
monthData['data'].add(dateData);
|
||||
}
|
||||
|
||||
if (!filteredByDateData.contains(monthData)) {
|
||||
filteredByDateData.add(monthData);
|
||||
}
|
||||
}
|
||||
filteredByDateData.sort((a, b) => a['month'].compareTo(b['month']));
|
||||
// log.i(filteredByDateData);
|
||||
|
||||
// group the data by month
|
||||
|
||||
monthIncomeOutcome = [];
|
||||
|
||||
for (var item in filteredByDateData) {
|
||||
var income = 0;
|
||||
var outcome = 0;
|
||||
|
||||
for (var dateData in item['data']) {
|
||||
for (var danaSosialModel in dateData['data_dana']) {
|
||||
if (danaSosialModel.bentuk == 'Pemasukan' &&
|
||||
danaSosialModel.jenisDonasi == 'Uang') {
|
||||
income += int.parse(danaSosialModel.jumlah ?? '0');
|
||||
} else if (danaSosialModel.bentuk == 'Pengeluaran' &&
|
||||
danaSosialModel.jenisDonasi == 'Uang') {
|
||||
outcome += int.parse(danaSosialModel.jumlah ?? '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
monthIncomeOutcome.add({
|
||||
'month': item['month'],
|
||||
'income': income,
|
||||
'outcome': outcome,
|
||||
});
|
||||
}
|
||||
|
||||
// log.i(monthIncomeOutcome);
|
||||
totalIncome = 0;
|
||||
totalOutcome = 0;
|
||||
|
||||
for (var item in monthIncomeOutcome) {
|
||||
totalIncome += int.parse(item['income'].toString());
|
||||
totalOutcome += int.parse(item['outcome'].toString());
|
||||
}
|
||||
|
||||
log.i(totalIncome);
|
||||
log.i(totalOutcome);
|
||||
}
|
||||
|
||||
goToTambahDanaSosial() {
|
||||
navigationService.navigateTo(
|
||||
Routes.tambahDanaSosialView,
|
||||
arguments: const TambahDanaSosialViewArguments(isKhusus: true),
|
||||
);
|
||||
}
|
||||
|
||||
getFilter(String sql) async {
|
||||
setBusy(true);
|
||||
easyLoading.showLoading();
|
||||
FormData formData = FormData.fromMap({
|
||||
'sql': sql,
|
||||
});
|
||||
try {
|
||||
var response = await _httpService.postWithFormData(
|
||||
'filter_dana_khusus',
|
||||
formData,
|
||||
);
|
||||
// log.i(response.data);
|
||||
danaSosialModelList = [];
|
||||
|
||||
var datanya = response.data['data'];
|
||||
jumlahDonasi = response.data['jumlah_donasi'];
|
||||
jumlahPengeluaran = response.data['jumlah_pengeluaran'];
|
||||
// log.i(datanya.length);
|
||||
if (datanya.length > 0) {
|
||||
for (var item in datanya) {
|
||||
danaSosialModelList.add(DanaSosialModel.fromJson(item));
|
||||
}
|
||||
}
|
||||
|
||||
setBusy(false);
|
||||
notifyListeners();
|
||||
log.i(danaSosialModelList);
|
||||
} catch (e) {
|
||||
log.e(e);
|
||||
setBusy(false);
|
||||
} finally {
|
||||
easyLoading.dismissLoading();
|
||||
}
|
||||
}
|
||||
|
||||
filterDialog(BuildContext context) async {
|
||||
// create a dialog
|
||||
final res = await dialogService.showCustomDialog(
|
||||
variant: DialogType.filterDialogView,
|
||||
);
|
||||
|
||||
if (res!.confirmed) {
|
||||
String jenisDonasi = res.data['jenisDonasi'] == 'Semua'
|
||||
? ''
|
||||
: "jenis = '${res.data['jenisDonasi']}' and ";
|
||||
String bulan = res.data['bulan'] == 'Semua'
|
||||
? ''
|
||||
: "tanggal like '%-${OtherFunction().changeMonth(res.data['bulan'])}-%' and ";
|
||||
String tahun = res.data['tahun'] == 'Semua'
|
||||
? ''
|
||||
: 'tanggal like "%${res.data['tahun']}-%" and ';
|
||||
String status = res.data['status'] == 'Semua'
|
||||
? ''
|
||||
: (res.data['status'] == 'Belum Dikonfirmasi')
|
||||
? 'status = 0'
|
||||
: 'status = 1';
|
||||
|
||||
if (jenisDonasi == 'Semua' &&
|
||||
bulan == 'Semua' &&
|
||||
tahun == 'Semua' &&
|
||||
status == 'Semua') {
|
||||
getData();
|
||||
return;
|
||||
}
|
||||
|
||||
String sql =
|
||||
'Select * from tb_dana_sosial_khusus where $jenisDonasi$bulan$tahun$status';
|
||||
|
||||
// check the last 3 character if it is 'or ' then remove it
|
||||
// if (sql.substring(sql.length - 3) == 'or ') {
|
||||
// sql = sql.substring(0, sql.length - 3);
|
||||
// }
|
||||
if (sql.substring(sql.length - 4) == 'and ') {
|
||||
sql = sql.substring(0, sql.length - 4);
|
||||
}
|
||||
|
||||
log.i(sql);
|
||||
|
||||
getFilter(sql);
|
||||
}
|
||||
}
|
||||
|
||||
goToEditDanaSosial(int id) async {
|
||||
navigationService.navigateTo(
|
||||
Routes.detailDanaSosialView,
|
||||
arguments: DetailDanaSosialViewArguments(
|
||||
id: id,
|
||||
isKhusus: true,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
deleteData(int parse) async {
|
||||
await dialogService
|
||||
.showDialog(
|
||||
title: 'Hapus Data',
|
||||
description: 'Apakah anda yakin ingin menghapus data ini?',
|
||||
buttonTitle: 'Hapus',
|
||||
cancelTitle: 'Batal',
|
||||
buttonTitleColor: Colors.red,
|
||||
cancelTitleColor: Colors.green,
|
||||
)
|
||||
.then(
|
||||
(value) async {
|
||||
if (value!.confirmed) {
|
||||
easyLoading.showLoading();
|
||||
setBusy(true);
|
||||
try {
|
||||
var response = await _httpService.postWithFormData(
|
||||
'hapus_dana_sosial_khusus',
|
||||
FormData.fromMap({
|
||||
'id_dana_sosial': parse,
|
||||
}));
|
||||
log.i(response.data);
|
||||
easyLoading.dismissLoading();
|
||||
easyLoading.showSuccess('Data berhasil dihapus');
|
||||
getData();
|
||||
getJumlahDonasi();
|
||||
} on DioError catch (e) {
|
||||
// easyLoading.dismissLoading();
|
||||
log.e(e);
|
||||
easyLoading.showError('Terjadi kesalahan');
|
||||
} finally {
|
||||
setBusy(false);
|
||||
easyLoading.dismissLoading();
|
||||
}
|
||||
} else {
|
||||
log.i('cancel');
|
||||
return;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<bool> addDonatur() async {
|
||||
var res = await dialogService.showCustomDialog(
|
||||
variant: DialogType.addDonaturDialogView,
|
||||
);
|
||||
|
||||
if (res!.confirmed) {
|
||||
snackbarService.showSnackbar(
|
||||
message: 'Berhasil menambahkan donatur',
|
||||
duration: const Duration(seconds: 2),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -44,7 +44,7 @@ class DataSiswaView extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Total Siswa',
|
||||
'Total Anak Panti',
|
||||
style: regularTextStyle.copyWith(
|
||||
color: Colors.white,
|
||||
fontSize: 15,
|
||||
@ -93,8 +93,23 @@ class DataSiswaView extends StatelessWidget {
|
||||
itemBuilder: (context, index) {
|
||||
return Card(
|
||||
child: ListTile(
|
||||
leading: Container(
|
||||
alignment: Alignment.center,
|
||||
width: 25,
|
||||
height: 25,
|
||||
decoration: BoxDecoration(
|
||||
color: mainColor,
|
||||
borderRadius: BorderRadius.circular(50),
|
||||
),
|
||||
child: Text(
|
||||
'${index + 1}',
|
||||
style: regularTextStyle.copyWith(
|
||||
color: Colors.white),
|
||||
),
|
||||
),
|
||||
title: Text(
|
||||
model.siswaModelList[index].nama ?? '',
|
||||
model.otherFunction.capitalizeEachWord(
|
||||
model.siswaModelList[index].nama!),
|
||||
style: boldTextStyle.copyWith(
|
||||
fontSize: 13, color: mainColor)),
|
||||
subtitle: Text(
|
||||
|
||||
@ -49,7 +49,7 @@ class EditDialogSiswaView extends StatelessWidget {
|
||||
children: [
|
||||
const Center(
|
||||
child: Text(
|
||||
'Edit Data Siswa',
|
||||
'Edit Data Anak Panti',
|
||||
style: boldTextStyle,
|
||||
),
|
||||
),
|
||||
|
||||
@ -29,7 +29,7 @@ class EditSiswaView extends StatelessWidget {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text(
|
||||
"Informasi Data Siswa",
|
||||
"Informasi Data Anak Panti",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 20,
|
||||
|
||||
@ -16,6 +16,7 @@ class FilterDialogViewModel extends CustomBaseViewModel {
|
||||
'April',
|
||||
'Mei',
|
||||
'Juni',
|
||||
'Juli',
|
||||
'Agustus',
|
||||
'September',
|
||||
'Oktober',
|
||||
@ -26,6 +27,7 @@ class FilterDialogViewModel extends CustomBaseViewModel {
|
||||
String tahun = 'Semua';
|
||||
List<String> tahunList = [
|
||||
'Semua',
|
||||
'2024',
|
||||
'2023',
|
||||
'2022',
|
||||
];
|
||||
|
||||
@ -47,7 +47,7 @@ class ProfilView extends StatelessWidget {
|
||||
SizedBox(width: 15),
|
||||
Expanded(
|
||||
child: Text(
|
||||
"081 343 434 343",
|
||||
"085 298 962 023",
|
||||
textAlign: TextAlign.justify,
|
||||
style: regularTextStyle,
|
||||
),
|
||||
|
||||
@ -56,6 +56,13 @@ class StrukturOrganisasiView extends StatelessWidget {
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
FirstWidget(
|
||||
title: 'Wakil Bendahara',
|
||||
data: model.dataWakilBendahara,
|
||||
),
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
SecondWidget(
|
||||
title: 'Seksi Pengasuh',
|
||||
data: model.dataPengasuh,
|
||||
|
||||
@ -16,6 +16,7 @@ class StrukturOrganisasiViewModel extends CustomBaseViewModel {
|
||||
Map<String, dynamic> dataKetua = {};
|
||||
Map<String, dynamic> dataSekretaris = {};
|
||||
Map<String, dynamic> dataBendahara = {};
|
||||
Map<String, dynamic> dataWakilBendahara = {};
|
||||
|
||||
Map<String, dynamic> dataPengasuh = {};
|
||||
int dataPengasuhLength = 0;
|
||||
@ -63,6 +64,7 @@ class StrukturOrganisasiViewModel extends CustomBaseViewModel {
|
||||
getData('Ketua', false, null);
|
||||
getData('Sekretaris', false, null);
|
||||
getData('Bendahara', false, null);
|
||||
getData('Wakil Bendahara', false, null);
|
||||
getData('Seksi Pengasuh', true, dataPengasuhLength);
|
||||
getData('Seksi Ibadah', true, dataIbadahLength);
|
||||
getData('Seksi Pendidikan', true, dataPendidikanLength);
|
||||
@ -108,6 +110,8 @@ class StrukturOrganisasiViewModel extends CustomBaseViewModel {
|
||||
dataSekretaris = data;
|
||||
} else if (jabatan == 'Bendahara') {
|
||||
dataBendahara = data;
|
||||
} else if (jabatan == 'Wakil Bendahara') {
|
||||
dataWakilBendahara = data;
|
||||
} else if (jabatan == 'Seksi Pengasuh') {
|
||||
dataPengasuh = data;
|
||||
dataPengasuhLength = length!;
|
||||
|
||||
Reference in New Issue
Block a user