Commit 47d7498c authored by Dio Maulana's avatar Dio Maulana

final

parent e8e4274e
......@@ -3,8 +3,10 @@ import 'dart:convert';
import 'package:excelso_attendance/helper/logger.dart';
import 'package:excelso_attendance/helper/pref.dart';
import 'package:excelso_attendance/main.dart';
import 'package:excelso_attendance/models/absent.dart';
import 'package:excelso_attendance/models/branch.dart';
import 'package:excelso_attendance/models/shift.dart';
import 'package:excelso_attendance/resource/strings.dart';
import 'package:http/http.dart' as http;
class Api {
......@@ -22,8 +24,9 @@ class Api {
typePost, apiUrl, "getNearestBranch",
bodies: bodies);
if (jsonObject == false) {
return ApiResponse(error: true, msg: "Can't connect to server");
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == "ok") {
List<BranchModel> branchList = [];
List<dynamic> branchs = jsonObject['data']['branch_list'];
......@@ -36,13 +39,18 @@ class Api {
}
return ApiResponse(
error: false,
msg: "Success get data",
msg: Strings.succesGetData,
data: branchList,
);
} else {
return ApiResponse(
error: true,
msg: jsonObject['msg'],
);
}
}
} catch (e) {
return ApiResponse(
error: true, msg: "Something wrong with our server, refresh page");
return ApiResponse(error: true, msg: Strings.serverError);
}
}
......@@ -57,8 +65,9 @@ class Api {
dynamic jsonObject =
await httpRequest(typePost, apiUrl, "getShiftList", bodies: bodies);
if (jsonObject == false) {
return ApiResponse(error: true, msg: "Can't connect to server");
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == "ok") {
List<ShiftModel> shiftList = [];
List<dynamic> shift = jsonObject['data']['shift_list'];
......@@ -71,13 +80,126 @@ class Api {
}
return ApiResponse(
error: false,
msg: "Success get data",
msg: Strings.succesGetData,
data: shiftList,
);
} else {
return ApiResponse(
error: true,
msg: jsonObject['msg'],
);
}
}
} catch (e) {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
static Future<ApiResponse> getUserProfile(String branchId, String nik) async {
String apiUrl = "$baseUrl${endPoint}profile_user";
try {
Map<String, dynamic> data = {
"branch_id": branchId,
"nik": nik,
};
String bodies = jsonEncode(data);
dynamic jsonObject =
await httpRequest(typePost, apiUrl, "getUserProfile", bodies: bodies);
if (jsonObject == false) {
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == "ok") {
return ApiResponse(
error: false,
msg: Strings.succesGetData,
);
} else {
return ApiResponse(
error: true,
msg: jsonObject['msg'],
);
}
}
} catch (e) {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
static Future<ApiResponse> shiftIn(
String branchId, String nik, String shiftId, String photoBase64) async {
String apiUrl = "$baseUrl${endPoint}clock_in";
try {
Map<String, dynamic> data = {
"branch_id": branchId,
"nik": nik,
"shift_id": shiftId,
"user_lat": getLatitude(),
"user_long": getLongitude(),
"photo_base64": "data:image/jpeg;base64,$photoBase64",
};
String bodies = jsonEncode(data);
dynamic jsonObject =
await httpRequest(typePost, apiUrl, "shiftIn", bodies: bodies);
if (jsonObject == false) {
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == "ok") {
return ApiResponse(
error: false,
msg: Strings.succesGetData,
data: AbsentSuccessModel.json(
jsonObject['data'],
),
);
} else {
return ApiResponse(
error: true,
msg: jsonObject['msg'],
);
}
}
} catch (e) {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
static Future<ApiResponse> shiftOut(
String branchId, String nik, String photoBase64) async {
String apiUrl = "$baseUrl${endPoint}clock_out";
try {
Map<String, dynamic> data = {
"branch_id": branchId,
"nik": nik,
"user_lat": getLatitude(),
"user_long": getLongitude(),
"photo_base64": photoBase64,
};
String bodies = jsonEncode(data);
dynamic jsonObject =
await httpRequest(typePost, apiUrl, "shiftOut", bodies: bodies);
if (jsonObject == false) {
return ApiResponse(error: true, msg: Strings.cantConnectToServer);
} else {
if (jsonObject['status'] == "ok") {
return ApiResponse(
error: true, msg: "Something wrong with our server, refresh page");
error: false,
msg: Strings.succesGetData,
data: AbsentSuccessModel.json(
jsonObject['data'],
),
);
} else {
return ApiResponse(
error: true,
msg: jsonObject['msg'],
);
}
}
} catch (e) {
return ApiResponse(error: true, msg: Strings.serverError);
}
}
}
......
import 'package:excelso_attendance/models/absent.dart';
import 'package:excelso_attendance/models/branch.dart';
import 'package:excelso_attendance/models/shift.dart';
......@@ -5,10 +6,12 @@ class AbsentCameraArguments {
final bool isIn;
final BranchModel branchModel;
final ShiftModel? shiftModel;
final String nik;
AbsentCameraArguments({
required this.isIn,
required this.branchModel,
required this.nik,
this.shiftModel,
});
}
......@@ -22,3 +25,13 @@ class HomeArguments {
required this.shiftModel,
});
}
class AbsentSuccessArguments {
final AbsentSuccessModel absentSuccess;
final bool isIn;
AbsentSuccessArguments({
required this.absentSuccess,
required this.isIn,
});
}
......@@ -90,11 +90,25 @@ class DateFormatCustom {
return result;
}
static String getDateLocal() {
static String getDateLocal({
bool fromApi = false,
String apiDate = '',
}) {
String day;
String month;
String year;
if (fromApi) {
List<String> splitApiDate = apiDate.split("-");
day = splitApiDate[2];
month = monthLocal(splitApiDate[1]);
year = splitApiDate[0];
} else {
DateTime localTime = DateTime.now().toLocal();
int day = localTime.day;
String month = monthLocal(localTime.month.toString());
int year = localTime.year;
day = localTime.day.toString();
month = monthLocal(localTime.month.toString());
year = localTime.year.toString();
}
String result = "$day $month $year";
return result;
......
class AbsentSuccessModel {
String branchCode;
String branchName;
String date;
String time;
String type;
AbsentSuccessModel({
required this.branchCode,
required this.branchName,
required this.date,
required this.time,
required this.type,
});
factory AbsentSuccessModel.json(Map<String, dynamic> json) {
return AbsentSuccessModel(
branchCode: json['branch_code'],
branchName: json['branch_name'],
date: json['date'],
time: json['time'],
type: json['type'],
);
}
}
// ignore_for_file: sized_box_for_whitespace
import 'dart:async';
import 'dart:io';
import 'dart:convert';
import 'dart:io' as Io;
import 'package:excelso_attendance/api/api.dart';
import 'package:excelso_attendance/helper/arguments/error_args.dart';
import 'package:excelso_attendance/helper/arguments/route_args.dart';
import 'package:excelso_attendance/helper/widget_responsive.dart';
import 'package:excelso_attendance/main.dart';
import 'package:excelso_attendance/models/absent.dart';
import 'package:excelso_attendance/models/branch.dart';
import 'package:excelso_attendance/models/shift.dart';
import 'package:excelso_attendance/resource/routes.dart';
......@@ -21,18 +25,21 @@ import 'package:excelso_attendance/resource/font.dart';
import 'package:excelso_attendance/resource/size.dart';
import 'package:excelso_attendance/resource/style.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
class AbsentCameraView extends StatefulWidget {
const AbsentCameraView({
super.key,
required this.isIn,
required this.branchModel,
required this.nik,
this.shiftModel,
});
final bool isIn;
final BranchModel branchModel;
final ShiftModel? shiftModel;
final String nik;
@override
State<AbsentCameraView> createState() => _AbsentCameraViewState();
......@@ -50,6 +57,8 @@ class _AbsentCameraViewState extends State<AbsentCameraView> {
bool pictureIsTaken = false;
bool isPhone = false;
String? imageBase64;
// bool isPermissionAccept = true;
// String? errorCamera;
......@@ -90,6 +99,7 @@ class _AbsentCameraViewState extends State<AbsentCameraView> {
_cameraDescription!,
// Define the resolution to use.
ResolutionPreset.medium,
imageFormatGroup: ImageFormatGroup.jpeg,
);
setState(() {
_initializeControllerFuture = _controller!.initialize();
......@@ -159,7 +169,7 @@ class _AbsentCameraViewState extends State<AbsentCameraView> {
child: (pictureIsTaken)
? (isPhone)
? Image.file(
File(imagePathPhone!),
Io.File(imagePathPhone!),
fit: BoxFit.fill,
)
: Image.memory(
......@@ -248,11 +258,69 @@ class _AbsentCameraViewState extends State<AbsentCameraView> {
width: 100,
child: CustomButton(
text: "Submit",
onTap: () {
onTap: () async {
await EasyLoading.show(
status: Strings.pleaseWait,
maskType:
EasyLoadingMaskType.none,
);
if (widget.isIn) {
Api.shiftIn(
widget.branchModel.id,
widget.nik,
widget.shiftModel!.id,
imageBase64!,
).then((apiResponse) {
EasyLoading.dismiss();
if (apiResponse.error) {
EasyLoading.showToast(
apiResponse.msg);
return;
}
AbsentSuccessModel
absentSuccess =
apiResponse.data
as AbsentSuccessModel;
Navigator.pushNamed(
context,
Routes.absentSuccess,
arguments:
AbsentSuccessArguments(
absentSuccess:
absentSuccess,
isIn: true,
),
);
});
} else {
Api.shiftOut(
widget.branchModel.id,
widget.nik,
imageBase64!,
).then((apiResponse) {
EasyLoading.dismiss();
if (apiResponse.error) {
EasyLoading.showToast(
apiResponse.msg,
);
return;
}
AbsentSuccessModel
absentSuccess =
apiResponse.data
as AbsentSuccessModel;
Navigator.pushNamed(
context,
Routes.absentSuccess,
arguments:
AbsentSuccessArguments(
absentSuccess:
absentSuccess,
isIn: false,
),
);
});
}
},
),
),
......@@ -270,6 +338,8 @@ class _AbsentCameraViewState extends State<AbsentCameraView> {
_cameraDescription!,
// Define the resolution to use.
ResolutionPreset.medium,
imageFormatGroup:
ImageFormatGroup.jpeg,
);
_initializeControllerFuture =
_controller!.initialize();
......@@ -324,6 +394,8 @@ class _AbsentCameraViewState extends State<AbsentCameraView> {
Uint8List? imageResultWeb;
if (isPhone) {
imageResultPhone = image.path;
imageResultWeb =
await image.readAsBytes();
} else {
imageResultWeb =
await image.readAsBytes();
......@@ -336,6 +408,8 @@ class _AbsentCameraViewState extends State<AbsentCameraView> {
imagePath = imageResultWeb;
imagePathPhone =
imageResultPhone;
imageBase64 = base64Encode(
imageResultWeb!);
});
} catch (e) {
if (debug) {
......@@ -380,6 +454,8 @@ class _AbsentCameraViewState extends State<AbsentCameraView> {
_cameraDescription!,
// Define the resolution to use.
ResolutionPreset.medium,
imageFormatGroup:
ImageFormatGroup.jpeg,
);
_initializeControllerFuture =
_controller!.initialize();
......
import 'package:excelso_attendance/helper/component/button.dart';
import 'package:excelso_attendance/helper/global_function/date_time.dart';
import 'package:excelso_attendance/models/absent.dart';
import 'package:excelso_attendance/resource/assets.dart';
import 'package:excelso_attendance/resource/colors.dart';
import 'package:excelso_attendance/resource/font.dart';
......@@ -8,7 +10,11 @@ import 'package:excelso_attendance/resource/style.dart';
import 'package:flutter/material.dart';
class AbsentSuccessView extends StatelessWidget {
const AbsentSuccessView({super.key});
const AbsentSuccessView(
{super.key, required this.absentSuccess, required this.isIn});
final AbsentSuccessModel absentSuccess;
final bool isIn;
@override
Widget build(BuildContext context) {
......@@ -75,7 +81,10 @@ class AbsentSuccessView extends StatelessWidget {
width: double.infinity,
child: Center(
child: Text(
'''Absen Masuk
(isIn)
? '''Absen Masuk
Sukses'''
: '''Absen Keluar
Sukses''',
style: getSemiBoldStyle(
color: Colors.black,
......@@ -135,7 +144,7 @@ Sukses''',
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"CRM",
absentSuccess.branchCode,
style: getSemiBoldStyle(
color: ColorManager.fontBlack,
fontSize: FontSize.s20,
......@@ -143,7 +152,7 @@ Sukses''',
),
),
Text(
"10:30 WIB",
absentSuccess.time,
style: getSemiBoldStyle(
color: ColorManager.fontBlack,
fontSize: FontSize.s20,
......@@ -160,7 +169,10 @@ Sukses''',
children: [
const Spacer(),
Text(
"23 Februari 2023",
DateFormatCustom.getDateLocal(
fromApi: true,
apiDate: absentSuccess.date,
),
style: getRegularStyle(
color: ColorManager.fontBlack,
fontSize: 16,
......
import 'dart:async';
import 'package:excelso_attendance/api/api.dart';
import 'package:excelso_attendance/helper/arguments/route_args.dart';
import 'package:excelso_attendance/helper/component/button.dart';
import 'package:excelso_attendance/helper/component/text_field.dart';
......@@ -12,6 +13,7 @@ import 'package:excelso_attendance/resource/colors.dart';
import 'package:excelso_attendance/resource/font.dart';
import 'package:excelso_attendance/resource/routes.dart';
import 'package:excelso_attendance/resource/size.dart';
import 'package:excelso_attendance/resource/strings.dart';
import 'package:excelso_attendance/resource/style.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
......@@ -240,6 +242,7 @@ class _BodyWidgetState extends State<BodyWidget> {
shiftList: widget.shiftList,
branchModel:
widget.nearestBranch[selectedOutlet],
nik: nikController.text,
);
});
}
......@@ -251,11 +254,23 @@ class _BodyWidgetState extends State<BodyWidget> {
Expanded(
child: CustomButton(
text: "Keluar",
onTap: () {
onTap: () async {
if (nikController.text.isEmpty) {
EasyLoading.showToast(
"Silakan isi NIK terlebih dahulu",
);
} else {
await EasyLoading.show(
status: Strings.pleaseWait,
maskType: EasyLoadingMaskType.none,
);
Api.getUserProfile(
widget.nearestBranch[selectedOutlet].id,
nikController.text,
).then((apiResponse) {
EasyLoading.dismiss();
if (apiResponse.error) {
EasyLoading.showToast(apiResponse.msg);
} else {
Navigator.pushNamed(
context,
......@@ -264,9 +279,12 @@ class _BodyWidgetState extends State<BodyWidget> {
isIn: false,
branchModel:
widget.nearestBranch[selectedOutlet],
nik: nikController.text,
),
);
}
});
}
},
),
),
......@@ -622,10 +640,12 @@ class WidgetSelectShift extends StatefulWidget {
Key? key,
required this.shiftList,
required this.branchModel,
required this.nik,
}) : super(key: key);
final List<ShiftModel> shiftList;
final BranchModel branchModel;
final String nik;
@override
State<WidgetSelectShift> createState() => _WidgetSelectShiftState();
......@@ -744,18 +764,33 @@ class _WidgetSelectShiftState extends State<WidgetSelectShift> {
),
margin: EdgeInsets.symmetric(vertical: AppMargin.m16),
child: GestureDetector(
onTap: () {
onTap: () async {
if (selectedShift != null) {
await EasyLoading.show(
status: Strings.pleaseWait,
maskType: EasyLoadingMaskType.none,
);
Api.getUserProfile(
widget.branchModel.id,
widget.nik,
).then((apiResponse) {
EasyLoading.dismiss();
if (apiResponse.error) {
Navigator.pop(context);
Navigator.pushNamed(
EasyLoading.showToast(apiResponse.msg);
} else {
Navigator.popAndPushNamed(
context,
Routes.absentCamera,
arguments: AbsentCameraArguments(
isIn: true,
branchModel: widget.branchModel,
shiftModel: widget.shiftList[selectedShift!],
nik: widget.nik,
),
);
}
});
} else {
EasyLoading.showToast("Silakan pilih shift");
}
......
......@@ -42,13 +42,22 @@ class RouteGenerator {
isIn: args.isIn,
branchModel: args.branchModel,
shiftModel: args.shiftModel,
nik: args.nik,
),
nameRoute: Routes.absentCamera,
routeSettings: routeSettings,
);
case Routes.absentSuccess:
return pageRouteCustom(const AbsentSuccessView(),
nameRoute: Routes.absentSuccess);
AbsentSuccessArguments args =
routeSettings.arguments as AbsentSuccessArguments;
return pageRouteCustom(
AbsentSuccessView(
absentSuccess: args.absentSuccess,
isIn: args.isIn,
),
nameRoute: Routes.absentSuccess,
routeSettings: routeSettings,
);
case Routes.errorWidget:
ErrorWidgetArguments args =
routeSettings.arguments as ErrorWidgetArguments;
......@@ -85,6 +94,7 @@ class RouteGenerator {
isIn: args.isIn,
branchModel: args.branchModel,
shiftModel: args.shiftModel,
nik: args.nik,
),
transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero,
......@@ -119,6 +129,21 @@ class RouteGenerator {
// name: nameRoute.replaceFirst("/", ""), arguments: args),
);
}
if (nameRoute == Routes.absentSuccess) {
AbsentSuccessArguments args =
routeSettings!.arguments as AbsentSuccessArguments;
return PageRouteBuilder(
pageBuilder: (context, a, b) => AbsentSuccessView(
absentSuccess: args.absentSuccess,
isIn: args.isIn,
),
transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero,
// settings: RouteSettings(
// name: nameRoute.replaceFirst("/", ""), arguments: args),
);
}
// else if (nameRoute == Routes.errorWidget) {
// ErrorWidgetArguments args =
// routeSettings!.arguments as ErrorWidgetArguments;
......
......@@ -7,4 +7,8 @@ class Strings {
"Tidak ada outlet yang ditemukan dalam radius 10Km";
static String errorGetShiftList =
"Tidak dapat terhubung ke server, shift tidak ditemukan";
static String cantConnectToServer = "Can't connect to server";
static String serverError = "Something wrong with our server, refresh page";
static String succesGetData = "Success get data";
static String pleaseWait = "Please wait...";
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment