step 18 : history widget atas cmp

This commit is contained in:
sindhu
2024-01-16 18:02:38 +07:00
parent de84b76170
commit 9416c010d7
19 changed files with 1108 additions and 126 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,30 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="32" height="32" fill="#F5F5F5"/>
<path d="M-2213 -1590C-2213 -1591.1 -2212.1 -1592 -2211 -1592H1326C1327.1 -1592 1328 -1591.1 1328 -1590V2084C1328 2085.1 1327.1 2086 1326 2086H-2211C-2212.1 2086 -2213 2085.1 -2213 2084V-1590Z" fill="#2C2C2D"/>
<path d="M-2211 -1591H1326V-1593H-2211V-1591ZM1327 -1590V2084H1329V-1590H1327ZM1326 2085H-2211V2087H1326V2085ZM-2212 2084V-1590H-2214V2084H-2212ZM-2211 2085C-2211.55 2085 -2212 2084.55 -2212 2084H-2214C-2214 2085.66 -2212.66 2087 -2211 2087V2085ZM1327 2084C1327 2084.55 1326.55 2085 1326 2085V2087C1327.66 2087 1329 2085.66 1329 2084H1327ZM1326 -1591C1326.55 -1591 1327 -1590.55 1327 -1590H1329C1329 -1591.66 1327.66 -1593 1326 -1593V-1591ZM-2211 -1593C-2212.66 -1593 -2214 -1591.66 -2214 -1590H-2212C-2212 -1590.55 -2211.55 -1591 -2211 -1591V-1593Z" fill="black" fill-opacity="0.1"/>
<rect width="390" height="1084" transform="translate(-44 -414)" fill="white"/>
<g filter="url(#filter0_dd_11_141)">
<rect x="-24" y="-28" width="350" height="145" rx="12" fill="white"/>
<rect x="-12" y="-12" width="56" height="56" rx="8" fill="#F15A29" fill-opacity="0.08"/>
<path d="M20 14.6666H20.0133M14.6666 20H14.68M21.3333 21.3333H21.3466M2.66663 21.3333L29.3333 29.3333L21.3333 2.66663C16.8694 3.89048 12.801 6.25514 9.52805 9.52805C6.25514 12.801 3.89048 16.8694 2.66663 21.3333Z" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7.61328 22.8133C8.69531 19.2219 10.6497 15.9542 13.3019 13.3019C15.9542 10.6497 19.2219 8.69531 22.8133 7.61328" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<filter id="filter0_dd_11_141" x="-44" y="-36" width="390" height="185" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feMorphology radius="4" operator="erode" in="SourceAlpha" result="effect1_dropShadow_11_141"/>
<feOffset dy="12"/>
<feGaussianBlur stdDeviation="12"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.568627 0 0 0 0 0.619608 0 0 0 0 0.670588 0 0 0 0.12 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_11_141"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.568627 0 0 0 0 0.619608 0 0 0 0 0.670588 0 0 0 0.2 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_11_141" result="effect2_dropShadow_11_141"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow_11_141" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M28 16V9.33333H6.66667C5.95942 9.33333 5.28115 9.05238 4.78105 8.55229C4.28095 8.05219 4 7.37391 4 6.66667C4 5.95942 4.28095 5.28115 4.78105 4.78105C5.28115 4.28095 5.95942 4 6.66667 4H25.3333V9.33333" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M4 6.66675V25.3334C4 26.0407 4.28095 26.7189 4.78105 27.219C5.28115 27.7191 5.95942 28.0001 6.66667 28.0001H28V21.3334" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M24 16C23.2928 16 22.6145 16.281 22.1144 16.781C21.6143 17.2811 21.3334 17.9594 21.3334 18.6667C21.3334 19.3739 21.6143 20.0522 22.1144 20.5523C22.6145 21.0524 23.2928 21.3333 24 21.3333H29.3334V16H24Z" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 904 B

View File

@@ -0,0 +1,5 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.0001 2.66663H12.0001C11.2637 2.66663 10.6667 3.26358 10.6667 3.99996V6.66663C10.6667 7.40301 11.2637 7.99996 12.0001 7.99996H20.0001C20.7365 7.99996 21.3334 7.40301 21.3334 6.66663V3.99996C21.3334 3.26358 20.7365 2.66663 20.0001 2.66663Z" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M13.8667 16.8C14.3971 16.2696 15.1166 15.9716 15.8667 15.9716C16.6169 15.9716 17.3363 16.2696 17.8667 16.8C18.3971 17.3304 18.6951 18.0498 18.6951 18.8C18.6951 19.5501 18.3971 20.2696 17.8667 20.8L10.6667 28L5.33337 29.3333L6.66671 24L13.8667 16.8Z" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M21.3334 5.33325H24C24.7073 5.33325 25.3856 5.6142 25.8857 6.1143C26.3858 6.6144 26.6667 7.29267 26.6667 7.99992V26.6666C26.6667 27.3738 26.3858 28.0521 25.8857 28.5522C25.3856 29.0523 24.7073 29.3333 24 29.3333H16.6667M5.33337 17.9999V7.99992C5.33337 7.29267 5.61433 6.6144 6.11442 6.1143C6.61452 5.6142 7.2928 5.33325 8.00004 5.33325H10.6667" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 775 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

View File

@@ -0,0 +1,4 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M26.6666 18.6666H5.33329C3.86053 18.6666 2.66663 19.8605 2.66663 21.3333V26.6666C2.66663 28.1394 3.86053 29.3333 5.33329 29.3333H26.6666C28.1394 29.3333 29.3333 28.1394 29.3333 26.6666V21.3333C29.3333 19.8605 28.1394 18.6666 26.6666 18.6666Z" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M8.01333 24H8M13.3467 24H13.3333M20 13.3333V18.6666M23.7867 9.55997C23.2913 9.0641 22.7031 8.67072 22.0557 8.40232C21.4082 8.13392 20.7142 7.99578 20.0133 7.99578C19.3125 7.99578 18.6184 8.13392 17.971 8.40232C17.3235 8.67072 16.7353 9.0641 16.24 9.55997M27.5467 5.78664C25.5465 3.78776 22.8344 2.66492 20.0067 2.66492C17.1789 2.66492 14.4669 3.78776 12.4667 5.78664" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 898 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 599 B

View File

@@ -0,0 +1,3 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M2.66663 29.3333L6.66663 25.3333M9.99996 18L13.3333 14.6667M14 22L17.3333 18.6667M24 4L18.6666 9.33333H26.6666L21.3333 14.6667M8.39996 27.0667C8.69725 27.365 9.05051 27.6017 9.43947 27.7632C9.82844 27.9247 10.2455 28.0079 10.6666 28.0079C11.0878 28.0079 11.5048 27.9247 11.8938 27.7632C12.2827 27.6017 12.636 27.365 12.9333 27.0667L16 24L7.99996 16L4.93329 19.0667C4.63497 19.364 4.39826 19.7172 4.23675 20.1062C4.07524 20.4951 3.9921 20.9122 3.9921 21.3333C3.9921 21.7545 4.07524 22.1715 4.23675 22.5605C4.39826 22.9495 4.63497 23.3027 4.93329 23.6L8.39996 27.0667Z" stroke="#F15A29" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 763 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

View File

@@ -15,8 +15,7 @@ class Constant {
// static String baseUrl = "https://devregonline.pramita.co.id/one-api/xdoc/";
// tester devbandungraya
static String baseUrlDevoneReport =
"devone.aplikasi.web.id";
static String baseUrlDevoneReport = "devone.aplikasi.web.id";
static String baseUrlDevone =
"http://devone.aplikasi.web.id/one-api-pettycash/pettycash/";

View File

@@ -0,0 +1,64 @@
class HistoryTransaksiModel {
String? id;
String? tanggaltransaksi;
String? tipe;
String? kategoriid;
String? kategoriname;
String? note;
String? amount;
String? sender;
String? imgurl;
String? isconfirm;
String? tanggalconfirm;
String? usertransaksi;
String? userconfirm;
HistoryTransaksiModel(
{this.id,
this.tanggaltransaksi,
this.tipe,
this.kategoriid,
this.kategoriname,
this.note,
this.amount,
this.sender,
this.imgurl,
this.isconfirm,
this.tanggalconfirm,
this.usertransaksi,
this.userconfirm});
HistoryTransaksiModel.fromJson(Map<String, dynamic> 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<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
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;
}
}

View File

@@ -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<List<HistoryTransaksiModel>> 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<HistoryTransaksiModel>.empty(growable: true);
resp['data'].forEach((e) {
final model = HistoryTransaksiModel.fromJson(e);
result.add(model);
});
return result;
}
}

View File

@@ -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<ListType>>(List.empty(growable: true));
final selectedListTypeData = useState<ListType>(ListType());
final listTypeLoading = useState(false);
// category
final listCategoryLoading = useState(false);
final selectedListCategory = useState<ListCategory>(ListCategory());
final listCategoryData = useState<List<ListCategory>>(
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>(DateTime.now());
final tglAwalTmp = useState<String>("");
final ctrlTglAkhir = useTextEditingController(text: formattedDate);
final tglAkhir = useState<DateTime>(DateTime.now());
final tglAkhirTmp = useState<String>("");
final categoryIsLoading = useState<bool>(false);
final searchHistoryIsLoading = useState<bool>(false);
final listSearchHistory = useState<List<HistoryTransaksiModel>>(
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<ListCategory>.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<String> 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<ListCategory>(
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<ListCategory>(
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<double>(6),
thumbVisibility:
MaterialStateProperty.all<bool>(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>(
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(),
],
),
),
),
],
),
),
),

View File

@@ -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<Object?> 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<HistoryTransaksiModel> model;
SearchHistoryTransaksiStateDone({
required this.model,
}) : super(DateTime.now());
}
//notifier
class SearchHistoryTransaksiNotifier
extends StateNotifier<SearchHistoryTransaksiState> {
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),
);

View File

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

View File

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

View File

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

View File

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