add swipe and forget password functionality ready for initial test

WaseemAbbasi22 1 year ago
parent ee6264f4b4
commit fd6b5dc83a

@ -1,4 +1,5 @@
storePassword=Cloud@AtomsSA
keyPassword=Cloud@AtomsSA
keyAlias=playstore
storeFile=/Users/sikandersaleem/StudioProjects/cloudsolutions-atoms/android/AtomsSA-playStore.jks
#storeFile=/Users/sikandersaleem/StudioProjects/cloudsolutions-atoms/android/AtomsSA-playStore.jks
storeFile=/Users/waseem/CsProjects/android/AtomsSA-playStore.jks

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

@ -0,0 +1,12 @@
<svg width="40" height="40" viewBox="0 0 40 40" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_3315_4264)">
<path d="M33.7512 39.2845L30.7402 37.2921C34.1004 32.1687 35.893 26.1529 35.893 20C35.893 13.8471 34.1004 7.8313 30.7402 2.70797L33.7512 0.715515C37.4393 6.45029 39.4303 13.1362 39.4889 19.9824V20.0186C39.4303 26.8645 37.4393 33.5501 33.7512 39.2845Z" fill="#3B3D4A" stroke="#3B3D4A"/>
<path d="M26.594 34.9749L23.6074 32.9463C26.1938 29.1382 27.5786 24.6234 27.5786 19.9995C27.5786 15.3756 26.1938 10.8608 23.6074 7.05269L26.594 5.02405C29.5196 9.45119 31.1108 14.6463 31.1732 19.9752V20.0238C31.1109 25.3527 29.5197 30.5478 26.594 34.9749Z" fill="#3B3D4A" stroke="#3B3D4A"/>
<path d="M20.1618 30.5113L4.30923 18.1512C4.17465 18.9366 4.10643 19.7322 4.1053 20.5294C4.21082 22.3475 4.75606 24.1113 5.6929 25.6651L2.67371 27.6441C1.36309 25.4998 0.618012 23.0498 0.509998 20.5294C0.498918 18.4074 0.883985 16.3024 1.64487 14.3256L2.56256 12.1904L18.667 24.7469C19.1283 23.2202 19.3506 21.6296 19.3257 20.0331C19.2579 16.9657 18.291 13.9882 16.5481 11.4801L19.496 9.39459C21.6466 12.4937 22.8386 16.172 22.9199 19.9607C22.9601 22.8932 22.3404 25.7964 21.108 28.4495L20.1618 30.5113Z" fill="#3B3D4A" stroke="#3B3D4A"/>
</g>
<defs>
<clipPath id="clip0_3315_4264">
<rect width="40" height="40" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -0,0 +1,11 @@
<svg width="82" height="82" viewBox="0 0 82 82" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M62.855 20.7976C55.0013 4.69411 33.6267 -0.701705 18.8103 9.36498C17.6396 10.1603 17.3354 11.754 18.1308 12.9246C18.9261 14.0952 20.5198 14.3994 21.6904 13.6041C33.9953 5.24389 51.7999 9.8215 58.2486 23.0442C58.869 24.3162 60.4031 24.8445 61.6751 24.2241C62.9471 23.6037 63.4754 22.0697 62.855 20.7976Z" fill="#54C166"/>
<path d="M35.8615 17.9308C34.4463 17.9308 33.299 19.0781 33.299 20.4933C33.299 21.9086 34.4463 23.0558 35.8615 23.0558C41.8738 23.0558 46.9587 28.2109 46.9587 34.8364C46.9587 36.2516 48.106 37.3989 49.5212 37.3989C50.9365 37.3989 52.0837 36.2516 52.0837 34.8364C52.0837 25.619 44.9371 17.9308 35.8615 17.9308Z" fill="#54C166"/>
<path d="M13.4347 23.1255C14.0502 21.8511 13.516 20.3191 12.2417 19.7036C10.9673 19.0881 9.43523 19.6223 8.81975 20.8967C6.99799 24.6687 5.97949 28.8838 5.97949 33.3255V48.5317C5.97949 58.4772 11.0762 67.2373 18.8103 72.492C19.9809 73.2873 21.5746 72.9831 22.3699 71.8125C23.1652 70.6419 22.861 69.0482 21.6904 68.2528C15.2692 63.8901 11.1045 56.672 11.1045 48.5317V33.3255C11.1045 29.6755 11.9399 26.2206 13.4347 23.1255Z" fill="#54C166"/>
<path d="M25.8509 29.7456C26.4343 28.4562 25.8619 26.938 24.5725 26.3547C23.2831 25.7713 21.7649 26.3437 21.1816 27.6331C20.1904 29.8241 19.6392 32.2679 19.6392 34.8364V47.1305C19.6392 56.3479 26.7857 64.0361 35.8615 64.0361C36.5507 64.0361 37.2321 63.9913 37.9024 63.9033C39.3056 63.7191 40.2938 62.4323 40.1097 61.0291C39.9255 59.6259 38.6386 58.6377 37.2355 58.8219C36.7871 58.8807 36.3285 58.9111 35.8615 58.9111C29.8491 58.9111 24.7642 53.756 24.7642 47.1305V34.8364C24.7642 33.0052 25.1564 31.2808 25.8509 29.7456Z" fill="#54C166"/>
<path d="M65.7435 35.2916C65.7435 33.8764 64.5962 32.7291 63.181 32.7291C61.7657 32.7291 60.6185 33.8764 60.6185 35.2916V39.2759C60.6185 40.6912 61.7657 41.8384 63.181 41.8384C64.5962 41.8384 65.7435 40.6912 65.7435 39.2759V35.2916Z" fill="#54C166"/>
<path d="M38.424 35.8609C38.424 34.4457 37.2767 33.2984 35.8615 33.2984C34.4463 33.2984 33.299 34.4457 33.299 35.8609V46.106C33.299 47.5212 34.4463 48.6685 35.8615 48.6685C37.2767 48.6685 38.424 47.5212 38.424 46.106V35.8609Z" fill="#54C166"/>
<path d="M41.4787 77.1333C42.8673 76.86 43.7714 75.5127 43.4982 74.1242C43.2249 72.7356 41.8777 71.8314 40.4891 72.1047C37.8559 72.6229 35.1017 72.7236 32.3125 72.3348C30.9108 72.1394 29.6161 73.1173 29.4207 74.5189C29.2253 75.9206 30.2032 77.2153 31.6049 77.4107C34.9745 77.8804 38.3024 77.7584 41.4787 77.1333Z" fill="#54C166"/>
<path d="M65.8112 60.5701C66.9947 59.794 67.325 58.2055 66.5489 57.0221C65.7728 55.8386 64.1843 55.5083 63.0008 56.2844C60.5195 57.9116 58.8881 59.9815 57.8293 61.6633C57.3764 61.3016 56.8771 60.9661 56.3573 60.7166C55.0814 60.1041 53.5507 60.642 52.9383 61.9178C52.3258 63.1937 52.8636 64.7244 54.1395 65.3369C54.3092 65.4183 54.6578 65.6561 55.0755 66.0616C55.3759 66.3532 55.6295 66.6513 55.8089 66.9002C55.8478 67.0018 55.8948 67.108 55.9518 67.2149C56.0821 67.4592 56.3952 67.959 57.0262 68.3006C57.7671 68.7016 58.5485 68.6753 59.1444 68.4634C59.6447 68.2855 59.9676 67.9997 60.1091 67.8635C60.2719 67.7069 60.3881 67.5572 60.457 67.4628C60.5935 67.2758 60.7003 67.0881 60.7655 66.9698C60.8682 66.7835 60.9917 66.5382 61.105 66.313L61.1943 66.1362C61.3455 65.8376 61.5162 65.5073 61.7173 65.1495C62.5272 63.7082 63.7899 61.8956 65.8112 60.5701Z" fill="#54C166"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M59.792 45.2702C50.8289 45.2702 43.5628 52.5363 43.5628 61.4994C43.5628 70.4625 50.8289 77.7286 59.792 77.7286C68.7551 77.7286 76.0212 70.4625 76.0212 61.4994C76.0212 52.5363 68.7551 45.2702 59.792 45.2702ZM48.6878 61.4994C48.6878 55.3667 53.6593 50.3952 59.792 50.3952C65.9247 50.3952 70.8962 55.3667 70.8962 61.4994C70.8962 67.6321 65.9247 72.6036 59.792 72.6036C53.6593 72.6036 48.6878 67.6321 48.6878 61.4994Z" fill="#54C166"/>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

@ -0,0 +1,8 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.34246 3.65546C15.1272 -0.274716 23.4724 1.83188 26.5387 8.11895C26.7808 8.61535 26.5746 9.21401 26.0782 9.45611C25.5818 9.69821 24.9832 9.49206 24.7411 8.99567C22.2231 3.83284 15.271 2.04549 10.4664 5.30977C10.0096 5.62014 9.38765 5.50141 9.07728 5.04459C8.76691 4.58776 8.88564 3.96583 9.34246 3.65546Z" fill="#3DA5E5"/>
<path d="M6.77731 7.69205C7.27463 7.93225 7.48307 8.53012 7.24287 9.02744C6.6592 10.2359 6.33301 11.5849 6.33301 13.01V18.947C6.33301 22.1254 7.95917 24.9438 10.4664 26.6472C10.9232 26.9576 11.042 27.5795 10.7316 28.0364C10.4212 28.4932 9.79928 28.6119 9.34246 28.3015C6.32289 26.25 4.33301 22.8298 4.33301 18.947V13.01C4.33301 11.2759 4.73065 9.63029 5.44193 8.15762C5.68212 7.6603 6.27999 7.45186 6.77731 7.69205Z" fill="#3DA5E5"/>
<path d="M26.6663 12.7777C27.2186 12.7777 27.6663 13.2254 27.6663 13.7777V18.947C27.6663 25.835 21.207 31.1789 14.3379 30.2219C13.7909 30.1457 13.4092 29.6404 13.4854 29.0934C13.5616 28.5464 14.0669 28.1648 14.6139 28.241C20.3494 29.0401 25.6663 24.5519 25.6663 18.947V13.7777C25.6663 13.2254 26.1141 12.7777 26.6663 12.7777Z" fill="#3DA5E5"/>
<path d="M14.9997 7.99974C14.9997 7.44745 15.4474 6.99974 15.9997 6.99974C19.5429 6.99974 22.333 10.0012 22.333 13.5997C22.333 14.152 21.8853 14.5997 21.333 14.5997C20.7807 14.5997 20.333 14.152 20.333 13.5997C20.333 11.0127 18.3475 8.99973 15.9997 8.99973C15.4474 8.99973 14.9997 8.55202 14.9997 7.99974Z" fill="#3DA5E5"/>
<path d="M11.5918 10.2886C12.095 10.5163 12.3183 11.1088 12.0907 11.6119C11.8195 12.2114 11.6663 12.8847 11.6663 13.5997V18.3997C11.6663 20.9868 13.6519 22.9997 15.9997 22.9997C18.3475 22.9997 20.333 20.9868 20.333 18.3997C20.333 17.8474 20.7807 17.3997 21.333 17.3997C21.8853 17.3997 22.333 17.8474 22.333 18.3997C22.333 21.9983 19.5429 24.9997 15.9997 24.9997C12.4565 24.9997 9.66634 21.9983 9.66634 18.3997V13.5997C9.66634 12.597 9.8815 11.6429 10.2685 10.7875C10.4961 10.2844 11.0886 10.061 11.5918 10.2886Z" fill="#3DA5E5"/>
<path d="M16.9997 13.9997C16.9997 13.4475 16.552 12.9997 15.9997 12.9997C15.4474 12.9997 14.9997 13.4475 14.9997 13.9997V17.9997C14.9997 18.552 15.4474 18.9997 15.9997 18.9997C16.552 18.9997 16.9997 18.552 16.9997 17.9997V13.9997Z" fill="#3DA5E5"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@ -0,0 +1,14 @@
<svg width="248" height="248" viewBox="0 0 248 248" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="124" cy="124" r="124" fill="black" fill-opacity="0.02"/>
<circle cx="124" cy="124" r="107" fill="black" fill-opacity="0.02"/>
<circle cx="124" cy="124" r="87" fill="white"/>
<path d="M145.855 103.798C138.001 87.6941 116.627 82.2983 101.81 92.365C100.64 93.1603 100.335 94.754 101.131 95.9246C101.926 97.0952 103.52 97.3994 104.69 96.6041C116.995 88.2439 134.8 92.8215 141.249 106.044C141.869 107.316 143.403 107.844 144.675 107.224C145.947 106.604 146.475 105.07 145.855 103.798Z" fill="#54C166"/>
<path d="M118.861 100.931C117.446 100.931 116.299 102.078 116.299 103.493C116.299 104.909 117.446 106.056 118.861 106.056C124.874 106.056 129.959 111.211 129.959 117.836C129.959 119.252 131.106 120.399 132.521 120.399C133.936 120.399 135.084 119.252 135.084 117.836C135.084 108.619 127.937 100.931 118.861 100.931Z" fill="#54C166"/>
<path d="M96.4347 106.126C97.0502 104.851 96.516 103.319 95.2417 102.704C93.9673 102.088 92.4352 102.622 91.8198 103.897C89.998 107.669 88.9795 111.884 88.9795 116.325V131.532C88.9795 141.477 94.0762 150.237 101.81 155.492C102.981 156.287 104.575 155.983 105.37 154.812C106.165 153.642 105.861 152.048 104.69 151.253C98.2692 146.89 94.1045 139.672 94.1045 131.532V116.325C94.1045 112.676 94.9399 109.221 96.4347 106.126Z" fill="#54C166"/>
<path d="M108.851 112.746C109.434 111.456 108.862 109.938 107.572 109.355C106.283 108.771 104.765 109.344 104.182 110.633C103.19 112.824 102.639 115.268 102.639 117.836V130.13C102.639 139.348 109.786 147.036 118.861 147.036C119.551 147.036 120.232 146.991 120.902 146.903C122.306 146.719 123.294 145.432 123.11 144.029C122.925 142.626 121.639 141.638 120.235 141.822C119.787 141.881 119.329 141.911 118.861 141.911C112.849 141.911 107.764 136.756 107.764 130.13V117.836C107.764 116.005 108.156 114.281 108.851 112.746Z" fill="#54C166"/>
<path d="M148.743 118.292C148.743 116.876 147.596 115.729 146.181 115.729C144.766 115.729 143.618 116.876 143.618 118.292V122.276C143.618 123.691 144.766 124.838 146.181 124.838C147.596 124.838 148.743 123.691 148.743 122.276V118.292Z" fill="#54C166"/>
<path d="M121.424 118.861C121.424 117.446 120.277 116.298 118.861 116.298C117.446 116.298 116.299 117.446 116.299 118.861V129.106C116.299 130.521 117.446 131.668 118.861 131.668C120.277 131.668 121.424 130.521 121.424 129.106V118.861Z" fill="#54C166"/>
<path d="M124.479 160.133C125.867 159.86 126.771 158.513 126.498 157.124C126.225 155.736 124.878 154.831 123.489 155.105C120.856 155.623 118.102 155.724 115.312 155.335C113.911 155.139 112.616 156.117 112.421 157.519C112.225 158.921 113.203 160.215 114.605 160.411C117.975 160.88 121.302 160.758 124.479 160.133Z" fill="#54C166"/>
<path d="M148.811 143.57C149.995 142.794 150.325 141.206 149.549 140.022C148.773 138.839 147.184 138.508 146.001 139.284C143.519 140.912 141.888 142.981 140.829 144.663C140.376 144.302 139.877 143.966 139.357 143.717C138.081 143.104 136.551 143.642 135.938 144.918C135.326 146.194 135.864 147.724 137.14 148.337C137.309 148.418 137.658 148.656 138.075 149.062C138.376 149.353 138.629 149.651 138.809 149.9C138.848 150.002 138.895 150.108 138.952 150.215C139.082 150.459 139.395 150.959 140.026 151.301C140.767 151.702 141.549 151.675 142.144 151.463C142.645 151.285 142.968 151 143.109 150.864C143.272 150.707 143.388 150.557 143.457 150.463C143.593 150.276 143.7 150.088 143.766 149.97C143.868 149.783 143.992 149.538 144.105 149.313L144.194 149.136C144.345 148.838 144.516 148.507 144.717 148.15C145.527 146.708 146.79 144.896 148.811 143.57Z" fill="#54C166"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M142.792 128.27C133.829 128.27 126.563 135.536 126.563 144.499C126.563 153.463 133.829 160.729 142.792 160.729C151.755 160.729 159.021 153.463 159.021 144.499C159.021 135.536 151.755 128.27 142.792 128.27ZM131.688 144.499C131.688 138.367 136.659 133.395 142.792 133.395C148.925 133.395 153.896 138.367 153.896 144.499C153.896 150.632 148.925 155.604 142.792 155.604C136.659 155.604 131.688 150.632 131.688 144.499Z" fill="#54C166"/>
</svg>

After

Width:  |  Height:  |  Size: 4.0 KiB

@ -0,0 +1,5 @@
<svg width="43" height="31" viewBox="0 0 43 31" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M15.5596 24.422L21.3946 30.257L27.2296 24.422C25.6811 22.8762 23.5825 22.008 21.3946 22.008C19.2066 22.008 17.108 22.8762 15.5596 24.422Z" fill="#3B3D4A"/>
<path d="M7.78027 16.643L11.6703 20.533C14.2501 17.9549 17.7481 16.5067 21.3953 16.5067C25.0425 16.5067 28.5404 17.9549 31.1203 20.533L35.0103 16.643C31.3989 13.0329 26.5016 11.0049 21.3953 11.0049C16.2889 11.0049 11.3916 13.0329 7.78027 16.643Z" fill="#3B3D4A"/>
<path d="M0 8.86698L3.89 12.757C8.53294 8.1146 14.8298 5.50658 21.3955 5.50658C27.9612 5.50658 34.2581 8.1146 38.901 12.757L42.791 8.86698C37.1165 3.19259 29.4204 0.00476074 21.3955 0.00476074C13.3706 0.00476074 5.67446 3.19259 0 8.86698Z" fill="#3B3D4A"/>
</svg>

After

Width:  |  Height:  |  Size: 789 B

File diff suppressed because one or more lines are too long

@ -91,6 +91,37 @@ class ApiManager {
return response;
}
Future<http.Response> postWithOutBody(String url, {Map<String, String> headers}) async {
headers ??= {};
headers.addAll(_headers);
Uri _url = Uri.parse(url);
if (!kReleaseMode) {
print("URL:$_url");
print("Headers:$headers");
}
var request = http.Request('POST', _url);
request.headers.addAll(headers);
http.StreamedResponse _streamedResponse = await request.send();
http.Response response = await http.Response.fromStream(_streamedResponse);
try {
if (response.statusCode == 401) {
showLoginDialog();
} else {
if (jsonDecode(response.body) is Map<String, dynamic>) {
final message = jsonDecode(response.body)["message"];
if (message != null && message.toString().isNotEmpty) {
Fluttertoast.showToast(msg: message ?? "", toastLength: Toast.LENGTH_LONG);
}
}
}
} catch (ex) {}
return response;
}
Future<http.Response> put(
String url, {

@ -32,6 +32,14 @@ class URLs {
static get getAssetById => "$_baseUrl/Asset/GetAssetById?assetId="; // get
static get getModels => "$_baseUrl/ModelDefinition/GetModelDefinitionAsset"; // get ?client=2
//Reset Password Apis...
static get sendForgetPasswordOtp => "$_baseUrl/Account/SendForgotPasswordOtp"; // send OTP.
static get sendForgetPasswordValidateOtp => "$_baseUrl/Account/SendForgotPasswordValidateOtp"; // validate OTP.
static get updateNewPassword => "$_baseUrl/Account/UpdatenewPassword"; // validate OTP.
//Swipe module Api..
static get swipeUrl=> '$_baseUrl/Swipe/Swipe';
static get getSwipeLastTransactionUrl=> '$_baseUrl/Swipe/GetLastTransaction';
static get getAllRequestsAndCount => "$_baseUrl/CallRequest/GetAllRequestsAndCount"; // get
// 08051
static get getServiceRequests => "$_baseUrl/CallRequest/GetCallRequests"; // get

@ -5,7 +5,12 @@ import 'package:flutter/material.dart';
import 'package:http/http.dart';
import 'package:test_sa/controllers/api_routes/api_manager.dart';
import 'package:test_sa/controllers/api_routes/urls.dart';
import 'package:test_sa/new_views/forget_password_module/models/general_response_model.dart';
import 'package:test_sa/new_views/swipe_module/models/swipe_model.dart';
import 'package:test_sa/new_views/forget_password_module/models/update_password.dart';
import 'package:test_sa/new_views/forget_password_module/models/verify_otp_model.dart';
import 'package:test_sa/models/user.dart';
import 'package:test_sa/new_views/swipe_module/models/swipe_transaction_model.dart';
import '../../../new_views/common_widgets/app_lazy_loading.dart';
@ -15,6 +20,8 @@ class UserProvider extends ChangeNotifier {
_user = null;
ApiManager.instance.user = user;
_loading = false;
isUserConfirmSwipe = false;
swipeTransactionModel = null;
}
// contain user data
@ -22,9 +29,21 @@ class UserProvider extends ChangeNotifier {
User _user;
User get user => _user;
String _newPassword;
String get newPassword => _newPassword;
set newPassword(String value) {
_newPassword = value;
notifyListeners();
}
String _confirmPassword;
File profileImage;
bool isUserConfirmSwipe = false;
set user(User user) {
_user = user;
ApiManager.instance.user = user;
@ -34,6 +53,23 @@ class UserProvider extends ChangeNotifier {
// when login or register in-process _login = true
// when login or register is done or not start = false
bool _loading = false;
VerifyOtpModel _verifyOtpModel;
SwipeTransaction _swipeTransactionModel=SwipeTransaction();
SwipeTransaction get swipeTransactionModel => _swipeTransactionModel;
set swipeTransactionModel(SwipeTransaction value) {
_swipeTransactionModel = value;
notifyListeners();
}
VerifyOtpModel get verifyOtpModel => _verifyOtpModel;
set verifyOtpModel(VerifyOtpModel value) {
_verifyOtpModel = value;
notifyListeners();
}
bool get isLoading => _loading;
@ -141,6 +177,157 @@ class UserProvider extends ChangeNotifier {
return -1;
}
}
//this need to be in seprate provider but for now place here...
Future<SwipeModel> makeSwipe({@required Swipe model}) async {
isLoading = true;
SwipeModel swipeResponse = SwipeModel(data: false, message: '', responseCode: 0, isSuccess: false);
notifyListeners();
Response response;
try {
response = await ApiManager.instance.post(URLs.swipeUrl, body: model.toJson());
swipeResponse = SwipeModel.fromJson(json.decode(response.body));
if (response.statusCode >= 200 && response.statusCode < 300) {
isUserConfirmSwipe = true;
await getSwipeLastTransaction(userId: user.userID);
notifyListeners();
}
notifyListeners();
return swipeResponse;
} catch (error) {
notifyListeners();
return swipeResponse;
}
}
Future<int> getSwipeLastTransaction({@required String userId}) async {
isLoading = true;
notifyListeners();
Response response;
var body = {
"userId": userId,
};
try {
response = await ApiManager.instance.post(URLs.getSwipeLastTransactionUrl, body: body);
if (response.statusCode >= 200 && response.statusCode < 300) {
swipeTransactionModel = SwipeTransaction.fromJson(json.decode(response.body)['data']);
}
notifyListeners();
return response.statusCode;
} catch (error) {
notifyListeners();
return -1;
}
}
Future<GeneralResponseModel> sendForgetPasswordOtp({@required BuildContext context, @required String employeeId}) async {
GeneralResponseModel generalResponseModel= GeneralResponseModel(responseCode: -1) ;
if (_loading == true) return generalResponseModel;
_loading = true;
notifyListeners();
Response response;
try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
response = await ApiManager.instance.postWithOutBody(
URLs.sendForgetPasswordOtp + '?employeeId=$employeeId',
);
generalResponseModel = GeneralResponseModel.fromJson(json.decode(response.body));
print('data i got is ${generalResponseModel.data}');
_loading = false;
if (response.statusCode >= 200 && response.statusCode < 300) {
notifyListeners();
Navigator.pop(context);
return generalResponseModel;
}
notifyListeners();
Navigator.pop(context);
return generalResponseModel;
} catch (error) {
// debugPrint(error);
Navigator.pop(context);
_loading = false;
notifyListeners();
return generalResponseModel;
}
}
Future<GeneralResponseModel> forgetPasswordValidateOtp({@required BuildContext context, @required String employeeId, @required String otp}) async {
print('payload i got is ${employeeId} code ${otp}');
GeneralResponseModel generalResponseModel= GeneralResponseModel(responseCode: -1) ;
// if (_loading == true) return generalResponseModel;
_loading = true;
notifyListeners();
Response response;
try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
response = await ApiManager.instance.postWithOutBody(
URLs.sendForgetPasswordValidateOtp + '?employeeId=$employeeId&otp=$otp',
);
generalResponseModel = GeneralResponseModel.fromJson(json.decode(response.body));
print('response model i got is ${generalResponseModel.data}');
_loading = false;
if (response.statusCode >= 200 && response.statusCode < 300) {
print('i got status ${response.statusCode}');
if(generalResponseModel.data!=null){
print('inside data not null ${generalResponseModel.data}');
verifyOtpModel = VerifyOtpModel.fromJson(generalResponseModel.data);
}
notifyListeners();
Navigator.pop(context);
return generalResponseModel;
}
notifyListeners();
Navigator.pop(context);
return generalResponseModel;
} catch (error) {
// debugPrint(error);
Navigator.pop(context);
_loading = false;
notifyListeners();
return generalResponseModel;
}
}
Future<GeneralResponseModel> updateNewPassword({@required BuildContext context,UpdatePasswordModel updatePasswordModel}) async {
GeneralResponseModel generalResponseModel= GeneralResponseModel(responseCode: -1) ;
if (_loading == true) return generalResponseModel;
_loading = true;
notifyListeners();
Response response;
try {
showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
response = await ApiManager.instance.post(
URLs.updateNewPassword,
body:updatePasswordModel.toJson()
);
generalResponseModel = GeneralResponseModel.fromJson(json.decode(response.body));
_loading = false;
if (response.statusCode >= 200 && response.statusCode < 300) {
notifyListeners();
Navigator.pop(context);
return generalResponseModel;
}
notifyListeners();
Navigator.pop(context);
return generalResponseModel;
} catch (error) {
// debugPrint(error);
Navigator.pop(context);
_loading = false;
notifyListeners();
return generalResponseModel;
}
}
String get confirmPassword => _confirmPassword;
set confirmPassword(String value) {
_confirmPassword = value;
notifyListeners();
}
// Future<int> updateProfile({
// @required String host,

@ -8,12 +8,22 @@
"confirm": "تاكيد",
"done": "تم",
"exit": "إغلاق",
"newPassword": "كلمة المرور الجديدة",
"otpVerification": "التحقق من OTP",
"pleaseEnterTheOtpSentTo": "يرجى إدخال OTP المرسل إلى",
"resetPassword": "إعادة تعيين كلمة المرور",
"pleaseEnterTheNewPassword": "يرجى إدخال كلمة المرور الجديدة",
"verify": "تحقق",
"employeeIdIsRequired": "رقم الموظف مطلوب",
"exitAlert": "هل انت متاكد من رغبتك في إغلاق التطبيق؟",
"signOut": "تسجيل الخروج",
"logoutAlert": "هل انت متاكد من رغبتك في تسجيل الخروج؟",
"language": "اللغة",
"name": "الاسم",
"email": "البريد الالكتروني",
"checkIn": "تسجيل الدخول",
"markAttendance": "تسجيل الحضور",
"selectMethodToMarkAttendance": "اختر الطريقة لتسجيل الحضور",
"phoneNumber": "رقم الهاتف",
"password": "كلمة المرور",
"confirmPassword": "تاكيد كلمة المرور",
@ -29,6 +39,8 @@
"termsAndConditionsValidateMessage": "موافقة علي الشروط والاحكام مطاوبة",
"update": "تحديث",
"step": "خطوة",
"successful": "ناجح",
"youHaveSuccessfullyMarkedYourAttendance": "لقد قمت بتسجيل حضورك بنجاح",
"forgetPasswordWithMark": "نسيت كلمة المرور؟",
"showPassword": "اظهار كلمة المرور",
"wrongEmailOrPassword": "البريد الالكتروني او كلمة المرور غير صحيح",
@ -196,6 +208,7 @@
"comment": "تعليق",
"updateServiceRequest": "تعديل طلب الخدمة",
"repairLocation": "موقع الإصلاح",
"travelingExpense": "مصاريف التنقل",
"startDate": "وقت البدء",
"requestedQuantity": "الكمية المطلوبة",

@ -6,8 +6,20 @@
"requestLockMessage": "Wait until your request complete",
"cancel": "Cancel",
"confirm": "Confirm",
"newPassword": "New Password",
"resetPassword": "Reset Password",
"otpVerification": "OTP Verification",
"pleaseEnterTheOtpSentTo": "Please enter the OTP sent to",
"pleaseEnterTheNewPassword": "Please enter the new password",
"markAttendance": "Mark Attendance",
"selectMethodToMarkAttendance": "Select the method to mark the attendance",
"verify": "Verify",
"employeeIdIsRequired": "Employee Id is required",
"successful": "Successful",
"youHaveSuccessfullyMarkedYourAttendance": "You have successfully marked your attendance",
"done": "Done",
"exit": "Exit",
"checkIn": "Check in",
"exitAlert": "Are you sure you want to exit?",
"signOut": "Sign Out",
"logoutAlert": "Are you sure you want to Sign Out?",

@ -50,6 +50,8 @@ import 'package:test_sa/new_views/pages/login_page.dart';
import 'package:test_sa/new_views/pages/report_bug_page.dart';
import 'package:test_sa/new_views/pages/settings_page.dart';
import 'package:test_sa/new_views/pages/splash_page.dart';
import 'package:test_sa/new_views/pages/usSafeDevice_view.dart';
import 'package:test_sa/new_views/swipe_module/swipe_success_view.dart';
import 'package:test_sa/providers/asset_transfer/asset_transfer_status_provider.dart';
import 'package:test_sa/providers/department_provider.dart';
import 'package:test_sa/providers/gas_request_providers/cylinder_size_provider.dart';
@ -255,6 +257,8 @@ class MyApp extends StatelessWidget {
routes: {
SplashPage.routeName: (_) => const SplashPage(),
LoginPage.routeName: (_) => const LoginPage(),
UnsafeDeviceScreen.routeName: (_) => const UnsafeDeviceScreen(),
SwipeSuccessView.routeName: (_) => const SwipeSuccessView(),
///todo deleted
//old.LandPage.id: (_) => const old.LandPage(),
LandPage.routeName: (_) => const LandPage(),

@ -3,12 +3,18 @@ import 'dart:io';
import 'package:test_sa/controllers/notification/firebase_notification_manger.dart';
import 'package:test_sa/models/enums/user_types.dart';
class User {
int clientId;
String clientName;
List<int> departmentId;
List<String> departmentName;
String message;
bool employeeIsHMG;
bool enableWifi;
bool enableNFC;
bool enableQR;
String username;
String userID;
String email;
@ -48,6 +54,10 @@ class User {
this.email,
this.password,
this.token,
this.employeeIsHMG,
this.enableNFC,
this.enableQR,
this.enableWifi,
this.roles,
this.userRoles,
this.tokenlife,
@ -126,6 +136,11 @@ class User {
map['email'] = email;
map['password'] = password;
map['token'] = token;
map['employeeIsHMG'] = employeeIsHMG;
map['enableWifi'] = enableWifi;
map['enableNFC'] = enableNFC;
map['enableQR'] = enableQR;
map['roles'] = roles;
if (userRoles != null) {
map['userRoles'] = userRoles.map((v) => v.toJson()).toList();
@ -176,6 +191,10 @@ class User {
email = json['email'];
password = json['password'];
token = json['token'];
employeeIsHMG = json['employeeIsHMG'];
enableWifi = json['enableWifi'];
enableNFC = json['enableNFC'];
enableQR = json['enableQR'];
roles = json['roles'];
if (json['userRoles'] != null) {
userRoles = [];

@ -19,10 +19,21 @@ class AppColor {
static const Color neutral50 = Color(0xff3B3D4A);
static const Color neutral60 = Color(0xff2C2C31);
static const Color neutral70 = Color(0xff111427);
static const Color neutral80 = Color(0xff212936);
//background
static const Color backgroundLight = Color(0xffF7F9FB);
static const Color white936 = Color(0xffF7F9FB);
static const Color white10 = Color(0xffE4E5E6);
static const Color white20 = Color(0xff7D859A);
static const Color white40 = Color(0xffF1F1F1);
static const Color white = Color(0xffFFFFFF);
//Todo replace with correct colors.
static const Color backgroundDark = Color(0xff111427);
static const Color white30 = Color(0xff111427);
static const Color black35 = Color(0xff111427);
//red
static const Color red40 = Color(0xffFFDBDC);

@ -16,7 +16,11 @@ class AppBottomNavigationBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
bool isEngineer = (Provider.of<UserProvider>(context, listen: false).user.type) == UsersTypes.engineer;
bool isEngineer = false;
UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
if(_userProvider.user!=null&&(_userProvider.user.type) == UsersTypes.engineer){
isEngineer=true;
}
return ClipRRect(
borderRadius: const BorderRadius.only(topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0)),
child: Container(

@ -16,6 +16,7 @@ class AppTextFormField extends StatefulWidget {
final String initialValue;
final TextStyle style;
final bool enable;
final bool showBorder;
final TextAlign textAlign;
final FocusNode node;
final Widget suffixIcon;
@ -39,6 +40,7 @@ class AppTextFormField extends StatefulWidget {
this.onChange,
this.obscureText,
this.showPassword,
this.showBorder=false,
this.hintText,
this.labelText,
this.textInputType = TextInputType.text,
@ -128,6 +130,7 @@ class _AppTextFormFieldState extends State<AppTextFormField> {
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: widget.showBorder?Border.all(color: AppColor.white10,width: 1):null,
boxShadow: widget.showShadow ? [BoxShadow(color: Colors.black.withOpacity(0.05), blurRadius: 10)] : null,
),
child: textField,

@ -0,0 +1,300 @@
// import 'package:flutter/material.dart';
// import 'package:pinput/pinput.dart';
// import 'package:provider/provider.dart';
// import 'package:test_sa/controllers/providers/api/user_provider.dart';
// import 'package:test_sa/extensions/context_extension.dart';
// import 'package:test_sa/extensions/int_extensions.dart';
// import 'package:test_sa/extensions/text_extensions.dart';
// import 'package:test_sa/extensions/widget_extensions.dart';
// import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
// import 'package:test_sa/new_views/forget_password_module/models/general_response_model.dart';
// import 'package:test_sa/new_views/app_style/app_color.dart';
// import 'package:test_sa/new_views/forget_password_module/reset_password_view.dart';
//
// class ForgetPasswordVerifyOtpView extends StatelessWidget {
// static const String routeName = "/verify_otp";
// String otp = '';
// ForgetPasswordVerifyOtpView({Key key}) : super(key: key);
// @override
// Widget build(BuildContext context) {
// final defaultPinTheme = PinTheme(
// width: 68.toScreenWidth,
// height: 86.toScreenHeight,
// textStyle: const TextStyle(
// fontSize: 22,
// color: Colors.black,
// ),
// decoration: BoxDecoration(
// color: AppColor.white,
// borderRadius: BorderRadius.circular(15),
// border: Border.all(color: AppColor.white10, width: 1),
// ),
// );
// return Scaffold(
// body: Column(
// children: [
// SingleChildScrollView(
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// context.translation.otpVerification.heading2(context).custom(color: AppColor.neutral80, fontWeight: FontWeight.w500),
// 8.height,
// '${context.translation.pleaseEnterTheOtpSentTo} 8997987979879'.bodyText2(context).custom(color: AppColor.white20, fontWeight: FontWeight.w500),
// 40.height,
// Center(
// child: Pinput(
// length: 4,
// defaultPinTheme: defaultPinTheme,
// focusedPinTheme: defaultPinTheme.copyWith(
// decoration: defaultPinTheme.decoration?.copyWith(
// border: Border.all(color: AppColor.white10, width: 1),
// ),
// ),
// onCompleted: (pin) async {
// otp = pin;
// },
// ),
// ),
//
// Row(
// children: [
// 'resend'.bodyText2(context).custom(color: AppColor.black35),
// 7.width,
// ValueListenableBuilder<String>(
// //add actual timer value...
// valueListenable: ValueNotifier("0:00"),
// builder: (context, value, _) {
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// value.bodyText2(context).custom(
// color: context.isDark ? AppColor.neutral10 : AppColor.neutral10,
// ),
// ],
// );
// },
// ),
// 7.width,
// InkWell(
// onTap: () async {
// UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
// String employeeId = '';
// if (_userProvider.user != null && _userProvider.user.userName != null) {
// employeeId = _userProvider.user.userName;
// } else {
// employeeId = 'OUT3893';
// }
// GeneralResponseModel response = await _userProvider.sendForgetPasswordOtp(context: context, employeeId: employeeId);
// // if(response.isSuccess){
// // Navigator.push(context, MaterialPageRoute(builder: (context)=>ForgetPasswordVerifyOtpView()));
// // // Navigator.push(context, ForgetPasswordVerifyOtpView.routeName);
// // }else{
// // Fluttertoast.showToast(msg: response?.message ?? context.translation.failedToCompleteRequest);
// // }
// print('response of send otp i got is ${response.toJson()}');
// },
// child: Text(
// 'resend',
// style: TextStyle(
// color: AppColor.primary30,
// fontWeight: FontWeight.w500,
// fontSize: 12.toScreenWidth,
// decorationColor: AppColor.primary30,
// decoration: TextDecoration.underline,
// ),
// ),
// ),
// ],
// ),
// ],
// ),
// ).center.expanded,
// AppFilledButton(label: context.translation.verify, maxWidth: true, onPressed: () async {
// if(otp.isNotEmpty){
// UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
// GeneralResponseModel generalResponseModel = await _userProvider.forgetPasswordValidateOtp(context: context, employeeId: 'OUT3893', otp: otp);
// if (generalResponseModel.isSuccess) {
// Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => ResetPasswordView()));
// }
// }
//
// }),
// ],
// ).paddingOnly(start: 20,end: 20,bottom: 16),
// );
// }
// }
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:pinput/pinput.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/forget_password_module/models/general_response_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/forget_password_module/reset_password_view.dart';
class ForgetPasswordVerifyOtpView extends StatefulWidget {
static const String routeName = "/verify_otp";
String employeeId = '';
ForgetPasswordVerifyOtpView({Key key,this.employeeId}) : super(key: key);
@override
State<ForgetPasswordVerifyOtpView> createState() => _ForgetPasswordVerifyOtpViewState();
}
class _ForgetPasswordVerifyOtpViewState extends State<ForgetPasswordVerifyOtpView> {
String otp = '';
Timer _timer;
int _remainingSeconds = 180; // 3 minutes in seconds
@override
void initState() {
super.initState();
_startTimer();
}
@override
void dispose() {
_timer.cancel();
super.dispose();
}
void _startTimer() {
setState(() {
_remainingSeconds = 180;
});
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
if (_remainingSeconds > 0) {
setState(() {
_remainingSeconds--;
});
} else {
_timer.cancel();
}
});
}
@override
Widget build(BuildContext context) {
final defaultPinTheme = PinTheme(
width: 68.toScreenWidth,
height: 86.toScreenHeight,
textStyle: const TextStyle(
fontSize: 22,
color: Colors.black,
),
decoration: BoxDecoration(
color: AppColor.white,
borderRadius: BorderRadius.circular(15),
border: Border.all(color: AppColor.white10, width: 1),
),
);
final minutes = (_remainingSeconds ~/ 60).toString().padLeft(2, '0');
final seconds = (_remainingSeconds % 60).toString().padLeft(2, '0');
return Scaffold(
body: Column(
children: [
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
context.translation.otpVerification.heading2(context).custom(color: AppColor.neutral80, fontWeight: FontWeight.w500),
8.height,
'${context.translation.pleaseEnterTheOtpSentTo} 8997987979879'.bodyText2(context).custom(color: AppColor.white20, fontWeight: FontWeight.w500),
40.height,
Center(
child: Pinput(
length: 4,
defaultPinTheme: defaultPinTheme,
focusedPinTheme: defaultPinTheme.copyWith(
decoration: defaultPinTheme.decoration?.copyWith(
border: Border.all(color: AppColor.white10, width: 1),
),
),
onCompleted: (pin) {
setState(() {
otp = pin;
});
verifyOtp();
},
),
),
18.height,
Row(
// mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
InkWell(
onTap: _remainingSeconds == 0
? () async {
UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
String employeeId = widget.employeeId;
GeneralResponseModel response = await _userProvider.sendForgetPasswordOtp(
context: context,
employeeId: employeeId,
);
print('Response of send OTP: ${response.toJson()}');
// Restart the timer
_startTimer();
}
: null,
child: Text(
'Resend',
style: TextStyle(
color: _remainingSeconds == 0 ? AppColor.primary40 : AppColor.white10,
fontWeight: FontWeight.w500,
fontSize: 16.toScreenWidth,
decorationColor: AppColor.primary30,
decoration: _remainingSeconds == 0 ? TextDecoration.underline : null,
),
),
),
7.width,
'$minutes:$seconds'.bodyText(context).custom(color: AppColor.neutral10),
],
),
],
),
).center.expanded,
AppFilledButton(
label: context.translation.verify,
maxWidth: true,
onPressed:verifyOtp,
),
],
).paddingOnly(start: 20, end: 20, bottom: 16),
);
}
void verifyOtp() async{
if (otp.isNotEmpty) {
UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
GeneralResponseModel generalResponseModel = await _userProvider.forgetPasswordValidateOtp(
context: context,
employeeId:widget.employeeId,
otp: otp,
);
if (generalResponseModel.isSuccess) {
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => ResetPasswordView()));
}
}
}
}

@ -0,0 +1,32 @@
class GeneralResponseModel {
dynamic data;
String message;
String title;
String innerMessage;
int responseCode;
bool isSuccess;
GeneralResponseModel({this.data, this.message, this.title, this.innerMessage, this.responseCode, this.isSuccess});
factory GeneralResponseModel.fromJson(Map<String, dynamic> json) {
return GeneralResponseModel(
data: json['data'],
message: json['message'] ?? '',
title: json['title'],
innerMessage: json['innerMessage'],
responseCode: json['responseCode'],
isSuccess: json['isSuccess'],
);
}
Map<String, dynamic> toJson() {
return {
'data': data,
'message': message,
'title': title,
'innerMessage': innerMessage,
'responseCode': responseCode,
'isSuccess': isSuccess,
};
}
}

@ -0,0 +1,24 @@
import 'package:flutter/material.dart';
class UpdatePasswordModel {
final String password;
final String confirmPassword;
final String userId;
final String token;
UpdatePasswordModel({
@required this.password,
@required this.confirmPassword,
@required this.userId,
@required this.token,
});
Map<String, dynamic> toJson() {
return {
'password': password,
'confirmPassword': confirmPassword,
'userId': userId,
'token': token,
};
}
}

@ -0,0 +1,41 @@
import 'package:flutter/material.dart';
class VerifyOtpModel {
final String userId;
final String userName;
final String email;
final String token;
final DateTime validTo;
VerifyOtpModel({
@required this.userId,
@required this.userName,
@required this.email,
@required this.token,
@required this.validTo,
});
// Factory constructor to create an instance from a JSON map
factory VerifyOtpModel.fromJson(Map<String, dynamic> json) {
return VerifyOtpModel(
userId: json['userId'],
userName: json['userName'],
email: json['email'],
token: json['token'],
validTo: DateTime.parse(json['validTo']),
);
}
// Convert the instance to a JSON map
Map<String, dynamic> toJson() {
return {
'userId': userId,
'userName': userName,
'email': email,
'token': token,
'validTo': validTo.toIso8601String(),
};
}
}

@ -0,0 +1,148 @@
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/forget_password_module/models/general_response_model.dart';
import 'package:test_sa/new_views/forget_password_module/models/update_password.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/common_widgets/app_text_form_field.dart';
import 'package:test_sa/new_views/common_widgets/default_app_bar.dart';
import 'package:test_sa/new_views/pages/login_page.dart';
import '../../controllers/providers/api/user_provider.dart';
import '../../controllers/validator/validator.dart';
class ResetPasswordView extends StatefulWidget {
static const String routeName = "/resetPassword";
ResetPasswordView({Key key}) : super(key: key);
@override
State<ResetPasswordView> createState() => _ResetPasswordViewState();
}
class _ResetPasswordViewState extends State<ResetPasswordView> {
UserProvider _userProvider;
bool _passwordVisible =false;
bool _confirmPasswordVisible =false;
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
@override
Widget build(BuildContext context) {
_userProvider = Provider.of<UserProvider>(context);
return Form(
key: _formKey,
child: Scaffold(
body: Column(
children: [
SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
context.translation.resetPassword.heading2(context).custom(color: AppColor.neutral80, fontWeight: FontWeight.w500),
8.height,
context.translation.pleaseEnterTheNewPassword.bodyText2(context).custom(color: AppColor.white20, fontWeight: FontWeight.w500),
32.height,
AppTextFormField(
initialValue: _userProvider.newPassword,
showBorder: true,
validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredField,
labelText: context.translation.password,
obscureText: !_passwordVisible,
suffixIcon: IconButton(
icon: Icon(
// Based on passwordVisible state choose the icon
_passwordVisible
? Icons.visibility
: Icons.visibility_off,
color: context.isDark ? AppColor.neutral10 : AppColor.neutral20,
),
onPressed: () {
// Update the state i.e. toogle the state of passwordVisible variable
setState(() {
_passwordVisible = !_passwordVisible;
});
},
),
onSaved: (value) {
_userProvider.newPassword = value;
},
),
16.height,
AppTextFormField(
initialValue: _userProvider.confirmPassword,
labelText: context.translation.confirmPassword,
obscureText: !_confirmPasswordVisible,
showBorder: true,
validator: (value) => Validator.isValidPassword(value)
? null
: value.isEmpty
? context.translation.requiredField
: context.translation.passwordLengthMessage,
onSaved: (value) {
_userProvider.confirmPassword = value;
},
suffixIcon: IconButton(
icon: Icon(
// Based on passwordVisible state choose the icon
_confirmPasswordVisible
? Icons.visibility
: Icons.visibility_off,
color: context.isDark ? AppColor.neutral10 : AppColor.neutral20,
),
onPressed: () {
// Update the state i.e. toogle the state of passwordVisible variable
setState(() {
_confirmPasswordVisible = !_confirmPasswordVisible;
});
},
),
),
138.height,
AppFilledButton(label: context.translation.resetPassword, maxWidth: true, onPressed: () => _resetPassword(context: context)),
],
),
).center.expanded,
],
).paddingOnly(start: 16, end: 16, bottom: 24, top: 24),
),
);
}
Future<void> _resetPassword({BuildContext context}) async {
if (!_formKey.currentState.validate()) return;
_formKey.currentState.save();
if (_userProvider.newPassword != _userProvider.confirmPassword) {
Fluttertoast.showToast(msg: 'Password not matched try again');
} else {
UpdatePasswordModel updatePasswordModel = UpdatePasswordModel(
password: _userProvider.newPassword, confirmPassword: _userProvider.confirmPassword, userId: _userProvider.verifyOtpModel.userId, token: _userProvider.verifyOtpModel.token);
GeneralResponseModel generalResponseModel = await _userProvider.updateNewPassword(context: context, updatePasswordModel: updatePasswordModel);
if (generalResponseModel.isSuccess) {
_userProvider.newPassword='';
_userProvider.confirmPassword='';
Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
}
}
// if (status >= 200 && status < 300 && _userProvider.user.isAuthenticated ?? false) {
// await _settingProvider.setUser(_userProvider.user);
// (await SharedPreferences.getInstance()).remove(ASettings.localAuth);
// await _settingProvider.setRememberMe(_user.userName, _user.password, rememberMe);
//
// /// The below line for the new design
// // Navigator.pushNamed(context, LandPage.routeName);
// Navigator.pushNamed(context, LandPage.routeName);
// } else {
// Fluttertoast.showToast(msg: _userProvider.user?.message ?? context.translation.failedToCompleteRequest);
// }
}
}

@ -1,6 +1,8 @@
import 'dart:io';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
@ -9,14 +11,17 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/string_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/models/enums/user_types.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
import 'package:test_sa/new_views/pages/land_page/calendar_page.dart';
import 'package:test_sa/new_views/pages/land_page/my_request/my_requests_page.dart';
import 'package:test_sa/new_views/swipe_module/mark_attendance_widget.dart';
import 'package:test_sa/new_views/pages/settings_page.dart';
import 'package:test_sa/new_views/swipe_module/swipe_success_view.dart';
import 'package:test_sa/new_views/swipe_module/utils/swipe_general_utils.dart';
import 'package:test_sa/views/widgets/equipment/single_device_picker.dart';
import '../../../controllers/providers/settings/setting_provider.dart';
import '../../../views/widgets/dialogs/dialog.dart';
import '../../common_widgets/app_bottom_nav_bar.dart';
@ -35,6 +40,7 @@ class LandPage extends StatefulWidget {
class _LandPageState extends State<LandPage> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
bool isNfcSupported = false;
int currentPageIndex = 0;
bool showAppbar = true;
List<Widget> _pages;
@ -43,6 +49,7 @@ class _LandPageState extends State<LandPage> {
@override
void initState() {
_pages = <Widget>[];
super.initState();
}
@ -96,10 +103,19 @@ class _LandPageState extends State<LandPage> {
}
}
Future<void> checkNfcSupported() async {
isNfcSupported = await NfcManager.instance.isAvailable();
setState(() {});
}
@override
Widget build(BuildContext context) {
if (_userProvider == null) {
_userProvider = Provider.of<UserProvider>(context, listen: false);
// if (_userProvider.isUserConfirmSwipe) {
if (!_userProvider.user.employeeIsHMG) {
checkNfcSupported();
}
_pages = <Widget>[
DashboardPage(onDrawerPress: (() {
_scaffoldKey.currentState.isDrawerOpen ? _scaffoldKey.currentState.closeDrawer() : _scaffoldKey.currentState.openDrawer();
@ -109,6 +125,8 @@ class _LandPageState extends State<LandPage> {
const MyAssetsPage(fromBottomBar: true),
if (_userProvider.user.type == UsersTypes.engineer) const CalendarPage(),
];
// }
checkLocalAuth();
}
@ -126,39 +144,89 @@ class _LandPageState extends State<LandPage> {
}
return false;
},
child: Scaffold(
key: _scaffoldKey,
drawer: const AppDrawer(),
body: _pages[currentPageIndex],
bottomNavigationBar: AppBottomNavigationBar(
selectedIndex: currentPageIndex,
onPressed: (index) {
bool isEngineer = _userProvider.user.type == UsersTypes.engineer;
child: Consumer<UserProvider>(builder: (context, userProvider, child) {
return Stack(
children: [
Scaffold(
key: _scaffoldKey,
drawer: const AppDrawer(),
body: _pages[currentPageIndex],
bottomNavigationBar: AppBottomNavigationBar(
selectedIndex: currentPageIndex,
onPressed: (index) {
bool isEngineer = _userProvider.user.type == UsersTypes.engineer;
if (index == (isEngineer ? 4 : 3)) {
showModalBottomSheet(
context: context,
useSafeArea: true,
backgroundColor: Colors.transparent,
builder: (context) => const ContactUsBottomSheet(),
);
} else {
setState(() {
currentPageIndex = index;
});
if (index == 1) {
setState(() {
showAppbar = false;
});
} else {
setState(() {
showAppbar = true;
});
}
}
},
),
),
if (index == (isEngineer ? 4 : 3)) {
showModalBottomSheet(
context: context,
useSafeArea: true,
backgroundColor: Colors.transparent,
builder: (context) => const ContactUsBottomSheet(),
);
} else {
setState(() {
currentPageIndex = index;
});
if (index == 1) {
setState(() {
showAppbar = false;
});
} else {
setState(() {
showAppbar = true;
});
}
}
},
),
),
Visibility(
visible: !userProvider.isUserConfirmSwipe && userProvider.user != null && !userProvider.user.employeeIsHMG,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5),
child: Container(
color: Colors.black.withOpacity(0.2), // Optional tint effect
),
),
),
if (userProvider.user != null && !userProvider.user.employeeIsHMG)
Positioned(
right:_userProvider.user.type==UsersTypes.engineer? 20.toScreenWidth:null,
left:_userProvider.user.type!=UsersTypes.engineer? 20.toScreenWidth:null ,
bottom: 130.toScreenHeight,
child: GestureDetector(
onTap: () {
SwipeGeneralUtils.showSwipeTypeBottomSheetSheet(context: context, isNfcSupported: isNfcSupported);
},
child: CircularAnimationWithProgressIndicator(
child: Container(
width: 120.toScreenWidth,
height: 120.toScreenHeight,
decoration: const BoxDecoration(
shape: BoxShape.circle,
color: AppColor.white,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
'swipe'.toSvgAsset(width: 32, height: 32),
8.height,
context.translation.checkIn.bodyText(context).custom(color: AppColor.neutral80),
8.height,
userProvider.swipeTransactionModel != null && userProvider.swipeTransactionModel.swipeTime != null
? SwipeGeneralUtils.formatTimeOnly(userProvider.swipeTransactionModel.swipeTime).bodyText(context).custom(color: AppColor.neutral80)
: '--:--'.bodyText(context).custom(color: AppColor.neutral80),
],
),
),
),
),
),
],
);
}),
);
// );
}
}

@ -0,0 +1,203 @@
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/platform_tags.dart';
void showNfcReader(BuildContext context, { Function(String nfcId) onNcfScan}) {
showModalBottomSheet(
context: context,
enableDrag: false,
isDismissible: false,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(topLeft: Radius.circular(12), topRight: Radius.circular(12)),
),
backgroundColor: Colors.white,
builder: (context) {
return NfcLayout(
onNcfScan: onNcfScan,
);
},
);
}
class NfcLayout extends StatefulWidget {
Function(String nfcId) onNcfScan;
NfcLayout({this.onNcfScan});
@override
_NfcLayoutState createState() => _NfcLayoutState();
}
class _NfcLayoutState extends State<NfcLayout> {
bool _reading = false;
Widget mainWidget;
String nfcId;
@override
void initState() {
super.initState();
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
var f;
if (Platform.isAndroid) {
f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
} else {
f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
}
String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
nfcId = identifier;
setState(() {
_reading = true;
mainWidget = doneNfc();
});
Future.delayed(const Duration(seconds: 1), () {
NfcManager.instance.stopSession();
Navigator.pop(context);
// if (Platform.isAndroid) {
// Navigator.pop(context);
// } else {
// Navigator.pop(context);
// Navigator.pop(context);
// }
widget.onNcfScan(nfcId);
});
}).catchError((err) {
print(err);
});
}
@override
Widget build(BuildContext context) {
(mainWidget == null && !_reading) ? mainWidget = scanNfc() : mainWidget = doneNfc();
return AnimatedSwitcher(duration: Duration(milliseconds: 500), child: mainWidget);
}
Widget scanNfc() {
return Container(
key: ValueKey(1),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: 30,
),
const Text(
"Ready To Scan",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24,
),
),
SizedBox(
height: 30,
),
Image.asset(
"assets/images/ic_nfc.png",
height: MediaQuery.of(context).size.width / 3,
width: double.infinity,
),
const SizedBox(
height: 30,
),
const Text(
"Approach an NFC Tag",
style: TextStyle(
fontSize: 18,
),
),
const SizedBox(
height: 30,
),
ButtonTheme(
minWidth: MediaQuery.of(context).size.width / 1.2,
height: 45.0,
buttonColor: Colors.grey[300],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
child: TextButton(
onPressed: () {
NfcManager.instance.stopSession();
Navigator.pop(context);
},
// elevation: 0,
child: const Text("CANCEL"),
),
),
SizedBox(
height: 30,
),
],
),
);
}
Widget doneNfc() {
return Container(
key: ValueKey(2),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
SizedBox(
height: 30,
),
Text(
"Successfully Scanned",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 24,
),
),
SizedBox(
height: 30,
),
Image.asset(
// "assets/icons/nfc/ic_done.png",
"assets/images/ic_done.png",
height: MediaQuery.of(context).size.width / 3,
width: double.infinity,
),
SizedBox(
height: 30,
),
Text(
"Approach an NFC Tag",
style: TextStyle(
fontSize: 18,
),
),
SizedBox(
height: 30,
),
ButtonTheme(
minWidth: MediaQuery.of(context).size.width / 1.2,
height: 45.0,
buttonColor: Colors.grey[300],
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6),
),
child: TextButton(
// onPressed: () {
// _stream?.cancel();
// widget.onNcfScan(nfcId);
// Navigator.pop(context);
// },
onPressed: null,
// elevation: 0,
child: Text("DONE"),
),
),
SizedBox(
height: 30,
),
],
),
);
}
}

@ -0,0 +1,35 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
class AAlertDialog extends StatelessWidget {
final String title;
final String content;
const AAlertDialog({Key key, this.title, this.content}) : super(key: key);
@override
Widget build(BuildContext context) {
//
return CupertinoAlertDialog(
title: title != null ? Text(title) : null,
content: content != null ? Text(content) : null,
actions: <Widget>[
TextButton(
// child: Text(_subtitle.confirm),
child: Text(context.translation.confirm),
onPressed: () {
Navigator.of(context).pop(true);
},
),
TextButton(
// child: Text(_subtitle.cancel),
child: Text(context.translation.cancel),
onPressed: () {
Navigator.of(context).pop(false);
},
),
],
);
}
}

@ -8,8 +8,10 @@ import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/forget_password_module/models/general_response_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/pages/land_page/land_page.dart';
import 'package:test_sa/new_views/forget_password_module/forget_passwod_verify_otp.dart';
import '../../controllers/providers/api/user_provider.dart';
import '../../controllers/providers/settings/setting_provider.dart';
@ -29,8 +31,10 @@ class LoginPage extends StatefulWidget {
class _LoginPageState extends State<LoginPage> {
final User _user = User();
bool _passwordVisible = false;
UserProvider _userProvider;
SettingProvider _settingProvider;
TextEditingController userNameController = TextEditingController();
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
bool rememberMe = false;
@ -50,6 +54,7 @@ class _LoginPageState extends State<LoginPage> {
rememberMe = _settingProvider.rememberMe;
if (rememberMe) {
_user.userName = _settingProvider.username;
userNameController.text=_user.userName??'';
_user.password = _settingProvider.password;
}
}
@ -71,6 +76,7 @@ class _LoginPageState extends State<LoginPage> {
32.height,
AppTextFormField(
initialValue: _user?.userName,
controller: userNameController,
validator: (value) => Validator.hasValue(value) ? null : context.translation.requiredField,
labelText: context.translation.username,
textInputType: TextInputType.text,
@ -82,7 +88,22 @@ class _LoginPageState extends State<LoginPage> {
AppTextFormField(
initialValue: _user?.password,
labelText: context.translation.password,
obscureText: true,
suffixIcon: IconButton(
icon: Icon(
// Based on passwordVisible state choose the icon
_passwordVisible
? Icons.visibility
: Icons.visibility_off,
color: context.isDark ? AppColor.neutral10 : AppColor.neutral20,
),
onPressed: () {
// Update the state i.e. toogle the state of passwordVisible variable
setState(() {
_passwordVisible = !_passwordVisible;
});
},
),
obscureText: !_passwordVisible,
validator: (value) => Validator.isValidPassword(value)
? null
: value.isEmpty
@ -110,8 +131,18 @@ class _LoginPageState extends State<LoginPage> {
Align(
alignment: AlignmentDirectional.centerEnd,
child: InkWell(
onTap: () {
/// TODO [zaid] : push to another screen
onTap: () async {
if(userNameController.text.isNotEmpty){
GeneralResponseModel response = await _userProvider.sendForgetPasswordOtp(context: context, employeeId: userNameController.text);
if(response.isSuccess){
Navigator.push(context, MaterialPageRoute(builder: (context)=>ForgetPasswordVerifyOtpView(employeeId:userNameController.text,)));
// Navigator.push(context, ForgetPasswordVerifyOtpView.routeName);
}else{
Fluttertoast.showToast(msg: response?.message ?? context.translation.failedToCompleteRequest);
}
}else{
Fluttertoast.showToast(msg: context.translation.employeeIdIsRequired);
}
},
child: context.translation.forgotPassword.bodyText(context).custom(color: AppColor.primary50, fontWeight: FontWeight.w500),
),

@ -10,7 +10,8 @@ import 'package:test_sa/controllers/providers/settings/setting_provider.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/pages/land_page/land_page.dart';
import 'package:test_sa/new_views/pages/login_page.dart';
import 'package:safe_device/safe_device.dart';
import 'package:test_sa/new_views/pages/usSafeDevice_view.dart';
import '../../models/size_config.dart';
class SplashPage extends StatefulWidget {
@ -105,10 +106,17 @@ class _SplashPageState extends State<SplashPage> {
fit: BoxFit.contain,
animation: "splash",
callback: (animation) async {
if (_settingProvider.isLoaded && (_settingProvider.user != null)) {
checkTokenValidity(_settingProvider.user.token);
} else {
Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
bool isSafe = await checkDeviceSafety();
print('is safe is ${isSafe}');
if(!isSafe){
Navigator.pushNamedAndRemoveUntil(context,UnsafeDeviceScreen.routeName, (_) => false);
}else{
if (_settingProvider.isLoaded && (_settingProvider.user != null)) {
checkTokenValidity(_settingProvider.user.token);
} else {
Navigator.of(context).pushNamedAndRemoveUntil(LoginPage.routeName, (routes) => true);
}
}
// if (_settingProvider.isLoaded && (_settingProvider.user?.isLiveToken ?? false)) {
@ -129,4 +137,28 @@ class _SplashPageState extends State<SplashPage> {
),
);
}
Future<bool> checkDeviceSafety() async {
bool isOnExternalStorage=false;
bool isDevelopmentModeEnable=false;
bool isJailBroken=false;
bool isRealDevice=false;
try {
isJailBroken = await SafeDevice.isJailBroken;
isRealDevice = await SafeDevice.isRealDevice;
if (Platform.isAndroid) {
isOnExternalStorage = await SafeDevice.isOnExternalStorage;
isDevelopmentModeEnable = await SafeDevice.isDevelopmentModeEnable;
}
//TODO correct isDevelopmentModeEnable when publish to prod...
if (isJailBroken || !isRealDevice || isOnExternalStorage || !isDevelopmentModeEnable) {
return false;
}else{
return true;
}
} catch (error) {
print(error);
return false;
}
}
}

@ -0,0 +1,80 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
class UnsafeDeviceScreen extends StatefulWidget {
const UnsafeDeviceScreen({Key key}) : super(key: key);
static const String routeName = "/unSafeDevice";
@override
State<UnsafeDeviceScreen> createState() => _UnsafeDeviceScreenState();
}
class _UnsafeDeviceScreenState extends State<UnsafeDeviceScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
21.height,
// Center(child: Image.asset("assets/images/logos/main_mohemm_logo.png", width: 200, height: 50)),
"logo".toSvgAsset(height: 64),
50.height,
"Sorry".heading5(context),
21.height,
"You are using Atoms app on an unsafe device. To be able to use the app with all it's features, Please make sure that the below points are considered: "
.heading5(context).paddingOnly(start: 20, end: 20),
48.height,
passwordConstraintsUI("The device is not jailbroken or rooted.", true).paddingOnly(start: 24, end: 5),
8.height,
passwordConstraintsUI("The app is not installed on external storage.", true).paddingOnly(start: 24, end: 5),
8.height,
passwordConstraintsUI("Development mode is disabled.", true).paddingOnly(start: 24, end: 5),
21.height,
AppFilledButton(label: context.translation.done, maxWidth: true, onPressed: () async {
if (Platform.isAndroid) {
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
} else {
// MinimizeApp.minimizeApp();
}
}).paddingAll(24),
// DefaultButton(LocaleKeys.ok.tr(), () async {
// if (Platform.isAndroid) {
// SystemChannels.platform.invokeMethod('SystemNavigator.pop');
// } else {
// // MinimizeApp.minimizeApp();
// }
// })
],
),
),
);
}
Widget passwordConstraintsUI(String description, bool check) {
return Row(
children: [
4.width,
SizedBox(
width: 12,
height: 12,
child: Checkbox(fillColor: MaterialStateProperty.all(AppColor.backgroundDark), shape: const CircleBorder(), value: check, onChanged: null),
),
8.width,
description.heading6(context)
],
);
}
}

@ -0,0 +1,62 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
class ConfirmDialog extends StatelessWidget {
final String title;
final String message;
final String okTitle;
final VoidCallback onTap;
final VoidCallback onCloseTap;
const ConfirmDialog({Key key, this.title, this.message, this.okTitle, this.onTap, this.onCloseTap}) : super(key: key);
@override
Widget build(BuildContext context) {
print('message i got is $message');
return Dialog(
backgroundColor: Colors.white,
shape: const RoundedRectangleBorder(),
insetPadding: const EdgeInsets.only(left: 21, right: 21),
child: Padding(
padding: const EdgeInsets.only(left: 20, right: 20, top: 18, bottom: 28),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Text(
title ?? "Confirm",
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w600, color: Colors.black87, height: 35 / 24, letterSpacing: -0.96),
).paddingOnly(top: 16),
),
IconButton(
padding: EdgeInsets.zero,
icon: const Icon(Icons.close),
color: Colors.black87,
constraints: const BoxConstraints(),
onPressed: () => onCloseTap ?? Navigator.pop(context),
// onPressed: () => Navigator.pop(context),
)
],
),
message.heading5(context).custom(color: AppColor.black35),
28.height,
AppFilledButton(
label: okTitle ?? "OK",
onPressed: onTap ?? () => Navigator.pop(context),
textColor: Colors.white,
//color: Ap.green,
),
],
),
),
);
}
}

@ -0,0 +1,79 @@
import 'package:flutter/material.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:test_sa/new_views/common_widgets/app_filled_button.dart';
class QrScannerDialog extends StatefulWidget {
@override
State<QrScannerDialog> createState() => _QrScannerDialogState();
}
class _QrScannerDialogState extends State<QrScannerDialog> {
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
Barcode result;
QRViewController controller;
bool isPicked = false;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: double.infinity,
height: double.infinity,
color: Colors.white,
child: Column(
children: [
Expanded(
flex: 1,
child: QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
),
),
// Expanded(
// flex: 1,
// child: Center(
// child: (result != null)
// ? Text(
// 'Barcode Type: ${result!.format} Data: ${result!.code}')
// : Text('Scan a code'),
// ),
// ),
Padding(
padding: const EdgeInsets.all(12.0),
child: AppFilledButton(
label: "Cancel",
onPressed: () {
Navigator.pop(context);
},
),
),
],
),
),
);
}
void _onQRViewCreated(QRViewController controller) {
this.controller = controller;
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
if (!isPicked) {
isPicked = true;
Navigator.pop(context, result.code);
}
});
});
controller.pauseCamera();
controller.resumeCamera();
}
@override
void dispose() {
controller?.dispose();
super.dispose();
}
}

@ -0,0 +1,76 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:just_audio/just_audio.dart';
import 'package:lottie/lottie.dart';
class SuccessDialog extends StatefulWidget {
bool isFromDashboard;
SuccessDialog(this.isFromDashboard);
@override
State<SuccessDialog> createState() => _SuccessDialogState();
}
class _SuccessDialogState extends State<SuccessDialog> with TickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
_controller = AnimationController(vsync: this);
super.initState();
}
Future<void> playSuccessSound() async {
AudioPlayer player = AudioPlayer();
String audioAsset = "";
if (Platform.isAndroid) {
audioAsset = "assets/audio/success_tone_android.mp3";
} else {
audioAsset = "assets/audio/success_tone_ios.caf";
}
await player.setAsset(audioAsset);
await player.load();
player.play();
}
@override
Widget build(BuildContext context) {
double size = MediaQuery.of(context).size.width / 1.8;
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: size,
height: size,
child: Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0),
),
child: Lottie.asset(
//TODO replace with original lottie file...
'assets/lottie/done.json',
repeat: false,
reverse: false,
controller: _controller,
frameRate: FrameRate(60.0),
onLoaded: (LottieComposition v) async {
await playSuccessSound();
_controller
..duration = v.duration
..forward().whenComplete(() async {
Navigator.pop(context);
if (widget.isFromDashboard) Navigator.pop(context);
});
},
),
),
),
],
);
}
}

@ -0,0 +1,18 @@
enum SwipeTypeEnum {
NFC, // 1
QR, // 2
Wifi, // 3
}
extension EnumExtensionsSwipeType on SwipeTypeEnum {
int getIntFromSwipeTypeEnum() {
switch (this) {
case SwipeTypeEnum.NFC:
return 1;
case SwipeTypeEnum.QR:
return 2;
case SwipeTypeEnum.Wifi:
return 3;
}
}
}

@ -0,0 +1,851 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:huawei_location/huawei_location.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/swipe_module/enums/swipe_type.dart';
import 'package:test_sa/new_views/swipe_module/models/swipe_model.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/pages/land_page/nfc/nfc_reader_sheet.dart';
import 'package:test_sa/new_views/swipe_module/utils/swipe_general_utils.dart';
import 'package:test_sa/new_views/swipe_module/utils/location_utils.dart';
import 'package:test_sa/new_views/swipe_module/dialoge/confirm_dialog.dart';
import 'package:test_sa/new_views/swipe_module/dialoge/success_dialog.dart';
import 'package:test_sa/new_views/swipe_module/dialoge/qr_scanner_dialog.dart';
import 'package:wifi_iot/wifi_iot.dart';
class MarkAttendanceWidget extends StatefulWidget {
double topPadding;
bool isFromDashboard;
MarkAttendanceWidget({Key key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key);
// todo MarkAttendanceWidget(this.model, {Key? key, this.topPadding = 0, this.isFromDashboard = false}) : super(key: key);
@override
_MarkAttendanceWidgetState createState() {
return _MarkAttendanceWidgetState();
}
}
class _MarkAttendanceWidgetState extends State<MarkAttendanceWidget> {
bool isNfcEnabled = false, isQrEnabled = false, isWifiEnabled = false;
UserProvider _userProvider;
int _locationUpdateCbId = 0;
@override
void initState() {
super.initState();
checkAttendanceAvailability();
}
void checkAttendanceAvailability() async {
_userProvider = Provider.of<UserProvider>(context, listen: false);
bool isAvailable = await NfcManager.instance.isAvailable();
log('backend enabled values are nfc ${_userProvider.user.enableNFC} qr ${_userProvider.user.enableQR} wifi ${_userProvider.user.enableWifi}');
setState(() {
if (isAvailable && _userProvider.user.enableNFC) isNfcEnabled = true;
if (_userProvider.user.enableQR) isQrEnabled = true;
if (_userProvider.user.enableWifi) isWifiEnabled = true;
});
}
void checkHuaweiLocationPermission(SwipeTypeEnum attendanceType,BuildContext context) async {
// Permission_Handler permissionHandler = PermissionHandler();
LocationUtilities.isEnabled((bool isEnabled) async {
if (isEnabled) {
LocationUtilities.havePermission((bool permission) async {
if (permission) {
getHuaweiCurrentLocation(attendanceType,context);
} else {
bool has = await requestPermissions();
if (has) {
getHuaweiCurrentLocation(attendanceType,context);
} else {
showDialog(
context: context,
builder: (BuildContext cxt) => ConfirmDialog(
message: "You need to give location permission to mark attendance",
onTap: () {
Navigator.pop(context);
},
),
);
}
}
});
} else {
showDialog(
context: context,
builder: (BuildContext cxt) => ConfirmDialog(
message: "You need to enable location services to mark attendance",
onTap: () async {
Navigator.pop(context);
await Geolocator.openLocationSettings();
},
),
);
}
});
// if (await permissionHandler.hasLocationPermission()) {
// getHuaweiCurrentLocation(attendanceType);
// } else {
// bool has = await requestPermissions();
// if (has) {
// getHuaweiCurrentLocation(attendanceType);
// } else {
// showDialog(
// context: context,
// builder: (BuildContext cxt) => ConfirmDialog(
// message: "You need to give location permission to mark attendance",
// onTap: () {
// Navigator.pop(context);
// },
// ),
// );
// }
// }
}
Future<bool> requestPermissions() async {
var result = await [
Permission.location,
].request();
return (result[Permission.location] == PermissionStatus.granted || result[Permission.locationAlways] == PermissionStatus.granted);
}
@override
void dispose() {
super.dispose();
// Stop Session
NfcManager.instance.stopSession();
}
@override
Widget build(BuildContext context) {
return
Container(
padding: EdgeInsets.only(left: 21, right: 21, bottom: 21, top: widget.topPadding),
decoration: const BoxDecoration(borderRadius: BorderRadius.only(topLeft: Radius.circular(25), topRight: Radius.circular(25)), color: Colors.white),
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
20.height,
'click me '.heading5(context),
// LocaleKeys.markAttendance.tr().toSectionHeading(),
// LocaleKeys.selectMethodOfAttendance.tr().toText11(color: const Color(0xff535353)),
GridView(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: const EdgeInsets.only(bottom: 0, top: 21),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 8, mainAxisSpacing: 8),
children: availableAttendanceMethodList(context: context),
)
],
),
);
}
void handleSwipe({
SwipeTypeEnum swipeType,
@required bool isEnable,
@required BuildContext context,
}) {
// if (AppState().getIsHuawei) {
if (false) {
checkHuaweiLocationPermission(swipeType,context);
} else {
LocationUtilities.isEnabled((bool isEnabled) {
if (isEnabled) {
LocationUtilities.havePermission((bool permission) {
if (permission) {
SwipeGeneralUtils.showLoading(context);
LocationUtilities.getCurrentLocation(
(Position position, bool isMocked) {
if (isMocked) {
SwipeGeneralUtils.hideLoading(context);
SwipeGeneralUtils.markFakeAttendance(swipeType.name, position.latitude.toString() ?? "", position.longitude.toString() ?? "", context);
} else {
SwipeGeneralUtils.hideLoading(context);
//todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
handleSwipeOperation(swipeType: swipeType, lat: position.latitude, lang: position.longitude);
}
},
() {
SwipeGeneralUtils.hideLoading(context);
SwipeGeneralUtils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
},
context,
);
} else {
showDialog(
context: context,
builder: (BuildContext cxt) => ConfirmDialog(
message: "You need to give location permission to mark attendance",
onTap: () async {
Navigator.pop(context);
await Geolocator.openAppSettings();
},
),
);
}
});
} else {
showDialog(
context: context,
builder: (BuildContext cxt) => ConfirmDialog(
message: "You need to enable location services to mark attendance",
onTap: () async {
Navigator.pop(context);
await Geolocator.openLocationSettings();
},
),
);
}
});
}
}
void handleSwipeOperation({@required SwipeTypeEnum swipeType, double lat, double lang,BuildContext context}) {
switch (swipeType) {
case SwipeTypeEnum.NFC:
handleNfcAttendance(latitude: lat, longitude: lang,context: context);
return;
case SwipeTypeEnum.QR:
performQrCodeAttendance(latitude: lat, longitude: lang,context:context);
return;
case SwipeTypeEnum.Wifi:
//TODO need to implement.
return;
}
}
void getHuaweiCurrentLocation(SwipeTypeEnum attendanceType,BuildContext context) async {
try {
SwipeGeneralUtils.showLoading(context);
FusedLocationProviderClient locationService = FusedLocationProviderClient()..initFusedLocationService();
LocationRequest locationRequest = LocationRequest();
locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
locationRequest.interval = 500;
List<LocationRequest> locationRequestList = <LocationRequest>[locationRequest];
LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList);
StreamSubscription<Location> _streamSubscription;
int requestCode = (await (locationService.requestLocationUpdates(locationRequest)));
_streamSubscription = locationService.onLocationData.listen(
(Location location) async {
SwipeGeneralUtils.hideLoading(context);
await locationService.removeLocationUpdates(requestCode);
handleSwipeOperation(swipeType: attendanceType);
requestCode = 0;
},
);
// locationService.checkLocationSettings(locationSettingsRequest).then((settings) async {
// await locationService.getLastLocation().then((value) {
// if (value.latitude == null || value.longitude == null) {
// showDialog(
// context: context,
// builder: (BuildContext cxt) => ConfirmDialog(
// message: "Unable to get your location, Please check your location settings & try again.",
// onTap: () {
// Navigator.pop(context);
// },
// ),
// );
// } else {
// if (attendanceType == "QR") {
// performQrCodeAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
// }
// if (attendanceType == "WIFI") {
// performWifiAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
// }
// if (attendanceType == "NFC") {
// performNfcAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
// }
// }
// }).catchError((error) {
// log("HUAWEI LOCATION getLastLocation ERROR!!!!!");
// log(error);
// });
// }).catchError((error) {
// log("HUAWEI LOCATION checkLocationSettings ERROR!!!!!");
// log(error);
// if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") {
// // Location service not enabled.
// }
// });
} catch (error) {
log("HUAWEI LOCATION ERROR!!!!!");
log('$error');
SwipeGeneralUtils.hideLoading(context);
// SwipeGeneralUtils.handleException(error, context, null);
}
}
Future<void> handleNfcAttendance({double latitude = 0, double longitude = 0,BuildContext context}) async {
final userProvider = Provider.of<UserProvider>(context, listen: false);
if (Platform.isIOS) {
SwipeGeneralUtils.readNFc(onRead: (String nfcId) async {
await _processNfcAttendance(userProvider, nfcId, latitude, longitude,context);
});
} else {
showNfcReader(context, onNcfScan: (String nfcId) async {
await _processNfcAttendance(userProvider, nfcId ?? '', latitude, longitude,context);
});
}
}
Future<void> _processNfcAttendance(
UserProvider userProvider,
String nfcId,
double latitude,
double longitude,
BuildContext context,
) async {
SwipeGeneralUtils.showLoading(context);
try {
// final swipeModel = Swipe(
// swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(),
// value: nfcId,
// latitude: latitude,
// longitude: longitude,
// );
//Test model...
final swipeModel = Swipe(
swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(),
value: '123',
latitude: 24.70865415364271,
longitude: 46.66600861881879,
);
print('swipe model to call api is ${swipeModel.toJson()} ');
final swipeResponse = await userProvider.makeSwipe(model: swipeModel);
log('swipe response i got is ${swipeResponse.toJson()}');
if (swipeResponse.isSuccess) {
if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3));
SwipeGeneralUtils.hideLoading(context);
SwipeGeneralUtils.showSuccessDialog(context: context, fromDashBoard: widget.isFromDashboard);
} else {
SwipeGeneralUtils.hideLoading(context);
SwipeGeneralUtils.showErrorDialog(message: swipeResponse.message ?? "Unexpected error occurred", context: context);
}
} catch (errSwipeGeneralUtilsor) {
SwipeGeneralUtils.hideLoading(context);
// Uncomment below line for error handling if needed
// SwipeGeneralUtils.handleException(error, context, null);
}
}
Future<bool> closeWifiRequest() async {
if (Platform.isAndroid) {
await WiFiForIoTPlugin.forceWifiUsage(false);
}
return await WiFiForIoTPlugin.disconnect();
}
Future<void> performQrCodeAttendance({double latitude, double longitude ,BuildContext context}) async {
UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
var qrCodeValue = await Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => QrScannerDialog(),
),
);
if (qrCodeValue != null) {
SwipeGeneralUtils.showLoading(context);
try {
//test model..
final swipeModel = Swipe(
swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(),
value: '2323',
latitude: 24.70865415364271,
longitude: 46.66600861881879,
);
// final swipeModel = Swipe(
// swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(),
// value: qrCodeValue,
// latitude: latitude,
// longitude: longitude,
// );
log('model i got to scan qr is ${swipeModel.toJson()}');
final swipeResponse = await userProvider.makeSwipe(model: swipeModel);
log('response of swipe is ${swipeResponse.toJson()}');
if (swipeResponse.isSuccess) {
SwipeGeneralUtils.hideLoading(context);
SwipeGeneralUtils.showMDialog(
context,
backgroundColor: Colors.transparent,
isDismissable: true,
child: SuccessDialog(widget.isFromDashboard),
);
} else {
SwipeGeneralUtils.hideLoading(context);
showDialog(
barrierDismissible: true,
context: context,
builder: (cxt) => ConfirmDialog(
message: swipeResponse.message ?? "",
onTap: () {
Navigator.pop(context);
},
onCloseTap: () {},
),
);
}
} catch (ex) {
log('$ex');
SwipeGeneralUtils.hideLoading(context);
//this need to confirm where it comes..
// SwipeGeneralUtils.handleException(ex, context, null);
}
}
}
List<Widget> availableAttendanceMethodList({@required BuildContext context}) {
List<Widget> availableMethods = [];
if (isNfcEnabled) {
availableMethods.add(attendanceMethod(SwipeTypeEnum.NFC.name, 'nfc_icon', isNfcEnabled, () {
handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: isNfcEnabled,context: context);
}));
}
if (isQrEnabled) {
availableMethods.add(attendanceMethod(SwipeTypeEnum.QR.name, 'wifi_icon', isQrEnabled, () {
handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: isQrEnabled,context: context);
}));
}
if (isWifiEnabled) {
availableMethods.add(attendanceMethod(SwipeTypeEnum.Wifi.name, 'wifi_icon', isWifiEnabled, () {
handleSwipe(swipeType: SwipeTypeEnum.Wifi, isEnable: isWifiEnabled,context: context);
}));
}
return availableMethods;
}
Widget attendanceMethod(String title, String icon, bool isEnabled, VoidCallback onPress) {
return Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(18),
border: Border.all(color: AppColor.white40, width: 2),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
icon.toSvgAsset(),
title.heading5(context).custom(color: AppColor.neutral50),
// Text(
// title,
// style: TextStyle(fontSize: 12, fontWeight: FontWeight.w500),
// ),
],
),
).onPress(
() {
log('isEnabled is ${!isEnabled}');
if (!isEnabled) return;
onPress();
},
);
// return Container(
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(15),
// color: isEnabled ? null : Colors.grey.withOpacity(.5),
// gradient: isEnabled
// ? const LinearGradient(
// transform: GradientRotation(.64),
// begin: Alignment.topRight,
// end: Alignment.bottomLeft,
// colors: [
// //ToDo set Colors according to design provided by designer...
// Colors.blue,
// Colors.green,
// // AppColor.gradiantEndColor,
// // MyColors.gradiantStartColor,
// ],
// )
// : null,
// ),
// clipBehavior: Clip.antiAlias,
// padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// // SvgPicture.asset(image, color: Colors.white, alignment: Alignment.topLeft).expanded,
// Icon(iconData, color: isEnabled ? AppColor.black35 : Colors.grey),
// title.heading6(context),
// // title.toText17(isBold: true, color: Colors.white),
// ],
// ),
// ).onPress(
// () {
// log('isEnabled is ${!isEnabled}');
// if (!isEnabled) return;
// onPress();
// },
// );
}
}
// Widget customListItem({required String icon, required String heading, required String subHeading, required VoidCallback onTap}) {
// return GestureDetector(
// onTap: onTap, // Handles the tap
// child: Card(
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(14), // Circular border radius
// ),
// color: Colors.white,
// child: Row(
// crossAxisAlignment: CrossAxisAlignment.start, // Align items at the top
// children: [
// // Icon Section
// icon
// .toSvgAsset(
// width: 32,
// color: AppColor.neutral120,
// height: 29,
// )
// .paddingOnly(top: 8),
// 14.width,
// Expanded(
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// Text(
// heading,
// style: AppTextStyles.heading6.copyWith(color: AppColor.neutral50),
// ),
// 7.height,
// Text(
// subHeading,
// style: AppTextStyles.bodyText2.copyWith(color: AppColor.neutral120),
// ),
// ],
// ).paddingOnly(end: 50),
// ),
// ],
// ).paddingAll(12),
// ),
// );
// }
//qr older code...
//nfc older code widget
// // if (AppState().getIsHuawei) {
// if (false) {
// checkHuaweiLocationPermission(SwipeTypeEnum.NFC);
// } else {
// LocationUtilities.isEnabled((bool isEnabled) {
// if (isEnabled) {
// LocationUtilities.havePermission((bool permission) {
// if (permission) {
// SwipeGeneralUtils.showLoading(context);
// LocationUtilities.getCurrentLocation(
// (Position position, bool isMocked) {
// if (isMocked) {
// SwipeGeneralUtils.hideLoading(context);
// SwipeGeneralUtils.markFakeAttendance("NFC", position.latitude.toString() ?? "", position.longitude.toString() ?? "",context);
// } else {
// SwipeGeneralUtils.hideLoading(context);
// //todo performNfcAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
// }
// },
// () {
// SwipeGeneralUtils.hideLoading(context);
// SwipeGeneralUtils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
// },
// context,
// );
// } else {
// showDialog(
// context: context,
// builder: (BuildContext cxt) => ConfirmDialog(
// message: "You need to give location permission to mark attendance",
// onTap: () async {
// Navigator.pop(context);
// await Geolocator.openAppSettings();
// },
// ),
// );
// }
// });
// } else {
// showDialog(
// context: context,
// builder: (BuildContext cxt) => ConfirmDialog(
// message: "You need to enable location services to mark attendance",
// onTap: () async {
// Navigator.pop(context);
// await Geolocator.openLocationSettings();
// },
// ),
// );
// }
// });
// }
//older code....
// Future<void> performNfcAttendance({double lat = 0, double lng = 0}) async {
// UserProvider userProvider = Provider.of<UserProvider>(context,listen:false);
// if (Platform.isIOS) {
// SwipeGeneralUtils.readNFc(onRead: (String nfcId) async {
// SwipeGeneralUtils.showLoading(context);
// try {
// SwipeModel swipeResponse = await userProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: '', latitude: lat, longitude: lng));
// if (swipeResponse.responseCode != 1) {
// SwipeGeneralUtils.hideLoading(context);
// showDialog(
// context: context,
// builder: (BuildContext cxt) => ConfirmDialog(
// message: swipeResponse.message ?? "Unexpected error occurred",
// onTap: () {
// Navigator.pop(context);
// },
// ),
// );
// } else {
// bool status = swipeResponse.data;
// if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3));
// SwipeGeneralUtils.hideLoading(context);
// SwipeGeneralUtils.showMDialog(
// context,
// backgroundColor: Colors.transparent,
// isDismissable: true,
// child: SuccessDialog(widget.isFromDashboard),
// );
// }
// } catch (ex) {
// SwipeGeneralUtils.hideLoading(context);
// // SwipeGeneralUtils.handleException(ex, context, null);
// }
// });
// } else {
// showNfcReader(context, onNcfScan: (String nfcId) async {
// SwipeGeneralUtils.showLoading(context);
// try {
// SwipeModel swipeResponse = await userProvider.makeSwipe(model: Swipe(swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(), value: nfcId??'', latitude: lat, longitude: lng));
// log('api response i got is ${swipeResponse.toJson()}');
// if (swipeResponse.responseCode != 1) {
// SwipeGeneralUtils.hideLoading(context);
// showDialog(
// context: context,
// builder: (BuildContext cxt) => ConfirmDialog(
// message: swipeResponse.message ?? "Unexpected error occurred",
// onTap: () {
// Navigator.pop(context);
// },
// ),
// );
// } else {
// bool status = swipeResponse.data; //use this status to get transactions.
// if (Platform.isIOS) await Future.delayed(const Duration(seconds: 3));
// SwipeGeneralUtils.hideLoading(context);
// SwipeGeneralUtils.showMDialog(
// context,
// backgroundColor: Colors.transparent,
// isDismissable: true,
// child: SuccessDialog(widget.isFromDashboard),
// );
// }
// } catch (ex) {
// SwipeGeneralUtils.hideLoading(context);
// // SwipeGeneralUtils.handleException(ex, context, null);
// }
// // SwipeGeneralUtils.showLoading(context);
// // try {
// // GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 2, nfcValue: nfcId ?? "", isGpsRequired: isNfcLocationEnabled, lat: lat, long: lng);
// // if (g?.messageStatus != 1) {
// // SwipeGeneralUtils.hideLoading(context);
// // showDialog(
// // context: context,
// // builder: (BuildContext cxt) => ConfirmDialog(
// // message: g?.errorEndUserMessage ?? "Unexpected error occurred",
// // onTap: () {
// // Navigator.pop(context);
// // },
// // ),
// // );
// // } else {
// // bool status = await model.fetchAttendanceTracking(context);
// // SwipeGeneralUtils.hideLoading(context);
// // showMDialog(
// // context,
// // backgroundColor: Colors.transparent,
// // isDismissable: false,
// // child: SuccessDialog(widget.isFromDashboard),
// // );
// // }
// // } catch (ex) {
// // log(ex);
// // SwipeGeneralUtils.hideLoading(context);
// // // SwipeGeneralUtils.handleException(ex, context, (String msg) {
// // // SwipeGeneralUtils.confirmDialog(context, msg);
// // // });
// // }
// });
// }
// }
//
// Future<bool> checkSession() async {
// try {
// SwipeGeneralUtils.showLoading(context);
// await DashboardApiClient().getOpenMissingSwipes();
// SwipeGeneralUtils.hideLoading(context);
// return true;
// } catch (ex) {
// SwipeGeneralUtils.hideLoading(context);
// SwipeGeneralUtils.handleException(ex, context, null);
// return false;
// }
// }
//TODO need to confirm ....
// Future<void> performWifiAttendance({double? latitude, double? lng}) async {
// // if (Platform.isAndroid) {
// // if (!(await checkSession())) {
// // return;
// // }
// // }
// SwipeGeneralUtils.showLoading(context);
// bool isConnected = await WiFiForIoTPlugin.connect(AppState().getMohemmWifiSSID ?? "",
// password: AppState().getMohemmWifiPassword ?? "", joinOnce: Platform.isIOS ? false : true, security: NetworkSecurity.WPA, withInternet: false);
//
// if (Platform.isIOS) {
// if (await WiFiForIoTPlugin.getSSID() == AppState().getMohemmWifiSSID) {
// isConnected = true;
// } else {
// isConnected = false;
// }
// }
//
// if (isConnected && AppState().isAuthenticated) {
// await WiFiForIoTPlugin.forceWifiUsage(true);
// await Future.delayed(const Duration(seconds: 6));
// try {
// GenericResponseModel? g = await DashboardApiClient().markAttendance(pointType: 3, nfcValue: "", isGpsRequired: isWifiLocationEnabled, lat: lat, long: lng);
// bool status = await model.fetchAttendanceTracking(context);
// SwipeGeneralUtils.hideLoading(context);
// await closeWifiRequest();
// if (g?.messageStatus == 2) {
// showDialog(
// barrierDismissible: true,
// context: context,
// builder: (cxt) => ConfirmDialog(
// message: g?.errorEndUserMessage ?? "",
// onTap: () {
// Navigator.pop(context);
// },
// onCloseTap: () {},
// ),
// );
// } else {
// showMDialog(
// context,
// backgroundColor: Colors.transparent,
// isDismissable: false,
// child: SuccessDialog(widget.isFromDashboard),
// );
// }
// } catch (ex) {
// await closeWifiRequest();
// SwipeGeneralUtils.hideLoading(context);
// SwipeGeneralUtils.handleException(ex, context, null);
// }
// } else {
// if (AppState().isAuthenticated) {
// SwipeGeneralUtils.hideLoading(context);
// SwipeGeneralUtils.confirmDialog(context, "LocaleKeys.comeNearHMGWifi.tr()");
// } else {
// await closeWifiRequest();
// }
// }
// }
// older grid widget..
// attendanceMethod(SwipeTypeEnum.NFC.name, Icons.nfc, isNfcEnabled, () {
// handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: isNfcEnabled);
// }),
// attendanceMethod(SwipeTypeEnum.QR.name, Icons.qr_code_2, isQrEnabled, () async {
// handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: true);
// }),
// //if (isWifiEnabled) //todo
// attendanceMethod(SwipeTypeEnum.Wifi.name, Icons.wifi, isWifiEnabled, () {
// // if (AppState().getIsHuawei) {
// if (false) {
// checkHuaweiLocationPermission(SwipeTypeEnum.Wifi);
// } else {
// LocationUtilities.isEnabled((bool isEnabled) {
// if (isEnabled) {
// LocationUtilities.havePermission((bool permission) {
// if (permission) {
// SwipeGeneralUtils.showLoading(context);
// LocationUtilities.getCurrentLocation(
// (Position position, bool isMocked) {
// if (isMocked) {
// SwipeGeneralUtils.hideLoading(context);
// SwipeGeneralUtils.markFakeAttendance("WIFI", position.latitude.toString() ?? "", position.longitude.toString() ?? "", context);
// } else {
// SwipeGeneralUtils.hideLoading(context);
// //todo performWifiAttendance(widget.model, lat: position.latitude.toString() ?? "", lng: position.longitude.toString() ?? "");
// }
// },
// () {
// SwipeGeneralUtils.hideLoading(context);
// SwipeGeneralUtils.confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
// },
// context,
// );
// } else {
// showDialog(
// context: context,
// builder: (BuildContext cxt) => ConfirmDialog(
// message: "You need to give location permission to mark attendance",
// onTap: () async {
// Navigator.pop(context);
// await Geolocator.openAppSettings();
// },
// ),
// );
// }
// });
// } else {
// showDialog(
// context: context,
// builder: (BuildContext cxt) => ConfirmDialog(
// message: "You need to enable location services to mark attendance",
// onTap: () async {
// Navigator.pop(context);
// await Geolocator.openLocationSettings();
// },
// ),
// );
// }
// });
// }
// }),

@ -0,0 +1,68 @@
import 'package:flutter/material.dart';
class SwipeModel {
final bool data;
final String message;
final String title;
final String innerMessage;
final int responseCode;
final bool isSuccess;
SwipeModel({
@required this.data,
@required this.message,
this.title,
this.innerMessage,
@required this.responseCode,
@required this.isSuccess,
});
factory SwipeModel.fromJson(Map<String, dynamic> json) {
return SwipeModel(
data: json['data'] as bool,
message: json['message'] as String,
title: json['title'] as String,
innerMessage: json['innerMessage'] as String,
responseCode: json['responseCode'] as int,
isSuccess: json['isSuccess'] as bool,
);
}
Map<String, dynamic> toJson() {
return {
'data': data,
'message': message,
'title': title,
'innerMessage': innerMessage,
'responseCode': responseCode,
'isSuccess': isSuccess,
};
}
}
class Swipe {
final int swipeTypeValue;
final String value;
final double latitude;
final double longitude;
Swipe({
@required this.swipeTypeValue,
@required this.value,
@required this.latitude,
@required this.longitude,
});
Map<String, dynamic> toJson() {
return {
'swipeTypeValue': swipeTypeValue,
'value': value,
'latitude': latitude,
'longitude': longitude,
};
}
}

@ -0,0 +1,47 @@
class SwipeTransaction {
final int id;
final String swipeTypeName;
final String userName;
final String siteName;
final String pointName;
final DateTime swipeTime;
final bool isSuccess;
final String errorMessage;
SwipeTransaction({
this.id,
this.swipeTypeName,
this.userName,
this.siteName,
this.pointName,
this.swipeTime,
this.isSuccess,
this.errorMessage,
});
factory SwipeTransaction.fromJson(Map<String, dynamic> json) {
return SwipeTransaction(
id: json['id'] as int,
swipeTypeName: json['swipeTypeName'] ,
userName: json['userName'] ,
siteName: json['siteName'] ,
pointName: json['pointName'] ,
swipeTime: DateTime.parse(json['swipeTime']),
isSuccess: json['isSuccess'] ,
errorMessage: json['errorMessage'] ,
);
}
// Map<String, dynamic> toJson() {
// return {
// 'id': id,
// 'swipeTypeName': swipeTypeName,
// 'userName': userName,
// 'siteName': siteName,
// 'pointName': pointName,
// 'swipeTime': swipeTime.toIso8601String(),
// 'isSuccess': isSuccess,
// 'errorMessage': errorMessage,
// };
// }
}

@ -0,0 +1,84 @@
import 'package:flutter/material.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
class NonHmgEmployeeSwipeView extends StatefulWidget {
NonHmgEmployeeSwipeView({Key key}) : super(key: key);
@override
_NonHmgEmployeeSwipeViewState createState() {
return _NonHmgEmployeeSwipeViewState();
}
}
class _NonHmgEmployeeSwipeViewState extends State<NonHmgEmployeeSwipeView> {
bool isNfcEnabled = false;
@override
void initState() {
super.initState();
checkForNfcAndLocationPermission();
}
void checkForNfcAndLocationPermission() async {
isNfcEnabled = await NfcManager.instance.isAvailable();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.all(16),
margin: const EdgeInsets.only(top: 21),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(30), color: Colors.white, border: Border.all(color: AppColor.white936.withOpacity(.05), width: 1)),
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Text(
"Mark Attendance",
style: AppTextStyles.heading5.copyWith(color: context.isDark ? AppColor.neutral30 : AppColor.neutral50),
),
GridView(
physics: const NeverScrollableScrollPhysics(),
shrinkWrap: true,
padding: const EdgeInsets.only(bottom: 0, top: 16),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: (MediaQuery.of(context).size.width < 550) ? 3 : 5, childAspectRatio: 1 / 1, crossAxisSpacing: 16, mainAxisSpacing: 16),
children: <Widget>[
gridItem("Nfc", Icons.nfc, isNfcEnabled).onPress(isNfcEnabled ? () {} : null),
gridItem("Qr Scan", Icons.qr_code, true).onPress(() {}),
],
)
],
),
);
}
Widget gridItem(String label, IconData iconData, bool enable) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(borderRadius: BorderRadius.circular(25), color: AppColor.white30, border: Border.all(color: AppColor.white936.withOpacity(.03), width: 1)),
alignment: Alignment.center,
child: Column(
//mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(iconData, color: enable ? AppColor.black35 : Colors.grey),
Text(
label,
style: AppTextStyles.heading6.copyWith(color: enable ? AppColor.black35 : Colors.grey),
),
],
),
);
}
}

@ -0,0 +1,116 @@
import 'package:flutter/material.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
class SwipeSuccessView extends StatelessWidget {
static const routeName = '/swipe_success_view';
const SwipeSuccessView({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:CrossAxisAlignment.center,
children: [
'swipe_success'.toSvgAsset(),
17.height,
context.translation.successful.heading4(context).custom(color: AppColor.neutral80),
8.height,
context.translation.youHaveSuccessfullyMarkedYourAttendance.bodyText2(context).custom(color: AppColor.white20),
],
),
),
);
}
}
class CircularAnimationWithProgressIndicator extends StatefulWidget {
Widget child;
CircularAnimationWithProgressIndicator({Key key, this.child}) : super(key: key);
@override
_CircularAnimationWithProgressIndicatorState createState() =>
_CircularAnimationWithProgressIndicatorState();
}
class _CircularAnimationWithProgressIndicatorState
extends State<CircularAnimationWithProgressIndicator>
with SingleTickerProviderStateMixin {
AnimationController _controller;
@override
void initState() {
super.initState();
// Animation controller for progress indicator
_controller = AnimationController(
vsync: this,
duration: const Duration(seconds: 40), // Duration of one full rotation
)..repeat(); // Repeat animation continuously
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Center(
child: Stack(
alignment: Alignment.center,
children: [
// Animated CircularProgressIndicator
AnimatedBuilder(
animation: _controller,
builder: (context, child) {
return Transform.rotate(
angle: _controller.value * 2 * 3.1416, // Full rotation
child: child,
);
},
child: SizedBox(
width: 120.toScreenHeight,
height: 120.toScreenWidth,
child: const CircularProgressIndicator(
strokeWidth: 3.0,
backgroundColor: AppColor.primary30,
value: null, // Infinite animation
),
),
),
// Static container in the center
widget.child?? const SizedBox(),
],
),
);
}
}
// ClipOval(
// child: Container(
// color: Colors.grey.withOpacity(0.2),
// padding: const EdgeInsets.all(10),
// child: ClipOval(
// child: Container(
// color: AppColor.white.withOpacity(0.2),
// padding: const EdgeInsets.all(10),
// child: ClipOval(
// child: Container(
// color: AppColor.white,
// child: 'success_swipe'.toSvgAsset().paddingAll(50),
// ),
// ).paddingAll(20),
// ),
// ),
// ),
// )

@ -0,0 +1,67 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:permission_handler/permission_handler.dart';
class LocationUtilities {
static void havePermission(Function(bool) callback) {
Geolocator.checkPermission().then((value) async {
if (value == LocationPermission.denied || value == LocationPermission.deniedForever) {
value = await Geolocator.requestPermission();
callback(![LocationPermission.denied, LocationPermission.deniedForever].contains(value));
} else {
callback(true);
}
});
}
static void isEnabled(Function(bool) callback) {
Geolocator.isLocationServiceEnabled().then((value) => callback(value));
}
static bool _listeningSettingChange = true;
static void listenGPS({bool change = true, Function(bool) onChange}) async {
_listeningSettingChange = change;
if (change == false) return;
Future.doWhile(() async {
await Future.delayed(const Duration(milliseconds: 1000));
var enable = await Geolocator.isLocationServiceEnabled();
onChange(enable);
return _listeningSettingChange;
});
}
static void locationFun(Function(bool) completion, BuildContext context) {
Permission.location.isGranted.then((isGranted) {
if (!isGranted) {
Permission.location.request().then((granted) {
completion(granted == PermissionStatus.granted);
});
}
completion(isGranted);
});
}
static void getCurrentLocation(Function(Position position, bool isMocked) callback, Function errorCallBack, BuildContext context) {
void done(Position position) {
//AppStorage.sp.saveLocation(position);
bool isMocked = position.isMocked;
callback(position, isMocked);
}
locationFun((granted) {
if (granted) {
Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.medium, timeLimit: const Duration(seconds: 5)).then((value) {
done(value);
}).catchError((err) {
errorCallBack();
});
} else {
// AppPermissions
}
}, context);
}
}

@ -0,0 +1,909 @@
import 'dart:async';
import 'dart:developer';
import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_api_availability/google_api_availability.dart';
import 'package:huawei_location/huawei_location.dart';
import 'package:intl/intl.dart';
import 'package:nfc_manager/nfc_manager.dart';
import 'package:nfc_manager/platform_tags.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:provider/provider.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:test_sa/controllers/providers/api/user_provider.dart';
import 'package:test_sa/extensions/context_extension.dart';
import 'package:test_sa/extensions/int_extensions.dart';
import 'package:test_sa/extensions/text_extensions.dart';
import 'package:test_sa/extensions/widget_extensions.dart';
import 'package:test_sa/main.dart';
import 'package:test_sa/new_views/app_style/app_color.dart';
import 'package:test_sa/new_views/common_widgets/app_lazy_loading.dart';
import 'package:test_sa/new_views/pages/land_page/nfc/nfc_reader_sheet.dart';
import 'package:test_sa/new_views/swipe_module/dialoge/confirm_dialog.dart';
import 'package:test_sa/new_views/swipe_module/dialoge/qr_scanner_dialog.dart';
import 'package:test_sa/new_views/swipe_module/enums/swipe_type.dart';
import 'package:test_sa/new_views/swipe_module/models/swipe_model.dart';
import 'package:test_sa/new_views/swipe_module/swipe_success_view.dart';
import 'package:test_sa/new_views/swipe_module/utils/location_utils.dart';
class SwipeGeneralUtils {
static bool _isLoadingVisible = false;
static bool get isLoading => _isLoadingVisible;
static void showToast(String message, {bool longDuration = true}) {
Fluttertoast.showToast(
msg: message,
toastLength: longDuration ? Toast.LENGTH_LONG : Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
timeInSecForIosWeb: 1,
backgroundColor: Colors.black54,
textColor: Colors.white,
fontSize: 13.0);
}
static dynamic getNotNullValue(List<dynamic> list, int index) {
try {
return list[index];
} catch (ex) {
return null;
}
}
static void markFakeAttendance(dynamic sourceName, String lat, String long, @required BuildContext context) async {
showLoading(context);
try {
hideLoading(navigatorKey.currentState.overlay.context);
confirmDialog(navigatorKey.currentState.overlay.context, "Fake Location)");
} catch (ex) {
log('$ex');
hideLoading(context);
//handleException(ex, context, null);
}
}
static int stringToHex(String colorCode) {
try {
return int.parse(colorCode.replaceAll("#", "0xff"));
} catch (ex) {
return (0xff000000);
}
}
static Future delay(int millis) async {
return await Future.delayed(Duration(milliseconds: millis));
}
static void showLoading(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_isLoadingVisible = true;
// showDialog(context: context, barrierDismissible: false, builder: (context) => const AppLazyLoading());
showDialog(
context: context,
barrierColor: Colors.black.withOpacity(0.5),
useRootNavigator: false,
builder: (BuildContext context) => const AppLazyLoading(),
).then((value) {
_isLoadingVisible = false;
});
});
}
static void hideLoading(BuildContext context) {
if (_isLoadingVisible) {
_isLoadingVisible = false;
Navigator.of(context).pop();
}
_isLoadingVisible = false;
}
static Future<String> getStringFromPrefs(String key) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(key) ?? "";
}
static Future<bool> removeStringFromPrefs(String key) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.remove(key);
}
static Future<bool> saveStringFromPrefs(String key, String value) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return await prefs.setString(key, value);
}
// static void handleException(dynamic exception, cxt, Function(String)? onErrorMessage) {
// String errorMessage;
// if (exception.error.errorType != null && exception.error.errorType == 4) {
// Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.appUpdateScreen, (_) => false, arguments: exception.error?.errorMessage);
// } else {
// if (exception is APIException) {
// if (exception.message == APIException.UNAUTHORIZED) {
// return;
// } else {
// errorMessage = exception.error?.errorMessage ?? exception.message;
// }
// } else {
// errorMessage = APIException.UNKNOWN;
// }
// if (onErrorMessage != null) {
// onErrorMessage(errorMessage);
// } else {
// if (!AppState().isAuthenticated) {
// showDialog(
// barrierDismissible: false,
// context: cxt,
// builder: (cxt) => ConfirmDialog(
// message: errorMessage,
// onTap: () {
// Navigator.pushNamedAndRemoveUntil(cxt, AppRoutes.login, (Route<dynamic> route) => false);
// },
// onCloseTap: () {},
// ),
// );
// } else {
// if (cxt != null) {
// confirmDialog(cxt, errorMessage);
// } else {
// showToast(errorMessage);
// }
// }
// }
// }
// }
//
// static Future showErrorDialog({required BuildContext context, required VoidCallback onOkTapped, required String message}) async {
// return showDialog(
// context: context,
// builder: (BuildContext context) => ConfirmDialog(
// message: message,
// onTap: onOkTapped,
// ),
// );
// }
//
static void confirmDialog(cxt, String message, {VoidCallback onTap}) {
showDialog(
context: cxt,
builder: (BuildContext cxt) => ConfirmDialog(
message: message,
onTap: onTap,
),
);
}
static void showErrorDialog({String message, @required BuildContext context}) {
showDialog(
context: context,
builder: (context) => ConfirmDialog(
message: message,
title: 'Error',
onTap: () => Navigator.pop(context),
),
);
}
static void showMDialog(context, {Widget child, Color backgroundColor, bool isDismissable = true, bool isBusniessCard = false}) async {
return showDialog(
context: context,
barrierDismissible: isDismissable,
builder: (context) {
return Dialog(
shape: isBusniessCard
? const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(15.0),
),
)
: null,
backgroundColor: backgroundColor,
child: child,
);
},
);
}
static Widget attendanceTypeCard(String title, String icon, bool isEnabled, VoidCallback onPress, BuildContext context) {
return Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(18),
border: Border.all(color: AppColor.white40, width: 2),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
icon.toSvgAsset(),
title.heading5(context).custom(color: AppColor.neutral50),
],
),
).onPress(
() {
log('isEnabled is ${!isEnabled}');
if (!isEnabled) return;
onPress();
},
);
// return Container(
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(15),
// color: isEnabled ? null : Colors.grey.withOpacity(.5),
// gradient: isEnabled
// ? const LinearGradient(
// transform: GradientRotation(.64),
// begin: Alignment.topRight,
// end: Alignment.bottomLeft,
// colors: [
// //ToDo set Colors according to design provided by designer...
// Colors.blue,
// Colors.green,
// // AppColor.gradiantEndColor,
// // MyColors.gradiantStartColor,
// ],
// )
// : null,
// ),
// clipBehavior: Clip.antiAlias,
// padding: const EdgeInsets.only(left: 10, right: 10, top: 14, bottom: 14),
// child: Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// children: [
// // SvgPicture.asset(image, color: Colors.white, alignment: Alignment.topLeft).expanded,
// Icon(iconData, color: isEnabled ? AppColor.black35 : Colors.grey),
// title.heading6(context),
// // title.toText17(isBold: true, color: Colors.white),
// ],
// ),
// ).onPress(
// () {
// log('isEnabled is ${!isEnabled}');
// if (!isEnabled) return;
// onPress();
// },
// );
}
//huawei permission part....
static void getHuaweiCurrentLocation({SwipeTypeEnum attendanceType, BuildContext context}) async {
try {
showLoading(context);
FusedLocationProviderClient locationService = FusedLocationProviderClient()..initFusedLocationService();
LocationRequest locationRequest = LocationRequest();
locationRequest.priority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
locationRequest.interval = 500;
List<LocationRequest> locationRequestList = <LocationRequest>[locationRequest];
LocationSettingsRequest locationSettingsRequest = LocationSettingsRequest(requests: locationRequestList);
StreamSubscription<Location> _streamSubscription;
int requestCode = (await (locationService.requestLocationUpdates(locationRequest)));
_streamSubscription = locationService.onLocationData.listen(
(Location location) async {
hideLoading(context);
await locationService.removeLocationUpdates(requestCode);
handleSwipeOperation(swipeType: attendanceType, context: context);
requestCode = 0;
},
);
// locationService.checkLocationSettings(locationSettingsRequest).then((settings) async {
// await locationService.getLastLocation().then((value) {
// if (value.latitude == null || value.longitude == null) {
// showDialog(
// context: context,
// builder: (BuildContext cxt) => ConfirmDialog(
// message: "Unable to get your location, Please check your location settings & try again.",
// onTap: () {
// Navigator.pop(context);
// },
// ),
// );
// } else {
// if (attendanceType == "QR") {
// performQrCodeAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
// }
// if (attendanceType == "WIFI") {
// performWifiAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
// }
// if (attendanceType == "NFC") {
// performNfcAttendance(widget.model, lat: value.latitude.toString() ?? "", lng: value.longitude.toString() ?? "");
// }
// }
// }).catchError((error) {
// log("HUAWEI LOCATION getLastLocation ERROR!!!!!");
// log(error);
// });
// }).catchError((error) {
// log("HUAWEI LOCATION checkLocationSettings ERROR!!!!!");
// log(error);
// if (error.code == "LOCATION_SETTINGS_NOT_AVAILABLE") {
// // Location service not enabled.
// }
// });
} catch (error) {
log("HUAWEI LOCATION ERROR!!!!!");
log('$error');
hideLoading(context);
// handleException(error, context, null);
}
}
static Future<bool> requestPermissions() async {
var result = await [
Permission.location,
].request();
return (result[Permission.location] == PermissionStatus.granted || result[Permission.locationAlways] == PermissionStatus.granted);
}
static void checkHuaweiLocationPermission({SwipeTypeEnum attendanceType, BuildContext context}) async {
// Permission_Handler permissionHandler = PermissionHandler();
LocationUtilities.isEnabled((bool isEnabled) async {
if (isEnabled) {
LocationUtilities.havePermission((bool permission) async {
if (permission) {
getHuaweiCurrentLocation(attendanceType: attendanceType, context: context);
} else {
bool has = await requestPermissions();
if (has) {
getHuaweiCurrentLocation(attendanceType: attendanceType, context: context);
} else {
showDialog(
context: context,
builder: (BuildContext cxt) => ConfirmDialog(
message: "You need to give location permission to mark attendance",
onTap: () {
Navigator.pop(context);
},
),
);
}
}
});
} else {
showDialog(
context: context,
builder: (BuildContext cxt) => ConfirmDialog(
message: "You need to enable location services to mark attendance",
onTap: () async {
Navigator.pop(context);
await Geolocator.openLocationSettings();
},
),
);
}
});
// if (await permissionHandler.hasLocationPermission()) {
// getHuaweiCurrentLocation(attendanceType);
// } else {
// bool has = await requestPermissions();
// if (has) {
// getHuaweiCurrentLocation(attendanceType);
// } else {
// showDialog(
// context: context,
// builder: (BuildContext cxt) => ConfirmDialog(
// message: "You need to give location permission to mark attendance",
// onTap: () {
// Navigator.pop(context);
// },
// ),
// );
// }
// }
}
// general methods......
static void handleSwipeOperation({@required SwipeTypeEnum swipeType, double lat, double lang, BuildContext context}) {
switch (swipeType) {
case SwipeTypeEnum.NFC:
handleNfcAttendance(latitude: lat, longitude: lang, context: context);
return;
case SwipeTypeEnum.QR:
performQrCodeAttendance(latitude: lat, longitude: lang, context: context);
return;
case SwipeTypeEnum.Wifi:
//TODO need to implement.
return;
}
}
static String formatTimeOnly(DateTime dateTime) {
return DateFormat.Hms().format(dateTime);
}
static Future<void> performQrCodeAttendance({double latitude, double longitude, BuildContext context}) async {
UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
var qrCodeValue = await Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context) => QrScannerDialog(),
),
);
if (qrCodeValue != null) {
showLoading(context);
try {
//test model..
final swipeModel = Swipe(
swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(),
value: '456',
latitude: 24.70865415364271,
longitude: 46.66600861881879,
);
// final swipeModel = Swipe(
// swipeTypeValue: SwipeTypeEnum.QR.getIntFromSwipeTypeEnum(),
// value: qrCodeValue,
// latitude: latitude,
// longitude: longitude,
// );
log('model i got to scan qr is ${swipeModel.toJson()}');
final swipeResponse = await userProvider.makeSwipe(model: swipeModel);
log('response of swipe is ${swipeResponse.toJson()}');
if (swipeResponse.isSuccess) {
hideLoading(context);
showSuccessDialog(context: context);
} else {
hideLoading(context);
showDialog(
barrierDismissible: true,
context: context,
builder: (cxt) => ConfirmDialog(
message: swipeResponse.message ?? "",
onTap: () {
Navigator.pop(context);
},
onCloseTap: () {},
),
);
}
} catch (ex) {
log('$ex');
hideLoading(context);
//this need to confirm where it comes..
// handleException(ex, context, null);
}
}
}
static Future<void> handleNfcAttendance({double latitude = 0, double longitude = 0, BuildContext context}) async {
// UserProvider _userProvider = Provider.of<UserProvider>(context,listen:false);
if (Platform.isIOS) {
readNFc(onRead: (String nfcId) async {
await _processNfcAttendance(nfcId, latitude, longitude, context);
});
} else {
showNfcReader(context, onNcfScan: (String nfcId) async {
await _processNfcAttendance(nfcId ?? '', latitude, longitude, context);
});
}
}
static Future<void> _processNfcAttendance(
String nfcId,
double latitude,
double longitude,
BuildContext context,
) async {
showLoading(context);
try {
// final swipeModel = Swipe(
// swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(),
// value: nfcId,
// latitude: latitude,
// longitude: longitude,
// );
UserProvider userProvider = Provider.of<UserProvider>(context, listen: false);
//Test model...
final swipeModel = Swipe(
swipeTypeValue: SwipeTypeEnum.NFC.getIntFromSwipeTypeEnum(),
value: '123',
latitude: 24.70865415364271,
longitude: 46.66600861881879,
);
final swipeResponse = await userProvider.makeSwipe(model: swipeModel);
if (swipeResponse.isSuccess) {
hideLoading(context);
showSuccessDialog(context: context, fromDashBoard: true);
} else {
hideLoading(context);
showErrorDialog(message: swipeResponse.message ?? "Unexpected error occurred", context: context);
}
} catch (errSwipeGeneralUtilsor) {
hideLoading(context);
// Uncomment below line for error handling if needed
// handleException(error, context, null);
}
}
static void handleSwipe({
SwipeTypeEnum swipeType,
@required bool isEnable,
@required BuildContext context,
}) async {
if (!(await isGoogleServicesAvailable())) {
checkHuaweiLocationPermission(attendanceType: swipeType, context: context);
} else {
LocationUtilities.isEnabled((bool isEnabled) {
if (isEnabled) {
LocationUtilities.havePermission((bool permission) {
if (permission) {
showLoading(context);
LocationUtilities.getCurrentLocation(
(Position position, bool isMocked) {
if (isMocked) {
hideLoading(context);
markFakeAttendance(swipeType.name, position.latitude.toString() ?? "", position.longitude.toString() ?? "", context);
} else {
hideLoading(context);
handleSwipeOperation(swipeType: swipeType, lat: position.latitude, lang: position.longitude, context: context);
}
},
() {
hideLoading(context);
confirmDialog(context, "Unable to determine your location, Please make sure that your location services are turned on & working.");
},
context,
);
} else {
showInfoDialog(
message: "You need to give location permission to mark attendance",
onTap: () async {
await Geolocator.openAppSettings();
});
}
});
} else {
showInfoDialog(
message: "You need to enable location services to mark attendance",
onTap: () async {
await Geolocator.openLocationSettings();
});
}
});
}
}
static void showInfoDialog({@required String message, VoidCallback onTap}) {
showDialog(
context: navigatorKey.currentState.overlay.context,
builder: (BuildContext cxt) => ConfirmDialog(
message: message,
onTap: () async {
Navigator.pop(navigatorKey.currentState.overlay.context);
onTap();
},
),
);
}
static List<Widget> availableAttendanceMethodList({@required BuildContext context, @required UserProvider userProvider, @required bool isNfcSupported}) {
List<Widget> availableMethods = [];
if (userProvider.user.enableNFC) {
availableMethods.add(attendanceTypeCard(SwipeTypeEnum.NFC.name, 'nfc_icon', userProvider.user.enableNFC, () {
handleSwipe(swipeType: SwipeTypeEnum.NFC, isEnable: userProvider.user.enableNFC, context: navigatorKey.currentState.overlay.context);
}, context));
}
if (userProvider.user.enableQR) {
availableMethods.add(attendanceTypeCard(SwipeTypeEnum.QR.name, 'qr', userProvider.user.enableQR, () {
handleSwipe(swipeType: SwipeTypeEnum.QR, isEnable: userProvider.user.enableQR, context: navigatorKey.currentState.overlay.context);
}, context));
}
if (userProvider.user.enableWifi) {
availableMethods.add(attendanceTypeCard(SwipeTypeEnum.Wifi.name, 'wifi_icon', userProvider.user.enableWifi, () {
handleSwipe(swipeType: SwipeTypeEnum.Wifi, isEnable: userProvider.user.enableWifi, context: navigatorKey.currentState.overlay.context);
}, context));
}
return availableMethods;
}
static Future<void> showSwipeTypeBottomSheetSheet({@required BuildContext context, @required bool isNfcSupported}) {
UserProvider _userProvider = Provider.of<UserProvider>(context, listen: false);
return showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(20),
),
),
clipBehavior: Clip.antiAliasWithSaveLayer,
builder: (BuildContext context) => Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
context.translation.markAttendance.heading4(context).custom(color: AppColor.neutral80),
8.height,
context.translation.selectMethodToMarkAttendance.bodyText2(context).custom(color: AppColor.white20),
12.height,
GridView(
padding: const EdgeInsets.all(0),
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3, childAspectRatio: 1, crossAxisSpacing: 12, mainAxisSpacing: 12),
children: availableAttendanceMethodList(context: context, userProvider: _userProvider, isNfcSupported: isNfcSupported)),
],
).paddingAll(16),
);
}
static void showSuccessDialog({@required BuildContext context, bool fromDashBoard}) {
Navigator.pushReplacementNamed(context, SwipeSuccessView.routeName);
// showMDialog(
// context,
// backgroundColor: Colors.transparent,
// isDismissable: true,
// child: SuccessDialog(fromDashBoard),
// );
}
static void readNFc({Function(String) onRead}) {
NfcManager.instance.startSession(onDiscovered: (NfcTag tag) async {
MifareUltralight f;
if (Platform.isAndroid) {
f = MifareUltralight(tag: tag, identifier: tag.data["nfca"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
} else {
f = MifareUltralight(tag: tag, identifier: tag.data["mifare"]["identifier"], type: 2, maxTransceiveLength: 252, timeout: 22);
}
String identifier = f.identifier.map((e) => e.toRadixString(16).padLeft(2, '0')).join('');
NfcManager.instance.stopSession();
onRead(identifier);
}).catchError((err) {
print(err);
});
}
//HUAWEI DECISION MAKING
static Future<bool> isGoogleServicesAvailable() async {
GooglePlayServicesAvailability availability = await GoogleApiAvailability.instance.checkGooglePlayServicesAvailability();
String status = availability.toString().split('.').last;
if (status == "success") {
return true;
}
return false;
}
//
// static bool isDate(String input, String format) {
// try {
// DateTime d = DateFormat(format).parseStrict(input);
// //print(d);
// return true;
// } catch (e) {
// //print(e);
// return false;
// }
// }
}
//
// static Widget getNoDataWidget(BuildContext context) {
// return Column(
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// SvgPicture.asset('assets/images/not_found.svg', width: 110.0, height: 110.0),
// LocaleKeys.noDataAvailable.tr().toText16().paddingOnly(top: 15),
// ],
// ).center;
// }
//
// static Widget getNoChatWidget(BuildContext context) {
// return Column(
// mainAxisAlignment: MainAxisAlignment.center,
// crossAxisAlignment: CrossAxisAlignment.center,
// children: [
// SvgPicture.asset('assets/images/not_found.svg', width: 110.0, height: 110.0),
// LocaleKeys.noDataAvailable.tr().toText16().paddingOnly(top: 15),
// ],
// ).center;
// }
//
// static Uint8List getPostBytes(img) {
// try {
// var b64 = img.replaceFirst('data:image/png;base64,', '');
// if (img != null && GeneralUtils.isBase64(b64)) return GeneralUtils.dataFromBase64String(b64);
// } catch (e) {}
// return Uint8List.fromList([]);
// }
//
// static String getBase64FromJpeg(img) {
// try {
// var b64 = img.replaceFirst('data:image/jpeg;base64,', '');
// return b64;
// } catch (e) {}
// return "";
// }
//
// static bool isBase64(String str) {
// RegExp _base64 = RegExp(r'^(?:[A-Za-z0-9+\/]{4})*(?:[A-Za-z0-9+\/]{2}==|[A-Za-z0-9+\/]{3}=|[A-Za-z0-9+\/]{4})$');
// return _base64.hasMatch(str);
// }
//
// static Uint8List dataFromBase64String(String base64String) {
// return base64Decode(base64String);
// }
//
// static Widget tableColumnTitle(String? text, {bool showDivider = true, bool alignCenter = false}) {
// text ??= "";
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisSize: MainAxisSize.min,
// children: [
// 6.height,
// alignCenter ? text.toText12().center : text.toText12(),
// 5.height,
// if (showDivider)
// const Divider(
// height: 1,
// color: Color(0xff2E303A),
// thickness: 1,
// )
// ],
// );
// }
//
// static Decoration containerRadius(Color background, double radius) {
// return BoxDecoration(
// color: background,
// border: Border.all(
// width: 1, //
// color: background // <--- border width here
// ),
// borderRadius: BorderRadius.circular(radius),
// );
// }
//
// static Widget mHeight(double h) {
// return Container(
// height: h,
// );
// }
//
// static Widget mDivider(Color color) {
// return Divider(
// // width: double.infinity,
// height: 1,
// color: color,
// );
// }
//
// static Widget tableColumnValue(String text, {bool isCapitable = true, bool alignCenter = false}) {
// return Column(
// crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisSize: MainAxisSize.min,
// children: [
// 12.height,
// if (alignCenter)
// (isCapitable ? text.toLowerCase().capitalizeFirstofEach : text).toText12(color: MyColors.normalTextColor).center
// else
// (isCapitable ? text.toLowerCase().capitalizeFirstofEach : text).toText12(color: MyColors.normalTextColor),
// 12.height,
// ],
// );
// }
//
// /// EIT Forms date formats
//
// static String getMonthNamedFormat(DateTime date) {
// /// it will return like "29-Sep-2022"
// return DateFormat('dd-MMM-yyyy', "en_US").format(date);
// }
//
// static String reverseFormatDate(String date) {
// String formattedDate;
// if (date.isNotEmpty) {
// formattedDate = date.replaceAll('/', '-');
// formattedDate = formattedDate.replaceAll(' 00:00:00', '');
// } else {
// formattedDate = date;
// }
// return formattedDate;
// }
//
// static String formatStandardDate(String date) {
// String formattedDate;
// if (date.isNotEmpty) {
// formattedDate = date.replaceAll('-', '/');
// } else {
// formattedDate = date;
// }
// return formattedDate;
// }
//
// static String reverseFormatStandardDate(String date) {
// String formattedDate;
// if (date.isNotEmpty) {
// formattedDate = date.replaceAll('/', '-');
// } else {
// formattedDate = date;
// }
// return formattedDate;
// }
//
// static String formatDate(String date) {
// String formattedDate;
//
// if (date.isNotEmpty) {
// date = date.substring(0, 10);
// formattedDate = date.replaceAll('-', '/');
// formattedDate = formattedDate + ' 00:00:00';
// } else {
// formattedDate = date;
// }
// return formattedDate;
// }
//
// static String formatDateNew(String date) {
// String formattedDate;
// if (date.isNotEmpty) {
// formattedDate = date.split('T')[0];
// if (!formattedDate.contains("00:00:00")) {
// formattedDate = formattedDate + ' 00:00:00';
// }
// } else {
// formattedDate = date;
// }
// return formattedDate;
// }
//
// static String formatDateDefault(String date) {
// if (date.isNotEmpty) {
// if (date.toLowerCase().contains("t")) {
// date = date.toLowerCase().split("t")[0];
// if (!date.contains("00:00:00")) {
// date = date + ' 00:00:00';
// }
// return date;
// } else {
// if (date.toLowerCase().split("-")[1].length == 3) {
// return DateFormat('dd-MM-yyyy', "en_US").format(DateFormat('dd-MMM-yyyy', "en_US").parseLoose(date));
// } else {
// return DateFormat('dd-MM-yyyy', "en_US").format(DateFormat('yyyy-MM-dd', "en_US").parseLoose(date));
// }
// // return DateFormat('yyyy-MM-dd').format(DateFormat('dd-MM-yyyy').parseLoose(date));
// }
// } else {
// return date;
// }
// }
//
// static Future<DateTime> selectDate(BuildContext context, DateTime selectedDate) async {
// if (!Platform.isIOS) {
// await showCupertinoModalPopup(
// context: context,
// builder: (BuildContext cxt) => Container(
// height: 250,
// color: Colors.white,
// child: CupertinoDatePicker(
// backgroundColor: Colors.white,
// mode: CupertinoDatePickerMode.date,
// onDateTimeChanged: (DateTime value) {
// if (value != null && value != selectedDate) {
// selectedDate = value;
// }
// },
// initialDateTime: selectedDate,
// ),
// ),
// );
// } else {
// DateTime? picked = await showDatePicker(context: context, initialDate: selectedDate, initialEntryMode: DatePickerEntryMode.calendarOnly, firstDate: DateTime(2015, 8), lastDate: DateTime(2101));
// if (picked != null && picked != selectedDate) {
// selectedDate = picked;
// }
// }
// return selectedDate;
// }

@ -33,6 +33,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.10.0"
audio_session:
dependency: transitive
description:
name: audio_session
sha256: "343e83bc7809fbda2591a49e525d6b63213ade10c76f15813be9aed6657b3261"
url: "https://pub.dev"
source: hosted
version: "0.1.21"
audioplayers:
dependency: "direct main"
description:
@ -541,6 +549,54 @@ packages:
url: "https://pub.dev"
source: hosted
version: "10.4.0"
geolocator:
dependency: "direct main"
description:
name: geolocator
sha256: "5c23f3613f50586c0bbb2b8f970240ae66b3bd992088cf60dd5ee2e6f7dde3a8"
url: "https://pub.dev"
source: hosted
version: "9.0.2"
geolocator_android:
dependency: transitive
description:
name: geolocator_android
sha256: "93906636752ea4d4e778afa981fdfe7409f545b3147046300df194330044d349"
url: "https://pub.dev"
source: hosted
version: "4.3.1"
geolocator_apple:
dependency: transitive
description:
name: geolocator_apple
sha256: "6154ea2682563f69fc0125762ed7e91e7ed85d0b9776595653be33918e064807"
url: "https://pub.dev"
source: hosted
version: "2.3.8+1"
geolocator_platform_interface:
dependency: transitive
description:
name: geolocator_platform_interface
sha256: b8cc1d3be0ca039a3f2174b0b026feab8af3610e220b8532e42cff8ec6658535
url: "https://pub.dev"
source: hosted
version: "4.1.0"
geolocator_web:
dependency: transitive
description:
name: geolocator_web
sha256: "102e7da05b48ca6bf0a5bda0010f886b171d1a08059f01bfe02addd0175ebece"
url: "https://pub.dev"
source: hosted
version: "2.2.1"
geolocator_windows:
dependency: transitive
description:
name: geolocator_windows
sha256: "4f4218f122a6978d0ad655fa3541eea74c67417440b09f0657238810d5af6bdc"
url: "https://pub.dev"
source: hosted
version: "0.1.3"
google_api_availability:
dependency: "direct main"
description:
@ -589,6 +645,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.2"
huawei_location:
dependency: "direct main"
description:
name: huawei_location
sha256: db937f0df4073ba6f3cdc1005855ee231aaf6bf5c2bd05a702d928d7e8bb4ee9
url: "https://pub.dev"
source: hosted
version: "6.12.0+303"
huawei_push:
dependency: "direct main"
description:
@ -717,6 +781,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.8.1"
just_audio:
dependency: "direct main"
description:
name: just_audio
sha256: b7cb6bbf3750caa924d03f432ba401ec300fd90936b3f73a9b33d58b1e96286b
url: "https://pub.dev"
source: hosted
version: "0.9.37"
just_audio_platform_interface:
dependency: transitive
description:
name: just_audio_platform_interface
sha256: "0243828cce503c8366cc2090cefb2b3c871aa8ed2f520670d76fd47aa1ab2790"
url: "https://pub.dev"
source: hosted
version: "4.3.0"
just_audio_web:
dependency: transitive
description:
name: just_audio_web
sha256: "134356b0fe3d898293102b33b5fd618831ffdc72bb7a1b726140abdf22772b70"
url: "https://pub.dev"
source: hosted
version: "0.4.9"
lints:
dependency: transitive
description:
@ -829,6 +917,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.0"
nfc_manager:
dependency: "direct main"
description:
name: nfc_manager
sha256: f5be75e90f8f2bff3ee49fbd7ef65bdd4a86ee679c2412e71ab2846a8cff8c59
url: "https://pub.dev"
source: hosted
version: "3.5.0"
octo_image:
dependency: transitive
description:
@ -981,6 +1077,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.1.0"
pinput:
dependency: "direct main"
description:
name: pinput
sha256: "7bf9aa7d0eeb3da9f7d49d2087c7bc7d36cd277d2e94cc31c6da52e1ebb048d0"
url: "https://pub.dev"
source: hosted
version: "5.0.0"
platform:
dependency: transitive
description:
@ -1069,6 +1173,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "0.27.7"
safe_device:
dependency: "direct main"
description:
name: safe_device
sha256: ae53e6ad4b7e3a9a89c3317636b52babd5916a6bf8c1e83ca82264cf82f6b2cc
url: "https://pub.dev"
source: hosted
version: "1.1.9"
share:
dependency: "direct main"
description:
@ -1306,6 +1418,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.2"
universal_platform:
dependency: transitive
description:
name: universal_platform
sha256: "64e16458a0ea9b99260ceb5467a214c1f298d647c659af1bff6d3bf82536b1ec"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
url_launcher:
dependency: "direct main"
description:
@ -1386,6 +1506,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
wifi_iot:
dependency: "direct main"
description:
name: wifi_iot
sha256: "4a3301f71663a908bb50ffe6d9dc9e8b8383fab48368accf978409bde96e9aca"
url: "https://pub.dev"
source: hosted
version: "0.3.19+1"
win32:
dependency: transitive
description:

@ -80,6 +80,13 @@ dependencies:
local_auth: ^2.1.6
google_api_availability: ^5.0.0
huawei_push: ^6.12.0+302
huawei_location: ^6.11.0+301
geolocator: ^9.0.2
nfc_manager: ^3.2.0
wifi_iot: ^0.3.19+1
just_audio: ^0.9.30
pinput:
safe_device: ^1.1.9
dev_dependencies:
flutter_test:
@ -113,6 +120,7 @@ flutter:
- assets/subtitles/
- assets/rives/
- assets/translations/
- assets/audio/
fonts:
- family: Swiss
fonts:

Loading…
Cancel
Save