瀏覽代碼

update 0601

dienianindya 1 年之前
父節點
當前提交
7d751c99f6
共有 71 個檔案被更改,包括 5848 行新增368 行删除
  1. 10
    1
      android/app/build.gradle
  2. 13
    3
      android/app/src/main/AndroidManifest.xml
  3. 二進制
      android/app/src/main/res/mipmap-hdpi/ic_launcher.png
  4. 二進制
      android/app/src/main/res/mipmap-mdpi/ic_launcher.png
  5. 二進制
      android/app/src/main/res/mipmap-xhdpi/ic_launcher.png
  6. 二進制
      android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
  7. 二進制
      android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
  8. 2
    1
      android/build.gradle
  9. 1
    0
      assets/animation/animation_4.json
  10. 二進制
      assets/icons/ic_salary.png
  11. 二進制
      assets/icons/menu/ic_about.png
  12. 二進制
      assets/icons/menu/ic_about_2.png
  13. 二進制
      assets/icons/menu/ic_absensi.png
  14. 二進制
      assets/icons/menu/ic_cuti.png
  15. 二進制
      assets/icons/menu/ic_cuti_2.png
  16. 二進制
      assets/icons/menu/ic_info.png
  17. 二進制
      assets/icons/menu/ic_menu_reimburse.png
  18. 二進制
      assets/icons/menu/ic_menu_surattugas.png
  19. 二進制
      assets/icons/menu/ic_menu_surattugas_2.png
  20. 二進制
      assets/icons/menu/ic_refund.png
  21. 二進制
      assets/icons/menu/ic_reimburse.png
  22. 二進制
      assets/icons/menu/ic_slipgaji.png
  23. 二進制
      assets/icons/menu/ic_slipgaji_2.png
  24. 二進制
      assets/icons/menu/ic_surattugas.png
  25. 二進制
      assets/icons/menu/ic_surattugas_2.png
  26. 二進制
      assets/images/ic_calendaroff.png
  27. 二進制
      assets/images/ic_history.png
  28. 二進制
      assets/images/ic_logo.png
  29. 二進制
      assets/images/lines_card.png
  30. 二進制
      firebase-tools-instant-win.exe
  31. 8
    0
      ios/Runner/Info.plist
  32. 94
    3
      lib/Screens/ForgotPassword/forgotPassword_screen.dart
  33. 29
    0
      lib/Screens/ForgotPassword/resetPassword_post.dart
  34. 500
    251
      lib/Screens/Home/home_screen.dart
  35. 8
    16
      lib/Screens/Login/background.dart
  36. 30
    4
      lib/Screens/Login/inputWidget.dart
  37. 188
    10
      lib/Screens/Login/login_screen.dart
  38. 89
    0
      lib/Screens/Login/post_result_model.dart
  39. 45
    2
      lib/Screens/Menu/About/about_screen.dart
  40. 10
    0
      lib/Screens/Menu/Absensi/absensi_history_screen.dart
  41. 354
    1
      lib/Screens/Menu/Absensi/absensi_screen.dart
  42. 39
    0
      lib/Screens/Menu/AjukanCuti/RequestHttp/detailCuti_post.dart
  43. 39
    0
      lib/Screens/Menu/AjukanCuti/RequestHttp/historyCuti_post.dart
  44. 39
    0
      lib/Screens/Menu/AjukanCuti/RequestHttp/jenisCuti_post.dart
  45. 49
    0
      lib/Screens/Menu/AjukanCuti/RequestHttp/pengajuanCuti_post.dart
  46. 815
    2
      lib/Screens/Menu/AjukanCuti/ajukancuti_screen.dart
  47. 87
    0
      lib/Screens/Menu/AjukanCuti/backgroundHistory.dart
  48. 309
    0
      lib/Screens/Menu/AjukanCuti/history_cuti.dart
  49. 9
    0
      lib/Screens/Menu/AjukanCuti/model.dart
  50. 0
    0
      lib/Screens/Menu/Reimburse/history_reimburse.dart
  51. 464
    0
      lib/Screens/Menu/Reimburse/reimburse_screen.dart
  52. 87
    0
      lib/Screens/Menu/SlipGaji/background.dart
  53. 149
    2
      lib/Screens/Menu/SlipGaji/slipgaji_screen.dart
  54. 465
    0
      lib/Screens/Menu/SuratTugas/surattugas_screen.dart
  55. 40
    0
      lib/Screens/Settings/RequestHttp/changePassword_post.dart
  56. 41
    0
      lib/Screens/Settings/RequestHttp/changeprofileimage_post.dart
  57. 39
    0
      lib/Screens/Settings/RequestHttp/getDetail_post.dart
  58. 39
    0
      lib/Screens/Settings/RequestHttp/getProfileImage_post.dart
  59. 39
    0
      lib/Screens/Settings/RequestHttp/logout_post.dart
  60. 75
    2
      lib/Screens/Settings/inputWidget.dart
  61. 777
    46
      lib/Screens/Settings/settings_screen.dart
  62. 46
    0
      lib/Screens/Splash/loginstatus_post.dart
  63. 183
    8
      lib/Screens/Splash/splash_screen.dart
  64. 9
    1
      lib/constants.dart
  65. 4
    0
      linux/flutter/generated_plugin_registrant.cc
  66. 1
    0
      linux/flutter/generated_plugins.cmake
  67. 16
    0
      macos/Flutter/GeneratedPluginRegistrant.swift
  68. 550
    11
      pubspec.lock
  69. 53
    4
      pubspec.yaml
  70. 3
    0
      windows/flutter/generated_plugin_registrant.cc
  71. 1
    0
      windows/flutter/generated_plugins.cmake

+ 10
- 1
android/app/build.gradle 查看文件

@@ -21,12 +21,14 @@ if (flutterVersionName == null) {
21 21
     flutterVersionName = '1.0'
22 22
 }
23 23
 
24
+//apply plugin: 'com.google.gms.google-services'
24 25
 apply plugin: 'com.android.application'
25 26
 apply plugin: 'kotlin-android'
26 27
 apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
27 28
 
28 29
 android {
29 30
     compileSdkVersion flutter.compileSdkVersion
31
+    compileSdkVersion 33
30 32
     ndkVersion flutter.ndkVersion
31 33
 
32 34
     compileOptions {
@@ -39,10 +41,13 @@ android {
39 41
         applicationId "com.example.hris_selfservice_mobile"
40 42
         // You can update the following values to match your application needs.
41 43
         // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
42
-        minSdkVersion flutter.minSdkVersion
44
+        //minSdkVersion flutter.minSdkVersion
45
+        minSdkVersion 28
46
+        //compiledSdkVersion 33
43 47
         targetSdkVersion flutter.targetSdkVersion
44 48
         versionCode flutterVersionCode.toInteger()
45 49
         versionName flutterVersionName
50
+        multiDexEnabled true
46 51
     }
47 52
 
48 53
     buildTypes {
@@ -57,3 +62,7 @@ android {
57 62
 flutter {
58 63
     source '../..'
59 64
 }
65
+
66
+dependencies{
67
+    implementation 'com.android.support:multidex:1.0.3'
68
+}

+ 13
- 3
android/app/src/main/AndroidManifest.xml 查看文件

@@ -1,18 +1,26 @@
1 1
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
2
+    xmlns:tools="http://schemas.android.com/tools"
2 3
     package="com.example.hris_selfservice_mobile">
3 4
 
4 5
     <application
5
-        android:name="${applicationName}"
6 6
         android:icon="@mipmap/ic_launcher"
7
-        android:label="HRIS Self Service">
7
+        android:label="Employee Self Service"
8
+        android:usesCleartextTraffic="true"
9
+        tools:targetApi="m">
10
+
11
+        <meta-data android:name="com.google.android.geo.API_KEY"
12
+            android:value="YOUR-KEY-HERE"/>
13
+
8 14
         <activity
9 15
             android:name=".MainActivity"
16
+            android:screenOrientation="portrait"
10 17
             android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
11 18
             android:exported="true"
12 19
             android:hardwareAccelerated="true"
13 20
             android:launchMode="singleTop"
14 21
             android:theme="@style/LaunchTheme"
15
-            android:windowSoftInputMode="adjustResize">
22
+            android:windowSoftInputMode="adjustResize"
23
+            tools:ignore="LockedOrientationActivity">
16 24
             <!-- Specifies an Android theme to apply to this Activity as soon as
17 25
                  the Android process has started. This theme is visible to the user
18 26
                  while the Flutter UI initializes. After that, this theme continues
@@ -32,3 +40,5 @@
32 40
             android:value="2" />
33 41
     </application>
34 42
 </manifest>
43
+
44
+

二進制
android/app/src/main/res/mipmap-hdpi/ic_launcher.png 查看文件


二進制
android/app/src/main/res/mipmap-mdpi/ic_launcher.png 查看文件


二進制
android/app/src/main/res/mipmap-xhdpi/ic_launcher.png 查看文件


二進制
android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png 查看文件


二進制
android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png 查看文件


+ 2
- 1
android/build.gradle 查看文件

@@ -1,5 +1,5 @@
1 1
 buildscript {
2
-    ext.kotlin_version = '1.6.10'
2
+    ext.kotlin_version = '1.7.20'
3 3
     repositories {
4 4
         google()
5 5
         mavenCentral()
@@ -8,6 +8,7 @@ buildscript {
8 8
     dependencies {
9 9
         classpath 'com.android.tools.build:gradle:7.1.3'
10 10
         classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
11
+        classpath 'com.google.gms:google-services:4.3.14'
11 12
     }
12 13
 }
13 14
 

+ 1
- 0
assets/animation/animation_4.json
文件差異過大導致無法顯示
查看文件


二進制
assets/icons/ic_salary.png 查看文件


二進制
assets/icons/menu/ic_about.png 查看文件


二進制
assets/icons/menu/ic_about_2.png 查看文件


二進制
assets/icons/menu/ic_absensi.png 查看文件


二進制
assets/icons/menu/ic_cuti.png 查看文件


二進制
assets/icons/menu/ic_cuti_2.png 查看文件


二進制
assets/icons/menu/ic_info.png 查看文件


二進制
assets/icons/menu/ic_menu_reimburse.png 查看文件


二進制
assets/icons/menu/ic_menu_surattugas.png 查看文件


二進制
assets/icons/menu/ic_menu_surattugas_2.png 查看文件


二進制
assets/icons/menu/ic_refund.png 查看文件


二進制
assets/icons/menu/ic_reimburse.png 查看文件


二進制
assets/icons/menu/ic_slipgaji.png 查看文件


二進制
assets/icons/menu/ic_slipgaji_2.png 查看文件


二進制
assets/icons/menu/ic_surattugas.png 查看文件


二進制
assets/icons/menu/ic_surattugas_2.png 查看文件


二進制
assets/images/ic_calendaroff.png 查看文件


二進制
assets/images/ic_history.png 查看文件


二進制
assets/images/ic_logo.png 查看文件


二進制
assets/images/lines_card.png 查看文件


二進制
firebase-tools-instant-win.exe 查看文件


+ 8
- 0
ios/Runner/Info.plist 查看文件

@@ -47,5 +47,13 @@
47 47
 	<true/>
48 48
 	<key>UIApplicationSupportsIndirectInputEvents</key>
49 49
 	<true/>
50
+	<key>NSPhotoLibraryUsageDescription</key>
51
+	<string>Need to upload image</string>
52
+	<key>NSCameraUsageDescription</key>
53
+	<string>Need to upload image</string>
54
+	<key>NSMicrophoneUsageDescription</key>
55
+	<string>Need to upload image</string>
56
+	<key>NSLocationWhenInUseUsageDescription</key>
57
+	<key>NSLocationAlwaysUsageDescription</key>
50 58
 </dict>
51 59
 </plist>

+ 94
- 3
lib/Screens/ForgotPassword/forgotPassword_screen.dart 查看文件

@@ -1,8 +1,13 @@
1
+import 'dart:convert';
2
+
1 3
 import 'package:flutter/material.dart';
4
+import 'package:fluttertoast/fluttertoast.dart';
2 5
 import 'package:google_fonts/google_fonts.dart';
6
+import 'package:hris_selfservice_mobile/Screens/ForgotPassword/resetPassword_post.dart';
3 7
 import 'package:hris_selfservice_mobile/Screens/Login/background.dart';
4 8
 import 'package:hris_selfservice_mobile/Screens/Login/inputWidget.dart';
5 9
 import 'package:hris_selfservice_mobile/Screens/Login/login_screen.dart';
10
+import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart';
6 11
 
7 12
 class ForgotPasswordView extends StatefulWidget {
8 13
   @override
@@ -29,6 +34,23 @@ class ForgotPasswordScreen extends StatelessWidget {
29 34
 
30 35
   @override
31 36
   Widget build(BuildContext context) {
37
+    ProgressDialog loading = ProgressDialog(context);
38
+    loading = ProgressDialog(context,
39
+        type: ProgressDialogType.normal, isDismissible: false, showLogs: true);
40
+    loading.style(
41
+        message: 'Please Wait .....',
42
+        borderRadius: 5,
43
+        backgroundColor: Colors.white,
44
+        progressWidget: CircularProgressIndicator(),
45
+        elevation: 10.0,
46
+        padding: EdgeInsets.all(10),
47
+        insetAnimCurve: Curves.easeInOut,
48
+        progress: 0.0,
49
+        maxProgress: 100.0,
50
+        progressTextStyle: TextStyle(
51
+            color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
52
+        messageTextStyle: TextStyle(
53
+            color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600));
32 54
     return Column(
33 55
       children: <Widget>[
34 56
         Padding(
@@ -88,8 +110,77 @@ class ForgotPasswordScreen extends StatelessWidget {
88 110
                                 color: Colors.white,
89 111
                               ),
90 112
                             ),
91
-                            onTap: () {
92
-                              showAlertDialog(context);
113
+                            onTap: () async {
114
+                              if (emailController.text.toString().isEmpty){
115
+                                Fluttertoast.showToast(
116
+                                    msg: "Email Required",
117
+                                    toastLength: Toast.LENGTH_SHORT,
118
+                                    gravity: ToastGravity.CENTER,
119
+                                    timeInSecForIosWeb: 1,
120
+                                    textColor: Colors.white,
121
+                                    fontSize: 16.0);
122
+                              } else {
123
+                                await loading.show();
124
+                                ResetPassword_Post.connectToAPI(emailController.text.toString())
125
+                                    .then((valueResult) async{
126
+                                  Map<String, dynamic> object = json.decode(valueResult);
127
+                                  if (object.containsKey("result").toString() == "true") {
128
+                                    String status = object['result']['status'].toString();
129
+                                    String message = object['result']['message'].toString();
130
+                                    if (status == "success") {
131
+                                      emailController.clear();
132
+                                      await loading.hide();
133
+                                      Widget okButton = TextButton(
134
+                                        child: Text("OK"),
135
+                                        onPressed: () {
136
+                                          Navigator.of(context, rootNavigator: true).pop();
137
+                                          Navigator.pushAndRemoveUntil(
138
+                                              context,
139
+                                              MaterialPageRoute(
140
+                                                  builder: (context) => LoginView()),
141
+                                                  (route) => false);
142
+                                        },
143
+                                      );
144
+
145
+                                      // set up the AlertDialog
146
+                                      AlertDialog alert = AlertDialog(
147
+                                        title: Text("Employee Self Service"),
148
+                                        content: Text(message),
149
+                                        actions: [
150
+                                          okButton,
151
+                                        ],
152
+                                      );
153
+
154
+                                      // show the dialog
155
+                                      showDialog(
156
+                                        context: context,
157
+                                        builder: (BuildContext context) {
158
+                                          return alert;
159
+                                        },
160
+                                      );
161
+                                    } else if (status == "failed") {
162
+                                      String message = object['result']['message'].toString();
163
+                                      Fluttertoast.showToast(
164
+                                          msg: message,
165
+                                          toastLength: Toast.LENGTH_SHORT,
166
+                                          gravity: ToastGravity.CENTER,
167
+                                          timeInSecForIosWeb: 1,
168
+                                          textColor: Colors.white,
169
+                                          fontSize: 16.0);
170
+                                      await loading.hide();
171
+                                    }
172
+                                  } else {
173
+                                    Fluttertoast.showToast(
174
+                                        msg: "Server Response Error",
175
+                                        toastLength: Toast.LENGTH_SHORT,
176
+                                        gravity: ToastGravity.CENTER,
177
+                                        timeInSecForIosWeb: 1,
178
+                                        textColor: Colors.white,
179
+                                        fontSize: 16.0);
180
+                                    await loading.hide();
181
+                                  }
182
+                                });
183
+                              }
93 184
                             },
94 185
                           )
95 186
                         ],
@@ -169,7 +260,7 @@ showAlertDialog(BuildContext context) {
169 260
 
170 261
   // set up the AlertDialog
171 262
   AlertDialog alert = AlertDialog(
172
-    title: Text("HRIS Self Service"),
263
+    title: Text("Employee Self Service"),
173 264
     content: Text("Please check your email."),
174 265
     actions: [
175 266
       okButton,

+ 29
- 0
lib/Screens/ForgotPassword/resetPassword_post.dart 查看文件

@@ -0,0 +1,29 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'dart:developer' as developer;
6
+
7
+class ResetPassword_Post {
8
+  late String email;
9
+
10
+  ResetPassword_Post({required this.email});
11
+
12
+  static Future<String> connectToAPI(String email) async {
13
+    String URL = baseURL + "/api/v1/ask_reset_password";
14
+
15
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
16
+      "data": [
17
+        {
18
+          "email": email
19
+        }
20
+      ]
21
+    }), headers: {
22
+      "Content-Type": "application/json",
23
+      "Api-key": apiKey
24
+    });
25
+
26
+    developer.log(sendData.body, name: "sendatabody");
27
+    return sendData.body;
28
+  }
29
+}

+ 500
- 251
lib/Screens/Home/home_screen.dart 查看文件

@@ -1,13 +1,35 @@
1
+import 'dart:convert';
2
+import 'dart:typed_data';
3
+
1 4
 import 'package:double_back_to_close/double_back_to_close.dart';
2 5
 import 'package:flutter/material.dart';
6
+import 'package:fluttertoast/fluttertoast.dart';
3 7
 import 'package:google_fonts/google_fonts.dart';
4 8
 import 'package:hris_selfservice_mobile/Screens/Menu/About/about_screen.dart';
5 9
 import 'package:hris_selfservice_mobile/Screens/Menu/Absensi/absensi_screen.dart';
6 10
 import 'package:hris_selfservice_mobile/Screens/Menu/AjukanCuti/ajukancuti_screen.dart';
7
-import 'package:hris_selfservice_mobile/Screens/Menu/Berita/berita_screen.dart';
8
-import 'package:hris_selfservice_mobile/Screens/Menu/Lainnya/lainnya_screen.dart';
11
+import 'package:hris_selfservice_mobile/Screens/Menu/Reimburse/reimburse_screen.dart';
9 12
 import 'package:hris_selfservice_mobile/Screens/Menu/SlipGaji/slipgaji_screen.dart';
13
+import 'package:hris_selfservice_mobile/Screens/Menu/SuratTugas/surattugas_screen.dart';
10 14
 import 'package:hris_selfservice_mobile/Screens/Settings/settings_screen.dart';
15
+import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart';
16
+import 'package:shared_preferences/shared_preferences.dart';
17
+import 'dart:developer' as logDev;
18
+import '../Settings/RequestHttp/getDetail_post.dart';
19
+import '../Settings/RequestHttp/getProfileImage_post.dart';
20
+import 'package:location/location.dart';
21
+
22
+
23
+var _imageToShow;
24
+late String nameShared;
25
+String name = "",
26
+    statusDetail = "",
27
+    dateOfBirth = "",
28
+    phone = "",
29
+    email = "",
30
+    address = "",
31
+    position = "";
32
+
11 33
 
12 34
 class HomeView extends StatefulWidget {
13 35
   @override
@@ -15,20 +37,161 @@ class HomeView extends StatefulWidget {
15 37
 }
16 38
 
17 39
 class _HomeView extends State<HomeView> {
40
+  @override
41
+  initState() {
42
+    getDetail();
43
+    _imageToShow = AssetImage('assets/images/ic_administrator.png');
44
+    WidgetsBinding.instance.addPostFrameCallback((_) async {
45
+     /* final location = await getLocation();
46
+      logDev.log("Location: ${location.latitude}, ${location.longitude}");*/
47
+      ProgressDialog loading = ProgressDialog(context);
48
+      loading = ProgressDialog(context,
49
+          type: ProgressDialogType.normal,
50
+          isDismissible: false,
51
+          showLogs: true);
52
+      loading.style(
53
+          message: 'Please Wait .....',
54
+          borderRadius: 5,
55
+          backgroundColor: Colors.white,
56
+          progressWidget: CircularProgressIndicator(),
57
+          elevation: 10.0,
58
+          padding: EdgeInsets.all(10),
59
+          insetAnimCurve: Curves.easeInOut,
60
+          progress: 0.0,
61
+          maxProgress: 100.0,
62
+          progressTextStyle: TextStyle(
63
+              color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
64
+          messageTextStyle: TextStyle(
65
+              color: Colors.black,
66
+              fontSize: 15.0,
67
+              fontWeight: FontWeight.w600));
68
+      loading.show();
69
+      _imageToShow = getProfileImage();
70
+    });
71
+  }
72
+
73
+  //Get Profile image
74
+  getProfileImage() async {
75
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
76
+    final session = prefs.getString('session');
77
+
78
+    ProgressDialog loading = ProgressDialog(context);
79
+    loading = ProgressDialog(context,
80
+        type: ProgressDialogType.normal,
81
+        isDismissible: false,
82
+        showLogs: true);
83
+    loading.style(
84
+        message: 'Please Wait .....',
85
+        borderRadius: 5,
86
+        backgroundColor: Colors.white,
87
+        progressWidget: CircularProgressIndicator(),
88
+        elevation: 10.0,
89
+        padding: EdgeInsets.all(10),
90
+        insetAnimCurve: Curves.easeInOut,
91
+        progress: 0.0,
92
+        maxProgress: 100.0,
93
+        progressTextStyle: TextStyle(
94
+            color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
95
+        messageTextStyle: TextStyle(
96
+            color: Colors.black,
97
+            fontSize: 15.0,
98
+            fontWeight: FontWeight.w600));
99
+
100
+    GetProfileImage_Post.connectToAPI(session!).then((valueResult) async {
101
+      Map<String, dynamic> object = json.decode(valueResult);
102
+      if (object.containsKey("result").toString() == "true") {
103
+        String status = object['result']['status'].toString();
104
+        logDev.log(status, name: "STATUS GET PROFILE");
105
+        if (status == "success") {
106
+          String photo = object['result']['photo'].toString();
107
+          if (photo == "false") {
108
+            setState(() {
109
+              _imageToShow = AssetImage('assets/images/ic_administrator.png');
110
+            });
111
+          } else if (photo != "false") {
112
+            Uint8List decodedBytes = Base64Decoder().convert(photo);
113
+            logDev.log(decodedBytes.toString(), name: "DECODED BYTES photo");
114
+            setState(() {
115
+              _imageToShow = Image
116
+                  .memory(decodedBytes, gaplessPlayback: true)
117
+                  .image;
118
+            });
119
+          }
120
+        } else if (status == "failed") {
121
+          String message = object['result']['message'].toString();
122
+          Fluttertoast.showToast(
123
+              msg: message,
124
+              toastLength: Toast.LENGTH_LONG,
125
+              gravity: ToastGravity.CENTER,
126
+              timeInSecForIosWeb: 1,
127
+              textColor: Colors.white,
128
+              fontSize: 16.0);
129
+        }
130
+        loading.hide();
131
+      } else {
132
+        Fluttertoast.showToast(
133
+            msg: "Server Response Error",
134
+            toastLength: Toast.LENGTH_SHORT,
135
+            gravity: ToastGravity.CENTER,
136
+            timeInSecForIosWeb: 1,
137
+            textColor: Colors.white,
138
+            fontSize: 16.0);
139
+        loading.hide();
140
+      }
141
+    });
142
+    return _imageToShow;
143
+  }
144
+
145
+  //GetDetail
146
+  getDetail() async {
147
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
148
+    final session = prefs.getString('session');
149
+    GetDetail_Post.connectToAPI(session!).then((valueResult) async {
150
+      Map<String, dynamic> object = json.decode(valueResult);
151
+      if (object.containsKey("result").toString() == "true") {
152
+        statusDetail = object['result']['status'].toString();
153
+        String message = object['result']['message'].toString();
154
+        if (statusDetail == "failed" || message == "User Not Found") {
155
+          Fluttertoast.showToast(
156
+              msg: message + ", Please login again!",
157
+              toastLength: Toast.LENGTH_SHORT,
158
+              gravity: ToastGravity.CENTER,
159
+              timeInSecForIosWeb: 1,
160
+              textColor: Colors.white,
161
+              fontSize: 16.0);
162
+        } else if (statusDetail != "failed") {
163
+          name = object['result']['name'].toString();
164
+          dateOfBirth = object['result']['date_of_birth'].toString();
165
+          phone = object['result']['phone'].toString();
166
+          email = object['result']['email'].toString();
167
+          address = object['result']['address'].toString();
168
+          position = object['result']['position'].toString();
169
+        }
170
+      } else {
171
+        Fluttertoast.showToast(
172
+            msg: "Server Response Error",
173
+            toastLength: Toast.LENGTH_SHORT,
174
+            gravity: ToastGravity.CENTER,
175
+            timeInSecForIosWeb: 1,
176
+            textColor: Colors.white,
177
+            fontSize: 16.0);
178
+      }
179
+    });
180
+  }
181
+
18 182
   @override
19 183
   Widget build(BuildContext context) {
20 184
     return MaterialApp(
21 185
       home: DoubleBack(
22
-        onFirstBackPress: (context) {
186
+        /*onFirstBackPress: (context) {
23 187
           final snackBar = SnackBar(content: Text("Double Back Press to Exit"));
24 188
           ScaffoldMessenger.of(context).showSnackBar(snackBar);
25
-        },
189
+        },*/
26 190
         message: "Double Back Press to Exit",
27 191
         background: Colors.black38,
28 192
         backgroundRadius: 10,
29 193
         textStyle: TextStyle(
30
-            fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white
31
-        ),
194
+            fontSize: 16, fontWeight: FontWeight.bold, color: Colors.white),
32 195
         child: Scaffold(
33 196
             resizeToAvoidBottomInset: false,
34 197
             //backgroundColor: Colors.white,
@@ -44,284 +207,370 @@ class _HomeView extends State<HomeView> {
44 207
 }
45 208
 
46 209
 class HomeScreen extends StatelessWidget {
47
-  const HomeScreen({Key? key}) : super(key: key);
48
-
49 210
   @override
50 211
   Widget build(BuildContext context) {
51
-    var size = MediaQuery
52
-        .of(context)
53
-        .size;
212
+    var size = MediaQuery.of(context).size;
54 213
     return Scaffold(
55 214
         body: SingleChildScrollView(
56
-          child: Stack(
57
-            children: <Widget>[
58
-              Container(
59
-                height: size.height * 0.3,
60
-                decoration: BoxDecoration(
61
-                    gradient: LinearGradient(
62
-                        begin: Alignment.topRight,
63
-                        end: Alignment.bottomRight,
64
-                        colors: [
65
-                          Color(0xFFD21404),
66
-                          Color(0xFFFD7267),
67
-                        ])),
68
-              ),
69
-              SafeArea(
70
-                child: Padding(
71
-                  padding: EdgeInsets.all(20),
72
-                  child: Column(
73
-                    children: <Widget>[
74
-                      Align(
75
-                        alignment: Alignment.topRight,
76
-                        child: InkWell(
77
-                          child: Container(
78
-                              alignment: Alignment.center,
79
-                              height: 40,
80
-                              width: 40,
81
-                              child: Image.asset(
82
-                                  'assets/images/ic_settings.png')),
83
-                          onTap: () {
84
-                            Navigator.push(
85
-                                context,
86
-                                MaterialPageRoute(
87
-                                    builder: (context) =>
88
-                                        SettingsScreen()));
89
-                          },
90
-                        ),
91
-                      ),
92
-                      Stack(
93
-                        alignment: Alignment.topCenter,
94
-                        children: [
95
-                          Container(
96
-                            margin: EdgeInsets.only(top: ((size.width - 20) *
97
-                                0.3) * 0.5),
98
-                            child: Card(
99
-                              elevation: 15,
100
-                              child: Container(
101
-                                  height: size.width * 0.35,
102
-                                  width: size.width - 20,
103
-                                  padding: EdgeInsets.all(15),
104
-                                  decoration: BoxDecoration(
105
-                                      color: Colors.white,
106
-                                      borderRadius:
107
-                                      BorderRadius.all(Radius.circular(10))),
108
-                                  child: Column(
109
-                                    mainAxisAlignment: MainAxisAlignment.end,
110
-                                    crossAxisAlignment: CrossAxisAlignment
111
-                                        .center,
112
-                                    children: <Widget>[
113
-                                      Text(
114
-                                        'Dieni Anindyasarathi',
115
-                                        maxLines: 2,
116
-                                        overflow: TextOverflow.ellipsis,
117
-                                        textAlign: TextAlign.center,
118
-                                        style: GoogleFonts.inter(
119
-                                            fontSize: 17,
120
-                                            color: Colors.black,
121
-                                            fontWeight: FontWeight.bold),
122
-                                      ),
123
-                                      Text(
124
-                                        'IT Developer',
125
-                                        textAlign: TextAlign.center,
126
-                                        style: GoogleFonts.inter(
127
-                                            fontSize: 16, color: Colors.black),
128
-                                      ),
129
-                                    ],
130
-                                  )),
131
-                            ),
215
+      child: Stack(
216
+        children: <Widget>[
217
+          Container(
218
+            height: size.height * 0.3,
219
+            decoration: BoxDecoration(
220
+                gradient: LinearGradient(
221
+                    begin: Alignment.topRight,
222
+                    end: Alignment.bottomRight,
223
+                    colors: [
224
+                  Color(0xFFD21404),
225
+                  Color(0xFFFD7267),
226
+                ])),
227
+          ),
228
+          SafeArea(
229
+            child: Padding(
230
+              padding: EdgeInsets.all(20),
231
+              child: Column(
232
+                children: <Widget>[
233
+                  Align(
234
+                    alignment: Alignment.topRight,
235
+                    child: InkWell(
236
+                      child: Container(
237
+                          alignment: Alignment.center,
238
+                          height: 40,
239
+                          width: 40,
240
+                          child: Image.asset('assets/images/ic_settings.png')),
241
+                      onTap: () {
242
+                        Navigator.push(
243
+                            context,
244
+                            MaterialPageRoute(
245
+                                builder: (context) => SettingsScreen()));
246
+                      },
247
+                    ),
248
+                  ),
249
+                  Container(
250
+                    child:  Stack(
251
+                      alignment: Alignment.topLeft,
252
+                      children: [
253
+                        Container(
254
+                          margin: EdgeInsets.only(top: ((size.width - 20) * 0.33) * 0.5),
255
+                          child: Card(
256
+                            elevation: 15,
257
+                            child: Container(
258
+                                height: size.width * 0.35,
259
+                                width: size.width - 20,
260
+                                padding: EdgeInsets.all(15),
261
+                                decoration: BoxDecoration(
262
+                                    color: Colors.white,
263
+                                    borderRadius:
264
+                                    BorderRadius.all(Radius.circular(10))),
265
+                                child: Column(
266
+                                  mainAxisAlignment: MainAxisAlignment.end,
267
+                                  crossAxisAlignment: CrossAxisAlignment.center,
268
+                                  children: <Widget>[
269
+                                    Text(name,
270
+                                      maxLines: 2,
271
+                                      overflow: TextOverflow.ellipsis,
272
+                                      textAlign: TextAlign.center,
273
+                                      style: GoogleFonts.inter(
274
+                                          fontSize: 18,
275
+                                          color: Colors.black,
276
+                                          fontWeight: FontWeight.bold),
277
+                                    ),
278
+                                    Text(position,
279
+                                      textAlign: TextAlign.center,
280
+                                      style: GoogleFonts.inter(
281
+                                          fontSize: 17, color: Colors.black),
282
+                                    ),
283
+                                  ],
284
+                                )),
132 285
                           ),
133
-                          Container(
134
-                            alignment: Alignment.topCenter,
135
-                            height: (size.width - 20) * 0.3,
136
-                            width: (size.width - 20) * 0.3,
286
+                        ),
287
+                        Align(
288
+                          alignment: Alignment.topCenter,
289
+                          child: Container(
290
+                            margin: EdgeInsets.only(left: 15),
291
+                            alignment: Alignment.topLeft,
292
+                            height: (size.width - 20) * 0.33,
293
+                            width: (size.width - 20) * 0.33,
137 294
                             decoration: BoxDecoration(
138 295
                               color: Colors.black,
139 296
                               image: DecorationImage(
140
-                                image: AssetImage(
141
-                                    'assets/images/ic_administrator.png'),
297
+                                image: _imageToShow,
142 298
                                 fit: BoxFit.fill,
143 299
                               ),
144 300
                               shape: BoxShape.circle,
145 301
                             ),
146 302
                           ),
147
-                        ],
148
-                      ),
149
-                      GridView.count(
150
-                        shrinkWrap: true,
151
-                        physics: NeverScrollableScrollPhysics(),
152
-                        padding: EdgeInsets.only(top: 25, left: 5, right: 5),
153
-                        crossAxisSpacing: 15,
154
-                        mainAxisSpacing: 15,
155
-                        crossAxisCount: 2,
156
-                        children: <Widget>[
157
-                          InkWell(
158
-                            child: Container(
159
-                              decoration: BoxDecoration(
160
-                                  color: Color(0xFFD9D9D9),
161
-                                  borderRadius: BorderRadius.circular(5)),
162
-                              child: Column(
163
-                                crossAxisAlignment: CrossAxisAlignment.center,
164
-                                mainAxisAlignment: MainAxisAlignment.center,
165
-                                children: <Widget>[
166
-                                  Image.asset(
167
-                                    "assets/icons/menu/ic_menu_absensi2.png",
168
-                                    width: 75,
169
-                                    height: 75,
303
+                        ),
304
+                      ],
305
+                    ),
306
+                  ),
307
+                  GridView.count(
308
+                    shrinkWrap: true,
309
+                    physics: NeverScrollableScrollPhysics(),
310
+                    padding: EdgeInsets.only(top: 25, left: 5, right: 5),
311
+                    crossAxisSpacing: 15,
312
+                    mainAxisSpacing: 15,
313
+                    crossAxisCount: 2,
314
+                    children: <Widget>[
315
+                      InkWell(
316
+                          child: Container(
317
+                            decoration: BoxDecoration(
318
+                                color: Color(0xFFD0D0D0),
319
+                                borderRadius: BorderRadius.circular(5)),
320
+                            child: Column(
321
+                              crossAxisAlignment: CrossAxisAlignment.center,
322
+                              mainAxisAlignment: MainAxisAlignment.center,
323
+                              children: <Widget>[
324
+                                Container(
325
+                                  width: 75,
326
+                                  height: 75,
327
+                                  child: Image.asset(
328
+                                    "assets/icons/menu/ic_absensi.png",
329
+                                    fit: BoxFit.fill,
330
+                                    alignment: Alignment.center,
170 331
                                   ),
171
-                                  Text(
332
+                                ),
333
+                                Container(
334
+                                  margin: EdgeInsets.only(top: 10),
335
+                                  child: Text(
172 336
                                     'Absensi',
173 337
                                     textAlign: TextAlign.center,
174 338
                                     style: GoogleFonts.acme(
175 339
                                         fontSize: 18, color: Colors.black),
176
-                                  )
177
-                                ],
178
-                              ),
340
+                                  ),
341
+                                ),
342
+                              ],
179 343
                             ),
180
-                            onTap:(){
181
-                              Navigator.push(context, MaterialPageRoute(
182
-                                  builder: (context) => AbsensiScreen()));
183
-                            }
184 344
                           ),
185
-                          InkWell(
186
-                            child: Container(
187
-                              decoration: BoxDecoration(
188
-                                  color: Color(0xFFD9D9D9),
189
-                                  borderRadius: BorderRadius.circular(5)),
190
-                              child: Column(
191
-                                crossAxisAlignment: CrossAxisAlignment.center,
192
-                                mainAxisAlignment: MainAxisAlignment.center,
193
-                                children: <Widget>[
194
-                                  Image.asset(
195
-                                      "assets/icons/menu/ic_menu_slipgaji2.png",
196
-                                      height: 75,
197
-                                      width: 75),
198
-                                  Text(
199
-                                    'Slip Gaji',
200
-                                    textAlign: TextAlign.center,
201
-                                    style: GoogleFonts.acme(
202
-                                        fontSize: 18, color: Colors.black),
203
-                                  )
204
-                                ],
345
+                          onTap: () {
346
+                            Navigator.push(
347
+                                context,
348
+                                MaterialPageRoute(
349
+                                    builder: (context) => AbsensiScreen()));
350
+                          }),
351
+                      InkWell(
352
+                        child: Container(
353
+                          decoration: BoxDecoration(
354
+                              color: Color(0xFFD0D0D0),
355
+                              borderRadius: BorderRadius.circular(5)),
356
+                          child: Column(
357
+                            crossAxisAlignment: CrossAxisAlignment.center,
358
+                            mainAxisAlignment: MainAxisAlignment.center,
359
+                            children: <Widget>[
360
+                              Container(
361
+                                width: 75,
362
+                                height: 75,
363
+                                child: Image.asset(
364
+                                    "assets/icons/menu/ic_slipgaji_2.png",
365
+                                    fit: BoxFit.fill,
366
+                                    alignment: Alignment.center),
205 367
                               ),
206
-                            ),
207
-                            onTap: (){
208
-                              Navigator.push(context, MaterialPageRoute(
209
-                                  builder: (context) => SlipGajiScreen()));
210
-                            },
368
+                              Container(
369
+                                margin: EdgeInsets.only(top: 10),
370
+                                child: Text(
371
+                                  'Slip Gaji',
372
+                                  textAlign: TextAlign.center,
373
+                                  style: GoogleFonts.acme(
374
+                                      fontSize: 18, color: Colors.black),
375
+                                ),
376
+                              ),
377
+                            ],
211 378
                           ),
212
-                          InkWell(
213
-                            child: Container(
214
-                              decoration: BoxDecoration(
215
-                                  color: Color(0xFFD9D9D9),
216
-                                  borderRadius: BorderRadius.circular(5)),
217
-                              child: Column(
218
-                                crossAxisAlignment: CrossAxisAlignment.center,
219
-                                mainAxisAlignment: MainAxisAlignment.center,
220
-                                children: <Widget>[
221
-                                  Image.asset(
222
-                                      "assets/icons/menu/ic_menu_ajukancuti2.png",
223
-                                      height: 75,
224
-                                      width: 75),
225
-                                  Text(
226
-                                    'Ajukan Cuti',
227
-                                    textAlign: TextAlign.center,
228
-                                    style: GoogleFonts.acme(
229
-                                        fontSize: 18, color: Colors.black),
230
-                                  )
231
-                                ],
379
+                        ),
380
+                        onTap: () {
381
+                          Navigator.push(
382
+                              context,
383
+                              MaterialPageRoute(
384
+                                  builder: (context) => SlipGajiScreen()));
385
+                        },
386
+                      ),
387
+                      InkWell(
388
+                        child: Container(
389
+                          decoration: BoxDecoration(
390
+                              color: Color(0xFFD0D0D0),
391
+                              borderRadius: BorderRadius.circular(5)),
392
+                          child: Column(
393
+                            crossAxisAlignment: CrossAxisAlignment.center,
394
+                            mainAxisAlignment: MainAxisAlignment.center,
395
+                            children: <Widget>[
396
+                              Container(
397
+                                width: 70,
398
+                                height: 70,
399
+                                child: Image.asset(
400
+                                    "assets/icons/menu/ic_cuti_2.png",
401
+                                    fit: BoxFit.fill,
402
+                                    alignment: Alignment.center),
232 403
                               ),
233
-                            ),
234
-                            onTap: (){
235
-                              Navigator.push(context, MaterialPageRoute(
236
-                                  builder: (context) => AjukanCutiScreen()));
237
-                            },
404
+                              Container(
405
+                                margin: EdgeInsets.only(top: 10),
406
+                                child: Text(
407
+                                  'Ajukan Cuti',
408
+                                  textAlign: TextAlign.center,
409
+                                  style: GoogleFonts.acme(
410
+                                      fontSize: 18, color: Colors.black),
411
+                                ),
412
+                              ),
413
+                            ],
238 414
                           ),
239
-                          InkWell(
240
-                            child: Container(
241
-                              decoration: BoxDecoration(
242
-                                  color: Color(0xFFD9D9D9),
243
-                                  borderRadius: BorderRadius.circular(5)),
244
-                              child: Column(
245
-                                crossAxisAlignment: CrossAxisAlignment.center,
246
-                                mainAxisAlignment: MainAxisAlignment.center,
247
-                                children: <Widget>[
248
-                                  Image.asset(
249
-                                      "assets/icons/menu/ic_menu_berita2.png",
250
-                                      height: 75, width: 75),
251
-                                  Text(
252
-                                    'Berita',
253
-                                    textAlign: TextAlign.center,
254
-                                    style: GoogleFonts.acme(
255
-                                        fontSize: 18, color: Colors.black),
256
-                                  )
257
-                                ],
415
+                        ),
416
+                        onTap: () {
417
+                          Navigator.push(
418
+                              context,
419
+                              MaterialPageRoute(
420
+                                  builder: (context) => AjukanCutiScreen()));
421
+                        },
422
+                      ),
423
+                      /*InkWell(
424
+                        child: Container(
425
+                          decoration: BoxDecoration(
426
+                              color: Color(0xFFD0D0D0),
427
+                              borderRadius: BorderRadius.circular(5)),
428
+                          child: Column(
429
+                            crossAxisAlignment: CrossAxisAlignment.center,
430
+                            mainAxisAlignment: MainAxisAlignment.center,
431
+                            children: <Widget>[
432
+                              Container(
433
+                                width: 75,
434
+                                height: 75,
435
+                                child: Image.asset(
436
+                                    "assets/icons/menu/ic_menu_berita2.png"),
258 437
                               ),
259
-                            ),
260
-                            onTap: (){
261
-                              Navigator.push(context, MaterialPageRoute(
438
+                              Container(
439
+                                margin: EdgeInsets.only(top: 10),
440
+                                child: Text(
441
+                                  'Berita',
442
+                                  textAlign: TextAlign.center,
443
+                                  style: GoogleFonts.acme(
444
+                                      fontSize: 18, color: Colors.black),
445
+                                ),
446
+                              ),
447
+                            ],
448
+                          ),
449
+                        ),
450
+                        onTap: () {
451
+                          Navigator.push(
452
+                              context,
453
+                              MaterialPageRoute(
262 454
                                   builder: (context) => BeritaScreen()));
263
-                            },
455
+                        },
456
+                      ),*/
457
+                      InkWell(
458
+                        child: Container(
459
+                          decoration: BoxDecoration(
460
+                              color: Color(0xFFD0D0D0),
461
+                              borderRadius: BorderRadius.circular(5)),
462
+                          child: Column(
463
+                            crossAxisAlignment: CrossAxisAlignment.center,
464
+                            mainAxisAlignment: MainAxisAlignment.center,
465
+                            children: <Widget>[
466
+                              Container(
467
+                                width: 70,
468
+                                height: 70,
469
+                                child: Image.asset(
470
+                                  "assets/icons/menu/ic_surattugas_2.png",
471
+                                  fit: BoxFit.fill,
472
+                                  alignment: Alignment.center,
473
+                                ),
474
+                              ),
475
+                              Container(
476
+                                margin: EdgeInsets.only(top: 10),
477
+                                child: Text(
478
+                                  'Surat Tugas',
479
+                                  textAlign: TextAlign.center,
480
+                                  style: GoogleFonts.acme(
481
+                                      fontSize: 18, color: Colors.black),
482
+                                ),
483
+                              ),
484
+                            ],
264 485
                           ),
265
-                          InkWell(
266
-                            child: Container(
267
-                              decoration: BoxDecoration(
268
-                                  color: Color(0xFFD9D9D9),
269
-                                  borderRadius: BorderRadius.circular(5)),
270
-                              child: Column(
271
-                                crossAxisAlignment: CrossAxisAlignment.center,
272
-                                mainAxisAlignment: MainAxisAlignment.center,
273
-                                children: <Widget>[
274
-                                  Image.asset(
275
-                                      "assets/icons/menu/ic_menu_about2.png",
276
-                                      height: 75, width: 75),
277
-                                  Text(
278
-                                    'About',
279
-                                    textAlign: TextAlign.center,
280
-                                    style: GoogleFonts.acme(
281
-                                        fontSize: 18, color: Colors.black),
282
-                                  )
283
-                                ],
486
+                        ),
487
+                        onTap: () {
488
+                          Navigator.push(
489
+                              context,
490
+                              MaterialPageRoute(
491
+                                  builder: (context) => SuratTugas_Screen()));
492
+                        },
493
+                      ),
494
+                      InkWell(
495
+                        child: Container(
496
+                          decoration: BoxDecoration(
497
+                              color: Color(0xFFD0D0D0),
498
+                              borderRadius: BorderRadius.circular(5)),
499
+                          child: Column(
500
+                            crossAxisAlignment: CrossAxisAlignment.center,
501
+                            mainAxisAlignment: MainAxisAlignment.center,
502
+                            children: <Widget>[
503
+                              Container(
504
+                                width: 70,
505
+                                height: 70,
506
+                                child: Image.asset(
507
+                                    "assets/icons/menu/ic_reimburse.png",
508
+                                    fit: BoxFit.fill,
509
+                                    alignment: Alignment.center),
284 510
                               ),
285
-                            ),
286
-                            onTap: (){
287
-                              Navigator.push(context, MaterialPageRoute(
288
-                                  builder: (context) => AboutScreen()));
289
-                            },
511
+                              Container(
512
+                                margin: EdgeInsets.only(top: 10),
513
+                                child: Text(
514
+                                  'Reimburse',
515
+                                  textAlign: TextAlign.center,
516
+                                  style: GoogleFonts.acme(
517
+                                      fontSize: 18, color: Colors.black),
518
+                                ),
519
+                              ),
520
+                            ],
290 521
                           ),
291
-                          InkWell(
292
-                            child: Container(
293
-                              decoration: BoxDecoration(
294
-                                  color: Color(0xFFD9D9D9),
295
-                                  borderRadius: BorderRadius.circular(5)),
296
-                              child: Column(
297
-                                crossAxisAlignment: CrossAxisAlignment.center,
298
-                                mainAxisAlignment: MainAxisAlignment.center,
299
-                                children: <Widget>[
300
-                                  Image.asset(
301
-                                      "assets/icons/menu/ic_menu_lainnya.png",
302
-                                      height: 75, width: 75),
303
-                                  Text(
304
-                                    'Lainnya',
305
-                                    textAlign: TextAlign.center,
306
-                                    style: GoogleFonts.acme(
307
-                                        fontSize: 18, color: Colors.black),
308
-                                  )
309
-                                ],
522
+                        ),
523
+                        onTap: () {
524
+                          Navigator.push(
525
+                              context,
526
+                              MaterialPageRoute(
527
+                                  builder: (context) => ReimburseScreen()));
528
+                        },
529
+                      ),
530
+                      InkWell(
531
+                        child: Container(
532
+                          decoration: BoxDecoration(
533
+                              color: Color(0xFFD0D0D0),
534
+                              borderRadius: BorderRadius.circular(5)),
535
+                          child: Column(
536
+                            crossAxisAlignment: CrossAxisAlignment.center,
537
+                            mainAxisAlignment: MainAxisAlignment.center,
538
+                            children: <Widget>[
539
+                              Container(
540
+                                width: 70,
541
+                                height: 70,
542
+                                child: Image.asset(
543
+                                    "assets/icons/menu/ic_about_2.png",
544
+                                    fit: BoxFit.fill,
545
+                                    alignment: Alignment.center),
310 546
                               ),
311
-                            ),
312
-                            onTap: (){
313
-                              Navigator.push(context, MaterialPageRoute(
314
-                                  builder: (context) => LainnyaScreen()));
315
-                            },
547
+                              Container(
548
+                                margin: EdgeInsets.only(top: 10),
549
+                                child: Text(
550
+                                  'About',
551
+                                  textAlign: TextAlign.center,
552
+                                  style: GoogleFonts.acme(
553
+                                      fontSize: 18, color: Colors.black),
554
+                                ),
555
+                              ),
556
+                            ],
316 557
                           ),
317
-                        ],
318
-                      )
558
+                        ),
559
+                        onTap: () {
560
+                          Navigator.push(
561
+                              context,
562
+                              MaterialPageRoute(
563
+                                  builder: (context) => AboutScreen()));
564
+                        },
565
+                      ),
319 566
                     ],
320
-                  ),
321
-                ),
567
+                  )
568
+                ],
322 569
               ),
323
-            ],
570
+            ),
324 571
           ),
325
-        ));
572
+        ],
573
+      ),
574
+    ));
326 575
   }
327 576
 }

+ 8
- 16
lib/Screens/Login/background.dart 查看文件

@@ -13,14 +13,19 @@ class Background extends StatelessWidget {
13 13
           new Stack(
14 14
             alignment: Alignment.bottomCenter,
15 15
             children: <Widget>[
16
-              Padding(
16
+              Container(
17
+                alignment: Alignment.bottomCenter,
17 18
                 padding: EdgeInsets.only(top: 0),
18 19
                 child: Image.asset(
19 20
                   'assets/images/collaboration.png',
20 21
                   width: MediaQuery.of(context).size.width / 1.5,
21 22
                 ),
22 23
               ),
23
-              WavyHeader()
24
+              Container(
25
+                margin: EdgeInsets.all(0),
26
+                child:
27
+                WavyHeader(),
28
+              )
24 29
             ],
25 30
           ),
26 31
           Expanded(
@@ -41,9 +46,6 @@ class Background extends StatelessWidget {
41 46
 }
42 47
 
43 48
 const List<Color> orangeGradients = [
44
-  /*Color(0xFFFF9844),
45
-  Color(0xFFFE8853),
46
-  Color(0xFFFD7267),*/
47 49
   Color(0xFFD21404),
48 50
   Color(0xFFFD7267)
49 51
 ];
@@ -172,14 +174,4 @@ class FooterWaveClipper extends CustomClipper<Path> {
172 174
 
173 175
   @override
174 176
   bool shouldReclip(CustomClipper<Path> oldClipper) => false;
175
-}
176
-
177
-class YellowCircleClipper extends CustomClipper<Rect> {
178
-  @override
179
-  Rect getClip(Size size) {
180
-    throw UnimplementedError();
181
-  }
182
-
183
-  @override
184
-  bool shouldReclip(CustomClipper<Rect> oldClipper) => false;
185
-}
177
+}

+ 30
- 4
lib/Screens/Login/inputWidget.dart 查看文件

@@ -1,4 +1,5 @@
1 1
 import 'package:flutter/material.dart';
2
+import 'dart:developer' as logDev;
2 3
 
3 4
 class InputWidgetEmail extends StatelessWidget {
4 5
   final double topRight;
@@ -34,6 +35,14 @@ class InputWidgetEmail extends StatelessWidget {
34 35
                   ),
35 36
                   hintText: "hris_selfservice@example.com",
36 37
                   hintStyle: TextStyle(color: Color(0xFFE1E1E1), fontSize: 16)),
38
+              validator: (text) {
39
+                if (text!.contains('@') && text.isNotEmpty) {
40
+                  return "Enter a valid email address!";
41
+                } else if (text.isEmpty) {
42
+                  return "Email Required";
43
+                }
44
+                return null;
45
+              },
37 46
             ),
38 47
           ),
39 48
         ),
@@ -76,9 +85,9 @@ class InputWidgetPassword extends StatelessWidget {
76 85
                   ),
77 86
                   hintText: "Password",
78 87
                   hintStyle: TextStyle(color: Color(0xFFE1E1E1), fontSize: 16)),
79
-              validator: (text){
80
-                if (text!.contains('@') && text.isNotEmpty){
81
-                  return "Enter a valid email address!";
88
+              validator: (text) {
89
+                if (text == null) {
90
+                  return "Password Required";
82 91
                 }
83 92
                 return null;
84 93
               },
@@ -91,4 +100,21 @@ class InputWidgetPassword extends StatelessWidget {
91 100
 }
92 101
 
93 102
 TextEditingController emailController = TextEditingController();
94
-TextEditingController passwordController = TextEditingController();
103
+TextEditingController passwordController = TextEditingController();
104
+
105
+/*bool validate() {
106
+  bool result = true;
107
+  if (emailController.text.contains('@') && emailController.text.isNotEmpty) {
108
+    emailController. "Enter a valid email address!";
109
+    result = false;
110
+  } else if (emailValue.isEmpty) {
111
+  return "Email Required";
112
+  }
113
+
114
+  if (passwordController.text == null) {
115
+  return "Password Required";
116
+  }
117
+
118
+  return
119
+  null;
120
+}*/

+ 188
- 10
lib/Screens/Login/login_screen.dart 查看文件

@@ -1,9 +1,18 @@
1
+import 'dart:convert';
1 2
 import 'package:flutter/material.dart';
3
+import 'package:flutter/services.dart';
4
+import 'package:flutter_udid/flutter_udid.dart';
5
+import 'package:fluttertoast/fluttertoast.dart';
2 6
 import 'package:google_fonts/google_fonts.dart';
3 7
 import 'package:hris_selfservice_mobile/Screens/ForgotPassword/forgotPassword_screen.dart';
4 8
 import 'package:hris_selfservice_mobile/Screens/Login/background.dart';
5
-import 'package:hris_selfservice_mobile/Screens/Home/home_screen.dart';
9
+import 'package:hris_selfservice_mobile/Screens/Login/post_result_model.dart';
10
+import 'package:hris_selfservice_mobile/Screens/Splash/splash_screen.dart';
11
+import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart';
12
+import 'package:shared_preferences/shared_preferences.dart';
13
+import '../Home/home_screen.dart';
6 14
 import 'inputWidget.dart';
15
+import 'dart:developer' as logDev;
7 16
 
8 17
 class LoginView extends StatefulWidget {
9 18
   @override
@@ -26,16 +35,38 @@ class _LoginView extends State<LoginView> {
26 35
 }
27 36
 
28 37
 class LoginScreen extends StatelessWidget {
29
-  const LoginScreen({Key? key}) : super(key: key);
38
+  late LoginPostResult loginPostResult;
39
+  String version = "1.0.0";
40
+  String notif_token = "ginro";
30 41
 
31 42
   @override
32 43
   Widget build(BuildContext context) {
44
+    ProgressDialog loading = ProgressDialog(context);
45
+    loading = ProgressDialog(context,
46
+        type: ProgressDialogType.normal, isDismissible: false, showLogs: true);
47
+    loading.style(
48
+        message: 'Please Wait .....',
49
+        borderRadius: 5,
50
+        backgroundColor: Colors.white,
51
+        progressWidget: CircularProgressIndicator(),
52
+        elevation: 10.0,
53
+        padding: EdgeInsets.all(10),
54
+        insetAnimCurve: Curves.easeInOut,
55
+        progress: 0.0,
56
+        maxProgress: 100.0,
57
+        progressTextStyle: TextStyle(
58
+            color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
59
+        messageTextStyle: TextStyle(
60
+            color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600));
61
+
33 62
     return SingleChildScrollView(
34
-      child: Column(
63
+      reverse: true,
64
+        padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
65
+        child: Column(
35 66
         children: <Widget>[
36 67
           Padding(
37 68
             padding:
38
-            EdgeInsets.only(top: MediaQuery.of(context).size.height / 2.45),
69
+                EdgeInsets.only(top: MediaQuery.of(context).size.height / 2.45),
39 70
           ),
40 71
           Column(
41 72
             children: <Widget>[
@@ -93,8 +124,8 @@ class LoginScreen extends StatelessWidget {
93 124
                           children: <Widget>[
94 125
                             Expanded(
95 126
                                 child: Padding(
96
-                                  padding: EdgeInsets.only(top: 0),
97
-                                )),
127
+                              padding: EdgeInsets.only(top: 0),
128
+                            )),
98 129
                             InkWell(
99 130
                               child: Container(
100 131
                                 padding: EdgeInsets.all(10),
@@ -111,13 +142,82 @@ class LoginScreen extends StatelessWidget {
111 142
                                   color: Colors.white,
112 143
                                 ),
113 144
                               ),
114
-                              onTap: () {
115
-                                Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => HomeView()));
145
+                              onTap: () async {
146
+                                String imei;
147
+                                try {
148
+                                  imei = await FlutterUdid.udid;
149
+                                } on PlatformException {
150
+                                  imei = 'Failed to get UDID.';
151
+                                }
152
+                                logDev.log(imei, name: "IMEI");
153
+                                if (!validateForm(context)) {
154
+                                  return;
155
+                                } else {
156
+                                  await loading.show();
157
+                                  LoginPostResult.connectToAPI(
158
+                                          emailController.text.toString(),
159
+                                          passwordController.text.toString(),
160
+                                          notif_token,
161
+                                          version,
162
+                                          platform(),
163
+                                          imei)
164
+                                      .then((valueResult) async {
165
+                                    // loginPostResult = valueResult;
166
+                                    Map<String, dynamic> object = json.decode(valueResult);
167
+                                    if (object.containsKey("result").toString() == "true") {
168
+                                      String status = object['result']['status'].toString();
169
+                                      if (status == "success") {
170
+                                        Fluttertoast.showToast(
171
+                                            msg: "Login Success",
172
+                                            toastLength: Toast.LENGTH_SHORT,
173
+                                            gravity: ToastGravity.CENTER,
174
+                                            timeInSecForIosWeb: 1,
175
+                                            textColor: Colors.white,
176
+                                            fontSize: 16.0);
177
+
178
+                                        var prefs = await SharedPreferences.getInstance();
179
+                                        await prefs.setString('version', version);
180
+                                        await prefs.setString('device', object['result']['device'].toString());
181
+                                        await prefs.setString('session', object['result']['hash'].toString());
182
+                                        await prefs.setString('name', object['result']['name'].toString());
183
+                                        await prefs.setString('notif_token', notif_token);
184
+
185
+                                        emailController.clear();
186
+                                        passwordController.clear();
187
+
188
+                                        await loading.hide();
189
+                                        Navigator.pushReplacement(
190
+                                            context,
191
+                                            MaterialPageRoute(
192
+                                                builder: (context) =>
193
+                                                    HomeView()));
194
+                                      } else if (status == "failed") {
195
+                                        String message = object['result']
196
+                                                ['message']
197
+                                            .toString();
198
+                                        Fluttertoast.showToast(
199
+                                            msg: message,
200
+                                            toastLength: Toast.LENGTH_SHORT,
201
+                                            gravity: ToastGravity.CENTER,
202
+                                            timeInSecForIosWeb: 1,
203
+                                            textColor: Colors.white,
204
+                                            fontSize: 16.0);
205
+                                        await loading.hide();
206
+                                      }
207
+                                    } else {
208
+                                      await loading.hide();
209
+                                      alertDialogFailedResponse(context);
210
+                                    }
211
+                                  });
212
+                                }
116 213
                               },
117 214
                             )
118 215
                           ],
119 216
                         ),
120 217
                       ),
218
+                      /*Padding(
219
+                          padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom)
220
+                      )*/
121 221
                     ],
122 222
                   ),
123 223
                 ],
@@ -126,9 +226,13 @@ class LoginScreen extends StatelessWidget {
126 226
                 padding: EdgeInsets.only(bottom: 10),
127 227
               ),
128 228
               InkWell(
129
-                  child: roundedRectButton("Forgot Password?", Gradients1, false),
229
+                  child:
230
+                      roundedRectButton("Forgot Password?", Gradients1, false),
130 231
                   onTap: () {
131
-                    Navigator.push(context, MaterialPageRoute(builder: (context) => ForgotPasswordView()));
232
+                    Navigator.push(
233
+                        context,
234
+                        MaterialPageRoute(
235
+                            builder: (context) => ForgotPasswordView()));
132 236
                   })
133 237
             ],
134 238
           )
@@ -191,3 +295,77 @@ const List<Color> Gradients2 = [
191 295
   Color(0xFFFF9945),
192 296
   Color(0xFFFc6076),
193 297
 ];
298
+
299
+bool validateForm(BuildContext context) {
300
+  bool result = true;
301
+  if (emailController.text.toString().isEmpty) {
302
+    /*final snackBar = SnackBar(content: Text("Email Required"));
303
+    ScaffoldMessenger.of(context).showSnackBar(snackBar);*/
304
+    Fluttertoast.showToast(
305
+        msg: "Email Required",
306
+        toastLength: Toast.LENGTH_SHORT,
307
+        gravity: ToastGravity.CENTER,
308
+        timeInSecForIosWeb: 1,
309
+        textColor: Colors.white,
310
+        fontSize: 16.0);
311
+    result = false;
312
+  } else if (!emailController.text.toString().contains("@")) {
313
+    Fluttertoast.showToast(
314
+        msg: "Incorrect email format",
315
+        toastLength: Toast.LENGTH_SHORT,
316
+        gravity: ToastGravity.CENTER,
317
+        timeInSecForIosWeb: 1,
318
+        textColor: Colors.white,
319
+        fontSize: 16.0);
320
+    result = false;
321
+  } else if (passwordController.text.toString().isEmpty) {
322
+    Fluttertoast.showToast(
323
+        msg: "Password Required",
324
+        toastLength: Toast.LENGTH_SHORT,
325
+        gravity: ToastGravity.CENTER,
326
+        timeInSecForIosWeb: 1,
327
+        textColor: Colors.white,
328
+        fontSize: 16.0);
329
+    result = false;
330
+  }
331
+
332
+  return result;
333
+}
334
+
335
+alertDialogFailedResponse(BuildContext context){
336
+  Widget okButton = TextButton(
337
+    child: Text("Refresh"),
338
+    onPressed: () {
339
+      Navigator.of(context, rootNavigator: true).pop();
340
+      Navigator.pushReplacement(context, MaterialPageRoute(
341
+          builder: (context) => SplashScreen()));
342
+    },
343
+  );
344
+
345
+  Widget noButton = TextButton(
346
+    child: Text("Back"),
347
+    onPressed: () {
348
+      Navigator.of(context, rootNavigator: true).pop();
349
+      Navigator.pop(context);
350
+
351
+    },
352
+  );
353
+
354
+  // set up the AlertDialog
355
+  AlertDialog alert = AlertDialog(
356
+    title: Text("Employee Self Service"),
357
+    content: Text("Server Response Error"),
358
+    actions: [
359
+      noButton,
360
+      okButton,
361
+    ],
362
+  );
363
+
364
+  // show the dialog
365
+  showDialog(
366
+    context: context,
367
+    builder: (BuildContext context) {
368
+      return alert;
369
+    },
370
+  );
371
+}

+ 89
- 0
lib/Screens/Login/post_result_model.dart 查看文件

@@ -0,0 +1,89 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'dart:io' show Platform;
4
+import 'package:device_imei/device_imei.dart';
5
+import 'package:device_info_plus/device_info_plus.dart';
6
+import 'package:flutter/services.dart';
7
+import 'package:flutter_udid/flutter_udid.dart';
8
+import 'package:http/http.dart' as http;
9
+import 'package:hris_selfservice_mobile/constants.dart';
10
+import 'dart:developer' as developer;
11
+import 'package:device_imei/device_imei.dart';
12
+import 'package:shared_preferences/shared_preferences.dart';
13
+
14
+late String platformDevice;
15
+platform(){
16
+  if (Platform.isAndroid){
17
+    platformDevice = "android";
18
+  } else if (Platform.isIOS){
19
+    platformDevice = "ios";
20
+  }
21
+  return platformDevice;
22
+}
23
+
24
+class LoginPostResult {
25
+  late String email;
26
+  late String password;
27
+  late String notif_token;
28
+  late String version;
29
+  late String device;
30
+  late String imei;
31
+
32
+  LoginPostResult({required this.email,
33
+    required this.password,
34
+    required this.notif_token,
35
+    required this.version,
36
+    required this.device,
37
+    required this.imei});
38
+
39
+  /*factory LoginPostResult.createPostResult(Map<String, dynamic> object) {
40
+    return LoginPostResult(
41
+        email: object['username'],
42
+        password: object['password'],
43
+        notif_token: object['notif_token'],
44
+        version: object['version'],
45
+        device: object['device'],
46
+        imei: object['imei']);
47
+  }*/
48
+
49
+  static Future<String> connectToAPI(String email, String password, String notif_token,
50
+      String version, String device, String imei) async {
51
+    String URL = baseURL + "/api/v1/login";
52
+    print(URL);
53
+
54
+
55
+
56
+    /*DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
57
+    AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
58
+    developer.log(androidInfo.manufacturer, name: "MAP IMEI");
59
+    //imei = androidInfo.data;
60
+    developer.log(imei, name: "IMEI Number");
61
+
62
+    imei = await DeviceImei.getImei().toString();
63
+    developer.log(imei, name: "IMEI Number");*/
64
+
65
+
66
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
67
+      "data": [
68
+        {
69
+          "username": email,
70
+          "password": password,
71
+          "notif_token": notif_token,
72
+          "version": version,
73
+          "device": platform(),
74
+          "imei": imei
75
+        }
76
+      ]
77
+    }), headers: {
78
+      "Content-Type": "application/json",
79
+      "Api-key": apiKey
80
+    });
81
+
82
+    return sendData.body;
83
+
84
+    /*var jsonObject = json.decode(sendData.body);
85
+    developer.log(jsonObject.toString(), name: 'Log');*/
86
+    // return jsonObject;
87
+    // return LoginPostResult.createPostResult(jsonObject);
88
+  }
89
+}

+ 45
- 2
lib/Screens/Menu/About/about_screen.dart 查看文件

@@ -1,10 +1,53 @@
1 1
 import 'package:flutter/material.dart';
2
+import 'package:google_fonts/google_fonts.dart';
2 3
 
3
-class AboutScreen extends StatelessWidget {
4
+import '../SlipGaji/background.dart';
5
+
6
+class AboutScreen extends StatefulWidget {
4 7
   const AboutScreen({Key? key}) : super(key: key);
5 8
 
9
+  @override
10
+  State<AboutScreen> createState() => _AboutScreenState();
11
+}
12
+
13
+class _AboutScreenState extends State<AboutScreen> {
6 14
   @override
7 15
   Widget build(BuildContext context) {
8
-    return Container();
16
+    return Scaffold(
17
+      body: SingleChildScrollView(
18
+          child: Column(
19
+            children: <Widget>[
20
+              Stack(
21
+                children: [
22
+                  WavyHeader(),
23
+                  Container(
24
+                      margin: EdgeInsets.only(top: 90),
25
+                      padding: EdgeInsets.fromLTRB(20, 5, 25, 5),
26
+                      child: Row(
27
+                        mainAxisAlignment: MainAxisAlignment.end,
28
+                        crossAxisAlignment: CrossAxisAlignment.end,
29
+                        children: [
30
+                          Text(
31
+                            'About\t\t',
32
+                            maxLines: 1,
33
+                            style: GoogleFonts.luckiestGuy(
34
+                              fontSize: 28,
35
+                              color: Colors.red,
36
+                              fontStyle: FontStyle.italic,
37
+                            ),
38
+                          ),
39
+                          Image.asset(
40
+                            'assets/icons/menu/ic_info.png',
41
+                            width: 40,
42
+                            height: 40,
43
+                          ),
44
+                        ],
45
+                      )),
46
+                ],
47
+              ),
48
+            ],
49
+          )),
50
+    );
9 51
   }
10 52
 }
53
+

+ 10
- 0
lib/Screens/Menu/Absensi/absensi_history_screen.dart 查看文件

@@ -0,0 +1,10 @@
1
+import 'package:flutter/material.dart';
2
+
3
+class HistoryAbsensi extends StatelessWidget {
4
+  const HistoryAbsensi({Key? key}) : super(key: key);
5
+
6
+  @override
7
+  Widget build(BuildContext context) {
8
+    return Container();
9
+  }
10
+}

+ 354
- 1
lib/Screens/Menu/Absensi/absensi_screen.dart 查看文件

@@ -1,14 +1,367 @@
1 1
 import 'package:flutter/material.dart';
2
+import 'package:flutter_map/plugin_api.dart';
3
+import 'package:geolocator/geolocator.dart';
4
+import 'package:google_maps_flutter/google_maps_flutter.dart';
5
+import 'package:hris_selfservice_mobile/Screens/Menu/Absensi/absensi_history_screen.dart';
6
+import 'package:latlong/latlong.dart' as latlong;
7
+import 'package:latlong2/latlong.dart';
2 8
 
3
-class AbsensiScreen extends StatelessWidget {
9
+
10
+class AbsensiScreen extends StatefulWidget {
4 11
   const AbsensiScreen({Key? key}) : super(key: key);
5 12
 
13
+  @override
14
+  State<AbsensiScreen> createState() => _AbsensiScreenState();
15
+}
16
+
17
+class _AbsensiScreenState extends State<AbsensiScreen> {
18
+  double long = 49.5;
19
+  double lat = -0.09;
20
+  latlong.LatLng point = latlong.LatLng(-6.186729296979901, 106.93023205185953);
21
+  var location = [];
22
+
6 23
   @override
7 24
   Widget build(BuildContext context) {
25
+    var size = MediaQuery.of(context).size;
26
+
8 27
     return Scaffold(
9 28
       body: SingleChildScrollView(
29
+        child: Column(
30
+          children: [
31
+            Container(
32
+              //Ganti yg ini untuk maps
33
+              height: size.height * 0.3,
34
+              child: FlutterMap(
35
+                options: MapOptions(
36
+                  center: point,
37
+                    zoom: 10.0,
38
+                ),
39
+                children: [
40
+                  TileLayer(
41
+                    minZoom: 1,
42
+                    maxZoom: 18,
43
+                    backgroundColor: Colors.black54,
44
+                    urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
45
+                    subdomains: ['a', 'b', 'c'],
46
+                  )
47
+                ],
48
+              )
49
+            ),
50
+            Container(
51
+              width: double.infinity,
52
+              margin: EdgeInsets.fromLTRB(10, 10, 10, 10),
53
+              decoration:
54
+                  BoxDecoration(border: Border.all(color: Colors.black)),
55
+              child: Column(
56
+                children: <Widget>[
57
+                  Container(
58
+                    child: Text("Attendance"),
59
+                    width: double.infinity,
60
+                    alignment: Alignment.center,
61
+                    decoration: BoxDecoration(
62
+                        gradient: LinearGradient(
63
+                            begin: Alignment.topRight,
64
+                            end: Alignment.bottomRight,
65
+                            colors: [
66
+                              Color(0xFFD21404),
67
+                              Color(0xFFFD7267),
68
+                            ]),
69
+                        border: Border.all(color: Colors.black)),
70
+                  ),
71
+                  Container(
72
+                    width: double.infinity,
73
+                    padding: EdgeInsets.all(15),
74
+                    child: Row(
75
+                      mainAxisAlignment: MainAxisAlignment.spaceAround,
76
+                      children: [
77
+                        Column(
78
+                          children: [
79
+                            Text('Check In'),
80
+                            Text('07.15'),
81
+                          ],
82
+                        ),
83
+                        Column(
84
+                          children: [
85
+                            Text('Check Out'),
86
+                            Text('16.45'),
87
+                          ],
88
+                        ),
89
+                      ],
90
+                    ),
91
+                  )
92
+                ],
93
+              ),
94
+            ),
95
+            Row(
96
+              mainAxisAlignment: MainAxisAlignment.center,
97
+              children: [
98
+                Visibility(
99
+                  visible: true,
100
+                  child: ElevatedButton(
101
+                    onPressed: () {
102
+                      ScaffoldMessenger.of(context).showSnackBar(
103
+                          const SnackBar(content: Text('Check Status Button')));
104
+                    },
105
+                    child: Text('Check In'),
106
+                    style: ButtonStyle(
107
+                        backgroundColor: MaterialStateProperty.all(Colors.red)),
108
+                  ),
109
+                ),
110
+                Visibility(
111
+                  visible: false,
112
+                  child: ElevatedButton(
113
+                    onPressed: () {
114
+                      ScaffoldMessenger.of(context).showSnackBar(
115
+                          const SnackBar(content: Text('Check Status Button')));
116
+                    },
117
+                    child: Text('Check Out'),
118
+                    style: ButtonStyle(
119
+                        backgroundColor: MaterialStateProperty.all(Colors.red)),
120
+                  ),
121
+                ),
122
+              ],
123
+            ),
124
+            InkWell(
125
+              child: Container(
126
+                alignment: Alignment.centerRight,
127
+                child:
128
+                    TextButton(onPressed: () {}, child: Text('View More...')),
129
+              ),
130
+              onTap: () {
131
+                Navigator.push(context,
132
+                    MaterialPageRoute(builder: (context) => HistoryAbsensi()));
133
+              },
134
+            ),
135
+            Container(
136
+                width: double.infinity,
137
+                margin: EdgeInsets.fromLTRB(10, 10, 10, 0),
138
+                padding: EdgeInsets.all(15),
139
+                decoration:
140
+                    BoxDecoration(border: Border.all(color: Colors.black)),
141
+                child: Column(
142
+                  children: [
143
+                    Row(
144
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
145
+                      children: [
146
+                        Text('Rabu, 23 November 2022', maxLines: 1),
147
+                        Column(
148
+                          children: [Text('Check In'), Text('07.00')],
149
+                        ),
150
+                        Column(
151
+                          children: [
152
+                            Text('Check Out'),
153
+                            Text('16.30'),
154
+                          ],
155
+                        ),
156
+                      ],
157
+                    ),
158
+                    Text('Location : Global Service Indonesia', maxLines: 1),
159
+                  ],
160
+                )),
161
+            Container(
162
+                width: double.infinity,
163
+                margin: EdgeInsets.fromLTRB(10, 10, 10, 0),
164
+                padding: EdgeInsets.all(15),
165
+                decoration:
166
+                    BoxDecoration(border: Border.all(color: Colors.black)),
167
+                child: Column(
168
+                  children: [
169
+                    Row(
170
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
171
+                      children: [
172
+                        Text('Rabu, 23 November 2022', maxLines: 1),
173
+                        Column(
174
+                          children: [Text('Check In'), Text('07.00')],
175
+                        ),
176
+                        Column(
177
+                          children: [
178
+                            Text('Check Out'),
179
+                            Text('16.30'),
180
+                          ],
181
+                        ),
182
+                      ],
183
+                    ),
184
+                    Text('Location : Global Service Indonesia', maxLines: 1),
185
+                  ],
186
+                )),
187
+            Container(
188
+                width: double.infinity,
189
+                margin: EdgeInsets.fromLTRB(10, 10, 10, 0),
190
+                padding: EdgeInsets.all(15),
191
+                decoration:
192
+                    BoxDecoration(border: Border.all(color: Colors.black)),
193
+                child: Column(
194
+                  children: [
195
+                    Row(
196
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
197
+                      children: [
198
+                        Text('Rabu, 23 November 2022', maxLines: 1),
199
+                        Column(
200
+                          children: [Text('Check In'), Text('07.00')],
201
+                        ),
202
+                        Column(
203
+                          children: [
204
+                            Text('Check Out'),
205
+                            Text('16.30'),
206
+                          ],
207
+                        ),
208
+                      ],
209
+                    ),
210
+                    Text('Location : Global Service Indonesia', maxLines: 1),
211
+                  ],
212
+                )),
213
+            Container(
214
+                width: double.infinity,
215
+                margin: EdgeInsets.fromLTRB(10, 10, 10, 0),
216
+                padding: EdgeInsets.all(15),
217
+                decoration:
218
+                    BoxDecoration(border: Border.all(color: Colors.black)),
219
+                child: Column(
220
+                  children: [
221
+                    Row(
222
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
223
+                      children: [
224
+                        Text('Rabu, 23 November 2022', maxLines: 1),
225
+                        Column(
226
+                          children: [Text('Check In'), Text('07.00')],
227
+                        ),
228
+                        Column(
229
+                          children: [
230
+                            Text('Check Out'),
231
+                            Text('16.30'),
232
+                          ],
233
+                        ),
234
+                      ],
235
+                    ),
236
+                    Text('Location : Global Service Indonesia', maxLines: 1),
237
+                  ],
238
+                )),
239
+            Container(
240
+                width: double.infinity,
241
+                margin: EdgeInsets.fromLTRB(10, 10, 10, 0),
242
+                padding: EdgeInsets.all(15),
243
+                decoration:
244
+                    BoxDecoration(border: Border.all(color: Colors.black)),
245
+                child: Column(
246
+                  children: [
247
+                    Row(
248
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
249
+                      children: [
250
+                        Text('Rabu, 23 November 2022', maxLines: 1),
251
+                        Column(
252
+                          children: [Text('Check In'), Text('07.00')],
253
+                        ),
254
+                        Column(
255
+                          children: [
256
+                            Text('Check Out'),
257
+                            Text('16.30'),
258
+                          ],
259
+                        ),
260
+                      ],
261
+                    ),
262
+                    Text('Location : Global Service Indonesia', maxLines: 1),
263
+                  ],
264
+                )),
265
+            Container(
266
+                width: double.infinity,
267
+                margin: EdgeInsets.fromLTRB(10, 10, 10, 0),
268
+                padding: EdgeInsets.all(15),
269
+                decoration:
270
+                    BoxDecoration(border: Border.all(color: Colors.black)),
271
+                child: Column(
272
+                  children: [
273
+                    Row(
274
+                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
275
+                      children: [
276
+                        Text('Rabu, 23 November 2022', maxLines: 1),
277
+                        Column(
278
+                          children: [Text('Check In'), Text('07.00')],
279
+                        ),
280
+                        Column(
281
+                          children: [
282
+                            Text('Check Out'),
283
+                            Text('16.30'),
284
+                          ],
285
+                        ),
286
+                      ],
287
+                    ),
288
+                    Text('Location : Global Service Indonesia', maxLines: 1),
289
+                  ],
290
+                )),
10 291
 
292
+            /*SizedBox(
293
+              */ /*child: GoogleMap(
294
+                initialCameraPosition: initialCameraPosition,
295
+                markers: markers,
296
+                zoomControlsEnabled: false,
297
+                mapType: MapType.normal,
298
+                onMapCreated: (GoogleMapController controller) {
299
+                  googleMapController = controller;
300
+                },
301
+              ),
302
+            ),*/ /*
303
+            ),*/
304
+          ],
305
+        ),
11 306
       ),
307
+      /* floatingActionButton: FloatingActionButton.extended(
308
+        onPressed: () async {
309
+          Position position = await _determinePosition();
310
+          googleMapController
311
+              .animateCamera(CameraUpdate.newCameraPosition(CameraPosition(
312
+              target: LatLng(position.latitude, position.longitude),
313
+              zoom: 14)));
314
+          markers.clear();
315
+          markers.add(Marker(markerId: const MarkerId('currentLocation'),
316
+              position: LatLng(position.latitude, position.longitude)));
317
+          setState(() {});
318
+        },
319
+        label: Text("Current Location"),
320
+        icon: Icon(Icons.location_history),),*/
12 321
     );
13 322
   }
14 323
 }
324
+
325
+/*_getCurrentLocation() {
326
+  Geolocator
327
+      .getCurrentPosition(desiredAccuracy: LocationAccuracy.best, forceAndroidLocationManager: true)
328
+      .then((Position position) {
329
+    setState(() {
330
+      _currentPosition = position;
331
+      _getAddressFromLatLng();
332
+    });
333
+  }).catchError((e) {
334
+    print(e);
335
+  });
336
+}*/
337
+
338
+
339
+/*
340
+Future<Position> _determinePosition() async {
341
+  bool serviceEnabled;
342
+  LocationPermission permission;
343
+
344
+  serviceEnabled = await Geolocator.isLocationServiceEnabled();
345
+
346
+  if (!serviceEnabled) {
347
+    return Future.error('Location services are disabled');
348
+  }
349
+
350
+  permission = await Geolocator.checkPermission();
351
+
352
+  if (permission == LocationPermission.denied) {
353
+    permission = await Geolocator.requestPermission();
354
+
355
+    if (permission == LocationPermission.denied) {
356
+      return Future.error("Location permission denied");
357
+    }
358
+  }
359
+
360
+  if (permission == LocationPermission.deniedForever) {
361
+    return Future.error('Location permissions are permanently denied');
362
+  }
363
+
364
+  Position position = await Geolocator.getCurrentPosition();
365
+
366
+  return position;
367
+}*/

+ 39
- 0
lib/Screens/Menu/AjukanCuti/RequestHttp/detailCuti_post.dart 查看文件

@@ -0,0 +1,39 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'dart:developer' as developer;
6
+
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+class DetailCuti_Post {
10
+  late String session;
11
+
12
+  DetailCuti_Post({required this.session});
13
+
14
+  static Future<String> connectToAPI() async {
15
+    String URL = baseURL + "/api/v1/detail_cuti";
16
+
17
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
18
+    final session = prefs.getString('session');
19
+
20
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
21
+      "data": [
22
+        {
23
+          "session": session
24
+        }
25
+      ]
26
+    }), headers: {
27
+      "Content-Type": "application/json",
28
+      "Api-key": apiKey
29
+    });
30
+
31
+    developer.log(sendData.body, name: "Get Jenis Cuti Result");
32
+    return sendData.body;
33
+
34
+    /*var jsonObject = json.decode(sendData.body);
35
+    developer.log(jsonObject.toString(), name: 'Log');*/
36
+    // return jsonObject;
37
+    // return LoginPostResult.createPostResult(jsonObject);
38
+  }
39
+}

+ 39
- 0
lib/Screens/Menu/AjukanCuti/RequestHttp/historyCuti_post.dart 查看文件

@@ -0,0 +1,39 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'dart:developer' as developer;
6
+
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+class HistoryCuti_Post {
10
+  late String session;
11
+
12
+  HistoryCuti_Post({required this.session});
13
+
14
+  static Future<String> connectToAPI() async {
15
+    String URL = baseURL + "/api/v1/list_cuti";
16
+
17
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
18
+    final session = prefs.getString('session');
19
+
20
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
21
+      "data": [
22
+        {
23
+          "session": session
24
+        }
25
+      ]
26
+    }), headers: {
27
+      "Content-Type": "application/json",
28
+      "Api-key": apiKey
29
+    });
30
+
31
+    //developer.log(sendData.body, name: "Get Jenis Cuti Result");
32
+    return sendData.body;
33
+
34
+    /*var jsonObject = json.decode(sendData.body);
35
+    developer.log(jsonObject.toString(), name: 'Log');*/
36
+    // return jsonObject;
37
+    // return LoginPostResult.createPostResult(jsonObject);
38
+  }
39
+}

+ 39
- 0
lib/Screens/Menu/AjukanCuti/RequestHttp/jenisCuti_post.dart 查看文件

@@ -0,0 +1,39 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'dart:developer' as developer;
6
+
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+class JenisCuti_Post {
10
+  late String session;
11
+
12
+  JenisCuti_Post({required this.session});
13
+
14
+  static Future<String> connectToAPI() async {
15
+    String URL = baseURL + "/api/v1/jenis_cuti";
16
+
17
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
18
+    final session = prefs.getString('session');
19
+
20
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
21
+      "data": [
22
+        {
23
+          "session": session
24
+        }
25
+      ]
26
+    }), headers: {
27
+      "Content-Type": "application/json",
28
+      "Api-key": apiKey
29
+    });
30
+
31
+    developer.log(sendData.body, name: "Get Jenis Cuti Result");
32
+    return sendData.body;
33
+
34
+    /*var jsonObject = json.decode(sendData.body);
35
+    developer.log(jsonObject.toString(), name: 'Log');*/
36
+    // return jsonObject;
37
+    // return LoginPostResult.createPostResult(jsonObject);
38
+  }
39
+}

+ 49
- 0
lib/Screens/Menu/AjukanCuti/RequestHttp/pengajuanCuti_post.dart 查看文件

@@ -0,0 +1,49 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'dart:developer' as developer;
6
+
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+class PengajuanCuti_Post {
10
+  late String session;
11
+  late String tipe;
12
+  late String date_from;
13
+  late String date_to;
14
+  late String deskripsi;
15
+  late List<String> file;
16
+
17
+  PengajuanCuti_Post({required this.session});
18
+
19
+  static Future<String> connectToAPI(String tipe, String date_from, String date_to, String deskripsi, List<String> file) async {
20
+    String URL = baseURL + "/api/v1/pengajuan_cuti";
21
+
22
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
23
+    final session = prefs.getString('session');
24
+
25
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
26
+      "data": [
27
+        {
28
+          "session": session,
29
+          "tipe" : tipe,
30
+          "date_from" : date_from,
31
+          "date_to" : date_to,
32
+          "deskripsi" : deskripsi,
33
+          "file" : file
34
+        }
35
+      ]
36
+    }), headers: {
37
+      "Content-Type": "application/json",
38
+      "Api-key": apiKey
39
+    });
40
+
41
+    developer.log(sendData.body, name: "Get Jenis Cuti Result");
42
+    return sendData.body;
43
+
44
+    /*var jsonObject = json.decode(sendData.body);
45
+    developer.log(jsonObject.toString(), name: 'Log');*/
46
+    // return jsonObject;
47
+    // return LoginPostResult.createPostResult(jsonObject);
48
+  }
49
+}

+ 815
- 2
lib/Screens/Menu/AjukanCuti/ajukancuti_screen.dart 查看文件

@@ -1,10 +1,823 @@
1
+import 'dart:convert';
2
+import 'dart:io';
3
+import 'package:file_picker/file_picker.dart';
4
+import 'package:flutter/cupertino.dart';
1 5
 import 'package:flutter/material.dart';
6
+import 'package:fluttertoast/fluttertoast.dart';
7
+import 'package:google_fonts/google_fonts.dart';
8
+import 'package:hris_selfservice_mobile/Screens/Menu/AjukanCuti/RequestHttp/jenisCuti_post.dart';
9
+import 'package:hris_selfservice_mobile/Screens/Menu/AjukanCuti/RequestHttp/pengajuanCuti_post.dart';
10
+import 'package:hris_selfservice_mobile/Screens/Menu/AjukanCuti/history_cuti.dart';
11
+import 'package:intl/intl.dart';
12
+import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart';
2 13
 
3
-class AjukanCutiScreen extends StatelessWidget {
14
+import 'dart:developer' as logDev;
15
+import '../SlipGaji/background.dart';
16
+
17
+List<String> fileAttach = [""];
18
+TextEditingController deskripsiTeksController = TextEditingController();
19
+
20
+class AjukanCutiScreen extends StatefulWidget {
4 21
   const AjukanCutiScreen({Key? key}) : super(key: key);
5 22
 
23
+  @override
24
+  State<AjukanCutiScreen> createState() => _AjukanCutiScreenState();
25
+}
26
+
27
+class _AjukanCutiScreenState extends State<AjukanCutiScreen> {
28
+  var selectedType;
29
+
30
+  String _fileText = "";
31
+  String _totalFile= "";
32
+
33
+  bool visibleDateFrom = false;
34
+  bool visibleDateTo = false;
35
+
36
+  late List <String> idCutiType;
37
+  late List <String> cutiType;
38
+
39
+  DateTime dateFrom = DateTime.now();
40
+  DateTime dateTo = DateTime.now();
41
+
42
+  late String formattedDateFrom = "";
43
+  late String formattedDateTo = "";
44
+  late String idCuti;
45
+
46
+  initState(){
47
+    deskripsiTeksController.clear();
48
+    cutiType = [""];
49
+    idCutiType = [""];
50
+    WidgetsBinding.instance.addPostFrameCallback((_) {
51
+      cutiType = getJenisCuti();
52
+    });
53
+    super.initState();
54
+  }
55
+
56
+  getJenisCuti () {
57
+    ProgressDialog loading = ProgressDialog(context);
58
+    loading = ProgressDialog(context,
59
+        type: ProgressDialogType.normal, isDismissible: false, showLogs: true);
60
+    loading.style(
61
+        message: 'Please Wait .....',
62
+        borderRadius: 3,
63
+        backgroundColor: Colors.white,
64
+        progressWidget: CircularProgressIndicator(),
65
+        elevation: 10.0,
66
+        padding: EdgeInsets.all(10),
67
+        insetAnimCurve: Curves.easeInOut,
68
+        progress: 0.0,
69
+        maxProgress: 100.0,
70
+        progressTextStyle: TextStyle(
71
+            color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
72
+        messageTextStyle: TextStyle(
73
+            color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600));
74
+
75
+    loading.show();
76
+    JenisCuti_Post.connectToAPI().then((valueResult) async {
77
+      Map<String, dynamic> object = json.decode(valueResult);
78
+      if (object.containsKey("result").toString() == "true"){
79
+        String result = object['result'].toString();
80
+        logDev.log(result, name: "Jenis Cuti Result");
81
+        if (result.contains("Failed")) {
82
+          loading.hide();
83
+          setState(() {
84
+            cutiType = [""];
85
+            alertDialogFailedRetrievedData(context);
86
+          });
87
+        } else {
88
+          List <dynamic> jenis = object['result']['jenis'];
89
+          setState(() {
90
+            idCutiType.removeAt(0);
91
+            cutiType.removeAt(0);
92
+            for (int i = 0; i < jenis.length; i++){
93
+              String id = jenis[i]['id'].toString();
94
+              String text = jenis[i]['text'].toString();
95
+              idCutiType.add(id);
96
+              cutiType.add(text);
97
+            }
98
+          });
99
+          loading.hide();
100
+        }
101
+      } else {
102
+        setState((){
103
+          cutiType = [""];
104
+          alertDialogFailedResponse(context);
105
+          /*Fluttertoast.showToast(
106
+              msg: "Server Response Error",
107
+              toastLength: Toast.LENGTH_SHORT,
108
+              gravity: ToastGravity.CENTER,
109
+              timeInSecForIosWeb: 1,
110
+              textColor: Colors.white,
111
+              fontSize: 16.0);*/
112
+        });
113
+        loading.hide();
114
+      }
115
+    });
116
+    return cutiType;
117
+  }
118
+
6 119
   @override
7 120
   Widget build(BuildContext context) {
8
-    return Container();
121
+    return Scaffold(
122
+      body: SingleChildScrollView(
123
+          child: Column(
124
+        children: <Widget>[
125
+          Stack(
126
+            children: [
127
+              WavyHeader(),
128
+              Container(
129
+                  margin: EdgeInsets.only(top: 90),
130
+                  padding: EdgeInsets.fromLTRB(20, 5, 25, 5),
131
+                  child: Row(
132
+                    mainAxisAlignment: MainAxisAlignment.end,
133
+                    crossAxisAlignment: CrossAxisAlignment.end,
134
+                    children: [
135
+                      Text(
136
+                        'Ajukan Cuti\t\t',
137
+                        maxLines: 1,
138
+                        style: GoogleFonts.luckiestGuy(
139
+                          fontSize: 28,
140
+                          color: Colors.red,
141
+                          fontStyle: FontStyle.italic,
142
+                        ),
143
+                      ),
144
+                      Image.asset(
145
+                        'assets/icons/menu/ic_cuti.png',
146
+                        width: 40,
147
+                        height: 40,
148
+                      ),
149
+                    ],
150
+                  )),
151
+              SafeArea(
152
+                child: Container(
153
+                  width: MediaQuery.of(context).size.width,
154
+                  margin: EdgeInsets.only(
155
+                    top: MediaQuery.of(context).size.height / 5,
156
+                    left: 10,
157
+                    right: 10,
158
+                  ),
159
+                  child: Column(
160
+                    children: [
161
+                      InkWell(
162
+                        child: Container(
163
+                            margin: EdgeInsets.only(top: 15, bottom: 15),
164
+                            padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
165
+                            width: double.infinity,
166
+                            decoration: BoxDecoration(
167
+                                borderRadius: BorderRadius.circular(5),
168
+                                gradient: LinearGradient(colors: [
169
+                                  Color(0xFF2D4059),
170
+                                  Color(0xFF2D4059),
171
+                                  /*Color(0xFFEAFFD0),
172
+                                  Color(0xFF95E1D3),*/
173
+                                ])),
174
+                            child: Row(
175
+                              mainAxisAlignment: MainAxisAlignment.center,
176
+                              children: [
177
+                                Text('Lihat Riwayat Cuti\t\t',
178
+                                    textAlign: TextAlign.center,
179
+                                    style: TextStyle(
180
+                                        color: Colors.white,
181
+                                        fontSize: 17,
182
+                                        fontWeight: FontWeight.w500)),
183
+                                Image.asset(
184
+                                  'assets/images/ic_history.png',
185
+                                  width: 30,
186
+                                  height: 30,
187
+                                )
188
+                              ],
189
+                            )),
190
+                        onTap: () {
191
+                          Navigator.push(context, MaterialPageRoute(
192
+                              builder: (context) => HistoryCuti()));
193
+                        },
194
+                      ),
195
+                      Container(
196
+                        child: Card(
197
+                          elevation: 10,
198
+                          child: Container(
199
+                            decoration: BoxDecoration(
200
+                                color: Color(0XFFFAF7EE),
201
+                                borderRadius: BorderRadius.circular(10)),
202
+                            child: Column(
203
+                              children: [
204
+                                Container(
205
+                                  margin: EdgeInsets.only(
206
+                                      left: 10, right: 10, top: 10, bottom: 10),
207
+                                  child: Row(
208
+                                    children: [
209
+                                      Expanded(
210
+                                          flex: 2,
211
+                                          child: Text(
212
+                                            'Tipe',
213
+                                            style: GoogleFonts.inconsolata(
214
+                                                fontSize: 17),
215
+                                          )),
216
+                                      Expanded(
217
+                                          flex: 8,
218
+                                          child: Container(
219
+                                            decoration: BoxDecoration(
220
+                                                color:
221
+                                                    CupertinoColors.systemGrey2,
222
+                                                borderRadius:
223
+                                                    BorderRadius.circular(5)),
224
+                                            child: DropdownButton(
225
+                                              value: this.selectedType,
226
+                                              isExpanded: true,
227
+                                              underline: SizedBox(),
228
+                                              hint: Text(
229
+                                                '\t\t\tPilih Tipe Cuti',
230
+                                                style: TextStyle(
231
+                                                    color: Colors.black54),
232
+                                              ),
233
+                                              onChanged: (value) {
234
+                                                logDev.log(value.toString(), name: "VALUENYA");
235
+                                                //print(value);
236
+                                                setState(() {
237
+                                                  selectedType = value!;
238
+                                                  for (int i = 0; i < cutiType.length; i++){
239
+                                                    if (selectedType == cutiType.elementAt(i)){
240
+                                                      idCuti = idCutiType.elementAt(i);
241
+                                                    }
242
+                                                  }
243
+                                                  logDev.log(idCuti, name: "ID CUTINYA APA");
244
+                                                });
245
+                                              },
246
+                                              items: cutiType
247
+                                                  .map((e) => DropdownMenuItem(
248
+                                                        value: e,
249
+                                                        child:
250
+                                                            Text("\t\t\t" + e)),
251
+                                                  ).toList(),
252
+                                            ),
253
+                                          )),
254
+                                    ],
255
+                                  ),
256
+                                ),
257
+                                Container(
258
+                                  margin: EdgeInsets.only(
259
+                                      left: 10, right: 10, top: 10, bottom: 10),
260
+                                  child: Row(
261
+                                    children: [
262
+                                      Expanded(
263
+                                          flex: 2,
264
+                                          child: Column(
265
+                                            crossAxisAlignment:
266
+                                                CrossAxisAlignment.start,
267
+                                            children: [
268
+                                              Text(
269
+                                                'Mulai',
270
+                                                style: GoogleFonts.inconsolata(
271
+                                                    fontSize: 17),
272
+                                              ),
273
+                                              Text(
274
+                                                '',
275
+                                                style: GoogleFonts.inconsolata(
276
+                                                    fontSize: 17),
277
+                                              )
278
+                                            ],
279
+                                          )),
280
+                                      Expanded(
281
+                                        flex: 8,
282
+                                        child: Column(
283
+                                          children: [
284
+                                            ElevatedButton(
285
+                                              onPressed: () async {
286
+                                                DateTime? newDate =
287
+                                                    await showDatePicker(
288
+                                                        context: context,
289
+                                                        initialDate: dateFrom,
290
+                                                        firstDate:
291
+                                                            DateTime(1900),
292
+                                                        lastDate:
293
+                                                            DateTime(2100));
294
+                                                final DateFormat formatter = DateFormat('yyyy-MM-dd');
295
+                                                if (newDate == null) {
296
+                                                  return;
297
+                                                } else {
298
+                                                  setState(() {
299
+                                                    if (visibleDateFrom == false){
300
+                                                      visibleDateFrom = !visibleDateFrom;
301
+                                                    }
302
+                                                    formattedDateFrom = formatter.format(newDate);
303
+                                                    //dateFrom = formattedFrom as DateTime;
304
+                                                  });
305
+                                                }
306
+                                              },
307
+                                              /*style: ElevatedButton.styleFrom(
308
+                                                  backgroundColor:
309
+                                                      CupertinoColors
310
+                                                          .systemGrey2),*/
311
+                                              child: Container(
312
+                                                width: double.infinity,
313
+                                                child: Text(
314
+                                                  "Pilih Tanggal",
315
+                                                  style: TextStyle(
316
+                                                      color: Colors.white,
317
+                                                      fontSize: 16,
318
+                                                      fontWeight:
319
+                                                          FontWeight.w400),
320
+                                                ),
321
+                                              ),
322
+                                            ),
323
+                                            Visibility(
324
+                                              visible: visibleDateFrom,
325
+                                              child: Container(
326
+                                                alignment: Alignment.centerLeft,
327
+                                                margin: EdgeInsets.only(
328
+                                                    left: 15,
329
+                                                    right: 15,
330
+                                                    bottom: 5),
331
+                                                child: Text(formattedDateFrom,
332
+                                                  overflow:
333
+                                                      TextOverflow.ellipsis,
334
+                                                  maxLines: 1,
335
+                                                  style: TextStyle(
336
+                                                      color: Colors.black54),
337
+                                                ),
338
+                                              ),
339
+                                            )
340
+                                          ],
341
+                                        ),
342
+                                      ),
343
+                                    ],
344
+                                  ),
345
+                                ),
346
+                                Container(
347
+                                  margin: EdgeInsets.only(
348
+                                      left: 10, right: 10, top: 10, bottom: 10),
349
+                                  child: Row(
350
+                                    children: [
351
+                                      Expanded(
352
+                                          flex: 2,
353
+                                          child: Column(
354
+                                            crossAxisAlignment:
355
+                                                CrossAxisAlignment.start,
356
+                                            children: [
357
+                                              Text(
358
+                                                'Sampai',
359
+                                                style: GoogleFonts.inconsolata(
360
+                                                    fontSize: 17),
361
+                                              ),
362
+                                              Text(
363
+                                                '',
364
+                                                style: GoogleFonts.inconsolata(
365
+                                                    fontSize: 17),
366
+                                              )
367
+                                            ],
368
+                                          )),
369
+                                      Expanded(
370
+                                        flex: 8,
371
+                                        child: Column(
372
+                                          children: [
373
+                                            ElevatedButton(
374
+                                              onPressed: () async {
375
+                                                DateTime? newDate =
376
+                                                    await showDatePicker(
377
+                                                        context: context,
378
+                                                        initialDate: dateTo,
379
+                                                        firstDate:
380
+                                                            DateTime(1900),
381
+                                                        lastDate:
382
+                                                            DateTime(2100));
383
+                                                final DateFormat formatter = DateFormat('yyyy-MM-dd');
384
+                                                if (newDate == null) {
385
+                                                  return;
386
+                                                } else {
387
+                                                  setState(() {
388
+                                                    if (visibleDateTo == false){
389
+                                                      visibleDateTo = !visibleDateTo;
390
+                                                    }
391
+                                                    formattedDateTo = formatter.format(newDate);
392
+                                                  });
393
+                                                }
394
+                                              },
395
+                                              /*style: ElevatedButton.styleFrom(
396
+                                                  backgroundColor:
397
+                                                      CupertinoColors
398
+                                                          .systemGrey2),*/
399
+                                              child: Container(
400
+                                                width: double.infinity,
401
+                                                child: Text(
402
+                                                  "Pilih Tanggal",
403
+                                                  style: TextStyle(
404
+                                                      color: Colors.white,
405
+                                                      fontSize: 16,
406
+                                                      fontWeight:
407
+                                                          FontWeight.w400),
408
+                                                ),
409
+                                              ),
410
+                                            ),
411
+                                            Visibility(
412
+                                              visible: visibleDateTo,
413
+                                              child: Container(
414
+                                                alignment: Alignment.centerLeft,
415
+                                                margin: EdgeInsets.only(
416
+                                                    left: 15,
417
+                                                    right: 15,
418
+                                                    bottom: 5),
419
+                                                child: Text(formattedDateTo,
420
+                                                  overflow:
421
+                                                      TextOverflow.ellipsis,
422
+                                                  maxLines: 1,
423
+                                                  style: TextStyle(
424
+                                                      color: Colors.black54),
425
+                                                ),
426
+                                              ),
427
+                                            )
428
+                                          ],
429
+                                        ),
430
+                                      ),
431
+                                    ],
432
+                                  ),
433
+                                ),
434
+                                Container(
435
+                                  margin: EdgeInsets.only(
436
+                                      left: 10, right: 10, top: 10, bottom: 10),
437
+                                  child: Row(
438
+                                    children: [
439
+                                      Expanded(
440
+                                          flex: 3,
441
+                                          child: Text(
442
+                                            'Deskripsi',
443
+                                            style: GoogleFonts.inconsolata(
444
+                                                fontSize: 17),
445
+                                          )),
446
+                                      Expanded(
447
+                                          flex: 7,
448
+                                          child: Container(
449
+                                              decoration: BoxDecoration(
450
+                                                  color: Colors.white,
451
+                                                  borderRadius:
452
+                                                      BorderRadius.circular(5)),
453
+                                              child: Padding(
454
+                                                padding: EdgeInsets.only(
455
+                                                    left: 10,
456
+                                                    right: 10,
457
+                                                    top: 5,
458
+                                                    bottom: 5),
459
+                                                child: TextFormField(
460
+                                                    keyboardType:
461
+                                                        TextInputType.multiline,
462
+                                                    maxLines: null,
463
+                                                    textInputAction:
464
+                                                        TextInputAction.done,
465
+                                                    controller: deskripsiTeksController,
466
+                                                    decoration: InputDecoration(
467
+                                                        border:
468
+                                                            InputBorder.none,
469
+                                                        hintText: "Deskripsi")),
470
+                                              ))),
471
+                                    ],
472
+                                  ),
473
+                                ),
474
+                                Container(
475
+                                  margin: EdgeInsets.only(
476
+                                      left: 10, right: 10, top: 10, bottom: 10),
477
+                                  child: Column(
478
+                                    children: [
479
+                                      Row(
480
+                                        children: [
481
+                                          Expanded(
482
+                                            flex: 3,
483
+                                            child: Text(
484
+                                              'Lampiran',
485
+                                              style: GoogleFonts.inconsolata(
486
+                                                  fontSize: 17),
487
+                                            ),
488
+                                          ),
489
+                                          Expanded(
490
+                                            flex: 7,
491
+                                            child: Container(
492
+                                              child: ElevatedButton(
493
+                                                onPressed: () {
494
+                                                  _pickMultipleFiles();
495
+                                                },
496
+                                                /*style: ElevatedButton.styleFrom(
497
+                                                    backgroundColor:
498
+                                                        CupertinoColors
499
+                                                            .systemGrey2),*/
500
+                                                child: Container(
501
+                                                  width: double.infinity,
502
+                                                  child: Text("Pilih File",
503
+                                                      style: TextStyle(
504
+                                                          color: Colors.white,
505
+                                                          fontSize: 16,
506
+                                                          fontWeight:
507
+                                                              FontWeight.w400)),
508
+                                                ),
509
+                                              ),
510
+                                            ),
511
+                                          )
512
+                                        ],
513
+                                      ),
514
+                                      Row(
515
+                                        children: [
516
+                                          Expanded(
517
+                                            flex: 3,
518
+                                            child: Text(
519
+                                              '',
520
+                                              style: GoogleFonts.inconsolata(
521
+                                                  fontSize: 17),
522
+                                            ),
523
+                                          ),
524
+                                          Expanded(
525
+                                            flex: 7,
526
+                                            child:  Container(
527
+                                                  alignment:
528
+                                                      Alignment.centerLeft,
529
+                                                  margin: EdgeInsets.only(
530
+                                                      left: 15,
531
+                                                      right: 15,
532
+                                                      bottom: 10),
533
+                                                  child: Text(_totalFile + _fileText,
534
+                                                    overflow:
535
+                                                        TextOverflow.ellipsis,
536
+                                                    /*maxLines: 7,*/
537
+                                                    style: TextStyle(
538
+                                                        color: Colors.black54),
539
+                                                  ),
540
+                                                ),
541
+                                          )
542
+                                        ],
543
+                                      ),
544
+                                      InkWell(
545
+                                        child: Container(
546
+                                          padding: EdgeInsets.fromLTRB(
547
+                                              10, 10, 10, 10),
548
+                                          width: double.infinity,
549
+                                          decoration: BoxDecoration(
550
+                                              borderRadius:
551
+                                                  BorderRadius.circular(5),
552
+                                              gradient: LinearGradient(colors: [
553
+                                                Color(0xFFFF9945),
554
+                                                Color(0xFFFc6076)
555
+                                              ])),
556
+                                          child: Text('Ajukan',
557
+                                              textAlign: TextAlign.center,
558
+                                              style: TextStyle(
559
+                                                  color: Colors.white,
560
+                                                  fontSize: 17,
561
+                                                  fontWeight: FontWeight.w500)),
562
+                                        ),
563
+                                        onTap: () {
564
+                                          ProgressDialog loading = ProgressDialog(context);
565
+                                          loading = ProgressDialog(context,
566
+                                              type: ProgressDialogType.normal, isDismissible: false, showLogs: true);
567
+                                          loading.style(
568
+                                              message: 'Please Wait .....',
569
+                                              borderRadius: 3,
570
+                                              backgroundColor: Colors.white,
571
+                                              progressWidget: CircularProgressIndicator(),
572
+                                              elevation: 10.0,
573
+                                              padding: EdgeInsets.all(10),
574
+                                              insetAnimCurve: Curves.easeInOut,
575
+                                              progress: 0.0,
576
+                                              maxProgress: 100.0,
577
+                                              progressTextStyle: TextStyle(
578
+                                                  color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
579
+                                              messageTextStyle: TextStyle(
580
+                                                  color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600));
581
+
582
+                                          //loading.show();
583
+
584
+                                          if (!validateFormCuti(context)){
585
+                                            return;
586
+                                          } else if (validateFormCuti(context)){
587
+                                            loading.show();
588
+                                            PengajuanCuti_Post.connectToAPI(idCuti, formattedDateFrom,
589
+                                                formattedDateTo, deskripsiTeksController.text.toString(), fileAttach)
590
+                                                .then((valueResult) async {
591
+                                              Map<String, dynamic> object = json.decode(valueResult);
592
+                                              logDev.log(fileAttach.toString(), name: "Attachment File Upload");
593
+                                              if (object.containsKey("result").toString() == "true") {
594
+                                                /*String employee = object['result']['employee'].toString();
595
+                                              String tipe = object['result']['tipe'].toString();
596
+                                              String from = object['result']['from'].toString();
597
+                                              String to = object['result']['to'].toString();
598
+                                              String deskripsi = object['result']['deskripsi'].toString();
599
+                                              String attachment = object['result']['attachment'].toString();*/
600
+                                                loading.hide();
601
+                                                deskripsiTeksController.clear();
602
+                                                Widget okButton = TextButton(
603
+                                                  child: Text("OK"),
604
+                                                  onPressed: () {
605
+                                                    Navigator.of(context, rootNavigator: true).pop();
606
+                                                    Navigator.pushReplacement(context, MaterialPageRoute(
607
+                                                        builder: (context) => AjukanCutiScreen()));
608
+                                                  },
609
+                                                );
610
+
611
+                                                // set up the AlertDialog
612
+                                                AlertDialog alert = AlertDialog(
613
+                                                  title: Text("Employee Self Service"),
614
+                                                  content: Text("Berhasil Mengajukan Cuti"),
615
+                                                  actions: [
616
+                                                    okButton,
617
+                                                  ],
618
+                                                );
619
+
620
+                                                // show the dialog
621
+                                                showDialog(
622
+                                                  context: context,
623
+                                                  builder: (BuildContext context) {
624
+                                                    return alert;
625
+                                                  },
626
+                                                );
627
+                                                /* deskripsiTeksController.clear();
628
+                                                formattedDateFrom = "";
629
+                                                formattedDateTo = "";
630
+                                                visibleDateFrom = false;
631
+                                                visibleDateFrom = false;*/
632
+                                              } else if (object.containsKey("error").toString() == "true") {
633
+                                                String errorMessage = object['error']['data']['message']
634
+                                                    .toString();
635
+                                                loading.hide();
636
+                                                Widget okButton = TextButton(
637
+                                                  child: Text("OK"),
638
+                                                  onPressed: () {
639
+                                                    Navigator.of(context, rootNavigator: true).pop();
640
+                                                  },
641
+                                                );
642
+
643
+                                                // set up the AlertDialog
644
+                                                AlertDialog alert = AlertDialog(
645
+                                                  title: Text("Employee Self Service"),
646
+                                                  content: Text(errorMessage),
647
+                                                  actions: [
648
+                                                    okButton,
649
+                                                  ],
650
+                                                );
651
+
652
+                                                // show the dialog
653
+                                                showDialog(
654
+                                                  context: context,
655
+                                                  builder: (BuildContext context) {
656
+                                                    return alert;
657
+                                                  },
658
+                                                );
659
+                                              }
660
+                                            });
661
+                                          }
662
+                                        },
663
+                                      )
664
+                                    ],
665
+                                  ),
666
+                                ),
667
+                              ],
668
+                            ),
669
+                          ),
670
+                        ),
671
+                      ),
672
+                    ],
673
+                  ),
674
+                ),
675
+              ),
676
+            ],
677
+          ),
678
+        ],
679
+      )),
680
+    );
681
+  }
682
+
683
+  void _pickMultipleFiles() async {
684
+    FilePickerResult? result = await FilePicker.platform.pickFiles(allowMultiple: true);
685
+
686
+    if (_fileText != ""){
687
+      _fileText = "";
688
+    }
689
+
690
+    if (result != null) {
691
+      List<File> files = result.paths.map((path) => File(path!)).toList();
692
+      for (int i = 0; i< files.length; i++){
693
+        String fileName = files[i].path.split('/').last;
694
+        _fileText = _fileText + "\n" + fileName;
695
+
696
+        List<int> fileInBytes = files[i].readAsBytesSync();
697
+        String toBase64 = base64Encode(fileInBytes);
698
+        fileAttach.add(toBase64);
699
+      }
700
+      fileAttach.removeAt(0);
701
+      /*logDev.log(fileAttach.toString(), name: "File Attach Base64");*/
702
+      logDev.log(fileAttach.length.toString(), name: "Length File Attach");
703
+      logDev.log(files.toString(), name: "Files Picked");
704
+
705
+      setState(() {
706
+        _fileText;
707
+        _totalFile = "Total File : " + files.length.toString();
708
+      });
709
+    } else {
710
+      // User canceled the picker
711
+    }
712
+  }
713
+
714
+  bool validateFormCuti(BuildContext context) {
715
+    bool result = true;
716
+    if (selectedType == null) {
717
+      Fluttertoast.showToast(
718
+          msg: "Tipe Cuti Belum Dipilih",
719
+          toastLength: Toast.LENGTH_SHORT,
720
+          gravity: ToastGravity.CENTER,
721
+          timeInSecForIosWeb: 1,
722
+          textColor: Colors.white,
723
+          fontSize: 16.0);
724
+      result = false;
725
+    } else if  (formattedDateFrom == "" || formattedDateTo == "") {
726
+      Fluttertoast.showToast(
727
+          msg: "Tanggal Cuti Belum Dipilih",
728
+          toastLength: Toast.LENGTH_SHORT,
729
+          gravity: ToastGravity.CENTER,
730
+          timeInSecForIosWeb: 1,
731
+          textColor: Colors.white,
732
+          fontSize: 16.0);
733
+      result = false;
734
+    } else if (deskripsiTeksController.text.toString().isEmpty) {
735
+      Fluttertoast.showToast(
736
+          msg: "Deskripsi Harus Diisi",
737
+          toastLength: Toast.LENGTH_SHORT,
738
+          gravity: ToastGravity.CENTER,
739
+          timeInSecForIosWeb: 1,
740
+          textColor: Colors.white,
741
+          fontSize: 16.0);
742
+      result = false;
743
+    }
744
+
745
+    return result;
9 746
   }
10 747
 }
748
+
749
+alertDialogFailedRetrievedData(BuildContext context){
750
+  Widget okButton = TextButton(
751
+    child: Text("Refresh"),
752
+    onPressed: () {
753
+      Navigator.of(context, rootNavigator: true).pop();
754
+      Navigator.pushReplacement(context, MaterialPageRoute(
755
+          builder: (context) => AjukanCutiScreen()));
756
+    },
757
+  );
758
+
759
+  Widget noButton = TextButton(
760
+    child: Text("Back"),
761
+    onPressed: () {
762
+      Navigator.of(context, rootNavigator: true).pop();
763
+      Navigator.pop(context);
764
+
765
+    },
766
+  );
767
+
768
+  // set up the AlertDialog
769
+  AlertDialog alert = AlertDialog(
770
+    title: Text("Employee Self Service"),
771
+    content: Text("Failed to Retrieve Data"),
772
+    actions: [
773
+      noButton,
774
+      okButton,
775
+    ],
776
+  );
777
+
778
+  // show the dialog
779
+  showDialog(
780
+    context: context,
781
+    builder: (BuildContext context) {
782
+      return alert;
783
+    },
784
+  );
785
+}
786
+
787
+alertDialogFailedResponse(BuildContext context){
788
+  Widget okButton = TextButton(
789
+    child: Text("Refresh"),
790
+    onPressed: () {
791
+      Navigator.of(context, rootNavigator: true).pop();
792
+      Navigator.pushReplacement(context, MaterialPageRoute(
793
+          builder: (context) => AjukanCutiScreen()));
794
+    },
795
+  );
796
+
797
+  Widget noButton = TextButton(
798
+    child: Text("Back"),
799
+    onPressed: () {
800
+      Navigator.of(context, rootNavigator: true).pop();
801
+      Navigator.pop(context);
802
+
803
+    },
804
+  );
805
+
806
+  // set up the AlertDialog
807
+  AlertDialog alert = AlertDialog(
808
+    title: Text("Employee Self Service"),
809
+    content: Text("Server Response Error"),
810
+    actions: [
811
+      noButton,
812
+      okButton,
813
+    ],
814
+  );
815
+
816
+  // show the dialog
817
+  showDialog(
818
+    context: context,
819
+    builder: (BuildContext context) {
820
+      return alert;
821
+    },
822
+  );
823
+}

+ 87
- 0
lib/Screens/Menu/AjukanCuti/backgroundHistory.dart 查看文件

@@ -0,0 +1,87 @@
1
+import 'package:flutter/material.dart';
2
+
3
+class Background extends StatelessWidget {
4
+  const Background({Key? key}) : super(key: key);
5
+
6
+  @override
7
+  Widget build(BuildContext context) {
8
+    return Scaffold(
9
+      resizeToAvoidBottomInset: false,
10
+      backgroundColor: Colors.white,
11
+      body: Column(
12
+        children: <Widget>[
13
+          new Stack(
14
+            children: <Widget>[
15
+              WavyHeader()
16
+            ],
17
+          ),
18
+        ],
19
+      ),
20
+    );
21
+  }
22
+}
23
+
24
+const List<Color> orangeGradients = [
25
+  Color(0xFFD21404),
26
+  Color(0xFFFD7267)
27
+];
28
+
29
+const List<Color> aquaGradients = [
30
+  Color(0xFF8EF7DA),
31
+  Color(0xFF5AEAF1),
32
+  Colors.blueAccent,
33
+];
34
+
35
+class WavyHeader extends StatelessWidget {
36
+  @override
37
+  Widget build(BuildContext context) {
38
+    return ClipPath(
39
+      clipper: TopWaveClipper(),
40
+      child: Container(
41
+        decoration: BoxDecoration(
42
+          gradient: LinearGradient(
43
+              colors: orangeGradients,
44
+              begin: Alignment.topLeft,
45
+              end: Alignment.center),
46
+        ),
47
+        height: MediaQuery.of(context).size.height / 2.5,
48
+      ),
49
+    );
50
+  }
51
+}
52
+
53
+class TopWaveClipper extends CustomClipper<Path> {
54
+  @override
55
+  Path getClip(Size size) {
56
+    // This is where we decide what part of our image is going to be visible.
57
+    var path = Path();
58
+    path.lineTo(0.0, 0.0);
59
+
60
+    var firstControlPoint = new Offset(0, size.height - 30);
61
+    var firstEndPoint = new Offset(0, size.height / 2);
62
+
63
+    path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
64
+        firstEndPoint.dx, firstEndPoint.dy);
65
+
66
+    var secondControlPoint = Offset(size.width / 5, size.height / 4);
67
+    var secondEndPoint = Offset(size.width / 1.5, size.height / 5);
68
+    path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
69
+        secondEndPoint.dx, secondEndPoint.dy);
70
+
71
+    var thirdControlPoint =
72
+    Offset(size.width - (size.width / 9), size.height / 6);
73
+    var thirdEndPoint = Offset(size.width, 0.0);
74
+    path.quadraticBezierTo(thirdControlPoint.dx, thirdControlPoint.dy,
75
+        thirdEndPoint.dx, thirdEndPoint.dy);
76
+
77
+    ///move from bottom right to top
78
+    path.lineTo(size.width, 0.0);
79
+
80
+    ///finally close the path by reaching start point from top right corner
81
+    path.close();
82
+    return path;
83
+  }
84
+
85
+  @override
86
+  bool shouldReclip(CustomClipper<Path> oldClipper) => false;
87
+}

+ 309
- 0
lib/Screens/Menu/AjukanCuti/history_cuti.dart 查看文件

@@ -0,0 +1,309 @@
1
+import 'dart:convert';
2
+
3
+import 'package:flutter/material.dart';
4
+import 'package:fluttertoast/fluttertoast.dart';
5
+import 'package:google_fonts/google_fonts.dart';
6
+import 'package:hris_selfservice_mobile/Screens/Menu/AjukanCuti/RequestHttp/historyCuti_post.dart';
7
+import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart';
8
+import 'dart:developer' as logDev;
9
+
10
+import '../AjukanCuti/backgroundHistory.dart';
11
+
12
+class HistoryCuti extends StatefulWidget {
13
+  const HistoryCuti({Key? key}) : super(key: key);
14
+
15
+  @override
16
+  State<HistoryCuti> createState() => _HistoryCutiState();
17
+}
18
+
19
+class _HistoryCutiState extends State<HistoryCuti> {
20
+  late List <String> id_List;
21
+  late List <String> name_List;
22
+  late List <String> type_cuti_List;
23
+  late List <String> detail_List;
24
+  late List <String> created_on_List;
25
+  late List <String> created_by_List;
26
+  late List <String> start_date_List;
27
+  late List <String> end_date_List;
28
+  late List <String> duration_List;
29
+  late List <String> status_List;
30
+  late List <Color> statusColor;
31
+  late List <bool> visible;
32
+
33
+  int HistoryLength = 0;
34
+
35
+  @override
36
+  initState() {
37
+    super.initState();
38
+    id_List = [""];
39
+    name_List = [""];
40
+    type_cuti_List = [""];
41
+    detail_List = [""];
42
+    created_on_List = [""];
43
+    created_by_List = [""];
44
+    start_date_List = [""];
45
+    end_date_List = [""];
46
+    duration_List = [""];
47
+    status_List = [""];
48
+    statusColor = [Colors.black54];
49
+    visible = [false];
50
+
51
+    WidgetsBinding.instance.addPostFrameCallback((_) async {
52
+      getHistoryData();
53
+    });
54
+    logDev.log(HistoryLength.toString(), name: "Banyak History");
55
+  }
56
+
57
+  getHistoryData() async {
58
+    ProgressDialog loading = ProgressDialog(context);
59
+    loading = ProgressDialog(context,
60
+        type: ProgressDialogType.normal, isDismissible: false, showLogs: true);
61
+    loading.style(
62
+        message: 'Please Wait .....',
63
+        borderRadius: 3,
64
+        backgroundColor: Colors.white,
65
+        progressWidget: CircularProgressIndicator(),
66
+        elevation: 10.0,
67
+        padding: EdgeInsets.all(10),
68
+        insetAnimCurve: Curves.easeInOut,
69
+        progress: 0.0,
70
+        maxProgress: 100.0,
71
+        progressTextStyle: TextStyle(
72
+            color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
73
+        messageTextStyle: TextStyle(
74
+            color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600));
75
+
76
+    loading.show();
77
+    HistoryCuti_Post.connectToAPI().then((valueResult) async {
78
+      Map<String, dynamic> object = jsonDecode(valueResult);
79
+      if (object.containsKey("result").toString() == "true") {
80
+        String result = object['result'].toString();
81
+        if (result.contains("Failed")) {
82
+          loading.hide();
83
+          alertDialogFailedRetrievedData(context);
84
+        } else {
85
+          List <dynamic> historyCuti = object['result'];
86
+         /* logDev.log(historyCuti.toString(), name: "History Cuti");
87
+          logDev.log(historyCuti.length.toString(), name: "Banyaknya History Cuti");*/
88
+          setState(() {
89
+            for (int i = 0; i < historyCuti.length; i++){
90
+              String id = historyCuti[i]['id'].toString();
91
+              String name = historyCuti[i]['name'].toString();
92
+              String type_cuti = historyCuti[i]['type_cuti'].toString();
93
+              String detail = historyCuti[i]['detail'].toString();
94
+              String created_on = historyCuti[i]['created_on'].toString();
95
+              String created_by = historyCuti[i]['created_by'].toString();
96
+              String start_date = historyCuti[i]['start_date'].toString();
97
+              String end_date = historyCuti[i]['end_date'].toString();
98
+              String duration = historyCuti[i]['duration'].toString();
99
+              String status = historyCuti[i]['status'].toString();
100
+
101
+              if (detail == "false"){
102
+                detail = "-";
103
+              }
104
+
105
+              id_List.add(id);
106
+              name_List.add(name);
107
+              type_cuti_List.add(type_cuti);
108
+              detail_List.add(detail);
109
+              created_on_List.add(created_on);
110
+              created_by_List.add(created_by);
111
+              start_date_List.add(start_date.substring(0,10));
112
+              end_date_List.add(end_date.substring(0,10));
113
+              duration_List.add(duration);
114
+              status_List.add(status);
115
+              visible.add(false);
116
+
117
+              var statColor;
118
+              if (status == "To Approve"){
119
+                statColor = Colors.red;
120
+              } else if (status == "Second Approval"){
121
+                statColor = Colors.green;
122
+              } else if (status == "Approved"){
123
+                statColor = Colors.blueAccent;
124
+              }
125
+              statusColor.add(statColor);
126
+            }
127
+
128
+            id_List.removeAt(0);
129
+            name_List.removeAt(0);
130
+            type_cuti_List.removeAt(0);
131
+            detail_List.removeAt(0);
132
+            created_on_List.removeAt(0);
133
+            created_by_List.removeAt(0);
134
+            start_date_List.removeAt(0);
135
+            end_date_List.removeAt(0);
136
+            duration_List.removeAt(0);
137
+            status_List.removeAt(0);
138
+            statusColor.removeAt(0);
139
+            visible.removeAt(0);
140
+
141
+            HistoryLength = historyCuti.length;
142
+          });
143
+          loading.hide();
144
+        }
145
+      } else {
146
+        Fluttertoast.showToast(
147
+            msg: "Server Response Error",
148
+            toastLength: Toast.LENGTH_SHORT,
149
+            gravity: ToastGravity.CENTER,
150
+            timeInSecForIosWeb: 1,
151
+            textColor: Colors.white,
152
+            fontSize: 16.0);
153
+      }
154
+    });
155
+    loading.hide();
156
+  }
157
+
158
+  @override
159
+  Widget build(BuildContext context) {
160
+    var size = MediaQuery.of(context).size;
161
+    return Scaffold(
162
+      body: Stack(
163
+          children: [
164
+            Column(
165
+              children: <Widget>[
166
+                Stack(
167
+                  children: [
168
+                    WavyHeader(),
169
+                    Container(
170
+                        margin: EdgeInsets.only(
171
+                            top: (size.height / 6) - 20),
172
+                        padding: EdgeInsets.fromLTRB(0, 5, 25, 5),
173
+                        child: Row(
174
+                          mainAxisAlignment: MainAxisAlignment.end,
175
+                          crossAxisAlignment: CrossAxisAlignment.end,
176
+                          children: [
177
+                            Text(
178
+                              'Riwayat Cuti\t\t',
179
+                              maxLines: 1,
180
+                              style: GoogleFonts.luckiestGuy(
181
+                                fontSize: 28,
182
+                                color: Colors.red,
183
+                                fontStyle: FontStyle.italic,
184
+                              ),
185
+                            ),
186
+                            Image.asset(
187
+                              'assets/images/ic_history.png',
188
+                              width: 40,
189
+                              height: 40,
190
+                            ),
191
+                          ],
192
+                        )
193
+                    ),
194
+                  ],
195
+                ),
196
+              ],
197
+            ),
198
+            Container(
199
+              margin: EdgeInsets.only(top: (MediaQuery.of(context).size.height / 6) + 40, left: 5, right: 5, bottom: 10),
200
+              child: ListView.builder(
201
+                scrollDirection: Axis.vertical,
202
+                shrinkWrap: true,
203
+                itemCount: HistoryLength,
204
+                itemBuilder: (context, int i) {
205
+                  return Container(
206
+                    child: InkWell(
207
+                      child: Card(
208
+                        elevation: 10,
209
+                        child: Column(
210
+                          children: [
211
+                            Row(
212
+                              children: [
213
+                                Expanded(
214
+                                    flex: 8,
215
+                                    child: Padding(
216
+                                      padding: EdgeInsets.fromLTRB(10, 5, 5, 5),
217
+                                      child: Column(
218
+                                        mainAxisAlignment: MainAxisAlignment.center,
219
+                                        crossAxisAlignment: CrossAxisAlignment.start,
220
+                                        children: [
221
+                                          Text(type_cuti_List[i], style: GoogleFonts.rubikBubbles(fontSize: 16)),
222
+                                          Text(start_date_List[i] + " - " + end_date_List[i] + " (" + duration_List[i] + ") ", style: GoogleFonts.nunito(fontSize: 15)),
223
+                                          Text("\nKeterangan : " + detail_List[i], style: GoogleFonts.nunito(fontSize: 15)),
224
+                                          Text("\nCreated : " + created_on_List[i], style: GoogleFonts.yeonSung(fontSize: 14, fontStyle: FontStyle.italic)),
225
+                                        ],
226
+                                      ),
227
+                                    )
228
+                                ),
229
+                                Expanded(
230
+                                    flex: 2,
231
+                                    child: Padding(
232
+                                      padding: EdgeInsets.fromLTRB(5, 5, 5, 5),
233
+                                      child: Text(status_List[i], style: GoogleFonts.lilitaOne(color: statusColor[i], fontSize: 17),
234
+                                      ),
235
+                                    )
236
+                                ),
237
+                              ],
238
+                            ),
239
+                            Align(
240
+                              alignment: Alignment.centerLeft,
241
+                              child: Visibility(
242
+                                  visible: visible[i],
243
+                                  child: Padding(
244
+                                    padding: EdgeInsets.fromLTRB(10, 5, 5, 5),
245
+                                    child: Column(
246
+                                      mainAxisAlignment: MainAxisAlignment.start,
247
+                                      crossAxisAlignment: CrossAxisAlignment.start,
248
+                                      children: [
249
+                                        Text("\nAttachment : ", style: GoogleFonts.josefinSans(fontSize: 15, fontWeight: FontWeight.bold)),
250
+                                        Text("Created : " + created_on_List[i], style: GoogleFonts.nunito(fontSize: 15, fontStyle: FontStyle.italic)),
251
+                                      ],
252
+                                    ),
253
+                                  )
254
+                              ),
255
+                            )
256
+                          ],
257
+                        ),
258
+                      ),
259
+                      onTap: (){
260
+                        setState(() {
261
+                          visible[i] = !visible[i];
262
+                        });
263
+                      },
264
+                    ),
265
+                  );
266
+                },
267
+              ),
268
+            )
269
+          ]),
270
+    );
271
+  }
272
+}
273
+
274
+alertDialogFailedRetrievedData(BuildContext context) {
275
+  Widget okButton = TextButton(
276
+    child: Text("Refresh"),
277
+    onPressed: () {
278
+      Navigator.of(context, rootNavigator: true).pop();
279
+      Navigator.pushReplacement(
280
+          context, MaterialPageRoute(builder: (context) => HistoryCuti()));
281
+    },
282
+  );
283
+
284
+  Widget noButton = TextButton(
285
+    child: Text("Back"),
286
+    onPressed: () {
287
+      Navigator.of(context, rootNavigator: true).pop();
288
+      Navigator.pop(context);
289
+    },
290
+  );
291
+
292
+  // set up the AlertDialog
293
+  AlertDialog alert = AlertDialog(
294
+    title: Text("Employee Self Service"),
295
+    content: Text("Failed to Retrieve Data"),
296
+    actions: [
297
+      noButton,
298
+      okButton,
299
+    ],
300
+  );
301
+
302
+  // show the dialog
303
+  showDialog(
304
+    context: context,
305
+    builder: (BuildContext context) {
306
+      return alert;
307
+    },
308
+  );
309
+}

+ 9
- 0
lib/Screens/Menu/AjukanCuti/model.dart 查看文件

@@ -0,0 +1,9 @@
1
+class cuti_model{
2
+  late final String jenisCuti;
3
+  late final String dateFrom;
4
+  late final String dateTo;
5
+  late final String deskripsi;
6
+
7
+  cuti_model(this.jenisCuti, this.dateFrom, this.dateTo, this.deskripsi);
8
+
9
+}

+ 0
- 0
lib/Screens/Menu/Reimburse/history_reimburse.dart 查看文件


+ 464
- 0
lib/Screens/Menu/Reimburse/reimburse_screen.dart 查看文件

@@ -0,0 +1,464 @@
1
+import 'package:flutter/cupertino.dart';
2
+import 'package:flutter/material.dart';
3
+import 'package:google_fonts/google_fonts.dart';
4
+
5
+import '../SlipGaji/background.dart';
6
+
7
+class ReimburseScreen extends StatefulWidget {
8
+  const ReimburseScreen({Key? key}) : super(key: key);
9
+
10
+  @override
11
+  State<ReimburseScreen> createState() => _ReimburseScreen_State();
12
+}
13
+
14
+class _ReimburseScreen_State extends State<ReimburseScreen> {
15
+  var selectedCategory;
16
+  var selectedDate;
17
+
18
+  int _value = 0;
19
+
20
+  @override
21
+  Widget build(BuildContext context) {
22
+    return Scaffold(
23
+      body: SingleChildScrollView(
24
+          child: Column(
25
+        children: <Widget>[
26
+          Stack(
27
+            children: [
28
+              WavyHeader(),
29
+              Container(
30
+                  margin: EdgeInsets.only(top: 90),
31
+                  padding: EdgeInsets.fromLTRB(20, 5, 25, 5),
32
+                  child: Row(
33
+                    mainAxisAlignment: MainAxisAlignment.end,
34
+                    crossAxisAlignment: CrossAxisAlignment.end,
35
+                    children: [
36
+                      Text(
37
+                        'Reimburse\t\t',
38
+                        maxLines: 1,
39
+                        style: GoogleFonts.luckiestGuy(
40
+                          fontSize: 28,
41
+                          color: Colors.red,
42
+                          fontStyle: FontStyle.italic,
43
+                        ),
44
+                      ),
45
+                      Image.asset(
46
+                        'assets/icons/menu/ic_refund.png',
47
+                        width: 40,
48
+                        height: 40,
49
+                      ),
50
+                    ],
51
+                  )),
52
+              SafeArea(
53
+                child: Container(
54
+                  width: MediaQuery.of(context).size.width,
55
+                  margin: EdgeInsets.only(
56
+                    top: MediaQuery.of(context).size.height / 5,
57
+                    left: 10,
58
+                    right: 10,
59
+                  ),
60
+                  child: Column(
61
+                    children: [
62
+                      InkWell(
63
+                        child: Container(
64
+                            margin: EdgeInsets.only(top: 15, bottom: 15),
65
+                            padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
66
+                            width: double.infinity,
67
+                            decoration: BoxDecoration(
68
+                                borderRadius: BorderRadius.circular(5),
69
+                                gradient: LinearGradient(colors: [
70
+                                  Color(0xFF2D4059),
71
+                                  Color(0xFF2D4059),
72
+                                  /*Color(0xFFEAFFD0),
73
+                                  Color(0xFF95E1D3),*/
74
+                                ])),
75
+                            child: Row(
76
+                              mainAxisAlignment: MainAxisAlignment.center,
77
+                              children: [
78
+                                Text('Lihat Riwayat Reimburse\t\t',
79
+                                    textAlign: TextAlign.center,
80
+                                    style: TextStyle(
81
+                                        color: Colors.white,
82
+                                        fontSize: 17,
83
+                                        fontWeight: FontWeight.w500)),
84
+                                Image.asset(
85
+                                  'assets/images/ic_history.png',
86
+                                  width: 30,
87
+                                  height: 30,
88
+                                )
89
+                              ],
90
+                            )),
91
+                        onTap: () {},
92
+                      ),
93
+                      Container(
94
+                        child: Card(
95
+                          elevation: 10,
96
+                          child: Container(
97
+                            decoration: BoxDecoration(
98
+                                color: Color(0XFFFAF7EE),
99
+                                borderRadius: BorderRadius.circular(10)),
100
+                            child: Column(
101
+                              children: [
102
+                                Container(
103
+                                  margin: EdgeInsets.only(
104
+                                      left: 10, right: 10, top: 10, bottom: 10),
105
+                                  child: Row(
106
+                                    children: [
107
+                                      Expanded(
108
+                                          flex: 3,
109
+                                          child: Text(
110
+                                            'Kategori\t:\t',
111
+                                            style: GoogleFonts.inconsolata(
112
+                                                fontSize: 17),
113
+                                          )),
114
+                                      Expanded(
115
+                                          flex: 7,
116
+                                          child: Container(
117
+                                            decoration: BoxDecoration(
118
+                                                color:
119
+                                                    CupertinoColors.systemGrey2,
120
+                                                borderRadius:
121
+                                                    BorderRadius.circular(5)),
122
+                                            child: DropdownButton(
123
+                                              value: this.selectedCategory,
124
+                                              isExpanded: true,
125
+                                              underline: SizedBox(),
126
+                                              hint: Text(
127
+                                                '\t\t\tPilih Kategori',
128
+                                                style: TextStyle(
129
+                                                    color: Colors.black54),
130
+                                              ),
131
+                                              onChanged: (value) {
132
+                                                print(value);
133
+                                                setState(() {
134
+                                                  selectedCategory = value!;
135
+                                                });
136
+                                              },
137
+                                              items: reimburseCategory
138
+                                                  .map(
139
+                                                    (e) => DropdownMenuItem(
140
+                                                        value: e,
141
+                                                        child:
142
+                                                            Text("\t\t\t" + e)),
143
+                                                  )
144
+                                                  .toList(),
145
+                                            ),
146
+                                          )),
147
+                                    ],
148
+                                  ),
149
+                                ),
150
+                                Container(
151
+                                  margin: EdgeInsets.only(
152
+                                      left: 10, right: 10, top: 10, bottom: 10),
153
+                                  child: Column(
154
+                                    children: [
155
+                                      Row(
156
+                                        children: [
157
+                                          Expanded(
158
+                                              flex: 3,
159
+                                              child: Text(
160
+                                                'Tanggal\t:\t',
161
+                                                style: GoogleFonts.inconsolata(
162
+                                                    fontSize: 17),
163
+                                              )),
164
+                                          Expanded(
165
+                                              flex: 7,
166
+                                              child: Container(
167
+                                                decoration: BoxDecoration(
168
+                                                    color: CupertinoColors
169
+                                                        .systemGrey2,
170
+                                                    borderRadius:
171
+                                                        BorderRadius.circular(
172
+                                                            5)),
173
+                                                child: Column(
174
+                                                  children: [
175
+                                                    DropdownButton(
176
+                                                      value: this.selectedDate,
177
+                                                      isExpanded: true,
178
+                                                      underline: SizedBox(),
179
+                                                      hint: Text(
180
+                                                        '\t\t\tPilih Tanggal',
181
+                                                        style: TextStyle(
182
+                                                            color:
183
+                                                                Colors.black54),
184
+                                                      ),
185
+                                                      onChanged: (value) {
186
+                                                        print(value);
187
+                                                        setState(() {
188
+                                                          selectedDate = value!;
189
+                                                        });
190
+                                                      },
191
+                                                      items: reimburseCategory
192
+                                                          .map(
193
+                                                            (e) =>
194
+                                                                DropdownMenuItem(
195
+                                                                    value: e,
196
+                                                                    child: Text(
197
+                                                                        "\t\t\t" +
198
+                                                                            e)),
199
+                                                          )
200
+                                                          .toList(),
201
+                                                    ),
202
+                                                  ],
203
+                                                ),
204
+                                              )),
205
+                                        ],
206
+                                      ),
207
+                                    ],
208
+                                  ),
209
+                                ),
210
+                                Container(
211
+                                  margin: EdgeInsets.only(
212
+                                      left: 10, right: 10, top: 10, bottom: 10),
213
+                                  child: Row(
214
+                                    children: [
215
+                                      Expanded(
216
+                                          flex: 3,
217
+                                          child: Text(
218
+                                            'Total Harga\t:\t',
219
+                                            style: GoogleFonts.inconsolata(
220
+                                                fontSize: 17),
221
+                                          )),
222
+                                      Expanded(
223
+                                          flex: 7,
224
+                                          child: Container(
225
+                                              decoration: BoxDecoration(
226
+                                                  color: Colors.white,
227
+                                                  borderRadius:
228
+                                                      BorderRadius.circular(5)),
229
+                                              child: Padding(
230
+                                                padding: EdgeInsets.only(
231
+                                                    left: 10,
232
+                                                    right: 10,
233
+                                                    top: 5,
234
+                                                    bottom: 5),
235
+                                                child: TextFormField(
236
+                                                    keyboardType:
237
+                                                        TextInputType.number,
238
+                                                    maxLines: 1,
239
+                                                    textInputAction:
240
+                                                        TextInputAction.next,
241
+                                                    decoration: InputDecoration(
242
+                                                        border:
243
+                                                            InputBorder.none,
244
+                                                        hintText:
245
+                                                            "Masukkan tanpa tanda baca (.) atau (,)")),
246
+                                              ))),
247
+                                    ],
248
+                                  ),
249
+                                ),
250
+                                Container(
251
+                                  margin: EdgeInsets.only(
252
+                                      left: 10, right: 10, top: 10, bottom: 10),
253
+                                  child: Row(
254
+                                    children: [
255
+                                      Expanded(
256
+                                          flex: 3,
257
+                                          child: Text(
258
+                                            'Deskripsi\t:\t',
259
+                                            style: GoogleFonts.inconsolata(
260
+                                                fontSize: 17),
261
+                                          )),
262
+                                      Expanded(
263
+                                          flex: 7,
264
+                                          child: Container(
265
+                                              decoration: BoxDecoration(
266
+                                                  color: Colors.white,
267
+                                                  borderRadius:
268
+                                                      BorderRadius.circular(5)),
269
+                                              child: Padding(
270
+                                                padding: EdgeInsets.only(
271
+                                                    left: 10,
272
+                                                    right: 10,
273
+                                                    top: 5,
274
+                                                    bottom: 5),
275
+                                                child: TextFormField(
276
+                                                    keyboardType:
277
+                                                        TextInputType.multiline,
278
+                                                    maxLines: null,
279
+                                                    textInputAction:
280
+                                                        TextInputAction.done,
281
+                                                    decoration: InputDecoration(
282
+                                                        border:
283
+                                                            InputBorder.none,
284
+                                                        hintText: "Deskripsi")),
285
+                                              ))),
286
+                                    ],
287
+                                  ),
288
+                                ),
289
+                                Container(
290
+                                  margin: EdgeInsets.only(
291
+                                      left: 10, right: 10, top: 10, bottom: 10),
292
+                                  child: Column(
293
+                                    children: [
294
+                                      Row(
295
+                                        children: [
296
+                                          Expanded(
297
+                                              flex: 3,
298
+                                              child: Text(
299
+                                                'Pembayaran\t:',
300
+                                                style: GoogleFonts.inconsolata(
301
+                                                    fontSize: 17),
302
+                                              )),
303
+                                          Expanded(
304
+                                              flex: 7,
305
+                                              child: Container(
306
+                                                child: Column(
307
+                                                  children: [
308
+                                                    Row(
309
+                                                      children: [
310
+                                                        Radio(
311
+                                                          value: 1,
312
+                                                          groupValue: _value,
313
+                                                          onChanged: (value) {
314
+                                                            setState(() {
315
+                                                              _value = value!;
316
+                                                            });
317
+                                                          },
318
+                                                        ),
319
+                                                        Flexible(
320
+                                                            child: Text(
321
+                                                                "Karyawan (Perlu Reimburse)",
322
+                                                                style:
323
+                                                                    TextStyle(
324
+                                                                  color: Colors
325
+                                                                      .black54,
326
+                                                                ))),
327
+                                                      ],
328
+                                                    ),
329
+                                                    Row(
330
+                                                      children: [
331
+                                                        Radio(
332
+                                                          value: 2,
333
+                                                          groupValue: _value,
334
+                                                          onChanged: (value) {
335
+                                                            setState(() {
336
+                                                              _value = value!;
337
+                                                            });
338
+                                                          },
339
+                                                        ),
340
+                                                        Flexible(
341
+                                                            child: Text(
342
+                                                                "Perusahaan",
343
+                                                                style: TextStyle(
344
+                                                                    color: Colors
345
+                                                                        .black54)))
346
+                                                      ],
347
+                                                    ),
348
+                                                  ],
349
+                                                ),
350
+                                              )),
351
+                                        ],
352
+                                      ),
353
+                                    ],
354
+                                  ),
355
+                                ),
356
+                                Container(
357
+                                  margin: EdgeInsets.only(
358
+                                      left: 10, right: 10, top: 10, bottom: 10),
359
+                                  child: Column(
360
+                                    children: [
361
+                                      Row(
362
+                                        children: [
363
+                                          Expanded(
364
+                                            flex: 3,
365
+                                            child: Text(
366
+                                              'Lampiran\t:\t',
367
+                                              style: GoogleFonts.inconsolata(
368
+                                                  fontSize: 17),
369
+                                            ),
370
+                                          ),
371
+                                          Expanded(
372
+                                            flex: 7,
373
+                                            child: Container(
374
+                                              child: ElevatedButton(
375
+                                                onPressed: () {},
376
+                                                child: Container(
377
+                                                  width: double.infinity,
378
+                                                  child: Text("Pilih File"),
379
+                                                ),
380
+                                              ),
381
+                                            ),
382
+                                          )
383
+                                        ],
384
+                                      ),
385
+                                      Row(
386
+                                        children: [
387
+                                          Expanded(
388
+                                            flex: 3,
389
+                                            child: Text(
390
+                                              '',
391
+                                              style: GoogleFonts.inconsolata(
392
+                                                  fontSize: 17),
393
+                                            ),
394
+                                          ),
395
+                                          Expanded(
396
+                                            flex: 7,
397
+                                            child: Visibility(
398
+                                                visible: true,
399
+                                                child: Container(
400
+                                                  alignment:
401
+                                                      Alignment.centerLeft,
402
+                                                  margin: EdgeInsets.only(
403
+                                                      left: 15,
404
+                                                      right: 15,
405
+                                                      bottom: 10),
406
+                                                  child: Flexible(
407
+                                                    child: Text(
408
+                                                      "Selected File",
409
+                                                      style: TextStyle(
410
+                                                          color:
411
+                                                              Colors.black54),
412
+                                                    ),
413
+                                                  ),
414
+                                                )),
415
+                                          )
416
+                                        ],
417
+                                      ),
418
+                                      InkWell(
419
+                                        child: Container(
420
+                                          padding: EdgeInsets.fromLTRB(
421
+                                              10, 10, 10, 10),
422
+                                          width: double.infinity,
423
+                                          decoration: BoxDecoration(
424
+                                              borderRadius:
425
+                                                  BorderRadius.circular(5),
426
+                                              gradient: LinearGradient(colors: [
427
+                                                Color(0xFFFF9945),
428
+                                                Color(0xFFFc6076)
429
+                                              ])),
430
+                                          child: Text('Ajukan',
431
+                                              textAlign: TextAlign.center,
432
+                                              style: TextStyle(
433
+                                                  color: Colors.white,
434
+                                                  fontSize: 17,
435
+                                                  fontWeight: FontWeight.w500)),
436
+                                        ),
437
+                                        onTap: () {},
438
+                                      )
439
+                                    ],
440
+                                  ),
441
+                                ),
442
+                              ],
443
+                            ),
444
+                          ),
445
+                        ),
446
+                      ),
447
+                    ],
448
+                  ),
449
+                ),
450
+              ),
451
+            ],
452
+          ),
453
+        ],
454
+      )),
455
+    );
456
+  }
457
+}
458
+
459
+List<String> reimburseCategory = [
460
+  "Paid Time Off",
461
+  "Sick Time Off",
462
+  "Compensatory Days",
463
+  "Unpaid"
464
+];

+ 87
- 0
lib/Screens/Menu/SlipGaji/background.dart 查看文件

@@ -0,0 +1,87 @@
1
+import 'package:flutter/material.dart';
2
+
3
+class Background extends StatelessWidget {
4
+  const Background({Key? key}) : super(key: key);
5
+
6
+  @override
7
+  Widget build(BuildContext context) {
8
+    return Scaffold(
9
+      resizeToAvoidBottomInset: false,
10
+      backgroundColor: Colors.white,
11
+      body: Column(
12
+        children: <Widget>[
13
+          new Stack(
14
+            children: <Widget>[
15
+              WavyHeader()
16
+            ],
17
+          ),
18
+        ],
19
+      ),
20
+    );
21
+  }
22
+}
23
+
24
+const List<Color> orangeGradients = [
25
+  Color(0xFFD21404),
26
+  Color(0xFFFD7267)
27
+];
28
+
29
+const List<Color> aquaGradients = [
30
+  Color(0xFF8EF7DA),
31
+  Color(0xFF5AEAF1),
32
+  Colors.blueAccent,
33
+];
34
+
35
+class WavyHeader extends StatelessWidget {
36
+  @override
37
+  Widget build(BuildContext context) {
38
+    return ClipPath(
39
+      clipper: TopWaveClipper(),
40
+      child: Container(
41
+        decoration: BoxDecoration(
42
+          gradient: LinearGradient(
43
+              colors: orangeGradients,
44
+              begin: Alignment.topLeft,
45
+              end: Alignment.center),
46
+        ),
47
+        height: MediaQuery.of(context).size.height / 2.5,
48
+      ),
49
+    );
50
+  }
51
+}
52
+
53
+class TopWaveClipper extends CustomClipper<Path> {
54
+  @override
55
+  Path getClip(Size size) {
56
+    // This is where we decide what part of our image is going to be visible.
57
+    var path = Path();
58
+    path.lineTo(0.0, 0.0);
59
+
60
+    var firstControlPoint = new Offset(0, size.height - 30);
61
+    var firstEndPoint = new Offset(0, size.height / 2);
62
+
63
+    path.quadraticBezierTo(firstControlPoint.dx, firstControlPoint.dy,
64
+        firstEndPoint.dx, firstEndPoint.dy);
65
+
66
+    var secondControlPoint = Offset(size.width / 5, size.height / 4);
67
+    var secondEndPoint = Offset(size.width / 1.5, size.height / 5);
68
+    path.quadraticBezierTo(secondControlPoint.dx, secondControlPoint.dy,
69
+        secondEndPoint.dx, secondEndPoint.dy);
70
+
71
+    var thirdControlPoint =
72
+        Offset(size.width - (size.width / 9), size.height / 6);
73
+    var thirdEndPoint = Offset(size.width, 0.0);
74
+    path.quadraticBezierTo(thirdControlPoint.dx, thirdControlPoint.dy,
75
+        thirdEndPoint.dx, thirdEndPoint.dy);
76
+
77
+    ///move from bottom right to top
78
+    path.lineTo(size.width, 0.0);
79
+
80
+    ///finally close the path by reaching start point from top right corner
81
+    path.close();
82
+    return path;
83
+  }
84
+
85
+  @override
86
+  bool shouldReclip(CustomClipper<Path> oldClipper) => false;
87
+}

+ 149
- 2
lib/Screens/Menu/SlipGaji/slipgaji_screen.dart 查看文件

@@ -1,10 +1,157 @@
1
+import 'package:flutter/cupertino.dart';
1 2
 import 'package:flutter/material.dart';
3
+import 'package:google_fonts/google_fonts.dart';
4
+import 'package:hris_selfservice_mobile/Screens/Menu/SlipGaji/background.dart';
2 5
 
3
-class SlipGajiScreen extends StatelessWidget {
6
+class SlipGajiScreen extends StatefulWidget {
4 7
   const SlipGajiScreen({Key? key}) : super(key: key);
5 8
 
9
+  @override
10
+  State<SlipGajiScreen> createState() => _SlipGajiScreenState();
11
+}
12
+
13
+class _SlipGajiScreenState extends State<SlipGajiScreen> {
14
+  var selectedDate;
15
+  bool visible = false;
16
+
6 17
   @override
7 18
   Widget build(BuildContext context) {
8
-    return Container();
19
+    return Scaffold(
20
+      body: SingleChildScrollView(
21
+          child: Column(
22
+        children: <Widget>[
23
+          Stack(
24
+            children: [
25
+              WavyHeader(),
26
+              Container(
27
+                margin: EdgeInsets.only(top: 90),
28
+                padding: EdgeInsets.fromLTRB(20, 5, 25, 5),
29
+                child: Row(
30
+                  mainAxisAlignment: MainAxisAlignment.end,
31
+                  crossAxisAlignment: CrossAxisAlignment.end,
32
+                  children: [
33
+                    Text(
34
+                      'Slip Gaji\t\t',
35
+                      maxLines: 1,
36
+                      style: GoogleFonts.luckiestGuy(
37
+                        fontSize: 28,
38
+                        color: Colors.red,
39
+                        fontStyle: FontStyle.italic,
40
+                      ),
41
+                    ),
42
+                    Image.asset('assets/icons/ic_salary.png', width: 40, height: 40,),
43
+                  ],
44
+                )
45
+              ),
46
+              SafeArea(
47
+                  child: Container(
48
+                width: MediaQuery.of(context).size.width,
49
+                margin: EdgeInsets.only(
50
+                  top: MediaQuery.of(context).size.height / 5,
51
+                  left: 15,
52
+                  right: 15,
53
+                ),
54
+                child: Column(
55
+                  children: [
56
+                    Container(
57
+                      margin: EdgeInsets.only(bottom: 20),
58
+                      child: Row(
59
+                        children: [
60
+                          Expanded(
61
+                              flex: 2,
62
+                              child: Text(
63
+                                'Date\t:\t',
64
+                                style: GoogleFonts.inconsolata(fontSize: 20),
65
+                              )),
66
+                          Expanded(
67
+                              flex: 8,
68
+                              child: Container(
69
+                                decoration: BoxDecoration(
70
+                                    color: CupertinoColors.systemGrey2,
71
+                                    borderRadius: BorderRadius.circular(5)),
72
+                                child: DropdownButton(
73
+                                  value: this.selectedDate,
74
+                                  isExpanded: true,
75
+                                  underline: SizedBox(),
76
+                                  hint: Text(
77
+                                    '\t\t\tChoose Date',
78
+                                    style: TextStyle(color: Colors.black54),
79
+                                  ),
80
+                                  onChanged: (value) {
81
+                                    print(value);
82
+                                    setState(() {
83
+                                      selectedDate = value!;
84
+                                      if (selectedDate == value){
85
+                                        visible = true;
86
+                                      } else {
87
+                                        visible = false;
88
+                                      }
89
+                                    });
90
+                                  },
91
+                                  items: dateList
92
+                                      .map(
93
+                                        (e) => DropdownMenuItem(
94
+                                            value: e,
95
+                                            child: Text("\t\t\t" + e)),
96
+                                      )
97
+                                      .toList(),
98
+                                ),
99
+                              )),
100
+                        ],
101
+                      ),
102
+                    ),
103
+                    Visibility(
104
+                      visible: visible,
105
+                      child: Text(
106
+                        'Detail Slip Gaji Bulan ' + selectedDate.toString(),
107
+                        style: GoogleFonts.viga(
108
+                          fontSize: 15,
109
+                          fontWeight: FontWeight.bold,
110
+                        ),
111
+                      ),
112
+                    ),
113
+                    Visibility(
114
+                        visible: visible,
115
+                        child: Container(
116
+                          height: 200,
117
+                          child: Card(
118
+                            elevation: 7,
119
+                            child: Container(
120
+                                decoration: BoxDecoration(
121
+                                    color: Color(0XFFFFFEFC),
122
+                                    borderRadius: BorderRadius.circular(10))),
123
+                          ),
124
+                        )),
125
+                    Visibility(
126
+                      visible: visible,
127
+                      child: Container(
128
+                        alignment: Alignment.centerRight,
129
+                        child: ElevatedButton(
130
+                          onPressed: () {},
131
+                          style: ElevatedButton.styleFrom(),
132
+                          child: Text('Download Slip Gaji'),
133
+                        ),
134
+                      ),
135
+                    ),
136
+                  ],
137
+                ),
138
+              )),
139
+            ],
140
+          ),
141
+        ],
142
+      )),
143
+    );
9 144
   }
10 145
 }
146
+
147
+List<String> dateList = [
148
+  "September 2022",
149
+  "Oktober 2022",
150
+  "November 2022",
151
+  "Desember 2022"
152
+];
153
+
154
+const List<Color> Gradients1 = [
155
+  Color(0xFF0EDED2),
156
+  Color(0xFF03A0FE),
157
+];

+ 465
- 0
lib/Screens/Menu/SuratTugas/surattugas_screen.dart 查看文件

@@ -0,0 +1,465 @@
1
+import 'package:flutter/cupertino.dart';
2
+import 'package:flutter/material.dart';
3
+import 'package:google_fonts/google_fonts.dart';
4
+
5
+import '../SlipGaji/background.dart';
6
+
7
+class SuratTugas_Screen extends StatefulWidget {
8
+  const SuratTugas_Screen({Key? key}) : super(key: key);
9
+
10
+  @override
11
+  State<SuratTugas_Screen> createState() => _SuratTugas_ScreenState();
12
+}
13
+
14
+class _SuratTugas_ScreenState extends State<SuratTugas_Screen> {
15
+  var selectedCategory;
16
+  var selectedDate;
17
+
18
+  int _value = 0;
19
+
20
+  @override
21
+  Widget build(BuildContext context) {
22
+    return Scaffold(
23
+      body: SingleChildScrollView(
24
+          child: Column(
25
+        children: <Widget>[
26
+          Stack(
27
+            children: [
28
+              WavyHeader(),
29
+              Container(
30
+                  margin: EdgeInsets.only(top: 90),
31
+                  padding: EdgeInsets.fromLTRB(20, 5, 25, 5),
32
+                  child: Row(
33
+                    mainAxisAlignment: MainAxisAlignment.end,
34
+                    crossAxisAlignment: CrossAxisAlignment.end,
35
+                    children: [
36
+                      Text(
37
+                        'Surat Tugas\t\t',
38
+                        maxLines: 1,
39
+                        style: GoogleFonts.luckiestGuy(
40
+                          fontSize: 28,
41
+                          color: Colors.red,
42
+                          fontStyle: FontStyle.italic,
43
+                        ),
44
+                      ),
45
+                      Image.asset(
46
+                        'assets/icons/menu/ic_menu_surattugas.png',
47
+                        width: 40,
48
+                        height: 40,
49
+                      ),
50
+                    ],
51
+                  )),
52
+              SafeArea(
53
+                child: Container(
54
+                  width: MediaQuery.of(context).size.width,
55
+                  margin: EdgeInsets.only(
56
+                    top: MediaQuery.of(context).size.height / 5,
57
+                    left: 10,
58
+                    right: 10,
59
+                  ),
60
+                  child: Column(
61
+                    children: [
62
+                      InkWell(
63
+                        child: Container(
64
+                            margin: EdgeInsets.only(top: 15, bottom: 15),
65
+                            padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
66
+                            width: double.infinity,
67
+                            decoration: BoxDecoration(
68
+                                borderRadius: BorderRadius.circular(5),
69
+                                gradient: LinearGradient(colors: [
70
+                                  Color(0xFF2D4059),
71
+                                  Color(0xFF2D4059),
72
+                                  /*Color(0xFFEAFFD0),
73
+                                  Color(0xFF95E1D3),*/
74
+                                ])),
75
+                            child: Row(
76
+                              mainAxisAlignment: MainAxisAlignment.center,
77
+                              children: [
78
+                                Flexible(
79
+                                    child: Text('Lihat Riwayat Surat Tugas\t\t',
80
+                                        textAlign: TextAlign.center,
81
+                                        style: TextStyle(
82
+                                            color: Colors.white,
83
+                                            fontSize: 17,
84
+                                            fontWeight: FontWeight.w500))),
85
+                                Image.asset(
86
+                                  'assets/images/ic_history.png',
87
+                                  width: 30,
88
+                                  height: 30,
89
+                                )
90
+                              ],
91
+                            )),
92
+                        onTap: () {},
93
+                      ),
94
+                      Container(
95
+                        child: Card(
96
+                          elevation: 10,
97
+                          child: Container(
98
+                            decoration: BoxDecoration(
99
+                                color: Color(0XFFFAF7EE),
100
+                                borderRadius: BorderRadius.circular(10)),
101
+                            child: Column(
102
+                              children: [
103
+                                Container(
104
+                                  margin: EdgeInsets.only(
105
+                                      left: 10, right: 10, top: 10, bottom: 10),
106
+                                  child: Row(
107
+                                    children: [
108
+                                      Expanded(
109
+                                          flex: 3,
110
+                                          child: Text(
111
+                                            'Kategori\t:\t',
112
+                                            style: GoogleFonts.inconsolata(
113
+                                                fontSize: 17),
114
+                                          )),
115
+                                      Expanded(
116
+                                          flex: 7,
117
+                                          child: Container(
118
+                                            decoration: BoxDecoration(
119
+                                                color:
120
+                                                    CupertinoColors.systemGrey2,
121
+                                                borderRadius:
122
+                                                    BorderRadius.circular(5)),
123
+                                            child: DropdownButton(
124
+                                              value: this.selectedCategory,
125
+                                              isExpanded: true,
126
+                                              underline: SizedBox(),
127
+                                              hint: Text(
128
+                                                '\t\t\tPilih Kategori',
129
+                                                style: TextStyle(
130
+                                                    color: Colors.black54),
131
+                                              ),
132
+                                              onChanged: (value) {
133
+                                                print(value);
134
+                                                setState(() {
135
+                                                  selectedCategory = value!;
136
+                                                });
137
+                                              },
138
+                                              items: reimburseCategory
139
+                                                  .map(
140
+                                                    (e) => DropdownMenuItem(
141
+                                                        value: e,
142
+                                                        child:
143
+                                                            Text("\t\t\t" + e)),
144
+                                                  )
145
+                                                  .toList(),
146
+                                            ),
147
+                                          )),
148
+                                    ],
149
+                                  ),
150
+                                ),
151
+                                Container(
152
+                                  margin: EdgeInsets.only(
153
+                                      left: 10, right: 10, top: 10, bottom: 10),
154
+                                  child: Column(
155
+                                    children: [
156
+                                      Row(
157
+                                        children: [
158
+                                          Expanded(
159
+                                              flex: 3,
160
+                                              child: Text(
161
+                                                'Tanggal\t:\t',
162
+                                                style: GoogleFonts.inconsolata(
163
+                                                    fontSize: 17),
164
+                                              )),
165
+                                          Expanded(
166
+                                              flex: 7,
167
+                                              child: Container(
168
+                                                decoration: BoxDecoration(
169
+                                                    color: CupertinoColors
170
+                                                        .systemGrey2,
171
+                                                    borderRadius:
172
+                                                        BorderRadius.circular(
173
+                                                            5)),
174
+                                                child: Column(
175
+                                                  children: [
176
+                                                    DropdownButton(
177
+                                                      value: this.selectedDate,
178
+                                                      isExpanded: true,
179
+                                                      underline: SizedBox(),
180
+                                                      hint: Text(
181
+                                                        '\t\t\tPilih Tanggal',
182
+                                                        style: TextStyle(
183
+                                                            color:
184
+                                                                Colors.black54),
185
+                                                      ),
186
+                                                      onChanged: (value) {
187
+                                                        print(value);
188
+                                                        setState(() {
189
+                                                          selectedDate = value!;
190
+                                                        });
191
+                                                      },
192
+                                                      items: reimburseCategory
193
+                                                          .map(
194
+                                                            (e) =>
195
+                                                                DropdownMenuItem(
196
+                                                                    value: e,
197
+                                                                    child: Text(
198
+                                                                        "\t\t\t" +
199
+                                                                            e)),
200
+                                                          )
201
+                                                          .toList(),
202
+                                                    ),
203
+                                                  ],
204
+                                                ),
205
+                                              )),
206
+                                        ],
207
+                                      ),
208
+                                    ],
209
+                                  ),
210
+                                ),
211
+                                Container(
212
+                                  margin: EdgeInsets.only(
213
+                                      left: 10, right: 10, top: 10, bottom: 10),
214
+                                  child: Row(
215
+                                    children: [
216
+                                      Expanded(
217
+                                          flex: 3,
218
+                                          child: Text(
219
+                                            'Total Harga\t:\t',
220
+                                            style: GoogleFonts.inconsolata(
221
+                                                fontSize: 17),
222
+                                          )),
223
+                                      Expanded(
224
+                                          flex: 7,
225
+                                          child: Container(
226
+                                              decoration: BoxDecoration(
227
+                                                  color: Colors.white,
228
+                                                  borderRadius:
229
+                                                      BorderRadius.circular(5)),
230
+                                              child: Padding(
231
+                                                padding: EdgeInsets.only(
232
+                                                    left: 10,
233
+                                                    right: 10,
234
+                                                    top: 5,
235
+                                                    bottom: 5),
236
+                                                child: TextFormField(
237
+                                                    keyboardType:
238
+                                                        TextInputType.number,
239
+                                                    maxLines: 1,
240
+                                                    textInputAction:
241
+                                                        TextInputAction.next,
242
+                                                    decoration: InputDecoration(
243
+                                                        border:
244
+                                                            InputBorder.none,
245
+                                                        hintText:
246
+                                                            "Masukkan tanpa tanda baca (.) atau (,)")),
247
+                                              ))),
248
+                                    ],
249
+                                  ),
250
+                                ),
251
+                                Container(
252
+                                  margin: EdgeInsets.only(
253
+                                      left: 10, right: 10, top: 10, bottom: 10),
254
+                                  child: Row(
255
+                                    children: [
256
+                                      Expanded(
257
+                                          flex: 3,
258
+                                          child: Text(
259
+                                            'Deskripsi\t:\t',
260
+                                            style: GoogleFonts.inconsolata(
261
+                                                fontSize: 17),
262
+                                          )),
263
+                                      Expanded(
264
+                                          flex: 7,
265
+                                          child: Container(
266
+                                              decoration: BoxDecoration(
267
+                                                  color: Colors.white,
268
+                                                  borderRadius:
269
+                                                      BorderRadius.circular(5)),
270
+                                              child: Padding(
271
+                                                padding: EdgeInsets.only(
272
+                                                    left: 10,
273
+                                                    right: 10,
274
+                                                    top: 5,
275
+                                                    bottom: 5),
276
+                                                child: TextFormField(
277
+                                                    keyboardType:
278
+                                                        TextInputType.multiline,
279
+                                                    maxLines: null,
280
+                                                    textInputAction:
281
+                                                        TextInputAction.done,
282
+                                                    decoration: InputDecoration(
283
+                                                        border:
284
+                                                            InputBorder.none,
285
+                                                        hintText: "Deskripsi")),
286
+                                              ))),
287
+                                    ],
288
+                                  ),
289
+                                ),
290
+                                Container(
291
+                                  margin: EdgeInsets.only(
292
+                                      left: 10, right: 10, top: 10, bottom: 10),
293
+                                  child: Column(
294
+                                    children: [
295
+                                      Row(
296
+                                        children: [
297
+                                          Expanded(
298
+                                              flex: 3,
299
+                                              child: Text(
300
+                                                'Pembayaran\t:',
301
+                                                style: GoogleFonts.inconsolata(
302
+                                                    fontSize: 17),
303
+                                              )),
304
+                                          Expanded(
305
+                                              flex: 7,
306
+                                              child: Container(
307
+                                                child: Column(
308
+                                                  children: [
309
+                                                    Row(
310
+                                                      children: [
311
+                                                        Radio(
312
+                                                          value: 1,
313
+                                                          groupValue: _value,
314
+                                                          onChanged: (value) {
315
+                                                            setState(() {
316
+                                                              _value = value!;
317
+                                                            });
318
+                                                          },
319
+                                                        ),
320
+                                                        Flexible(
321
+                                                            child: Text(
322
+                                                                "Karyawan (Perlu Reimburse)",
323
+                                                                style:
324
+                                                                    TextStyle(
325
+                                                                  color: Colors
326
+                                                                      .black54,
327
+                                                                ))),
328
+                                                      ],
329
+                                                    ),
330
+                                                    Row(
331
+                                                      children: [
332
+                                                        Radio(
333
+                                                          value: 2,
334
+                                                          groupValue: _value,
335
+                                                          onChanged: (value) {
336
+                                                            setState(() {
337
+                                                              _value = value!;
338
+                                                            });
339
+                                                          },
340
+                                                        ),
341
+                                                        Flexible(
342
+                                                            child: Text(
343
+                                                                "Perusahaan",
344
+                                                                style: TextStyle(
345
+                                                                    color: Colors
346
+                                                                        .black54)))
347
+                                                      ],
348
+                                                    ),
349
+                                                  ],
350
+                                                ),
351
+                                              )),
352
+                                        ],
353
+                                      ),
354
+                                    ],
355
+                                  ),
356
+                                ),
357
+                                Container(
358
+                                  margin: EdgeInsets.only(
359
+                                      left: 10, right: 10, top: 10, bottom: 10),
360
+                                  child: Column(
361
+                                    children: [
362
+                                      Row(
363
+                                        children: [
364
+                                          Expanded(
365
+                                            flex: 3,
366
+                                            child: Text(
367
+                                              'Lampiran\t:\t',
368
+                                              style: GoogleFonts.inconsolata(
369
+                                                  fontSize: 17),
370
+                                            ),
371
+                                          ),
372
+                                          Expanded(
373
+                                            flex: 7,
374
+                                            child: Container(
375
+                                              child: ElevatedButton(
376
+                                                onPressed: () {},
377
+                                                child: Container(
378
+                                                  width: double.infinity,
379
+                                                  child: Text("Pilih File"),
380
+                                                ),
381
+                                              ),
382
+                                            ),
383
+                                          )
384
+                                        ],
385
+                                      ),
386
+                                      Row(
387
+                                        children: [
388
+                                          Expanded(
389
+                                            flex: 3,
390
+                                            child: Text(
391
+                                              '',
392
+                                              style: GoogleFonts.inconsolata(
393
+                                                  fontSize: 17),
394
+                                            ),
395
+                                          ),
396
+                                          Expanded(
397
+                                            flex: 7,
398
+                                            child: Visibility(
399
+                                                visible: true,
400
+                                                child: Container(
401
+                                                  alignment:
402
+                                                      Alignment.centerLeft,
403
+                                                  margin: EdgeInsets.only(
404
+                                                      left: 15,
405
+                                                      right: 15,
406
+                                                      bottom: 10),
407
+                                                  child: Flexible(
408
+                                                    child: Text(
409
+                                                      "Selected File",
410
+                                                      style: TextStyle(
411
+                                                          color:
412
+                                                              Colors.black54),
413
+                                                    ),
414
+                                                  ),
415
+                                                )),
416
+                                          )
417
+                                        ],
418
+                                      ),
419
+                                      InkWell(
420
+                                        child: Container(
421
+                                          padding: EdgeInsets.fromLTRB(
422
+                                              10, 10, 10, 10),
423
+                                          width: double.infinity,
424
+                                          decoration: BoxDecoration(
425
+                                              borderRadius:
426
+                                                  BorderRadius.circular(5),
427
+                                              gradient: LinearGradient(colors: [
428
+                                                Color(0xFFFF9945),
429
+                                                Color(0xFFFc6076)
430
+                                              ])),
431
+                                          child: Text('Ajukan',
432
+                                              textAlign: TextAlign.center,
433
+                                              style: TextStyle(
434
+                                                  color: Colors.white,
435
+                                                  fontSize: 17,
436
+                                                  fontWeight: FontWeight.w500)),
437
+                                        ),
438
+                                        onTap: () {},
439
+                                      )
440
+                                    ],
441
+                                  ),
442
+                                ),
443
+                              ],
444
+                            ),
445
+                          ),
446
+                        ),
447
+                      ),
448
+                    ],
449
+                  ),
450
+                ),
451
+              ),
452
+            ],
453
+          ),
454
+        ],
455
+      )),
456
+    );
457
+  }
458
+}
459
+
460
+List<String> reimburseCategory = [
461
+  "Paid Time Off",
462
+  "Sick Time Off",
463
+  "Compensatory Days",
464
+  "Unpaid"
465
+];

+ 40
- 0
lib/Screens/Settings/RequestHttp/changePassword_post.dart 查看文件

@@ -0,0 +1,40 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'dart:developer' as developer;
6
+
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+class ChangePassword_Post {
10
+  late String password;
11
+  late String new_password;
12
+  late String session;
13
+
14
+  ChangePassword_Post({required this.password, required this.new_password, required this.session});
15
+
16
+  static Future<String> connectToAPI(String password, String new_password, String session) async {
17
+    String URL = baseURL + "/api/v1/change_password";
18
+
19
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
20
+      "data": [
21
+        {
22
+          "password": password,
23
+          "new_password": new_password,
24
+          "session": session
25
+        }
26
+      ]
27
+    }), headers: {
28
+      "Content-Type": "application/json",
29
+      "Api-key": apiKey
30
+    });
31
+
32
+    developer.log(sendData.toString(), name: "sendatabody");
33
+    return sendData.body;
34
+
35
+    /*var jsonObject = json.decode(sendData.body);
36
+    developer.log(jsonObject.toString(), name: 'Log');*/
37
+    // return jsonObject;
38
+    // return LoginPostResult.createPostResult(jsonObject);
39
+  }
40
+}

+ 41
- 0
lib/Screens/Settings/RequestHttp/changeprofileimage_post.dart 查看文件

@@ -0,0 +1,41 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'dart:developer' as developer;
6
+
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+class ChangeProfileImage_Post {
10
+  late String session;
11
+  late String imageBase64;
12
+
13
+  ChangeProfileImage_Post({required this.session,
14
+    required this.imageBase64});
15
+
16
+  static Future<String> connectToAPI(String session, String imageBase64) async {
17
+    String URL = baseURL + "/api/v1/change_profile";
18
+
19
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
20
+    final session = prefs.getString('session');
21
+
22
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
23
+      "data": [
24
+        {
25
+          "session": session,
26
+          "image": imageBase64,
27
+        }
28
+      ]
29
+    }), headers: {
30
+      "Content-Type": "application/json",
31
+      "Api-key": apiKey
32
+    });
33
+
34
+    return sendData.body;
35
+
36
+    /*var jsonObject = json.decode(sendData.body);
37
+    developer.log(jsonObject.toString(), name: 'Log');*/
38
+    // return jsonObject;
39
+    // return LoginPostResult.createPostResult(jsonObject);
40
+  }
41
+}

+ 39
- 0
lib/Screens/Settings/RequestHttp/getDetail_post.dart 查看文件

@@ -0,0 +1,39 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'dart:developer' as developer;
6
+
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+class GetDetail_Post {
10
+  late String session;
11
+
12
+  GetDetail_Post({required this.session});
13
+
14
+  static Future<String> connectToAPI(String session) async {
15
+    String URL = baseURL + "/api/v1/get_detail";
16
+
17
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
18
+    final session = prefs.getString('session');
19
+
20
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
21
+      "data": [
22
+        {
23
+          "session": session
24
+        }
25
+      ]
26
+    }), headers: {
27
+      "Content-Type": "application/json",
28
+      "Api-key": apiKey
29
+    });
30
+
31
+    developer.log(sendData.body, name: "Get Detail Result");
32
+    return sendData.body;
33
+
34
+    /*var jsonObject = json.decode(sendData.body);
35
+    developer.log(jsonObject.toString(), name: 'Log');*/
36
+    // return jsonObject;
37
+    // return LoginPostResult.createPostResult(jsonObject);
38
+  }
39
+}

+ 39
- 0
lib/Screens/Settings/RequestHttp/getProfileImage_post.dart 查看文件

@@ -0,0 +1,39 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'dart:developer' as developer;
6
+
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+class GetProfileImage_Post {
10
+  late String session;
11
+
12
+  GetProfileImage_Post({required this.session});
13
+
14
+  static Future<String> connectToAPI(String session) async {
15
+    String URL = baseURL + "/api/v1/get_image";
16
+
17
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
18
+    final session = prefs.getString('session');
19
+
20
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
21
+      "data": [
22
+        {
23
+          "session": session
24
+        }
25
+      ]
26
+    }), headers: {
27
+      "Content-Type": "application/json",
28
+      "Api-key": apiKey
29
+    });
30
+
31
+    developer.log(sendData.body, name: "sendatabody");
32
+    return sendData.body;
33
+
34
+    /*var jsonObject = json.decode(sendData.body);
35
+    developer.log(jsonObject.toString(), name: 'Log');*/
36
+    // return jsonObject;
37
+    // return LoginPostResult.createPostResult(jsonObject);
38
+  }
39
+}

+ 39
- 0
lib/Screens/Settings/RequestHttp/logout_post.dart 查看文件

@@ -0,0 +1,39 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'dart:developer' as developer;
6
+
7
+import 'package:shared_preferences/shared_preferences.dart';
8
+
9
+class Logout_Post {
10
+  late String session;
11
+
12
+  Logout_Post({required this.session});
13
+
14
+  static Future<String> connectToAPI(String session) async {
15
+    String URL = baseURL + "/api/v1/logout";
16
+
17
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
18
+    final session = prefs.getString('session');
19
+
20
+    var sendData = await http.post(Uri.parse(URL), body: jsonEncode({
21
+      "data": [
22
+        {
23
+          "session": session
24
+        }
25
+      ]
26
+    }), headers: {
27
+      "Content-Type": "application/json",
28
+      "Api-key": apiKey
29
+    });
30
+
31
+    developer.log(sendData.body, name: "sendatabody");
32
+    return sendData.body;
33
+
34
+    /*var jsonObject = json.decode(sendData.body);
35
+    developer.log(jsonObject.toString(), name: 'Log');*/
36
+    // return jsonObject;
37
+    // return LoginPostResult.createPostResult(jsonObject);
38
+  }
39
+}

+ 75
- 2
lib/Screens/Settings/inputWidget.dart 查看文件

@@ -1,9 +1,9 @@
1 1
 import 'package:flutter/material.dart';
2 2
 
3
-class InputWidgetPassword extends StatelessWidget {
3
+class InputWidgetCurrentPassword extends StatelessWidget {
4 4
   final String hintText;
5 5
 
6
-  InputWidgetPassword(this.hintText);
6
+  InputWidgetCurrentPassword(this.hintText);
7 7
 
8 8
   @override
9 9
   Widget build(BuildContext context) {
@@ -19,6 +19,75 @@ class InputWidgetPassword extends StatelessWidget {
19 19
           child: Padding(
20 20
             padding: EdgeInsets.only(left: 5, right: 5),
21 21
             child: TextFormField(
22
+              controller: passwordController,
23
+              textInputAction: TextInputAction.next,
24
+              obscureText: true,
25
+              decoration: InputDecoration(
26
+                  border: InputBorder.none,
27
+                  hintText: hintText,
28
+                  hintStyle: TextStyle(color: Color(0xFFE1E1E1), fontSize: 16)),
29
+            ),
30
+          ),
31
+        ),
32
+      ),
33
+    );
34
+  }
35
+}
36
+
37
+class InputWidgetNewPassword extends StatelessWidget {
38
+  final String hintText;
39
+
40
+  InputWidgetNewPassword(this.hintText);
41
+
42
+  @override
43
+  Widget build(BuildContext context) {
44
+    return Padding(
45
+      padding: EdgeInsets.only(bottom: 15),
46
+      child: Container(
47
+        width: MediaQuery.of(context).size.width,
48
+        child: Material(
49
+          elevation: 10,
50
+          color: Colors.white,
51
+          shape: RoundedRectangleBorder(
52
+              borderRadius: BorderRadius.all(Radius.circular(10))),
53
+          child: Padding(
54
+            padding: EdgeInsets.only(left: 5, right: 5),
55
+            child: TextFormField(
56
+              controller: newPasswordController,
57
+              textInputAction: TextInputAction.next,
58
+              obscureText: true,
59
+              decoration: InputDecoration(
60
+                  border: InputBorder.none,
61
+                  hintText: hintText,
62
+                  hintStyle: TextStyle(color: Color(0xFFE1E1E1), fontSize: 16)),
63
+            ),
64
+          ),
65
+        ),
66
+      ),
67
+    );
68
+  }
69
+}
70
+
71
+class InputWidgetRetypeNewPassword extends StatelessWidget {
72
+  final String hintText;
73
+
74
+  InputWidgetRetypeNewPassword(this.hintText);
75
+
76
+  @override
77
+  Widget build(BuildContext context) {
78
+    return Padding(
79
+      padding: EdgeInsets.only(bottom: 15),
80
+      child: Container(
81
+        width: MediaQuery.of(context).size.width,
82
+        child: Material(
83
+          elevation: 10,
84
+          color: Colors.white,
85
+          shape: RoundedRectangleBorder(
86
+              borderRadius: BorderRadius.all(Radius.circular(10))),
87
+          child: Padding(
88
+            padding: EdgeInsets.only(left: 5, right: 5),
89
+            child: TextFormField(
90
+              controller: retypeNewPasswordController,
22 91
               textInputAction: TextInputAction.done,
23 92
               obscureText: true,
24 93
               decoration: InputDecoration(
@@ -32,3 +101,7 @@ class InputWidgetPassword extends StatelessWidget {
32 101
     );
33 102
   }
34 103
 }
104
+
105
+TextEditingController passwordController = TextEditingController();
106
+TextEditingController newPasswordController = TextEditingController();
107
+TextEditingController retypeNewPasswordController = TextEditingController();

+ 777
- 46
lib/Screens/Settings/settings_screen.dart 查看文件

@@ -1,7 +1,20 @@
1
+import 'dart:convert';
2
+import 'dart:io';
1 3
 import 'package:flutter/material.dart';
4
+import 'package:flutter/services.dart';
5
+import 'package:fluttertoast/fluttertoast.dart';
2 6
 import 'package:google_fonts/google_fonts.dart';
7
+import 'package:hris_selfservice_mobile/Screens/Settings/RequestHttp/changePassword_post.dart';
8
+import 'package:hris_selfservice_mobile/Screens/Settings/RequestHttp/changeprofileimage_post.dart';
9
+import 'package:hris_selfservice_mobile/Screens/Settings/RequestHttp/getDetail_post.dart';
10
+import 'package:hris_selfservice_mobile/Screens/Settings/RequestHttp/getProfileImage_post.dart';
11
+import 'package:hris_selfservice_mobile/Screens/Settings/RequestHttp/logout_post.dart';
12
+import 'package:image_picker/image_picker.dart';
13
+import 'package:progress_dialog_null_safe/progress_dialog_null_safe.dart';
14
+import 'package:shared_preferences/shared_preferences.dart';
3 15
 import '../Login/login_screen.dart';
4 16
 import '../Settings/inputWidget.dart';
17
+import 'dart:developer' as logDev;
5 18
 
6 19
 class SettingsScreen extends StatefulWidget {
7 20
   const SettingsScreen({Key? key}) : super(key: key);
@@ -12,10 +25,200 @@ class SettingsScreen extends StatefulWidget {
12 25
 
13 26
 class _SettingsScreenState extends State<SettingsScreen> {
14 27
   bool visible = false;
28
+  bool visiblePersonalInformation = false;
29
+  File? _imagePath;
30
+
31
+  String name = "",
32
+      statusDetail = "",
33
+      dateOfBirth = "",
34
+      phone = "",
35
+      email = "",
36
+      address = "",
37
+      position = "";
38
+
39
+  var _imageToShow;
40
+
41
+  @override
42
+  initState() {
43
+    super.initState();
44
+    passwordController.clear();
45
+    newPasswordController.clear();
46
+    retypeNewPasswordController.clear();
47
+    getDetail();
48
+    _imageToShow = AssetImage('assets/images/ic_administrator.png');
49
+    WidgetsBinding.instance.addPostFrameCallback((_) {
50
+      ProgressDialog loading = ProgressDialog(context);
51
+      loading = ProgressDialog(context,
52
+          type: ProgressDialogType.normal,
53
+          isDismissible: false,
54
+          showLogs: true);
55
+      loading.style(
56
+          message: 'Please Wait .....',
57
+          borderRadius: 5,
58
+          backgroundColor: Colors.white,
59
+          progressWidget: CircularProgressIndicator(),
60
+          elevation: 10.0,
61
+          padding: EdgeInsets.all(10),
62
+          insetAnimCurve: Curves.easeInOut,
63
+          progress: 0.0,
64
+          maxProgress: 100.0,
65
+          progressTextStyle: TextStyle(
66
+              color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
67
+          messageTextStyle: TextStyle(
68
+              color: Colors.black,
69
+              fontSize: 15.0,
70
+              fontWeight: FontWeight.w600));
71
+      loading.show();
72
+      logDev.log(getProfileImage().toString(), name: "APA ISINYA");
73
+      _imageToShow = getProfileImage();
74
+    });
75
+  }
76
+
77
+  //Get Profile image
78
+  getProfileImage() async {
79
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
80
+    final session = prefs.getString('session');
81
+
82
+    ProgressDialog loading = ProgressDialog(context);
83
+    loading = ProgressDialog(context,
84
+        type: ProgressDialogType.normal, isDismissible: false, showLogs: true);
85
+    loading.style(
86
+        message: 'Please Wait .....',
87
+        borderRadius: 5,
88
+        backgroundColor: Colors.white,
89
+        progressWidget: CircularProgressIndicator(),
90
+        elevation: 10.0,
91
+        padding: EdgeInsets.all(10),
92
+        insetAnimCurve: Curves.easeInOut,
93
+        progress: 0.0,
94
+        maxProgress: 100.0,
95
+        progressTextStyle: TextStyle(
96
+            color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
97
+        messageTextStyle: TextStyle(
98
+            color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600));
99
+
100
+    GetProfileImage_Post.connectToAPI(session!).then((valueResult) async {
101
+      Map<String, dynamic> object = json.decode(valueResult);
102
+      if (object.containsKey("result").toString() == "true") {
103
+        String status = object['result']['status'].toString();
104
+        logDev.log(status, name: "STATUS GET PROFILE");
105
+        if (status == "success") {
106
+          String photo = object['result']['photo'].toString();
107
+          if (photo == "false") {
108
+            _imageToShow = AssetImage('assets/images/ic_administrator.png');
109
+            logDev.log("PHOTO RESULT FALSE", name: "DECODED BYTES");
110
+          } else if (photo != "false") {
111
+            Uint8List decodedBytes = Base64Decoder().convert(photo);
112
+            logDev.log(decodedBytes.toString(), name: "DECODED BYTES photo");
113
+            setState(() {
114
+              _imageToShow = Image.memory(decodedBytes, gaplessPlayback: true).image;
115
+            });
116
+            //_imageToShow = Image.memory(base64Decode(photo));
117
+            //logDev.log(_imageToShow.toString(), name: "Image to Show");
118
+            //_imageToShow = AssetImage('assets/images/collaboration.png');
119
+          }
120
+        } else if (status == "failed") {
121
+          String message = object['result']['message'].toString();
122
+          Fluttertoast.showToast(
123
+              msg: message,
124
+              toastLength: Toast.LENGTH_LONG,
125
+              gravity: ToastGravity.CENTER,
126
+              timeInSecForIosWeb: 1,
127
+              textColor: Colors.white,
128
+              fontSize: 16.0);
129
+        }
130
+        loading.hide();
131
+      } else {
132
+        Fluttertoast.showToast(
133
+            msg: "Server Response Error",
134
+            toastLength: Toast.LENGTH_SHORT,
135
+            gravity: ToastGravity.CENTER,
136
+            timeInSecForIosWeb: 1,
137
+            textColor: Colors.white,
138
+            fontSize: 16.0);
139
+        loading.hide();
140
+      }
141
+    });
142
+    //return Image.memory(decodedBytes);
143
+    loading.hide();
144
+    return _imageToShow;
145
+  }
146
+
147
+  //Get Detail
148
+  getDetail() async {
149
+    final SharedPreferences prefs = await SharedPreferences.getInstance();
150
+    final session = prefs.getString('session');
151
+    GetDetail_Post.connectToAPI(session!).then((valueResult) async {
152
+      Map<String, dynamic> object = json.decode(valueResult);
153
+      if (object.containsKey("result").toString() == "true") {
154
+        statusDetail = object['result']['status'].toString();
155
+        String message = object['result']['message'].toString();
156
+        if (statusDetail == "failed" || message == "User Not Found") {
157
+          Fluttertoast.showToast(
158
+              msg: message + ", Please login again!",
159
+              toastLength: Toast.LENGTH_SHORT,
160
+              gravity: ToastGravity.CENTER,
161
+              timeInSecForIosWeb: 1,
162
+              textColor: Colors.white,
163
+              fontSize: 16.0);
164
+        } else if (statusDetail != "failed") {
165
+          name = object['result']['name'].toString();
166
+          dateOfBirth = object['result']['date_of_birth'].toString();
167
+          phone = object['result']['phone'].toString();
168
+          email = object['result']['email'].toString();
169
+          address = object['result']['address'].toString();
170
+          position = object['result']['position'].toString();
171
+
172
+          if (name == "false"){
173
+            name = "-";
174
+          }
175
+          if (dateOfBirth == "false"){
176
+            dateOfBirth = "-";
177
+          }
178
+          if (phone == "false"){
179
+            phone = "-";
180
+          }
181
+          if (email == "false"){
182
+            email = "-";
183
+          }
184
+          if (address == "false"){
185
+            address = "-";
186
+          }
187
+        }
188
+      } else {
189
+        Fluttertoast.showToast(
190
+            msg: "Server Response Error",
191
+            toastLength: Toast.LENGTH_SHORT,
192
+            gravity: ToastGravity.CENTER,
193
+            timeInSecForIosWeb: 1,
194
+            textColor: Colors.white,
195
+            fontSize: 16.0);
196
+      }
197
+    });
198
+  }
15 199
 
16 200
   @override
17 201
   Widget build(BuildContext context) {
18 202
     var size = MediaQuery.of(context).size;
203
+
204
+    ProgressDialog loading = ProgressDialog(context);
205
+    loading = ProgressDialog(context,
206
+        type: ProgressDialogType.normal, isDismissible: false, showLogs: true);
207
+    loading.style(
208
+        message: 'Please Wait .....',
209
+        borderRadius: 5,
210
+        backgroundColor: Colors.white,
211
+        progressWidget: CircularProgressIndicator(),
212
+        elevation: 10.0,
213
+        padding: EdgeInsets.all(10),
214
+        insetAnimCurve: Curves.easeInOut,
215
+        progress: 0.0,
216
+        maxProgress: 100.0,
217
+        progressTextStyle: TextStyle(
218
+            color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
219
+        messageTextStyle: TextStyle(
220
+            color: Colors.black, fontSize: 15.0, fontWeight: FontWeight.w600));
221
+
19 222
     return Scaffold(
20 223
         body: SingleChildScrollView(
21 224
       child: Stack(
@@ -40,8 +243,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
40 243
                     alignment: Alignment.topCenter,
41 244
                     children: [
42 245
                       Container(
43
-                        margin: EdgeInsets.only(
44
-                            top: (((size.width - 20) * 0.33) * 0.5)),
246
+                        margin: EdgeInsets.only(top: (((size.width - 20) * 0.33) * 0.5)),
45 247
                         child: Card(
46 248
                           elevation: 15,
47 249
                           child: Container(
@@ -56,59 +258,304 @@ class _SettingsScreenState extends State<SettingsScreen> {
56 258
                                 mainAxisAlignment: MainAxisAlignment.end,
57 259
                                 crossAxisAlignment: CrossAxisAlignment.center,
58 260
                                 children: <Widget>[
59
-                                  Text(
60
-                                    'Dieni Anindyasarathi',
261
+                                  Text(name,
61 262
                                     maxLines: 2,
62 263
                                     overflow: TextOverflow.ellipsis,
63 264
                                     textAlign: TextAlign.center,
64 265
                                     style: GoogleFonts.inter(
65
-                                        fontSize: 17,
266
+                                        fontSize: 18,
66 267
                                         color: Colors.black,
67 268
                                         fontWeight: FontWeight.bold),
68 269
                                   ),
69
-                                  Text(
70
-                                    'IT Developer',
270
+                                  Text(position,
71 271
                                     textAlign: TextAlign.center,
72 272
                                     style: GoogleFonts.inter(
73
-                                        fontSize: 16, color: Colors.black),
273
+                                        fontSize: 17, color: Colors.black),
74 274
                                   ),
75 275
                                 ],
76 276
                               )),
77 277
                         ),
78 278
                       ),
79 279
                       Container(
80
-                          height: (size.width - 20) * 0.33,
81
-                          width: (size.width - 20) * 0.33,
280
+                        height: (size.width - 20) * 0.33,
281
+                        width: (size.width - 20) * 0.33,
282
+                        decoration: BoxDecoration(
283
+                          color: Colors.black,
284
+                          image: DecorationImage(
285
+                            image: _imageToShow,
286
+                            fit: BoxFit.fill,
287
+                          ),
288
+                          shape: BoxShape.circle,
289
+                        ),
290
+                      ),
291
+                      InkWell(
292
+                        child: Container(
293
+                          height: ((size.width - 20) * 0.33) * 0.25,
294
+                          width: ((size.width - 20) * 0.33) * 0.25,
295
+                          margin: EdgeInsets.only(
296
+                              top: (((size.width - 20) * 0.33) - 20),
297
+                              left: ((size.width - 20) * 0.33) - 10),
82 298
                           decoration: BoxDecoration(
83
-                            color: Colors.black,
299
+                            color: Colors.yellow,
84 300
                             image: DecorationImage(
85
-                              image: AssetImage(
86
-                                  'assets/images/ic_administrator.png'),
87
-                              fit: BoxFit.fill,
301
+                              image: AssetImage('assets/images/ic_camera.png'),
302
+                              scale: 3,
303
+                              fit: BoxFit.scaleDown,
88 304
                             ),
89 305
                             shape: BoxShape.circle,
90 306
                           ),
307
+                        ),
308
+                        onTap: () async {
309
+                          final SharedPreferences prefs =
310
+                              await SharedPreferences.getInstance();
311
+                          final String? session = prefs.getString('session');
312
+                          final ImagePicker _picker = ImagePicker();
313
+                          final XFile? imagePicked = await _picker.pickImage(
314
+                              source: ImageSource.gallery);
315
+                          if (imagePicked != null) {
316
+                            _imagePath = File(imagePicked.path);
317
+                            List<int> imageBytes =
318
+                                _imagePath!.readAsBytesSync();
319
+                            String base64Image = base64Encode(imageBytes);
320
+                            logDev.log(base64Image, name: "String base64");
321
+                            await loading.show();
322
+                            ChangeProfileImage_Post.connectToAPI(
323
+                                    session!, base64Image)
324
+                                .then((valueResult) async {
325
+                              logDev.log(valueResult, name: "HASIL CHANGE");
326
+                              Map<String, dynamic> object =
327
+                                  json.decode(valueResult);
328
+                              if (object.containsKey("result").toString() ==
329
+                                  "true") {
330
+                                String status =
331
+                                    object['result']['status'].toString();
332
+                                String message =
333
+                                    object['result']['message'].toString();
334
+                                if (status == "success") {
335
+                                  _imageToShow =
336
+                                      FileImage(File(imagePicked.path));
337
+                                  Fluttertoast.showToast(
338
+                                      msg: message,
339
+                                      toastLength: Toast.LENGTH_LONG,
340
+                                      gravity: ToastGravity.CENTER,
341
+                                      timeInSecForIosWeb: 1,
342
+                                      textColor: Colors.white,
343
+                                      fontSize: 16.0);
344
+                                  await loading.hide();
345
+                                } else if (status == "failed") {
346
+                                  Fluttertoast.showToast(
347
+                                      msg: message,
348
+                                      toastLength: Toast.LENGTH_LONG,
349
+                                      gravity: ToastGravity.CENTER,
350
+                                      timeInSecForIosWeb: 1,
351
+                                      textColor: Colors.white,
352
+                                      fontSize: 16.0);
353
+                                  await loading.hide();
354
+                                }
355
+                              } else {
356
+                                Fluttertoast.showToast(
357
+                                    msg: "Server Response Error",
358
+                                    toastLength: Toast.LENGTH_SHORT,
359
+                                    gravity: ToastGravity.CENTER,
360
+                                    timeInSecForIosWeb: 1,
361
+                                    textColor: Colors.white,
362
+                                    fontSize: 16.0);
363
+                                await loading.hide();
364
+                              }
365
+                              setState(() {});
366
+                            });
367
+                          } else if (imagePicked == null) {
368
+                            logDev.log("NULL", name: "NO IMAGE SELECTED");
369
+                            //_imagePath = await getImageFileFromAssets('assets/images/ic_administrator.png') as File?;
370
+                          }
371
+                        },
372
+                      )
373
+                    ],
374
+                  ),
375
+                  InkWell(
376
+                    child: roundedRectButton(
377
+                        "Personal Information", Gradients1, 20, 5),
378
+                    onTap: () async {
379
+                      setState(() {
380
+                        visiblePersonalInformation =
381
+                            !visiblePersonalInformation;
382
+                      });
383
+                    },
384
+                  ),
385
+                  Visibility(
386
+                    visible: visiblePersonalInformation,
387
+                    child: Container(
388
+                      margin: EdgeInsets.only(top: 10),
389
+                      width: size.width - 50,
390
+                      padding: EdgeInsets.all(15),
391
+                      decoration: BoxDecoration(
392
+                          color: Color(0xFFD9D9D9),
393
+                          borderRadius: BorderRadius.all(Radius.circular(5))),
394
+                      child: Column(
395
+                        children: [
396
+                          Column(
397
+                            crossAxisAlignment: CrossAxisAlignment.start,
398
+                            children: <Widget>[
399
+                              Padding(
400
+                                padding: EdgeInsets.only(bottom: 5),
401
+                                child: Text(
402
+                                  "Nama Pegawai",
403
+                                  style: TextStyle(
404
+                                      fontSize: 16, color: Colors.black87),
405
+                                ),
406
+                              ),
407
+                              Stack(
408
+                                alignment: Alignment.bottomRight,
409
+                                children: <Widget>[
410
+                                  roundDetail(name, 0, 5, 3),
411
+                                ],
412
+                              ),
413
+                            ],
414
+                          ),
415
+                          Column(
416
+                            crossAxisAlignment: CrossAxisAlignment.start,
417
+                            children: <Widget>[
418
+                              Padding(
419
+                                padding: EdgeInsets.only(bottom: 5),
420
+                                child: Text(
421
+                                  "Status",
422
+                                  style: TextStyle(
423
+                                      fontSize: 16, color: Colors.black87),
424
+                                ),
425
+                              ),
426
+                              Stack(
427
+                                alignment: Alignment.bottomRight,
428
+                                children: <Widget>[
429
+                                  roundDetail(statusDetail, 0, 5, 3),
430
+                                ],
431
+                              ),
432
+                            ],
91 433
                           ),
92
-                      Container(
93
-                        height: ((size.width - 20) * 0.33) * 0.25,
94
-                        width: ((size.width - 20) * 0.33) * 0.25,
95
-                        margin: EdgeInsets.only(
96
-                            top: (((size.width - 20) * 0.33) - 20),
97
-                            left: ((size.width - 20) * 0.33) - 10),
98
-                        decoration: BoxDecoration(
99
-                          color: Colors.yellow,
100
-                          image: DecorationImage(
101
-                            image: AssetImage('assets/images/ic_camera.png'),
102
-                            fit: BoxFit.scaleDown,
434
+                          Column(
435
+                            crossAxisAlignment: CrossAxisAlignment.start,
436
+                            children: <Widget>[
437
+                              Padding(
438
+                                padding: EdgeInsets.only(bottom: 5),
439
+                                child: Text(
440
+                                  "Tanggal Lahir",
441
+                                  style: TextStyle(
442
+                                      fontSize: 16, color: Colors.black87),
443
+                                ),
444
+                              ),
445
+                              Stack(
446
+                                alignment: Alignment.bottomRight,
447
+                                children: <Widget>[
448
+                                  roundDetail(dateOfBirth, 0, 5, 3),
449
+                                ],
450
+                              ),
451
+                            ],
103 452
                           ),
104
-                          shape: BoxShape.circle,
105
-                        ),
453
+                          Column(
454
+                            crossAxisAlignment: CrossAxisAlignment.start,
455
+                            children: <Widget>[
456
+                              Padding(
457
+                                padding: EdgeInsets.only(bottom: 5),
458
+                                child: Text(
459
+                                  "Nomor Telepon",
460
+                                  style: TextStyle(
461
+                                      fontSize: 16, color: Colors.black87),
462
+                                ),
463
+                              ),
464
+                              Stack(
465
+                                alignment: Alignment.bottomRight,
466
+                                children: <Widget>[
467
+                                  roundDetail(phone, 0, 5, 3),
468
+                                ],
469
+                              ),
470
+                            ],
471
+                          ),
472
+                          Column(
473
+                            crossAxisAlignment: CrossAxisAlignment.start,
474
+                            children: <Widget>[
475
+                              Padding(
476
+                                padding: EdgeInsets.only(bottom: 5),
477
+                                child: Text(
478
+                                  "Alamat Email",
479
+                                  style: TextStyle(
480
+                                      fontSize: 16, color: Colors.black87),
481
+                                ),
482
+                              ),
483
+                              Stack(
484
+                                alignment: Alignment.bottomRight,
485
+                                children: <Widget>[
486
+                                  roundDetail(email, 0, 5, 3),
487
+                                ],
488
+                              ),
489
+                            ],
490
+                          ),
491
+                          Column(
492
+                            crossAxisAlignment: CrossAxisAlignment.start,
493
+                            children: <Widget>[
494
+                              Padding(
495
+                                padding: EdgeInsets.only(bottom: 5),
496
+                                child: Text(
497
+                                  "Alamat Rumah",
498
+                                  style: TextStyle(
499
+                                      fontSize: 16, color: Colors.black87),
500
+                                ),
501
+                              ),
502
+                              Stack(
503
+                                alignment: Alignment.bottomRight,
504
+                                children: <Widget>[
505
+                                  roundDetail(address, 0, 5, 3),
506
+                                ],
507
+                              ),
508
+                            ],
509
+                          ),
510
+                          /*InkWell(
511
+                              child: roundedRectButton(
512
+                                  "Save Password", Gradients2, 10, 10),
513
+                              onTap: () {
514
+                                if (!validateFormSavePassword(context)) {
515
+                                  return;
516
+                                } else if (validateFormSavePassword(context)) {
517
+                                  if (newPasswordController.text.toString() ==
518
+                                      retypeNewPasswordController.text
519
+                                          .toString()) {
520
+                                    if (passwordController.text.toString() ==
521
+                                        newPasswordController.text
522
+                                            .toString() ||
523
+                                        passwordController.text.toString() ==
524
+                                            retypeNewPasswordController.text
525
+                                                .toString()) {
526
+                                      Fluttertoast.showToast(
527
+                                          msg:
528
+                                          "Your new password is the same with your old password, please change with new password!",
529
+                                          toastLength: Toast.LENGTH_LONG,
530
+                                          gravity: ToastGravity.CENTER,
531
+                                          timeInSecForIosWeb: 1,
532
+                                          textColor: Colors.white,
533
+                                          fontSize: 16.0);
534
+                                    } else {
535
+                                      showAlertDialogSavePassword(context);
536
+                                    }
537
+                                  } else if (newPasswordController.text
538
+                                      .toString() !=
539
+                                      retypeNewPasswordController.text
540
+                                          .toString()) {
541
+                                    Fluttertoast.showToast(
542
+                                        msg:
543
+                                        "Your retype password was entered incorrectly.\nPlease enter it again!",
544
+                                        toastLength: Toast.LENGTH_LONG,
545
+                                        gravity: ToastGravity.CENTER,
546
+                                        timeInSecForIosWeb: 1,
547
+                                        textColor: Colors.white,
548
+                                        fontSize: 16.0);
549
+                                  }
550
+                                }
551
+                              }),*/
552
+                        ],
106 553
                       ),
107
-                    ],
554
+                    ),
108 555
                   ),
109 556
                   InkWell(
110 557
                     child:
111
-                        roundedRectButton("Edit Password", Gradients1, 20, 5),
558
+                        roundedRectButton("Edit Password", Gradients1, 10, 5),
112 559
                     onTap: () {
113 560
                       setState(() {
114 561
                         visible = !visible;
@@ -140,7 +587,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
140 587
                               Stack(
141 588
                                 alignment: Alignment.bottomRight,
142 589
                                 children: <Widget>[
143
-                                  InputWidgetPassword("Current Password"),
590
+                                  InputWidgetCurrentPassword(
591
+                                      "Current Password"),
144 592
                                 ],
145 593
                               ),
146 594
                             ],
@@ -159,7 +607,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
159 607
                               Stack(
160 608
                                 alignment: Alignment.bottomRight,
161 609
                                 children: <Widget>[
162
-                                  InputWidgetPassword("New Password"),
610
+                                  InputWidgetNewPassword("New Password"),
163 611
                                 ],
164 612
                               ),
165 613
                             ],
@@ -178,7 +626,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
178 626
                               Stack(
179 627
                                 alignment: Alignment.bottomRight,
180 628
                                 children: <Widget>[
181
-                                  InputWidgetPassword("Re-type New Password"),
629
+                                  InputWidgetRetypeNewPassword(
630
+                                      "Re-type New Password"),
182 631
                                 ],
183 632
                               ),
184 633
                             ],
@@ -187,7 +636,43 @@ class _SettingsScreenState extends State<SettingsScreen> {
187 636
                               child: roundedRectButton(
188 637
                                   "Save Password", Gradients2, 10, 10),
189 638
                               onTap: () {
190
-                                showAlertDialog(context);
639
+                                if (!validateFormSavePassword(context)) {
640
+                                  return;
641
+                                } else if (validateFormSavePassword(context)) {
642
+                                  if (newPasswordController.text.toString() ==
643
+                                      retypeNewPasswordController.text
644
+                                          .toString()) {
645
+                                    if (passwordController.text.toString() ==
646
+                                            newPasswordController.text
647
+                                                .toString() ||
648
+                                        passwordController.text.toString() ==
649
+                                            retypeNewPasswordController.text
650
+                                                .toString()) {
651
+                                      Fluttertoast.showToast(
652
+                                          msg:
653
+                                              "Your new password is the same with your old password, please change with new password!",
654
+                                          toastLength: Toast.LENGTH_LONG,
655
+                                          gravity: ToastGravity.CENTER,
656
+                                          timeInSecForIosWeb: 1,
657
+                                          textColor: Colors.white,
658
+                                          fontSize: 16.0);
659
+                                    } else {
660
+                                      showAlertDialogSavePassword(context);
661
+                                    }
662
+                                  } else if (newPasswordController.text
663
+                                          .toString() !=
664
+                                      retypeNewPasswordController.text
665
+                                          .toString()) {
666
+                                    Fluttertoast.showToast(
667
+                                        msg:
668
+                                            "Your retype password was entered incorrectly.\nPlease enter it again!",
669
+                                        toastLength: Toast.LENGTH_LONG,
670
+                                        gravity: ToastGravity.CENTER,
671
+                                        timeInSecForIosWeb: 1,
672
+                                        textColor: Colors.white,
673
+                                        fontSize: 16.0);
674
+                                  }
675
+                                }
191 676
                               }),
192 677
                         ],
193 678
                       ),
@@ -196,7 +681,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
196 681
                   InkWell(
197 682
                       child: roundedRectButton("Logout", Gradients1, 10, 5),
198 683
                       onTap: () {
199
-                        showAlertDialog(context);
684
+                        showAlertDialogLogout(context);
200 685
                       }),
201 686
                 ],
202 687
               ),
@@ -229,11 +714,52 @@ Widget roundedRectButton(String title, List<Color> gradient, double marginTop,
229 714
                   begin: Alignment.topLeft,
230 715
                   end: Alignment.bottomRight),
231 716
             ),
232
-            child: Text(title,
233
-                style: TextStyle(
234
-                    color: Colors.white,
235
-                    fontSize: 19,
236
-                    fontWeight: FontWeight.w500)),
717
+            child: Padding(
718
+              padding: EdgeInsets.fromLTRB(10, 3, 10, 3),
719
+              child: Text(title,
720
+                  style: TextStyle(
721
+                      color: Colors.white,
722
+                      fontSize: 19,
723
+                      fontWeight: FontWeight.w500)),
724
+            ),
725
+            padding: EdgeInsets.all(10),
726
+          )
727
+        ],
728
+      ),
729
+    );
730
+  });
731
+}
732
+
733
+Widget roundDetail(String detail, double marginTop, double marginBottom,
734
+    double radiusCircular) {
735
+  return Builder(builder: (BuildContext mContext) {
736
+    return Align(
737
+      alignment: Alignment.center,
738
+      child: Stack(
739
+        children: <Widget>[
740
+          Container(
741
+            margin: EdgeInsets.only(top: marginTop, bottom: marginBottom),
742
+            alignment: Alignment.centerLeft,
743
+            height: 45,
744
+            width: MediaQuery.of(mContext).size.width - 50,
745
+            decoration: ShapeDecoration(
746
+              shape: RoundedRectangleBorder(
747
+                  borderRadius:
748
+                      BorderRadius.all(Radius.circular(radiusCircular))),
749
+              color: Colors.blueGrey,
750
+              /*gradient: LinearGradient(
751
+                  colors: gradient,
752
+                  begin: Alignment.topLeft,
753
+                  end: Alignment.bottomRight),*/
754
+            ),
755
+            child: Padding(
756
+              padding: EdgeInsets.fromLTRB(3, 3, 3, 3),
757
+              child: Text(detail,
758
+                  style: TextStyle(
759
+                      color: Colors.white,
760
+                      fontSize: 15,
761
+                      fontWeight: FontWeight.w500)),
762
+            ),
237 763
             padding: EdgeInsets.all(10),
238 764
           )
239 765
         ],
@@ -252,16 +778,220 @@ const List<Color> Gradients2 = [
252 778
   Color(0xFFFc6076),
253 779
 ];
254 780
 
255
-showAlertDialog(BuildContext context) {
781
+//Save New Password
782
+showAlertDialogSavePassword(BuildContext context) {
256 783
   // set up the button
257 784
   Widget okButton = TextButton(
258 785
     child: Text("Yes"),
786
+    onPressed: () async {
787
+      ProgressDialog loading = ProgressDialog(context);
788
+      loading = ProgressDialog(context,
789
+          type: ProgressDialogType.normal,
790
+          isDismissible: false,
791
+          showLogs: true);
792
+      loading.style(
793
+          message: 'Please Wait .....',
794
+          borderRadius: 5,
795
+          backgroundColor: Colors.white,
796
+          progressWidget: CircularProgressIndicator(),
797
+          elevation: 10.0,
798
+          padding: EdgeInsets.all(10),
799
+          insetAnimCurve: Curves.easeInOut,
800
+          progress: 0.0,
801
+          maxProgress: 100.0,
802
+          progressTextStyle: TextStyle(
803
+              color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
804
+          messageTextStyle: TextStyle(
805
+              color: Colors.black,
806
+              fontSize: 15.0,
807
+              fontWeight: FontWeight.w600));
808
+      await loading.show();
809
+
810
+      final SharedPreferences prefs = await SharedPreferences.getInstance();
811
+      final session = prefs.getString('session');
812
+      ChangePassword_Post.connectToAPI(passwordController.text.toString(),
813
+              newPasswordController.text.toString(), session!)
814
+          .then((valueResult) async {
815
+        Map<String, dynamic> object = json.decode(valueResult);
816
+        if (object.containsKey("result").toString() == "true") {
817
+          String status = object['result']['status'].toString();
818
+          String message = object['result']['message'].toString();
819
+          if (status == "success") {
820
+            Fluttertoast.showToast(
821
+                msg: message + ", Please login again!",
822
+                toastLength: Toast.LENGTH_SHORT,
823
+                gravity: ToastGravity.CENTER,
824
+                timeInSecForIosWeb: 1,
825
+                textColor: Colors.white,
826
+                fontSize: 16.0);
827
+
828
+            passwordController.clear();
829
+            newPasswordController.clear();
830
+            retypeNewPasswordController.clear();
831
+
832
+            final session = await prefs.remove('session');
833
+            logDev.log(session.toString(), name: "SESSION KEHAPUS GAAAA?");
834
+            await loading.hide();
835
+            Navigator.of(context, rootNavigator: true).pop();
836
+            Navigator.pushReplacement(
837
+                context, MaterialPageRoute(builder: (context) => LoginView()));
838
+          } else if (status == "failed") {
839
+            Fluttertoast.showToast(
840
+                msg: message,
841
+                toastLength: Toast.LENGTH_SHORT,
842
+                gravity: ToastGravity.CENTER,
843
+                timeInSecForIosWeb: 1,
844
+                textColor: Colors.white,
845
+                fontSize: 16.0);
846
+            Navigator.of(context, rootNavigator: true).pop();
847
+            await loading.hide();
848
+          }
849
+        } else {
850
+          Fluttertoast.showToast(
851
+              msg: "Server Response Error",
852
+              toastLength: Toast.LENGTH_SHORT,
853
+              gravity: ToastGravity.CENTER,
854
+              timeInSecForIosWeb: 1,
855
+              textColor: Colors.white,
856
+              fontSize: 16.0);
857
+          await loading.hide();
858
+        }
859
+      });
860
+    },
861
+  );
862
+
863
+  Widget noButton = TextButton(
864
+    child: Text("No"),
259 865
     onPressed: () {
260 866
       Navigator.of(context, rootNavigator: true).pop();
261
-      Navigator.pushAndRemoveUntil(
262
-          context,
263
-          MaterialPageRoute(builder: (context) => LoginView()),
264
-          (route) => false);
867
+    },
868
+  );
869
+
870
+  // set up the AlertDialog
871
+  AlertDialog alert = AlertDialog(
872
+    title: Text("Employee Self Service"),
873
+    content: Text("Save New Password?"),
874
+    actions: [noButton, okButton],
875
+  );
876
+
877
+  // show the dialog
878
+  showDialog(
879
+    context: context,
880
+    builder: (BuildContext context) {
881
+      return alert;
882
+    },
883
+  );
884
+}
885
+
886
+//Validate Form Change Password
887
+bool validateFormSavePassword(BuildContext context) {
888
+  bool result = true;
889
+
890
+  if (passwordController.text.toString().isEmpty) {
891
+    Fluttertoast.showToast(
892
+        msg: "Old Password Required!",
893
+        toastLength: Toast.LENGTH_SHORT,
894
+        gravity: ToastGravity.CENTER,
895
+        timeInSecForIosWeb: 1,
896
+        textColor: Colors.white,
897
+        fontSize: 16.0);
898
+    result = false;
899
+  }
900
+
901
+  if (newPasswordController.text.toString().isEmpty) {
902
+    Fluttertoast.showToast(
903
+        msg: "New Password Required",
904
+        toastLength: Toast.LENGTH_SHORT,
905
+        gravity: ToastGravity.CENTER,
906
+        timeInSecForIosWeb: 1,
907
+        textColor: Colors.white,
908
+        fontSize: 16.0);
909
+    result = false;
910
+  }
911
+
912
+  if (retypeNewPasswordController.text.toString().isEmpty) {
913
+    Fluttertoast.showToast(
914
+        msg: "Retype New Password Required",
915
+        toastLength: Toast.LENGTH_SHORT,
916
+        gravity: ToastGravity.CENTER,
917
+        timeInSecForIosWeb: 1,
918
+        textColor: Colors.white,
919
+        fontSize: 16.0);
920
+    result = false;
921
+  }
922
+
923
+  return result;
924
+}
925
+
926
+//LOGOUT
927
+showAlertDialogLogout(BuildContext context) {
928
+  // set up the button
929
+  Widget okButton = TextButton(
930
+    child: Text("Yes"),
931
+    onPressed: () async {
932
+      ProgressDialog loading = ProgressDialog(context);
933
+      loading = ProgressDialog(context,
934
+          type: ProgressDialogType.normal,
935
+          isDismissible: false,
936
+          showLogs: true);
937
+      loading.style(
938
+          message: 'Please Wait .....',
939
+          borderRadius: 5,
940
+          backgroundColor: Colors.white,
941
+          progressWidget: CircularProgressIndicator(),
942
+          elevation: 10.0,
943
+          padding: EdgeInsets.all(10),
944
+          insetAnimCurve: Curves.easeInOut,
945
+          progress: 0.0,
946
+          maxProgress: 100.0,
947
+          progressTextStyle: TextStyle(
948
+              color: Colors.black, fontSize: 10.0, fontWeight: FontWeight.w400),
949
+          messageTextStyle: TextStyle(
950
+              color: Colors.black,
951
+              fontSize: 15.0,
952
+              fontWeight: FontWeight.w600));
953
+      await loading.show();
954
+
955
+      final SharedPreferences prefs = await SharedPreferences.getInstance();
956
+      final session = prefs.getString('session');
957
+
958
+      Logout_Post.connectToAPI(session!).then((valueResult) async {
959
+        Map<String, dynamic> object = json.decode(valueResult);
960
+        if (object.containsKey("result").toString() == "true") {
961
+          String status = object['result']['status'].toString();
962
+          if (status == "success") {
963
+            final session = await prefs.remove('session');
964
+            logDev.log(session.toString(), name: "SESSION KEHAPUS GA?");
965
+            Navigator.of(context, rootNavigator: true).pop();
966
+            await loading.hide();
967
+            Navigator.pushAndRemoveUntil(
968
+                context,
969
+                MaterialPageRoute(builder: (context) => LoginView()),
970
+                (route) => false);
971
+          } else if (status == "failed") {
972
+            String message = object['result']['message'].toString();
973
+            Fluttertoast.showToast(
974
+                msg: message,
975
+                toastLength: Toast.LENGTH_SHORT,
976
+                gravity: ToastGravity.CENTER,
977
+                timeInSecForIosWeb: 1,
978
+                textColor: Colors.white,
979
+                fontSize: 16.0);
980
+            await loading.hide();
981
+            Navigator.of(context, rootNavigator: true).pop();
982
+          }
983
+        } else {
984
+          Fluttertoast.showToast(
985
+              msg: "Server Response Error",
986
+              toastLength: Toast.LENGTH_SHORT,
987
+              gravity: ToastGravity.CENTER,
988
+              timeInSecForIosWeb: 1,
989
+              textColor: Colors.white,
990
+              fontSize: 16.0);
991
+          await loading.hide();
992
+          Navigator.of(context, rootNavigator: true).pop();
993
+        }
994
+      });
265 995
     },
266 996
   );
267 997
 
@@ -274,8 +1004,9 @@ showAlertDialog(BuildContext context) {
274 1004
 
275 1005
   // set up the AlertDialog
276 1006
   AlertDialog alert = AlertDialog(
277
-    title: Text("HRIS Self Service"),
278
-    content: Text("Are you sure you want to logout from this Application?"),
1007
+    title: Text("Employee Self Service"),
1008
+    //content: Text("Are you sure you want to logout from this Application?"),
1009
+    content: Text("Apakah Anda yakin ingin keluar dari aplikasi ini?"),
279 1010
     actions: [noButton, okButton],
280 1011
   );
281 1012
 

+ 46
- 0
lib/Screens/Splash/loginstatus_post.dart 查看文件

@@ -0,0 +1,46 @@
1
+import 'dart:convert';
2
+import 'dart:core';
3
+import 'package:http/http.dart' as http;
4
+import 'package:hris_selfservice_mobile/constants.dart';
5
+import 'package:shared_preferences/shared_preferences.dart';
6
+import 'dart:developer' as logDev;
7
+
8
+class LoginStatus_Post {
9
+  late String version;
10
+  late String device;
11
+  late String session;
12
+  late String notif_token;
13
+
14
+  LoginStatus_Post(
15
+      {required this.version,
16
+      required this.device,
17
+      required this.session,
18
+      required this.notif_token});
19
+
20
+  static Future<String> connectToAPI(
21
+      String version, String device, String session, String notif_token) async {
22
+    String URL = baseURL + "/api/v1/login_status";
23
+    print(URL);
24
+
25
+    var sendData = await http.post(Uri.parse(URL),
26
+        body: jsonEncode({
27
+          "data": [
28
+            {
29
+              "version": version,
30
+              "device": device,
31
+              "session": session,
32
+              "notif_token": notif_token
33
+            }
34
+          ]
35
+        }),
36
+        headers: {"Content-Type": "application/json", "Api-key": apiKey});
37
+
38
+    return sendData.body;
39
+
40
+
41
+    // var jsonObject = json.decode(sendData.body);
42
+    //developer.log(jsonObject.toString(), name: 'Log');
43
+    // return jsonObject;
44
+    // return LoginPostResult.createPostResult(jsonObject);
45
+  }
46
+}

+ 183
- 8
lib/Screens/Splash/splash_screen.dart 查看文件

@@ -1,10 +1,17 @@
1 1
 import 'dart:async';
2
-
2
+import 'dart:convert';
3 3
 import 'package:flutter/material.dart';
4
+import 'package:flutter/services.dart';
5
+import 'package:fluttertoast/fluttertoast.dart';
4 6
 import 'package:google_fonts/google_fonts.dart';
5 7
 import 'package:hris_selfservice_mobile/Screens/Login/login_screen.dart';
8
+import 'package:hris_selfservice_mobile/Screens/Splash/loginstatus_post.dart';
6 9
 import 'package:lottie/lottie.dart';
10
+import 'package:shared_preferences/shared_preferences.dart';
11
+import '../Home/home_screen.dart';
7 12
 import '../Splash/background.dart';
13
+import 'package:url_launcher/url_launcher.dart';
14
+import 'dart:developer' as logDev;
8 15
 
9 16
 class Splash extends StatefulWidget {
10 17
   const Splash({Key? key}) : super(key: key);
@@ -17,10 +24,7 @@ class _SplashState extends State<Splash> {
17 24
   @override
18 25
   void initState() {
19 26
     super.initState();
20
-    Timer(
21
-        Duration(seconds: 10),
22
-        () => Navigator.pushReplacement(
23
-            context, MaterialPageRoute(builder: (context) => LoginView())));
27
+    Timer(Duration(seconds: 10), () => loginStatus(context));
24 28
   }
25 29
 
26 30
   @override
@@ -66,15 +70,186 @@ class SplashScreen extends StatelessWidget {
66 70
               child: SizedBox(
67 71
                 width: 250,
68 72
                 height: 250,
69
-                child: LottieBuilder.asset('assets/animation/animation_1.json',
73
+                child: LottieBuilder.asset('assets/animation/animation_4.json',
70 74
                     repeat: true),
71 75
               ),
72 76
             ),
73
-            Text('Lottie Animation\nby Lottiefiles.com',
74
-                style: GoogleFonts.knewave(fontSize: 17, color: Colors.white))
77
+            Text('Employee Self Service',
78
+                style: GoogleFonts.knewave(fontSize: 22, color: Colors.white))
75 79
           ],
76 80
         ),
77 81
       ),
78 82
     ));
79 83
   }
80 84
 }
85
+
86
+Future<void> loginStatus(BuildContext context) async {
87
+  final SharedPreferences prefs = await SharedPreferences.getInstance();
88
+  String? version = prefs.getString('version');
89
+  String? device = prefs.getString('device');
90
+  String? session = prefs.getString('session');
91
+  String? notif_token = prefs.getString('notif_token');
92
+
93
+  if (session == null) {
94
+    session = "";
95
+    version = "";
96
+    device = "";
97
+    notif_token = "";
98
+  }
99
+
100
+  logDev.log(session, name: "SESSIONNYA");
101
+
102
+  LoginStatus_Post.connectToAPI(version!, device!, session, notif_token!)
103
+      .then((valueResult) async {
104
+    Map<String, dynamic> object = json.decode(valueResult);
105
+    logDev.log(valueResult, name: "LOGIN STATUS!");
106
+    if (object.containsKey("result").toString() == "true") {
107
+      String status = object['result']['status'].toString();
108
+      if (status == "success") {
109
+        Fluttertoast.showToast(
110
+            msg: "You are already logged in",
111
+            toastLength: Toast.LENGTH_SHORT,
112
+            gravity: ToastGravity.CENTER,
113
+            timeInSecForIosWeb: 1,
114
+            textColor: Colors.white,
115
+            fontSize: 16.0);
116
+        Navigator.pushReplacement(
117
+            context, MaterialPageRoute(builder: (context) => HomeView()));
118
+      } else if (status == "failed") {
119
+        String message = object['result']['message'].toString();
120
+        if (message == "Not Logged In") {
121
+          Fluttertoast.showToast(
122
+              msg: message,
123
+              toastLength: Toast.LENGTH_SHORT,
124
+              gravity: ToastGravity.CENTER,
125
+              timeInSecForIosWeb: 1,
126
+              textColor: Colors.white,
127
+              fontSize: 16.0);
128
+          Navigator.pushReplacement(
129
+              context, MaterialPageRoute(builder: (context) => LoginView()));
130
+        } else {
131
+          String title = object['result']['title'].toString();
132
+          String action = object['result']['action'].toString();
133
+          String block = object['result']['block'].toString();
134
+          if (block == "false") {
135
+            Widget okButton = TextButton(
136
+              child: Text(action),
137
+              onPressed: () {
138
+                _launchURL(Uri.parse("https://play.google.com/store/apps"));
139
+                SystemChannels.platform.invokeMethod('SystemNavigator.pop');
140
+              },
141
+            );
142
+
143
+            Widget noButton = TextButton(
144
+              child: Text("Later"),
145
+              onPressed: () {
146
+                if (session == ""){
147
+                  Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => LoginView()));
148
+                } else {
149
+                  Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => HomeView()));
150
+                }
151
+              },
152
+            );
153
+
154
+            // set up the AlertDialog
155
+            AlertDialog alert = AlertDialog(
156
+              title: Text("Employee Self Service"),
157
+              content: Text(title + "\n" + message),
158
+              actions: [noButton, okButton],
159
+            );
160
+
161
+            // show the dialog
162
+            showDialog(
163
+              context: context,
164
+              builder: (BuildContext context) {
165
+                return alert;
166
+              },
167
+            );
168
+          } else if (block == "true") {
169
+            Widget okButton = TextButton(
170
+              child: Text(action),
171
+              onPressed: () {
172
+                if (action == "update") {
173
+                  _launchURL(Uri.parse("https://play.google.com/store/apps"));
174
+                  SystemChannels.platform.invokeMethod('SystemNavigator.pop');
175
+                } else if (action == "close") {
176
+                  SystemChannels.platform.invokeMethod('SystemNavigator.pop');
177
+                }
178
+              },
179
+            );
180
+
181
+            // set up the AlertDialog
182
+            AlertDialog alert = AlertDialog(
183
+              title: Text("Employee Self Service"),
184
+              content: Text(title + "\n" + message),
185
+              actions: [okButton],
186
+            );
187
+
188
+            // show the dialog
189
+            showDialog(
190
+              context: context,
191
+              builder: (BuildContext context) {
192
+                return alert;
193
+              },
194
+            );
195
+          }
196
+        }
197
+      }
198
+    } else {
199
+      alertDialogFailedResponse(context);
200
+      /*Fluttertoast.showToast(
201
+          msg: "Server Response Error",
202
+          toastLength: Toast.LENGTH_SHORT,
203
+          gravity: ToastGravity.CENTER,
204
+          timeInSecForIosWeb: 1,
205
+          textColor: Colors.white,
206
+          fontSize: 16.0);*/
207
+    }
208
+  });
209
+}
210
+
211
+_launchURL(Uri url) async {
212
+  if (await canLaunchUrl(url)) {
213
+    await launchUrl(url);
214
+  } else {
215
+    throw 'Could not launch $url';
216
+  }
217
+}
218
+
219
+alertDialogFailedResponse(BuildContext context){
220
+  Widget okButton = TextButton(
221
+    child: Text("Refresh"),
222
+    onPressed: () {
223
+      Navigator.of(context, rootNavigator: true).pop();
224
+      Navigator.pushReplacement(context, MaterialPageRoute(
225
+          builder: (context) => SplashScreen()));
226
+    },
227
+  );
228
+
229
+  Widget noButton = TextButton(
230
+    child: Text("Back"),
231
+    onPressed: () {
232
+      Navigator.of(context, rootNavigator: true).pop();
233
+      Navigator.pop(context);
234
+
235
+    },
236
+  );
237
+
238
+  // set up the AlertDialog
239
+  AlertDialog alert = AlertDialog(
240
+    title: Text("Employee Self Service"),
241
+    content: Text("Server Response Error"),
242
+    actions: [
243
+      noButton,
244
+      okButton,
245
+    ],
246
+  );
247
+
248
+  // show the dialog
249
+  showDialog(
250
+    context: context,
251
+    builder: (BuildContext context) {
252
+      return alert;
253
+    },
254
+  );
255
+}

+ 9
- 1
lib/constants.dart 查看文件

@@ -3,4 +3,12 @@ import 'package:flutter/material.dart';
3 3
 const kPrimaryColor = Color(0xFF6F35A5);
4 4
 const kPrimaryLightColor = Color(0xFFF1E6FF);
5 5
 
6
-const double defaultPadding = 16.0;
6
+const double defaultPadding = 16.0;
7
+
8
+
9
+//String baseURL = "http://10.209.8.49:8090";
10
+//String baseURL = "https://bisops.globalservice.co.id";
11
+String baseURL = "https://urp.myapps.id";
12
+//String apiKey = "admin";
13
+//String apiKey = "G514p1k3y";
14
+String apiKey = "4pik3y";

+ 4
- 0
linux/flutter/generated_plugin_registrant.cc 查看文件

@@ -6,6 +6,10 @@
6 6
 
7 7
 #include "generated_plugin_registrant.h"
8 8
 
9
+#include <url_launcher_linux/url_launcher_plugin.h>
9 10
 
10 11
 void fl_register_plugins(FlPluginRegistry* registry) {
12
+  g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar =
13
+      fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin");
14
+  url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar);
11 15
 }

+ 1
- 0
linux/flutter/generated_plugins.cmake 查看文件

@@ -3,6 +3,7 @@
3 3
 #
4 4
 
5 5
 list(APPEND FLUTTER_PLUGIN_LIST
6
+  url_launcher_linux
6 7
 )
7 8
 
8 9
 list(APPEND FLUTTER_FFI_PLUGIN_LIST

+ 16
- 0
macos/Flutter/GeneratedPluginRegistrant.swift 查看文件

@@ -5,10 +5,26 @@
5 5
 import FlutterMacOS
6 6
 import Foundation
7 7
 
8
+import device_info_plus
9
+import firebase_core
10
+import firebase_messaging
11
+import flutter_local_notifications
12
+import flutter_udid
8 13
 import geolocator_apple
14
+import location
9 15
 import path_provider_macos
16
+import shared_preferences_macos
17
+import url_launcher_macos
10 18
 
11 19
 func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
20
+  DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
21
+  FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
22
+  FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin"))
23
+  FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin"))
24
+  FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin"))
12 25
   GeolocatorPlugin.register(with: registry.registrar(forPlugin: "GeolocatorPlugin"))
26
+  LocationPlugin.register(with: registry.registrar(forPlugin: "LocationPlugin"))
13 27
   PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
28
+  SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
29
+  UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
14 30
 }

+ 550
- 11
pubspec.lock 查看文件

@@ -1,6 +1,13 @@
1 1
 # Generated by pub
2 2
 # See https://dart.dev/tools/pub/glossary#lockfile
3 3
 packages:
4
+  _flutterfire_internals:
5
+    dependency: transitive
6
+    description:
7
+      name: _flutterfire_internals
8
+      url: "https://pub.dartlang.org"
9
+    source: hosted
10
+    version: "1.0.12"
4 11
   animated_splash_screen:
5 12
     dependency: "direct main"
6 13
     description:
@@ -8,6 +15,20 @@ packages:
8 15
       url: "https://pub.dartlang.org"
9 16
     source: hosted
10 17
     version: "1.3.0"
18
+  animated_stack_widget:
19
+    dependency: transitive
20
+    description:
21
+      name: animated_stack_widget
22
+      url: "https://pub.dartlang.org"
23
+    source: hosted
24
+    version: "0.0.4"
25
+  ansicolor:
26
+    dependency: transitive
27
+    description:
28
+      name: ansicolor
29
+      url: "https://pub.dartlang.org"
30
+    source: hosted
31
+    version: "1.1.1"
11 32
   archive:
12 33
     dependency: transitive
13 34
     description:
@@ -23,7 +44,7 @@ packages:
23 44
     source: hosted
24 45
     version: "2.3.1"
25 46
   async:
26
-    dependency: transitive
47
+    dependency: "direct main"
27 48
     description:
28 49
       name: async
29 50
       url: "https://pub.dartlang.org"
@@ -49,7 +70,7 @@ packages:
49 70
       name: checked_yaml
50 71
       url: "https://pub.dartlang.org"
51 72
     source: hosted
52
-    version: "2.0.1"
73
+    version: "2.0.2"
53 74
   cli_util:
54 75
     dependency: transitive
55 76
     description:
@@ -65,12 +86,19 @@ packages:
65 86
     source: hosted
66 87
     version: "1.1.1"
67 88
   collection:
68
-    dependency: transitive
89
+    dependency: "direct main"
69 90
     description:
70 91
       name: collection
71 92
       url: "https://pub.dartlang.org"
72 93
     source: hosted
73 94
     version: "1.16.0"
95
+  console_log_handler:
96
+    dependency: transitive
97
+    description:
98
+      name: console_log_handler
99
+      url: "https://pub.dartlang.org"
100
+    source: hosted
101
+    version: "1.1.6"
74 102
   convert:
75 103
     dependency: transitive
76 104
     description:
@@ -78,6 +106,13 @@ packages:
78 106
       url: "https://pub.dartlang.org"
79 107
     source: hosted
80 108
     version: "3.1.1"
109
+  cross_file:
110
+    dependency: transitive
111
+    description:
112
+      name: cross_file
113
+      url: "https://pub.dartlang.org"
114
+    source: hosted
115
+    version: "0.3.3+2"
81 116
   crypto:
82 117
     dependency: transitive
83 118
     description:
@@ -92,6 +127,41 @@ packages:
92 127
       url: "https://pub.dartlang.org"
93 128
     source: hosted
94 129
     version: "1.0.5"
130
+  dbus:
131
+    dependency: transitive
132
+    description:
133
+      name: dbus
134
+      url: "https://pub.dartlang.org"
135
+    source: hosted
136
+    version: "0.7.8"
137
+  device_imei:
138
+    dependency: "direct main"
139
+    description:
140
+      name: device_imei
141
+      url: "https://pub.dartlang.org"
142
+    source: hosted
143
+    version: "0.0.2"
144
+  device_info_plus:
145
+    dependency: "direct main"
146
+    description:
147
+      name: device_info_plus
148
+      url: "https://pub.dartlang.org"
149
+    source: hosted
150
+    version: "8.0.0"
151
+  device_info_plus_platform_interface:
152
+    dependency: transitive
153
+    description:
154
+      name: device_info_plus_platform_interface
155
+      url: "https://pub.dartlang.org"
156
+    source: hosted
157
+    version: "7.0.0"
158
+  dio:
159
+    dependency: "direct main"
160
+    description:
161
+      name: dio
162
+      url: "https://pub.dartlang.org"
163
+    source: hosted
164
+    version: "4.0.6"
95 165
   double_back_to_close:
96 166
     dependency: "direct main"
97 167
     description:
@@ -120,18 +190,130 @@ packages:
120 190
       url: "https://pub.dartlang.org"
121 191
     source: hosted
122 192
     version: "6.1.4"
193
+  file_picker:
194
+    dependency: "direct main"
195
+    description:
196
+      name: file_picker
197
+      url: "https://pub.dartlang.org"
198
+    source: hosted
199
+    version: "5.2.4"
200
+  firebase_core:
201
+    dependency: "direct main"
202
+    description:
203
+      name: firebase_core
204
+      url: "https://pub.dartlang.org"
205
+    source: hosted
206
+    version: "2.4.1"
207
+  firebase_core_platform_interface:
208
+    dependency: transitive
209
+    description:
210
+      name: firebase_core_platform_interface
211
+      url: "https://pub.dartlang.org"
212
+    source: hosted
213
+    version: "4.5.2"
214
+  firebase_core_web:
215
+    dependency: transitive
216
+    description:
217
+      name: firebase_core_web
218
+      url: "https://pub.dartlang.org"
219
+    source: hosted
220
+    version: "2.1.0"
221
+  firebase_messaging:
222
+    dependency: "direct main"
223
+    description:
224
+      name: firebase_messaging
225
+      url: "https://pub.dartlang.org"
226
+    source: hosted
227
+    version: "14.2.1"
228
+  firebase_messaging_platform_interface:
229
+    dependency: transitive
230
+    description:
231
+      name: firebase_messaging_platform_interface
232
+      url: "https://pub.dartlang.org"
233
+    source: hosted
234
+    version: "4.2.10"
235
+  firebase_messaging_web:
236
+    dependency: transitive
237
+    description:
238
+      name: firebase_messaging_web
239
+      url: "https://pub.dartlang.org"
240
+    source: hosted
241
+    version: "3.2.11"
123 242
   flutter:
124 243
     dependency: "direct main"
125 244
     description: flutter
126 245
     source: sdk
127 246
     version: "0.0.0"
247
+  flutter_image:
248
+    dependency: "direct main"
249
+    description:
250
+      name: flutter_image
251
+      url: "https://pub.dartlang.org"
252
+    source: hosted
253
+    version: "4.1.4"
128 254
   flutter_launcher_icons:
129
-    dependency: "direct dev"
255
+    dependency: "direct main"
130 256
     description:
131 257
       name: flutter_launcher_icons
132 258
       url: "https://pub.dartlang.org"
133 259
     source: hosted
134 260
     version: "0.11.0"
261
+  flutter_local_notifications:
262
+    dependency: "direct main"
263
+    description:
264
+      name: flutter_local_notifications
265
+      url: "https://pub.dartlang.org"
266
+    source: hosted
267
+    version: "13.0.0"
268
+  flutter_local_notifications_linux:
269
+    dependency: transitive
270
+    description:
271
+      name: flutter_local_notifications_linux
272
+      url: "https://pub.dartlang.org"
273
+    source: hosted
274
+    version: "3.0.0"
275
+  flutter_local_notifications_platform_interface:
276
+    dependency: transitive
277
+    description:
278
+      name: flutter_local_notifications_platform_interface
279
+      url: "https://pub.dartlang.org"
280
+    source: hosted
281
+    version: "6.0.0"
282
+  flutter_map:
283
+    dependency: "direct main"
284
+    description:
285
+      name: flutter_map
286
+      url: "https://pub.dartlang.org"
287
+    source: hosted
288
+    version: "3.1.0"
289
+  flutter_map_marker_cluster:
290
+    dependency: "direct main"
291
+    description:
292
+      name: flutter_map_marker_cluster
293
+      url: "https://pub.dartlang.org"
294
+    source: hosted
295
+    version: "1.0.1"
296
+  flutter_map_marker_popup:
297
+    dependency: transitive
298
+    description:
299
+      name: flutter_map_marker_popup
300
+      url: "https://pub.dartlang.org"
301
+    source: hosted
302
+    version: "4.0.0"
303
+  flutter_plugin_android_lifecycle:
304
+    dependency: transitive
305
+    description:
306
+      name: flutter_plugin_android_lifecycle
307
+      url: "https://pub.dartlang.org"
308
+    source: hosted
309
+    version: "2.0.7"
310
+  flutter_polyline_points:
311
+    dependency: "direct main"
312
+    description:
313
+      name: flutter_polyline_points
314
+      url: "https://pub.dartlang.org"
315
+    source: hosted
316
+    version: "1.0.0"
135 317
   flutter_staggered_grid_view:
136 318
     dependency: "direct main"
137 319
     description:
@@ -151,6 +333,13 @@ packages:
151 333
     description: flutter
152 334
     source: sdk
153 335
     version: "0.0.0"
336
+  flutter_udid:
337
+    dependency: "direct main"
338
+    description:
339
+      name: flutter_udid
340
+      url: "https://pub.dartlang.org"
341
+    source: hosted
342
+    version: "2.0.1"
154 343
   flutter_web_plugins:
155 344
     dependency: transitive
156 345
     description: flutter
@@ -162,7 +351,28 @@ packages:
162 351
       name: fluttertoast
163 352
       url: "https://pub.dartlang.org"
164 353
     source: hosted
165
-    version: "8.1.1"
354
+    version: "8.1.2"
355
+  geocoder:
356
+    dependency: "direct main"
357
+    description:
358
+      name: geocoder
359
+      url: "https://pub.dartlang.org"
360
+    source: hosted
361
+    version: "0.2.1"
362
+  geocoding:
363
+    dependency: "direct main"
364
+    description:
365
+      name: geocoding
366
+      url: "https://pub.dartlang.org"
367
+    source: hosted
368
+    version: "2.0.5"
369
+  geocoding_platform_interface:
370
+    dependency: transitive
371
+    description:
372
+      name: geocoding_platform_interface
373
+      url: "https://pub.dartlang.org"
374
+    source: hosted
375
+    version: "2.0.1"
166 376
   geolocator:
167 377
     dependency: "direct main"
168 378
     description:
@@ -205,6 +415,13 @@ packages:
205 415
       url: "https://pub.dartlang.org"
206 416
     source: hosted
207 417
     version: "0.1.1"
418
+  get_it:
419
+    dependency: "direct main"
420
+    description:
421
+      name: get_it
422
+      url: "https://pub.dartlang.org"
423
+    source: hosted
424
+    version: "7.2.0"
208 425
   google_fonts:
209 426
     dependency: "direct main"
210 427
     description:
@@ -213,7 +430,7 @@ packages:
213 430
     source: hosted
214 431
     version: "3.0.1"
215 432
   http:
216
-    dependency: transitive
433
+    dependency: "direct main"
217 434
     description:
218 435
       name: http
219 436
       url: "https://pub.dartlang.org"
@@ -232,7 +449,70 @@ packages:
232 449
       name: image
233 450
       url: "https://pub.dartlang.org"
234 451
     source: hosted
235
-    version: "3.2.2"
452
+    version: "3.3.0"
453
+  image_cropper:
454
+    dependency: "direct main"
455
+    description:
456
+      name: image_cropper
457
+      url: "https://pub.dartlang.org"
458
+    source: hosted
459
+    version: "3.0.1"
460
+  image_cropper_for_web:
461
+    dependency: transitive
462
+    description:
463
+      name: image_cropper_for_web
464
+      url: "https://pub.dartlang.org"
465
+    source: hosted
466
+    version: "1.0.3"
467
+  image_cropper_platform_interface:
468
+    dependency: transitive
469
+    description:
470
+      name: image_cropper_platform_interface
471
+      url: "https://pub.dartlang.org"
472
+    source: hosted
473
+    version: "3.0.3"
474
+  image_picker:
475
+    dependency: "direct main"
476
+    description:
477
+      name: image_picker
478
+      url: "https://pub.dartlang.org"
479
+    source: hosted
480
+    version: "0.8.6"
481
+  image_picker_android:
482
+    dependency: transitive
483
+    description:
484
+      name: image_picker_android
485
+      url: "https://pub.dartlang.org"
486
+    source: hosted
487
+    version: "0.8.5+4"
488
+  image_picker_for_web:
489
+    dependency: transitive
490
+    description:
491
+      name: image_picker_for_web
492
+      url: "https://pub.dartlang.org"
493
+    source: hosted
494
+    version: "2.1.10"
495
+  image_picker_ios:
496
+    dependency: transitive
497
+    description:
498
+      name: image_picker_ios
499
+      url: "https://pub.dartlang.org"
500
+    source: hosted
501
+    version: "0.8.6+5"
502
+  image_picker_platform_interface:
503
+    dependency: transitive
504
+    description:
505
+      name: image_picker_platform_interface
506
+      url: "https://pub.dartlang.org"
507
+    source: hosted
508
+    version: "2.6.2"
509
+  intl:
510
+    dependency: "direct main"
511
+    description:
512
+      name: intl
513
+      url: "https://pub.dartlang.org"
514
+    source: hosted
515
+    version: "0.17.0"
236 516
   js:
237 517
     dependency: transitive
238 518
     description:
@@ -247,13 +527,62 @@ packages:
247 527
       url: "https://pub.dartlang.org"
248 528
     source: hosted
249 529
     version: "4.7.0"
530
+  latlong:
531
+    dependency: "direct main"
532
+    description:
533
+      name: latlong
534
+      url: "https://pub.dartlang.org"
535
+    source: hosted
536
+    version: "0.6.1"
537
+  latlong2:
538
+    dependency: transitive
539
+    description:
540
+      name: latlong2
541
+      url: "https://pub.dartlang.org"
542
+    source: hosted
543
+    version: "0.8.1"
544
+  lists:
545
+    dependency: transitive
546
+    description:
547
+      name: lists
548
+      url: "https://pub.dartlang.org"
549
+    source: hosted
550
+    version: "1.0.1"
551
+  location:
552
+    dependency: "direct main"
553
+    description:
554
+      name: location
555
+      url: "https://pub.dartlang.org"
556
+    source: hosted
557
+    version: "4.4.0"
558
+  location_platform_interface:
559
+    dependency: transitive
560
+    description:
561
+      name: location_platform_interface
562
+      url: "https://pub.dartlang.org"
563
+    source: hosted
564
+    version: "2.3.0"
565
+  location_web:
566
+    dependency: transitive
567
+    description:
568
+      name: location_web
569
+      url: "https://pub.dartlang.org"
570
+    source: hosted
571
+    version: "3.1.1"
572
+  logging:
573
+    dependency: transitive
574
+    description:
575
+      name: logging
576
+      url: "https://pub.dartlang.org"
577
+    source: hosted
578
+    version: "0.11.4"
250 579
   lottie:
251 580
     dependency: "direct main"
252 581
     description:
253 582
       name: lottie
254 583
       url: "https://pub.dartlang.org"
255 584
     source: hosted
256
-    version: "2.0.0"
585
+    version: "2.1.0"
257 586
   matcher:
258 587
     dependency: transitive
259 588
     description:
@@ -269,12 +598,26 @@ packages:
269 598
     source: hosted
270 599
     version: "0.1.5"
271 600
   meta:
272
-    dependency: transitive
601
+    dependency: "direct main"
273 602
     description:
274 603
       name: meta
275 604
       url: "https://pub.dartlang.org"
276 605
     source: hosted
277 606
     version: "1.8.0"
607
+  mgrs_dart:
608
+    dependency: transitive
609
+    description:
610
+      name: mgrs_dart
611
+      url: "https://pub.dartlang.org"
612
+    source: hosted
613
+    version: "2.0.0"
614
+  nested:
615
+    dependency: transitive
616
+    description:
617
+      name: nested
618
+      url: "https://pub.dartlang.org"
619
+    source: hosted
620
+    version: "1.0.0"
278 621
   page_transition:
279 622
     dependency: transitive
280 623
     description:
@@ -380,6 +723,27 @@ packages:
380 723
       url: "https://pub.dartlang.org"
381 724
     source: hosted
382 725
     version: "3.6.2"
726
+  polylabel:
727
+    dependency: transitive
728
+    description:
729
+      name: polylabel
730
+      url: "https://pub.dartlang.org"
731
+    source: hosted
732
+    version: "1.0.1"
733
+  positioned_tap_detector:
734
+    dependency: "direct main"
735
+    description:
736
+      name: positioned_tap_detector
737
+      url: "https://pub.dartlang.org"
738
+    source: hosted
739
+    version: "1.0.3"
740
+  positioned_tap_detector_2:
741
+    dependency: transitive
742
+    description:
743
+      name: positioned_tap_detector_2
744
+      url: "https://pub.dartlang.org"
745
+    source: hosted
746
+    version: "1.0.4"
383 747
   process:
384 748
     dependency: transitive
385 749
     description:
@@ -387,6 +751,83 @@ packages:
387 751
       url: "https://pub.dartlang.org"
388 752
     source: hosted
389 753
     version: "4.2.4"
754
+  progress_dialog_null_safe:
755
+    dependency: "direct main"
756
+    description:
757
+      name: progress_dialog_null_safe
758
+      url: "https://pub.dartlang.org"
759
+    source: hosted
760
+    version: "1.0.7"
761
+  proj4dart:
762
+    dependency: transitive
763
+    description:
764
+      name: proj4dart
765
+      url: "https://pub.dartlang.org"
766
+    source: hosted
767
+    version: "2.1.0"
768
+  provider:
769
+    dependency: transitive
770
+    description:
771
+      name: provider
772
+      url: "https://pub.dartlang.org"
773
+    source: hosted
774
+    version: "6.0.5"
775
+  shared_preferences:
776
+    dependency: "direct main"
777
+    description:
778
+      name: shared_preferences
779
+      url: "https://pub.dartlang.org"
780
+    source: hosted
781
+    version: "2.0.15"
782
+  shared_preferences_android:
783
+    dependency: transitive
784
+    description:
785
+      name: shared_preferences_android
786
+      url: "https://pub.dartlang.org"
787
+    source: hosted
788
+    version: "2.0.14"
789
+  shared_preferences_ios:
790
+    dependency: transitive
791
+    description:
792
+      name: shared_preferences_ios
793
+      url: "https://pub.dartlang.org"
794
+    source: hosted
795
+    version: "2.1.1"
796
+  shared_preferences_linux:
797
+    dependency: transitive
798
+    description:
799
+      name: shared_preferences_linux
800
+      url: "https://pub.dartlang.org"
801
+    source: hosted
802
+    version: "2.1.2"
803
+  shared_preferences_macos:
804
+    dependency: transitive
805
+    description:
806
+      name: shared_preferences_macos
807
+      url: "https://pub.dartlang.org"
808
+    source: hosted
809
+    version: "2.0.4"
810
+  shared_preferences_platform_interface:
811
+    dependency: transitive
812
+    description:
813
+      name: shared_preferences_platform_interface
814
+      url: "https://pub.dartlang.org"
815
+    source: hosted
816
+    version: "2.1.0"
817
+  shared_preferences_web:
818
+    dependency: transitive
819
+    description:
820
+      name: shared_preferences_web
821
+      url: "https://pub.dartlang.org"
822
+    source: hosted
823
+    version: "2.0.4"
824
+  shared_preferences_windows:
825
+    dependency: transitive
826
+    description:
827
+      name: shared_preferences_windows
828
+      url: "https://pub.dartlang.org"
829
+    source: hosted
830
+    version: "2.1.2"
390 831
   sky_engine:
391 832
     dependency: transitive
392 833
     description: flutter
@@ -434,6 +875,27 @@ packages:
434 875
       url: "https://pub.dartlang.org"
435 876
     source: hosted
436 877
     version: "0.4.12"
878
+  timezone:
879
+    dependency: transitive
880
+    description:
881
+      name: timezone
882
+      url: "https://pub.dartlang.org"
883
+    source: hosted
884
+    version: "0.9.1"
885
+  transparent_image:
886
+    dependency: "direct main"
887
+    description:
888
+      name: transparent_image
889
+      url: "https://pub.dartlang.org"
890
+    source: hosted
891
+    version: "2.0.0"
892
+  tuple:
893
+    dependency: "direct main"
894
+    description:
895
+      name: tuple
896
+      url: "https://pub.dartlang.org"
897
+    source: hosted
898
+    version: "2.0.1"
437 899
   typed_data:
438 900
     dependency: transitive
439 901
     description:
@@ -441,8 +903,78 @@ packages:
441 903
       url: "https://pub.dartlang.org"
442 904
     source: hosted
443 905
     version: "1.3.1"
444
-  vector_math:
906
+  unicode:
445 907
     dependency: transitive
908
+    description:
909
+      name: unicode
910
+      url: "https://pub.dartlang.org"
911
+    source: hosted
912
+    version: "0.3.1"
913
+  url_launcher:
914
+    dependency: "direct main"
915
+    description:
916
+      name: url_launcher
917
+      url: "https://pub.dartlang.org"
918
+    source: hosted
919
+    version: "6.1.7"
920
+  url_launcher_android:
921
+    dependency: transitive
922
+    description:
923
+      name: url_launcher_android
924
+      url: "https://pub.dartlang.org"
925
+    source: hosted
926
+    version: "6.0.22"
927
+  url_launcher_ios:
928
+    dependency: transitive
929
+    description:
930
+      name: url_launcher_ios
931
+      url: "https://pub.dartlang.org"
932
+    source: hosted
933
+    version: "6.0.17"
934
+  url_launcher_linux:
935
+    dependency: transitive
936
+    description:
937
+      name: url_launcher_linux
938
+      url: "https://pub.dartlang.org"
939
+    source: hosted
940
+    version: "3.0.1"
941
+  url_launcher_macos:
942
+    dependency: transitive
943
+    description:
944
+      name: url_launcher_macos
945
+      url: "https://pub.dartlang.org"
946
+    source: hosted
947
+    version: "3.0.1"
948
+  url_launcher_platform_interface:
949
+    dependency: transitive
950
+    description:
951
+      name: url_launcher_platform_interface
952
+      url: "https://pub.dartlang.org"
953
+    source: hosted
954
+    version: "2.1.1"
955
+  url_launcher_web:
956
+    dependency: transitive
957
+    description:
958
+      name: url_launcher_web
959
+      url: "https://pub.dartlang.org"
960
+    source: hosted
961
+    version: "2.0.13"
962
+  url_launcher_windows:
963
+    dependency: transitive
964
+    description:
965
+      name: url_launcher_windows
966
+      url: "https://pub.dartlang.org"
967
+    source: hosted
968
+    version: "3.0.1"
969
+  validate:
970
+    dependency: transitive
971
+    description:
972
+      name: validate
973
+      url: "https://pub.dartlang.org"
974
+    source: hosted
975
+    version: "1.7.0"
976
+  vector_math:
977
+    dependency: "direct main"
446 978
     description:
447 979
       name: vector_math
448 980
       url: "https://pub.dartlang.org"
@@ -454,7 +986,14 @@ packages:
454 986
       name: win32
455 987
       url: "https://pub.dartlang.org"
456 988
     source: hosted
457
-    version: "3.1.1"
989
+    version: "3.1.3"
990
+  wkt_parser:
991
+    dependency: transitive
992
+    description:
993
+      name: wkt_parser
994
+      url: "https://pub.dartlang.org"
995
+    source: hosted
996
+    version: "2.0.0"
458 997
   xdg_directories:
459 998
     dependency: transitive
460 999
     description:

+ 53
- 4
pubspec.yaml 查看文件

@@ -33,7 +33,6 @@ dependencies:
33 33
     sdk: flutter
34 34
   google_fonts: ^3.0.1
35 35
 
36
-
37 36
   # The following adds the Cupertino Icons font to your application.
38 37
   # Use with the CupertinoIcons class for iOS style icons.
39 38
   cupertino_icons: ^1.0.2
@@ -42,19 +41,69 @@ dependencies:
42 41
   double_back_to_close: ^2.0.0
43 42
   animated_splash_screen: ^1.3.0
44 43
   lottie: ^2.0.0
45
-  geolocator: ^9.0.2
46 44
   fluttertoast: ^8.1.1
45
+  #google_maps_flutter: ^2.2.1
46
+  http: ^0.13.5
47
+  intl: ^0.17.0
48
+  dio: ^4.0.6
49
+  get_it: ^7.2.0
50
+  firebase_messaging: ^14.1.3
51
+  firebase_core: ^2.4.0
52
+  flutter_local_notifications: ^13.0.0
53
+  shared_preferences: ^2.0.15
54
+  # device_information: ^0.0.4
55
+  device_imei: ^0.0.2
56
+  device_info_plus: ^8.0.0
57
+  flutter_udid: ^2.0.1
58
+  image_picker: ^0.8.6
59
+  image_cropper: ^3.0.1
60
+  url_launcher: ^6.1.7
61
+  #progress_dialog: ^1.2.4
62
+  progress_dialog_null_safe: ^1.0.4
63
+  #mapbox_gl: ^0.16.0
64
+  file_picker: ^5.2.4
65
+  #device_id: ^0.2.0
66
+  flutter_launcher_icons: ^0.11.0
67
+  location: ^4.4.0
68
+  latlong: ^0.6.1
69
+  flutter_map: ^3.1.0
70
+  geolocator: ^9.0.2
71
+  geocoding: ^2.0.5
72
+  geocoder: ^0.2.1
73
+  tuple: ^2.0.1
74
+  positioned_tap_detector: ^1.0.3
75
+  transparent_image: ^2.0.0
76
+  async: ^2.9.0
77
+  flutter_image: ^4.1.4
78
+  vector_math: ^2.1.2
79
+  meta: ^1.1.0
80
+  collection: ^1.16.0
81
+  flutter_map_marker_cluster: ^1.0.1
82
+  flutter_polyline_points: ^1.0.0
83
+
47 84
 
48 85
 dev_dependencies:
49 86
   flutter_test:
50 87
     sdk: flutter
51 88
 
52
-  flutter_launcher_icons: ^0.11.0
53 89
 
54 90
 flutter_icons:
55 91
   android: true
56 92
   ios: true
57
-  image_path: "assets/images/logo.png"
93
+  image_path: "assets/images/ic_logo.png"
94
+  min_sdk_android: 21 # android min sdk min:16, default 21
95
+  web:
96
+    generate: true
97
+    image_path: "assets/images/ic_logo.png"
98
+    background_color: "#hexcode"
99
+    theme_color: "#hexcode"
100
+  windows:
101
+    generate: true
102
+    image_path: "assets/images/ic_logo.png"
103
+    icon_size: 48 # min:48, max:256, default: 48
104
+  macos:
105
+    generate: true
106
+    image_path: "assets/images/ic_logo.png"
58 107
 
59 108
   # The "flutter_lints" package below contains a set of recommended lints to
60 109
   # encourage good coding practices. The lint set provided by the package is

+ 3
- 0
windows/flutter/generated_plugin_registrant.cc 查看文件

@@ -7,8 +7,11 @@
7 7
 #include "generated_plugin_registrant.h"
8 8
 
9 9
 #include <geolocator_windows/geolocator_windows.h>
10
+#include <url_launcher_windows/url_launcher_windows.h>
10 11
 
11 12
 void RegisterPlugins(flutter::PluginRegistry* registry) {
12 13
   GeolocatorWindowsRegisterWithRegistrar(
13 14
       registry->GetRegistrarForPlugin("GeolocatorWindows"));
15
+  UrlLauncherWindowsRegisterWithRegistrar(
16
+      registry->GetRegistrarForPlugin("UrlLauncherWindows"));
14 17
 }

+ 1
- 0
windows/flutter/generated_plugins.cmake 查看文件

@@ -4,6 +4,7 @@
4 4
 
5 5
 list(APPEND FLUTTER_PLUGIN_LIST
6 6
   geolocator_windows
7
+  url_launcher_windows
7 8
 )
8 9
 
9 10
 list(APPEND FLUTTER_FFI_PLUGIN_LIST

Loading…
取消
儲存