complete admin, mandor and user page
This commit is contained in:
@ -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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@ -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,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user