Commit e8e4274e authored by Dio Maulana's avatar Dio Maulana

fixed API for onboarding and HOME view

parent bc1bc4a3
import 'dart:convert'; import 'dart:convert';
import 'package:excelso_attendance/helper/logger.dart'; import 'package:excelso_attendance/helper/logger.dart';
import 'package:excelso_attendance/helper/pref.dart';
import 'package:excelso_attendance/main.dart'; import 'package:excelso_attendance/main.dart';
import 'package:excelso_attendance/models/branch.dart'; import 'package:excelso_attendance/models/branch.dart';
import 'package:excelso_attendance/models/shift.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
String baseUrl = "";
String endPoint = "rav/attendance/";
class Api { class Api {
static Future<Map<String, dynamic>> getNearestBranch() async { static Future<ApiResponse> getNearestBranch() async {
String apiUrl = "$baseUrl${endPoint}nearest_branch_list"; String apiUrl = "$baseUrl${endPoint}nearest_branch_list";
Map<String, dynamic> result;
try { try {
dynamic jsonObject = Map<String, dynamic> data = {
await httpRequest(typePost, apiUrl, "getNearestBranch"); "brand_code": brandCode,
"user_lat": getLatitude(),
"user_long": getLongitude(),
};
String bodies = jsonEncode(data);
dynamic jsonObject = await httpRequest(
typePost, apiUrl, "getNearestBranch",
bodies: bodies);
if (jsonObject == false) { if (jsonObject == false) {
result = {"error": true, "msg": "Can't connect to server"}; return ApiResponse(error: true, msg: "Can't connect to server");
return result;
} else { } else {
List<BranchModel> branchList = []; List<BranchModel> branchList = [];
...@@ -30,20 +34,50 @@ class Api { ...@@ -30,20 +34,50 @@ class Api {
), ),
); );
} }
return ApiResponse(
result = { error: false,
"error": false, msg: "Success get data",
"msg": "Success get data", data: branchList,
"branchs": branchList, );
};
return result;
} }
} catch (e) { } catch (e) {
result = { return ApiResponse(
"error": true, error: true, msg: "Something wrong with our server, refresh page");
"msg": "Something wrong with our server, try again later" }
}
static Future<ApiResponse> getShiftList() async {
String apiUrl = "$baseUrl${endPoint}shift_list";
try {
Map<String, dynamic> data = {
"brand_code": brandCode,
}; };
return result; String bodies = jsonEncode(data);
dynamic jsonObject =
await httpRequest(typePost, apiUrl, "getShiftList", bodies: bodies);
if (jsonObject == false) {
return ApiResponse(error: true, msg: "Can't connect to server");
} else {
List<ShiftModel> shiftList = [];
List<dynamic> shift = jsonObject['data']['shift_list'];
for (int i = 0; i < shift.length; i++) {
shiftList.add(
ShiftModel.json(
shift[i],
),
);
}
return ApiResponse(
error: false,
msg: "Success get data",
data: shiftList,
);
}
} catch (e) {
return ApiResponse(
error: true, msg: "Something wrong with our server, refresh page");
} }
} }
} }
...@@ -79,3 +113,15 @@ Future<dynamic> httpRequest(int typeRequest, String apiUrl, String namaFungsi, ...@@ -79,3 +113,15 @@ Future<dynamic> httpRequest(int typeRequest, String apiUrl, String namaFungsi,
return false; return false;
} }
} }
class ApiResponse {
bool error;
String msg;
dynamic data;
ApiResponse({
required this.error,
required this.msg,
this.data,
});
}
import 'package:excelso_attendance/models/branch.dart';
import 'package:excelso_attendance/models/shift.dart';
class AbsentCameraArguments { class AbsentCameraArguments {
final bool isIn; final bool isIn;
final String outletName; final BranchModel branchModel;
final ShiftModel? shiftModel;
AbsentCameraArguments({ AbsentCameraArguments({
required this.isIn, required this.isIn,
required this.outletName, required this.branchModel,
this.shiftModel,
});
}
class HomeArguments {
final List<BranchModel> branchModel;
final List<ShiftModel> shiftModel;
HomeArguments({
required this.branchModel,
required this.shiftModel,
}); });
} }
class DateFormatCustom { class DateFormatCustom {
static String monthLocal(String month) { static String monthLocal(String m) {
String month;
if (m.length == 1) {
month = "0$m";
} else {
month = m;
}
switch (month) { switch (month) {
case "01": case "01":
return "Januari"; return "Januari";
...@@ -44,24 +50,41 @@ class DateFormatCustom { ...@@ -44,24 +50,41 @@ class DateFormatCustom {
} }
} }
static String getLocalTime({bool timeZoneActive = false}) { static String getLocalTime(
{bool timeZoneActive = false, bool secondActive = false}) {
DateTime localTime = DateTime.now().toLocal(); DateTime localTime = DateTime.now().toLocal();
int hour = localTime.hour; int hour = localTime.hour;
String min = localTime.minute.toString(); String min = localTime.minute.toString();
String second = localTime.second.toString();
String minute; String minute;
String sec;
if (min.length == 1) { if (min.length == 1) {
minute = "0$min"; minute = "0$min";
} else { } else {
minute = min; minute = min;
} }
if (second.length == 1) {
sec = "0$second";
} else {
sec = second;
}
// int sec = localTime.second; // int sec = localTime.second;
String timeZone = localTimeZoneName(localTime.timeZoneOffset.toString()); String timeZone = localTimeZoneName(localTime.timeZoneOffset.toString());
String result; String result;
if (timeZoneActive) { if (timeZoneActive) {
result = "$hour : $minute $timeZone"; if (secondActive) {
result = "$hour : $minute : $sec $timeZone";
} else {
result = "$hour : $minute $timeZone";
}
} else { } else {
result = "$hour : $minute"; if (secondActive) {
result = "$hour : $minute : $sec";
} else {
result = "$hour : $minute";
}
} }
return result; return result;
...@@ -76,4 +99,13 @@ class DateFormatCustom { ...@@ -76,4 +99,13 @@ class DateFormatCustom {
String result = "$day $month $year"; String result = "$day $month $year";
return result; return result;
} }
static String getTimeHourMinuteOnly(String time) {
// awalnya dari API 00:00:00, balikin 00:00 ke UI
List<String> timeSplit = time.split(":");
String result;
result = "${timeSplit[0]} : ${timeSplit[1]}";
return result;
}
} }
...@@ -4,9 +4,16 @@ import 'package:flutter_easyloading/flutter_easyloading.dart'; ...@@ -4,9 +4,16 @@ import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:url_strategy/url_strategy.dart'; import 'package:url_strategy/url_strategy.dart';
// all config here
bool debug = true; bool debug = true;
late SharedPreferences prefs; late SharedPreferences prefs;
String titleApp = 'Excelso Attendances'; String titleApp = 'Excelso Attendances';
String brandCode = "EXC";
String baseUrl = "https://hibiscus-dev.ravku.com/";
String endPoint = "rav/attendance/";
// final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>(); // final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
void main() async { void main() async {
......
...@@ -2,11 +2,13 @@ class BranchModel { ...@@ -2,11 +2,13 @@ class BranchModel {
String id; String id;
String code; String code;
String name; String name;
double distance;
BranchModel({ BranchModel({
required this.id, required this.id,
required this.code, required this.code,
required this.name, required this.name,
required this.distance,
}); });
factory BranchModel.json(Map<String, dynamic> json) { factory BranchModel.json(Map<String, dynamic> json) {
...@@ -14,6 +16,7 @@ class BranchModel { ...@@ -14,6 +16,7 @@ class BranchModel {
id: json['id'], id: json['id'],
code: json['code'], code: json['code'],
name: json['name'], name: json['name'],
distance: json['distance'],
); );
} }
} }
...@@ -5,6 +5,8 @@ import 'dart:io'; ...@@ -5,6 +5,8 @@ import 'dart:io';
import 'package:excelso_attendance/helper/arguments/error_args.dart'; import 'package:excelso_attendance/helper/arguments/error_args.dart';
import 'package:excelso_attendance/helper/widget_responsive.dart'; import 'package:excelso_attendance/helper/widget_responsive.dart';
import 'package:excelso_attendance/main.dart'; import 'package:excelso_attendance/main.dart';
import 'package:excelso_attendance/models/branch.dart';
import 'package:excelso_attendance/models/shift.dart';
import 'package:excelso_attendance/resource/routes.dart'; import 'package:excelso_attendance/resource/routes.dart';
import 'package:excelso_attendance/resource/strings.dart'; import 'package:excelso_attendance/resource/strings.dart';
import 'package:flutter/foundation.dart' show kIsWeb; import 'package:flutter/foundation.dart' show kIsWeb;
...@@ -21,11 +23,16 @@ import 'package:excelso_attendance/resource/style.dart'; ...@@ -21,11 +23,16 @@ import 'package:excelso_attendance/resource/style.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class AbsentCameraView extends StatefulWidget { class AbsentCameraView extends StatefulWidget {
const AbsentCameraView( const AbsentCameraView({
{super.key, required this.outletName, required this.isIn}); super.key,
required this.isIn,
required this.branchModel,
this.shiftModel,
});
final String outletName;
final bool isIn; final bool isIn;
final BranchModel branchModel;
final ShiftModel? shiftModel;
@override @override
State<AbsentCameraView> createState() => _AbsentCameraViewState(); State<AbsentCameraView> createState() => _AbsentCameraViewState();
...@@ -229,7 +236,7 @@ class _AbsentCameraViewState extends State<AbsentCameraView> { ...@@ -229,7 +236,7 @@ class _AbsentCameraViewState extends State<AbsentCameraView> {
), ),
WidgetAbsentAndTime( WidgetAbsentAndTime(
isIn: widget.isIn, isIn: widget.isIn,
outletName: widget.outletName, outletName: widget.branchModel.code,
), ),
const Spacer(), const Spacer(),
(pictureIsTaken) (pictureIsTaken)
...@@ -258,6 +265,14 @@ class _AbsentCameraViewState extends State<AbsentCameraView> { ...@@ -258,6 +265,14 @@ class _AbsentCameraViewState extends State<AbsentCameraView> {
onTap: () { onTap: () {
setState(() { setState(() {
pictureIsTaken = false; pictureIsTaken = false;
_controller = CameraController(
// Get a specific camera from the list of available cameras.
_cameraDescription!,
// Define the resolution to use.
ResolutionPreset.medium,
);
_initializeControllerFuture =
_controller!.initialize();
}); });
}, },
child: CustomButton( child: CustomButton(
...@@ -507,13 +522,17 @@ class _WidgetAbsentAndTimeState extends State<WidgetAbsentAndTime> { ...@@ -507,13 +522,17 @@ class _WidgetAbsentAndTimeState extends State<WidgetAbsentAndTime> {
fontFamily: FontConstants.poppins, fontFamily: FontConstants.poppins,
), ),
), ),
Text( Expanded(
"${widget.outletName} - ${DateFormatCustom.getLocalTime( child: Text(
timeZoneActive: true, "${widget.outletName} - ${DateFormatCustom.getLocalTime(
)}", timeZoneActive: true,
style: getSemiBoldStyle( )}",
color: Colors.black, style: getSemiBoldStyle(
fontSize: FontSize.s24, color: Colors.black,
fontSize: FontSize.s24,
),
maxLines: 3,
overflow: TextOverflow.ellipsis,
), ),
), ),
], ],
......
This diff is collapsed.
import 'package:excelso_attendance/api/api.dart';
import 'package:excelso_attendance/helper/arguments/error_args.dart'; import 'package:excelso_attendance/helper/arguments/error_args.dart';
import 'package:excelso_attendance/helper/arguments/route_args.dart';
import 'package:excelso_attendance/helper/pref.dart'; import 'package:excelso_attendance/helper/pref.dart';
import 'package:excelso_attendance/helper/widget_responsive.dart'; import 'package:excelso_attendance/helper/widget_responsive.dart';
import 'package:excelso_attendance/models/branch.dart';
import 'package:excelso_attendance/models/shift.dart';
import 'package:excelso_attendance/resource/assets.dart'; import 'package:excelso_attendance/resource/assets.dart';
import 'package:excelso_attendance/resource/colors.dart'; import 'package:excelso_attendance/resource/colors.dart';
import 'package:excelso_attendance/resource/font.dart'; import 'package:excelso_attendance/resource/font.dart';
...@@ -21,10 +25,29 @@ class OnBoardingView extends StatefulWidget { ...@@ -21,10 +25,29 @@ class OnBoardingView extends StatefulWidget {
} }
class _OnBoardingViewState extends State<OnBoardingView> { class _OnBoardingViewState extends State<OnBoardingView> {
bool getAllApi = false;
String? errorMessage;
List<BranchModel> nearestBranch = [];
List<ShiftModel> shiftList = [];
@override @override
void initState() { void initState() {
super.initState(); super.initState();
getUserPermission(); getUserPermission().then((value) {
if (value) {
getNearestBranch().then((branchBool) {
if (branchBool) {
// ambil list shift kalau ada outlet
getShiftList();
} else {
// setstate aja, gausah ambil list shift karena gak ada utlet
setState(() {});
}
});
}
});
// final perm = // final perm =
// await html.window.navigator.permissions!.query({"name": "camera"}); // await html.window.navigator.permissions!.query({"name": "camera"});
// if (perm.state == "denied") { // if (perm.state == "denied") {
...@@ -35,7 +58,43 @@ class _OnBoardingViewState extends State<OnBoardingView> { ...@@ -35,7 +58,43 @@ class _OnBoardingViewState extends State<OnBoardingView> {
// } // }
} }
void getUserPermission() async { Future<bool> getNearestBranch() async {
ApiResponse getNearestBranch = await Api.getNearestBranch();
if (getNearestBranch.error) {
errorMessage = getNearestBranch.msg;
getAllApi = true;
return false;
} else {
List<BranchModel> dataBranchs =
getNearestBranch.data as List<BranchModel>;
nearestBranch = dataBranchs;
if (dataBranchs.isEmpty) {
errorMessage = Strings.noOutletArround;
getAllApi = true;
return false;
}
return true;
}
}
void getShiftList() async {
ApiResponse getShiftList = await Api.getShiftList();
setState(() {
getAllApi = true;
if (getShiftList.error) {
errorMessage = Strings.errorGetShiftList;
} else {
List<ShiftModel> dataShift = getShiftList.data as List<ShiftModel>;
shiftList = dataShift;
if (dataShift.isEmpty) {
errorMessage = Strings.errorGetShiftList;
}
}
});
}
Future<bool> getUserPermission() async {
LocationPermission permission = await Geolocator.requestPermission(); LocationPermission permission = await Geolocator.requestPermission();
if (permission == LocationPermission.always || if (permission == LocationPermission.always ||
permission == LocationPermission.whileInUse) { permission == LocationPermission.whileInUse) {
...@@ -43,6 +102,7 @@ class _OnBoardingViewState extends State<OnBoardingView> { ...@@ -43,6 +102,7 @@ class _OnBoardingViewState extends State<OnBoardingView> {
setLatitude(position.latitude.toString()); setLatitude(position.latitude.toString());
setLongitude(position.longitude.toString()); setLongitude(position.longitude.toString());
}); });
return true;
} else { } else {
// ignore: use_build_context_synchronously // ignore: use_build_context_synchronously
Navigator.pushNamedAndRemoveUntil( Navigator.pushNamedAndRemoveUntil(
...@@ -53,6 +113,7 @@ class _OnBoardingViewState extends State<OnBoardingView> { ...@@ -53,6 +113,7 @@ class _OnBoardingViewState extends State<OnBoardingView> {
errorMessage: Strings.locationNotActive, errorMessage: Strings.locationNotActive,
), ),
); );
return false;
} }
// await html.window.navigator.getUserMedia(audio: true, video: true); // await html.window.navigator.getUserMedia(audio: true, video: true);
} }
...@@ -62,7 +123,12 @@ class _OnBoardingViewState extends State<OnBoardingView> { ...@@ -62,7 +123,12 @@ class _OnBoardingViewState extends State<OnBoardingView> {
return Scaffold( return Scaffold(
backgroundColor: ColorManager.backgroundColor, backgroundColor: ColorManager.backgroundColor,
body: ScreenResponsive( body: ScreenResponsive(
widget: const BodyWidget(), widget: BodyWidget(
getAllApi: getAllApi,
errorMessage: errorMessage,
nearestBranch: nearestBranch,
shiftList: shiftList,
),
widthScreen: MediaQuery.of(context).size.width, widthScreen: MediaQuery.of(context).size.width,
), ),
); );
...@@ -72,8 +138,17 @@ class _OnBoardingViewState extends State<OnBoardingView> { ...@@ -72,8 +138,17 @@ class _OnBoardingViewState extends State<OnBoardingView> {
class BodyWidget extends StatelessWidget { class BodyWidget extends StatelessWidget {
const BodyWidget({ const BodyWidget({
super.key, super.key,
required this.getAllApi,
required this.nearestBranch,
this.errorMessage,
required this.shiftList,
}); });
final bool getAllApi;
final String? errorMessage;
final List<BranchModel> nearestBranch;
final List<ShiftModel> shiftList;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SingleChildScrollView( return SingleChildScrollView(
...@@ -157,28 +232,53 @@ dengan sekali klik''', ...@@ -157,28 +232,53 @@ dengan sekali klik''',
), ),
GestureDetector( GestureDetector(
onTap: () { onTap: () {
Navigator.pushNamed(context, Routes.home); if (getAllApi) {
Navigator.pushNamed(
context,
Routes.home,
arguments: HomeArguments(
branchModel: nearestBranch,
shiftModel: shiftList,
),
);
}
}, },
child: Container( child: Container(
margin: const EdgeInsets.only( margin: const EdgeInsets.only(
top: 60, top: 60,
), ),
padding: EdgeInsets.symmetric(
horizontal: AppPadding.p20,
),
child: Center( child: Center(
child: Container( child: (getAllApi)
width: 60, ? (errorMessage == null)
height: 60, ? Container(
decoration: BoxDecoration( width: 60,
borderRadius: BorderRadius.circular(100), height: 60,
color: ColorManager.primary, decoration: BoxDecoration(
), borderRadius: BorderRadius.circular(100),
child: const Center( color: ColorManager.primary,
child: Icon( ),
Icons.arrow_forward_ios_rounded, child: const Center(
color: Colors.white, child: Icon(
size: 23, Icons.arrow_forward_ios_rounded,
), color: Colors.white,
), size: 23,
), ),
),
)
: Text(
errorMessage!,
style: getSemiBoldStyle(
color: Colors.black,
fontSize: 16,
),
textAlign: TextAlign.center,
)
: CircularProgressIndicator(
color: ColorManager.primary,
),
), ),
), ),
), ),
......
...@@ -24,14 +24,24 @@ class RouteGenerator { ...@@ -24,14 +24,24 @@ class RouteGenerator {
return pageRouteCustom(const OnBoardingView(), return pageRouteCustom(const OnBoardingView(),
nameRoute: Routes.onBoarding); nameRoute: Routes.onBoarding);
case Routes.home: case Routes.home:
return pageRouteCustom(HomeView(), nameRoute: Routes.home); HomeArguments args = routeSettings.arguments as HomeArguments;
return pageRouteCustom(
HomeView(
nearestBranch: args.branchModel,
shiftList: args.shiftModel,
),
nameRoute: Routes.home,
routeSettings: routeSettings,
);
case Routes.absentCamera: case Routes.absentCamera:
AbsentCameraArguments args = AbsentCameraArguments args =
routeSettings.arguments as AbsentCameraArguments; routeSettings.arguments as AbsentCameraArguments;
return pageRouteCustom( return pageRouteCustom(
AbsentCameraView( AbsentCameraView(
outletName: args.outletName,
isIn: args.isIn, isIn: args.isIn,
branchModel: args.branchModel,
shiftModel: args.shiftModel,
), ),
nameRoute: Routes.absentCamera, nameRoute: Routes.absentCamera,
routeSettings: routeSettings, routeSettings: routeSettings,
...@@ -72,8 +82,9 @@ class RouteGenerator { ...@@ -72,8 +82,9 @@ class RouteGenerator {
routeSettings!.arguments as AbsentCameraArguments; routeSettings!.arguments as AbsentCameraArguments;
return PageRouteBuilder( return PageRouteBuilder(
pageBuilder: (context, a, b) => AbsentCameraView( pageBuilder: (context, a, b) => AbsentCameraView(
outletName: args.outletName,
isIn: args.isIn, isIn: args.isIn,
branchModel: args.branchModel,
shiftModel: args.shiftModel,
), ),
transitionDuration: Duration.zero, transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero, reverseTransitionDuration: Duration.zero,
...@@ -94,6 +105,20 @@ class RouteGenerator { ...@@ -94,6 +105,20 @@ class RouteGenerator {
// name: nameRoute.replaceFirst("/", ""), arguments: args), // name: nameRoute.replaceFirst("/", ""), arguments: args),
); );
} }
if (nameRoute == Routes.home) {
HomeArguments args = routeSettings!.arguments as HomeArguments;
return PageRouteBuilder(
pageBuilder: (context, a, b) => HomeView(
nearestBranch: args.branchModel,
shiftList: args.shiftModel,
),
transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero,
// settings: RouteSettings(
// name: nameRoute.replaceFirst("/", ""), arguments: args),
);
}
// else if (nameRoute == Routes.errorWidget) { // else if (nameRoute == Routes.errorWidget) {
// ErrorWidgetArguments args = // ErrorWidgetArguments args =
// routeSettings!.arguments as ErrorWidgetArguments; // routeSettings!.arguments as ErrorWidgetArguments;
......
...@@ -3,4 +3,8 @@ class Strings { ...@@ -3,4 +3,8 @@ class Strings {
"Silakan aktifkan permission kamera pada pengaturan browser anda"; "Silakan aktifkan permission kamera pada pengaturan browser anda";
static String locationNotActive = static String locationNotActive =
"Silakan aktifkan permission lokasi pada pengaturan browser anda"; "Silakan aktifkan permission lokasi pada pengaturan browser anda";
static String noOutletArround =
"Tidak ada outlet yang ditemukan dalam radius 10Km";
static String errorGetShiftList =
"Tidak dapat terhubung ke server, shift tidak ditemukan";
} }
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