added cetak laporan

This commit is contained in:
kicap
2024-06-05 17:09:58 +08:00
parent 41ecbc0065
commit 0ad81dd67d
41 changed files with 3065 additions and 342 deletions

View File

@ -1,13 +1,16 @@
import 'package:panti_asuhan/ui/views/admin_index_tracking/edit_siswa/edit_dialog_siswa/edit_dialog_siswa_view.dart';
import 'package:stacked_services/stacked_services.dart';
import 'package:stacked/stacked_annotations.dart';
import '../services/http_services.dart';
import '../services/my_easyloading.dart';
import '../services/other_function.dart';
import '../ui/views/admin_index_tracking/add_siswa_dialog/add_siswa_dialog/add_siswa_dialog_view.dart';
import '../ui/views/admin_index_tracking/dana_sosial_khusus/add_donatur_dialog/add_donatur_dialog_view.dart';
import '../ui/views/admin_index_tracking/dana_sosial_khusus/dana_sosial_khusus_view.dart';
import '../ui/views/admin_index_tracking/admin_index_tracking_view.dart';
import '../ui/views/admin_index_tracking/dana_sosial_admin/dana_sosial_admin_view.dart';
import '../ui/views/admin_index_tracking/data_siswa/data_siswa_view.dart';
import '../ui/views/admin_index_tracking/edit_siswa/edit_dialog_siswa/edit_dialog_siswa_view.dart';
import '../ui/views/admin_index_tracking/edit_siswa/edit_siswa_view.dart';
import '../ui/views/admin_index_tracking/filter_dialog/filter_dialog_view.dart';
import '../ui/views/admin_index_tracking/profil/profil_view.dart';
@ -31,11 +34,14 @@ import '../ui/views/user_index_tracking/user_index_tracking_view.dart';
children: [
// MaterialRoute(page: AdminIndexView, initial: true),
MaterialRoute(page: DanaSosialAdminView),
MaterialRoute(page: DanaSosialKhususView),
MaterialRoute(page: DataSiswaView),
MaterialRoute(page: ProfilView),
MaterialRoute(page: VisiMisiView),
MaterialRoute(page: SejarahView),
MaterialRoute(page: StrukturOrganisasiView),
MaterialRoute(
page: StrukturOrganisasiView,
),
],
),
MaterialRoute(page: TambahDanaSosialView),
@ -46,6 +52,7 @@ import '../ui/views/user_index_tracking/user_index_tracking_view.dart';
children: [
// MaterialRoute(page: AdminIndexView, initial: true),
MaterialRoute(page: DanaSosialAdminView),
MaterialRoute(page: DanaSosialKhususView),
MaterialRoute(page: DataSiswaView),
MaterialRoute(page: ProfilView),
],
@ -55,6 +62,7 @@ import '../ui/views/user_index_tracking/user_index_tracking_view.dart';
children: [
// MaterialRoute(page: AdminIndexView, initial: true),
MaterialRoute(page: DanaSosialAdminView),
MaterialRoute(page: DanaSosialKhususView),
MaterialRoute(page: DataSiswaView),
MaterialRoute(page: ProfilView),
MaterialRoute(page: VisiMisiView),
@ -67,7 +75,8 @@ import '../ui/views/user_index_tracking/user_index_tracking_view.dart';
StackedDialog(classType: AddSiswaDialogView),
StackedDialog(classType: FilterDialogView),
StackedDialog(classType: EditStrukrurOrganisasiDialogView),
StackedDialog(classType: EditDialogSiswaView)
StackedDialog(classType: EditDialogSiswaView),
StackedDialog(classType: AddDonaturDialogView),
],
dependencies: [
LazySingleton(classType: NavigationService),
@ -78,6 +87,7 @@ import '../ui/views/user_index_tracking/user_index_tracking_view.dart';
LazySingleton(classType: MyEasyLoading),
LazySingleton(classType: MyHttpServices),
LazySingleton(classType: OtherFunction),
],
logger: StackedLogger(),
)

View File

@ -8,6 +8,7 @@ import 'package:stacked_services/stacked_services.dart';
import 'app.locator.dart';
import '../ui/views/admin_index_tracking/add_siswa_dialog/add_siswa_dialog/add_siswa_dialog_view.dart';
import '../ui/views/admin_index_tracking/dana_sosial_khusus/add_donatur_dialog/add_donatur_dialog_view.dart';
import '../ui/views/admin_index_tracking/edit_siswa/edit_dialog_siswa/edit_dialog_siswa_view.dart';
import '../ui/views/admin_index_tracking/filter_dialog/filter_dialog_view.dart';
import '../ui/views/admin_index_tracking/struktur_organisasi/edit_strukrur_organisasi_dialog/edit_strukrur_organisasi_dialog_view.dart';
@ -17,6 +18,7 @@ enum DialogType {
filterDialogView,
editStrukrurOrganisasiDialogView,
editDialogSiswaView,
addDonaturDialogView,
}
void setupDialogUi() {
@ -32,6 +34,8 @@ void setupDialogUi() {
request: request, completer: completer),
DialogType.editDialogSiswaView: (context, request, completer) =>
EditDialogSiswaView(request: request, completer: completer),
DialogType.addDonaturDialogView: (context, request, completer) =>
AddDonaturDialogView(request: request, completer: completer),
};
dialogService.registerCustomDialogBuilders(builders);

View File

@ -14,6 +14,7 @@ import 'package:stacked_shared/stacked_shared.dart';
import '../services/http_services.dart';
import '../services/my_easyloading.dart';
import '../services/other_function.dart';
final locator = StackedLocator.instance;
@ -32,4 +33,5 @@ Future<void> setupLocator({
locator.registerLazySingleton(() => BottomSheetService());
locator.registerLazySingleton(() => MyEasyLoading());
locator.registerLazySingleton(() => MyHttpServices());
locator.registerLazySingleton(() => OtherFunction());
}

View File

@ -11,18 +11,20 @@ import 'package:panti_asuhan/ui/views/admin_index_tracking/admin_index_tracking_
as _i4;
import 'package:panti_asuhan/ui/views/admin_index_tracking/dana_sosial_admin/dana_sosial_admin_view.dart'
as _i11;
import 'package:panti_asuhan/ui/views/admin_index_tracking/data_siswa/data_siswa_view.dart'
import 'package:panti_asuhan/ui/views/admin_index_tracking/dana_sosial_khusus/dana_sosial_khusus_view.dart'
as _i12;
import 'package:panti_asuhan/ui/views/admin_index_tracking/data_siswa/data_siswa_view.dart'
as _i13;
import 'package:panti_asuhan/ui/views/admin_index_tracking/edit_siswa/edit_siswa_view.dart'
as _i6;
import 'package:panti_asuhan/ui/views/admin_index_tracking/profil/profil_view.dart'
as _i13;
import 'package:panti_asuhan/ui/views/admin_index_tracking/sejarah/sejarah_view.dart'
as _i15;
import 'package:panti_asuhan/ui/views/admin_index_tracking/struktur_organisasi/struktur_organisasi_view.dart'
as _i16;
import 'package:panti_asuhan/ui/views/admin_index_tracking/visi_misi/visi_misi_view.dart'
as _i14;
import 'package:panti_asuhan/ui/views/admin_index_tracking/sejarah/sejarah_view.dart'
as _i16;
import 'package:panti_asuhan/ui/views/admin_index_tracking/struktur_organisasi/struktur_organisasi_view.dart'
as _i17;
import 'package:panti_asuhan/ui/views/admin_index_tracking/visi_misi/visi_misi_view.dart'
as _i15;
import 'package:panti_asuhan/ui/views/detail_dana_sosial/detail_dana_sosial_view.dart'
as _i7;
import 'package:panti_asuhan/ui/views/login_screen/login_screen_view.dart'
@ -36,7 +38,7 @@ import 'package:panti_asuhan/ui/views/tambah_dana_sosial/tambah_dana_sosial_view
import 'package:panti_asuhan/ui/views/user_index_tracking/user_index_tracking_view.dart'
as _i9;
import 'package:stacked/stacked.dart' as _i1;
import 'package:stacked_services/stacked_services.dart' as _i17;
import 'package:stacked_services/stacked_services.dart' as _i18;
class Routes {
static const splashScreenView = '/';
@ -126,8 +128,12 @@ class StackedRouter extends _i1.RouterBase {
);
},
_i5.TambahDanaSosialView: (data) {
final args = data.getArgs<TambahDanaSosialViewArguments>(
orElse: () => const TambahDanaSosialViewArguments(),
);
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i5.TambahDanaSosialView(),
builder: (context) =>
_i5.TambahDanaSosialView(key: args.key, isKhusus: args.isKhusus),
settings: data,
maintainState: false,
);
@ -144,8 +150,8 @@ class StackedRouter extends _i1.RouterBase {
_i7.DetailDanaSosialView: (data) {
final args = data.getArgs<DetailDanaSosialViewArguments>(nullOk: false);
return _i10.MaterialPageRoute<dynamic>(
builder: (context) =>
_i7.DetailDanaSosialView(key: args.key, id: args.id),
builder: (context) => _i7.DetailDanaSosialView(
key: args.key, id: args.id, isKhusus: args.isKhusus),
settings: data,
maintainState: false,
);
@ -172,6 +178,22 @@ class StackedRouter extends _i1.RouterBase {
Map<Type, _i1.StackedRouteFactory> get pagesMap => _pagesMap;
}
class TambahDanaSosialViewArguments {
const TambahDanaSosialViewArguments({
this.key,
this.isKhusus = false,
});
final _i10.Key? key;
final bool isKhusus;
@override
String toString() {
return '{"key": "$key", "isKhusus": "$isKhusus"}';
}
}
class EditSiswaViewArguments {
const EditSiswaViewArguments({
required this.idSiswa,
@ -192,21 +214,26 @@ class DetailDanaSosialViewArguments {
const DetailDanaSosialViewArguments({
this.key,
required this.id,
this.isKhusus = false,
});
final _i10.Key? key;
final int id;
final bool isKhusus;
@override
String toString() {
return '{"key": "$key", "id": "$id"}';
return '{"key": "$key", "id": "$id", "isKhusus": "$isKhusus"}';
}
}
class AdminIndexTrackingViewRoutes {
static const danaSosialAdminView = 'dana-sosial-admin-view';
static const danaSosialKhususView = 'dana-sosial-khusus-view';
static const dataSiswaView = 'data-siswa-view';
static const profilView = 'profil-view';
@ -219,6 +246,7 @@ class AdminIndexTrackingViewRoutes {
static const all = <String>{
danaSosialAdminView,
danaSosialKhususView,
dataSiswaView,
profilView,
visiMisiView,
@ -233,25 +261,29 @@ class AdminIndexTrackingViewRouter extends _i1.RouterBase {
AdminIndexTrackingViewRoutes.danaSosialAdminView,
page: _i11.DanaSosialAdminView,
),
_i1.RouteDef(
AdminIndexTrackingViewRoutes.danaSosialKhususView,
page: _i12.DanaSosialKhususView,
),
_i1.RouteDef(
AdminIndexTrackingViewRoutes.dataSiswaView,
page: _i12.DataSiswaView,
page: _i13.DataSiswaView,
),
_i1.RouteDef(
AdminIndexTrackingViewRoutes.profilView,
page: _i13.ProfilView,
page: _i14.ProfilView,
),
_i1.RouteDef(
AdminIndexTrackingViewRoutes.visiMisiView,
page: _i14.VisiMisiView,
page: _i15.VisiMisiView,
),
_i1.RouteDef(
AdminIndexTrackingViewRoutes.sejarahView,
page: _i15.SejarahView,
page: _i16.SejarahView,
),
_i1.RouteDef(
AdminIndexTrackingViewRoutes.strukturOrganisasiView,
page: _i16.StrukturOrganisasiView,
page: _i17.StrukturOrganisasiView,
),
];
@ -263,37 +295,44 @@ class AdminIndexTrackingViewRouter extends _i1.RouterBase {
maintainState: false,
);
},
_i12.DataSiswaView: (data) {
_i12.DanaSosialKhususView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i12.DataSiswaView(),
builder: (context) => const _i12.DanaSosialKhususView(),
settings: data,
maintainState: false,
);
},
_i13.ProfilView: (data) {
_i13.DataSiswaView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i13.ProfilView(),
builder: (context) => const _i13.DataSiswaView(),
settings: data,
maintainState: false,
);
},
_i14.VisiMisiView: (data) {
_i14.ProfilView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i14.VisiMisiView(),
builder: (context) => const _i14.ProfilView(),
settings: data,
maintainState: false,
);
},
_i15.SejarahView: (data) {
_i15.VisiMisiView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i15.SejarahView(),
builder: (context) => const _i15.VisiMisiView(),
settings: data,
maintainState: false,
);
},
_i16.StrukturOrganisasiView: (data) {
_i16.SejarahView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i16.StrukturOrganisasiView(),
builder: (context) => const _i16.SejarahView(),
settings: data,
maintainState: false,
);
},
_i17.StrukturOrganisasiView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i17.StrukturOrganisasiView(),
settings: data,
maintainState: false,
);
@ -309,12 +348,15 @@ class AdminIndexTrackingViewRouter extends _i1.RouterBase {
class PimpinanIndexTrackingViewRoutes {
static const danaSosialAdminView = 'dana-sosial-admin-view';
static const danaSosialKhususView = 'dana-sosial-khusus-view';
static const dataSiswaView = 'data-siswa-view';
static const profilView = 'profil-view';
static const all = <String>{
danaSosialAdminView,
danaSosialKhususView,
dataSiswaView,
profilView,
};
@ -326,13 +368,17 @@ class PimpinanIndexTrackingViewRouter extends _i1.RouterBase {
PimpinanIndexTrackingViewRoutes.danaSosialAdminView,
page: _i11.DanaSosialAdminView,
),
_i1.RouteDef(
PimpinanIndexTrackingViewRoutes.danaSosialKhususView,
page: _i12.DanaSosialKhususView,
),
_i1.RouteDef(
PimpinanIndexTrackingViewRoutes.dataSiswaView,
page: _i12.DataSiswaView,
page: _i13.DataSiswaView,
),
_i1.RouteDef(
PimpinanIndexTrackingViewRoutes.profilView,
page: _i13.ProfilView,
page: _i14.ProfilView,
),
];
@ -344,16 +390,23 @@ class PimpinanIndexTrackingViewRouter extends _i1.RouterBase {
maintainState: false,
);
},
_i12.DataSiswaView: (data) {
_i12.DanaSosialKhususView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i12.DataSiswaView(),
builder: (context) => const _i12.DanaSosialKhususView(),
settings: data,
maintainState: false,
);
},
_i13.ProfilView: (data) {
_i13.DataSiswaView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i13.ProfilView(),
builder: (context) => const _i13.DataSiswaView(),
settings: data,
maintainState: false,
);
},
_i14.ProfilView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i14.ProfilView(),
settings: data,
maintainState: false,
);
@ -369,6 +422,8 @@ class PimpinanIndexTrackingViewRouter extends _i1.RouterBase {
class UserIndexTrackingViewRoutes {
static const danaSosialAdminView = 'dana-sosial-admin-view';
static const danaSosialKhususView = 'dana-sosial-khusus-view';
static const dataSiswaView = 'data-siswa-view';
static const profilView = 'profil-view';
@ -381,6 +436,7 @@ class UserIndexTrackingViewRoutes {
static const all = <String>{
danaSosialAdminView,
danaSosialKhususView,
dataSiswaView,
profilView,
visiMisiView,
@ -395,25 +451,29 @@ class UserIndexTrackingViewRouter extends _i1.RouterBase {
UserIndexTrackingViewRoutes.danaSosialAdminView,
page: _i11.DanaSosialAdminView,
),
_i1.RouteDef(
UserIndexTrackingViewRoutes.danaSosialKhususView,
page: _i12.DanaSosialKhususView,
),
_i1.RouteDef(
UserIndexTrackingViewRoutes.dataSiswaView,
page: _i12.DataSiswaView,
page: _i13.DataSiswaView,
),
_i1.RouteDef(
UserIndexTrackingViewRoutes.profilView,
page: _i13.ProfilView,
page: _i14.ProfilView,
),
_i1.RouteDef(
UserIndexTrackingViewRoutes.visiMisiView,
page: _i14.VisiMisiView,
page: _i15.VisiMisiView,
),
_i1.RouteDef(
UserIndexTrackingViewRoutes.sejarahView,
page: _i15.SejarahView,
page: _i16.SejarahView,
),
_i1.RouteDef(
UserIndexTrackingViewRoutes.strukturOrganisasiView,
page: _i16.StrukturOrganisasiView,
page: _i17.StrukturOrganisasiView,
),
];
@ -425,37 +485,44 @@ class UserIndexTrackingViewRouter extends _i1.RouterBase {
maintainState: false,
);
},
_i12.DataSiswaView: (data) {
_i12.DanaSosialKhususView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i12.DataSiswaView(),
builder: (context) => const _i12.DanaSosialKhususView(),
settings: data,
maintainState: false,
);
},
_i13.ProfilView: (data) {
_i13.DataSiswaView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i13.ProfilView(),
builder: (context) => const _i13.DataSiswaView(),
settings: data,
maintainState: false,
);
},
_i14.VisiMisiView: (data) {
_i14.ProfilView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i14.VisiMisiView(),
builder: (context) => const _i14.ProfilView(),
settings: data,
maintainState: false,
);
},
_i15.SejarahView: (data) {
_i15.VisiMisiView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i15.SejarahView(),
builder: (context) => const _i15.VisiMisiView(),
settings: data,
maintainState: false,
);
},
_i16.StrukturOrganisasiView: (data) {
_i16.SejarahView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i16.StrukturOrganisasiView(),
builder: (context) => const _i16.SejarahView(),
settings: data,
maintainState: false,
);
},
_i17.StrukturOrganisasiView: (data) {
return _i10.MaterialPageRoute<dynamic>(
builder: (context) => const _i17.StrukturOrganisasiView(),
settings: data,
maintainState: false,
);
@ -468,7 +535,7 @@ class UserIndexTrackingViewRouter extends _i1.RouterBase {
Map<Type, _i1.StackedRouteFactory> get pagesMap => _pagesMap;
}
extension NavigatorStateExtension on _i17.NavigationService {
extension NavigatorStateExtension on _i18.NavigationService {
Future<dynamic> navigateToSplashScreenView([
int? routerId,
bool preventDuplicates = true,
@ -511,14 +578,17 @@ extension NavigatorStateExtension on _i17.NavigationService {
transition: transition);
}
Future<dynamic> navigateToTambahDanaSosialView([
Future<dynamic> navigateToTambahDanaSosialView({
_i10.Key? key,
bool isKhusus = false,
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
]) async {
}) async {
return navigateTo<dynamic>(Routes.tambahDanaSosialView,
arguments: TambahDanaSosialViewArguments(key: key, isKhusus: isKhusus),
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
@ -545,6 +615,7 @@ extension NavigatorStateExtension on _i17.NavigationService {
Future<dynamic> navigateToDetailDanaSosialView({
_i10.Key? key,
required int id,
bool isKhusus = false,
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
@ -552,7 +623,8 @@ extension NavigatorStateExtension on _i17.NavigationService {
transition,
}) async {
return navigateTo<dynamic>(Routes.detailDanaSosialView,
arguments: DetailDanaSosialViewArguments(key: key, id: id),
arguments:
DetailDanaSosialViewArguments(key: key, id: id, isKhusus: isKhusus),
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
@ -602,6 +674,22 @@ extension NavigatorStateExtension on _i17.NavigationService {
transition: transition);
}
Future<dynamic>
navigateToNestedDanaSosialKhususViewInAdminIndexTrackingViewRouter([
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
]) async {
return navigateTo<dynamic>(
AdminIndexTrackingViewRoutes.danaSosialKhususView,
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
transition: transition);
}
Future<dynamic> navigateToNestedDataSiswaViewInAdminIndexTrackingViewRouter([
int? routerId,
bool preventDuplicates = true,
@ -690,6 +778,22 @@ extension NavigatorStateExtension on _i17.NavigationService {
transition: transition);
}
Future<dynamic>
navigateToNestedDanaSosialKhususViewInPimpinanIndexTrackingViewRouter([
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
]) async {
return navigateTo<dynamic>(
PimpinanIndexTrackingViewRoutes.danaSosialKhususView,
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
transition: transition);
}
Future<dynamic>
navigateToNestedDataSiswaViewInPimpinanIndexTrackingViewRouter([
int? routerId,
@ -734,6 +838,21 @@ extension NavigatorStateExtension on _i17.NavigationService {
transition: transition);
}
Future<dynamic>
navigateToNestedDanaSosialKhususViewInUserIndexTrackingViewRouter([
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
]) async {
return navigateTo<dynamic>(UserIndexTrackingViewRoutes.danaSosialKhususView,
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
transition: transition);
}
Future<dynamic> navigateToNestedDataSiswaViewInUserIndexTrackingViewRouter([
int? routerId,
bool preventDuplicates = true,
@ -848,14 +967,17 @@ extension NavigatorStateExtension on _i17.NavigationService {
transition: transition);
}
Future<dynamic> replaceWithTambahDanaSosialView([
Future<dynamic> replaceWithTambahDanaSosialView({
_i10.Key? key,
bool isKhusus = false,
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
]) async {
}) async {
return replaceWith<dynamic>(Routes.tambahDanaSosialView,
arguments: TambahDanaSosialViewArguments(key: key, isKhusus: isKhusus),
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
@ -882,6 +1004,7 @@ extension NavigatorStateExtension on _i17.NavigationService {
Future<dynamic> replaceWithDetailDanaSosialView({
_i10.Key? key,
required int id,
bool isKhusus = false,
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
@ -889,7 +1012,8 @@ extension NavigatorStateExtension on _i17.NavigationService {
transition,
}) async {
return replaceWith<dynamic>(Routes.detailDanaSosialView,
arguments: DetailDanaSosialViewArguments(key: key, id: id),
arguments:
DetailDanaSosialViewArguments(key: key, id: id, isKhusus: isKhusus),
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
@ -940,6 +1064,22 @@ extension NavigatorStateExtension on _i17.NavigationService {
transition: transition);
}
Future<dynamic>
replaceWithNestedDanaSosialKhususViewInAdminIndexTrackingViewRouter([
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
]) async {
return replaceWith<dynamic>(
AdminIndexTrackingViewRoutes.danaSosialKhususView,
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
transition: transition);
}
Future<dynamic> replaceWithNestedDataSiswaViewInAdminIndexTrackingViewRouter([
int? routerId,
bool preventDuplicates = true,
@ -1028,6 +1168,22 @@ extension NavigatorStateExtension on _i17.NavigationService {
transition: transition);
}
Future<dynamic>
replaceWithNestedDanaSosialKhususViewInPimpinanIndexTrackingViewRouter([
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
]) async {
return replaceWith<dynamic>(
PimpinanIndexTrackingViewRoutes.danaSosialKhususView,
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
transition: transition);
}
Future<dynamic>
replaceWithNestedDataSiswaViewInPimpinanIndexTrackingViewRouter([
int? routerId,
@ -1072,6 +1228,22 @@ extension NavigatorStateExtension on _i17.NavigationService {
transition: transition);
}
Future<dynamic>
replaceWithNestedDanaSosialKhususViewInUserIndexTrackingViewRouter([
int? routerId,
bool preventDuplicates = true,
Map<String, String>? parameters,
Widget Function(BuildContext, Animation<double>, Animation<double>, Widget)?
transition,
]) async {
return replaceWith<dynamic>(
UserIndexTrackingViewRoutes.danaSosialKhususView,
id: routerId,
preventDuplicates: preventDuplicates,
parameters: parameters,
transition: transition);
}
Future<dynamic> replaceWithNestedDataSiswaViewInUserIndexTrackingViewRouter([
int? routerId,
bool preventDuplicates = true,

View File

@ -2,6 +2,7 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart';
import '../../services/other_function.dart';
import '../app.locator.dart';
class CustomBaseViewModel extends BaseViewModel {
@ -10,6 +11,7 @@ class CustomBaseViewModel extends BaseViewModel {
final bottomSheetService = locator<BottomSheetService>();
final snackbarService = locator<SnackbarService>();
final Future<SharedPreferences> prefs = SharedPreferences.getInstance();
final otherFunction = locator<OtherFunction>();
void back() {
navigationService.back();

View File

@ -1,3 +1,5 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
@ -10,6 +12,7 @@ import 'app/themes/app_theme.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
HttpOverrides.global = MyHttpOverrides();
await dotenv.load(fileName: ".env");
await setupAllLocator();
runApp(const MyApp());
@ -38,3 +41,12 @@ Future<void> setupAllLocator() async {
// setupBottomsheetUi();
// setupSnackbarUi();
}
class MyHttpOverrides extends HttpOverrides {
@override
HttpClient createHttpClient(SecurityContext? context) {
return super.createHttpClient(context)
..badCertificateCallback =
(X509Certificate cert, String host, int port) => true;
}
}

View File

@ -7,6 +7,9 @@ class DanaSosialModel {
String? keterangan;
String? jenisDonasi;
String? status;
String? jenisBarang;
String? satuan;
String? jumlahBarang;
String? createdAt;
String? updatedAt;
@ -20,6 +23,9 @@ class DanaSosialModel {
this.keterangan,
this.jenisDonasi,
this.status,
this.jenisBarang,
this.satuan,
this.jumlahBarang,
this.createdAt,
this.updatedAt});
@ -33,6 +39,9 @@ class DanaSosialModel {
jenisDonasi = json['jenis'];
status =
json['status'] == '0' ? 'Belum Dikonfirmasi' : 'Sudah Dikonfirmasi';
jenisBarang = json['jenis_barang'] ?? '';
satuan = json['satuan'] ?? '';
jumlahBarang = json['jumlah_barang'] ?? '';
createdAt = json['created_at'];
updatedAt = json['updated_at'];
}
@ -47,6 +56,9 @@ class DanaSosialModel {
data['ket'] = keterangan;
data['jenis'] = jenisDonasi;
data['status'] = status;
data['jenis_barang'] = jenisBarang;
data['satuan'] = satuan;
data['jumlah_barang'] = jumlahBarang;
data['created_at'] = createdAt;
data['updated_at'] = updatedAt;
return data;

View File

@ -32,7 +32,8 @@ class MyHttpServices {
return await _dio.post(path, data: formData);
} on DioError catch (e) {
log.e(e.message);
log.e(e.response);
log.e(e.response!.statusCode);
log.e(e.response!.statusMessage);
rethrow;
}
}

View File

@ -46,4 +46,61 @@ class OtherFunction {
return '';
}
}
String changeMonthYear(String s) {
// get the last 2 digits
String month = s.substring(s.length - 2);
// get the first 4 digits
String year = s.substring(0, 4);
// return the month and year
switch (month) {
case '01':
return 'Januari $year';
case '02':
return 'Februari $year';
case '03':
return 'Maret $year';
case '04':
return 'April $year';
case '05':
return 'Mei $year';
case '06':
return 'Juni $year';
case '07':
return 'Juli $year';
case '08':
return 'Agustus $year';
case '09':
return 'September $year';
case '10':
return 'Oktober $year';
case '11':
return 'November $year';
case '12':
return 'Desember $year';
default:
return '';
}
}
String getDayOfWeek(String date) {
DateTime dateTime = DateTime.parse(date);
List<String> daysOfWeek = [
'Senin',
'Selasa',
'Rabu',
'Kamis',
'Jumat',
'Sabtu',
'Minggu'
];
return daysOfWeek[dateTime.weekday - 1];
}
String capitalizeEachWord(String s) {
return s
.split(' ')
.map((word) => word[0].toUpperCase() + word.substring(1))
.join(' ');
}
}

View File

@ -53,7 +53,7 @@ class AddSiswaDialogView extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Tambah Siswa',
'Tambah Anak Panti',
style: boldTextStyle.copyWith(
fontSize: 16,
),

View File

@ -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 ==

View File

@ -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,

View File

@ -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,
),
);
}
}

View File

@ -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();
}
}
}

View File

@ -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));
}
}
},
),
),
],
),
),
),
);
},
);
}
}

View File

@ -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();
}
}
}

View File

@ -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,
),
],
)
],
),
);
}
}

View File

@ -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;
}
}

View File

@ -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(

View File

@ -49,7 +49,7 @@ class EditDialogSiswaView extends StatelessWidget {
children: [
const Center(
child: Text(
'Edit Data Siswa',
'Edit Data Anak Panti',
style: boldTextStyle,
),
),

View File

@ -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,

View File

@ -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',
];

View File

@ -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,
),

View File

@ -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,

View File

@ -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!;

View File

@ -9,14 +9,18 @@ import './detail_dana_sosial_view_model.dart';
class DetailDanaSosialView extends StatelessWidget {
final int id;
const DetailDanaSosialView({Key? key, required this.id}) : super(key: key);
final bool isKhusus;
const DetailDanaSosialView(
{Key? key, required this.id, this.isKhusus = false})
: super(key: key);
@override
Widget build(BuildContext context) {
return ViewModelBuilder<DetailDanaSosialViewModel>.reactive(
viewModelBuilder: () => DetailDanaSosialViewModel(),
onViewModelReady: (DetailDanaSosialViewModel model) async {
await model.init(id);
await model.init(id, isKhusus);
},
builder: (
BuildContext context,
@ -37,7 +41,7 @@ class DetailDanaSosialView extends StatelessWidget {
child: CircularProgressIndicator(),
)
: (model.danaSosialModel!.bentuk == 'Pemasukan'
? const PemasukanWidget()
? const SafeArea(child: PemasukanWidget())
: const PengeluaranWidget()),
),
);
@ -205,147 +209,183 @@ class PemasukanWidget extends ViewModelWidget<DetailDanaSosialViewModel> {
@override
Widget build(BuildContext context, DetailDanaSosialViewModel viewModel) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
"Nama Donator",
style: regularTextStyle.copyWith(color: mainColor),
),
),
MyTextFormField(
controller: viewModel.namaController,
maxLines: 1,
readOnly: true,
),
const SizedBox(
height: 15,
),
Align(
alignment: Alignment.centerLeft,
child: Text(
"Tanggal",
style: regularTextStyle.copyWith(color: mainColor),
),
),
MyTextFormField(
controller: viewModel.tanggalController,
maxLines: 1,
readOnly: true,
),
const SizedBox(
height: 15,
),
Align(
alignment: Alignment.centerLeft,
child: Text(
"Jenis",
style: regularTextStyle.copyWith(color: mainColor),
),
),
MyTextFormField(
controller: viewModel.jenisController,
maxLines: 1,
readOnly: true,
),
Visibility(
visible: viewModel.jenisBool,
child: const SizedBox(
height: 15,
),
),
Visibility(
visible: viewModel.jenisBool,
child: Align(
alignment: Alignment.centerLeft,
child: Text(
"Jumlah",
style: regularTextStyle.copyWith(color: mainColor),
return SingleChildScrollView(
child: SizedBox(
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Align(
alignment: Alignment.centerLeft,
child: Text(
"Nama Donator",
style: regularTextStyle.copyWith(color: mainColor),
),
),
),
),
Visibility(
visible: viewModel.jenisBool,
child: MyTextFormField(
controller: viewModel.jumlahController,
maxLines: 1,
readOnly: true,
),
),
Visibility(
visible: !viewModel.jenisBool,
child: const SizedBox(
height: 15,
),
),
Visibility(
visible: !viewModel.jenisBool,
child: Align(
alignment: Alignment.centerLeft,
child: Text(
"Keterangan",
style: regularTextStyle.copyWith(color: mainColor),
MyTextFormField(
controller: viewModel.namaController,
maxLines: 1,
readOnly: true,
),
),
),
Visibility(
visible: !viewModel.jenisBool,
child: MyTextFormField(
controller: viewModel.keteranganController,
maxLines: 2,
readOnly: true,
),
),
const SizedBox(
height: 15,
),
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Tanda Tangan",
const SizedBox(
height: 15,
),
Align(
alignment: Alignment.centerLeft,
child: Text(
"Tanggal",
style: regularTextStyle.copyWith(color: mainColor),
),
),
MyTextFormField(
controller: viewModel.tanggalController,
maxLines: 1,
readOnly: true,
),
const SizedBox(
height: 15,
),
Align(
alignment: Alignment.centerLeft,
child: Text(
"Jenis",
style: regularTextStyle.copyWith(color: mainColor),
),
),
MyTextFormField(
controller: viewModel.jenisController,
maxLines: 1,
readOnly: true,
),
Visibility(
visible: viewModel.jenisBool,
child: const SizedBox(
height: 15,
),
),
Visibility(
visible: viewModel.jenisBool,
child: Align(
alignment: Alignment.centerLeft,
child: Text(
"Jumlah",
style: regularTextStyle.copyWith(color: mainColor),
),
SizedBox(
height: 150,
width: 150,
child: viewModel.danaSosialModel == null
? Container(
decoration: BoxDecoration(
border: Border.all(color: mainColor),
),
)
: (viewModel.danaSosialModel!.status! ==
'Belum Dikonfirmasi'
? const TtdWidget()
: Image.asset(
'assets/qrcode.png',
fit: BoxFit.cover,
)),
),
const SizedBox(
height: 10,
),
Text(
"Dr. Andi Fitriani D, S.Ag, M.Pd",
style: regularTextStyle.copyWith(
color: mainColor,
fontWeight: FontWeight.bold,
),
),
// create a horizontal line
],
),
),
),
Visibility(
visible: viewModel.jenisBool,
child: MyTextFormField(
controller: viewModel.jumlahController,
maxLines: 1,
readOnly: true,
),
),
Visibility(
visible: !viewModel.jenisBool,
child: const SizedBox(
height: 15,
),
),
if (!viewModel.jenisBool)
Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Jenis Barang",
style: regularTextStyle.copyWith(color: mainColor),
),
MyTextFormField(
controller: viewModel.jenisBarangController,
maxLines: 1,
readOnly: true,
),
const SizedBox(
height: 15,
),
Text(
"Jumlah Barang",
style: regularTextStyle.copyWith(color: mainColor),
),
MyTextFormField(
controller: viewModel.jumlahBarangController,
maxLines: 1,
readOnly: true,
),
const SizedBox(
height: 15,
),
],
),
Visibility(
visible: !viewModel.jenisBool,
child: Align(
alignment: Alignment.centerLeft,
child: Text(
"Keterangan",
style: regularTextStyle.copyWith(color: mainColor),
),
),
),
Visibility(
visible: !viewModel.jenisBool,
child: MyTextFormField(
controller: viewModel.keteranganController,
maxLines: 2,
readOnly: true,
),
),
const SizedBox(
height: 15,
),
Expanded(
child: Align(
alignment: Alignment.centerRight,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Tanda Tangan",
style: regularTextStyle.copyWith(color: mainColor),
),
SizedBox(
height: 150,
width: 150,
child: viewModel.danaSosialModel == null
? Container(
decoration: BoxDecoration(
border: Border.all(color: mainColor),
),
)
: (viewModel.danaSosialModel!.status! ==
'Belum Dikonfirmasi'
? const TtdWidget()
: Image.asset(
'assets/qrcode.png',
fit: BoxFit.cover,
)),
),
const SizedBox(
height: 10,
),
Text(
"DRA. HJ. CIA",
style: regularTextStyle.copyWith(
color: mainColor,
fontWeight: FontWeight.bold,
),
),
// create a horizontal line
],
),
),
),
],
),
],
),
);
}
}
@ -361,7 +401,7 @@ class TtdWidget extends ViewModelWidget<DetailDanaSosialViewModel> {
decoration: BoxDecoration(
border: Border.all(color: mainColor),
),
child: viewModel.role == 'pimpinan'
child: viewModel.role == 'pimpinan' || viewModel.role == 'admin'
? InkWell(
onTap: () {
viewModel.handleTtd();

View File

@ -15,6 +15,8 @@ class DetailDanaSosialViewModel extends CustomBaseViewModel {
final _httpService = locator<MyHttpServices>();
final easyLoading = locator<MyEasyLoading>();
bool isKhusus = false;
int? idDanaSosial;
DanaSosialModel? danaSosialModel;
bool jenisBool = true;
@ -29,8 +31,14 @@ class DetailDanaSosialViewModel extends CustomBaseViewModel {
TextEditingController bentukController = TextEditingController();
Future<void> init(int id) async {
// my revision syntax
TextEditingController jenisBarangController = TextEditingController();
TextEditingController jumlahBarangController = TextEditingController();
// TextEditingController satuanController = TextEditingController();
Future<void> init(int id, bool isKhusus) async {
log.i('init and id: $id');
this.isKhusus = isKhusus;
getData(id);
idDanaSosial = id;
prefs.then((SharedPreferences prefs) {
@ -42,7 +50,10 @@ class DetailDanaSosialViewModel extends CustomBaseViewModel {
setBusy(true);
easyLoading.showLoading();
try {
var response = await _httpService.get('dana_sosial_detail?id=$id');
String url = isKhusus
? 'dana_sosial_khusus_detail?id=$id'
: 'dana_sosial_detail?id=$id';
var response = await _httpService.get(url);
log.i(response.data['data']);
danaSosialModel = DanaSosialModel.fromJson(response.data['data']);
namaController.text = danaSosialModel!.nama!;
@ -54,6 +65,12 @@ class DetailDanaSosialViewModel extends CustomBaseViewModel {
bentukController.text = danaSosialModel!.bentuk!;
// my revision syntax
jenisBarangController.text = danaSosialModel!.jenisBarang!;
jumlahBarangController.text =
'${danaSosialModel!.jumlahBarang!} ${danaSosialModel!.satuan!}';
// satuanController.text = danaSosialModel!.satuan! ;
if (danaSosialModel!.jenisDonasi == 'Uang') {
jenisBool = true;
} else {
@ -86,8 +103,9 @@ class DetailDanaSosialViewModel extends CustomBaseViewModel {
FormData formData = FormData.fromMap({
'id': idDanaSosial,
});
var response =
await _httpService.postWithFormData('dana_sosial_ttd', formData);
String url = isKhusus ? 'dana_sosial_khusus_ttd' : 'dana_sosial_ttd';
var response = await _httpService.postWithFormData(url, formData);
log.i(response.data);
getData(idDanaSosial!);

View File

@ -18,11 +18,12 @@ class PimpinanIndexTrackingViewModel extends IndexTrackingViewModel {
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,
@ -34,6 +35,7 @@ class PimpinanIndexTrackingViewModel extends IndexTrackingViewModel {
final List<String> _views = [
PimpinanIndexTrackingViewRoutes.dataSiswaView,
PimpinanIndexTrackingViewRoutes.danaSosialAdminView,
// PimpinanIndexTrackingViewRoutes.danaSosialKhususView,
PimpinanIndexTrackingViewRoutes.profilView,
];
Future<void> init() async {

View File

@ -9,14 +9,19 @@ import '../../widgets/my_textformfield.dart';
import './tambah_dana_sosial_view_model.dart';
class TambahDanaSosialView extends StatelessWidget {
const TambahDanaSosialView({super.key});
final bool isKhusus;
const TambahDanaSosialView({
Key? key,
this.isKhusus = false,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ViewModelBuilder<TambahDanaSosialViewModel>.reactive(
viewModelBuilder: () => TambahDanaSosialViewModel(),
onViewModelReady: (TambahDanaSosialViewModel model) async {
await model.init();
await model.init(isKhusus);
},
builder: (
BuildContext context,
@ -66,6 +71,7 @@ class TambahDanaSosialView extends StatelessWidget {
// model.setSelectedbentukDonasi(newValue!);
model.log.i(newValue);
model.bentukDonasi = newValue!;
model.notifyListeners();
},
items: model.bentukDonasiList.map((String value) {
@ -91,7 +97,8 @@ class TambahDanaSosialView extends StatelessWidget {
),
),
Visibility(
visible: model.bentukDonasi == 'Pemasukan',
visible: model.bentukDonasi == 'Pemasukan' &&
isKhusus == false,
child: MyTextFormField(
hintText: "Nama Donatur",
controller: model.namaController,
@ -100,6 +107,51 @@ class TambahDanaSosialView extends StatelessWidget {
// 'Nama Donatur tidak boleh kosong'),
),
),
Visibility(
visible: model.bentukDonasi == 'Pemasukan' &&
isKhusus == true,
child: Container(
width: double.infinity,
height: 60,
padding: const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
border: Border.all(
color: mainColor,
),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: model.donaturSelected,
onChanged: (String? newValue) {
// model.setSelectedjenisDonasi(newValue!);
model.log.i(newValue);
model.donaturSelected = newValue!;
// check where is the index and get the ['id_donatur']
var index = model.listDonatur.indexWhere(
(element) => element == newValue,
);
model.donaturSelectedIndex = int.parse(
model.listDonaturMap[index]['id_donatur'],
);
model.log.i(model.donaturSelectedIndex);
},
items: model.listDonatur.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: regularTextStyle.copyWith(
fontSize: 16,
),
),
);
}).toList(),
),
),
),
),
Visibility(
visible: model.bentukDonasi == 'Pemasukan',
child: const SizedBox(height: 20),
@ -141,6 +193,130 @@ class TambahDanaSosialView extends StatelessWidget {
),
),
),
// ini jika barang
if (model.jenisDonasi == 'Barang')
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 20),
Text(
"Jenis Barang",
style:
regularTextStyle.copyWith(color: mainColor),
),
Container(
width: double.infinity,
height: 60,
padding:
const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
border: Border.all(
color: mainColor,
),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: model.jenisBarangSelected,
onChanged: (String? newValue) {
// model.setSelectedjenisDonasi(newValue!);
model.log.i(newValue);
model.jenisBarangSelected = newValue!;
model.changeSatuan(newValue);
model.notifyListeners();
},
items:
model.jenisBarangList.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: regularTextStyle.copyWith(
fontSize: 16,
),
),
);
}).toList(),
),
),
),
],
),
// ini jika barang dan jenis barang beras dll
if (model.jenisDonasi == 'Barang' &&
(model.jenisBarangSelected == 'Beras' ||
model.jenisBarangSelected == 'Mi Instan' ||
model.jenisBarangSelected == 'Telur' ||
model.jenisBarangSelected == 'Gula'))
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 20),
Text(
"Pilih Satuan ${model.jenisBarangSelected}",
style:
regularTextStyle.copyWith(color: mainColor),
),
Container(
width: double.infinity,
height: 60,
padding:
const EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(25),
border: Border.all(
color: mainColor,
),
),
child: DropdownButtonHideUnderline(
child: DropdownButton<String>(
value: model.satuanSelected,
onChanged: (String? newValue) {
// model.setSelectedjenisDonasi(newValue!);
model.log.i(newValue);
model.satuanSelected = newValue!;
model.notifyListeners();
},
items: model.satuanList.map((String value) {
return DropdownMenuItem<String>(
value: value,
child: Text(
value,
style: regularTextStyle.copyWith(
fontSize: 16,
),
),
);
}).toList(),
),
),
),
],
),
// ini jika barang dan jenis barang dll
if (model.jenisDonasi == 'Barang')
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 20),
Text(
"Jumlah ${model.satuanSelected}",
style:
regularTextStyle.copyWith(color: mainColor),
),
MyTextFormField(
hintText: "Jumlah ${model.satuanSelected}",
controller: model.jumlahBarangController,
maxLines: 1,
keyboardType: TextInputType.number,
maxLength: 3,
// validator: Validatorless.required(
// 'Nama Donatur tidak boleh kosong'),
),
],
),
Visibility(
visible: model.jenisDonasi == 'Uang',
child: const SizedBox(height: 20),
@ -212,6 +388,15 @@ class TambahDanaSosialView extends StatelessWidget {
MyButton(
text: "Simpan Data",
onPressed: () {
if (isKhusus &&
model.donaturSelected == '-Tiada Donatur-') {
model.snackbarService.showSnackbar(
message: 'Donatur harus diisi terlebih dahulu',
title: 'Gagal',
duration: const Duration(seconds: 2),
);
return;
}
if (model.formKey.currentState!.validate()) {
model.log.i('Form Valid');
model.addData();

View File

@ -23,10 +23,77 @@ class TambahDanaSosialViewModel extends CustomBaseViewModel {
TextEditingController namaController = TextEditingController();
TextEditingController jumlahController = TextEditingController();
TextEditingController jumlahBarangController = TextEditingController();
TextEditingController tanggalController = TextEditingController();
TextEditingController keteranganController = TextEditingController();
Future<void> init() async {}
// my revision syntax
List<String> jenisBarangList = [
'Beras',
'Minyak',
'Mi Instan',
'Telur',
'Gula',
'Susu',
'Pakaian'
];
String jenisBarangSelected = 'Beras';
String satuanSelected = 'Kg';
// TextEditingController jumlahBarangController = TextEditingController();
bool isJenisBarangSelected = true;
List<String> satuanLiterKg = ['Liter', 'Kg'];
List<String> satuanBungkusDos = ['Bungkus', 'Dos'];
List<String> satuanButirRak = ['Butir', 'Rak'];
List<String> satuanList = ['Liter', 'Kg'];
// end of my revision syntax
// the new revision syntax
bool isKhusus = false;
List<String> listDonatur = ['-Tiada Donatur-'];
List<Map<String, dynamic>> listDonaturMap = [];
String donaturSelected = '-Tiada Donatur-';
int donaturSelectedIndex = 0;
// end of the new revision syntax
Future<void> init(bool isKhusus) async {
this.isKhusus = isKhusus;
if (isKhusus) {
bentukDonasiList = ['Pemasukan'];
getDonatur();
}
}
getDonatur() async {
setBusy(true);
easyLoading.customLoading('Mengambil data...');
try {
var response = await _httpService.get('donatur');
Map<String, dynamic> data = response.data;
// log.i(data);
int jumlah = data['jumlah'];
if (jumlah > 0) {
listDonatur.clear();
for (var i = 0; i < data['data'].length; i++) {
listDonatur.add(data['data'][i]['nama_donatur']);
listDonaturMap.add(data['data'][i]);
}
// get the [id_donatur] of the first [donatur
donaturSelected = listDonatur[0];
donaturSelectedIndex = int.parse(listDonaturMap[0]['id_donatur']);
log.i(donaturSelectedIndex);
}
} catch (e) {
log.e(e);
} finally {
setBusy(false);
easyLoading.dismissLoading();
}
}
void changeDate(BuildContext context) async {
// get today's date
@ -46,6 +113,7 @@ class TambahDanaSosialViewModel extends CustomBaseViewModel {
void addData() async {
easyLoading.customLoading('Menambahkan data...');
log.i(donaturSelectedIndex);
try {
var formData = FormData.fromMap({
'bentuk': bentukDonasi,
@ -54,9 +122,17 @@ class TambahDanaSosialViewModel extends CustomBaseViewModel {
'tanggal': tanggalController.text,
'ket': keteranganController.text,
'jenis': jenisDonasi,
'jenis_barang': jenisDonasi == 'Barang' ? jenisBarangSelected : null,
'satuan': jenisDonasi == 'Barang' ? satuanSelected : null,
'jumlah_barang':
jenisDonasi == 'Barang' ? jumlahBarangController.text : null,
'donatur': isKhusus ? donaturSelectedIndex : null,
});
var response =
await _httpService.postWithFormData('dana_sosial', formData);
// await _httpService.postWithFormData('dana_sosial', formData);
await _httpService.postWithFormData(
!isKhusus ? 'dana_sosial' : 'dana_sosial_khusus', formData);
log.i(response.data);
easyLoading.showSuccess(" Data berhasil ditambahkan");
navigationService.navigateTo(Routes.adminIndexTrackingView);
@ -71,4 +147,49 @@ class TambahDanaSosialViewModel extends CustomBaseViewModel {
easyLoading.dismissLoading();
}
}
// my revision syntax
changeSatuan(String value) {
jenisBarangSelected = value;
switch (value) {
case 'Beras':
isJenisBarangSelected = true;
satuanSelected = 'Kg';
satuanList = satuanLiterKg;
break;
case 'Minyak':
isJenisBarangSelected = false;
satuanSelected = 'Liter';
break;
case 'Mi Instan':
isJenisBarangSelected = true;
satuanSelected = 'Bungkus';
satuanList = satuanBungkusDos;
break;
case 'Telur':
isJenisBarangSelected = true;
satuanSelected = 'Butir';
satuanList = satuanButirRak;
break;
case 'Gula':
isJenisBarangSelected = true;
satuanSelected = 'Kg';
satuanList = satuanLiterKg;
break;
case 'Susu':
isJenisBarangSelected = false;
satuanSelected = 'Liter';
break;
case 'Pakaian':
isJenisBarangSelected = false;
satuanSelected = 'Helai';
// satuanList = satuanButirRak;
break;
default:
satuanSelected = '';
}
// notifyListeners();
}
}

View File

@ -15,11 +15,12 @@ class UserIndexTrackingViewModel extends IndexTrackingViewModel {
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 +40,7 @@ class UserIndexTrackingViewModel extends IndexTrackingViewModel {
final List<String> _views = [
UserIndexTrackingViewRoutes.dataSiswaView,
UserIndexTrackingViewRoutes.danaSosialAdminView,
// UserIndexTrackingViewRoutes.danaSosialKhususView,
UserIndexTrackingViewRoutes.profilView,
UserIndexTrackingViewRoutes.visiMisiView,
UserIndexTrackingViewRoutes.sejarahView,

View File

@ -20,6 +20,7 @@ class MyTextFormField extends StatelessWidget {
this.keyboardType = TextInputType.text,
this.initialValue,
this.enabled = true,
this.maxLength,
}) : super(key: key);
final String? labelText;
@ -37,10 +38,12 @@ class MyTextFormField extends StatelessWidget {
final TextInputType keyboardType;
final String? initialValue;
final bool enabled;
final int? maxLength;
@override
Widget build(BuildContext context) {
return TextFormField(
maxLength: maxLength,
enabled: enabled,
initialValue: initialValue,
onEditingComplete: onEditingComplete,