step 7 : ui login, transaksi, user sesuai wireframe

This commit is contained in:
sindhu
2024-01-15 12:10:15 +07:00
parent 71085788cd
commit 95df7d4c5b
13 changed files with 1151 additions and 303 deletions

View File

@@ -1,9 +1,13 @@
import 'package:app_petty_cash/app/app_extension.dart';
import 'package:dropdown_button2/dropdown_button2.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:intl/intl.dart';
import '../../app/constant.dart';
import '../../widget/custom_drawer.dart';
import '../login/custom_text_field.dart';
class DummyDropdownTipe {
@@ -30,6 +34,18 @@ class TransaksiScreen extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final ctrlJumlah = useTextEditingController(text: "");
final ctrlCatatan = useTextEditingController(text: "");
final ctrlNamaPengirim = useTextEditingController(text: "");
String formattedDate = DateFormat('dd-MM-yyyy').format(DateTime.now());
// final ctrlTglAwal = useTextEditingController(
// text: DateTime.now().toString().split(' ')[0],
// );
final ctrlTglAwal = useTextEditingController(text: formattedDate);
final tglAwal = useState<DateTime>(DateTime.now());
final tglAwalTmp = useState<String>("");
final selectedDropdownKategori = useState<DummyDropdownTipe>(
DummyDropdownTipe(
@@ -58,244 +74,509 @@ class TransaksiScreen extends HookConsumerWidget {
selectedDropdownKategori.value = dropdownItemsKategori.value[0];
radioButtonItems.value = [
DummyRadioTipe(
"Debit",
"Income",
1,
),
DummyRadioTipe(
"Kredit",
"Expenses",
2,
),
];
selectedRadio.value = radioButtonItems.value[0];
return () {};
}, []);
final isMounted = useIsMounted();
return Scaffold(
appBar: AppBar(
title: Text('Transaksi'),
var sbHeight = MediaQuery.of(context).padding.top;
print('Height : ${sbHeight}');
return Padding(
padding: EdgeInsets.only(
top: Constant.getActualYPhone(context: context, y: 30),
),
body: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Kategori',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 10),
),
// Dropdown kategori
SizedBox(
width: Constant.getActualXPhone(context: context, x: 390),
child: DropdownButtonHideUnderline(
child: DropdownButton2<DummyDropdownTipe>(
isExpanded: true,
hint: Row(
children: [
Expanded(
child: Text(
'Select Item',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600,
color: Constant.textBlack),
overflow: TextOverflow.ellipsis,
),
),
],
),
items: dropdownItemsKategori.value
.map((DummyDropdownTipe option) {
return DropdownMenuItem<DummyDropdownTipe>(
value: option,
child: Text(
option.options,
style: Constant.body1(context: context).copyWith(
color: Constant.textBlack,
fontWeight: FontWeight.w600),
),
);
}).toList(),
value: selectedDropdownKategori.value,
onChanged: (DummyDropdownTipe? newValue) {
// if (newValue) {
selectedDropdownKategori.value = newValue!;
print(selectedDropdownKategori.value.id);
// }
},
buttonStyleData: ButtonStyleData(
height: Constant.getActualY(context: context, y: 56),
width: Constant.getActualX(context: context, x: 320),
padding: EdgeInsets.only(
left: Constant.getActualX(context: context, x: 10),
right: Constant.getActualX(context: context, x: 10),
),
decoration: BoxDecoration(
color: Constant.white,
border: Border.all(color: Constant.textBlack, width: 1),
borderRadius: BorderRadius.circular(8),
),
elevation: 2,
),
iconStyleData: IconStyleData(
icon: Icon(
Icons.keyboard_arrow_down_outlined,
),
iconSize: 24,
iconEnabledColor: Constant.textBlack,
iconDisabledColor: Colors.grey,
),
dropdownStyleData: DropdownStyleData(
maxHeight: Constant.getActualY(context: context, y: 200),
// width: Constant.getActualX(context: context, x: 320),
padding: EdgeInsets.only(
top: Constant.getActualY(context: context, y: 10),
left: Constant.getActualX(context: context, x: 10),
right: Constant.getActualX(context: context, x: 10),
bottom: Constant.getActualY(context: context, y: 10),
),
decoration: BoxDecoration(
color: Constant.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: 20.0,
spreadRadius: 2.0,
offset: Offset(0.0, 0.0),
),
],
),
elevation: 8,
offset: const Offset(0, -10),
scrollbarTheme: ScrollbarThemeData(
radius: const Radius.circular(40),
thickness: MaterialStateProperty.all<double>(6),
thumbVisibility: MaterialStateProperty.all<bool>(true),
),
),
menuItemStyleData: MenuItemStyleData(
height: Constant.getActualY(context: context, y: 56),
padding: EdgeInsets.only(
top: Constant.getActualY(context: context, y: 10),
left: Constant.getActualX(context: context, x: 10),
right: Constant.getActualX(context: context, x: 10),
),
),
child: Scaffold(
appBar: AppBar(
// centerTitle: true,
title: Text('Transaksi'),
),
drawer: CustomDrawer(),
body: SafeArea(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Tanggal Transaksi',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
// jenis
Text(
'Jenis',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 10),
),
SizedBox(
width: Constant.getActualXPhone(context: context, x: 340),
height: Constant.getActualYPhone(context: context, y: 36),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (radioButtonItems.value.isEmpty)
Text('Radio Button Empty')
else
for (var i = 0; i < radioButtonItems.value.length; i++)
Padding(
padding: const EdgeInsets.only(right: 20),
child: Row(
children: [
Radio<DummyRadioTipe>(
activeColor: Constant.confirmed,
value: radioButtonItems.value[i],
groupValue: selectedRadio.value,
onChanged: (DummyRadioTipe? index) {
if (isMounted()) {
selectedRadio.value = index!;
} else {
return;
}
},
SizedBox(
height: Constant.getActualYPhone(context: context, y: 10),
),
// Tanggal Transaksi
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(
color: Colors.orange,
width: 1,
),
Text(
radioButtonItems.value[i].text,
style:
Constant.body1(context: context).copyWith(
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
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),
),
// Kategori
Text(
'Kategori',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 10),
),
// Dropdown kategori
SizedBox(
width: Constant.getActualXPhone(context: context, x: 390),
child: DropdownButtonHideUnderline(
child: DropdownButton2<DummyDropdownTipe>(
isExpanded: true,
hint: Row(
children: [
Expanded(
child: Text(
'Select Item',
style: Constant.body1(context: context)
.copyWith(
fontWeight: FontWeight.w600,
color: Constant.textBlack),
overflow: TextOverflow.ellipsis,
),
),
],
),
items: dropdownItemsKategori.value
.map((DummyDropdownTipe option) {
return DropdownMenuItem<DummyDropdownTipe>(
value: option,
child: Text(
option.options,
style: Constant.body1(context: context).copyWith(
color: Constant.textBlack,
fontWeight: FontWeight.w400,
),
fontWeight: FontWeight.w600),
),
);
}).toList(),
value: selectedDropdownKategori.value,
onChanged: (DummyDropdownTipe? newValue) {
// if (newValue) {
selectedDropdownKategori.value = newValue!;
print(selectedDropdownKategori.value.id);
// }
},
buttonStyleData: ButtonStyleData(
height: Constant.getActualY(context: context, y: 56),
width: Constant.getActualX(context: context, x: 320),
padding: EdgeInsets.only(
left: Constant.getActualX(context: context, x: 10),
right: Constant.getActualX(context: context, x: 10),
),
decoration: BoxDecoration(
color: Constant.white,
border:
Border.all(color: Constant.textBlack, width: 1),
borderRadius: BorderRadius.circular(8),
),
elevation: 2,
),
iconStyleData: IconStyleData(
icon: Icon(
Icons.keyboard_arrow_down_outlined,
),
iconSize: 24,
iconEnabledColor: Constant.textBlack,
iconDisabledColor: Colors.grey,
),
dropdownStyleData: DropdownStyleData(
maxHeight:
Constant.getActualY(context: context, y: 200),
// width: Constant.getActualX(context: context, x: 320),
padding: EdgeInsets.only(
top: Constant.getActualY(context: context, y: 10),
left: Constant.getActualX(context: context, x: 10),
right: Constant.getActualX(context: context, x: 10),
bottom:
Constant.getActualY(context: context, y: 10),
),
decoration: BoxDecoration(
color: Constant.white,
borderRadius: BorderRadius.circular(8),
boxShadow: [
BoxShadow(
color: Colors.grey,
blurRadius: 20.0,
spreadRadius: 2.0,
offset: Offset(0.0, 0.0),
),
],
),
elevation: 8,
offset: const Offset(0, -10),
scrollbarTheme: ScrollbarThemeData(
radius: const Radius.circular(40),
thickness: MaterialStateProperty.all<double>(6),
thumbVisibility:
MaterialStateProperty.all<bool>(true),
),
),
],
menuItemStyleData: MenuItemStyleData(
height: Constant.getActualY(context: context, y: 56),
padding: EdgeInsets.only(
top: Constant.getActualY(context: context, y: 10),
left: Constant.getActualX(context: context, x: 10),
right: Constant.getActualX(context: context, x: 10),
),
),
),
),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
Text(
'Nama Pengirim',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 10),
),
TextField(
controller: ctrlNamaPengirim,
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: "Nama Pengirim",
// hintText: 'Nama Pengirim',
),
),
// CustomTextField(
// isNumber: false,
// isReadOnly: false,
// ctrl: ctrlNamaPengirim,
// isPassword: false,
// isMaxLine: false,
// hintText: "Nama Pengirim",
// labelText: "Nama Pengirim",
// // onChange: (String searchResult) {},
// isPrefix: false,
// ),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
// jenis
Text(
'Jenis',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 10),
),
SizedBox(
width: Constant.getActualXPhone(context: context, x: 340),
height: Constant.getActualYPhone(context: context, y: 36),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
if (radioButtonItems.value.isEmpty)
Text('Radio Button Empty')
else
for (var i = 0;
i < radioButtonItems.value.length;
i++)
Padding(
padding: const EdgeInsets.only(right: 20),
child: Row(
children: [
Radio<DummyRadioTipe>(
activeColor: Constant.confirmed,
value: radioButtonItems.value[i],
groupValue: selectedRadio.value,
onChanged: (DummyRadioTipe? index) {
if (isMounted()) {
selectedRadio.value = index!;
} else {
return;
}
},
),
Text(
radioButtonItems.value[i].text,
style: Constant.body1(context: context)
.copyWith(
color: Constant.textBlack,
fontWeight: FontWeight.w400,
),
),
],
),
),
],
),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
// jumlah
Text(
'Jumlah',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
TextField(
controller: ctrlJumlah,
keyboardType: TextInputType.number,
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: "Jumlah",
// hintText: 'Jumlah',
),
),
// CustomTextField(
// isNumber: true,
// isReadOnly: false,
// ctrl: ctrlJumlah,
// isPassword: false,
// isMaxLine: false,
// hintText: "Jumlah",
// labelText: "Jumlah",
// // onChange: (String searchResult) {},
// isPrefix: false,
// ),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
// catatan
Text(
'Catatan',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
TextField(
controller: ctrlCatatan,
maxLines: 4,
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: "Catatan",
// hintText: 'Catatan',
),
),
// CustomTextField(
// isNumber: false,
// isReadOnly: false,
// ctrl: ctrlCatatan,
// isPassword: false,
// isMaxLine: true,
// isTextArea: true,
// hintText: "Catatan",
// labelText: "Catatan",
// // onChange: (String searchResult) {},
// isPrefix: false,
// ),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
// Upload File
Container(
width: Constant.getActualXPhone(context: context, x: 336),
height: Constant.getActualYPhone(context: context, y: 83),
decoration: BoxDecoration(color: Constant.bgUploadFile),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
Icons.upload_outlined,
),
Text(
'Upload File',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600,
color: Constant.textBlack),
)
],
),
),
],
),
),
),
),
bottomNavigationBar: 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: 10),
),
child: BottomAppBar(
child: Container(
width: Constant.getActualXPhone(context: context, x: 336),
height: Constant.getActualYPhone(context: context, y: 42),
child: ElevatedButton(
child: Text(
'Simpan',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
onPressed: () {},
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
// jumlah
Text(
'Jumlah',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
CustomTextField(
isNumber: true,
isReadOnly: false,
ctrl: ctrlJumlah,
isPassword: false,
isMaxLine: false,
hintText: "Jumlah",
labelText: "Jumlah",
// onChange: (String searchResult) {},
isPrefix: false,
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
// catatan
Text(
'Catatan',
style: Constant.body1(context: context).copyWith(
fontWeight: FontWeight.w600, color: Constant.textBlack),
),
SizedBox(
height: Constant.getActualYPhone(context: context, y: 20),
),
CustomTextField(
isNumber: false,
isReadOnly: false,
ctrl: ctrlCatatan,
isPassword: false,
isMaxLine: true,
isTextArea: true,
hintText: "Catatan",
labelText: "Catatan",
// onChange: (String searchResult) {},
isPrefix: false,
),
],
),
),
),
),