Compare commits

..

3 Commits

Author SHA1 Message Date
aamir-csol 4f4db082fa Chat Bot Completed 2 weeks ago
aamir-csol f253a5e99e Chat Bot Completed 2 weeks ago
aamir-csol 234dce65e5 chat bot & Speech to Text 2 weeks ago

@ -30,6 +30,15 @@
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<queries>
<intent>
<action android:name="android.speech.RecognitionService" />
</intent>
</queries>
<application <application
android:allowBackup="false" android:allowBackup="false"
android:icon="@mipmap/ic_launcher" android:icon="@mipmap/ic_launcher"

@ -0,0 +1,46 @@
<svg width="74" height="74" viewBox="0 0 74 74" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_d_119_438)">
<rect x="17" y="17" width="40" height="40" rx="20" fill="url(#paint0_linear_119_438)"/>
</g>
<g filter="url(#filter1_d_119_438)">
<rect x="13" y="13" width="48" height="48" rx="24" fill="url(#paint1_linear_119_438)" fill-opacity="0.4" shape-rendering="crispEdges"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M41.9992 37.5291C40.7637 38.0552 39.4301 38.3796 38.0352 38.4637C37.7946 38.4782 37.5523 38.4856 37.3082 38.4856C37.0642 38.4856 36.8219 38.4782 36.5813 38.4637C35.1861 38.3796 33.8522 38.055 32.6165 37.5287C30.0232 36.4243 27.8623 34.4316 26.4749 31.9094C28.6373 27.9782 32.6791 25.3333 37.3082 25.3333C41.9374 25.3333 45.9792 27.9782 48.1416 31.9094C46.7541 34.4319 44.5928 36.4247 41.9992 37.5291Z" fill="white"/>
<path d="M32.6163 38.5525C32.3175 38.4253 32.0245 38.2863 31.7378 38.136C30.8058 38.8264 30.018 39.6862 29.4248 40.6673C30.4331 42.3347 32.0037 43.6522 33.8885 44.3824C34.7866 44.7303 35.7561 44.9449 36.7701 45.0005H37.8268C38.8406 44.9449 40.6224 46.0011 38.035 48.6666C39.9201 47.9364 44.1637 42.3349 45.1721 40.6673C44.5806 39.689 43.7956 38.8313 42.8671 38.1419C42.5837 38.29 42.2941 38.4272 41.999 38.5529C40.7635 39.079 39.4299 39.4034 38.035 39.4875C37.7945 39.502 37.5521 39.5093 37.3081 39.5093C37.0641 39.5093 36.8217 39.502 36.5811 39.4875C35.1859 39.4034 33.852 39.0788 32.6163 38.5525Z" fill="white"/>
<rect x="32.0844" y="30.2271" width="10.4705" height="3.93258" rx="1.96629" fill="#162550"/>
<ellipse cx="40.2071" cy="32.1717" rx="0.685571" ry="0.720974" fill="#04FED1"/>
<ellipse cx="37.2984" cy="41.8719" rx="0.685571" ry="0.720974" fill="#162550"/>
<ellipse cx="34.5566" cy="32.1717" rx="0.685571" ry="0.720974" fill="#04FED1"/>
<ellipse cx="34.5566" cy="41.8719" rx="0.685571" ry="0.720974" fill="#162550"/>
<ellipse cx="40.0411" cy="41.8719" rx="0.685571" ry="0.720974" fill="#162550"/>
<defs>
<filter id="filter0_d_119_438" x="4" y="4" width="66" height="66" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6.5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0784314 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_119_438"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_119_438" result="shape"/>
</filter>
<filter id="filter1_d_119_438" x="0" y="0" width="74" height="74" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="6.5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.0784314 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_119_438"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_119_438" result="shape"/>
</filter>
<linearGradient id="paint0_linear_119_438" x1="-12.3178" y1="86.2302" x2="-12.3178" y2="18.3971" gradientUnits="userSpaceOnUse">
<stop offset="1" stop-color="#259CB8"/>
<stop stop-color="#32D892"/>
</linearGradient>
<linearGradient id="paint1_linear_119_438" x1="-22.1814" y1="96.0762" x2="-22.1814" y2="14.6765" gradientUnits="userSpaceOnUse">
<stop offset="1" stop-color="#259CB8"/>
<stop stop-color="#32D892"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

@ -0,0 +1,12 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_120_1007)">
<path d="M13.125 5C13.125 3.27411 11.7259 1.875 10 1.875C8.27411 1.875 6.875 3.27411 6.875 5V10C6.875 11.7259 8.27411 13.125 10 13.125C11.7259 13.125 13.125 11.7259 13.125 10V5Z" stroke="#697586" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M10 15.625V18.75" stroke="#697586" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M15.625 10C15.625 11.4918 15.0324 12.9226 13.9775 13.9775C12.9226 15.0324 11.4918 15.625 10 15.625C8.50816 15.625 7.07742 15.0324 6.02252 13.9775C4.96763 12.9226 4.375 11.4918 4.375 10" stroke="#697586" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</g>
<defs>
<clipPath id="clip0_120_1007">
<rect width="20" height="20" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 903 B

@ -0,0 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.8744 6.13098L7.58175 10.4694L2.69958 7.41575C2.00006 6.97811 2.14558 5.91558 2.93679 5.6842L14.5284 2.28958C15.253 2.07722 15.9244 2.75462 15.7092 3.4815L12.2798 15.0651C12.0448 15.8574 10.9884 15.999 10.5549 15.2965L7.5795 10.4701" stroke="#0D121C" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 434 B

@ -1,4 +0,0 @@
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M17.3339 15.9992H13.3339V11.1992C13.3339 10.9365 13.3343 10.7929 13.34 10.6886L13.341 10.673L13.3565 10.6721C13.4609 10.6664 13.6045 10.6659 13.8672 10.6659H17.3339C18.8066 10.6659 20.0005 11.8598 20.0005 13.3326C20.0005 14.8053 18.8066 15.9992 17.3339 15.9992Z" fill="#2E3039"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.0684 2.33203H15.9316C13.1698 2.33202 11.005 2.33201 9.30102 2.53899C7.55973 2.75051 6.16606 3.19084 5.02088 4.16892C4.71548 4.42976 4.43104 4.71419 4.1702 5.0196C3.19212 6.16478 2.75179 7.55845 2.54027 9.29974C2.33329 11.0037 2.3333 13.1684 2.33331 15.9304V16.067C2.3333 18.829 2.33329 20.9937 2.54027 22.6977C2.75179 24.4389 3.19212 25.8326 4.1702 26.9778C4.43104 27.2832 4.71547 27.5676 5.02088 27.8285C6.16606 28.8066 7.55973 29.2469 9.30102 29.4584C11.005 29.6654 13.1697 29.6654 15.9316 29.6654H16.0683C18.8302 29.6654 20.995 29.6654 22.6989 29.4584C24.4402 29.2469 25.8339 28.8066 26.9791 27.8285C27.2845 27.5676 27.5689 27.2832 27.8298 26.9778C28.8078 25.8326 29.2482 24.4389 29.4597 22.6977C29.6667 20.9937 29.6667 18.829 29.6666 16.067V15.9304C29.6667 13.1684 29.6667 11.0037 29.4597 9.29974C29.2482 7.55845 28.8078 6.16478 27.8298 5.0196C27.5689 4.71419 27.2845 4.42976 26.9791 4.16892C25.8339 3.19084 24.4402 2.75051 22.6989 2.53899C20.995 2.33201 18.8303 2.33202 16.0684 2.33203ZM13.8672 7.99925L13.7592 7.99898C13.3835 7.99761 12.9217 7.99593 12.5098 8.12976C11.698 8.39355 11.0615 9.03003 10.7977 9.84187C10.6639 10.2538 10.6656 10.7156 10.6669 11.0913L10.6672 11.1992V23.9993C10.6672 24.7356 11.2642 25.3326 12.0005 25.3326C12.7369 25.3326 13.3339 24.7356 13.3339 23.9993V18.6659H17.3339C20.2794 18.6659 22.6672 16.2781 22.6672 13.3326C22.6672 10.3871 20.2794 7.99925 17.3339 7.99925H13.8672Z" fill="#2E3039"/>
</svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

@ -642,6 +642,5 @@
"yearsUsed": "سنوات الاستخدام", "yearsUsed": "سنوات الاستخدام",
"faRequest": "طلب التخلص من FA", "faRequest": "طلب التخلص من FA",
"showMore": "عرض المزيد", "showMore": "عرض المزيد",
"buyerDetails": "تفاصيل المشتري", "buyerDetails": "تفاصيل المشتري"
"parkingQr": "وقوف السيارات QR"
} }

@ -640,6 +640,5 @@
"yearsUsed": "Years Used", "yearsUsed": "Years Used",
"faRequest":"FA Disposal Request", "faRequest":"FA Disposal Request",
"showMore": "Show More", "showMore": "Show More",
"buyerDetails": "Buyer Details", "buyerDetails": "Buyer Details"
"parkingQr": "Parking QR"
} }

@ -56,7 +56,9 @@
<key>NSLocationWhenInUseUsageDescription</key> <key>NSLocationWhenInUseUsageDescription</key>
<string>This App requires access to your location to mark your attendance.</string> <string>This App requires access to your location to mark your attendance.</string>
<key>NSMicrophoneUsageDescription</key> <key>NSMicrophoneUsageDescription</key>
<string>This app requires microphone access to for call.</string> <string>This app requires microphone access for calls and speech-to-text input.</string>
<key>NSSpeechRecognitionUsageDescription</key>
<string>This app requires speech recognition to convert your voice to text.</string>
<key>NSPhotoLibraryUsageDescription</key> <key>NSPhotoLibraryUsageDescription</key>
<string>This app requires photo library access to select image as document &amp; upload it.</string> <string>This app requires photo library access to select image as document &amp; upload it.</string>
<key>UIApplicationSupportsIndirectInputEvents</key> <key>UIApplicationSupportsIndirectInputEvents</key>

@ -16,7 +16,6 @@ import 'package:mohem_flutter_app/models/dashboard/get_attendance_tracking_list_
import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart'; import 'package:mohem_flutter_app/models/dashboard/itg_forms_model.dart';
import 'package:mohem_flutter_app/models/dashboard/list_menu.dart'; import 'package:mohem_flutter_app/models/dashboard/list_menu.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart'; import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:mohem_flutter_app/models/get_employee_parking_details_model.dart';
import 'package:mohem_flutter_app/models/itg/itg_main_response.dart'; import 'package:mohem_flutter_app/models/itg/itg_main_response.dart';
import 'package:mohem_flutter_app/models/itg/itg_response_model.dart'; import 'package:mohem_flutter_app/models/itg/itg_response_model.dart';
import 'package:mohem_flutter_app/models/sso_auth_model.dart'; import 'package:mohem_flutter_app/models/sso_auth_model.dart';
@ -227,9 +226,9 @@ class DashboardApiClient {
} }
Future<dynamic> getBookingSSOFinalRedirection({required String token}) async { Future<dynamic> getBookingSSOFinalRedirection({required String token}) async {
// token = token =
// "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhjZTE2OWM0YjIwYjQ2ZWM5YTQyOTU3Y2ZhODUzNzQ1IiwidHlwIjoiSldUIn0.eyJ0ZW5hbnRfaWQiOiJhOWY0ZDFhMDU5NmQ0YWVhOGY4MzA5OTJlYzRiZGFjMSIsImVpZCI6IjExNzkzMCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3NpZCI6Ijk2MDI0OGM1NzA3YzQ3MmFhYTEzM2I1N2ZhODE1ZmVhIiwibGFuZ3VhZ2UiOiJVUyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI6IjExNzkzMEBobWcuY29tIiwiZXhwIjoxNzgyNDc1NzY5LCJpc3MiOiJodHRwczovL3Nzby11YXQuaG1nLmNvbSIsImF1ZCI6ImE5ZjRkMWEwNTk2ZDRhZWE4ZjgzMDk5MmVjNGJkYWMxIn0.rJcLVsG8D0XECyLERCTD2uqGeWyvp-OBVGE9uL2qKrX4etFUHgdFt_5kYF6edFTtGy-0PIZadHDmv7e-IOhVWHm5HVMClaukiXoRXR8cDN8XA1wfme3Kd-U5PXN-IRh49AyRTzLO0rYNPvH81ScosWGlsFSkOvA-0hJNa2adHdtvgNvB8wJshSU5p7sAmF8mjdDY6aInG19etu2iEuUDwHHA4ZY_ts4hboHo8fE392hFaYGonExoD7bpW5RMx5xKWeRCmWpG_PK8Aw_z1jGzdB9PANus4pteRGuln1J-kmo2lQC9pVrSyZATAKp1HfgfyZ_vUhaHEfM69cMWaCslJQ"; "eyJhbGciOiJSUzI1NiIsImtpZCI6IjhjZTE2OWM0YjIwYjQ2ZWM5YTQyOTU3Y2ZhODUzNzQ1IiwidHlwIjoiSldUIn0.eyJ0ZW5hbnRfaWQiOiJhOWY0ZDFhMDU5NmQ0YWVhOGY4MzA5OTJlYzRiZGFjMSIsImVpZCI6IjExNzkzMCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL3NpZCI6Ijk2MDI0OGM1NzA3YzQ3MmFhYTEzM2I1N2ZhODE1ZmVhIiwibGFuZ3VhZ2UiOiJVUyIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL2VtYWlsYWRkcmVzcyI6IjExNzkzMEBobWcuY29tIiwiZXhwIjoxNzgyNDc1NzY5LCJpc3MiOiJodHRwczovL3Nzby11YXQuaG1nLmNvbSIsImF1ZCI6ImE5ZjRkMWEwNTk2ZDRhZWE4ZjgzMDk5MmVjNGJkYWMxIn0.rJcLVsG8D0XECyLERCTD2uqGeWyvp-OBVGE9uL2qKrX4etFUHgdFt_5kYF6edFTtGy-0PIZadHDmv7e-IOhVWHm5HVMClaukiXoRXR8cDN8XA1wfme3Kd-U5PXN-IRh49AyRTzLO0rYNPvH81ScosWGlsFSkOvA-0hJNa2adHdtvgNvB8wJshSU5p7sAmF8mjdDY6aInG19etu2iEuUDwHHA4ZY_ts4hboHo8fE392hFaYGonExoD7bpW5RMx5xKWeRCmWpG_PK8Aw_z1jGzdB9PANus4pteRGuln1J-kmo2lQC9pVrSyZATAKp1HfgfyZ_vUhaHEfM69cMWaCslJQ";
// // var request = http.MultipartRequest('POST', Uri.parse('https://ek.techmaster.in/SSO/HMG')); // var request = http.MultipartRequest('POST', Uri.parse('https://ek.techmaster.in/SSO/HMG'));
var request = http.MultipartRequest('POST', Uri.parse('https://Paxes-release.techmaster.in/SSO/HMG')); var request = http.MultipartRequest('POST', Uri.parse('https://Paxes-release.techmaster.in/SSO/HMG'));
request.fields.addAll({'JWTToken': token}); request.fields.addAll({'JWTToken': token});
@ -416,13 +415,27 @@ class DashboardApiClient {
// ); // );
// } // }
Future<GetEmployeeParking?> getEmployeeParkingQrCode() async { Future<GenericResponseModel?> getChatBotSession() async {
String url = "${ApiConsts.erpRest}GET_Employee_Parking"; String url = "${ApiConsts.erpRest}Atlas_InitiateChat";
Map<String, dynamic> postParams = {}; Map<String, dynamic> postParams = {};
postParams.addAll(AppState().postParamsJson); postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject( return await ApiClient().postJsonForObject(
(json) { (json) {
GetEmployeeParking responseData = GetEmployeeParking.fromJson(json); GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData;
},
url,
postParams,
);
}
Future<GenericResponseModel?> sendChatBotMessage({required AtlasInitiateChatResponse atlasChatTokenResponse, required String atlasChatText}) async {
String url = "${ApiConsts.erpRest}Atlas_ContinueChat";
Map<String, dynamic> postParams = <String, dynamic>{"Atlas_AccessToken": atlasChatTokenResponse.atlasAccessToken, "Atlas_ChatSessionID": atlasChatTokenResponse.atlasChatSessionId, "Atlas_ChatText": atlasChatText};
postParams.addAll(AppState().postParamsJson);
return await ApiClient().postJsonForObject(
(json) {
GenericResponseModel responseData = GenericResponseModel.fromJson(json);
return responseData; return responseData;
}, },
url, url,

@ -67,4 +67,5 @@ class MyColors {
static const Color lightGreyIconColor = Color(0xff919191); static const Color lightGreyIconColor = Color(0xff919191);
static const Color selectedBorderColor = Color(0xff37A4BE); static const Color selectedBorderColor = Color(0xff37A4BE);
static const Color mazayaRedColor = Color(0xffED1C2B); static const Color mazayaRedColor = Color(0xffED1C2B);
static const Color hintTextColor = Color(0xff9AA4B2);
} }

@ -4,14 +4,14 @@ class ApiConsts {
// static String baseUrl = "http://10.200.204.11"; // Local server // static String baseUrl = "http://10.200.204.11"; // Local server
// static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server // static String baseUrl = "https://erptstapp.srca.org.sa"; // SRCA server
static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver // static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver
// static String baseUrl = "http://10.201.204.101:2024"; // static String baseUrl = "http://10.201.204.101:2024";
// static String baseUrl = "https://webservices.hmg.com"; // PreProd // static String baseUrl = "https://webservices.hmg.com"; // PreProd
// static String baseUrl = "https://hmgwebservices.com"; // Live server // static String baseUrl = "https://hmgwebservices.com"; // Live server
// static String baseUrl = "https://mohemm.hmg.com"; // New Live server // static String baseUrl = "https://mohemm.hmg.com"; // New Live server
// //
// static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver static String baseUrl = "https://uat.hmgwebservices.com"; // UAT ser343622ver
// static String baseUrl = "http://10.20.200.111:1010/"; // static String baseUrl = "http://10.20.200.111:1010/";
// static String baseUrl = "https://webservices.hmg.com"; // PreProd // static String baseUrl = "https://webservices.hmg.com"; // PreProd

@ -10,6 +10,7 @@ import 'package:mohem_flutter_app/ui/chat/favorite_users_screen.dart';
import 'package:mohem_flutter_app/ui/chat/group_chat_detaied_screen.dart'; import 'package:mohem_flutter_app/ui/chat/group_chat_detaied_screen.dart';
import 'package:mohem_flutter_app/ui/chat/group_members.dart'; import 'package:mohem_flutter_app/ui/chat/group_members.dart';
import 'package:mohem_flutter_app/ui/chat/manage_group.dart'; import 'package:mohem_flutter_app/ui/chat/manage_group.dart';
import 'package:mohem_flutter_app/ui/chatbot/chatbot_screen.dart';
import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart'; import 'package:mohem_flutter_app/ui/landing/dashboard_screen.dart';
import 'package:mohem_flutter_app/ui/landing/itg/change_itg_ad_password_screen.dart'; import 'package:mohem_flutter_app/ui/landing/itg/change_itg_ad_password_screen.dart';
import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart'; import 'package:mohem_flutter_app/ui/landing/itg/its_add_screen_video_image.dart';
@ -32,6 +33,7 @@ import 'package:mohem_flutter_app/ui/misc/request_submit_screen.dart';
import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_input_screen.dart';
import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart'; import 'package:mohem_flutter_app/ui/my_attendance/dynamic_screens/dynamic_listview_screen.dart';
import 'package:mohem_flutter_app/ui/my_attendance/services_menu_list_screen.dart'; import 'package:mohem_flutter_app/ui/my_attendance/services_menu_list_screen.dart';
// import 'package:mohem_flutter_app/ui/my_attendance/my_attendance_screen.dart'; // import 'package:mohem_flutter_app/ui/my_attendance/my_attendance_screen.dart';
import 'package:mohem_flutter_app/ui/my_team/create_request.dart'; import 'package:mohem_flutter_app/ui/my_team/create_request.dart';
import 'package:mohem_flutter_app/ui/my_team/employee_details.dart'; import 'package:mohem_flutter_app/ui/my_team/employee_details.dart';
@ -40,7 +42,6 @@ import 'package:mohem_flutter_app/ui/my_team/profile_details.dart';
import 'package:mohem_flutter_app/ui/my_team/subordinate_leave.dart'; import 'package:mohem_flutter_app/ui/my_team/subordinate_leave.dart';
import 'package:mohem_flutter_app/ui/my_team/team_members.dart'; import 'package:mohem_flutter_app/ui/my_team/team_members.dart';
import 'package:mohem_flutter_app/ui/my_team/view_attendance.dart'; import 'package:mohem_flutter_app/ui/my_team/view_attendance.dart';
import 'package:mohem_flutter_app/ui/parking_qr/parking_qr.dart';
import 'package:mohem_flutter_app/ui/payslip/monthly_pay_slip_screen.dart'; import 'package:mohem_flutter_app/ui/payslip/monthly_pay_slip_screen.dart';
import 'package:mohem_flutter_app/ui/performance/performance_appraisal_screen.dart'; import 'package:mohem_flutter_app/ui/performance/performance_appraisal_screen.dart';
import 'package:mohem_flutter_app/ui/profile/add_update_family_member.dart'; import 'package:mohem_flutter_app/ui/profile/add_update_family_member.dart';
@ -55,6 +56,7 @@ import 'package:mohem_flutter_app/ui/profile/profile_screen.dart';
import 'package:mohem_flutter_app/ui/screens/announcements/announcement_details.dart'; import 'package:mohem_flutter_app/ui/screens/announcements/announcement_details.dart';
import 'package:mohem_flutter_app/ui/screens/announcements/announcements.dart'; import 'package:mohem_flutter_app/ui/screens/announcements/announcements.dart';
import 'package:mohem_flutter_app/ui/screens/child_education/child_education_assistance.dart'; import 'package:mohem_flutter_app/ui/screens/child_education/child_education_assistance.dart';
// import 'package:mohem_flutter_app/ui/my_attendance/work_from_home_screen.dart'; // import 'package:mohem_flutter_app/ui/my_attendance/work_from_home_screen.dart';
import 'package:mohem_flutter_app/ui/screens/eit/add_eit.dart'; import 'package:mohem_flutter_app/ui/screens/eit/add_eit.dart';
import 'package:mohem_flutter_app/ui/screens/event_activity/event_activity.dart'; import 'package:mohem_flutter_app/ui/screens/event_activity/event_activity.dart';
@ -192,6 +194,7 @@ class AppRoutes {
static const String chat = "/chat"; static const String chat = "/chat";
static const String chatDetailed = "/chatDetailed"; static const String chatDetailed = "/chatDetailed";
static const String chatFavoriteUsers = "/chatFavoriteUsers"; static const String chatFavoriteUsers = "/chatFavoriteUsers";
static const String chatBotHome = "/chatBotHome";
//Group Chat //Group Chat
static const String manageGroup = "/manageGroup"; static const String manageGroup = "/manageGroup";
@ -212,9 +215,6 @@ class AppRoutes {
static const String activityScreen = "/activityScreen"; static const String activityScreen = "/activityScreen";
//Parking QR
static const String parkingQr = "/parkingQrScreen";
static final Map<String, WidgetBuilder> routes = { static final Map<String, WidgetBuilder> routes = {
login: (BuildContext context) => LoginScreen(), login: (BuildContext context) => LoginScreen(),
verifyLogin: (BuildContext context) => VerifyLoginScreen(), verifyLogin: (BuildContext context) => VerifyLoginScreen(),
@ -227,8 +227,8 @@ class AppRoutes {
newPassword: (BuildContext context) => NewPasswordScreen(), newPassword: (BuildContext context) => NewPasswordScreen(),
forgotPassword: (BuildContext context) => ForgotPasswordScreen(), forgotPassword: (BuildContext context) => ForgotPasswordScreen(),
todayAttendance: (BuildContext context) => TodayAttendanceScreen2(), todayAttendance: (BuildContext context) => TodayAttendanceScreen2(),
//eit
//eit
addEitScreen: (BuildContext context) => AddEITScreen(), addEitScreen: (BuildContext context) => AddEITScreen(),
//Work List //Work List
@ -239,7 +239,6 @@ class AppRoutes {
worklistSettings: (BuildContext context) => WorklistSettings(), worklistSettings: (BuildContext context) => WorklistSettings(),
// Leave Balance // Leave Balance
leaveBalance: (BuildContext context) => LeaveBalance(), leaveBalance: (BuildContext context) => LeaveBalance(),
addLeaveBalance: (BuildContext context) => AddLeaveBalanceScreen(), addLeaveBalance: (BuildContext context) => AddLeaveBalanceScreen(),
@ -316,6 +315,7 @@ class AppRoutes {
chat: (BuildContext context) => ChatHome(), chat: (BuildContext context) => ChatHome(),
chatDetailed: (BuildContext context) => ChatDetailScreen(), chatDetailed: (BuildContext context) => ChatDetailScreen(),
chatFavoriteUsers: (BuildContext context) => ChatFavoriteUsersScreen(), chatFavoriteUsers: (BuildContext context) => ChatFavoriteUsersScreen(),
chatBotHome: (BuildContext context) => ChatBotScreen(),
//Group Chat //Group Chat
manageGroup: (BuildContext context) => ManageGroupScreen(), manageGroup: (BuildContext context) => ManageGroupScreen(),
@ -332,10 +332,6 @@ class AppRoutes {
unsafeDeviceScreen: (BuildContext context) => const UnsafeDeviceScreen(), unsafeDeviceScreen: (BuildContext context) => const UnsafeDeviceScreen(),
appUpdateScreen: (BuildContext context) => const AppUpdateScreen(), appUpdateScreen: (BuildContext context) => const AppUpdateScreen(),
childEducation: (BuildContext context) => ChildEducationAssistance(), childEducation: (BuildContext context) => ChildEducationAssistance(),
activityScreen:(BuildContext context) => const EventActivityScreen(), activityScreen: (BuildContext context) => const EventActivityScreen(),
//Parking QR
parkingQr: (BuildContext context) => const ParkingQrScreen(),
}; };
} }

@ -655,8 +655,7 @@ class CodegenLoader extends AssetLoader{
"yearsUsed": "سنوات الاستخدام", "yearsUsed": "سنوات الاستخدام",
"faRequest": "طلب التخلص من FA", "faRequest": "طلب التخلص من FA",
"showMore": "عرض المزيد", "showMore": "عرض المزيد",
"buyerDetails": "تفاصيل المشتري", "buyerDetails": "تفاصيل المشتري"
"parkingQr": "وقوف السيارات QR"
}; };
static const Map<String,dynamic> _en_US = { static const Map<String,dynamic> _en_US = {
"mohemm": "Mohemm", "mohemm": "Mohemm",
@ -1299,8 +1298,7 @@ static const Map<String,dynamic> _en_US = {
"yearsUsed": "Years Used", "yearsUsed": "Years Used",
"faRequest": "FA Disposal Request", "faRequest": "FA Disposal Request",
"showMore": "Show More", "showMore": "Show More",
"buyerDetails": "Buyer Details", "buyerDetails": "Buyer Details"
"parkingQr": "Parking QR"
}; };
static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": _ar_SA, "en_US": _en_US}; static const Map<String, Map<String,dynamic>> mapLocales = {"ar_SA": _ar_SA, "en_US": _en_US};
} }

@ -628,6 +628,5 @@ abstract class LocaleKeys {
static const faRequest = 'faRequest'; static const faRequest = 'faRequest';
static const showMore = 'showMore'; static const showMore = 'showMore';
static const buyerDetails = 'buyerDetails'; static const buyerDetails = 'buyerDetails';
static const parkingQr = 'parkingQr';
} }

@ -398,6 +398,9 @@ class GenericResponseModel {
bool? isActiveCode; bool? isActiveCode;
bool? isSMSSent; bool? isSMSSent;
PortalDirectionData? portalDirectionData; PortalDirectionData? portalDirectionData;
AtlasInitiateChatResponse? atlasInitiateChatResponse;
AtlasContinueChatResponseDetails? atlasContinueChatResponseDetails;
GenericResponseModel({ GenericResponseModel({
this.date, this.date,
@ -669,7 +672,10 @@ class GenericResponseModel {
this.ePharmacyGetItemOnHandList, this.ePharmacyGetItemOnHandList,
this.isActiveCode, this.isActiveCode,
this.isSMSSent, this.isSMSSent,
this.getFADisposalNtfDetails this.getFADisposalNtfDetails,
this.atlasInitiateChatResponse,
this.atlasContinueChatResponseDetails,
}); });
GenericResponseModel.fromJson(Map<String, dynamic> json) { GenericResponseModel.fromJson(Map<String, dynamic> json) {
@ -943,7 +949,6 @@ class GenericResponseModel {
getFADisposalNtfDetails = json['GetFADisposalNtfDetails'] != null ? GetFaDisposalNtfDetails.fromJson(json['GetFADisposalNtfDetails']) : null; getFADisposalNtfDetails = json['GetFADisposalNtfDetails'] != null ? GetFaDisposalNtfDetails.fromJson(json['GetFADisposalNtfDetails']) : null;
if (json['GetEarningsList'] != null) { if (json['GetEarningsList'] != null) {
getEarningsList = <GetEarningsList>[]; getEarningsList = <GetEarningsList>[];
json['GetEarningsList'].forEach((v) { json['GetEarningsList'].forEach((v) {
@ -1464,6 +1469,10 @@ class GenericResponseModel {
ePharmacyGetItemOnHandList = json['ePharmacy_GetItemOnHandList']; ePharmacyGetItemOnHandList = json['ePharmacy_GetItemOnHandList'];
isActiveCode = json['isActiveCode']; isActiveCode = json['isActiveCode'];
isSMSSent = json['isSMSSent']; isSMSSent = json['isSMSSent'];
atlasInitiateChatResponse = json["Atlas_InitiateChat_Response"] == null ? null : AtlasInitiateChatResponse.fromJson(json["Atlas_InitiateChat_Response"]);
atlasContinueChatResponseDetails = json["Atlas_ContinueChat_ResponseDetails"] == null ? null : AtlasContinueChatResponseDetails.fromJson(json["Atlas_ContinueChat_ResponseDetails"]);
} }
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
@ -1561,7 +1570,7 @@ class GenericResponseModel {
if (this.getActionHistoryList != null) { if (this.getActionHistoryList != null) {
data['GetActionHistoryList'] = this.getActionHistoryList!.map((v) => v.toJson()).toList(); data['GetActionHistoryList'] = this.getActionHistoryList!.map((v) => v.toJson()).toList();
} }
data['GetFADisposalNtfDetails'] =this.getFADisposalNtfDetails; data['GetFADisposalNtfDetails'] = this.getFADisposalNtfDetails;
data['GetAddressDffStructureList'] = this.getAddressDffStructureList; data['GetAddressDffStructureList'] = this.getAddressDffStructureList;
data['GetAddressNotificationBodyList'] = this.getAddressNotificationBodyList; data['GetAddressNotificationBodyList'] = this.getAddressNotificationBodyList;
@ -1949,6 +1958,9 @@ class GenericResponseModel {
data['ePharmacy_GetItemOnHandList'] = this.ePharmacyGetItemOnHandList; data['ePharmacy_GetItemOnHandList'] = this.ePharmacyGetItemOnHandList;
data['isActiveCode'] = this.isActiveCode; data['isActiveCode'] = this.isActiveCode;
data['isSMSSent'] = this.isSMSSent; data['isSMSSent'] = this.isSMSSent;
data["Atlas_InitiateChat_Response"] = atlasInitiateChatResponse?.toJson();
data["Atlas_ContinueChat_ResponseDetails"] = atlasContinueChatResponseDetails?.toJson();
return data; return data;
} }
} }
@ -1974,3 +1986,138 @@ class TicketBookingResult {
TicketBookingResult(this.success, this.clientId); TicketBookingResult(this.success, this.clientId);
} }
class AtlasInitiateChatResponse {
String? atlasAccessToken;
String? atlasChatSessionId;
String? atlasTokenType;
AtlasInitiateChatResponse({this.atlasAccessToken, this.atlasChatSessionId, this.atlasTokenType});
factory AtlasInitiateChatResponse.fromRawJson(String str) => AtlasInitiateChatResponse.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory AtlasInitiateChatResponse.fromJson(Map<String, dynamic> json) =>
AtlasInitiateChatResponse(atlasAccessToken: json["Atlas_AccessToken"], atlasChatSessionId: json["Atlas_ChatSessionID"], atlasTokenType: json["Atlas_TokenType"]);
Map<String, dynamic> toJson() => {"Atlas_AccessToken": atlasAccessToken, "Atlas_ChatSessionID": atlasChatSessionId, "Atlas_TokenType": atlasTokenType};
}
class AtlasContinueChatResponseDetails {
AiResponse? aiResponse;
QueryClassification? queryClassification;
String? sessionId;
AiResponse? userMessage;
AtlasContinueChatResponseDetails({
this.aiResponse,
this.queryClassification,
this.sessionId,
this.userMessage,
});
factory AtlasContinueChatResponseDetails.fromRawJson(String str) => AtlasContinueChatResponseDetails.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory AtlasContinueChatResponseDetails.fromJson(Map<String, dynamic> json) => AtlasContinueChatResponseDetails(
aiResponse: json["ai_response"] == null ? null : AiResponse.fromJson(json["ai_response"]),
queryClassification: json["query_classification"] == null ? null : QueryClassification.fromJson(json["query_classification"]),
sessionId: json["session_id"],
userMessage: json["user_message"] == null ? null : AiResponse.fromJson(json["user_message"]),
);
Map<String, dynamic> toJson() => {
"ai_response": aiResponse?.toJson(),
"query_classification": queryClassification?.toJson(),
"session_id": sessionId,
"user_message": userMessage?.toJson(),
};
}
class AiResponse {
DateTime? createdAt;
String? id;
StructuredData? structuredData;
String? text;
AiResponse({
this.createdAt,
this.id,
this.structuredData,
this.text,
});
factory AiResponse.fromRawJson(String str) => AiResponse.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory AiResponse.fromJson(Map<String, dynamic> json) => AiResponse(
createdAt: json["created_at"] == null ? null : DateTime.parse(json["created_at"]),
id: json["id"],
structuredData: json["structured_data"] == null ? null : StructuredData.fromJson(json["structured_data"]),
text: json["text"],
);
Map<String, dynamic> toJson() => {
"created_at": createdAt?.toIso8601String(),
"id": id,
"structured_data": structuredData?.toJson(),
"text": text,
};
}
class StructuredData {
String? answer;
List<dynamic>? sources;
String? type;
StructuredData({
this.answer,
this.sources,
this.type,
});
factory StructuredData.fromRawJson(String str) => StructuredData.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory StructuredData.fromJson(Map<String, dynamic> json) => StructuredData(
answer: json["answer"],
sources: json["sources"] == null ? [] : List<dynamic>.from(json["sources"]!.map((x) => x)),
type: json["type"],
);
Map<String, dynamic> toJson() => {
"answer": answer,
"sources": sources == null ? [] : List<dynamic>.from(sources!.map((x) => x)),
"type": type,
};
}
class QueryClassification {
int? confidence;
String? type;
QueryClassification({
this.confidence,
this.type,
});
factory QueryClassification.fromRawJson(String str) => QueryClassification.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory QueryClassification.fromJson(Map<String, dynamic> json) => QueryClassification(
confidence: json["confidence"],
type: json["type"],
);
Map<String, dynamic> toJson() => {
"confidence": confidence,
"type": type,
};
}

@ -1,61 +0,0 @@
import 'dart:convert';
class GetEmployeeParking {
GetEmployeeParkingClass? getEmployeeParking;
GetEmployeeParking({
this.getEmployeeParking,
});
factory GetEmployeeParking.fromRawJson(String str) => GetEmployeeParking.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory GetEmployeeParking.fromJson(Map<String, dynamic> json) => GetEmployeeParking(
getEmployeeParking: json["GET_Employee_Parking"] == null ? null : GetEmployeeParkingClass.fromJson(json["GET_Employee_Parking"]),
);
Map<String, dynamic> toJson() => {
"GET_Employee_Parking": getEmployeeParking?.toJson(),
};
}
class GetEmployeeParkingClass {
DateTime? createdAt;
String? employeeCode;
String? isNewQrCode;
String? qrCode;
String? qrCodeImageBase64;
bool? success;
GetEmployeeParkingClass({
this.createdAt,
this.employeeCode,
this.isNewQrCode,
this.qrCode,
this.qrCodeImageBase64,
this.success,
});
factory GetEmployeeParkingClass.fromRawJson(String str) => GetEmployeeParkingClass.fromJson(json.decode(str));
String toRawJson() => json.encode(toJson());
factory GetEmployeeParkingClass.fromJson(Map<String, dynamic> json) => GetEmployeeParkingClass(
createdAt: json["createdAt"] == null ? null : DateTime.parse(json["createdAt"]),
employeeCode: json["employeeCode"],
isNewQrCode: json["isNewQRCode"],
qrCode: json["qrCode"],
qrCodeImageBase64: json["qrCodeImageBase64"],
success: json["success"],
);
Map<String, dynamic> toJson() => {
"createdAt": createdAt?.toIso8601String(),
"employeeCode": employeeCode,
"isNewQRCode": isNewQrCode,
"qrCode": qrCode,
"qrCodeImageBase64": qrCodeImageBase64,
"success": success,
};
}

@ -120,7 +120,6 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
DrawerMenuItem("assets/images/drawer/my_profile.svg", LocaleKeys.myProfile.tr(), AppRoutes.profile), DrawerMenuItem("assets/images/drawer/my_profile.svg", LocaleKeys.myProfile.tr(), AppRoutes.profile),
DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation), DrawerMenuItem("assets/images/drawer/performance_evaluation.svg", LocaleKeys.performanceEvaluation.tr(), AppRoutes.performanceEvaluation),
DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi), DrawerMenuItem("assets/images/drawer/mowadhafi.svg", LocaleKeys.mowadhafhi.tr(), AppRoutes.mowadhafhi),
DrawerMenuItem("assets/images/drawer/car_parking_icon.svg", LocaleKeys.parkingQr.tr(), AppRoutes.parkingQr),
DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions), DrawerMenuItem("assets/images/drawer/pending_trasactions.svg", LocaleKeys.pendingTransactions.tr(), AppRoutes.pendingTransactions),
// DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen), // DrawerMenuItem("assets/images/drawer/drawer_marathon.svg", LocaleKeys.brainMarathon.tr(), AppRoutes.marathonIntroScreen),
DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword), DrawerMenuItem("assets/images/drawer/change_password.svg", LocaleKeys.changePassword.tr(), AppRoutes.changePassword),
@ -327,6 +326,8 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
void fetchTicketBalance() async { void fetchTicketBalance() async {
try { try {
GenericResponseModel? ticketResponse = await DashboardApiClient().getTicketBalance(); GenericResponseModel? ticketResponse = await DashboardApiClient().getTicketBalance();
logger.d("Ticket Balance Response: ${ticketResponse?.toJson()}");
print(" ========= Ticket Balance Response ======= ");
} catch (ex) { } catch (ex) {
logger.wtf(ex); logger.wtf(ex);
isEventLoadingLoading = false; isEventLoadingLoading = false;
@ -339,7 +340,8 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
Future<SSOAuthModel?> fetchSSOAuthRedirection({String? clientID}) async { Future<SSOAuthModel?> fetchSSOAuthRedirection({String? clientID}) async {
try { try {
SSOAuthModel? ssoResponse = await DashboardApiClient().getBookingSSOAuthRedirection(clientID: clientID!); SSOAuthModel? ssoResponse = await DashboardApiClient().getBookingSSOAuthRedirection(clientID: clientID!);
if (ssoResponse!.status == "Success") { logger.d("SSO Response: ${ssoResponse!.toJson()}");
if (ssoResponse.status == "Success") {
return ssoResponse; return ssoResponse;
} else { } else {
Utils.showToast(ssoResponse.message!.first ?? "Failed to fetch SSO Auth Token"); Utils.showToast(ssoResponse.message!.first ?? "Failed to fetch SSO Auth Token");
@ -359,12 +361,18 @@ class DashboardProviderModel with ChangeNotifier, DiagnosticableTreeMixin {
dynamic res = await DashboardApiClient().getBookingSSOFinalRedirection(token: token); dynamic res = await DashboardApiClient().getBookingSSOFinalRedirection(token: token);
logger.d("SSO URL: $res"); logger.d("SSO URL: $res");
return res; return res;
// if (ssoResponse.status == "Success") {
// return ssoResponse;
// } else {
// Utils.showToast(ssoResponse.message!.first ?? "Failed to fetch SSO Auth Token");
// return null;
// }
} catch (ex) { } catch (ex) {
logger.wtf(ex); logger.wtf(ex);
isEventLoadingLoading = false; isEventLoadingLoading = false;
notifyListeners(); notifyListeners();
Utils.handleException(ex, null, null); Utils.handleException(ex, null, null);
return null; return null; // Ensure a return value in case of an exception
} }
} }

@ -0,0 +1,450 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
import 'package:mohem_flutter_app/models/generic_response_model.dart';
import 'package:speech_to_text/speech_recognition_result.dart';
import 'package:speech_to_text/speech_to_text.dart';
enum ChatMode { home, chatActive }
class ChatMessage {
final String text;
final bool isUser;
final DateTime timestamp;
ChatMessage({required this.text, required this.isUser, required this.timestamp});
}
class ChatBotScreen extends StatefulWidget {
const ChatBotScreen({Key? key}) : super(key: key);
@override
State<ChatBotScreen> createState() => _ChatBotScreenState();
}
class _ChatBotScreenState extends State<ChatBotScreen> {
ChatMode _currentMode = ChatMode.home;
final List<ChatMessage> _messages = <ChatMessage>[];
final TextEditingController _messageController = TextEditingController();
final ScrollController _scrollController = ScrollController();
AtlasInitiateChatResponse? atlasChatTokenResponse;
bool _isThinking = false;
// Speech to text
final SpeechToText _speechToText = SpeechToText();
bool _speechEnabled = false;
@override
void initState() {
// TODO: implement initState
super.initState();
getChatSession();
_initSpeech();
}
/// Initialize speech to text
void _initSpeech() async {
_speechEnabled = await _speechToText.initialize();
setState(() {});
}
/// Start listening for speech
void _startListening() async {
await _speechToText.listen(onResult: _onSpeechResult);
setState(() {});
}
/// Stop listening for speech
void _stopListening() async {
await _speechToText.stop();
setState(() {});
}
/// Callback when speech is recognized
void _onSpeechResult(SpeechRecognitionResult result) {
setState(() {
_messageController.text = result.recognizedWords;
// Move cursor to end of text
_messageController.selection = TextSelection.fromPosition(TextPosition(offset: _messageController.text.length));
});
}
void getChatSession() async {
try {
GenericResponseModel? res = await DashboardApiClient().getChatBotSession();
if (res != null) {
setState(() {
atlasChatTokenResponse = res.atlasInitiateChatResponse;
});
}
} catch (ex) {
Utils.handleException(ex, context, null);
}
}
@override
void dispose() {
atlasChatTokenResponse = null;
_messageController.dispose();
_scrollController.dispose();
super.dispose();
}
void _sendMessage({String? suggestionText}) async {
String text = suggestionText ?? _messageController.text.trim();
if (text.isEmpty || atlasChatTokenResponse == null) return;
try {
setState(() {
_messages.add(ChatMessage(text: text, isUser: true, timestamp: DateTime.now()));
_currentMode = ChatMode.chatActive;
_messageController.clear();
_isThinking = true;
});
_scrollToBottom();
GenericResponseModel? res = await DashboardApiClient().sendChatBotMessage(atlasChatTokenResponse: atlasChatTokenResponse!, atlasChatText: text);
if (res != null) {
res.atlasContinueChatResponseDetails;
if (mounted) {
setState(() {
_isThinking = false;
_messages.add(
ChatMessage(
text: res.atlasContinueChatResponseDetails!.aiResponse!.structuredData!.answer ?? "",
isUser: false,
timestamp: res.atlasContinueChatResponseDetails!.aiResponse!.createdAt ?? DateTime.now(),
),
);
});
}
_scrollToBottom();
}
} catch (ex) {
setState(() {
_isThinking = false;
});
Utils.handleException(ex, context, null);
}
_scrollToBottom();
}
void _scrollToBottom() {
Future.delayed(const Duration(milliseconds: 100), () {
if (_scrollController.hasClients) {
_scrollController.animateTo(_scrollController.position.maxScrollExtent, duration: const Duration(milliseconds: 300), curve: Curves.easeOut);
}
});
}
void _sendSuggestion(String text) {
if (atlasChatTokenResponse == null) {
Utils.showToast("Please wait, initializing chat...");
return;
}
_sendMessage(suggestionText: text);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: MyColors.backgroundColor,
appBar: AppBar(
title: const Text("ChatBot", style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xFF2B353E))),
backgroundColor: MyColors.backgroundColor,
centerTitle: false,
),
body: Column(children: <Widget>[Expanded(child: _currentMode == ChatMode.home ? _buildHomeMode() : _buildChatMode()), _buildBottomInputBar()]),
);
}
Widget _buildHomeMode() {
return Center(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 24.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
const Text("Hello, ask me", textAlign: TextAlign.center, style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xFF2E303A))),
const Text("anything...", textAlign: TextAlign.center, style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xFF2E303A))),
const SizedBox(height: 50),
Wrap(
alignment: WrapAlignment.center,
spacing: 8,
runSpacing: 12,
children: <Widget>[
_buildSuggestionChip("Nostalgia Perfume", () => _sendSuggestion("Nostalgia Perfume")),
_buildSuggestionChip("Al Nafoura", () => _sendSuggestion("Al Nafoura")),
_buildSuggestionChip("Al Nafoura", () => _sendSuggestion("Al Nafoura")),
_buildSuggestionChip("Al Jadi", () => _sendSuggestion("Al Jadi")),
],
),
],
),
),
);
}
Widget _buildChatMode() {
return ListView.separated(
controller: _scrollController,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
itemCount: _messages.length + (_isThinking ? 1 : 0),
itemBuilder: (BuildContext context, int index) {
if (index == _messages.length && _isThinking) {
return _buildThinkingIndicator();
}
ChatMessage message = _messages[index];
return _buildMessageBubble(message);
},
separatorBuilder: (BuildContext context, int index) {
return const SizedBox(height: 15);
},
);
}
Widget _buildThinkingIndicator() {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
gradient: const LinearGradient(colors: <Color>[Color(0xFF32D892), Color(0xFF259CB8)], begin: Alignment.centerLeft, end: Alignment.centerRight),
borderRadius: BorderRadius.circular(15),
boxShadow: <BoxShadow>[BoxShadow(color: const Color(0xFF000000).withValues(alpha: 0.0784), offset: const Offset(0, 0), blurRadius: 13, spreadRadius: 0)],
),
child: const ThinkingDotsAnimation(),
),
const Spacer(flex: 2),
],
);
}
Widget _buildMessageBubble(ChatMessage message) {
bool isUser = message.isUser;
Widget bubbleContent = Row(
mainAxisAlignment: isUser ? MainAxisAlignment.end : MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
if (isUser) const Spacer(flex: 2),
Flexible(
flex: 7,
child: Column(
crossAxisAlignment: isUser ? CrossAxisAlignment.end : CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: isUser ? Colors.white : null,
gradient: isUser ? null : const LinearGradient(colors: <Color>[Color(0xFF32D892), Color(0xFF259CB8)], begin: Alignment.centerLeft, end: Alignment.centerRight),
borderRadius: BorderRadius.circular(15),
boxShadow: isUser ? null : <BoxShadow>[BoxShadow(color: const Color(0xFF000000).withValues(alpha: 0.0784), offset: const Offset(0, 0), blurRadius: 13, spreadRadius: 0)],
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(message.text, softWrap: true, style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: isUser ? const Color(0xFF2B353E) : MyColors.white)),
Align(
alignment: Alignment.centerRight,
child: Text(
_formatTimestamp(message.timestamp),
style: TextStyle(fontSize: 11, fontWeight: FontWeight.w500, letterSpacing: -0.4, color: isUser ? const Color(0xFF2B353E) : MyColors.whiteColor),
),
),
],
),
),
],
),
),
if (!isUser) const Spacer(flex: 2),
],
);
if (!isUser) {
return AnimatedMessageBubble(child: bubbleContent);
}
return bubbleContent;
}
String _formatTimestamp(DateTime timestamp) {
String hour = timestamp.hour.toString().padLeft(2, '0');
String minute = timestamp.minute.toString().padLeft(2, '0');
String month = timestamp.month.toString().padLeft(2, '0');
String day = timestamp.day.toString().padLeft(2, '0');
int year = timestamp.year;
return "$month/$day/$year $hour:$minute AM";
}
Widget _buildSuggestionChip(String label, VoidCallback onTap) {
return Material(
color: Colors.white,
elevation: 3,
shadowColor: const Color(0xFF000015).withValues(alpha: 0.0784),
borderRadius: BorderRadius.circular(10),
child: InkWell(
borderRadius: BorderRadius.circular(10),
onTap: onTap,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
child: Text(label, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: MyColors.darkTextColor, letterSpacing: 0.2)),
),
),
);
}
Widget _buildBottomInputBar() {
return Container(
decoration: const BoxDecoration(color: MyColors.backgroundColor),
child: SafeArea(
top: false,
child: Row(
children: <Widget>[
// Plus button
// IconButton(padding: EdgeInsets.zero, icon: const Icon(Icons.add, color: MyColors.darkTextColor, size: 34), onPressed: () {}),
// const SizedBox(width: 12),
// Text field
Expanded(
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
height: 48,
decoration: BoxDecoration(color: Colors.transparent, borderRadius: BorderRadius.circular(10), border: BoxBorder.all(width: 1, color: const Color(0xFFE5E5E5))),
child: Row(
children: <Widget>[
Expanded(
child: TextField(
controller: _messageController,
onSubmitted: _isThinking ? null : (_) => _sendMessage(),
enabled: !_isThinking,
maxLines: 1,
textAlignVertical: TextAlignVertical.center,
decoration: InputDecoration(
hintText: _isThinking ? 'Waiting for response...' : 'Type a message..',
hintStyle: const TextStyle(color: MyColors.hintTextColor, fontSize: 14, fontWeight: FontWeight.normal),
border: InputBorder.none,
isDense: true,
contentPadding: const EdgeInsets.symmetric(vertical: 10),
),
),
),
GestureDetector(
onTap: _isThinking ? null : (_speechEnabled ? (_speechToText.isNotListening ? _startListening : _stopListening) : null),
child: SvgPicture.asset(
"assets/icons/microphone.svg",
colorFilter: ColorFilter.mode(_isThinking ? MyColors.hintTextColor : (_speechToText.isListening ? Colors.red : MyColors.darkTextColor), BlendMode.srcIn),
),
),
],
),
),
),
const SizedBox(width: 6),
// Send button
GestureDetector(
onTap: _isThinking ? null : _sendMessage,
child: Container(
width: 48,
height: 48,
decoration: BoxDecoration(color: _isThinking ? MyColors.hintTextColor.withValues(alpha: 0.3) : MyColors.white, shape: BoxShape.circle),
child: Center(child: SvgPicture.asset("assets/icons/send.svg", colorFilter: _isThinking ? const ColorFilter.mode(MyColors.hintTextColor, BlendMode.srcIn) : null)),
),
),
],
),
),
).paddingOnly(left: 16, right: 16, bottom: 16);
}
}
class ThinkingDotsAnimation extends StatefulWidget {
const ThinkingDotsAnimation({Key? key}) : super(key: key);
@override
State<ThinkingDotsAnimation> createState() => _ThinkingDotsAnimationState();
}
class _ThinkingDotsAnimationState extends State<ThinkingDotsAnimation> with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 1200))..repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
const Text("Thinking", style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white)),
const SizedBox(width: 2),
AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget? child) {
int dotCount = (_controller.value * 4).floor() % 4;
String dots = '.' * dotCount;
return SizedBox(width: 18, child: Text(dots, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white)));
},
),
],
);
}
}
class AnimatedMessageBubble extends StatefulWidget {
final Widget child;
const AnimatedMessageBubble({Key? key, required this.child}) : super(key: key);
@override
State<AnimatedMessageBubble> createState() => _AnimatedMessageBubbleState();
}
class _AnimatedMessageBubbleState extends State<AnimatedMessageBubble> with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<double> _fadeAnimation;
late Animation<Offset> _slideAnimation;
late Animation<double> _scaleAnimation;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: const Duration(milliseconds: 400));
_fadeAnimation = Tween<double>(begin: 0.0, end: 1.0).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOut));
_slideAnimation = Tween<Offset>(begin: const Offset(-0.3, 0.0), end: Offset.zero).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOutCubic));
_scaleAnimation = Tween<double>(begin: 0.8, end: 1.0).animate(CurvedAnimation(parent: _controller, curve: Curves.easeOutBack));
_controller.forward();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return SlideTransition(
position: _slideAnimation,
child: FadeTransition(opacity: _fadeAnimation, child: ScaleTransition(scale: _scaleAnimation, alignment: Alignment.centerLeft, child: widget.child)),
);
}
}

@ -577,11 +577,9 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
6.width, 6.width,
Container( Container(
padding: const EdgeInsets.only(left: 8, right: 8), padding: const EdgeInsets.only(left: 8, right: 8),
decoration: BoxDecoration( decoration: BoxDecoration(color: MyColors.yellowColor, borderRadius: BorderRadius.circular(10)),
color: MyColors.yellowColor, child: LocaleKeys.newString.tr().toText10(isBold: true),
borderRadius: BorderRadius.circular(10),
), ),
child: LocaleKeys.newString.tr().toText10(isBold: true)),
], ],
), ),
], ],
@ -589,7 +587,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
), ),
LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() { LocaleKeys.viewAllOffers.tr().toText12(isUnderLine: true).onPress(() {
Navigator.pushNamed(context, AppRoutes.offersAndDiscounts); Navigator.pushNamed(context, AppRoutes.offersAndDiscounts);
}) }),
], ],
).paddingOnly(left: 21, right: 21), ).paddingOnly(left: 21, right: 21),
Consumer<DashboardProviderModel>( Consumer<DashboardProviderModel>(
@ -618,28 +616,22 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
height: 73, height: 73,
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: const BorderRadius.all( borderRadius: const BorderRadius.all(Radius.circular(100)),
Radius.circular(100),
),
border: Border.all(color: MyColors.lightGreyE3Color, width: 1), border: Border.all(color: MyColors.lightGreyE3Color, width: 1),
), ),
child: ClipRRect( child: ClipRRect(
borderRadius: const BorderRadius.all( borderRadius: const BorderRadius.all(Radius.circular(50)),
Radius.circular(50),
),
child: Hero( child: Hero(
tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!, tag: "ItemImage" + data.getOffersList[index].offersDiscountId.toString()!,
transitionOnUserGestures: true, transitionOnUserGestures: true,
child: Image.network( child: Image.network(data.getOffersList[index].logo ?? "", fit: BoxFit.contain),
data.getOffersList[index].logo ?? "",
fit: BoxFit.contain,
),
), ),
), ),
), ),
4.height, 4.height,
Expanded( Expanded(
child: AppState().isArabic(context) child:
AppState().isArabic(context)
? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1) ? data.getOffersList[index].titleAr!.toText12(isCenter: true, maxLine: 1)
: data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1), : data.getOffersList[index].titleEn!.toText12(isCenter: true, maxLine: 1),
), ),
@ -649,7 +641,8 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
); );
}, },
separatorBuilder: (BuildContext cxt, int index) => 8.width, separatorBuilder: (BuildContext cxt, int index) => 8.width,
itemCount: 9), itemCount: 9,
),
); );
}, },
), ),
@ -824,6 +817,19 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
}, },
), ),
), ),
floatingActionButton: FloatingActionButton.large(
onPressed: () {
Navigator.pushNamed(context, AppRoutes.chatBotHome);
},
backgroundColor: Colors.transparent,
elevation: 0,
focusElevation: 0,
hoverElevation: 0,
highlightElevation: 0,
shape: const CircleBorder(),
child: SvgPicture.asset("assets/icons/chatbot.svg", width: 100, height: 100),
),
), ),
); );
} }

@ -1,106 +0,0 @@
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
import 'package:mohem_flutter_app/classes/colors.dart';
import 'package:mohem_flutter_app/classes/utils.dart';
import 'package:mohem_flutter_app/extensions/int_extensions.dart';
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
import 'package:mohem_flutter_app/models/get_employee_parking_details_model.dart';
import 'package:mohem_flutter_app/widgets/app_bar_widget.dart';
class ParkingQrScreen extends StatefulWidget {
const ParkingQrScreen({Key? key}) : super(key: key);
@override
_RequestDetailsState createState() => _RequestDetailsState();
}
class _RequestDetailsState extends State<ParkingQrScreen> {
GetEmployeeParking? qrData;
@override
void initState() {
super.initState();
getTicketDetails();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBarWidget(context, title: LocaleKeys.parkingQr.tr()),
body:
qrData?.getEmployeeParking == null
? Center(child: Text(LocaleKeys.noDataAvailable.tr()))
: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Container(
padding: const EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
boxShadow: [BoxShadow(color: Colors.grey.withValues(alpha: 0.2), spreadRadius: 5, blurRadius: 10, offset: const Offset(0, 3))],
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// QR Code Image
if (qrData!.getEmployeeParking!.qrCodeImageBase64 != null && qrData!.getEmployeeParking!.qrCodeImageBase64!.isNotEmpty)
Image.memory(Utils.dataFromBase64String(qrData!.getEmployeeParking!.qrCodeImageBase64!), width: 300, height: 300, fit: BoxFit.contain)
else
Container(
width: 300,
height: 300,
color: MyColors.lightGreyEFColor,
child: Center(child: Text(LocaleKeys.noDataAvailable.tr(), style: const TextStyle(color: MyColors.grey67Color))),
),
10.height,
Container(height: 1, color: MyColors.lightGreyE3Color, margin: const EdgeInsets.symmetric(vertical: 10)),
20.height,
SizedBox(
width: double.infinity,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Employee Code
if (qrData!.getEmployeeParking!.employeeCode != null && qrData!.getEmployeeParking!.employeeCode!.isNotEmpty) ...[
Text(LocaleKeys.employeeNumber.tr(), style: const TextStyle(fontSize: 14, color: MyColors.grey67Color, fontWeight: FontWeight.w400)),
8.height,
Text(qrData!.getEmployeeParking!.employeeCode!, style: const TextStyle(fontSize: 18, color: MyColors.darkTextColor, fontWeight: FontWeight.w600)),
8.height,
],
if (qrData!.getEmployeeParking!.createdAt != null) ...[
Text(LocaleKeys.creationDate.tr(), style: const TextStyle(fontSize: 14, color: MyColors.grey67Color, fontWeight: FontWeight.w400)),
8.height,
Text(
DateFormat('dd MMM yyyy, hh:mm a').format(qrData!.getEmployeeParking!.createdAt!),
style: const TextStyle(fontSize: 16, color: MyColors.darkTextColor, fontWeight: FontWeight.w500),
),
],
],
),
),
],
),
),
),
),
),
);
}
void getTicketDetails() async {
try {
Utils.showLoading(context);
qrData = await DashboardApiClient().getEmployeeParkingQrCode();
Utils.hideLoading(context);
setState(() {});
} catch (ex) {
Utils.hideLoading(context);
Utils.handleException(ex, context, null);
}
}
}

@ -150,9 +150,7 @@ class _MowadhafhiHRRequestState extends State<MowadhafhiHRRequest> {
isReadOnly: false, isReadOnly: false,
onChange: (String value) { onChange: (String value) {
debugPrint(value); debugPrint(value);
setState(() {
description = value; description = value;
});
}, },
), ),
], ],
@ -173,7 +171,7 @@ class _MowadhafhiHRRequestState extends State<MowadhafhiHRRequest> {
} }
bool checkValidation() { bool checkValidation() {
if (selectedServiceType == null || selectedDepartment == null || selectedSection == null || selectedTopic == null || description == "") { if (selectedServiceType == null || selectedDepartment == null || selectedSection == null || selectedTopic == null) {
return false; return false;
} else { } else {
return true; return true;

@ -142,6 +142,8 @@ dependencies:
webview_flutter: ^4.13.0 webview_flutter: ^4.13.0
nfc_manager: ^3.2.0 nfc_manager: ^3.2.0
speech_to_text: ^7.3.0
# saf: ^1.0.3+4 # saf: ^1.0.3+4

Loading…
Cancel
Save