added add siswa and dana sosial

This commit is contained in:
kicap 2023-05-18 18:58:21 +08:00
parent 949474b8ef
commit e0b5213a3b
14 changed files with 519 additions and 161 deletions

View File

@ -1,5 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.panti_asuhan"> package="com.example.panti_asuhan">
<uses-permission android:name="android.permission.INTERNET" />
<application <application
android:label="panti_asuhan" android:label="panti_asuhan"
android:name="${applicationName}" android:name="${applicationName}"

View File

@ -87,7 +87,7 @@ class StackedRouter extends _i1.RouterBase {
}, },
_i5.TambahDanaSosialView: (data) { _i5.TambahDanaSosialView: (data) {
return _i6.MaterialPageRoute<dynamic>( return _i6.MaterialPageRoute<dynamic>(
builder: (context) => _i5.TambahDanaSosialView(), builder: (context) => const _i5.TambahDanaSosialView(),
settings: data, settings: data,
maintainState: false, maintainState: false,
); );

View File

@ -0,0 +1,40 @@
class DanaSosialModel {
String? idDanaSosial;
String? keterangan;
String? jumlah;
String? tanggal;
String? jenis;
String? createdAt;
String? updatedAt;
DanaSosialModel(
{this.idDanaSosial,
this.keterangan,
this.jumlah,
this.tanggal,
this.jenis,
this.createdAt,
this.updatedAt});
DanaSosialModel.fromJson(Map<String, dynamic> json) {
idDanaSosial = json['id_dana_sosial'];
keterangan = json['keterangan'];
jumlah = json['jumlah'];
tanggal = json['tanggal'];
jenis = json['jenis'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id_dana_sosial'] = idDanaSosial;
data['keterangan'] = keterangan;
data['jumlah'] = jumlah;
data['tanggal'] = tanggal;
data['jenis'] = jenis;
data['created_at'] = createdAt;
data['updated_at'] = updatedAt;
return data;
}
}

View File

@ -0,0 +1,80 @@
class SiswaModel {
String? idSiswa;
String? nama;
String? tanggalLahir;
String? jenisKelamin;
String? alamat;
String? kemampuan;
String? imgUrl;
String? createdAt;
String? updatedAt;
String? tempatLahir;
String? noTelpon;
String? agama;
String? kewarganegaraan;
String? pendidikanSd;
String? pendidikanSmp;
String? pendidikanSma;
String? hobi;
SiswaModel(
{this.idSiswa,
this.nama,
this.tanggalLahir,
this.jenisKelamin,
this.alamat,
this.kemampuan,
this.imgUrl,
this.createdAt,
this.updatedAt,
this.tempatLahir,
this.noTelpon,
this.agama,
this.kewarganegaraan,
this.pendidikanSd,
this.pendidikanSmp,
this.pendidikanSma,
this.hobi});
SiswaModel.fromJson(Map<String, dynamic> json) {
idSiswa = json['id_siswa'];
nama = json['nama'];
tanggalLahir = json['tanggal_lahir'];
jenisKelamin = json['jenis_kelamin'];
alamat = json['alamat'];
kemampuan = json['kemampuan'];
imgUrl = json['img_url'];
createdAt = json['created_at'];
updatedAt = json['updated_at'];
tempatLahir = json['tempat_lahir'];
noTelpon = json['no_telpon'];
agama = json['agama'];
kewarganegaraan = json['kewarganegaraan'];
pendidikanSd = json['pendidikan_sd'];
pendidikanSmp = json['pendidikan_smp'];
pendidikanSma = json['pendidikan_sma'];
hobi = json['hobi'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['id_siswa'] = idSiswa;
data['nama'] = nama;
data['tanggal_lahir'] = tanggalLahir;
data['jenis_kelamin'] = jenisKelamin;
data['alamat'] = alamat;
data['kemampuan'] = kemampuan;
data['img_url'] = imgUrl;
data['created_at'] = createdAt;
data['updated_at'] = updatedAt;
data['tempat_lahir'] = tempatLahir;
data['no_telpon'] = noTelpon;
data['agama'] = agama;
data['kewarganegaraan'] = kewarganegaraan;
data['pendidikan_sd'] = pendidikanSd;
data['pendidikan_smp'] = pendidikanSmp;
data['pendidikan_sma'] = pendidikanSma;
data['hobi'] = hobi;
return data;
}
}

View File

@ -7,8 +7,8 @@ class MyHttpServices {
final log = getLogger('MyHttpServices'); final log = getLogger('MyHttpServices');
final _options = BaseOptions( final _options = BaseOptions(
baseUrl: dotenv.env['api_url']!, baseUrl: dotenv.env['api_url']!,
connectTimeout: const Duration(seconds: 60), connectTimeout: const Duration(seconds: 120),
receiveTimeout: const Duration(seconds: 60), receiveTimeout: const Duration(seconds: 120),
); );
late Dio _dio; late Dio _dio;

View File

@ -0,0 +1,11 @@
class OtherFunction {
int umur(String tanggalLahir) {
// change tanggalLahir to DateTime
DateTime date = DateTime.parse(tanggalLahir);
// get current date
DateTime now = DateTime.now();
// get difference in year
int year = now.year - date.year;
return year;
}
}

View File

@ -101,16 +101,6 @@ class AddSiswaDialogView extends StatelessWidget {
], ],
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
MyTextFormField(
labelText: 'NIS',
controller: model.nisController,
keyboardType: TextInputType.number,
validator: Validatorless.multiple([
Validatorless.required('NIS tidak boleh kosong'),
Validatorless.number('NIS harus angka'),
]),
),
const SizedBox(height: 10),
MyTextFormField( MyTextFormField(
labelText: 'Nama', labelText: 'Nama',
controller: model.namaController, controller: model.namaController,
@ -128,6 +118,14 @@ class AddSiswaDialogView extends StatelessWidget {
model.changeDate(context); model.changeDate(context);
}, },
), ),
const SizedBox(height: 10),
MyTextFormField(
labelText: 'Tempat Lahir',
controller: model.tempatLahirController,
validator: Validatorless.required(
'Tempat lahir tidak boleh kosong'),
),
const SizedBox(height: 10), const SizedBox(height: 10),
// create dropdown button // create dropdown button
Container( Container(
@ -164,6 +162,36 @@ class AddSiswaDialogView extends StatelessWidget {
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
MyTextFormField(
labelText: 'No. Telepon',
controller: model.noTelponController,
keyboardType: TextInputType.number,
validator: Validatorless.multiple(
[
Validatorless.required(
'No. telepon tidak boleh kosong'),
Validatorless.number(
'No. telepon harus berupa angka'),
],
),
),
const SizedBox(height: 10),
MyTextFormField(
labelText: 'Agama',
controller: model.agamaController,
keyboardType: TextInputType.emailAddress,
validator:
Validatorless.required('Agama tidak boleh kosong'),
),
const SizedBox(height: 10),
MyTextFormField(
labelText: 'Kewarganegaraan',
controller: model.kewarganegaraanController,
keyboardType: TextInputType.emailAddress,
validator: Validatorless.required(
'Kewarganegaraan tidak boleh kosong'),
),
const SizedBox(height: 10),
MyTextFormField( MyTextFormField(
labelText: 'Alamat', labelText: 'Alamat',
controller: model.alamatController, controller: model.alamatController,
@ -173,11 +201,40 @@ class AddSiswaDialogView extends StatelessWidget {
), ),
const SizedBox(height: 10), const SizedBox(height: 10),
MyTextFormField( MyTextFormField(
labelText: 'Keahlian', labelText: 'Pendidikan SD',
controller: model.keahlianController, controller: model.pendidikanSDController,
validator: Validatorless.required(
'Pendidikan SD tidak boleh kosong'),
),
const SizedBox(height: 10),
MyTextFormField(
labelText: 'Pendidikan SMP',
controller: model.pendidikanSMPController,
validator: Validatorless.required(
'Pendidikan SMP tidak boleh kosong'),
),
const SizedBox(height: 10),
MyTextFormField(
labelText: 'Pendidikan SMA',
controller: model.pendidikanSMAController,
validator: Validatorless.required(
'Pendidikan SMA tidak boleh kosong'),
),
const SizedBox(height: 10),
MyTextFormField(
labelText: 'Kemampuan',
controller: model.kemampuanController,
maxLines: 4, maxLines: 4,
validator: Validatorless.required( validator: Validatorless.required(
'Keahlian tidak boleh kosong'), 'Kemampuan tidak boleh kosong'),
),
const SizedBox(height: 10),
MyTextFormField(
labelText: "Hobi",
controller: model.hobiController,
maxLines: 4,
validator:
Validatorless.required('Hobi tidak boleh kosong'),
), ),
Row( Row(
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
@ -200,13 +257,13 @@ class AddSiswaDialogView extends StatelessWidget {
if (model.formKey.currentState!.validate()) { if (model.formKey.currentState!.validate()) {
bool res = await model.postData(); bool res = await model.postData();
model.log.i("res: $res"); model.log.i("res: $res");
// if (res) { if (res) {
// completer( completer(
// DialogResponse( DialogResponse(
// confirmed: true, confirmed: true,
// ), ),
// ); );
// } }
} }
}, },
child: const Text( child: const Text(

View File

@ -4,10 +4,10 @@ import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_holo_date_picker/flutter_holo_date_picker.dart'; import 'package:flutter_holo_date_picker/flutter_holo_date_picker.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:panti_asuhan/app/app.locator.dart';
import 'package:panti_asuhan/app/core/custom_base_view_model.dart';
import '../../../../../app/app.locator.dart';
import '../../../../../app/app.logger.dart'; import '../../../../../app/app.logger.dart';
import '../../../../../app/core/custom_base_view_model.dart';
import '../../../../../services/http_services.dart'; import '../../../../../services/http_services.dart';
import '../../../../../services/my_easyloading.dart'; import '../../../../../services/my_easyloading.dart';
@ -28,11 +28,18 @@ class AddSiswaDialogViewModel extends CustomBaseViewModel {
// form and text controller // form and text controller
final formKey = GlobalKey<FormState>(); final formKey = GlobalKey<FormState>();
TextEditingController nisController = TextEditingController();
TextEditingController namaController = TextEditingController(); TextEditingController namaController = TextEditingController();
TextEditingController tanggalLahirController = TextEditingController(); TextEditingController tanggalLahirController = TextEditingController();
TextEditingController tempatLahirController = TextEditingController();
TextEditingController alamatController = TextEditingController(); TextEditingController alamatController = TextEditingController();
TextEditingController keahlianController = TextEditingController(); TextEditingController noTelponController = TextEditingController();
TextEditingController agamaController = TextEditingController();
TextEditingController kewarganegaraanController = TextEditingController();
TextEditingController pendidikanSDController = TextEditingController();
TextEditingController pendidikanSMPController = TextEditingController();
TextEditingController pendidikanSMAController = TextEditingController();
TextEditingController kemampuanController = TextEditingController();
TextEditingController hobiController = TextEditingController();
Future<void> init() async {} Future<void> init() async {}
@ -79,12 +86,19 @@ class AddSiswaDialogViewModel extends CustomBaseViewModel {
easyLoading.customLoading('Menambahkan data...'); easyLoading.customLoading('Menambahkan data...');
try { try {
var formData = FormData.fromMap({ var formData = FormData.fromMap({
'nis': nisController.text,
'nama': namaController.text, 'nama': namaController.text,
'jenis_kelamin': jenisKelamin, 'jenis_kelamin': jenisKelamin,
'tanggal_lahir': tanggalLahirController.text, 'tanggal_lahir': tanggalLahirController.text,
'tempat_lahir': tempatLahirController.text,
'alamat': alamatController.text, 'alamat': alamatController.text,
'keahlian': keahlianController.text, 'no_telpon': noTelponController.text,
'agama': agamaController.text,
'kewarganegaraan': kewarganegaraanController.text,
'pendidikan_sd': pendidikanSDController.text,
'pendidikan_smp': pendidikanSMPController.text,
'pendidikan_sma': pendidikanSMAController.text,
'kemampuan': kemampuanController.text,
'hobi': hobiController.text,
'foto': await MultipartFile.fromFile(_imagePath!), 'foto': await MultipartFile.fromFile(_imagePath!),
}); });

View File

@ -88,22 +88,47 @@ class DanaSosialAdminView extends StatelessWidget {
), ),
], ],
), ),
child: ListView.builder( child: (model.danaSosialModelList.isEmpty)
? Center(
child: Text(
'Tidak ada data',
style: boldTextStyle.copyWith(
fontSize: 20,
),
),
)
: ListView.builder(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 10), horizontal: 15, vertical: 10),
itemCount: 20, itemCount: model.danaSosialModelList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return Card( return Card(
child: GestureDetector(
onTap: () {
model.log.i('Card $index tapped');
},
child: ListTile( child: ListTile(
title: Text('1/02/15 - 10.00 am', title: Text(
model.danaSosialModelList[index].tanggal ??
'',
style: boldTextStyle.copyWith( style: boldTextStyle.copyWith(
fontSize: 13, color: mainColor)), fontSize: 13, color: mainColor)),
subtitle: Text('Progress $index'), subtitle: Text(
trailing: Text('Pembangunan $index'), 'Rp. ${model.danaSosialModelList[index].jumlah}',
style: regularTextStyle.copyWith(
fontSize: 13, color: mainColor)),
trailing: Container(
width: 50,
height: 50,
decoration: BoxDecoration(
color: mainColor,
borderRadius: BorderRadius.circular(50),
),
child: IconButton(
onPressed: () {
// model.goToTambahDanaSosial();
},
icon: const Icon(
Icons.edit,
color: Colors.white,
),
),
), ),
), ),
); );

View File

@ -1,10 +1,48 @@
import '../../../../app/app.locator.dart';
import '../../../../app/app.logger.dart'; import '../../../../app/app.logger.dart';
import '../../../../app/app.router.dart'; import '../../../../app/app.router.dart';
import '../../../../app/core/custom_base_view_model.dart'; import '../../../../app/core/custom_base_view_model.dart';
import '../../../../model/dana_sosial_model.dart';
import '../../../../services/http_services.dart';
import '../../../../services/my_easyloading.dart';
class DanaSosialAdminViewModel extends CustomBaseViewModel { class DanaSosialAdminViewModel extends CustomBaseViewModel {
final log = getLogger('DanaSosialAdminViewModel'); final log = getLogger('DanaSosialAdminViewModel');
Future<void> init() async {} final _httpService = locator<MyHttpServices>();
final easyLoading = locator<MyEasyLoading>();
List<DanaSosialModel> danaSosialModelList = [];
Future<void> init() async {
await getData();
}
getData() async {
setBusy(true);
easyLoading.showLoading();
try {
var response = await _httpService.get('dana_sosial');
log.i(response.data);
danaSosialModelList = [];
var datanya = response.data['data'];
// log.i(datanya.length);
if (datanya.length > 0) {
for (var item in datanya) {
danaSosialModelList.add(DanaSosialModel.fromJson(item));
}
}
setBusy(false);
notifyListeners();
log.i(danaSosialModelList);
} catch (e) {
log.e(e);
setBusy(false);
} finally {
easyLoading.dismissLoading();
}
}
goToTambahDanaSosial() { goToTambahDanaSosial() {
navigationService.navigateTo(Routes.tambahDanaSosialView); navigationService.navigateTo(Routes.tambahDanaSosialView);

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:panti_asuhan/services/other_function.dart';
import 'package:stacked/stacked.dart'; import 'package:stacked/stacked.dart';
import '../../../../app/themes/app_colors.dart'; import '../../../../app/themes/app_colors.dart';
@ -75,21 +76,29 @@ class DataSiswaView extends StatelessWidget {
), ),
], ],
), ),
child: ListView.builder( child: (model.siswaModelList.isEmpty)
? Center(
child: Text(
'Tidak ada data',
style: boldTextStyle.copyWith(
fontSize: 20,
),
),
)
: // ListView.builder(
ListView.builder(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 15, vertical: 10), horizontal: 15, vertical: 10),
itemCount: 20, itemCount: model.siswaModelList.length,
itemBuilder: (context, index) { itemBuilder: (context, index) {
return Card( return Card(
child: GestureDetector(
onTap: () {
model.log.i('Card $index tapped');
},
child: ListTile( child: ListTile(
title: Text('Namanya', title: Text(
model.siswaModelList[index].nama ?? '',
style: boldTextStyle.copyWith( style: boldTextStyle.copyWith(
fontSize: 13, color: mainColor)), fontSize: 13, color: mainColor)),
subtitle: Text('Umurnya : $index'), subtitle: Text(
'Umur : ${OtherFunction().umur(model.siswaModelList[index].tanggalLahir ?? '')}'),
// circle avatar // circle avatar
trailing: Container( trailing: Container(
width: 50, width: 50,
@ -103,7 +112,6 @@ class DataSiswaView extends StatelessWidget {
color: Colors.white, color: Colors.white,
), ),
)), )),
),
); );
}, },
), ),

View File

@ -1,12 +1,49 @@
import 'package:panti_asuhan/app/core/custom_base_view_model.dart';
import '../../../../app/app.dialogs.dart'; import '../../../../app/app.dialogs.dart';
import '../../../../app/app.locator.dart';
import '../../../../app/app.logger.dart'; import '../../../../app/app.logger.dart';
import '../../../../app/core/custom_base_view_model.dart';
import '../../../../model/siswa_model.dart';
import '../../../../services/http_services.dart';
import '../../../../services/my_easyloading.dart';
import '../add_siswa_dialog/add_siswa_dialog/add_siswa_dialog_view.dart'; import '../add_siswa_dialog/add_siswa_dialog/add_siswa_dialog_view.dart';
class DataSiswaViewModel extends CustomBaseViewModel { class DataSiswaViewModel extends CustomBaseViewModel {
final log = getLogger('DataSiswaViewModel'); final log = getLogger('DataSiswaViewModel');
Future<void> init() async {} final _httpService = locator<MyHttpServices>();
final easyLoading = locator<MyEasyLoading>();
List<SiswaModel> siswaModelList = [];
Future<void> init() async {
await getData();
}
getData() async {
setBusy(true);
easyLoading.showLoading();
try {
var response = await _httpService.get('siswa');
log.i(response.data);
siswaModelList = [];
var datanya = response.data['data'];
// log.i(datanya.length);
if (datanya.length > 0) {
for (var item in datanya) {
siswaModelList.add(SiswaModel.fromJson(item));
}
}
setBusy(false);
notifyListeners();
log.i(siswaModelList);
} catch (e) {
log.e(e);
setBusy(false);
} finally {
easyLoading.dismissLoading();
}
}
void addSiswa() async { void addSiswa() async {
final res = await dialogService.showCustomDialog( final res = await dialogService.showCustomDialog(
@ -15,5 +52,7 @@ class DataSiswaViewModel extends CustomBaseViewModel {
); );
if (res?.confirmed != true) return; if (res?.confirmed != true) return;
siswaModelList = [];
await getData();
} }
} }

View File

@ -40,6 +40,7 @@ class TambahDanaSosialView extends StatelessWidget {
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 15), padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 15),
child: Form( child: Form(
key: model.formKey, key: model.formKey,
child: SingleChildScrollView(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -79,6 +80,7 @@ class TambahDanaSosialView extends StatelessWidget {
MyTextFormField( MyTextFormField(
hintText: 'Tanggal', hintText: 'Tanggal',
readOnly: true, readOnly: true,
controller: model.tanggalController,
validator: Validatorless.required( validator: Validatorless.required(
'Tanggal lahir tidak boleh kosong'), 'Tanggal lahir tidak boleh kosong'),
onTap: () { onTap: () {
@ -120,13 +122,19 @@ class TambahDanaSosialView extends StatelessWidget {
const SizedBox(height: 20), const SizedBox(height: 20),
MyButton( MyButton(
text: "Simpan", text: "Simpan",
onPressed: () {}, onPressed: () {
if (model.formKey.currentState!.validate()) {
model.log.i('Form Valid');
model.addData();
}
},
), ),
], ],
), ),
), ),
), ),
), ),
),
); );
}, },
); );

View File

@ -1,7 +1,18 @@
import 'package:dio/dio.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:panti_asuhan/app/core/custom_base_view_model.dart';
import '../../../app/app.locator.dart';
import '../../../app/app.logger.dart';
import '../../../app/app.router.dart';
import '../../../app/core/custom_base_view_model.dart';
import '../../../services/http_services.dart';
import '../../../services/my_easyloading.dart';
class TambahDanaSosialViewModel extends CustomBaseViewModel { class TambahDanaSosialViewModel extends CustomBaseViewModel {
final log = getLogger('TambahDanaSosialViewModel');
final _httpService = locator<MyHttpServices>();
final easyLoading = locator<MyEasyLoading>();
String jenisDana = 'Pemasukan'; String jenisDana = 'Pemasukan';
List<String> jenisDanaList = ['Pemasukan', 'Pengeluaran']; List<String> jenisDanaList = ['Pemasukan', 'Pengeluaran'];
@ -28,4 +39,30 @@ class TambahDanaSosialViewModel extends CustomBaseViewModel {
tanggalController.text = date; tanggalController.text = date;
} }
} }
void addData() async {
easyLoading.customLoading('Menambahkan data...');
try {
var formData = FormData.fromMap({
'jenis': jenisDana,
'keterangan': ketController.text,
'jumlah': jumlahController.text,
'tanggal': tanggalController.text,
});
var response =
await _httpService.postWithFormData('dana_sosial', formData);
log.i(response.data);
easyLoading.showSuccess(" Data berhasil ditambahkan");
navigationService.navigateTo(Routes.adminIndexTrackingView);
} catch (e) {
log.e(e);
snackbarService.showSnackbar(
message: 'Gagal menambahkan data',
title: 'Error',
duration: const Duration(seconds: 4),
);
} finally {
easyLoading.dismissLoading();
}
}
} }