From 9416c010d7569fca1afce84c651c469983f76c65 Mon Sep 17 00:00:00 2001 From: sindhu Date: Tue, 16 Jan 2024 18:02:38 +0700 Subject: [PATCH] step 18 : history widget atas cmp --- app_petty_cash/images/icon_12.png | Bin 0 -> 1039 bytes app_petty_cash/images/icon_12.svg | 30 + app_petty_cash/images/icon_13.svg | 5 + app_petty_cash/images/icon_3.svg | 5 + app_petty_cash/images/icon_4.png | Bin 0 -> 775 bytes app_petty_cash/images/icon_5.png | Bin 0 -> 716 bytes app_petty_cash/images/icon_5.svg | 4 + app_petty_cash/images/icon_6.png | Bin 0 -> 599 bytes app_petty_cash/images/icon_6.svg | 3 + app_petty_cash/images/icon_delete.png | Bin 0 -> 407 bytes app_petty_cash/lib/app/constant.dart | 3 +- .../lib/model/history_transaksi_model.dart | 64 ++ .../lib/repository/transaksi_repository.dart | 28 + .../transaksi/history_transaksi_screen.dart | 765 ++++++++++++++++-- .../search_history_transaksi_provider.dart | 76 ++ app_petty_cash/lib/widget/custom_drawer.dart | 76 +- .../lib/widget/history_row_atas_widget.dart | 110 +++ app_petty_cash/pubspec.lock | 64 ++ app_petty_cash/pubspec.yaml | 1 + 19 files changed, 1108 insertions(+), 126 deletions(-) create mode 100644 app_petty_cash/images/icon_12.png create mode 100644 app_petty_cash/images/icon_12.svg create mode 100644 app_petty_cash/images/icon_13.svg create mode 100644 app_petty_cash/images/icon_3.svg create mode 100644 app_petty_cash/images/icon_4.png create mode 100644 app_petty_cash/images/icon_5.png create mode 100644 app_petty_cash/images/icon_5.svg create mode 100644 app_petty_cash/images/icon_6.png create mode 100644 app_petty_cash/images/icon_6.svg create mode 100644 app_petty_cash/images/icon_delete.png create mode 100644 app_petty_cash/lib/model/history_transaksi_model.dart create mode 100644 app_petty_cash/lib/screen/transaksi/search_history_transaksi_provider.dart create mode 100644 app_petty_cash/lib/widget/history_row_atas_widget.dart diff --git a/app_petty_cash/images/icon_12.png b/app_petty_cash/images/icon_12.png new file mode 100644 index 0000000000000000000000000000000000000000..5395e37c01896925f25e7bd088fbedb10fa7f86d GIT binary patch literal 1039 zcmV+q1n~QbP)YM0bsSIqr3b*JQ6I zn|E!up*LukJ3<%K73&lza^eAqtsZwIQHPA zcvOR_4nzsb7e`X|qVgWeQ|CR`Hg$A**|P5iG#`a%t$llip;`sn=6w2!7=v_PIUyvu zHzd<<$P3$;kT4CM7^GOubHA<_xifw9u5q}FB0YU%#Nyn!HaO#d*@^(t@2#Rd7?gyO zo?eP`7^7Or;aucc`S&+6kDsJS>e%j@*I16tm~7=CjffavWzgXwy#qozEHJ`tb7*2i z=jBTGC7`1$O=MNV;k@rvsG@vmG+^?Zz%yCexXw6 zOurUlEqOI_0{MWJt}Y_4P?coV>)sy){2=!McTzRz7zh1&{vUEJCU&~CY&QS^002ov JPDHLkV1j12)V2Ts literal 0 HcmV?d00001 diff --git a/app_petty_cash/images/icon_12.svg b/app_petty_cash/images/icon_12.svg new file mode 100644 index 0000000..1ed2c00 --- /dev/null +++ b/app_petty_cash/images/icon_12.svg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app_petty_cash/images/icon_13.svg b/app_petty_cash/images/icon_13.svg new file mode 100644 index 0000000..b540a9b --- /dev/null +++ b/app_petty_cash/images/icon_13.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app_petty_cash/images/icon_3.svg b/app_petty_cash/images/icon_3.svg new file mode 100644 index 0000000..4695dfd --- /dev/null +++ b/app_petty_cash/images/icon_3.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/app_petty_cash/images/icon_4.png b/app_petty_cash/images/icon_4.png new file mode 100644 index 0000000000000000000000000000000000000000..7859bb90f711c39d3144c35174673e2dfbcb7970 GIT binary patch literal 775 zcmV+i1Ni)jP){`IQUK$WW zHH|G243GNb(^R%;jAZ6Y;Q$D1_C8E-S>-=dYdTF6iAVv{da0H}JaetcB$C-v_qaE? zfH<-BVpk!aOB4XncE{`C(bvgMn0-F%;k;4)LO>S(+y?}i;Vzdq9xe7+J?h;D#4G=U zX`?8_7R#RTZBqkXXo4F^i5%eZnzbuq#fSJ3pYu=UGrxT>0upLo7){hR`r~Uy)Q9&Y zc#}V8N7h55WI+tPU}+6)eg|x4e7%GU;fns~8sFY++N(%UNHec#eE&7#*|fQ7Ln3g- z5xexr{l5IjLrNIENsBKn*fA75GhPL}3P}AGY+~9dS8_yGUU5Re?n>+S)~A;enIjRE5h|Y6CV-3!iafg8HTW24kh(&*{)UvQfNUO9ACUq z)%r55S_V!=GAoe6^7uFk5QacbP`vAnu7bpMB~1KF!C!>yX|)s#=e_^{002ovPDHLk FV1h|#QMv#C literal 0 HcmV?d00001 diff --git a/app_petty_cash/images/icon_5.png b/app_petty_cash/images/icon_5.png new file mode 100644 index 0000000000000000000000000000000000000000..ef0e0852310bfaa8e8dd3b8451802256194b00aa GIT binary patch literal 716 zcmV;-0yF)IP){3 z(?AgI9@`626qarvHh{BIZjjtS*Pi|Yg zG67Ml9zJ-9zri7d?VM>IA`KtCKYIst5(v6a9Hp8^KxD+9nGleVKpp`aKw#h^DW8eF z$s)2efgdkAheR-tF%h{uKFBk7@ch}HQmW50?NAviw#K*pl?enr{vhCy>{t^Wn4{BS zsde3_1BH#(OvKOx`{{KGmV#mv!&n3ClvOS;N8g9ChOOnY8Qk={%26QB*xcCYYaoXo z?O5#b&W?X+Ix#<<`9w{Sh**P^v|i;{&0#i z7Uj`9EPYfM&H^OTBQR`nQahV%&-Z7$j9 zmdHa3h}lB|#O$Witun3DDhT#$LtS5=hh;gkf*UzueCAxMzphKUz&!T2kI*M+oeNQ* z6a{d{C=5d`H0Sb5%cQ$uSrA6cx(S4!EMe$6KGcB1TEMma@!v9OuV9|@E91^HVFR!Y zHwfs&oaltNoHaqd&6gNEt#g(MFM69_;{M%70*|}b+QX5RJK<%9^G$mc9q-HswAQ;x yHspy`j`vk$5dM37r`SzIwHBjWkx`899e)7q2mIp^W82990000 + + + diff --git a/app_petty_cash/images/icon_6.png b/app_petty_cash/images/icon_6.png new file mode 100644 index 0000000000000000000000000000000000000000..85ba30e4abf5352a0056384ddbaaea91da004f7c GIT binary patch literal 599 zcmV-d0;v6oP)5xXbDu{&fTjA+aQn!+!%ovxEPed6CiqW-gGkQIrs0+(KZWA#B^!{vE1;LAsmBB zeU>%m*LJkYTnQSLI-j~7ZQ}~x=MYyjR_d~B!v``ou@M3~g4Ff_zwX+8yL~Mh`uV`h0&Apt`nVUst28F^%-4pw~N0Bn<2I0bxE$Vq>J#|+M19x;EIcCFwqt%hid{{MZgo6G*L+;jQD7b0A;inG-Ba8 zO;qwqgkE8UfOGrSrNBD;(Iz|AU?pWUSSylNOrg)$c9cd!_spk7U@^GZ*B2x{&&ub) z_vTSG&#@~jFbN)+8G#l7yiD{mXvdfa9x + + diff --git a/app_petty_cash/images/icon_delete.png b/app_petty_cash/images/icon_delete.png new file mode 100644 index 0000000000000000000000000000000000000000..e11e1cc014c7917379ae6e92194b1953208e0c41 GIT binary patch literal 407 zcmV;I0cie-P)FK4iL9Q2-p%R!F1r9;6VJD>?SxH$6Di@ zKzRpiJv)E?>{=QFe;uil#3X5>Wv+DD@hZ;o!I4;-#k9w$gD*ZR9JQ~OWI?Qg(g}E( zbg=GpNq*FZ;cXCeiO3-NU`w9L)TWgNyg2V`u?Or$ex@dN{bqtavxwel6yhW(x%uLp za~Ys1G<})b$4Ubq***nReGEaq6(LPRBd7_JP zOddB7_!Bk!K5>IRIT#!a9NkrF_a{Qrb0eJS#l*X&X`;nm(TH%+xwc9<3p5{iJG3PO zd9pflXz^>9dTmI>AC1H1J?qRlMLpi}$vgZ@z5&QeVXvC9Fv json) { + id = json['id']; + tanggaltransaksi = json['tanggaltransaksi']; + tipe = json['tipe']; + kategoriid = json['kategoriid']; + kategoriname = json['kategoriname']; + note = json['note']; + amount = json['amount']; + sender = json['sender']; + imgurl = json['imgurl']; + isconfirm = json['isconfirm']; + tanggalconfirm = json['tanggalconfirm']; + usertransaksi = json['usertransaksi']; + userconfirm = json['userconfirm']; + } + + Map toJson() { + final Map data = new Map(); + data['id'] = this.id; + data['tanggaltransaksi'] = this.tanggaltransaksi; + data['tipe'] = this.tipe; + data['kategoriid'] = this.kategoriid; + data['kategoriname'] = this.kategoriname; + data['note'] = this.note; + data['amount'] = this.amount; + data['sender'] = this.sender; + data['imgurl'] = this.imgurl; + data['isconfirm'] = this.isconfirm; + data['tanggalconfirm'] = this.tanggalconfirm; + data['usertransaksi'] = this.usertransaksi; + data['userconfirm'] = this.userconfirm; + return data; + } +} \ No newline at end of file diff --git a/app_petty_cash/lib/repository/transaksi_repository.dart b/app_petty_cash/lib/repository/transaksi_repository.dart index 9c8fdc4..77e0674 100644 --- a/app_petty_cash/lib/repository/transaksi_repository.dart +++ b/app_petty_cash/lib/repository/transaksi_repository.dart @@ -1,6 +1,7 @@ import 'package:app_petty_cash/model/list_type_model.dart'; import '../app/constant.dart'; +import '../model/history_transaksi_model.dart'; import '../model/list_category_model.dart'; import 'base_repository.dart'; @@ -93,4 +94,31 @@ class TransaksiRepository extends BaseRepository { return resp['status']; } + + // list history transaksi + Future> getListHistoryTransaksi( + String companyid, + String tglAwal, + String tglAkhir, + String categoryid, + ) async { + final service = + "${Constant.baseUrlDevone}/homescreen/list_transaction/?companyid=$companyid&startdate=$tglAwal&enddate=$tglAkhir&kategoriid=$categoryid"; + // https://devone.aplikasi.web.id/one-api-pettycash/pettycash/history/list_transaction/?companyid=1&startdate=2023-12-01&enddate=2023-12-30&kategoriid=0 + final resp = await get( + // param: { + // "": "", + // }, + service: service, + ); + + print("url list history transaksi : $service"); + + final result = List.empty(growable: true); + resp['data'].forEach((e) { + final model = HistoryTransaksiModel.fromJson(e); + result.add(model); + }); + return result; + } } diff --git a/app_petty_cash/lib/screen/transaksi/history_transaksi_screen.dart b/app_petty_cash/lib/screen/transaksi/history_transaksi_screen.dart index 8400a6c..dcb0a82 100644 --- a/app_petty_cash/lib/screen/transaksi/history_transaksi_screen.dart +++ b/app_petty_cash/lib/screen/transaksi/history_transaksi_screen.dart @@ -1,18 +1,162 @@ +import 'dart:convert'; + +import 'package:app_petty_cash/screen/transaksi/search_history_transaksi_provider.dart'; +import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:intl/intl.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import '../../app/constant.dart'; import '../../app/route.dart'; +import '../../model/history_transaksi_model.dart'; +import '../../model/list_category_model.dart'; +import '../../model/list_type_model.dart'; import '../../provider/current_user_provider.dart'; import '../../widget/custom_drawer.dart'; import '../../widget/field_row_history_transaksi.dart'; +import '../../widget/history_row_atas_widget.dart'; +import '../../widget/sankbar_widget.dart'; +import 'list_category_provider.dart'; +import 'list_type_provider.dart'; class HistoryTransaksiScreen extends HookConsumerWidget { const HistoryTransaksiScreen({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { + final listTypeData = useState>(List.empty(growable: true)); + final selectedListTypeData = useState(ListType()); + + final listTypeLoading = useState(false); + + // category + final listCategoryLoading = useState(false); + final selectedListCategory = useState(ListCategory()); + final listCategoryData = useState>( + List.empty( + growable: true, + ), + ); + + String M_CompanyID = "0"; + String formattedDate = DateFormat('dd-MM-yyyy').format(DateTime.now()); + final ctrlTglAwal = useTextEditingController(text: formattedDate); + + final tglAwal = useState(DateTime.now()); + final tglAwalTmp = useState(""); + + final ctrlTglAkhir = useTextEditingController(text: formattedDate); + + final tglAkhir = useState(DateTime.now()); + final tglAkhirTmp = useState(""); + final categoryIsLoading = useState(false); + final searchHistoryIsLoading = useState(false); + final listSearchHistory = useState>( + List.empty( + growable: true, + ), + ); + + // A. LISTEN PROVIDER + + // type + ref.listen( + listTypeProvider, + (previous, next) { + if (next is ListTypeStateLoading) { + listTypeLoading.value = true; + } else if (next is ListTypeStateError) { + // print(next.message); + listTypeLoading.value = false; + SanckbarWidget(context, next.message, snackbarType.error); + } else if (next is ListTypeStateDone) { + // print(jsonEncode(next.model)); + // print(next.model.length); + listTypeData.value = next.model; + listTypeLoading.value = false; + + var idx = 0; + for (var i = 0; i < listTypeData.value.length; i++) { + if (listTypeData.value[i].typeid == "KREDIT") { + selectedListTypeData.value = listTypeData.value[i]; + idx = i; + } + } + selectedListTypeData.value = listTypeData.value[idx]; + } + }, + ); + + // category + ref.listen( + listCategoryProvider, + (previous, next) { + if (next is ListCategoryStateLoading) { + listCategoryLoading.value = true; + } else if (next is ListCategoryStateError) { + // print(next.message); + listCategoryLoading.value = false; + SanckbarWidget(context, next.message, snackbarType.error); + } else if (next is ListCategoryStateDone) { + // print(jsonEncode(next.model)); + // print(next.model.length); + // listCategoryData.value = next.model; + final xList = List.empty(growable: true); + xList.add( + ListCategory( + categoryid: "0", + categoryname: "ALL", + ), + ); + xList.addAll(next.model); + listCategoryData.value = xList; + listCategoryLoading.value = false; + selectedListCategory.value = listCategoryData.value[0]; + } + }, + ); + + // search + ref.listen( + searchHistoryTransaksiProvider, + (previous, next) { + if (next is SearchHistoryTransaksiStateLoading) { + searchHistoryIsLoading.value = true; + } else if (next is SearchHistoryTransaksiStateError) { + // print(next.message); + searchHistoryIsLoading.value = false; + SanckbarWidget(context, next.message, snackbarType.error); + } else if (next is SearchHistoryTransaksiStateDone) { + // print(jsonEncode(next.model)); + // print(next.model.length); + listSearchHistory.value = next.model; + searchHistoryIsLoading.value = false; + } + }, + ); + + Future getCompanyID() async { + final shared = await SharedPreferences.getInstance(); + String M_CompanyID = "0"; + + if (shared != null) { + final bearerString = shared.get(Constant.bearerName).toString(); + final xmodel = jsonDecode(bearerString); + if (xmodel != null) { + M_CompanyID = xmodel["model"]["M_CompanyID"]; + } + } + + if (M_CompanyID == "0") { + // throw BaseRepositoryException(message: 'Invalid Company ID'); + } + + return M_CompanyID; + } + useEffect(() { WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { final userID = ref.read(currentUserProvider)?.model.M_UserID ?? "0"; @@ -28,6 +172,38 @@ class HistoryTransaksiScreen extends HookConsumerWidget { return () {}; }, []); + useEffect(() { + WidgetsBinding.instance.addPostFrameCallback((timeStamp) async { + // list Type Provider + ref.read(listTypeProvider.notifier).getListType(); + + // list category provider + ref.read(listCategoryProvider.notifier).getListCategory(); + + M_CompanyID = await getCompanyID(); + + DateTime parsedDate = DateFormat('dd-MM-yyyy').parse( + ctrlTglAwal.value.text.toString(), + ); + String formattedDateAwal = DateFormat('yyyy-MM-dd').format(parsedDate); + + DateTime parsedDateAkhir = DateFormat('dd-MM-yyyy').parse( + ctrlTglAkhir.value.text.toString(), + ); + String formattedDateAkhir = + DateFormat('yyyy-MM-dd').format(parsedDateAkhir); + + final categoryid = selectedListCategory.value.categoryid ?? "0"; + + // search + ref + .read(searchHistoryTransaksiProvider.notifier) + .searchHistoryTransaksi( + M_CompanyID, formattedDateAwal, formattedDateAkhir, categoryid); + }); + return () {}; + }, []); + return Padding( padding: EdgeInsets.only( top: Constant.getActualYPhone(context: context, y: 30), @@ -45,100 +221,517 @@ class HistoryTransaksiScreen extends HookConsumerWidget { ), drawer: CustomDrawer(), body: SafeArea( - child: SingleChildScrollView( - child: Padding( - padding: EdgeInsets.only( - top: Constant.getActualYPhone(context: context, y: 10), - left: Constant.getActualXPhone(context: context, x: 8), - right: Constant.getActualXPhone(context: context, x: 8), - ), - child: Container( - height: MediaQuery.of(context).size.height - 10, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Card looping transaksi - Card( - margin: EdgeInsets.all(16.0), - child: Padding( - padding: EdgeInsets.all(16.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - FieldRowHistoryTransaksi( - label: "Tipe", - value: "DEBIT", + child: Padding( + padding: EdgeInsets.only( + top: Constant.getActualYPhone(context: context, y: 15), + left: Constant.getActualXPhone(context: context, x: 10), + right: Constant.getActualXPhone(context: context, x: 10), + bottom: Constant.getActualYPhone(context: context, y: 10), + ), + child: Container( + // height: MediaQuery.of(context).size.height - 10, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // filter + Row( + children: [ + // Tanggal Awal + Expanded( + child: TextField( + controller: ctrlTglAwal, + decoration: InputDecoration( + hintStyle: + Constant.body2_400(context: context).copyWith( + color: Constant.textGreyv2, ), - SizedBox(height: 8.0), - FieldRowHistoryTransaksi( - label: "Tanggal", - value: "15-12-2023", + labelStyle: + Constant.body2_400(context: context).copyWith( + color: Constant.textGreyv2, ), - SizedBox(height: 8.0), - FieldRowHistoryTransaksi( - label: "Nominal", - value: "100.000", - ), - SizedBox(height: 8.0), - FieldRowHistoryTransaksi( - label: "Kategori", - value: "Jumat Sehat", - ), - SizedBox(height: 8.0), - Chip( - label: Text( - 'Verify', - style: TextStyle(color: Constant.green_600), + border: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.orange, + width: 1, ), - shape: RoundedRectangleBorder( - side: BorderSide( - color: Constant.green_600, - ), - borderRadius: BorderRadius.circular(4.0), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Constant.textGreyv2, + width: 1, ), - backgroundColor: Colors.white, ), - SizedBox( - height: Constant.getActualYPhone( - context: context, y: 6), - ), - Chip( - label: Text( - 'Not Verify', - style: TextStyle(color: Constant.textGreyv2), - ), - shape: RoundedRectangleBorder( - side: BorderSide( - color: Constant.textGreyv2, - ), - borderRadius: BorderRadius.circular(4.0), - ), - backgroundColor: Colors.white, - ), - Row( - mainAxisAlignment: MainAxisAlignment.end, - children: [ - ElevatedButton( - onPressed: () { - // Handle delete button tap - }, - child: Text( - 'Delete', - style: TextStyle(color: Constant.textWhite), - ), - style: ElevatedButton.styleFrom( - backgroundColor: Colors - .red, // Ganti dengan warna delete button yang diinginkan - ), - ), - ], - ), - ], + labelText: "Tanggal Awal", + hintText: 'Tanggal Awal', + // suffixIcon: isLoadingFilterScope.value + // ? SizedBox( + // width: Constant.getActualXPhone( + // context: context, + // x: 4, + // ), + // height: Constant.getActualYPhone( + // context: context, + // y: 4, + // ), + // child: CircularProgressIndicator( + // color: Constant.textRed, + // ), + // ) + // : Icon( + // Icons.calendar_month_sharp, + // color: Constant.colorIconDate, + // ), + ), + onTap: () async { + final selectedDateAwal = await showDatePicker( + // locale: const Locale("en-CA"), + // locale: , + context: context, + initialEntryMode: + DatePickerEntryMode.calendarOnly, + firstDate: DateTime(2000), + lastDate: DateTime(2100), + + initialDate: (ctrlTglAwal.text.isEmpty) + ? DateTime.now() + : tglAwal.value, + ); + + if (selectedDateAwal != null) { + String formattedDate = DateFormat('dd-MM-yyyy') + .format(selectedDateAwal); + // ctrlTglAwal.text = + // selectedDateAwal.toString().split(' ')[0]; + ctrlTglAwal.text = formattedDate; + tglAwal.value = selectedDateAwal; + tglAwalTmp.value = selectedDateAwal.toString(); + } + + if (selectedDateAwal == null) { + print('cancel button'); + return; + } + }, ), ), + + SizedBox( + width: + Constant.getActualXPhone(context: context, x: 10), + ), + // Tanggal Akhir + Expanded( + child: TextField( + controller: ctrlTglAkhir, + decoration: InputDecoration( + hintStyle: + Constant.body2_400(context: context).copyWith( + color: Constant.textGreyv2, + ), + labelStyle: + Constant.body2_400(context: context).copyWith( + color: Constant.textGreyv2, + ), + border: OutlineInputBorder( + borderSide: BorderSide( + color: Colors.orange, + width: 1, + ), + ), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide( + color: Constant.textGreyv2, + width: 1, + ), + ), + labelText: "Tanggal Akhir", + hintText: 'Tanggal Akhir', + // suffixIcon: isLoadingFilterScope.value + // ? SizedBox( + // width: Constant.getActualXPhone( + // context: context, + // x: 4, + // ), + // height: Constant.getActualYPhone( + // context: context, + // y: 4, + // ), + // child: CircularProgressIndicator( + // color: Constant.textRed, + // ), + // ) + // : Icon( + // Icons.calendar_month_sharp, + // color: Constant.colorIconDate, + // ), + ), + onTap: () async { + final selectedDateAkhir = await showDatePicker( + // locale: const Locale("en-CA"), + // locale: , + context: context, + initialEntryMode: + DatePickerEntryMode.calendarOnly, + firstDate: DateTime(2000), + lastDate: DateTime(2100), + + initialDate: (ctrlTglAkhir.text.isEmpty) + ? DateTime.now() + : tglAkhir.value, + ); + + if (selectedDateAkhir != null) { + String formattedDate = DateFormat('dd-MM-yyyy') + .format(selectedDateAkhir); + // ctrlTglAkhir.text = + // selectedDateAkhir.toString().split(' ')[0]; + ctrlTglAkhir.text = formattedDate; + tglAkhir.value = selectedDateAkhir; + tglAkhirTmp.value = selectedDateAkhir.toString(); + } + + if (selectedDateAkhir == null) { + print('cancel button'); + return; + } + }, + ), + ), + ], + ), + SizedBox( + height: Constant.getActualYPhone(context: context, y: 20), + ), + Text( + 'Kategori', + style: Constant.body1(context: context).copyWith( + fontWeight: FontWeight.w600, + color: Constant.textBlack, ), - ], - ), + ), + SizedBox( + height: Constant.getActualYPhone(context: context, y: 10), + ), + // Dropdown kategori + (listCategoryLoading.value) + ? SizedBox( + width: + Constant.getActualXPhone(context: context, x: 24), + height: + Constant.getActualYPhone(context: context, y: 32), + child: Center( + child: CircularProgressIndicator(), + ), + ) + : SizedBox( + width: Constant.getActualXPhone( + context: context, x: 390), + child: DropdownButtonHideUnderline( + child: DropdownButton2( + isExpanded: true, + hint: Row( + children: [ + Expanded( + child: Text( + 'Select Item', + style: Constant.body1(context: context) + .copyWith( + fontWeight: FontWeight.w600, + color: Constant.textBlack), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + items: listCategoryData.value + .map((ListCategory option) { + return DropdownMenuItem( + value: option, + child: Text( + option.categoryname ?? "", + style: Constant.body1(context: context) + .copyWith( + color: Constant.textBlack, + fontWeight: FontWeight.w600), + ), + ); + }).toList(), + value: selectedListCategory.value, + onChanged: (ListCategory? newValue) { + // if (newValue) { + selectedListCategory.value = newValue!; + print(selectedListCategory.value.categoryid); + // } + }, + buttonStyleData: ButtonStyleData( + height: Constant.getActualY( + context: context, y: 56), + width: Constant.getActualX( + context: context, x: 320), + padding: EdgeInsets.only( + left: Constant.getActualX( + context: context, x: 10), + right: Constant.getActualX( + context: context, x: 10), + ), + decoration: BoxDecoration( + color: Constant.white, + border: Border.all( + color: Constant.textBlack, width: 1), + borderRadius: BorderRadius.circular(8), + ), + elevation: 2, + ), + iconStyleData: IconStyleData( + icon: Icon( + Icons.keyboard_arrow_down_outlined, + ), + iconSize: 24, + iconEnabledColor: Constant.textBlack, + iconDisabledColor: Colors.grey, + ), + dropdownStyleData: DropdownStyleData( + maxHeight: Constant.getActualY( + context: context, y: 200), + // width: Constant.getActualX(context: context, x: 320), + padding: EdgeInsets.only( + top: Constant.getActualY( + context: context, y: 10), + left: Constant.getActualX( + context: context, x: 10), + right: Constant.getActualX( + context: context, x: 10), + bottom: Constant.getActualY( + context: context, y: 10), + ), + decoration: BoxDecoration( + color: Constant.white, + borderRadius: BorderRadius.circular(8), + boxShadow: [ + BoxShadow( + color: Colors.grey, + blurRadius: 20.0, + spreadRadius: 2.0, + offset: Offset(0.0, 0.0), + ), + ], + ), + elevation: 8, + offset: const Offset(0, -10), + scrollbarTheme: ScrollbarThemeData( + radius: const Radius.circular(40), + thickness: + MaterialStateProperty.all(6), + thumbVisibility: + MaterialStateProperty.all(true), + ), + ), + menuItemStyleData: MenuItemStyleData( + height: Constant.getActualY( + context: context, y: 56), + padding: EdgeInsets.only( + top: Constant.getActualY( + context: context, y: 10), + left: Constant.getActualX( + context: context, x: 10), + right: Constant.getActualX( + context: context, x: 10), + ), + ), + ), + ), + ), + + SizedBox( + height: Constant.getActualYPhone(context: context, y: 10), + ), + Container( + width: Constant.getActualXPhone(context: context, x: 390), + child: Align( + alignment: Alignment.centerRight, + child: ElevatedButton( + style: ButtonStyle( + backgroundColor: MaterialStateColor.resolveWith( + (st) => Constant.pcBtnBackgroundColor), + shape: + MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + side: BorderSide( + color: Constant.pcBtnBackgroundColor, + ), + ), + ), + shadowColor: + MaterialStateProperty.all(Color(0xffff48423d)), + elevation: MaterialStateProperty.all(4.0), + ), + child: Stack( + children: [ + (categoryIsLoading.value) + ? SizedBox( + width: Constant.getActualXPhone( + context: context, x: 24), + height: Constant.getActualYPhone( + context: context, y: 32), + child: CircularProgressIndicator( + color: Colors.white, + ), + ) + : Text( + 'Search', + style: Constant.body1(context: context) + .copyWith( + fontWeight: FontWeight.w600, + color: Constant.white), + ), + ], + ), + onPressed: () async { + M_CompanyID = await getCompanyID(); + ref + .read(searchHistoryTransaksiProvider.notifier) + .searchHistoryTransaksi( + M_CompanyID, + ctrlTglAwal.text, + ctrlTglAkhir.text, + selectedListCategory.value.categoryid ?? "0", + ); + }, + ), + ), + ), + + SizedBox( + height: Constant.getActualYPhone(context: context, y: 20), + ), + + // Card looping transaksi + + // (searchHistoryIsLoading.value) + // ? Center( + // child: CircularProgressIndicator(), + // ) + // : Expanded( + // child: ListView.builder( + // itemCount: listSearchHistory.value.length, + // itemBuilder: (context, idx) { + // return Card( + // child: Padding( + // padding: EdgeInsets.all(16.0), + // child: Column( + // crossAxisAlignment: + // CrossAxisAlignment.start, + // children: [ + // FieldRowHistoryTransaksi( + // label: "Tipe", + // value: listSearchHistory + // .value[idx].tipe + // .toString(), + // ), + // SizedBox(height: 8.0), + // FieldRowHistoryTransaksi( + // label: "Tanggal", + // value: listSearchHistory + // .value[idx].tanggaltransaksi + // .toString(), + // ), + // SizedBox(height: 8.0), + // FieldRowHistoryTransaksi( + // label: "Nominal", + // value: listSearchHistory + // .value[idx].amount + // .toString(), + // // value: "nunggu api", + // ), + // SizedBox(height: 8.0), + // FieldRowHistoryTransaksi( + // label: "Kategori", + // value: listSearchHistory + // .value[idx].kategoriname + // .toString(), + // ), + // SizedBox(height: 8.0), + // if (listSearchHistory + // .value[idx].isconfirm == + // "Y") + // Row( + // mainAxisAlignment: + // MainAxisAlignment.end, + // children: [ + // Chip( + // label: Text( + // 'Confirmed', + // style: TextStyle( + // color: + // Constant.green_600), + // ), + // shape: RoundedRectangleBorder( + // side: BorderSide( + // color: + // Constant.green_600), + // borderRadius: + // BorderRadius.circular( + // 4.0), + // ), + // backgroundColor: Colors.white, + // ), + // ], + // ), + // SizedBox( + // height: Constant.getActualYPhone( + // context: context, y: 6), + // ), + // if (listSearchHistory + // .value[idx].isconfirm == + // "N") + // Row( + // mainAxisAlignment: + // MainAxisAlignment.end, + // children: [ + // ElevatedButton( + // onPressed: () { + // // Handle delete button tap + // }, + // child: Text( + // 'Delete', + // style: TextStyle( + // color: + // Constant.textWhite), + // ), + // style: ElevatedButton.styleFrom( + // backgroundColor: Colors + // .red, // Ganti dengan warna delete button yang diinginkan + // ), + // ), + // ], + // ) + // ], + // ), + // ), + // ); + // }, + // ), + // ), + + Card( + elevation: 2.0, + child: Padding( + padding: const EdgeInsets.all(10), + child: Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // mainAxisAlignment: MainAxisAlignment.start, + children: [ + // atas + HistoryRowAtasWidget(), + + // bawah + Row(), + ], + ), + ), + ), + ], ), ), ), diff --git a/app_petty_cash/lib/screen/transaksi/search_history_transaksi_provider.dart b/app_petty_cash/lib/screen/transaksi/search_history_transaksi_provider.dart new file mode 100644 index 0000000..d434b69 --- /dev/null +++ b/app_petty_cash/lib/screen/transaksi/search_history_transaksi_provider.dart @@ -0,0 +1,76 @@ +import 'package:equatable/equatable.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +import '../../model/history_transaksi_model.dart'; +import '../../repository/transaksi_repository.dart'; +import '../../provider/dio_provider.dart'; +import '../../repository/base_repository.dart'; + +abstract class SearchHistoryTransaksiState extends Equatable { + final DateTime date; + const SearchHistoryTransaksiState(this.date); + @override + List get props => [date]; +} + +class SearchHistoryTransaksiStateInit extends SearchHistoryTransaksiState { + SearchHistoryTransaksiStateInit() : super(DateTime.now()); +} + +class SearchHistoryTransaksiStateLoading extends SearchHistoryTransaksiState { + SearchHistoryTransaksiStateLoading() : super(DateTime.now()); +} + +class SearchHistoryTransaksiStateError extends SearchHistoryTransaksiState { + final String message; + SearchHistoryTransaksiStateError({ + required this.message, + }) : super(DateTime.now()); +} + +class SearchHistoryTransaksiStateDone extends SearchHistoryTransaksiState { + final List model; + SearchHistoryTransaksiStateDone({ + required this.model, + }) : super(DateTime.now()); +} + +//notifier +class SearchHistoryTransaksiNotifier + extends StateNotifier { + final Ref ref; + SearchHistoryTransaksiNotifier({ + required this.ref, + }) : super(SearchHistoryTransaksiStateInit()); + + void searchHistoryTransaksi( + String companyid, + String tglAwal, + String tglAkhir, + String categoryid, + ) async { + try { + state = SearchHistoryTransaksiStateLoading(); + final dio = ref.read(dioProvider); + final resp = await TransaksiRepository(dio: dio).getListHistoryTransaksi( + companyid, + tglAwal, + tglAkhir, + categoryid, + ); + state = SearchHistoryTransaksiStateDone(model: resp); + } catch (e) { + if (e is BaseRepositoryException) { + state = SearchHistoryTransaksiStateError(message: e.message.toString()); + } else { + state = SearchHistoryTransaksiStateError(message: e.toString()); + } + } + } +} + +//provider +final searchHistoryTransaksiProvider = StateNotifierProvider< + SearchHistoryTransaksiNotifier, SearchHistoryTransaksiState>( + (ref) => SearchHistoryTransaksiNotifier(ref: ref), +); diff --git a/app_petty_cash/lib/widget/custom_drawer.dart b/app_petty_cash/lib/widget/custom_drawer.dart index 203a50e..d1e2ae6 100644 --- a/app_petty_cash/lib/widget/custom_drawer.dart +++ b/app_petty_cash/lib/widget/custom_drawer.dart @@ -162,44 +162,44 @@ class CustomDrawer extends HookConsumerWidget { Navigator.pushNamed(context, reportRoute); }, ), - ListTile( - title: Text( - 'User', - style: TextStyle( - color: (currentMenu == 4) - ? Constant.textWhite - : Constant.textBlack, - ), - ), - tileColor: (currentMenu == 4) - ? Constant.pcBtnBackgroundColor - : Colors.transparent, - onTap: () { - // Handle navigation to User screen - Navigator.pop(context); - ref.read(currentPageProvider.state).update((state) => 4); - Navigator.pushNamed(context, userRoute); - }, - ), - ListTile( - title: Text( - 'Change Company', - style: TextStyle( - color: (currentMenu == 5) - ? Constant.textWhite - : Constant.textBlack, - ), - ), - tileColor: (currentMenu == 5) - ? Constant.pcBtnBackgroundColor - : Colors.transparent, - onTap: () { - // Handle navigation to User screen - Navigator.pop(context); - ref.read(currentPageProvider.state).update((state) => 5); - Navigator.pushNamed(context, changeCompanyRoute); - }, - ), + // ListTile( + // title: Text( + // 'User', + // style: TextStyle( + // color: (currentMenu == 4) + // ? Constant.textWhite + // : Constant.textBlack, + // ), + // ), + // tileColor: (currentMenu == 4) + // ? Constant.pcBtnBackgroundColor + // : Colors.transparent, + // onTap: () { + // // Handle navigation to User screen + // Navigator.pop(context); + // ref.read(currentPageProvider.state).update((state) => 4); + // Navigator.pushNamed(context, userRoute); + // }, + // ), + // ListTile( + // title: Text( + // 'Change Company', + // style: TextStyle( + // color: (currentMenu == 5) + // ? Constant.textWhite + // : Constant.textBlack, + // ), + // ), + // tileColor: (currentMenu == 5) + // ? Constant.pcBtnBackgroundColor + // : Colors.transparent, + // onTap: () { + // // Handle navigation to User screen + // Navigator.pop(context); + // ref.read(currentPageProvider.state).update((state) => 5); + // Navigator.pushNamed(context, changeCompanyRoute); + // }, + // ), ListTile( title: Text( 'Logout', diff --git a/app_petty_cash/lib/widget/history_row_atas_widget.dart b/app_petty_cash/lib/widget/history_row_atas_widget.dart new file mode 100644 index 0000000..42b3faa --- /dev/null +++ b/app_petty_cash/lib/widget/history_row_atas_widget.dart @@ -0,0 +1,110 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +import '../app/constant.dart'; + +class HistoryRowAtasWidget extends HookConsumerWidget { + const HistoryRowAtasWidget({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Row( + children: [ + // kiri + Container( + width: Constant.getActualXPhone(context: context, x: 38), + height: Constant.getActualYPhone(context: context, y: 38), + decoration: BoxDecoration( + color: Color.fromRGBO(241, 90, 41, 0.08), + borderRadius: BorderRadius.all( + Radius.circular(8.0), + ), + ), + // child: Text('s'), + child: SvgPicture.network( + 'https://devone.aplikasi.web.id/pettycash-media/icon/icon_12.svg', + semanticsLabel: 'Icon pizza', + placeholderBuilder: (BuildContext context) => Container( + padding: const EdgeInsets.all(30.0), + child: const CircularProgressIndicator(), + ), + ), + ), + + // tengah + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + 'Makanan & Minuman', + style: Constant.body2_600(context: context).copyWith( + fontWeight: FontWeight.w600, color: Constant.textBlack), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, + y: 8, + ), + ), + Text( + '100000', + style: Constant.body1_600(context: context).copyWith( + fontWeight: FontWeight.w600, + color: Constant.pcBtnBackgroundColor), + ), + ], + ), + ), + ), + + // kanan + Expanded( + child: Padding( + padding: EdgeInsets.only(right: 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.end, + children: [ + Container( + // width: Constant.getActualXPhone(context: context, x: 32), + height: Constant.getActualYPhone(context: context, y: 19), + decoration: BoxDecoration( + color: Color.fromRGBO(241, 90, 41, 0.16), + borderRadius: BorderRadius.all( + Radius.circular(6.0), + ), + ), + child: Padding( + padding: EdgeInsets.all(2.0), + child: Text( + 'Kredit', + style: Constant.body1_600(context: context).copyWith( + fontWeight: FontWeight.w600, + color: Constant.pcBtnBackgroundColor), + ), + ), + ), + SizedBox( + height: Constant.getActualYPhone( + context: context, + y: 8, + ), + ), + Text( + '15 Des 2023', + style: Constant.body1_600(context: context).copyWith( + fontWeight: FontWeight.w600, color: Constant.textGreyv2), + ), + ], + ), + ), + ), + ], + ); + } +} diff --git a/app_petty_cash/pubspec.lock b/app_petty_cash/pubspec.lock index ba1a4c2..d9ea55c 100644 --- a/app_petty_cash/pubspec.lock +++ b/app_petty_cash/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596 + url: "https://pub.dev" + source: hosted + version: "2.4.2" async: dependency: transitive description: @@ -190,6 +198,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c + url: "https://pub.dev" + source: hosted + version: "2.0.9" flutter_test: dependency: "direct dev" description: flutter @@ -280,6 +296,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" path_provider_linux: dependency: transitive description: @@ -344,6 +368,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.3" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750 + url: "https://pub.dev" + source: hosted + version: "5.4.0" platform: dependency: transitive description: @@ -565,6 +597,30 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.1" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "18f6690295af52d081f6808f2f7c69f0eed6d7e23a71539d75f4aeb8f0062172" + url: "https://pub.dev" + source: hosted + version: "1.1.9+2" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "531d20465c10dfac7f5cd90b60bbe4dd9921f1ec4ca54c83ebb176dbacb7bb2d" + url: "https://pub.dev" + source: hosted + version: "1.1.9+2" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "03012b0a33775c5530576b70240308080e1d5050f0faf000118c20e6463bc0ad" + url: "https://pub.dev" + source: hosted + version: "1.1.9+2" vector_math: dependency: transitive description: @@ -589,6 +645,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + xml: + dependency: transitive + description: + name: xml + sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84" + url: "https://pub.dev" + source: hosted + version: "6.3.0" sdks: dart: ">=3.0.6 <4.0.0" flutter: ">=3.10.0" diff --git a/app_petty_cash/pubspec.yaml b/app_petty_cash/pubspec.yaml index 93edb0c..1c82ca6 100644 --- a/app_petty_cash/pubspec.yaml +++ b/app_petty_cash/pubspec.yaml @@ -50,6 +50,7 @@ dependencies: flutter_multi_formatter: ^2.12.4 top_snackbar_flutter: ^3.1.0 url_launcher: ^6.1.13 + flutter_svg: ^2.0.9 dev_dependencies: flutter_test: