complete admin, mandor and user page

This commit is contained in:
kicap
2023-11-03 23:24:23 +08:00
parent 4cc9967ab8
commit 8eacfa6dee
41 changed files with 1335 additions and 492 deletions

View File

@ -1,10 +1,12 @@
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:native_video_player/native_video_player.dart';
import 'package:perumahan_bew/app/themes/app_text.dart';
import 'package:perumahan_bew/ui/widgets/my_button.dart';
import 'package:perumahan_bew/ui/widgets/my_textformfield.dart';
import 'package:stacked/stacked.dart';
import 'package:stacked_services/stacked_services.dart';
import 'package:url_launcher/url_launcher.dart';
import 'package:validatorless/validatorless.dart';
import '../../../app/themes/app_colors.dart';
@ -70,7 +72,7 @@ class TambahLihatProgressBottomSheetView extends StatelessWidget {
children: [
Center(
child: Text(
'${request!.title!} ${request!.data.toString().toUpperCase()}',
'${request!.title!} ${request!.data['idPerumahan'].toString().toUpperCase()}',
style: boldTextStyle,
),
),
@ -94,8 +96,8 @@ class TambahLihatProgressBottomSheetView extends StatelessWidget {
borderRadius:
BorderRadius.circular(10),
child: GestureDetector(
onTap: () =>
model.showImage(context),
onTap: () => model.showImage(
context, 'file', null),
child: Image.memory(
model.imageVideoBytes!,
fit: BoxFit.fill,
@ -139,30 +141,123 @@ class TambahLihatProgressBottomSheetView extends StatelessWidget {
),
),
))
: const Icon(
Icons.credit_card_rounded,
color: Colors.white,
size: 50,
),
: (model.progressModel != null
? (model.imageVideoType == 'image'
? ClipRRect(
borderRadius:
BorderRadius.circular(10),
child: GestureDetector(
onTap: () => model.showImage(
context,
'network',
dotenv.env['url']! +
model.progressModel!
.img!),
child: Image.network(
dotenv.env['url']! +
model.progressModel!
.img!,
fit: BoxFit.fill,
)),
)
: ClipRRect(
borderRadius:
BorderRadius.circular(10),
child: AspectRatio(
aspectRatio: 16 / 11,
child: NativeVideoPlayerView(
onViewReady:
(controller) async {
final videoSource =
await VideoSource.init(
path: dotenv.env['url']! +
model.progressModel!
.img!,
type: VideoSourceType
.network,
);
await controller
.loadVideoSource(
videoSource);
model.nativeVideoPlayerController =
controller;
model.notifyListeners();
model
.nativeVideoPlayerController!
.play();
// loop video
model
.nativeVideoPlayerController!
.onPlaybackEnded
.addListener(() {
model
.nativeVideoPlayerController!
.seekTo(0);
model
.nativeVideoPlayerController!
.play();
});
},
),
),
))
: const Icon(
Icons.credit_card_rounded,
color: Colors.white,
size: 50,
)),
),
Positioned(
bottom: 0,
right: 0,
child: CircleAvatar(
radius: 15,
backgroundColor: sixthGrey,
child: IconButton(
onPressed: () {
model.pilihImageVideo();
},
icon: const Icon(
Icons.add,
color: backgroundColor3,
size: 15,
if (model.progressModel == null)
Positioned(
bottom: 0,
right: 0,
child: CircleAvatar(
radius: 15,
backgroundColor: sixthGrey,
child: IconButton(
onPressed: () {
model.pilihImageVideo();
},
icon: const Icon(
Icons.add,
color: backgroundColor3,
size: 15,
),
),
),
),
if (model.imageVideoType == 'video')
Positioned(
bottom: 0,
left: 0,
top: 0,
right: 0,
child: Container(
alignment: Alignment.center,
child: CircleAvatar(
radius: 15,
backgroundColor: sixthGrey,
child: IconButton(
onPressed: () {
if (model.progressModel != null) {
model.playVideo(
'network',
dotenv.env['url']! +
model.progressModel!.img!);
} else {
model.playVideo(
'file', model.imageVideoPath);
}
},
icon: const Icon(
Icons.play_arrow,
color: backgroundColor3,
size: 15,
),
),
),
),
),
),
],
),
),
@ -174,54 +269,140 @@ class TambahLihatProgressBottomSheetView extends StatelessWidget {
controller: model.ketController,
validator:
Validatorless.required('Keterangan harus diisi'),
readOnly: model.progressModel != null,
),
const SizedBox(height: 20),
Center(
child: SizedBox(
width: 250,
child: MyButton(
text: 'Tambah Progress',
onPressed: () {
if (model.imageVideoBytes == null) {
model.snackbarService.showSnackbar(
message: 'Gambar/video harus diisi',
);
model.pilihImageVideo();
return;
}
if (model.progressModel != null)
MyTextFormField(
labelText: 'Waktu',
controller: model.waktuController,
readOnly: true,
),
if (model.progressModel == null)
Center(
child: SizedBox(
width: 250,
child: MyButton(
text: 'Tambah Progress',
onPressed: () {
if (model.imageVideoBytes == null) {
model.snackbarService.showSnackbar(
message: 'Gambar/video harus diisi',
);
model.pilihImageVideo();
return;
}
if (model.globalKey.currentState!.validate()) {
model.dialogService
.showDialog(
title: 'Tambah Progress',
description: 'Apakah anda yakin?',
buttonTitle: 'Ya',
cancelTitle: 'Tidak',
)
.then((value) async {
if (value!.confirmed) {
// stop playing video
model.nativeVideoPlayerController?.pause();
model.nativeVideoPlayerController
?.removeListener(() {
// model.nativeVideoPlayerController?.dispose();
if (model.globalKey.currentState!.validate()) {
model.dialogService
.showDialog(
title: 'Tambah Progress',
description: 'Apakah anda yakin?',
buttonTitle: 'Ya',
cancelTitle: 'Tidak',
)
.then((value) async {
if (value!.confirmed) {
// stop playing video
model.nativeVideoPlayerController
?.pause();
model.nativeVideoPlayerController
?.removeListener(() {
// model.nativeVideoPlayerController?.dispose();
model.nativeVideoPlayerController =
null;
});
model.nativeVideoPlayerController = null;
});
model.nativeVideoPlayerController = null;
// add progress
bool res = await model.tambahProgress();
model.log.i('res: $res');
completer!(SheetResponse(
confirmed: true,
));
}
});
}
},
// add progress
bool res = await model.tambahProgress();
model.log.i('res: $res');
completer!(SheetResponse(
confirmed: true,
));
}
});
}
},
),
),
),
),
if (model.level == 'Pemilik Rumah' &&
model.mandorModel != null)
Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 20),
MyTextFormField(
labelText: 'Mandor',
controller: model.mandorController,
readOnly: true,
),
const SizedBox(height: 20),
MyTextFormField(
labelText: 'No. Telp Mandor',
controller: model.noHpController,
readOnly: true,
),
const SizedBox(height: 20),
// create row with 2 rounded icon , one is chat whatsapp , one is call
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircleAvatar(
radius: 15,
backgroundColor: greenColor,
child: IconButton(
onPressed: () async {
// model.openWhatsapp();
String noTelpon =
model.noHpController!.text;
// convert the number to international format
noTelpon = noTelpon.replaceAll(
RegExp(r'[^0-9]'), '');
noTelpon = '62${noTelpon.substring(1)}';
// log.i('no_telpon: $noTelpon');
final url =
Uri.parse('https://wa.me/$noTelpon');
if (!await launchUrl(url)) {
throw Exception(
'Could not launch $url');
}
},
icon: const Icon(
Icons.chat,
color: backgroundColor3,
size: 15,
),
),
),
const SizedBox(width: 20),
CircleAvatar(
radius: 15,
backgroundColor: mainColor,
child: IconButton(
onPressed: () async {
// model.callPhone();
final Uri callUri = Uri(
scheme: 'tel',
path: model.noHpController!.text);
if (!await launchUrl(callUri)) {
throw 'Could not launch ${callUri.toString()}';
}
},
icon: const Icon(
Icons.call,
color: backgroundColor3,
size: 15,
),
),
),
],
),
],
),
],
),
),

View File

@ -5,22 +5,31 @@ import 'package:easy_image_viewer/easy_image_viewer.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:native_video_player/native_video_player.dart';
import 'package:perumahan_bew/model/rumah_model.dart';
import '../../../app/app.dialogs.dart';
import '../../../app/app.logger.dart';
import '../../../app/core/custom_base_view_model.dart';
import '../../../app/themes/app_colors.dart';
import '../../../model/my_response_model.dart';
class TambahLihatProgressBottomSheetViewModel extends CustomBaseViewModel {
final log = getLogger('TambahLihatProgressBottomSheetViewModel');
NativeVideoPlayerController? nativeVideoPlayerController;
String? level;
MandorModel? mandorModel;
TextEditingController? mandorController = TextEditingController();
TextEditingController? noHpController = TextEditingController();
String? idPerumahan;
ProgressModel? progressModel;
// form variable
final globalKey = GlobalKey<FormState>();
TextEditingController? ketController = TextEditingController();
TextEditingController? waktuController = TextEditingController();
// image video variable
// image picker
@ -29,9 +38,40 @@ class TambahLihatProgressBottomSheetViewModel extends CustomBaseViewModel {
XFile? imageVideoFile;
Uint8List? imageVideoBytes;
String? imageVideoType;
Future<void> init(String data) async {
Future<void> init(data) async {
globalVar.backPressed = "exitApp";
idPerumahan = data;
idPerumahan = data['idPerumahan'];
// log.i(data['progressModel']);
if (data['progressModel'] != null) {
progressModel = data['progressModel'];
ketController!.text = progressModel!.ket!;
waktuController!.text = progressModel!.createdAt!;
log.i('type: ${progressModel!.type}');
imageVideoType = progressModel!.type;
}
level = await mySharedPrefs.getString('level');
if (level == 'Pemilik Rumah') {
await getData();
}
}
getData() async {
setBusy(true);
try {
var response =
await httpService.get('mandor?id=${progressModel!.idMandor}');
MyResponseModel myResponseModel = MyResponseModel.fromJson(response.data);
mandorModel = MandorModel.fromJson(myResponseModel.data);
log.i('mandorModel: ${mandorModel!.nama}');
mandorController!.text = mandorModel!.nama!;
noHpController!.text = mandorModel!.noTelpon!;
} catch (e) {
log.e('Error: $e');
} finally {
setBusy(false);
}
}
addImage(String type) async {
@ -79,13 +119,20 @@ class TambahLihatProgressBottomSheetViewModel extends CustomBaseViewModel {
});
}
playVideo() async {
playVideo(String status, String? url) async {
// play video by imageVideoPath
log.i('play video');
log.i(status);
log.i(url);
await dialogService.showCustomDialog(
variant: DialogType.playVideoDialogView,
title: 'Video',
data: imageVideoPath,
data: {
'status': status,
'url': url,
'path': imageVideoPath,
},
);
}
@ -117,13 +164,20 @@ class TambahLihatProgressBottomSheetViewModel extends CustomBaseViewModel {
}
}
showImage(BuildContext context) async {
showImage(BuildContext context, String status, String? url) async {
log.i(status);
log.i(url);
showImageViewer(
context,
Image.memory(
imageVideoBytes!,
fit: BoxFit.fill,
).image,
status == 'file'
? Image.memory(
imageVideoBytes!,
fit: BoxFit.fill,
).image
: Image.network(
url!,
fit: BoxFit.fill,
).image,
swipeDismissible: true,
doubleTapZoomable: true,
);