Compare commits
9 Commits
step/impro
...
andy/coba-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
050f5f25e2 | ||
|
|
8e15f91b33 | ||
|
|
73cbde7f3e | ||
|
|
01d4560df1 | ||
|
|
532a341cec | ||
|
|
157ad9a34c | ||
|
|
0691012133 | ||
|
|
674471402a | ||
|
|
3c9253c1c1 |
2
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
{
|
||||
}
|
||||
@@ -52,6 +52,7 @@ android {
|
||||
targetSdkVersion flutter.targetSdkVersion
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
multiDexEnabled true
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
@@ -69,4 +70,5 @@ flutter {
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation 'com.android.support:multidex:1.0.3'
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||
<application
|
||||
android:label="app_petty_cash"
|
||||
android:name="${applicationName}"
|
||||
|
||||
|
Before Width: | Height: | Size: 1.0 KiB |
@@ -1,30 +0,0 @@
|
||||
<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>
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1,5 +0,0 @@
|
||||
<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>
|
||||
|
Before Width: | Height: | Size: 904 B |
@@ -1,5 +0,0 @@
|
||||
<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>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 775 B |
|
Before Width: | Height: | Size: 716 B |
@@ -1,4 +0,0 @@
|
||||
<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>
|
||||
|
Before Width: | Height: | Size: 898 B |
|
Before Width: | Height: | Size: 599 B |
@@ -1,3 +0,0 @@
|
||||
<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>
|
||||
|
Before Width: | Height: | Size: 763 B |
|
Before Width: | Height: | Size: 407 B |
|
Before Width: | Height: | Size: 8.0 KiB |
@@ -15,8 +15,6 @@ class Constant {
|
||||
// static String baseUrl = "https://devregonline.pramita.co.id/one-api/xdoc/";
|
||||
|
||||
// tester devbandungraya
|
||||
static String baseUrlDevoneReport = "devone.aplikasi.web.id";
|
||||
|
||||
static String baseUrlDevone =
|
||||
"http://devone.aplikasi.web.id/one-api-pettycash/pettycash/";
|
||||
|
||||
@@ -262,18 +260,6 @@ class Constant {
|
||||
// background upload file
|
||||
static Color bgUploadFile = Color.fromRGBO(207, 207, 207, 0.20);
|
||||
|
||||
// background icon history
|
||||
static Color bgIconHistory = Color.fromRGBO(241, 90, 41, 0.16);
|
||||
|
||||
// background chip confirmed
|
||||
static Color bgChipConfirmed = Color(0xffe8f4f5);
|
||||
|
||||
static Color bgTextChipConfirmed = Color(0xff32827C);
|
||||
|
||||
// delete text
|
||||
static Color bgTextDelete = Color(0xffFF4842);
|
||||
static Color bgTextChipDelete = Color.fromRGBO(255, 72, 66, 0.12);
|
||||
|
||||
//typoGraphy
|
||||
static TextStyle titleH1Login({required BuildContext context}) {
|
||||
return TextStyle(
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import '../screen/change_company/change_company.dart';
|
||||
import 'package:app_petty_cash/screen/camera/coba_camera.dart';
|
||||
import 'package:app_petty_cash/screen/camera/example.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../screen/home/home_screen.dart';
|
||||
import '../screen/transaksi/history_transaksi_screen.dart';
|
||||
import '../screen/transaksi/transaksi_screen.dart';
|
||||
import '../screen/login/login_screen.dart';
|
||||
import '../screen/splash/splash_screen.dart';
|
||||
@@ -17,8 +17,8 @@ const homeRoute = "/homeRoute";
|
||||
const transaksiRoute = "/transaksiRoute";
|
||||
const userRoute = "/userRoute";
|
||||
const reportRoute = "/reportRoute";
|
||||
const changeCompanyRoute = "/changeCompanyRoute";
|
||||
const historyTransaksiRoute = "/historyTransaksiRoute";
|
||||
const cameraExampleRoute = "/cameraExampleRoute";
|
||||
const cobaCameraRoute = "/cobaCameraRoute";
|
||||
|
||||
// test screen
|
||||
const testFilePickerRoute = "/testFilePickerRoute";
|
||||
@@ -38,32 +38,6 @@ class AppRoute {
|
||||
});
|
||||
}
|
||||
|
||||
// change Company
|
||||
if (settings.name == changeCompanyRoute) {
|
||||
return MaterialPageRoute(builder: (context) {
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(
|
||||
textScaleFactor: 1.0,
|
||||
padding: EdgeInsets.all(0),
|
||||
),
|
||||
child: ChangeCompanyScreen(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// history transaksi
|
||||
if (settings.name == historyTransaksiRoute) {
|
||||
return MaterialPageRoute(builder: (context) {
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(
|
||||
textScaleFactor: 1.0,
|
||||
padding: EdgeInsets.all(0),
|
||||
),
|
||||
child: HistoryTransaksiScreen(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// report screen
|
||||
if (settings.name == reportRoute) {
|
||||
return MaterialPageRoute(builder: (context) {
|
||||
@@ -128,6 +102,30 @@ class AppRoute {
|
||||
);
|
||||
});
|
||||
}
|
||||
// Camera example route
|
||||
if (settings.name == cameraExampleRoute) {
|
||||
return MaterialPageRoute(builder: (context) {
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(
|
||||
textScaleFactor: 1.0,
|
||||
padding: EdgeInsets.all(0),
|
||||
),
|
||||
child: CamerExample(),
|
||||
);
|
||||
});
|
||||
}
|
||||
// Coba Camera route
|
||||
if (settings.name == cobaCameraRoute) {
|
||||
return MaterialPageRoute(builder: (context) {
|
||||
return MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(
|
||||
textScaleFactor: 1.0,
|
||||
padding: EdgeInsets.all(0),
|
||||
),
|
||||
child: CobaCamera(),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// default
|
||||
return MaterialPageRoute(builder: (context) {
|
||||
|
||||
@@ -25,8 +25,8 @@ class AuthDoctorModel {
|
||||
late String M_UserID;
|
||||
late String M_UserUsername;
|
||||
late String M_UserEmail;
|
||||
late String M_CompanyID;
|
||||
late String M_CompanyName;
|
||||
// late String M_UserM_DoctorCode;
|
||||
// late String M_UserM_DoctorID;
|
||||
// late String M_UserM_StaffID;
|
||||
// late String M_UserM_MouID;
|
||||
late String ip;
|
||||
@@ -39,8 +39,8 @@ class AuthDoctorModel {
|
||||
required this.M_UserID,
|
||||
required this.M_UserUsername,
|
||||
required this.M_UserEmail,
|
||||
required this.M_CompanyID,
|
||||
required this.M_CompanyName,
|
||||
// required this.M_UserM_DoctorCode,
|
||||
// required this.M_UserM_DoctorID,
|
||||
// this.M_UserM_StaffID = "",
|
||||
// this.M_UserM_MouID = "",
|
||||
this.ip = "",
|
||||
@@ -51,8 +51,8 @@ class AuthDoctorModel {
|
||||
M_UserID = json['M_UserID'].toString();
|
||||
M_UserUsername = json['M_UserUsername'].toString();
|
||||
M_UserEmail = json['M_UserEmail'].toString();
|
||||
M_CompanyID = json['M_CompanyID'].toString();
|
||||
M_CompanyName = json['M_CompanyName'].toString();
|
||||
// M_UserM_DoctorCode = json['M_UserM_DoctorCode'].toString();
|
||||
// M_UserM_DoctorID = json['M_UserM_DoctorID'].toString();
|
||||
// M_UserM_StaffID = json['M_UserM_StaffID'].toString();
|
||||
// M_UserM_MouID = json['M_UserM_MouID'].toString();
|
||||
ip = json['ip'].toString();
|
||||
@@ -64,8 +64,8 @@ class AuthDoctorModel {
|
||||
data['M_UserID'] = M_UserID;
|
||||
data['M_UserUsername'] = M_UserUsername;
|
||||
data['M_UserEmail'] = M_UserEmail;
|
||||
data['M_CompanyID'] = M_CompanyID;
|
||||
data['M_CompanyName'] = M_CompanyName;
|
||||
// data['M_UserM_DoctorCode'] = M_UserM_DoctorCode;
|
||||
// data['M_UserM_DoctorID'] = M_UserM_DoctorID;
|
||||
// data['M_UserM_StaffID'] = M_UserM_StaffID;
|
||||
// data['M_UserM_MouID'] = M_UserM_MouID;
|
||||
data['ip'] = ip;
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../app/constant.dart';
|
||||
import '../model/auth_model.dart';
|
||||
import 'base_repository.dart';
|
||||
@@ -23,8 +19,6 @@ class AuthRepository extends BaseRepository {
|
||||
// "doctor_id": "2891",
|
||||
// "password": "3"
|
||||
};
|
||||
|
||||
print(param);
|
||||
// final service = "${Constant.baseUrlDevone}xauth/login";
|
||||
final service = "${Constant.baseUrlDevone}auth/login";
|
||||
print('url login $service');
|
||||
@@ -88,7 +82,7 @@ class AuthRepository extends BaseRepository {
|
||||
// model: AuthDoctorModel.fromJson(resp["data"]["user"]),
|
||||
// );
|
||||
// return result;
|
||||
|
||||
|
||||
if (resp["status"] == "OK") {
|
||||
return resp['message'];
|
||||
} else {
|
||||
|
||||
@@ -2,33 +2,11 @@ import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../app/constant.dart';
|
||||
|
||||
abstract class BaseRepository {
|
||||
final Dio dio;
|
||||
BaseRepository({required this.dio});
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> post({
|
||||
required Map<String, dynamic> param,
|
||||
required String service,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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';
|
||||
|
||||
@@ -59,20 +58,17 @@ class TransaksiRepository extends BaseRepository {
|
||||
String sender,
|
||||
String url) async {
|
||||
String paramPostInUrl = "";
|
||||
String M_CompanyID = await getCompanyID();
|
||||
if (tipe == "DEBIT") {
|
||||
if (tipe == "KREDIT") {
|
||||
sender = "";
|
||||
paramPostInUrl =
|
||||
"?tanggal=$tanggal&tipe=$tipe&kategoriid=$kategoriid&jumlah=$jumlah&catatan=$catatan&url=$url&userid=$userid&sender=$sender";
|
||||
} else {
|
||||
if (tipe == "KREDIT") {
|
||||
if (tipe == "DEBIT") {
|
||||
kategoriid = "0";
|
||||
paramPostInUrl =
|
||||
"?tanggal=$tanggal&tipe=$tipe&kategoriid=$kategoriid&jumlah=$jumlah&catatan=$catatan&url=$url&userid=$userid&sender=$sender";
|
||||
}
|
||||
}
|
||||
|
||||
paramPostInUrl += "&companyid=$M_CompanyID";
|
||||
// /?tanggal=2023-12-29&tipe=KREDIT&kategoriid=3&jumlah=5000&catatan=Lakban%20Besar&url=&userid=1&sender=
|
||||
|
||||
final service =
|
||||
@@ -94,61 +90,4 @@ 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;
|
||||
}
|
||||
|
||||
// delete transaksi
|
||||
Future<String> deleteTransaksi(
|
||||
String id,
|
||||
String userid,
|
||||
) async {
|
||||
|
||||
final service =
|
||||
"${Constant.baseUrlDevone}transaction/deletetransaction/?id=$id&userid=$userid";
|
||||
final resp = await get(
|
||||
// param: {
|
||||
// "": "",
|
||||
// },
|
||||
service: service,
|
||||
);
|
||||
|
||||
print("url delete transaksi : $service");
|
||||
|
||||
// final result = List<ListCategory>.empty(growable: true);
|
||||
// resp['data'].forEach((e) {
|
||||
// final model = ListCategory.fromJson(e);
|
||||
// result.add(model);
|
||||
// });
|
||||
|
||||
if(resp['status'] != "OK"){
|
||||
return resp['message'];
|
||||
}
|
||||
|
||||
return resp['status'];
|
||||
}
|
||||
}
|
||||
|
||||
128
app_petty_cash/lib/screen/camera/coba_camera.dart
Normal file
@@ -0,0 +1,128 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:io' as io;
|
||||
|
||||
import 'package:app_petty_cash/app/constant.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
class CobaCamera extends HookConsumerWidget {
|
||||
const CobaCamera({super.key});
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final photo = useState<XFile?>(null);
|
||||
final photoBase64 = useState<String>("");
|
||||
final previewLoading = useState(false);
|
||||
getBase64() async {
|
||||
// List<int> imageBytes = await photo.value?.readAsBytes();
|
||||
if (photo.value != null) {
|
||||
final bytes = io.File(photo.value!.path).readAsBytesSync();
|
||||
String base64Image = base64Encode(bytes);
|
||||
photoBase64.value = base64Image;
|
||||
final file = File(photo.value!.path);
|
||||
print(file.lengthSync() / 1000000);
|
||||
print(await photo.value!.length());
|
||||
|
||||
// await getExternalStorageDirectory();
|
||||
// print(await photo.value!.saveTo(path));
|
||||
print(base64Image);
|
||||
}
|
||||
}
|
||||
|
||||
final ImagePicker _picker = ImagePicker();
|
||||
pickImage() async {
|
||||
previewLoading.value = true;
|
||||
final XFile? pickedFile = await _picker.pickImage(
|
||||
source: ImageSource.camera,
|
||||
);
|
||||
photo.value = pickedFile;
|
||||
// final Directory appDocumentsDir =
|
||||
// await getApplicationDocumentsDirectory();
|
||||
// print(appDocumentsDir);
|
||||
// await pickedFile!.saveTo(appDocumentsDir.path);
|
||||
await getBase64();
|
||||
previewLoading.value = false;
|
||||
}
|
||||
|
||||
browseImage() async {
|
||||
previewLoading.value = true;
|
||||
|
||||
final XFile? pickedFile = await _picker.pickImage(
|
||||
source: ImageSource.gallery,
|
||||
);
|
||||
photo.value = pickedFile;
|
||||
getBase64();
|
||||
previewLoading.value = false;
|
||||
}
|
||||
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: SafeArea(
|
||||
minimum: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: Constant.getActualYPhone(context: context, y: 500),
|
||||
width: MediaQuery.of(context).size.width,
|
||||
color: Colors.red,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final String? mime =
|
||||
lookupMimeType(photo.value?.path ?? "");
|
||||
|
||||
return Semantics(
|
||||
label: 'image_picker_example_picked_image',
|
||||
child: (mime != null
|
||||
? (mime.startsWith('image/'))
|
||||
? Image.file(
|
||||
// image: AssetImage(photo.value!.path),
|
||||
File(photo.value!.path),
|
||||
frameBuilder: (context, child, frame,
|
||||
wasSynchronouslyLoaded) {
|
||||
return (wasSynchronouslyLoaded)
|
||||
? Center(
|
||||
child: Text("Loadinga"),
|
||||
)
|
||||
: Container(
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
errorBuilder: (BuildContext context,
|
||||
Object error, StackTrace? stackTrace) {
|
||||
return const Center(
|
||||
child: Text(
|
||||
'This image type is not supported'));
|
||||
},
|
||||
)
|
||||
: null
|
||||
: null));
|
||||
},
|
||||
),
|
||||
),
|
||||
// photo.value != null
|
||||
// ? PhotoView(imageProvider: AssetImage(photo.value!.path))
|
||||
// : Container(),
|
||||
Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
pickImage();
|
||||
},
|
||||
child: Text("Take a picture")),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
browseImage();
|
||||
},
|
||||
child: Text("Browse a picture"))
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
542
app_petty_cash/lib/screen/camera/example.dart
Normal file
@@ -0,0 +1,542 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
class CamerExample extends StatefulWidget {
|
||||
const CamerExample({super.key});
|
||||
|
||||
@override
|
||||
State<CamerExample> createState() => _CamerExampleState();
|
||||
}
|
||||
|
||||
class _CamerExampleState extends State<CamerExample> {
|
||||
List<XFile>? _mediaFileList;
|
||||
|
||||
void _setImageFileListFromFile(XFile? value) {
|
||||
_mediaFileList = value == null ? null : <XFile>[value];
|
||||
}
|
||||
|
||||
dynamic _pickImageError;
|
||||
bool isVideo = false;
|
||||
|
||||
VideoPlayerController? _controller;
|
||||
VideoPlayerController? _toBeDisposed;
|
||||
String? _retrieveDataError;
|
||||
|
||||
final ImagePicker _picker = ImagePicker();
|
||||
final TextEditingController maxWidthController = TextEditingController();
|
||||
final TextEditingController maxHeightController = TextEditingController();
|
||||
final TextEditingController qualityController = TextEditingController();
|
||||
|
||||
Future<void> _playVideo(XFile? file) async {
|
||||
if (file != null && mounted) {
|
||||
await _disposeVideoController();
|
||||
late VideoPlayerController controller;
|
||||
if (kIsWeb) {
|
||||
controller = VideoPlayerController.networkUrl(Uri.parse(file.path));
|
||||
} else {
|
||||
controller = VideoPlayerController.file(File(file.path));
|
||||
}
|
||||
_controller = controller;
|
||||
// In web, most browsers won't honor a programmatic call to .play
|
||||
// if the video has a sound track (and is not muted).
|
||||
// Mute the video so it auto-plays in web!
|
||||
// This is not needed if the call to .play is the result of user
|
||||
// interaction (clicking on a "play" button, for example).
|
||||
const double volume = kIsWeb ? 0.0 : 1.0;
|
||||
await controller.setVolume(volume);
|
||||
await controller.initialize();
|
||||
await controller.setLooping(true);
|
||||
await controller.play();
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onImageButtonPressed(
|
||||
ImageSource source, {
|
||||
required BuildContext context,
|
||||
bool isMultiImage = false,
|
||||
bool isMedia = false,
|
||||
}) async {
|
||||
if (_controller != null) {
|
||||
await _controller!.setVolume(0.0);
|
||||
}
|
||||
if (context.mounted) {
|
||||
if (isVideo) {
|
||||
final XFile? file = await _picker.pickVideo(
|
||||
source: source, maxDuration: const Duration(seconds: 10));
|
||||
await _playVideo(file);
|
||||
} else if (isMultiImage) {
|
||||
await _displayPickImageDialog(context,
|
||||
(double? maxWidth, double? maxHeight, int? quality) async {
|
||||
try {
|
||||
final List<XFile> pickedFileList = isMedia
|
||||
? await _picker.pickMultipleMedia(
|
||||
maxWidth: maxWidth,
|
||||
maxHeight: maxHeight,
|
||||
imageQuality: quality,
|
||||
)
|
||||
: await _picker.pickMultiImage(
|
||||
maxWidth: maxWidth,
|
||||
maxHeight: maxHeight,
|
||||
imageQuality: quality,
|
||||
);
|
||||
setState(() {
|
||||
_mediaFileList = pickedFileList;
|
||||
});
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_pickImageError = e;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (isMedia) {
|
||||
await _displayPickImageDialog(context,
|
||||
(double? maxWidth, double? maxHeight, int? quality) async {
|
||||
try {
|
||||
final List<XFile> pickedFileList = <XFile>[];
|
||||
final XFile? media = await _picker.pickMedia(
|
||||
maxWidth: maxWidth,
|
||||
maxHeight: maxHeight,
|
||||
imageQuality: quality,
|
||||
);
|
||||
if (media != null) {
|
||||
pickedFileList.add(media);
|
||||
setState(() {
|
||||
_mediaFileList = pickedFileList;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_pickImageError = e;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
await _displayPickImageDialog(context,
|
||||
(double? maxWidth, double? maxHeight, int? quality) async {
|
||||
try {
|
||||
final XFile? pickedFile = await _picker.pickImage(
|
||||
source: source,
|
||||
maxWidth: maxWidth,
|
||||
maxHeight: maxHeight,
|
||||
imageQuality: quality,
|
||||
);
|
||||
setState(() {
|
||||
_setImageFileListFromFile(pickedFile);
|
||||
});
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
_pickImageError = e;
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void deactivate() {
|
||||
if (_controller != null) {
|
||||
_controller!.setVolume(0.0);
|
||||
_controller!.pause();
|
||||
}
|
||||
super.deactivate();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_disposeVideoController();
|
||||
maxWidthController.dispose();
|
||||
maxHeightController.dispose();
|
||||
qualityController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _disposeVideoController() async {
|
||||
if (_toBeDisposed != null) {
|
||||
await _toBeDisposed!.dispose();
|
||||
}
|
||||
_toBeDisposed = _controller;
|
||||
_controller = null;
|
||||
}
|
||||
|
||||
Widget _previewVideo() {
|
||||
final Text? retrieveError = _getRetrieveErrorWidget();
|
||||
if (retrieveError != null) {
|
||||
return retrieveError;
|
||||
}
|
||||
if (_controller == null) {
|
||||
return const Text(
|
||||
'You have not yet picked a video',
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
}
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: AspectRatioVideo(_controller),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _previewImages() {
|
||||
final Text? retrieveError = _getRetrieveErrorWidget();
|
||||
if (retrieveError != null) {
|
||||
return retrieveError;
|
||||
}
|
||||
if (_mediaFileList != null) {
|
||||
return Semantics(
|
||||
label: 'image_picker_example_picked_images',
|
||||
child: ListView.builder(
|
||||
key: UniqueKey(),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
final String? mime = lookupMimeType(_mediaFileList![index].path);
|
||||
|
||||
// Why network for web?
|
||||
// See https://pub.dev/packages/image_picker_for_web#limitations-on-the-web-platform
|
||||
return Semantics(
|
||||
label: 'image_picker_example_picked_image',
|
||||
child: kIsWeb
|
||||
? Image.network(_mediaFileList![index].path)
|
||||
: (mime == null || mime.startsWith('image/')
|
||||
? Image.file(
|
||||
File(_mediaFileList![index].path),
|
||||
errorBuilder: (BuildContext context, Object error,
|
||||
StackTrace? stackTrace) {
|
||||
return const Center(
|
||||
child:
|
||||
Text('This image type is not supported'));
|
||||
},
|
||||
)
|
||||
: _buildInlineVideoPlayer(index)),
|
||||
);
|
||||
},
|
||||
itemCount: _mediaFileList!.length,
|
||||
),
|
||||
);
|
||||
} else if (_pickImageError != null) {
|
||||
return Text(
|
||||
'Pick image error: $_pickImageError',
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
} else {
|
||||
return const Text(
|
||||
'You have not yet picked an image.',
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildInlineVideoPlayer(int index) {
|
||||
final VideoPlayerController controller =
|
||||
VideoPlayerController.file(File(_mediaFileList![index].path));
|
||||
const double volume = kIsWeb ? 0.0 : 1.0;
|
||||
controller.setVolume(volume);
|
||||
controller.initialize();
|
||||
controller.setLooping(true);
|
||||
controller.play();
|
||||
return Center(child: AspectRatioVideo(controller));
|
||||
}
|
||||
|
||||
Widget _handlePreview() {
|
||||
if (isVideo) {
|
||||
return _previewVideo();
|
||||
} else {
|
||||
return _previewImages();
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> retrieveLostData() async {
|
||||
final LostDataResponse response = await _picker.retrieveLostData();
|
||||
if (response.isEmpty) {
|
||||
return;
|
||||
}
|
||||
if (response.file != null) {
|
||||
if (response.type == RetrieveType.video) {
|
||||
isVideo = true;
|
||||
await _playVideo(response.file);
|
||||
} else {
|
||||
isVideo = false;
|
||||
setState(() {
|
||||
if (response.files == null) {
|
||||
_setImageFileListFromFile(response.file);
|
||||
} else {
|
||||
_mediaFileList = response.files;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
_retrieveDataError = response.exception!.code;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text("Camera example"),
|
||||
),
|
||||
body: Center(
|
||||
child: !kIsWeb && defaultTargetPlatform == TargetPlatform.android
|
||||
? FutureBuilder<void>(
|
||||
future: retrieveLostData(),
|
||||
builder: (BuildContext context, AsyncSnapshot<void> snapshot) {
|
||||
switch (snapshot.connectionState) {
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
return const Text(
|
||||
'You have not yet picked an image.',
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
case ConnectionState.done:
|
||||
return _handlePreview();
|
||||
case ConnectionState.active:
|
||||
if (snapshot.hasError) {
|
||||
return Text(
|
||||
'Pick image/video error: ${snapshot.error}}',
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
} else {
|
||||
return const Text(
|
||||
'You have not yet picked an image.',
|
||||
textAlign: TextAlign.center,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
: _handlePreview(),
|
||||
),
|
||||
floatingActionButton: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
children: <Widget>[
|
||||
Semantics(
|
||||
label: 'image_picker_example_from_gallery',
|
||||
child: FloatingActionButton(
|
||||
onPressed: () {
|
||||
isVideo = false;
|
||||
_onImageButtonPressed(ImageSource.gallery, context: context);
|
||||
},
|
||||
heroTag: 'image0',
|
||||
tooltip: 'Pick Image from gallery',
|
||||
child: const Icon(Icons.photo),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: FloatingActionButton(
|
||||
onPressed: () {
|
||||
isVideo = false;
|
||||
_onImageButtonPressed(
|
||||
ImageSource.gallery,
|
||||
context: context,
|
||||
isMultiImage: true,
|
||||
isMedia: true,
|
||||
);
|
||||
},
|
||||
heroTag: 'multipleMedia',
|
||||
tooltip: 'Pick Multiple Media from gallery',
|
||||
child: const Icon(Icons.photo_library),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: FloatingActionButton(
|
||||
onPressed: () {
|
||||
isVideo = false;
|
||||
_onImageButtonPressed(
|
||||
ImageSource.gallery,
|
||||
context: context,
|
||||
isMedia: true,
|
||||
);
|
||||
},
|
||||
heroTag: 'media',
|
||||
tooltip: 'Pick Single Media from gallery',
|
||||
child: const Icon(Icons.photo_library),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: FloatingActionButton(
|
||||
onPressed: () {
|
||||
isVideo = false;
|
||||
_onImageButtonPressed(
|
||||
ImageSource.gallery,
|
||||
context: context,
|
||||
isMultiImage: true,
|
||||
);
|
||||
},
|
||||
heroTag: 'image1',
|
||||
tooltip: 'Pick Multiple Image from gallery',
|
||||
child: const Icon(Icons.photo_library),
|
||||
),
|
||||
),
|
||||
if (_picker.supportsImageSource(ImageSource.camera))
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: FloatingActionButton(
|
||||
onPressed: () {
|
||||
isVideo = false;
|
||||
_onImageButtonPressed(ImageSource.camera, context: context);
|
||||
},
|
||||
heroTag: 'image2',
|
||||
tooltip: 'Take a Photo',
|
||||
child: const Icon(Icons.camera_alt),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: FloatingActionButton(
|
||||
backgroundColor: Colors.red,
|
||||
onPressed: () {
|
||||
isVideo = true;
|
||||
_onImageButtonPressed(ImageSource.gallery, context: context);
|
||||
},
|
||||
heroTag: 'video0',
|
||||
tooltip: 'Pick Video from gallery',
|
||||
child: const Icon(Icons.video_library),
|
||||
),
|
||||
),
|
||||
if (_picker.supportsImageSource(ImageSource.camera))
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: FloatingActionButton(
|
||||
backgroundColor: Colors.red,
|
||||
onPressed: () {
|
||||
isVideo = true;
|
||||
_onImageButtonPressed(ImageSource.camera, context: context);
|
||||
},
|
||||
heroTag: 'video1',
|
||||
tooltip: 'Take a Video',
|
||||
child: const Icon(Icons.videocam),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Text? _getRetrieveErrorWidget() {
|
||||
if (_retrieveDataError != null) {
|
||||
final Text result = Text(_retrieveDataError!);
|
||||
_retrieveDataError = null;
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<void> _displayPickImageDialog(
|
||||
BuildContext context, OnPickImageCallback onPick) async {
|
||||
return showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Add optional parameters'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
TextField(
|
||||
controller: maxWidthController,
|
||||
keyboardType:
|
||||
const TextInputType.numberWithOptions(decimal: true),
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Enter maxWidth if desired'),
|
||||
),
|
||||
TextField(
|
||||
controller: maxHeightController,
|
||||
keyboardType:
|
||||
const TextInputType.numberWithOptions(decimal: true),
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Enter maxHeight if desired'),
|
||||
),
|
||||
TextField(
|
||||
controller: qualityController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Enter quality if desired'),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('CANCEL'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('PICK'),
|
||||
onPressed: () {
|
||||
final double? width = maxWidthController.text.isNotEmpty
|
||||
? double.parse(maxWidthController.text)
|
||||
: null;
|
||||
final double? height = maxHeightController.text.isNotEmpty
|
||||
? double.parse(maxHeightController.text)
|
||||
: null;
|
||||
final int? quality = qualityController.text.isNotEmpty
|
||||
? int.parse(qualityController.text)
|
||||
: null;
|
||||
onPick(width, height, quality);
|
||||
Navigator.of(context).pop();
|
||||
}),
|
||||
],
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
typedef OnPickImageCallback = void Function(
|
||||
double? maxWidth, double? maxHeight, int? quality);
|
||||
|
||||
class AspectRatioVideo extends StatefulWidget {
|
||||
const AspectRatioVideo(this.controller, {super.key});
|
||||
|
||||
final VideoPlayerController? controller;
|
||||
|
||||
@override
|
||||
AspectRatioVideoState createState() => AspectRatioVideoState();
|
||||
}
|
||||
|
||||
class AspectRatioVideoState extends State<AspectRatioVideo> {
|
||||
VideoPlayerController? get controller => widget.controller;
|
||||
bool initialized = false;
|
||||
|
||||
void _onVideoControllerUpdate() {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
if (initialized != controller!.value.isInitialized) {
|
||||
initialized = controller!.value.isInitialized;
|
||||
setState(() {});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
controller!.addListener(_onVideoControllerUpdate);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
controller!.removeListener(_onVideoControllerUpdate);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (initialized) {
|
||||
return Center(
|
||||
child: AspectRatio(
|
||||
aspectRatio: controller!.value.aspectRatio,
|
||||
child: VideoPlayer(controller!),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
import '../../app/constant.dart';
|
||||
import '../../app/route.dart';
|
||||
import '../../provider/current_user_provider.dart';
|
||||
import '../../widget/custom_drawer.dart';
|
||||
|
||||
class ChangeCompanyScreen extends HookConsumerWidget {
|
||||
const ChangeCompanyScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
useEffect(() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||
final userID = ref.read(currentUserProvider)?.model.M_UserID ?? "0";
|
||||
if (userID == "0") {
|
||||
//not login
|
||||
Navigator.of(context)
|
||||
.pushNamedAndRemoveUntil(loginRoute, (route) => true);
|
||||
|
||||
// Navigator.popAndPushNamed(context, loginRoute);
|
||||
return;
|
||||
}
|
||||
});
|
||||
return () {};
|
||||
}, []);
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: Constant.getActualYPhone(context: context, y: 30),
|
||||
),
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
// centerTitle: true,
|
||||
title: Text(
|
||||
'Change Company',
|
||||
style: TextStyle(color: Constant.textWhite),
|
||||
),
|
||||
backgroundColor: Constant.pcBtnBackgroundColor,
|
||||
iconTheme: IconThemeData(
|
||||
color: Constant.textWhite,
|
||||
),
|
||||
),
|
||||
drawer: CustomDrawer(),
|
||||
body: Text('Under Construction'),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -29,8 +29,7 @@ class LoginScreen extends HookConsumerWidget {
|
||||
final authModel = AuthModel(
|
||||
token: xmodel["token"],
|
||||
model: AuthDoctorModel(
|
||||
M_CompanyID: xmodel["model"]["M_CompanyID"],
|
||||
M_CompanyName: xmodel["model"]["M_CompanyName"],
|
||||
// M_UserM_DoctorID: xmodel["model"]["M_UserM_DoctorID"],
|
||||
M_UserEmail: xmodel["model"]["M_UserEmail"],
|
||||
M_UserUsername: xmodel["model"]["M_UserUsername"],
|
||||
// M_UserM_DoctorCode: xmodel["model"]["M_UserM_DoctorCode"],
|
||||
|
||||
@@ -1,7 +1,3 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../widget/sankbar_widget.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
@@ -29,26 +25,6 @@ class ReportScreen extends HookConsumerWidget {
|
||||
|
||||
final tglAkhir = useState<DateTime>(DateTime.now());
|
||||
final tglAkhirTmp = useState<String>("");
|
||||
String M_CompanyID = "0";
|
||||
|
||||
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 {
|
||||
@@ -82,373 +58,337 @@ class ReportScreen extends HookConsumerWidget {
|
||||
),
|
||||
drawer: CustomDrawer(),
|
||||
body: SafeArea(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Tanggal Awal',
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600, color: Constant.textBlack),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(context: context, y: 10),
|
||||
),
|
||||
// Tanggal Awal
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: ctrlTglAwal,
|
||||
decoration: InputDecoration(
|
||||
hintStyle:
|
||||
Constant.body2_400(context: context).copyWith(
|
||||
color: Colors.orange,
|
||||
),
|
||||
labelStyle:
|
||||
Constant.body2_400(context: context).copyWith(
|
||||
color: Colors.orange,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
child: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Tanggal Awal',
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600, color: Constant.textBlack),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(context: context, y: 10),
|
||||
),
|
||||
// Tanggal Awal
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: ctrlTglAwal,
|
||||
decoration: InputDecoration(
|
||||
hintStyle:
|
||||
Constant.body2_400(context: context).copyWith(
|
||||
color: Colors.orange,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
labelStyle:
|
||||
Constant.body2_400(context: context).copyWith(
|
||||
color: Colors.orange,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
// 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(
|
||||
height: Constant.getActualYPhone(context: context, y: 20),
|
||||
),
|
||||
|
||||
Text(
|
||||
'Tanggal Akhir',
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600, color: Constant.textBlack),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(context: context, y: 10),
|
||||
),
|
||||
// Tanggal Akhir
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: ctrlTglAkhir,
|
||||
decoration: InputDecoration(
|
||||
hintStyle:
|
||||
Constant.body2_400(context: context).copyWith(
|
||||
color: Colors.orange,
|
||||
),
|
||||
labelStyle:
|
||||
Constant.body2_400(context: context).copyWith(
|
||||
color: Colors.orange,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.orange,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.orange,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
// labelText: "Tanggal Awal",
|
||||
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;
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Spacer(),
|
||||
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateColor.resolveWith(
|
||||
(states) => Colors.white),
|
||||
// side: MaterialStateBorderSide.resolveWith(
|
||||
// (states) => BorderSide(color: Colors.green),
|
||||
// ),
|
||||
|
||||
// backgroundColor: MaterialStateColor.resolveWith(
|
||||
// (st) => Constant.pcBtnBackgroundColor),
|
||||
shape:
|
||||
MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(
|
||||
color: Colors.green,
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.orange,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
shadowColor:
|
||||
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||
elevation: MaterialStateProperty.all(4.0),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: Constant.getActualXPhone(
|
||||
context: context, x: 16),
|
||||
height: Constant.getActualYPhone(
|
||||
context: context, y: 16),
|
||||
// decoration: BoxDecoration(color: Colors.grey),
|
||||
child: Image.asset(
|
||||
"images/logo_excel.png",
|
||||
fit: BoxFit.fill,
|
||||
// scale: 1,
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.orange,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: Constant.getActualXPhone(
|
||||
context: context, x: 6),
|
||||
// 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(
|
||||
height: Constant.getActualYPhone(context: context, y: 20),
|
||||
),
|
||||
|
||||
Text(
|
||||
'Tanggal Akhir',
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600, color: Constant.textBlack),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(context: context, y: 10),
|
||||
),
|
||||
// Tanggal Akhir
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: ctrlTglAkhir,
|
||||
decoration: InputDecoration(
|
||||
hintStyle:
|
||||
Constant.body2_400(context: context).copyWith(
|
||||
color: Colors.orange,
|
||||
),
|
||||
Text(
|
||||
'Excel',
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
labelStyle:
|
||||
Constant.body2_400(context: context).copyWith(
|
||||
color: Colors.orange,
|
||||
),
|
||||
border: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.orange,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.orange,
|
||||
width: 1,
|
||||
),
|
||||
),
|
||||
// labelText: "Tanggal Awal",
|
||||
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;
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: BottomAppBar(
|
||||
height: 150,
|
||||
child: Container(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
// right: Constant.getActualXPhone(context: context, x: 27),
|
||||
// left: Constant.getActualXPhone(context: context, x: 27),
|
||||
// bottom: Constant.getActualYPhone(context: context, y: 32),
|
||||
// top: Constant.getActualYPhone(context: context, y: 24),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Excel
|
||||
Container(
|
||||
width: Constant.getActualXPhone(context: context, x: 336),
|
||||
height: Constant.getActualYPhone(context: context, y: 42),
|
||||
child: ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateColor.resolveWith(
|
||||
(states) => Colors.white),
|
||||
// side: MaterialStateBorderSide.resolveWith(
|
||||
// (states) => BorderSide(color: Colors.green),
|
||||
// ),
|
||||
|
||||
// backgroundColor: MaterialStateColor.resolveWith(
|
||||
// (st) => Constant.pcBtnBackgroundColor),
|
||||
shape:
|
||||
MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
),
|
||||
shadowColor:
|
||||
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||
elevation: MaterialStateProperty.all(4.0),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: Constant.getActualXPhone(
|
||||
context: context, x: 16),
|
||||
height: Constant.getActualYPhone(
|
||||
context: context, y: 16),
|
||||
// decoration: BoxDecoration(color: Colors.grey),
|
||||
child: Image.asset(
|
||||
"images/logo_excel.png",
|
||||
fit: BoxFit.fill,
|
||||
// scale: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualXPhone(
|
||||
context: context, x: 8),
|
||||
),
|
||||
Text(
|
||||
'Download Report (xls) ',
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () {},
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(context: context, y: 20),
|
||||
),
|
||||
|
||||
// PDF
|
||||
Container(
|
||||
width: Constant.getActualXPhone(context: context, x: 336),
|
||||
height: Constant.getActualYPhone(context: context, y: 42),
|
||||
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: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: Constant.getActualXPhone(
|
||||
context: context, x: 16),
|
||||
height: Constant.getActualYPhone(
|
||||
context: context, y: 16),
|
||||
// decoration: BoxDecoration(color: Colors.grey),
|
||||
child: Image.asset(
|
||||
"images/logo_pdf.png",
|
||||
fit: BoxFit.fill,
|
||||
// scale: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualXPhone(
|
||||
context: context, x: 8),
|
||||
),
|
||||
Text(
|
||||
'Download Report (PDF)',
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.green,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () async {
|
||||
M_CompanyID = await getCompanyID();
|
||||
if (M_CompanyID == "0") {
|
||||
SanckbarWidget(
|
||||
context, 'Invalid Company', snackbarType.error);
|
||||
return;
|
||||
}
|
||||
// Awal
|
||||
DateTime parsedDateAwal =
|
||||
DateFormat('dd-MM-yyyy').parse(
|
||||
ctrlTglAwal.value.text.toString(),
|
||||
);
|
||||
String formattedDateAwal =
|
||||
DateFormat('yyyy-MM-dd').format(parsedDateAwal);
|
||||
|
||||
// Akhir
|
||||
DateTime parsedDateAkhir =
|
||||
DateFormat('dd-MM-yyyy').parse(
|
||||
ctrlTglAwal.value.text.toString(),
|
||||
);
|
||||
String formattedDateAkhir =
|
||||
DateFormat('yyyy-MM-dd').format(parsedDateAkhir);
|
||||
|
||||
String url =
|
||||
"https://${Constant.baseUrlDevoneReport}/birt/run?__report=report/one/pettycash/rpt_r_pt_001.rptdesign&__format=xls&PStartDate=$formattedDateAwal&PEndDate=$formattedDateAkhir&PCompanyID=$M_CompanyID&username=adminsas%20";
|
||||
if (!await launchUrl(Uri.parse(url))) {
|
||||
// throw Exception('Could not launch $url');
|
||||
SanckbarWidget(context, 'Could not launch $url',
|
||||
snackbarType.error);
|
||||
}
|
||||
// https://devone.aplikasi.web.id/birt/run?__report=report/one/pettycash/rpt_r_pt_001.rptdesign&__format=pdf&PStartDate=2023-11-01&PEndDate=2023-12-30&PCompanyID=0&username=adminsas%20&tm=1701327096267
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
width: Constant.getActualXPhone(context: context, x: 10),
|
||||
),
|
||||
|
||||
// PDF
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
style: ButtonStyle(
|
||||
backgroundColor: MaterialStateColor.resolveWith(
|
||||
(st) => Constant.pcBtnBackgroundColor),
|
||||
shape:
|
||||
MaterialStateProperty.all<RoundedRectangleBorder>(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
side: BorderSide(
|
||||
color: Constant.pcBtnBackgroundColor,
|
||||
),
|
||||
),
|
||||
color: Constant.white),
|
||||
),
|
||||
shadowColor:
|
||||
MaterialStateProperty.all(Color(0xffff48423d)),
|
||||
elevation: MaterialStateProperty.all(4.0),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Container(
|
||||
width: Constant.getActualXPhone(
|
||||
context: context, x: 16),
|
||||
height: Constant.getActualYPhone(
|
||||
context: context, y: 16),
|
||||
// decoration: BoxDecoration(color: Colors.grey),
|
||||
child: Image.asset(
|
||||
"images/logo_pdf.png",
|
||||
fit: BoxFit.fill,
|
||||
// scale: 1,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: Constant.getActualXPhone(
|
||||
context: context, x: 6),
|
||||
),
|
||||
Text(
|
||||
'PDF',
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Constant.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
onPressed: () async {
|
||||
M_CompanyID = await getCompanyID();
|
||||
if (M_CompanyID == "0") {
|
||||
SanckbarWidget(
|
||||
context, 'Invalid Company', snackbarType.error);
|
||||
return;
|
||||
}
|
||||
// Awal
|
||||
DateTime parsedDateAwal =
|
||||
DateFormat('dd-MM-yyyy').parse(
|
||||
ctrlTglAwal.value.text.toString(),
|
||||
);
|
||||
String formattedDateAwal =
|
||||
DateFormat('yyyy-MM-dd').format(parsedDateAwal);
|
||||
|
||||
// Akhir
|
||||
DateTime parsedDateAkhir =
|
||||
DateFormat('dd-MM-yyyy').parse(
|
||||
ctrlTglAwal.value.text.toString(),
|
||||
);
|
||||
String formattedDateAkhir =
|
||||
DateFormat('yyyy-MM-dd').format(parsedDateAkhir);
|
||||
|
||||
String url =
|
||||
"https://${Constant.baseUrlDevoneReport}/birt/run?__report=report/one/pettycash/rpt_r_pt_001.rptdesign&__format=pdf&PStartDate=$formattedDateAwal&PEndDate=$formattedDateAkhir&PCompanyID=$M_CompanyID&username=adminsas%20";
|
||||
if (!await launchUrl(Uri.parse(url))) {
|
||||
// throw Exception('Could not launch $url');
|
||||
SanckbarWidget(context, 'Could not launch $url',
|
||||
snackbarType.error);
|
||||
}
|
||||
},
|
||||
],
|
||||
),
|
||||
onPressed: () async {
|
||||
String url = "https://pub.dev/packages?q=url+launcher";
|
||||
if (!await launchUrl(Uri.parse(url))) {
|
||||
// throw Exception('Could not launch $url');
|
||||
SanckbarWidget(context, 'Could not launch $url',
|
||||
snackbarType.error);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../repository/transaksi_repository.dart';
|
||||
import '../../provider/dio_provider.dart';
|
||||
import '../../repository/base_repository.dart';
|
||||
import 'search_history_transaksi_provider.dart';
|
||||
|
||||
abstract class DeleteTransaksiState extends Equatable {
|
||||
final DateTime date;
|
||||
const DeleteTransaksiState(this.date);
|
||||
@override
|
||||
List<Object?> get props => [date];
|
||||
}
|
||||
|
||||
class DeleteTransaksiStateInit extends DeleteTransaksiState {
|
||||
DeleteTransaksiStateInit() : super(DateTime.now());
|
||||
}
|
||||
|
||||
class DeleteTransaksiStateLoading extends DeleteTransaksiState {
|
||||
DeleteTransaksiStateLoading() : super(DateTime.now());
|
||||
}
|
||||
|
||||
class DeleteTransaksiStateError extends DeleteTransaksiState {
|
||||
final String message;
|
||||
DeleteTransaksiStateError({
|
||||
required this.message,
|
||||
}) : super(DateTime.now());
|
||||
}
|
||||
|
||||
class DeleteTransaksiStateDone extends DeleteTransaksiState {
|
||||
// final List<ListType> model;
|
||||
final String resp;
|
||||
DeleteTransaksiStateDone({
|
||||
required this.resp,
|
||||
}) : super(DateTime.now());
|
||||
}
|
||||
|
||||
//notifier
|
||||
class DeleteTransaksiNotifier extends StateNotifier<DeleteTransaksiState> {
|
||||
final Ref ref;
|
||||
DeleteTransaksiNotifier({
|
||||
required this.ref,
|
||||
}) : super(DeleteTransaksiStateInit());
|
||||
|
||||
void deleteTransaksi(
|
||||
String id,
|
||||
String userid,
|
||||
String companyid,
|
||||
String tglAwal,
|
||||
String tglAkhir,
|
||||
String categoryid,
|
||||
) async {
|
||||
try {
|
||||
state = DeleteTransaksiStateLoading();
|
||||
final dio = ref.read(dioProvider);
|
||||
final resp = await TransaksiRepository(dio: dio).deleteTransaksi(
|
||||
id,
|
||||
userid,
|
||||
);
|
||||
state = DeleteTransaksiStateDone(resp: resp);
|
||||
|
||||
// search lagi buat get data
|
||||
ref.read(searchHistoryTransaksiProvider.notifier).searchHistoryTransaksi(
|
||||
companyid,
|
||||
tglAwal,
|
||||
tglAkhir,
|
||||
categoryid,
|
||||
);
|
||||
} catch (e) {
|
||||
if (e is BaseRepositoryException) {
|
||||
state = DeleteTransaksiStateError(message: e.message.toString());
|
||||
} else {
|
||||
state = DeleteTransaksiStateError(message: e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//provider
|
||||
final deleteTransaksiProvider =
|
||||
StateNotifierProvider<DeleteTransaksiNotifier, DeleteTransaksiState>(
|
||||
(ref) => DeleteTransaksiNotifier(ref: ref),
|
||||
);
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
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),
|
||||
);
|
||||
@@ -0,0 +1,100 @@
|
||||
import 'package:app_petty_cash/app/constant.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
class TransaksiPickDateWidget extends StatelessWidget {
|
||||
const TransaksiPickDateWidget({
|
||||
super.key,
|
||||
required this.ctrlTglAwal,
|
||||
required this.tglAwal,
|
||||
required this.tglAwalTmp,
|
||||
});
|
||||
|
||||
final TextEditingController ctrlTglAwal;
|
||||
final ValueNotifier<DateTime> tglAwal;
|
||||
final ValueNotifier<String> tglAwalTmp;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextField(
|
||||
readOnly: true,
|
||||
controller: ctrlTglAwal,
|
||||
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 Awal",
|
||||
hintText: 'Tanggal Transaksi',
|
||||
// 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(
|
||||
keyboardType: TextInputType.none,
|
||||
// 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;
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
import 'package:app_petty_cash/app/constant.dart';
|
||||
import 'package:app_petty_cash/model/list_category_model.dart';
|
||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class TransaksiSelectKategoriWidget extends StatelessWidget {
|
||||
const TransaksiSelectKategoriWidget({
|
||||
super.key,
|
||||
required this.listCategoryData,
|
||||
required this.selectedListCategory,
|
||||
});
|
||||
|
||||
final ValueNotifier<List<ListCategory>> listCategoryData;
|
||||
final ValueNotifier<ListCategory> selectedListCategory;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return 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.w400, 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.w400),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
style: Constant.body1(context: context)
|
||||
.copyWith(color: Constant.textBlack, fontWeight: FontWeight.w400),
|
||||
value: selectedListCategory.value,
|
||||
onChanged: (ListCategory? newValue) {
|
||||
// if (newValue) {
|
||||
selectedListCategory.value = newValue!;
|
||||
print(selectedListCategory.value.categoryid);
|
||||
// }
|
||||
},
|
||||
buttonStyleData: ButtonStyleData(
|
||||
height: Constant.getActualY(context: context, y: 80),
|
||||
width: Constant.getActualX(context: context, x: 320),
|
||||
padding: EdgeInsets.only(
|
||||
left: Constant.getActualX(context: context, x: 20),
|
||||
right: Constant.getActualX(context: context, x: 20),
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Constant.white,
|
||||
border: Border.all(color: Constant.textGrey, 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: 20),
|
||||
right: Constant.getActualX(context: context, x: 20),
|
||||
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: 20),
|
||||
right: Constant.getActualX(context: context, x: 20),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:app_petty_cash/app/constant.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:mime/mime.dart';
|
||||
|
||||
class TransaksiUploadAreaWidget extends StatelessWidget {
|
||||
const TransaksiUploadAreaWidget({
|
||||
super.key,
|
||||
required this.isImage,
|
||||
required this.fileData,
|
||||
required this.fileDataBase64,
|
||||
required this.pickFile,
|
||||
required this.pickImage,
|
||||
});
|
||||
|
||||
final ValueNotifier<bool> isImage;
|
||||
final ValueNotifier<XFile?> fileData;
|
||||
final ValueNotifier<String> fileDataBase64;
|
||||
final Function pickImage;
|
||||
final Function pickFile;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
print("tapped");
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) {
|
||||
return Container(
|
||||
height: Constant.getActualY(context: context, y: 200),
|
||||
padding: EdgeInsets.all(20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
pickFile();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.folder_copy_rounded,
|
||||
size: 50,
|
||||
color: Constant.pcBtnBackgroundColor,
|
||||
)),
|
||||
Text("Browse a file",
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Constant.textBlack))
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
pickImage();
|
||||
},
|
||||
icon: Icon(
|
||||
Icons.add_a_photo_rounded,
|
||||
size: 50,
|
||||
color: Constant.pcBtnBackgroundColor,
|
||||
)),
|
||||
Text("Take a picture",
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Constant.textBlack))
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Stack(
|
||||
alignment: AlignmentDirectional.topEnd,
|
||||
children: [
|
||||
Container(
|
||||
width: Constant.getActualXPhone(context: context, x: 390),
|
||||
height: Constant.getActualYPhone(
|
||||
context: context, y: isImage.value ? 200 : 83),
|
||||
decoration: BoxDecoration(color: Constant.bgUploadFile),
|
||||
child: Builder(builder: (context) {
|
||||
final String? mime = lookupMimeType(fileData.value?.path ?? "");
|
||||
return Semantics(
|
||||
label: 'image_picker_example_picked_image',
|
||||
child: (mime != null
|
||||
? (mime.startsWith('image/'))
|
||||
? Image.file(
|
||||
// image: AssetImage(photo.value!.path),
|
||||
File(fileData.value!.path),
|
||||
frameBuilder: (context, child, frame,
|
||||
wasSynchronouslyLoaded) {
|
||||
return (wasSynchronouslyLoaded)
|
||||
? Center(
|
||||
child: Text("Loadinga"),
|
||||
)
|
||||
: Container(
|
||||
child: child,
|
||||
);
|
||||
},
|
||||
errorBuilder: (BuildContext context, Object error,
|
||||
StackTrace? stackTrace) {
|
||||
return const Center(
|
||||
child: Text(
|
||||
'This image type is not supported'));
|
||||
},
|
||||
)
|
||||
: Container(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.file_present_rounded,
|
||||
size: 40,
|
||||
color: Constant.pcBtnBackgroundColor,
|
||||
),
|
||||
Text(
|
||||
fileData.value?.name ?? '',
|
||||
style: Constant.body2_400(context: context),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.upload_outlined,
|
||||
color: Constant.pcBtnBackgroundColor,
|
||||
),
|
||||
Text(
|
||||
'Upload File',
|
||||
style: Constant.body1(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Constant.pcBtnBackgroundColor),
|
||||
)
|
||||
],
|
||||
)));
|
||||
}),
|
||||
),
|
||||
if (fileData.value != null)
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
fileData.value = null;
|
||||
fileDataBase64.value = '';
|
||||
isImage.value = false;
|
||||
},
|
||||
icon: Icon(Icons.cancel_outlined)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
@@ -13,12 +12,9 @@ import '../provider/current_user_provider.dart';
|
||||
import '../screen/login/logout_provider.dart';
|
||||
|
||||
class CustomDrawer extends HookConsumerWidget {
|
||||
// final String userCompany;
|
||||
|
||||
const CustomDrawer({
|
||||
Key? key,
|
||||
// required this.userCompany,
|
||||
}) : super(key: key);
|
||||
super.key,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
@@ -26,26 +22,6 @@ class CustomDrawer extends HookConsumerWidget {
|
||||
final isLoading = useState(false);
|
||||
final errorMessage = useState("");
|
||||
final successMessage = useState("");
|
||||
final M_CompanyName = useState("-");
|
||||
|
||||
Future<String> getCompanyName() async {
|
||||
final shared = await SharedPreferences.getInstance();
|
||||
String M_CompanyName = "-";
|
||||
|
||||
if (shared != null) {
|
||||
final bearerString = shared.get(Constant.bearerName).toString();
|
||||
final xmodel = jsonDecode(bearerString);
|
||||
if (xmodel != null) {
|
||||
M_CompanyName = xmodel["model"]["M_CompanyName"];
|
||||
}
|
||||
}
|
||||
|
||||
if (M_CompanyName == "0") {
|
||||
// throw BaseRepositoryException(message: 'Invalid Company ID');
|
||||
}
|
||||
|
||||
return M_CompanyName;
|
||||
}
|
||||
|
||||
useEffect(() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((timeStamp) async {
|
||||
@@ -58,7 +34,6 @@ class CustomDrawer extends HookConsumerWidget {
|
||||
// Navigator.popAndPushNamed(context, loginRoute);
|
||||
return;
|
||||
}
|
||||
M_CompanyName.value = await getCompanyName();
|
||||
});
|
||||
return () {};
|
||||
}, []);
|
||||
@@ -94,229 +69,135 @@ class CustomDrawer extends HookConsumerWidget {
|
||||
final currentMenu = ref.read(currentPageProvider);
|
||||
|
||||
return Drawer(
|
||||
elevation: 0,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(0))
|
||||
),
|
||||
|
||||
child: Container(
|
||||
child: ListView(
|
||||
// padding: EdgeInsets.only(
|
||||
// top: Constant.getActualYPhone(context: context, y: 10),
|
||||
// ),
|
||||
children: [
|
||||
Container(
|
||||
|
||||
// decoration: BoxDecoration(
|
||||
// border: Border(bottom: BorderSide(color: Colors.transparent)) // <--- use the global theme to change the dividerColor property
|
||||
// ),
|
||||
child:
|
||||
Image(image: AssetImage('images/logo_sismedika_landscape.png')),
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(context: context, y: 8),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: EdgeInsets.only(
|
||||
top: Constant.getActualYPhone(context: context, y: 10),
|
||||
bottom: Constant.getActualYPhone(context: context, y: 10),
|
||||
right: Constant.getActualXPhone(context: context, x: 24),
|
||||
left: Constant.getActualXPhone(context: context, x: 24),
|
||||
),
|
||||
child: Container(
|
||||
width: Constant.getActualXPhone(context: context, x: 300),
|
||||
),
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: Constant.getActualXPhone(context: context, x: 24),
|
||||
right: Constant.getActualXPhone(context: context, x: 71),
|
||||
),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
color: Constant.textGrey.withOpacity(0.16),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: Constant.getActualXPhone(context: context, x: 8),
|
||||
right: Constant.getActualXPhone(context: context, x: 8),
|
||||
),
|
||||
child: Text(
|
||||
M_CompanyName.value,
|
||||
style: Constant.body3(context: context).copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
color: Constant.textGreyv2,
|
||||
backgroundColor: Constant.textGrey.withOpacity(0.16),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
ListTile(
|
||||
leading: Icon(
|
||||
Icons.home,
|
||||
color: (currentMenu == 0)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Constant.textGreyv2,
|
||||
),
|
||||
title: Text(
|
||||
'Home',
|
||||
style: TextStyle(
|
||||
color: (currentMenu == 0)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Constant.textGreyv2,
|
||||
),
|
||||
),
|
||||
// tileColor: (currentMenu == 0)
|
||||
// ? Constant.pcBtnBackgroundColor
|
||||
// : Colors.transparent,
|
||||
onTap: () {
|
||||
// Handle navigation to Home screen
|
||||
Navigator.pop(context);
|
||||
ref.read(currentPageProvider.state).update((state) => 0);
|
||||
Navigator.pushNamed(context, homeRoute);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(
|
||||
Icons.money,
|
||||
color: (currentMenu == 1)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Constant.textGreyv2,
|
||||
),
|
||||
title: Text(
|
||||
'Transaksi',
|
||||
style: TextStyle(
|
||||
color: (currentMenu == 1)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Constant.textGreyv2,
|
||||
),
|
||||
),
|
||||
// tileColor: (currentMenu == 1)
|
||||
// ? Constant.pcBtnBackgroundColor
|
||||
// : Colors.transparent,
|
||||
onTap: () {
|
||||
// Handle navigation to Transaksi screen
|
||||
Navigator.pop(context);
|
||||
ref.read(currentPageProvider.state).update((state) => 1);
|
||||
Navigator.pushNamed(context, transaksiRoute);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(
|
||||
Icons.history,
|
||||
color: (currentMenu == 2)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Constant.textGreyv2,
|
||||
),
|
||||
title: Text(
|
||||
'History Transaksi',
|
||||
style: TextStyle(
|
||||
color: (currentMenu == 2)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Constant.textGreyv2,
|
||||
),
|
||||
),
|
||||
// tileColor: (currentMenu == 2)
|
||||
// ? Constant.pcBtnBackgroundColor
|
||||
// : Colors.transparent,
|
||||
onTap: () {
|
||||
// Handle navigation to User screen
|
||||
Navigator.pop(context);
|
||||
ref.read(currentPageProvider.state).update((state) => 2);
|
||||
Navigator.pushNamed(context, historyTransaksiRoute);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(
|
||||
Icons.feed,
|
||||
color: (currentMenu == 3)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Constant.textGreyv2,
|
||||
),
|
||||
title: Text(
|
||||
'Report',
|
||||
style: TextStyle(
|
||||
color: (currentMenu == 3)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Constant.textGreyv2,
|
||||
),
|
||||
),
|
||||
// tileColor: (currentMenu == 3)
|
||||
// ? Constant.pcBtnBackgroundColor
|
||||
// : Colors.transparent,
|
||||
onTap: () {
|
||||
// Handle navigation to Transaksi screen
|
||||
Navigator.pop(context);
|
||||
ref.read(currentPageProvider.state).update((state) => 3);
|
||||
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(
|
||||
leading: Icon(
|
||||
Icons.logout,
|
||||
color: Constant.textGreyv2,
|
||||
),
|
||||
title: Text(
|
||||
'Logout',
|
||||
style: TextStyle(color: Constant.textGreyv2),
|
||||
),
|
||||
onTap: () {
|
||||
// di set ke 0 lagi
|
||||
ref.read(currentPageProvider.state).update((state) => 0);
|
||||
ref.read(logoutProvider.notifier).logout(
|
||||
M_UserID: selectedUser?.model.M_UserID ?? "",
|
||||
M_UserUsername: selectedUser?.model.M_UserUsername ?? "",
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
child: ListView(
|
||||
padding: EdgeInsets.only(
|
||||
top: Constant.getActualYPhone(context: context, y: 10),
|
||||
),
|
||||
children: [
|
||||
// DrawerHeader(
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.blue,
|
||||
// ),
|
||||
// child: Text(
|
||||
// 'Drawer Header',
|
||||
// style: TextStyle(
|
||||
// color: Colors.white,
|
||||
// fontSize: 24,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'Home',
|
||||
style: TextStyle(
|
||||
color: (currentMenu == 0)
|
||||
? Constant.textWhite
|
||||
: Constant.textBlack,
|
||||
),
|
||||
),
|
||||
tileColor: (currentMenu == 0)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Colors.transparent,
|
||||
onTap: () {
|
||||
// Handle navigation to Home screen
|
||||
Navigator.pop(context);
|
||||
ref.read(currentPageProvider.state).update((state) => 0);
|
||||
Navigator.pushNamed(context, homeRoute);
|
||||
// Navigator.pushNamed(context, cameraExampleRoute);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'Coba Camera',
|
||||
style: TextStyle(
|
||||
color: (currentMenu == 10)
|
||||
? Constant.textWhite
|
||||
: Constant.textBlack,
|
||||
),
|
||||
),
|
||||
tileColor: (currentMenu == 10)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Colors.transparent,
|
||||
onTap: () {
|
||||
// Handle navigation to Home screen
|
||||
Navigator.pop(context);
|
||||
ref.read(currentPageProvider.state).update((state) => 10);
|
||||
// Navigator.pushNamed(context, homeRoute);
|
||||
Navigator.pushNamed(context, cobaCameraRoute);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'Transaksi',
|
||||
style: TextStyle(
|
||||
color: (currentMenu == 1)
|
||||
? Constant.textWhite
|
||||
: Constant.textBlack,
|
||||
),
|
||||
),
|
||||
tileColor: (currentMenu == 1)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Colors.transparent,
|
||||
onTap: () {
|
||||
// Handle navigation to Transaksi screen
|
||||
Navigator.pop(context);
|
||||
ref.read(currentPageProvider.state).update((state) => 1);
|
||||
Navigator.pushNamed(context, transaksiRoute);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'Report',
|
||||
style: TextStyle(
|
||||
color: (currentMenu == 2)
|
||||
? Constant.textWhite
|
||||
: Constant.textBlack,
|
||||
),
|
||||
),
|
||||
tileColor: (currentMenu == 2)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Colors.transparent,
|
||||
onTap: () {
|
||||
// Handle navigation to Transaksi screen
|
||||
Navigator.pop(context);
|
||||
ref.read(currentPageProvider.state).update((state) => 2);
|
||||
Navigator.pushNamed(context, reportRoute);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'User',
|
||||
style: TextStyle(
|
||||
color: (currentMenu == 3)
|
||||
? Constant.textWhite
|
||||
: Constant.textBlack,
|
||||
),
|
||||
),
|
||||
tileColor: (currentMenu == 3)
|
||||
? Constant.pcBtnBackgroundColor
|
||||
: Colors.transparent,
|
||||
onTap: () {
|
||||
// Handle navigation to User screen
|
||||
Navigator.pop(context);
|
||||
ref.read(currentPageProvider.state).update((state) => 3);
|
||||
Navigator.pushNamed(context, userRoute);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: Text(
|
||||
'Logout',
|
||||
// style: TextStyle(color: Constant.textWhite),
|
||||
),
|
||||
onTap: () {
|
||||
// di set ke 0 lagi
|
||||
ref.read(currentPageProvider.state).update((state) => 0);
|
||||
ref.read(logoutProvider.notifier).logout(
|
||||
M_UserID: selectedUser?.model.M_UserID ?? "",
|
||||
M_UserUsername: selectedUser?.model.M_UserUsername ?? "",
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
import '../app/constant.dart';
|
||||
|
||||
class FieldRowHistoryTransaksi extends HookConsumerWidget {
|
||||
final String label;
|
||||
final String value;
|
||||
const FieldRowHistoryTransaksi({
|
||||
Key? key,
|
||||
required this.label,
|
||||
required this.value,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
return Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 10),
|
||||
child: SizedBox(
|
||||
width: Constant.getActualXPhone(context: context, x: 100),
|
||||
child: Text(label),
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Text(':'),
|
||||
),
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: 10),
|
||||
child: Text(
|
||||
value,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,197 +0,0 @@
|
||||
import 'package:app_petty_cash/widget/sankbar_widget.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import '../app/constant.dart';
|
||||
|
||||
class HistoryRowAtasWidget extends HookConsumerWidget {
|
||||
final String icon_category_id;
|
||||
final String icon_category_name;
|
||||
final String amount;
|
||||
final String tipe;
|
||||
final String tglTransaksi;
|
||||
// final ValueNotifier<bool> searchHistoryIsLoading;
|
||||
|
||||
const HistoryRowAtasWidget({
|
||||
Key? key,
|
||||
required this.icon_category_id,
|
||||
required this.icon_category_name,
|
||||
required this.amount,
|
||||
required this.tipe,
|
||||
required this.tglTransaksi,
|
||||
// required this.searchHistoryIsLoading,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
// check file exist
|
||||
Future<Widget> checkFileExistence(String fileUrl) async {
|
||||
try {
|
||||
final dio = Dio();
|
||||
final response = await dio.head(fileUrl);
|
||||
if (response.statusCode == 200) {
|
||||
return SvgPicture.network(
|
||||
fileUrl,
|
||||
semanticsLabel: 'Icon pizza',
|
||||
placeholderBuilder: (BuildContext context) => Container(
|
||||
padding: const EdgeInsets.all(30.0),
|
||||
child: const CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return SvgPicture.network(
|
||||
'https://devone.aplikasi.web.id/pettycash-media/icon/icon_13.svg',
|
||||
semanticsLabel: 'Icon pizza',
|
||||
placeholderBuilder: (BuildContext context) => Container(
|
||||
padding: const EdgeInsets.all(30.0),
|
||||
child: const CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
// print('Error checking file existence: $e');
|
||||
return SvgPicture.network(
|
||||
'https://devone.aplikasi.web.id/pettycash-media/icon/icon_13.svg',
|
||||
semanticsLabel: 'Icon pizza',
|
||||
placeholderBuilder: (BuildContext context) => Container(
|
||||
padding: const EdgeInsets.all(30.0),
|
||||
child: const CircularProgressIndicator(),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// fungsi tanggal
|
||||
String formatDateString(String inputDate) {
|
||||
try {
|
||||
// Parsing tanggal dari string input
|
||||
DateTime date = DateFormat('dd-MM-yyyy').parse(inputDate);
|
||||
|
||||
// Format tanggal ke '30 Des 2023'
|
||||
String formattedDate = DateFormat('dd MMM yyyy', 'id').format(date);
|
||||
|
||||
return formattedDate;
|
||||
} catch (e) {
|
||||
// Tangkap kesalahan jika format tanggal tidak sesuai
|
||||
print('Error parsing date: $e');
|
||||
// return 'Format Tanggal Salah';
|
||||
return inputDate;
|
||||
}
|
||||
}
|
||||
|
||||
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: FutureBuilder<Widget>(
|
||||
future: checkFileExistence(
|
||||
'https://devone.aplikasi.web.id/pettycash-media/icon/icon_$icon_category_id.svg'),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return CircularProgressIndicator();
|
||||
} else if (snapshot.hasError) {
|
||||
return Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
);
|
||||
} else {
|
||||
return snapshot.data ?? Container();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
// tengah
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
left: Constant.getActualYPhone(context: context, y: 20),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
icon_category_name,
|
||||
style: Constant.body2_600(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Constant.textBlack,
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(
|
||||
context: context,
|
||||
y: 8,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
amount,
|
||||
style: Constant.body1_600(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Constant.pcBtnBackgroundColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
// kanan
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(
|
||||
right: Constant.getActualYPhone(context: context, y: 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: Constant.bgIconHistory,
|
||||
borderRadius: BorderRadius.all(
|
||||
Radius.circular(6.0),
|
||||
),
|
||||
),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(2.0),
|
||||
child: Text(
|
||||
tipe,
|
||||
style: Constant.body1_600(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Constant.pcBtnBackgroundColor),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
height: Constant.getActualYPhone(
|
||||
context: context,
|
||||
y: 8,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
formatDateString(tglTransaksi),
|
||||
style: Constant.body1_600(context: context).copyWith(
|
||||
fontWeight: FontWeight.w600, color: Constant.textGreyv2),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -6,9 +6,13 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <file_selector_linux/file_selector_plugin.h>
|
||||
#include <url_launcher_linux/url_launcher_plugin.h>
|
||||
|
||||
void fl_register_plugins(FlPluginRegistry* registry) {
|
||||
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||
g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
|
||||
fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
|
||||
url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_linux
|
||||
url_launcher_linux
|
||||
)
|
||||
|
||||
|
||||
@@ -5,10 +5,16 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import file_selector_macos
|
||||
import path_provider_foundation
|
||||
import shared_preferences_foundation
|
||||
import url_launcher_macos
|
||||
import video_player_avfoundation
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
|
||||
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
|
||||
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
|
||||
}
|
||||
|
||||
@@ -1,14 +1,6 @@
|
||||
# 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:
|
||||
@@ -73,6 +65,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.1"
|
||||
cross_file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cross_file
|
||||
sha256: fedaadfa3a6996f75211d835aaeb8fede285dae94262485698afd832371b9a5e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.3+8"
|
||||
crypto:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -81,6 +81,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.3"
|
||||
csslib:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: csslib
|
||||
sha256: "706b5707578e0c1b4b7550f64078f0a0f19dec3f50a178ffae7006b0a9ca58fb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -153,6 +161,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.1"
|
||||
file_selector_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_linux
|
||||
sha256: "045d372bf19b02aeb69cacf8b4009555fb5f6f0b7ad8016e5f46dd1387ddd492"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.2+1"
|
||||
file_selector_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_macos
|
||||
sha256: b15c3da8bd4908b9918111fa486903f5808e388b8d1c559949f584725a6594d6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3+3"
|
||||
file_selector_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_platform_interface
|
||||
sha256: a3994c26f10378a039faa11de174d7b78eb8f79e4dd0af2a451410c1a5c3f66b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.6.2"
|
||||
file_selector_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file_selector_windows
|
||||
sha256: d3547240c20cabf205c7c7f01a50ecdbc413755814d6677f3cb366f04abcead0
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.3+1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@@ -198,14 +238,6 @@ 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
|
||||
@@ -224,6 +256,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: html
|
||||
sha256: "3a7812d5bcd2894edf53dfaf8cd640876cf6cef50a8f238745c8b8120ea74d3a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.15.4"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.2"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -232,6 +280,70 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
image_picker:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: image_picker
|
||||
sha256: "26222b01a0c9a2c8fe02fc90b8208bd3325da5ed1f4a2acabf75939031ac0bdd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.7"
|
||||
image_picker_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_android
|
||||
sha256: "39f2bfe497e495450c81abcd44b62f56c2a36a37a175da7d137b4454977b51b1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.9+3"
|
||||
image_picker_for_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_for_web
|
||||
sha256: e2423c53a68b579a7c37a1eda967b8ae536c3d98518e5db95ca1fe5719a730a3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
image_picker_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_ios
|
||||
sha256: fadafce49e8569257a0cad56d24438a6fa1f0cbd7ee0af9b631f7492818a4ca3
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.8.9+1"
|
||||
image_picker_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_linux
|
||||
sha256: "4ed1d9bb36f7cd60aa6e6cd479779cc56a4cb4e4de8f49d487b1aaad831300fa"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1+1"
|
||||
image_picker_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_macos
|
||||
sha256: "3f5ad1e8112a9a6111c46d0b57a7be2286a9a07fc6e1976fdf5be2bd31d4ff62"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1+1"
|
||||
image_picker_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_platform_interface
|
||||
sha256: fa4e815e6fcada50e35718727d83ba1c92f1edf95c0b4436554cec301b56233b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.9.3"
|
||||
image_picker_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image_picker_windows
|
||||
sha256: "6ad07afc4eb1bc25f3a01084d28520496c4a3bb0cb13685435838167c9dcedeb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1+1"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -272,6 +384,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.0"
|
||||
mime:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: mime
|
||||
sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.4"
|
||||
open_file:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -288,14 +408,30 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.8.3"
|
||||
path_parsing:
|
||||
dependency: transitive
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: path_parsing
|
||||
sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf
|
||||
name: path_provider
|
||||
sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
version: "2.1.2"
|
||||
path_provider_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.2"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_foundation
|
||||
sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
path_provider_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -360,14 +496,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
photo_view:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
|
||||
name: photo_view
|
||||
sha256: "8036802a00bae2a78fc197af8a158e3e2f7b500561ed23b4c458107685e645bb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.4.0"
|
||||
version: "0.14.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -589,30 +725,6 @@ 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:
|
||||
@@ -621,6 +733,46 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
video_player:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: video_player
|
||||
sha256: fbf28ce8bcfe709ad91b5789166c832cb7a684d14f571a81891858fefb5bb1c2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.8.2"
|
||||
video_player_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_android
|
||||
sha256: "7f8f25d7ad56819a82b2948357f3c3af071f6a678db33833b26ec36bbc221316"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.11"
|
||||
video_player_avfoundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_avfoundation
|
||||
sha256: "309e3962795e761be010869bae65c0b0e45b5230c5cee1bec72197ca7db040ed"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.6"
|
||||
video_player_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_platform_interface
|
||||
sha256: "236454725fafcacf98f0f39af0d7c7ab2ce84762e3b63f2cbb3ef9a7e0550bc6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.2.2"
|
||||
video_player_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: video_player_web
|
||||
sha256: "34beb3a07d4331a24f7e7b2f75b8e2b103289038e07e65529699a671b6a6e2cb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -645,14 +797,6 @@ 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.2.0-194.0.dev <4.0.0"
|
||||
flutter: ">=3.10.0"
|
||||
dart: ">=3.2.0 <4.0.0"
|
||||
flutter: ">=3.16.0"
|
||||
|
||||
@@ -50,7 +50,11 @@ dependencies:
|
||||
flutter_multi_formatter: ^2.12.4
|
||||
top_snackbar_flutter: ^3.1.0
|
||||
url_launcher: ^6.1.13
|
||||
flutter_svg: ^2.0.9
|
||||
image_picker: ^1.0.7
|
||||
video_player: ^2.7.2
|
||||
photo_view: ^0.14.0
|
||||
mime: ^1.0.4
|
||||
path_provider: ^2.1.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <file_selector_windows/file_selector_windows.h>
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
#include <url_launcher_windows/url_launcher_windows.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
FileSelectorWindowsRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||
UrlLauncherWindowsRegisterWithRegistrar(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
file_selector_windows
|
||||
permission_handler_windows
|
||||
url_launcher_windows
|
||||
)
|
||||
|
||||