diff --git a/assets/images/revise_sound.mpeg b/assets/images/revise_sound.mpeg new file mode 100644 index 0000000..b04eec1 Binary files /dev/null and b/assets/images/revise_sound.mpeg differ diff --git a/lib/auth/employee_login_screen.dart b/lib/auth/employee_login_screen.dart index 7244aca..1aae07b 100644 --- a/lib/auth/employee_login_screen.dart +++ b/lib/auth/employee_login_screen.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:get/get.dart'; import 'package:taxglide/consts/app_asstes.dart'; import 'package:taxglide/consts/app_colors.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:taxglide/consts/comman_button.dart'; import 'package:taxglide/consts/comman_container_auth.dart'; import 'package:taxglide/consts/comman_textformfileds.dart'; @@ -100,7 +101,13 @@ class _EmployeeLoginScreenState extends ConsumerState { final spacingMD = r.spacing(mobile: 20, tablet: 20, desktop: 24); final spacingLG = r.spacing(mobile: 20, tablet: 22, desktop: 28); - return Scaffold( + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + Get.offAllNamed(ConstRouters.login); + }, + child: Scaffold( resizeToAvoidBottomInset: true, body: Container( width: double.infinity, @@ -141,10 +148,8 @@ class _EmployeeLoginScreenState extends ConsumerState { Text( "Login", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + style: AppTextStyles.bold.copyWith( fontSize: titleFontSize, - fontWeight: FontWeight.w600, height: 1.3, letterSpacing: 0.01 * titleFontSize, color: AppColors.authheading, @@ -156,10 +161,8 @@ class _EmployeeLoginScreenState extends ConsumerState { Text( "Enter your registered Mobile Number", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + style: AppTextStyles.bold.copyWith( fontSize: subtitleFontSize, - fontWeight: FontWeight.w600, height: 1.4, letterSpacing: 0.03 * subtitleFontSize, color: AppColors.authleading, @@ -180,9 +183,7 @@ class _EmployeeLoginScreenState extends ConsumerState { Text.rich( TextSpan( text: "By signing up, you agree to the ", - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: termsFontSize, height: 1.8, letterSpacing: 0.01, @@ -191,9 +192,7 @@ class _EmployeeLoginScreenState extends ConsumerState { children: [ TextSpan( text: "Terms of Service ", - style: TextStyle( - fontFamily: 'Gilroy-Bold', - fontWeight: FontWeight.w700, + style: AppTextStyles.bold.copyWith( fontSize: termsFontSize, height: 1.8, letterSpacing: 0.01, @@ -202,20 +201,16 @@ class _EmployeeLoginScreenState extends ConsumerState { ), TextSpan( text: "and ", - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, - fontSize: termsFontSize, - height: 1.8, - letterSpacing: 0.01, - color: AppColors.authleading, - ), + style: AppTextStyles.medium.copyWith( + fontSize: termsFontSize, + height: 1.8, + letterSpacing: 0.01, + color: AppColors.authleading, + ), ), TextSpan( text: "Data Processing Agreement", - style: TextStyle( - fontFamily: 'Gilroy-Bold', - fontWeight: FontWeight.w700, + style: AppTextStyles.bold.copyWith( fontSize: termsFontSize, height: 1.8, letterSpacing: 0.01, @@ -242,13 +237,11 @@ class _EmployeeLoginScreenState extends ConsumerState { Text( "Other Login", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Inter', - fontWeight: FontWeight.w500, + style: AppTextStyles.semiBold.copyWith( fontSize: otherLoginFontSize, height: 1.8, letterSpacing: 0.13, - color: const Color(0xFF6C7278), + color: AppColors.authleading, ), ), @@ -257,14 +250,16 @@ class _EmployeeLoginScreenState extends ConsumerState { Text.rich( TextSpan( text: "User Login? ", - style: TextStyle(fontSize: linkFontSize), + style: AppTextStyles.bold.copyWith( + fontSize: linkFontSize, + color: AppColors.black, + ), children: [ TextSpan( text: "Click Here", - style: TextStyle( + style: AppTextStyles.bold.copyWith( fontSize: linkFontSize, color: AppColors.authsignup, - fontWeight: FontWeight.bold, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -282,6 +277,7 @@ class _EmployeeLoginScreenState extends ConsumerState { ), ), ), + ), ); } } diff --git a/lib/auth/employee_otp_screen.dart b/lib/auth/employee_otp_screen.dart index 1acc4cc..f7cd6b5 100644 --- a/lib/auth/employee_otp_screen.dart +++ b/lib/auth/employee_otp_screen.dart @@ -247,7 +247,7 @@ class _EmployeeOtpScreenState extends ConsumerState { "Enter OTP", textAlign: TextAlign.center, style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontSize: titleFontSize, fontWeight: FontWeight.w600, height: 1.3, @@ -262,7 +262,7 @@ class _EmployeeOtpScreenState extends ConsumerState { "OTP has been sent to your registered mobile number", textAlign: TextAlign.center, style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontSize: subtitleFontSize, fontWeight: FontWeight.w600, height: 1.4, @@ -277,7 +277,7 @@ class _EmployeeOtpScreenState extends ConsumerState { TextSpan( text: mobile, style: TextStyle( - fontFamily: 'Gilroy-Medium', + fontFamily: "Gilroy", fontWeight: FontWeight.w500, fontSize: mobileFontSize, height: 1.8, @@ -288,7 +288,7 @@ class _EmployeeOtpScreenState extends ConsumerState { TextSpan( text: " ( Change Number )", style: TextStyle( - fontFamily: 'Gilroy-ExtraBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w800, fontSize: mobileFontSize, height: 1.8, @@ -347,7 +347,7 @@ class _EmployeeOtpScreenState extends ConsumerState { maxLength: 1, enabled: !isLoading, style: TextStyle( - fontFamily: 'Gilroy-Medium', + fontFamily: "Gilroy", fontWeight: FontWeight.w400, fontSize: otpFontSize, letterSpacing: 0.03 * otpFontSize, @@ -375,7 +375,7 @@ class _EmployeeOtpScreenState extends ConsumerState { "Resend", textAlign: TextAlign.center, style: TextStyle( - fontFamily: 'Gilroy-Medium', + fontFamily: "Gilroy", fontWeight: FontWeight.w500, fontSize: resendFontSize, height: 1.4, @@ -393,7 +393,7 @@ class _EmployeeOtpScreenState extends ConsumerState { Text( _formatTime(_remainingSeconds), style: TextStyle( - fontFamily: 'Gilroy-Medium', + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontSize: timerFontSize, color: _remainingSeconds > 0 diff --git a/lib/auth/login_screen.dart b/lib/auth/login_screen.dart index ce980f6..873f28f 100644 --- a/lib/auth/login_screen.dart +++ b/lib/auth/login_screen.dart @@ -12,6 +12,7 @@ import 'package:taxglide/consts/responsive_helper.dart'; import 'package:taxglide/consts/validation_popup.dart'; import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/router/consts_routers.dart'; +import 'package:taxglide/consts/app_style.dart'; class LoginScreen extends ConsumerStatefulWidget { const LoginScreen({super.key}); @@ -102,7 +103,12 @@ class _LoginScreenState extends ConsumerState { final spacingMD = r.spacing(mobile: 20, tablet: 22, desktop: 26); final spacingLG = r.spacing(mobile: 20, tablet: 22, desktop: 28); - return Scaffold( + return PopScope( + canPop: true, + onPopInvokedWithResult: (didPop, result) { + // Handle custom behavior here if needed in the future + }, + child: Scaffold( resizeToAvoidBottomInset: true, body: Container( width: double.infinity, @@ -141,10 +147,8 @@ class _LoginScreenState extends ConsumerState { // Title Text( "Login", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + style: AppTextStyles.semiBold.copyWith( fontSize: titleFontSize, - fontWeight: FontWeight.w600, color: AppColors.authheading, ), ), @@ -154,8 +158,7 @@ class _LoginScreenState extends ConsumerState { Text( "Enter your Mobile Number", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + style: AppTextStyles.semiBold.copyWith( fontSize: subtitleFontSize, color: AppColors.authleading, ), @@ -175,15 +178,14 @@ class _LoginScreenState extends ConsumerState { Text.rich( TextSpan( text: "By signing up, you agree to the ", - style: TextStyle( + style: AppTextStyles.medium.copyWith( fontSize: termsFontSize, color: AppColors.authleading, ), children: [ TextSpan( text: "Terms of Service ", - style: TextStyle( - fontWeight: FontWeight.w700, + style: AppTextStyles.bold.copyWith( fontSize: termsFontSize, color: AppColors.authtermsandcondition, ), @@ -259,21 +261,26 @@ class _LoginScreenState extends ConsumerState { ), SizedBox(height: spacingSM), - const Text("Or"), + Text("Or",style: AppTextStyles.medium.copyWith( + fontSize: spacingSM, + color: AppColors.authleading, + ),), SizedBox(height: spacingSM), // Sign up Text.rich( TextSpan( text: "Didn't Have account? ", - style: TextStyle(fontSize: signupFontSize), + style: AppTextStyles.bold.copyWith( + fontSize: signupFontSize, + color: AppColors.black, + ), children: [ TextSpan( text: "Sign Up", - style: TextStyle( + style: AppTextStyles.bold.copyWith( fontSize: signupFontSize, color: AppColors.authsignup, - fontWeight: FontWeight.bold, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -298,13 +305,11 @@ class _LoginScreenState extends ConsumerState { Text( "Other Login", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Inter', - fontWeight: FontWeight.w500, + style: AppTextStyles.semiBold.copyWith( fontSize: otherLoginFontSize, height: 1.8, letterSpacing: 0.13, - color: const Color(0xFF6C7278), + color: AppColors.authleading, ), ), @@ -313,14 +318,16 @@ class _LoginScreenState extends ConsumerState { Text.rich( TextSpan( text: "Staff Login? ", - style: TextStyle(fontSize: signupFontSize), + style: AppTextStyles.bold.copyWith( + fontSize: signupFontSize, + color: AppColors.black, + ), children: [ TextSpan( text: "Click Here", - style: TextStyle( + style: AppTextStyles.bold.copyWith( fontSize: signupFontSize, color: AppColors.authsignup, - fontWeight: FontWeight.bold, ), recognizer: TapGestureRecognizer() ..onTap = () { @@ -338,6 +345,7 @@ class _LoginScreenState extends ConsumerState { ), ), ), + ), ); } } diff --git a/lib/auth/otp_screen.dart b/lib/auth/otp_screen.dart index 8ec0412..dab58ff 100644 --- a/lib/auth/otp_screen.dart +++ b/lib/auth/otp_screen.dart @@ -13,6 +13,7 @@ import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/router/consts_routers.dart'; import 'package:taxglide/view/Main_controller/main_controller.dart'; +import 'package:taxglide/consts/app_style.dart'; class OtpScreen extends ConsumerStatefulWidget { const OtpScreen({super.key}); @@ -248,10 +249,8 @@ class _OtpScreenState extends ConsumerState { Text( "Enter OTP", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + style: AppTextStyles.semiBold.copyWith( fontSize: titleFontSize, - fontWeight: FontWeight.w600, height: 1.3, letterSpacing: 0.01 * titleFontSize, color: AppColors.authheading, @@ -263,10 +262,8 @@ class _OtpScreenState extends ConsumerState { Text( "OTP has been sent to your registered mobile number", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + style: AppTextStyles.semiBold.copyWith( fontSize: subtitleFontSize, - fontWeight: FontWeight.w600, height: 1.4, letterSpacing: 0.03 * subtitleFontSize, color: AppColors.authleading, @@ -278,9 +275,7 @@ class _OtpScreenState extends ConsumerState { Text.rich( TextSpan( text: mobile, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: mobileFontSize, height: 1.8, letterSpacing: 0.01, @@ -289,9 +284,7 @@ class _OtpScreenState extends ConsumerState { children: [ TextSpan( text: " ( Change Number )", - style: TextStyle( - fontFamily: 'Gilroy-ExtraBold', - fontWeight: FontWeight.w800, + style: AppTextStyles.extraBold.copyWith( fontSize: mobileFontSize, height: 1.8, letterSpacing: 0.04, @@ -349,7 +342,7 @@ class _OtpScreenState extends ConsumerState { maxLength: 1, enabled: !isLoading, style: TextStyle( - fontFamily: 'Gilroy-Medium', + fontFamily: "Gilroy", fontWeight: FontWeight.w400, fontSize: otpFontSize, letterSpacing: 0.03 * otpFontSize, @@ -376,9 +369,7 @@ class _OtpScreenState extends ConsumerState { child: Text( "Resend", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: resendFontSize, height: 1.4, letterSpacing: 0.02 * resendFontSize, @@ -394,9 +385,7 @@ class _OtpScreenState extends ConsumerState { // Timer Text( _formatTime(_remainingSeconds), - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: timerFontSize, color: _remainingSeconds > 0 ? AppColors.authheading diff --git a/lib/auth/register_otp_screen.dart b/lib/auth/register_otp_screen.dart index 91fb48c..82ca785 100644 --- a/lib/auth/register_otp_screen.dart +++ b/lib/auth/register_otp_screen.dart @@ -11,6 +11,7 @@ import 'package:taxglide/consts/validation_popup.dart'; import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/router/consts_routers.dart'; import 'package:taxglide/view/Main_controller/main_controller.dart'; +import 'package:taxglide/consts/app_style.dart'; class RegisterOtpScreen extends ConsumerStatefulWidget { const RegisterOtpScreen({super.key}); @@ -247,10 +248,8 @@ class _RegisterOtpScreenState extends ConsumerState { Text( "Enter OTP", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + style: AppTextStyles.semiBold.copyWith( fontSize: 32, - fontWeight: FontWeight.w600, height: 1.3, letterSpacing: 0.01 * 32, color: AppColors.authheading, @@ -260,10 +259,8 @@ class _RegisterOtpScreenState extends ConsumerState { Text( "OTP has been sent to your registered mobile number", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + style: AppTextStyles.semiBold.copyWith( fontSize: 14, - fontWeight: FontWeight.w600, height: 1.4, letterSpacing: 0.03 * 14, color: AppColors.authleading, @@ -273,9 +270,7 @@ class _RegisterOtpScreenState extends ConsumerState { Text.rich( TextSpan( text: mobile, - style: const TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: 13, height: 1.8, letterSpacing: 0.01, @@ -284,9 +279,7 @@ class _RegisterOtpScreenState extends ConsumerState { children: [ TextSpan( text: " ( Change Number )", - style: const TextStyle( - fontFamily: 'Gilroy-ExtraBold', - fontWeight: FontWeight.w800, + style: AppTextStyles.extraBold.copyWith( fontSize: 13, height: 1.8, letterSpacing: 0.04, @@ -346,7 +339,7 @@ class _RegisterOtpScreenState extends ConsumerState { maxLength: 1, enabled: !isLoading, style: TextStyle( - fontFamily: 'Gilroy-Medium', + fontFamily: "Gilroy", fontWeight: FontWeight.w400, fontSize: 28, letterSpacing: 0.03 * 28, @@ -373,9 +366,7 @@ class _RegisterOtpScreenState extends ConsumerState { child: Text( "Resend", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: 14, height: 1.4, letterSpacing: 0.02 * 14, @@ -391,9 +382,7 @@ class _RegisterOtpScreenState extends ConsumerState { // Timer Display Text( _formatTime(_remainingSeconds), - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 16, color: _remainingSeconds > 0 ? AppColors.authheading diff --git a/lib/auth/signup_screen.dart b/lib/auth/signup_screen.dart index ec2b5b8..05eab84 100644 --- a/lib/auth/signup_screen.dart +++ b/lib/auth/signup_screen.dart @@ -9,6 +9,7 @@ import 'package:taxglide/consts/comman_textformfileds.dart'; import 'package:taxglide/consts/validation_popup.dart'; import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/router/consts_routers.dart'; +import 'package:taxglide/consts/app_style.dart'; class SignupScreen extends ConsumerStatefulWidget { const SignupScreen({super.key}); @@ -89,7 +90,13 @@ class _SignupScreenState extends ConsumerState { ); }); - return Scaffold( + return PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + Get.offAllNamed(ConstRouters.login); + }, + child: Scaffold( body: Stack( children: [ // 🌈 Background gradient @@ -131,10 +138,8 @@ class _SignupScreenState extends ConsumerState { Text( "Sign Up", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + style: AppTextStyles.semiBold.copyWith( fontSize: 32, - fontWeight: FontWeight.w600, height: 1.3, letterSpacing: 0.01 * 32, color: AppColors.authheading, @@ -148,10 +153,9 @@ class _SignupScreenState extends ConsumerState { alignment: Alignment.centerLeft, child: Text( "Name*", - style: TextStyle( - fontFamily: 'Gilroy-Medium', + style: AppTextStyles.semiBold.copyWith( fontSize: 14, - color: AppColors.authleading, + color: AppColors.authheading, ), ), ), @@ -177,10 +181,9 @@ class _SignupScreenState extends ConsumerState { alignment: Alignment.centerLeft, child: Text( "Contact Number *", - style: TextStyle( - fontFamily: 'Gilroy-Medium', + style: AppTextStyles.semiBold.copyWith( fontSize: 14, - color: AppColors.authleading, + color: AppColors.authheading, ), ), ), @@ -206,10 +209,9 @@ class _SignupScreenState extends ConsumerState { alignment: Alignment.centerLeft, child: Text( "Email *", - style: TextStyle( - fontFamily: 'Gilroy-Medium', + style: AppTextStyles.semiBold.copyWith( fontSize: 14, - color: AppColors.authleading, + color: AppColors.authheading, ), ), ), @@ -247,6 +249,7 @@ class _SignupScreenState extends ConsumerState { ), ], ), + ), ); } diff --git a/lib/consts/app_style.dart b/lib/consts/app_style.dart new file mode 100644 index 0000000..8ffe7fa --- /dev/null +++ b/lib/consts/app_style.dart @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; + +class AppTextStyles { + static const TextStyle thin = TextStyle( + fontFamily: 'Gilroy-Thin', + ); + + static const TextStyle ultraLight = TextStyle( + fontFamily: 'Gilroy-UltraLight', + ); + static const TextStyle ultralight = ultraLight; + + static const TextStyle light = TextStyle( + fontFamily: 'Gilroy-Light', + ); + + static const TextStyle regular = TextStyle( + fontFamily: 'Gilroy-Regular', + ); + + static const TextStyle medium = TextStyle( + fontFamily: 'Gilroy-Medium', + ); + + static const TextStyle semiBold = TextStyle( + fontFamily: 'Gilroy-SemiBold', + ); + static const TextStyle semibold = semiBold; + static const TextStyle semi_bold = semiBold; + + static const TextStyle bold = TextStyle( + fontFamily: 'Gilroy-Bold', + ); + + static const TextStyle extraBold = TextStyle( + fontFamily: 'Gilroy-ExtraBold', + ); + static const TextStyle extrabold = extraBold; + + static const TextStyle black = TextStyle( + fontFamily: 'Gilroy-Black', + ); + + static const TextStyle heavy = TextStyle( + fontFamily: 'Gilroy-Heavy', + ); +} diff --git a/lib/consts/comman_button.dart b/lib/consts/comman_button.dart index da96dd8..ad727e2 100644 --- a/lib/consts/comman_button.dart +++ b/lib/consts/comman_button.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:taxglide/consts/app_colors.dart'; +import 'package:taxglide/consts/app_style.dart'; class CommanButton extends StatelessWidget { final String text; @@ -51,9 +52,7 @@ class CommanButton extends StatelessWidget { ], Text( text, - style: const TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.semiBold.copyWith( fontSize: 16, height: 1.4, letterSpacing: 0.03 * 16, diff --git a/lib/consts/comman_popup.dart b/lib/consts/comman_popup.dart index 5d867fe..75f4359 100644 --- a/lib/consts/comman_popup.dart +++ b/lib/consts/comman_popup.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:taxglide/consts/app_style.dart'; class CommonInfoPopup { /// 🔹 Show a reusable popup dialog @@ -22,10 +23,8 @@ class CommonInfoPopup { contentPadding: const EdgeInsets.fromLTRB(20, 0, 20, 10), title: Text( title, - style: const TextStyle( - fontFamily: 'Gilroy-Bold', + style: AppTextStyles.bold.copyWith( fontSize: 18, - fontWeight: FontWeight.w700, color: Colors.black87, ), ), @@ -48,8 +47,7 @@ class CommonInfoPopup { child: Text( content, textAlign: TextAlign.justify, - style: const TextStyle( - fontFamily: 'Gilroy-Medium', + style: AppTextStyles.regular.copyWith( fontSize: 14, height: 1.6, color: Colors.black54, @@ -63,15 +61,14 @@ class CommonInfoPopup { actions: [ TextButton( onPressed: () => Navigator.of(ctx).pop(), - child: const Text( - "Close", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontSize: 14, - color: Color(0xFF6A4BFC), - ), + child: Text( + "Close", + style: AppTextStyles.regular.copyWith( + fontSize: 14, + color: const Color(0xFF6A4BFC), ), ), + ), ], ); }, diff --git a/lib/consts/comman_serivce.dart b/lib/consts/comman_serivce.dart index ec976f4..8239604 100644 --- a/lib/consts/comman_serivce.dart +++ b/lib/consts/comman_serivce.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:get/get.dart'; import 'package:taxglide/consts/app_colors.dart'; import 'package:taxglide/model/serivce_list_model.dart'; @@ -67,9 +68,7 @@ class CommonServiceItem extends StatelessWidget { textAlign: TextAlign.center, maxLines: 2, overflow: TextOverflow.ellipsis, - style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 13, height: 1.3, letterSpacing: 0.02, diff --git a/lib/consts/comman_textformfileds.dart b/lib/consts/comman_textformfileds.dart index 03a14b4..ff69030 100644 --- a/lib/consts/comman_textformfileds.dart +++ b/lib/consts/comman_textformfileds.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:taxglide/consts/app_colors.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:flutter/services.dart'; class CommanTextFormField extends StatelessWidget { @@ -69,15 +70,13 @@ class CommanTextFormField extends StatelessWidget { prefixIcon: prefixIcon != null ? Icon(prefixIcon, color: AppColors.authleading) : null, - hintStyle: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w400, + hintStyle: AppTextStyles.medium.copyWith( fontSize: 11.31, height: 1.4, letterSpacing: 0.03, color: hasError ? Colors.red.withOpacity(0.6) - : Colors.grey.shade500, + : AppColors.authleading ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(6), @@ -85,7 +84,7 @@ class CommanTextFormField extends StatelessWidget { color: hasError ? Colors.red : readOnly - ? Colors.grey.shade300 + ? AppColors.authleading : const Color(0xFFDFDFDF), width: 1, ), @@ -113,13 +112,11 @@ class CommanTextFormField extends StatelessWidget { ), ), ), - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: 11.31, height: 1.4, letterSpacing: 0.03, - color: readOnly ? Colors.grey.shade600 : AppColors.authleading, + color: readOnly ? AppColors.authleading : AppColors.authleading, ), ), ); diff --git a/lib/consts/download_helper.dart b/lib/consts/download_helper.dart index c9590ce..c515d9d 100644 --- a/lib/consts/download_helper.dart +++ b/lib/consts/download_helper.dart @@ -1,10 +1,13 @@ import 'dart:io'; import 'package:dio/dio.dart'; +import 'package:flutter/material.dart'; +import 'package:get/get.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:open_filex/open_filex.dart'; import 'package:gal/gal.dart'; +import 'package:taxglide/services/notification_service.dart'; class DownloadHelper { static const String API_BASE_URL = "https://www.taxglide.amrithaa.net/api/"; @@ -254,6 +257,13 @@ class DownloadHelper { } print("✅ File downloaded to: $savePath"); + + // ⭐ Show Download Notification + try { + Get.find().showDownloadNotification(fileName, savePath); + } catch (e) { + debugPrint('⚠️ Could not show download notification: $e'); + } // Open the downloaded file await openDownloadedFile(savePath); @@ -349,6 +359,28 @@ class DownloadHelper { } } + /// ⭐ NEW: Open folder in system file manager + static Future openFolder(String path) async { + print("📂 Opening folder: $path"); + + try { + final dir = Directory(path); + if (!await dir.exists()) { + print("❌ Folder not found at $path"); + return; + } + + // On Android, most file managers respond well to OpenFilex on a directory + final result = await OpenFilex.open(path); + + if (result.type != ResultType.done) { + print("⚠️ Could not open folder: ${result.message}"); + } + } catch (e) { + print("❌ Error opening folder: $e"); + } + } + /// Get all files from Send folder static Future> getSentFiles() async { try { diff --git a/lib/consts/image_permission.dart b/lib/consts/image_permission.dart index 241909d..80a7b01 100644 --- a/lib/consts/image_permission.dart +++ b/lib/consts/image_permission.dart @@ -318,7 +318,7 @@ class LabeledTextField extends StatelessWidget { Text( label, style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontSize: 16, height: 1.3, @@ -391,7 +391,7 @@ class SingleImageSectionField extends StatelessWidget { Text( title, style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontSize: 16, height: 1.3, @@ -527,7 +527,7 @@ class FileUploadSectionField extends StatelessWidget { Text( title, style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontSize: 16, height: 1.3, diff --git a/lib/consts/local_store.dart b/lib/consts/local_store.dart index 9b3babf..0d1aba6 100644 --- a/lib/consts/local_store.dart +++ b/lib/consts/local_store.dart @@ -1,3 +1,4 @@ +import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; class LocalStore { @@ -10,7 +11,8 @@ class LocalStore { Future saveLoginData(Map data) async { final token = data['access_token'] ?? ''; final role = data['role'] ?? ''; - +debugPrint('token: $token'); +debugPrint('role: $role'); // Keep existing FCM token (do not overwrite) String? existingFcmToken = await _storage.read(key: 'fcm_token'); diff --git a/lib/consts/notification_webscoket.dart b/lib/consts/notification_webscoket.dart index 23c8002..06ee431 100644 --- a/lib/consts/notification_webscoket.dart +++ b/lib/consts/notification_webscoket.dart @@ -55,6 +55,16 @@ class NotificationWebSocket { _subscribeToChatChannel(chatId); } + /// Manually trigger a refresh for all providers watching `notificationTriggerProvider`. + void triggerRefresh() { + try { + _container?.read(notificationTriggerProvider.notifier).update((state) => state + 1); + debugPrint('🔔 NotificationWS: manual refresh triggered'); + } catch (e) { + debugPrint('⚠️ NotificationWS: triggerRefresh failed: $e'); + } + } + /// Connect (or skip if already connected for the same user). Future connect({ required String userId, diff --git a/lib/controller/api_contoller.dart b/lib/controller/api_contoller.dart index c2c702d..5526cd3 100644 --- a/lib/controller/api_contoller.dart +++ b/lib/controller/api_contoller.dart @@ -185,10 +185,14 @@ class ServiceHistoryNotifier fetchServiceHistory(); } - Future fetchServiceHistory() async { + Future fetchServiceHistory({bool isSilent = false}) async { try { if (!mounted) return; - state = const AsyncValue.loading(); + + // 🔄 Skip loading state for silent refresh + if (!isSilent) { + state = const AsyncValue.loading(); + } final repo = ref.read(apiRepositoryProvider); @@ -238,8 +242,6 @@ final notificationTriggerProvider = StateProvider((ref) => 0); // 🔥 fetch notification count API final notificationCountProvider = FutureProvider.autoDispose((ref) async { - ref.watch(notificationTriggerProvider); // listen for refresh trigger - final repo = ref.read(apiRepositoryProvider); return await repo.fetchNotificationCount(); }); @@ -409,34 +411,55 @@ class ChatMessagesNotifier return dateA.compareTo(dateB); }); - // ⭐ Check if we have any new messages - final lastMessageId = _messages.isNotEmpty ? _messages.last.id : -1; - final latestMessageId = result.last.id; + // ⭐ Merge strategy: + // 1. Update existing messages (read/delivered status) + // 2. Add new messages + bool hasChanges = false; - if (latestMessageId != lastMessageId) { - // ⭐ New messages found - merge them smoothly - print("✅ Found new messages, updating list"); + for (var incomingMsg in result) { + final existingIndex = _messages.indexWhere((m) => m.id == incomingMsg.id); + + if (existingIndex != -1) { + // Check if status changed + final existingMsg = _messages[existingIndex]; + if (existingMsg.isRead != incomingMsg.isRead || + existingMsg.isDelivered != incomingMsg.isDelivered) { + print("♻️ Updating status for message ID ${incomingMsg.id}"); + _messages[existingIndex] = incomingMsg; + hasChanges = true; + } + } else { + // ⭐ NEW: Check if this server message replaces an optimistic one + final optimisticIndex = _messages.indexWhere( + (m) => (m.id > 1000000000000 && + m.message == incomingMsg.message && + m.chatBy == incomingMsg.chatBy) + ); - // Add only new messages that don't exist in current list - for (var newMsg in result) { - final exists = _messages.any((m) => m.id == newMsg.id); - if (!exists) { - _messages.add(newMsg); + if (optimisticIndex != -1) { + print("🔄 refresh: Replacing optimistic message with ID ${incomingMsg.id}"); + _messages[optimisticIndex] = incomingMsg; + hasChanges = true; + } else { + // Truly new message (e.g. incoming from someone else) + print("➕ Adding new message ID ${incomingMsg.id}"); + _messages.add(incomingMsg); + hasChanges = true; } } + } - // Sort the entire list + if (hasChanges) { + // Sort the entire list to be sure _messages.sort((a, b) { - final dateA = - DateTime.tryParse(a.createdAt ?? '') ?? DateTime(1970); - final dateB = - DateTime.tryParse(b.createdAt ?? '') ?? DateTime(1970); + final dateA = DateTime.tryParse(a.createdAt ?? '') ?? DateTime(1970); + final dateB = DateTime.tryParse(b.createdAt ?? '') ?? DateTime(1970); return dateA.compareTo(dateB); }); - + if (mounted) state = AsyncData(List.from(_messages)); } else { - print("✅ No new messages"); + print("✅ No new messages or status changes"); } } } catch (e) { @@ -472,10 +495,8 @@ class ChatMessagesNotifier // 2. Check if this is a server confirmation of an optimistic message // Optimistic messages have large positive IDs from DateTime.now().millisecondsSinceEpoch - // OR content match for very recent messages final optimisticIndex = _messages.indexWhere( (m) => - // Match by content and sender if it's a very recent "local" message (m.id > 1000000000000 && m.message == msg.message && m.chatBy == msg.chatBy), @@ -489,6 +510,13 @@ class ChatMessagesNotifier _messages.add(msg); } + // Sort to ensure order (important if multiple local messages are sent) + _messages.sort((a, b) { + final dateA = DateTime.tryParse(a.createdAt ?? '') ?? DateTime(1970); + final dateB = DateTime.tryParse(b.createdAt ?? '') ?? DateTime(1970); + return dateA.compareTo(dateB); + }); + if (mounted) state = AsyncData(List.from(_messages)); } diff --git a/lib/controller/api_repository.dart b/lib/controller/api_repository.dart index 2ff9546..370c32d 100644 --- a/lib/controller/api_repository.dart +++ b/lib/controller/api_repository.dart @@ -458,7 +458,7 @@ class ApiRepository { headers: await _authorizedHeaders(), ); }); - + debugPrint("response: ${response.body}"); if (response.statusCode == 200) { final data = jsonDecode(response.body); return DetailModel.fromJson(data); @@ -635,17 +635,17 @@ class ApiRepository { File? panFile, File? gstFile, File? incorporationFile, - required int countryId, - required int stateId, - required int cityId, - required String companyPincode, - required String companyAddress, - required String panNumber, - required String gstNumber, - required String tanNumber, - required String cinNumber, - required String yearOfIncorporation, - required String address, + int? countryId, + int? stateId, + int? cityId, + String? companyPincode, + String? companyAddress, + String? panNumber, + String? gstNumber, + String? tanNumber, + String? cinNumber, + String? yearOfIncorporation, + String? address, }) async { try { final token = await _localStore.getToken(); @@ -658,17 +658,17 @@ class ApiRepository { 'Connection': 'keep-alive', }) ..fields.addAll({ - 'country_id': countryId.toString(), - 'state_id': stateId.toString(), - 'district_id': cityId.toString(), - 'company_pincode': companyPincode, - 'company_address': companyAddress, - 'pan_number': panNumber, - 'gst_number': gstNumber, - 'tan_number': tanNumber, - 'cin': cinNumber, - 'year_of_incorporation': yearOfIncorporation, - 'address': address, + if (countryId != null) 'country_id': countryId.toString(), + if (stateId != null) 'state_id': stateId.toString(), + if (cityId != null) 'district_id': cityId.toString(), + if (companyPincode != null) 'company_pincode': companyPincode, + if (companyAddress != null) 'company_address': companyAddress, + if (panNumber != null) 'pan_number': panNumber, + if (gstNumber != null) 'gst_number': gstNumber, + if (tanNumber != null) 'tan_number': tanNumber, + if (cinNumber != null) 'cin': cinNumber, + if (yearOfIncorporation != null) 'year_of_incorporation': yearOfIncorporation, + if (address != null) 'address': address, }); await Future.wait([ @@ -686,7 +686,8 @@ class ApiRepository { ); final response = await http.Response.fromStream(streamedResponse); - +debugPrint('📦 KYC Response Status: ${response.statusCode}'); +debugPrint('📦 KYC Response Body: ${response.body}'); // Handle token expiry if (response.statusCode == 401 || response.statusCode == 403) { await _handleUnauthorized(); diff --git a/lib/firebase_options.dart b/lib/firebase_options.dart index c39f6b8..25de6ca 100644 --- a/lib/firebase_options.dart +++ b/lib/firebase_options.dart @@ -85,4 +85,4 @@ class DefaultFirebaseOptions { storageBucket: 'taxglide-bd535.firebasestorage.app', measurementId: 'G-14E4NG37P2', ); -} \ No newline at end of file +} diff --git a/lib/main.dart b/lib/main.dart index 744ad4a..10a4330 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -6,6 +6,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:get/get.dart'; import 'package:file_picker/file_picker.dart'; import 'package:permission_handler/permission_handler.dart'; +import 'package:taxglide/consts/notification_webscoket.dart'; import 'firebase_options.dart'; import 'package:taxglide/router/router.dart'; @@ -138,6 +139,9 @@ void _setupFcmListeners() { message, tag: dedupTag, ); + + // 🔄 Trigger live refresh for detail screens/badge counts + NotificationWebSocket().triggerRefresh(); } }); @@ -232,6 +236,7 @@ class _TaxglideAppState extends State { getPages: AppRoutes.routes, theme: ThemeData( useMaterial3: true, + fontFamily: 'Gilroy', colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue), ), ); diff --git a/lib/model/detail_model.dart b/lib/model/detail_model.dart index d394c63..9bd6dd0 100644 --- a/lib/model/detail_model.dart +++ b/lib/model/detail_model.dart @@ -50,12 +50,13 @@ class DetailData { final String? proforma; final int? proformaId; final String? proformaNumber; - final String? proformastatus; + final String? proformaStatus; final String? createdDate; final String? createdTime; final String? createdBy; final String? message; + final String? subject; final String? completedDate; final String? paidBy; @@ -70,7 +71,7 @@ class DetailData { this.firmId, this.dueDate, this.service, - this.proformastatus, + this.proformaStatus, this.serviceStatus, this.paymentStatus, this.paidStatus, @@ -85,6 +86,7 @@ class DetailData { this.createdTime, this.createdBy, this.message, + this.subject, this.completedDate, this.paidBy, required this.userUploadedDocuments, @@ -102,7 +104,7 @@ class DetailData { serviceStatus: json["service_status"], paymentStatus: json["payment_status"], - proformastatus: json["proforma_status"], + proformaStatus: json["proforma_status"], paidStatus: json["paid_status"], paymentDate: json["payment_date"], paymentAmount: json["payment_amount"]?.toString(), @@ -119,6 +121,7 @@ class DetailData { createdBy: json["created_by"], message: json["message"], + subject: json["subject"], completedDate: json["completed_date"], paidBy: json["paid_by"], @@ -153,7 +156,7 @@ class DetailData { "payment_date": paymentDate, "payment_amount": paymentAmount, "invoice": invoice, - "proforma_status": proformastatus, + "proforma_status": proformaStatus, "invoice_number": invoiceNumber, "proforma": proforma, "proforma_id": proformaId, @@ -162,6 +165,7 @@ class DetailData { "created_time": createdTime, "created_by": createdBy, "message": message, + "subject": subject, "completed_date": completedDate, "paid_by": paidBy, "user_uploaded_documents": userUploadedDocuments diff --git a/lib/model/service_list_history_model.dart b/lib/model/service_list_history_model.dart index f6a8451..76231d8 100644 --- a/lib/model/service_list_history_model.dart +++ b/lib/model/service_list_history_model.dart @@ -42,23 +42,41 @@ class ServiceListHistoryModel { class ServiceHistoryData { final int? id; + final String? name; + final String? firmName; final String? paymentStatus; final String? paymentAmount; final String? status; final String? service; final String? message; + final String? subject; + final String? assignee; final String? createdDate; final String? createdTime; + final String? createdAt; + final int? actions; + final int? chatId; + final int? isProformaGenerated; + final String? paymentId; ServiceHistoryData({ this.id, + this.name, + this.firmName, this.paymentStatus, this.paymentAmount, this.status, this.service, this.message, + this.subject, + this.assignee, this.createdDate, this.createdTime, + this.createdAt, + this.actions, + this.chatId, + this.isProformaGenerated, + this.paymentId, }); factory ServiceHistoryData.fromJson(Map json) { @@ -66,26 +84,50 @@ class ServiceHistoryData { id: json['id'] is int ? json['id'] : int.tryParse(json['id']?.toString() ?? ''), + name: json['name']?.toString(), + firmName: json['firm_name']?.toString(), paymentStatus: json['payment_status']?.toString(), paymentAmount: json['payment_amount']?.toString(), status: json['status']?.toString(), service: json['service']?.toString(), message: json['message']?.toString(), + subject: json['subject']?.toString(), + assignee: json['assignee']?.toString(), createdDate: json['created_date']?.toString(), createdTime: json['created_time']?.toString(), + createdAt: json['created_at']?.toString(), + actions: json['actions'] is int + ? json['actions'] + : int.tryParse(json['actions']?.toString() ?? ''), + chatId: json['chat_id'] is int + ? json['chat_id'] + : int.tryParse(json['chat_id']?.toString() ?? ''), + isProformaGenerated: json['is_proforma_generated'] is int + ? json['is_proforma_generated'] + : int.tryParse(json['is_proforma_generated']?.toString() ?? ''), + paymentId: json['payment_id']?.toString(), ); } Map toJson() { return { 'id': id, + 'name': name, + 'firm_name': firmName, 'payment_status': paymentStatus, 'payment_amount': paymentAmount, 'status': status, 'service': service, 'message': message, + 'subject': subject, + 'assignee': assignee, 'created_date': createdDate, 'created_time': createdTime, + 'created_at': createdAt, + 'actions': actions, + 'chat_id': chatId, + 'is_proforma_generated': isProformaGenerated, + 'payment_id': paymentId, }; } } diff --git a/lib/services/notification_service.dart b/lib/services/notification_service.dart index 5ef7a2c..870b1b4 100644 --- a/lib/services/notification_service.dart +++ b/lib/services/notification_service.dart @@ -2,6 +2,7 @@ import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:get/get.dart'; +import 'package:taxglide/consts/download_helper.dart'; import 'package:taxglide/consts/local_store.dart'; import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart'; import 'package:taxglide/view/Main_controller/main_controller.dart'; @@ -26,6 +27,16 @@ const AndroidNotificationChannel _channel = AndroidNotificationChannel( enableVibration: true, ); +/// Android notification channel for download updates. +const AndroidNotificationChannel _downloadChannel = AndroidNotificationChannel( + 'taxglide_downloads', + 'TaxGlide Downloads', + description: 'Notifications for file downloads', + importance: Importance.high, + playSound: true, + enableVibration: true, +); + /// Call once in main() after Firebase.initializeApp(). Future initLocalNotifications() async { const initSettings = InitializationSettings( @@ -37,19 +48,34 @@ Future initLocalNotifications() async { initSettings, onDidReceiveNotificationResponse: (NotificationResponse response) { // Notification tapped while app is open – handled inside NotificationService. - debugPrint('🔔 Local notification tapped: payload=${response.payload}'); + debugPrint('🔔 Local notification action: ${response.actionId} payload=${response.payload}'); + + if (response.actionId == 'location') { + final payload = response.payload; + if (payload != null && payload.startsWith('download:')) { + final filePath = payload.replaceFirst('download:', ''); + final String dirPath = filePath.substring(0, filePath.lastIndexOf('/')); + debugPrint('📂 Opening folder from notification: $dirPath'); + // Open the system file manager at this location + DownloadHelper.openFolder(dirPath); + return; + } + } + Get.find().handleNavigationFromPayload( response.payload, ); }, ); - // Create the Android channel (no-op on iOS). - await flutterLocalNotificationsPlugin + // Create the channels + final androidPlugin = flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin - >() - ?.createNotificationChannel(_channel); + >(); + + await androidPlugin?.createNotificationChannel(_channel); + await androidPlugin?.createNotificationChannel(_downloadChannel); debugPrint('✅ LocalNotifications initialized'); } @@ -123,6 +149,55 @@ class NotificationService extends GetxController { ); } + /// Shows a notification when a file is successfully downloaded. + /// [filename] is the base name of the file. + /// [filePath] is the absolute path to the local file. + void showDownloadNotification(String filename, String filePath) { + debugPrint('📩 NotificationService: showing download success: $filename'); + + flutterLocalNotificationsPlugin.show( + filename.hashCode.abs() % 100000, + 'Download Complete', + 'File saved: $filename', + NotificationDetails( + android: AndroidNotificationDetails( + _downloadChannel.id, + _downloadChannel.name, + channelDescription: _downloadChannel.description, + importance: Importance.high, + priority: Priority.high, + icon: '@mipmap/launcher_icon', + playSound: true, + styleInformation: BigTextStyleInformation( + 'The file **$filename** has been saved to your downloads folder:\n\n$filePath', + contentTitle: 'Download Complete', + summaryText: 'TaxGlide Download', + htmlFormatContent: true, + htmlFormatTitle: true, + ), + actions: [ + const AndroidNotificationAction( + 'view', + 'View File', + showsUserInterface: true, + ), + const AndroidNotificationAction( + 'location', + 'Show in Folder', + showsUserInterface: true, + ), + ], + ), + iOS: const DarwinNotificationDetails( + presentAlert: true, + presentBadge: true, + presentSound: true, + ), + ), + payload: 'download:$filePath', + ); + } + // ── Navigation helpers ────────────────────────────────────────────────────── /// Called when a local notification is tapped (payload = "type:id"). @@ -131,6 +206,15 @@ class NotificationService extends GetxController { _safeNavigate(() => Get.offAll(() => MainController())); return; } + + // ⭐ Handle file download notifications + if (payload.startsWith('download:')) { + final filePath = payload.replaceFirst('download:', ''); + debugPrint('📂 Opening downloaded file from notification: $filePath'); + DownloadHelper.openDownloadedFile(filePath); + return; + } + final parts = payload.split(':'); final type = parts.isNotEmpty ? parts[0] : null; final idStr = parts.length > 1 ? parts[1] : null; diff --git a/lib/view/Mahi_chat/chat_profile_screen.dart b/lib/view/Mahi_chat/chat_profile_screen.dart index 5a86000..3582bf7 100644 --- a/lib/view/Mahi_chat/chat_profile_screen.dart +++ b/lib/view/Mahi_chat/chat_profile_screen.dart @@ -39,7 +39,7 @@ class ChatProfileScreen extends ConsumerWidget { title: const Text( "Profile", style: TextStyle( - fontFamily: "Gilroy-SemiBold", + fontFamily: "Gilroy", fontWeight: FontWeight.w400, fontSize: 20, height: 1.4, @@ -113,7 +113,7 @@ class ChatProfileScreen extends ConsumerWidget { const Text( "Shared By Taxglide", style: TextStyle( - fontFamily: "Gilroy-SemiBold", + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontSize: 20, height: 1.4, @@ -213,7 +213,7 @@ class ChatProfileScreen extends ConsumerWidget { const Text( "Shared By Client", style: TextStyle( - fontFamily: "Gilroy-SemiBold", + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontSize: 20, height: 1.4, diff --git a/lib/view/Mahi_chat/comman_input_button.dart b/lib/view/Mahi_chat/comman_input_button.dart index eb7ccf5..5819023 100644 --- a/lib/view/Mahi_chat/comman_input_button.dart +++ b/lib/view/Mahi_chat/comman_input_button.dart @@ -7,6 +7,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:taxglide/consts/download_helper.dart'; import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/controller/api_repository.dart'; +import 'package:taxglide/model/chat_model.dart'; import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart'; // ⭐⭐⭐ CHAT INPUT BOX WITH FILE TAG SUPPORT ⭐⭐⭐ @@ -246,49 +247,61 @@ class _ChatInputBoxState extends ConsumerState { setState(() => _isSending = true); - // Show loading dialog - showDialog( - context: context, - barrierDismissible: false, - builder: (context) => WillPopScope( - onWillPop: () async => false, - child: const Center( - child: Card( - child: Padding( - padding: EdgeInsets.all(20), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - CircularProgressIndicator(), - SizedBox(height: 16), - Text("Sending message..."), - ], - ), - ), - ), - ), - ), + // ⭐ OPTIMISTIC UI: Create a temporary message and add it immediately + final tempId = DateTime.now().millisecondsSinceEpoch; + final tempMsg = MessageModel( + id: tempId, + chatBy: "user", // User + message: text, + type: selectedFiles.isNotEmpty ? "file" : "text", + isDelivered: 0, + isRead: 0, + createdAt: DateTime.now().toIso8601String(), + userId: 0, + tagId: tagId > 0 ? tagId : null, + parentTag: taggedMessage != null ? ParentTagModel( + id: taggedMessage.id, + message: taggedMessage.message, + type: taggedMessage.type, + fileName: taggedMessage.fileName, + ) : null, + uploadedDocuments: selectedFiles.map((file) => DocumentModel( + filePath: file.path, + fileName: file.path.split('/').last, + fileType: "image", + )).toList(), + documents: [], ); + // Add to UI immediately + final notifier = ref.read(chatMessagesProvider(widget.chatId).notifier); + notifier.addNewMessage(tempMsg); + + // Clear input immediately for snappy feel + final savedSelectedFiles = List.from(selectedFiles); + messageCtrl.clear(); + selectedFiles.clear(); + ref.read(taggedMessageProvider.notifier).state = null; + + // Notify parent to scroll to bottom instantly + if (widget.onMessageSent != null) { + widget.onMessageSent!(); + } + try { List filesToUpload = []; // ⭐⭐⭐ Save files to Send folder - if (selectedFiles.isNotEmpty) { - print("📤 Saving ${selectedFiles.length} files to Send folder..."); - - for (File file in selectedFiles) { + if (savedSelectedFiles.isNotEmpty) { + for (File file in savedSelectedFiles) { try { // Try to save to Send folder, fallback to original if fails final savedPath = await DownloadHelper.saveToSendFolder(file); filesToUpload.add(File(savedPath)); } catch (e) { - print("⚠️ Could not save file, using original: $e"); filesToUpload.add(file); } } - - print("✅ Files prepared for upload: ${filesToUpload.length}"); } // Send message with files @@ -299,37 +312,22 @@ class _ChatInputBoxState extends ConsumerState { files: filesToUpload, ); - // Refresh chat messages - await ref.read(chatMessagesProvider(widget.chatId).notifier).refresh(); + // Refresh chat messages (this will replace the temp message with the real one) + await notifier.refresh(); ref.invalidate(chatDocumentProvider); - print("✅ Message sent successfully with tagId: $tagId"); - - // Close loading dialog - if (mounted) Navigator.pop(context); - - // Clear input + if (mounted) { - setState(() { - messageCtrl.clear(); - selectedFiles.clear(); - _isSending = false; - }); - } - - // Clear the tagged message - ref.read(taggedMessageProvider.notifier).state = null; - - // Notify parent to scroll to bottom - if (widget.onMessageSent != null) { - widget.onMessageSent!(); + setState(() => _isSending = false); } } catch (e) { print("❌ Error sending message: $e"); + + if (mounted) { + setState(() => _isSending = false); + } - // Close loading dialog - if (mounted) Navigator.pop(context); - - setState(() => _isSending = false); + // If it failed, delete the temporary message + notifier.deleteMessage(tempId); // Show error message if (mounted) { @@ -361,6 +359,7 @@ class _ChatInputBoxState extends ConsumerState { } } + @override Widget build(BuildContext context) { final taggedMessage = ref.watch(taggedMessageProvider); diff --git a/lib/view/Mahi_chat/downloadchat.dart b/lib/view/Mahi_chat/downloadchat.dart index fa05cc3..b96d682 100644 --- a/lib/view/Mahi_chat/downloadchat.dart +++ b/lib/view/Mahi_chat/downloadchat.dart @@ -270,7 +270,7 @@ class _DownloadsScreenState extends State title: const Text( "Downloads", style: TextStyle( - fontFamily: "Gilroy-SemiBold", + fontFamily: "Gilroy", fontWeight: FontWeight.w600, ), ), diff --git a/lib/view/Mahi_chat/file_images_screen.dart b/lib/view/Mahi_chat/file_images_screen.dart index 2c8a24a..7ab9096 100644 --- a/lib/view/Mahi_chat/file_images_screen.dart +++ b/lib/view/Mahi_chat/file_images_screen.dart @@ -9,7 +9,7 @@ class SwipeableMessageBubble extends StatefulWidget { final MessageModel message; final DateTime msgDate; final String Function(DateTime) formatTime; - final Widget Function(int, int) buildTick; + final Widget Function(MessageModel) buildTick; final VoidCallback onSwipe; final Function(int?)? onParentTagTap; final Function(List imageUrls, int initialIndex)? @@ -669,10 +669,7 @@ class SwipeableMessageBubbleState extends State ), ), const SizedBox(width: 4), - widget.buildTick( - widget.message.isDelivered, - widget.message.isRead, - ), + widget.buildTick(widget.message), ], ), ], diff --git a/lib/view/Mahi_chat/live_chat_screen.dart b/lib/view/Mahi_chat/live_chat_screen.dart index 5404749..841fa7c 100644 --- a/lib/view/Mahi_chat/live_chat_screen.dart +++ b/lib/view/Mahi_chat/live_chat_screen.dart @@ -160,8 +160,11 @@ class _LiveChatScreenState extends ConsumerState try { final event = message['event'] as String?; - if (event == 'message.sent' || event == 'message.received') { - debugPrint("🔔 New message detected!"); + if (event == 'message.sent' || + event == 'message.received' || + event == 'message.read' || + event == 'message.delivered') { + debugPrint("🔔 Message status/new message event: $event"); if (WidgetsBinding.instance.lifecycleState == AppLifecycleState.resumed) { @@ -409,7 +412,16 @@ class _LiveChatScreenState extends ConsumerState return "$hour:$minute $period"; } - Widget buildTick(int isDelivered, int isRead) { + Widget buildTick(MessageModel message) { + // ⭐ Status 0/1/pending + final isRead = message.isRead; + final isDelivered = message.isDelivered; + + // Check if it's an optimistic pending message (huge ID) + if (message.id > 1000000000000) { + return const Icon(Icons.schedule, size: 14, color: Colors.grey); + } + if (isRead == 1) { return const Icon(Icons.done_all, size: 16, color: Colors.blue); } else if (isDelivered == 1) { @@ -445,7 +457,7 @@ class _LiveChatScreenState extends ConsumerState ? 'File ID : ${widget.fileid.toString()}' : "Live Chat", style: const TextStyle( - fontFamily: "Gilroy-SemiBold", + fontFamily: "Gilroy", fontWeight: FontWeight.w600, ), ), diff --git a/lib/view/Main_controller/comman_chat_box.dart b/lib/view/Main_controller/comman_chat_box.dart index fbe97a1..54a8e76 100644 --- a/lib/view/Main_controller/comman_chat_box.dart +++ b/lib/view/Main_controller/comman_chat_box.dart @@ -1,12 +1,14 @@ import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:taxglide/consts/app_asstes.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:taxglide/consts/comman_webscoket.dart'; import 'package:taxglide/consts/local_store.dart'; import 'package:taxglide/consts/notification_webscoket.dart'; import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:taxglide/consts/responsive_helper.dart'; class CommanChatBox extends ConsumerStatefulWidget { final String? chatId; @@ -86,11 +88,12 @@ class _CommanChatBoxState extends ConsumerState { } final id = snapshot.data ?? "0"; + final r = ResponsiveUtils(context); final countAsync = ref.watch(countProvider(id)); return Positioned( right: 20, - bottom: 120, + bottom: r.spacing(mobile: 35, tablet: 45, desktop: 55), child: Stack( clipBehavior: Clip.none, children: [ @@ -154,10 +157,9 @@ class _CommanChatBoxState extends ConsumerState { ), child: Text( data.count.toString(), - style: const TextStyle( + style: AppTextStyles.bold.copyWith( color: Colors.white, - fontSize: 11, - fontWeight: FontWeight.bold, + fontSize: 10, ), ), ); diff --git a/lib/view/Main_controller/main_controller.dart b/lib/view/Main_controller/main_controller.dart index 606534d..9755d34 100644 --- a/lib/view/Main_controller/main_controller.dart +++ b/lib/view/Main_controller/main_controller.dart @@ -13,6 +13,9 @@ import 'package:taxglide/view/screens/home_screen.dart'; import 'package:taxglide/view/screens/list_service_screen.dart'; import 'package:taxglide/view/screens/profile/employee_profile/employee_profile_screen.dart'; import 'package:taxglide/view/screens/profile/profile_screen.dart'; +import 'package:curved_labeled_navigation_bar/curved_navigation_bar.dart'; +import 'package:curved_labeled_navigation_bar/curved_navigation_bar_item.dart'; +import 'package:taxglide/consts/app_style.dart'; class MainController extends ConsumerStatefulWidget { final Widget? child; // Optional child (like ServiceRequestScreen) @@ -39,7 +42,7 @@ class _MainControllerState extends ConsumerState { final List _labels = [ 'Home', 'Services', - 'Service Details', + 'Task Status', 'Profile', ]; @@ -177,65 +180,6 @@ class _MainControllerState extends ConsumerState { body: Stack( children: [ mainContent, - - /// ✅ Bottom Navigation Bar - Positioned( - bottom: 0, - left: 0, - child: SafeArea( - top: false, - child: Container( - width: size.width, - height: 80, - child: Stack( - clipBehavior: Clip.none, - children: [ - CustomPaint( - size: Size(size.width, 80), - painter: BNBCustomPainter(), - ), - Center( - heightFactor: 0.6, - child: GestureDetector( - onTap: () {}, - child: CustomPaint( - painter: PentagonPainter( - color: const Color(0xFF61277A), - ), - child: Container( - width: 70, - height: 70, - alignment: Alignment.center, - child: Image.asset( - AppAssets.maincontroller, - color: Colors.white, - fit: BoxFit.contain, - height: 40, - width: 40, - ), - ), - ), - ), - ), - SizedBox( - width: size.width, - height: 80, - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - _buildNavItem(Icons.home, 0, _labels[0]), - _buildNavItem(Icons.list_alt_sharp, 1, _labels[1]), - SizedBox(width: size.width * 0.20), - _buildNavItem(Icons.history_edu, 2, _labels[2]), - _buildNavItem(Icons.person_2, 3, _labels[3]), - ], - ), - ), - ], - ), - ), - ), - ), dashboardAsync.when( data: (dashboard) { final int? chatIdInt = dashboard.generalChatId; @@ -253,199 +197,89 @@ class _MainControllerState extends ConsumerState { ), ], ), - ), - ); - } - - /// ✅ Navigation Logic with Refresh - Widget _buildNavItem(IconData icon, int index, String label) { - bool isSelected = currentIndex == index; - - return GestureDetector( - onTap: () { - // 🔹 If inside ServiceRequestScreen - if (widget.child != null) { - if (widget.initialIndex == index) return; - - if (widget.sourceTabIndex == 0 && index == 1) { - Get.offAll(() => const MainController(initialIndex: 1)); - return; - } - - if (widget.sourceTabIndex == 1 && index == 1) return; - - Get.offAll(() => MainController(initialIndex: index)); - return; - } - - // 🔹 If same tab tapped again → refresh - if (currentIndex == index) { - _refreshTab(index); - return; - } - - // 🔹 Switch to a different tab - setBottomBarIndex(index); - }, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - AnimatedContainer( - duration: const Duration(milliseconds: 200), - padding: const EdgeInsets.all(6), - decoration: BoxDecoration( - shape: BoxShape.circle, - border: isSelected - ? Border.all(color: const Color(0xFF61277A), width: 2) - : null, - ), - child: Icon( - icon, - color: isSelected - ? const Color(0xFF61277A) - : const Color(0xFF6C7278), - size: isSelected ? 19.5 : 20.8, - ), - ), - if (isSelected) - Padding( - padding: const EdgeInsets.only(top: 4), - child: Text( - label, - style: const TextStyle( - color: Color(0xFF61277A), + bottomNavigationBar: SafeArea( + top: false, + child: CurvedNavigationBar( + backgroundColor: Color(0xFF61277A), + buttonBackgroundColor: Colors.white, + color: Colors.white, + animationDuration: const Duration(milliseconds: 300), + index: currentIndex, + items: [ + CurvedNavigationBarItem( + child: Icon( + Icons.home, + color: currentIndex == 0 ? Colors.black : const Color(0xFF6C7278), + ), + label: _labels[0], + labelStyle: (currentIndex == 0 ? AppTextStyles.bold : AppTextStyles.bold).copyWith( + color: currentIndex == 0 ? const Color(0xFF61277A) : const Color(0xFF6C7278), fontSize: 12, - fontWeight: FontWeight.w600, ), ), - ), - ], + CurvedNavigationBarItem( + child: Icon( + Icons.list_alt_sharp, + color: currentIndex == 1 ? Colors.black : const Color(0xFF6C7278), + ), + label: _labels[1], + labelStyle: (currentIndex == 0 ? AppTextStyles.bold : AppTextStyles.bold).copyWith( + color: currentIndex == 1 ? const Color(0xFF61277A) : const Color(0xFF6C7278), + fontSize: 12, + ), + ), + CurvedNavigationBarItem( + child: Icon( + Icons.history_edu, + color: currentIndex == 2 ? Colors.black : const Color(0xFF6C7278), + ), + label: _labels[2], + labelStyle: (currentIndex == 0 ? AppTextStyles.bold : AppTextStyles.bold).copyWith( + color: currentIndex == 2 ? const Color(0xFF61277A) : const Color(0xFF6C7278), + fontSize: 12, + ), + ), + CurvedNavigationBarItem( + child: Icon( + Icons.person_2, + color: currentIndex == 3 ? Colors.black : const Color(0xFF6C7278), + ), + label: _labels[3], + labelStyle: (currentIndex == 0 ? AppTextStyles.bold : AppTextStyles.bold).copyWith( + color: currentIndex == 3 ? const Color(0xFF61277A) : const Color(0xFF6C7278), + fontSize: 12, + ), + ), + ], + onTap: (index) { + // 🔹 If inside ServiceRequestScreen + if (widget.child != null) { + if (widget.initialIndex == index) return; + + if (widget.sourceTabIndex == 0 && index == 1) { + Get.offAll(() => const MainController(initialIndex: 1)); + return; + } + + if (widget.sourceTabIndex == 1 && index == 1) return; + + Get.offAll(() => MainController(initialIndex: index)); + return; + } + + // 🔹 If same tab tapped again → refresh + if (currentIndex == index) { + _refreshTab(index); + return; + } + + // 🔹 Switch to a different tab + setBottomBarIndex(index); + }, + ), + ), ), ); } -} - -/// ✅ Custom Curved Bottom Navigation Painter -class BNBCustomPainter extends CustomPainter { - @override - void paint(Canvas canvas, Size size) { - Paint paint = Paint() - ..color = Colors.white - ..style = PaintingStyle.fill; - - Path path = Path(); - path.moveTo(0, 20); - path.quadraticBezierTo(size.width * 0.20, 0, size.width * 0.35, 0); - path.quadraticBezierTo(size.width * 0.40, 0, size.width * 0.40, 20); - path.arcToPoint( - Offset(size.width * 0.60, 20), - radius: const Radius.circular(20.0), - clockwise: false, - ); - path.quadraticBezierTo(size.width * 0.60, 0, size.width * 0.65, 0); - path.quadraticBezierTo(size.width * 0.80, 0, size.width, 20); - path.lineTo(size.width, size.height); - path.lineTo(0, size.height); - path.close(); - - canvas.drawShadow(path, Colors.black.withOpacity(0.2), 5, true); - canvas.drawPath(path, paint); - } - - @override - bool shouldRepaint(CustomPainter oldDelegate) => false; -} - -/// ✅ Pentagon Button Painter -/// ✅ Pentagon Button Painter -class PentagonPainter extends CustomPainter { - final Color color; - final double cornerRadius; - - PentagonPainter({ - required this.color, - this.cornerRadius = 8.0, // Adjust this value for more/less rounding - }); - - @override - void paint(Canvas canvas, Size size) { - final paint = Paint() - ..color = color - ..style = PaintingStyle.fill; - - final double w = size.width; - final double cx = w / 2; - final double cy = size.height / 2; - final double r = w / 2; - - // Calculate pentagon vertices - List vertices = []; - for (int i = 0; i < 5; i++) { - double angle = (72 * i - 90) * math.pi / 180; - double x = cx + r * 0.95 * math.cos(angle); - double y = cy + r * 0.95 * math.sin(angle); - vertices.add(Offset(x, y)); - } - - // Create path with rounded corners - final path = Path(); - - for (int i = 0; i < vertices.length; i++) { - final current = vertices[i]; - final next = vertices[(i + 1) % vertices.length]; - final prev = vertices[(i - 1 + vertices.length) % vertices.length]; - - // Calculate direction vectors - final toCurrent = Offset(current.dx - prev.dx, current.dy - prev.dy); - final toNext = Offset(next.dx - current.dx, next.dy - current.dy); - - // Normalize and scale by corner radius - final lengthToCurrent = math.sqrt( - toCurrent.dx * toCurrent.dx + toCurrent.dy * toCurrent.dy, - ); - final lengthToNext = math.sqrt( - toNext.dx * toNext.dx + toNext.dy * toNext.dy, - ); - - final normalizedToCurrent = Offset( - toCurrent.dx / lengthToCurrent, - toCurrent.dy / lengthToCurrent, - ); - final normalizedToNext = Offset( - toNext.dx / lengthToNext, - toNext.dy / lengthToNext, - ); - - // Points before and after the corner - final beforeCorner = Offset( - current.dx - normalizedToCurrent.dx * cornerRadius, - current.dy - normalizedToCurrent.dy * cornerRadius, - ); - final afterCorner = Offset( - current.dx + normalizedToNext.dx * cornerRadius, - current.dy + normalizedToNext.dy * cornerRadius, - ); - - if (i == 0) { - path.moveTo(beforeCorner.dx, beforeCorner.dy); - } else { - path.lineTo(beforeCorner.dx, beforeCorner.dy); - } - - // Draw rounded corner using quadratic bezier - path.quadraticBezierTo( - current.dx, - current.dy, - afterCorner.dx, - afterCorner.dy, - ); - } - path.close(); - - canvas.drawShadow(path, Colors.black.withOpacity(0.3), 4, true); - canvas.drawPath(path, paint); - } - - @override - bool shouldRepaint(CustomPainter oldDelegate) => false; + } diff --git a/lib/view/screens/history/completed_live_chat_screen.dart b/lib/view/screens/history/completed_live_chat_screen.dart index 1507e14..e7addd6 100644 --- a/lib/view/screens/history/completed_live_chat_screen.dart +++ b/lib/view/screens/history/completed_live_chat_screen.dart @@ -4,6 +4,7 @@ import 'package:flutter_riverpod/legacy.dart'; import 'package:get/get.dart'; import 'package:get/get_core/src/get_main.dart'; import 'package:taxglide/consts/app_asstes.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/model/chat_model.dart'; import 'package:taxglide/view/Mahi_chat/chat_profile_screen.dart'; @@ -193,8 +194,11 @@ class _CompletedLiveChatScreenState try { final event = message['event'] as String?; - if (event == 'message.sent' || event == 'message.received') { - debugPrint("🔔 New message detected!"); + if (event == 'message.sent' || + event == 'message.received' || + event == 'message.read' || + event == 'message.delivered') { + debugPrint("🔔 Message status/new message event: $event"); if (WidgetsBinding.instance.lifecycleState == AppLifecycleState.resumed) { @@ -332,7 +336,11 @@ class _CompletedLiveChatScreenState return "$hour:$minute $period"; } - Widget buildTick(int isDelivered, int isRead) { + Widget buildTick(MessageModel message) { + // ⭐ Status 0/1 + final isRead = message.isRead; + final isDelivered = message.isDelivered; + if (isRead == 1) { return const Icon(Icons.done_all, size: 16, color: Colors.blue); } else if (isDelivered == 1) { @@ -357,9 +365,9 @@ class _CompletedLiveChatScreenState widget.fileid.toString() != "0") ? 'File ID : ${widget.fileid.toString()}' : "Live Chat", - style: const TextStyle( - fontFamily: "Gilroy-SemiBold", - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( + fontSize: 16, + color: Colors.black, ), ), backgroundColor: Colors.white, diff --git a/lib/view/screens/history/detail_screen.dart b/lib/view/screens/history/detail_screen.dart index 3cefffe..7ae8c2d 100644 --- a/lib/view/screens/history/detail_screen.dart +++ b/lib/view/screens/history/detail_screen.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:get/get.dart'; import 'package:taxglide/consts/app_asstes.dart'; import 'package:taxglide/consts/comman_button.dart'; @@ -183,9 +184,7 @@ class _DetailScreenState extends ConsumerState { label: Text( "Invoice Not Available", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.045, height: 1.3, letterSpacing: 0.04 * 17.64, @@ -239,9 +238,7 @@ class _DetailScreenState extends ConsumerState { ? "View Invoice" : "Download Invoice", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.045, height: 1.3, letterSpacing: 0.04 * 17.64, @@ -312,9 +309,7 @@ class _DetailScreenState extends ConsumerState { : isDownloaded ? "View Proforma" : "Download Proforma", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 12, height: 1.3, letterSpacing: 0.04 * 14.47, @@ -337,6 +332,22 @@ class _DetailScreenState extends ConsumerState { final detailAsync = ref.watch(serviceDetailProvider(widget.id)); + // 🔄 Silent refresh when notification trigger changes + ref.listen(notificationTriggerProvider, (previous, next) { + if (previous != null && next != previous) { + debugPrint("🔔 Silent refresh triggered for DetailScreen"); + ref.refresh(serviceDetailProvider(widget.id)); + + // Also refresh unread count if available + detailAsync.whenData((model) { + final chatId = model.data?.chatId; + if (chatId != null && chatId.isNotEmpty) { + ref.refresh(countProvider(chatId)); + } + }); + } + }); + return Scaffold( body: Container( height: height, @@ -349,16 +360,16 @@ class _DetailScreenState extends ConsumerState { ), child: SafeArea( child: detailAsync.when( + skipLoadingOnRefresh: true, loading: () => const Center( child: CircularProgressIndicator(color: Colors.deepPurple), ), error: (e, _) => Center( child: Text( "Error: $e", - style: const TextStyle( + style: AppTextStyles.regular.copyWith( color: Colors.red, fontSize: 16, - fontFamily: 'Gilroy-Medium', ), ), ), @@ -391,9 +402,7 @@ class _DetailScreenState extends ConsumerState { Text( "Service Details", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.055, color: const Color(0xFF111827), ), @@ -474,9 +483,7 @@ class _DetailScreenState extends ConsumerState { children: [ Text( "Detailed Information", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.047, height: 1.4, letterSpacing: 0.03 * 20, @@ -508,9 +515,7 @@ class _DetailScreenState extends ConsumerState { child: Center( child: Text( data.serviceStatus.toString(), - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.029, color: const Color(0xFFFF0F0F), ), @@ -541,9 +546,7 @@ class _DetailScreenState extends ConsumerState { child: Center( child: Text( data.serviceStatus.toString(), - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.032, letterSpacing: 0.03, color: const Color(0xFF12800C), @@ -575,9 +578,7 @@ class _DetailScreenState extends ConsumerState { child: Center( child: Text( data.serviceStatus.toString(), - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.029, letterSpacing: 0.03, color: const Color(0xFFFF630F), @@ -616,18 +617,16 @@ class _DetailScreenState extends ConsumerState { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - "Task Final Report", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, - fontSize: width * 0.042, - height: 1.4, - letterSpacing: 0.03 * 16, - color: const Color(0xFF111827), - ), - textAlign: TextAlign.start, + Text( + "This is your final task document", + style: AppTextStyles.semiBold.copyWith( + fontSize: width * 0.042, + height: 1.4, + letterSpacing: 0.03 * 16, + color: const Color(0xFF111827), ), + textAlign: TextAlign.start, + ), const SizedBox(height: 15), Row( mainAxisAlignment: @@ -640,9 +639,7 @@ class _DetailScreenState extends ConsumerState { children: [ TextSpan( text: 'Date: ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, height: 1.3, letterSpacing: 0.04 * 13.97, @@ -651,9 +648,7 @@ class _DetailScreenState extends ConsumerState { ), TextSpan( text: data.createdDate ?? "-", - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.035, height: 1.3, letterSpacing: 0.04 * 13.97, @@ -673,9 +668,7 @@ class _DetailScreenState extends ConsumerState { children: [ TextSpan( text: 'Payment : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, height: 1.3, letterSpacing: 0.04 * 13.97, @@ -684,9 +677,7 @@ class _DetailScreenState extends ConsumerState { ), TextSpan( text: data.paymentStatus ?? "-", - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.035, height: 1.3, letterSpacing: 0.04 * 13.97, @@ -899,7 +890,10 @@ class _DetailScreenState extends ConsumerState { ], Column( children: [ - if (data.paymentStatus == "Un Paid") ...[ + if (data.paymentStatus == "Un Paid" && + !(data.serviceStatus ?? "") + .toLowerCase() + .contains("cancelled")) ...[ Padding( padding: const EdgeInsets.symmetric( vertical: 31, @@ -932,9 +926,7 @@ class _DetailScreenState extends ConsumerState { children: [ Text( "Payment Advice", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.042, height: 1.4, letterSpacing: 0.03 * 16, @@ -953,36 +945,22 @@ class _DetailScreenState extends ConsumerState { children: [ TextSpan( text: 'Date: ', - style: TextStyle( - fontFamily: - 'Gilroy-SemiBold', - fontWeight: - FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, height: 1.3, - letterSpacing: - 0.04 * 13.97, - color: const Color( - 0xFF111827, - ), + letterSpacing: 0.04 * 13.97, + color: const Color(0xFF111827), ), ), TextSpan( text: data.createdDate ?? "-", - style: TextStyle( - fontFamily: - 'Gilroy-Medium', - fontWeight: - FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.035, height: 1.3, - letterSpacing: - 0.04 * 13.97, - color: const Color( - 0xFF111827, - ), + letterSpacing: 0.04 * 13.97, + color: const Color(0xFF111827), ), ), ], @@ -998,36 +976,22 @@ class _DetailScreenState extends ConsumerState { children: [ TextSpan( text: 'Payment : ', - style: TextStyle( - fontFamily: - 'Gilroy-SemiBold', - fontWeight: - FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, height: 1.3, - letterSpacing: - 0.04 * 13.97, - color: const Color( - 0xFF111827, - ), + letterSpacing: 0.04 * 13.97, + color: const Color(0xFF111827), ), ), TextSpan( text: data.paymentStatus ?? "-", - style: TextStyle( - fontFamily: - 'Gilroy-Medium', - fontWeight: - FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.035, height: 1.3, - letterSpacing: - 0.04 * 13.97, - color: const Color( - 0xFF111827, - ), + letterSpacing: 0.04 * 13.97, + color: const Color(0xFF111827), ), ), ], @@ -1045,18 +1009,15 @@ class _DetailScreenState extends ConsumerState { children: [ Text( "Total Amount", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.04, color: const Color(0xFF111827), ), ), Text( "₹ ${data.paymentAmount ?? '0'}", - style: TextStyle( + style: AppTextStyles.semiBold.copyWith( fontFamily: 'Roboto', - fontWeight: FontWeight.w600, fontSize: width * 0.045, color: const Color(0xFF111827), ), @@ -1105,9 +1066,7 @@ class _DetailScreenState extends ConsumerState { children: [ Text( "Payment Advice", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.042, height: 1.4, letterSpacing: 0.03 * 16, @@ -1126,36 +1085,22 @@ class _DetailScreenState extends ConsumerState { children: [ TextSpan( text: 'Date: ', - style: TextStyle( - fontFamily: - 'Gilroy-SemiBold', - fontWeight: - FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, height: 1.3, - letterSpacing: - 0.04 * 13.97, - color: const Color( - 0xFF111827, - ), + letterSpacing: 0.04 * 13.97, + color: const Color(0xFF111827), ), ), TextSpan( text: data.createdDate ?? "-", - style: TextStyle( - fontFamily: - 'Gilroy-Medium', - fontWeight: - FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.035, height: 1.3, - letterSpacing: - 0.04 * 13.97, - color: const Color( - 0xFF111827, - ), + letterSpacing: 0.04 * 13.97, + color: const Color(0xFF111827), ), ), ], @@ -1171,36 +1116,22 @@ class _DetailScreenState extends ConsumerState { children: [ TextSpan( text: 'Payment: ', - style: TextStyle( - fontFamily: - 'Gilroy-SemiBold', - fontWeight: - FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, height: 1.3, - letterSpacing: - 0.04 * 13.97, - color: const Color( - 0xFF111827, - ), + letterSpacing: 0.04 * 13.97, + color: const Color(0xFF111827), ), ), TextSpan( text: data.paymentStatus ?? "-", - style: TextStyle( - fontFamily: - 'Gilroy-Medium', - fontWeight: - FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.035, height: 1.3, - letterSpacing: - 0.04 * 13.97, - color: const Color( - 0xFF111827, - ), + letterSpacing: 0.04 * 13.97, + color: const Color(0xFF111827), ), ), ], @@ -1218,18 +1149,15 @@ class _DetailScreenState extends ConsumerState { children: [ Text( "Total Amount", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.04, color: const Color(0xFF111827), ), ), Text( "₹ ${data.paymentAmount ?? '0'}", - style: TextStyle( + style: AppTextStyles.semiBold.copyWith( fontFamily: 'Roboto', - fontWeight: FontWeight.w600, fontSize: width * 0.045, color: const Color(0xFF111827), ), @@ -1248,10 +1176,8 @@ class _DetailScreenState extends ConsumerState { ], ), ), - ] else if (data.paymentStatus == "Waiting") ...[ - const SizedBox.shrink(), ] else ...[ - Text("Unknown Status: ${data.paymentStatus}"), + const SizedBox.shrink(), ], if (data.proforma != null && @@ -1285,10 +1211,8 @@ class _DetailScreenState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - "Payment Advice", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + "Profoma Advice", + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.042, height: 1.4, letterSpacing: 0.03 * 16, @@ -1308,10 +1232,7 @@ class _DetailScreenState extends ConsumerState { children: [ TextSpan( text: 'proforma Number : ', - style: TextStyle( - fontFamily: - 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, height: 1.3, letterSpacing: 0.04 * 13.97, @@ -1321,12 +1242,9 @@ class _DetailScreenState extends ConsumerState { ), ), TextSpan( - text: - data.proformaNumber ?? + text: data.proformaNumber ?? "-", - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: width * 0.035, height: 1.3, letterSpacing: 0.04 * 13.97, @@ -1349,9 +1267,7 @@ class _DetailScreenState extends ConsumerState { children: [ TextSpan( text: 'proforma Status : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.035, height: 1.3, letterSpacing: 0.04 * 13.97, @@ -1359,10 +1275,35 @@ class _DetailScreenState extends ConsumerState { ), ), TextSpan( - text: data.proformastatus ?? "-", - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w400, + text: data.proformaStatus ?? "-", + style: AppTextStyles.regular.copyWith( + fontSize: width * 0.035, + height: 1.3, + letterSpacing: 0.04 * 13.97, + color: const Color(0xFF111827), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + RichText( + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.end, + text: TextSpan( + children: [ + TextSpan( + text: 'Subject : ', + style: AppTextStyles.semiBold.copyWith( + fontSize: width * 0.035, + height: 1.3, + letterSpacing: 0.04 * 13.97, + color: const Color(0xFF111827), + ), + ), + TextSpan( + text: data.subject ?? "-", + style: AppTextStyles.regular.copyWith( fontSize: width * 0.035, height: 1.3, letterSpacing: 0.04 * 13.97, @@ -1372,15 +1313,12 @@ class _DetailScreenState extends ConsumerState { ], ), ), - const SizedBox(height: 20), - if (data.proformastatus != "Accepted") ...[ + if (data.proformaStatus != "Accepted") ...[ Text( "Note : Once you accept this proforma only you can pay the amount for the service", textAlign: TextAlign.start, - style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 13, height: 1.78, // 178% line-height letterSpacing: 0.04 * 13, // 4% @@ -1404,7 +1342,7 @@ class _DetailScreenState extends ConsumerState { const SizedBox(width: 8), - if (data.proformastatus != "Accepted") + if (data.proformaStatus != "Accepted") /// ✅ Accept (Less width) Expanded( flex: 2, @@ -1525,9 +1463,7 @@ class _DetailScreenState extends ConsumerState { /// 🔹 File List Section Text( "File Attachments:", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.04, color: const Color(0xFF111827), ), @@ -1714,18 +1650,19 @@ class _DetailScreenState extends ConsumerState { ), ) else - const Text( + Text( "No documents uploaded", - style: TextStyle( - fontFamily: 'Gilroy-Medium', - color: Color(0xFF6B7280), + style: AppTextStyles.regular.copyWith( + color: const Color(0xFF6B7280), ), ), ], ), ), ), - if (data.chatId != null && data.chatId!.isNotEmpty) + if (data.chatId != null && + data.chatId!.isNotEmpty && + !(data.serviceStatus ?? "").toLowerCase().contains("cancelled")) Padding( padding: const EdgeInsets.symmetric( horizontal: 20, @@ -1821,7 +1758,7 @@ class _DetailScreenState extends ConsumerState { ), ), - const SizedBox(height: 150), + SizedBox(height: 80.0 + MediaQuery.of(context).padding.bottom), ], ), ); @@ -1839,18 +1776,14 @@ class _DetailScreenState extends ConsumerState { children: [ TextSpan( text: '$label: ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.04, color: const Color(0xFF111827), ), ), TextSpan( text: value.isEmpty ? '—' : value, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: width * 0.04, height: 1.5, color: const Color(0xFF374151), @@ -1879,10 +1812,9 @@ class _DetailScreenState extends ConsumerState { ), child: Text( count.toString(), - style: const TextStyle( + style: AppTextStyles.bold.copyWith( color: Colors.white, fontSize: 10, - fontWeight: FontWeight.bold, ), ), ), diff --git a/lib/view/screens/history/flitter_popup.dart b/lib/view/screens/history/flitter_popup.dart index 7168bc1..4278466 100644 --- a/lib/view/screens/history/flitter_popup.dart +++ b/lib/view/screens/history/flitter_popup.dart @@ -145,7 +145,7 @@ class _FilterBottomSheetState extends State<_FilterBottomSheet> child: const Text( "Cancel", style: TextStyle( - fontFamily: "Gilroy-SemiBold", // ✅ Font + fontFamily: "Gilroy", // ✅ Font fontWeight: FontWeight.w400, fontSize: 16, height: 1.3, // ✅ line-height 130% diff --git a/lib/view/screens/history/pending_screen.dart b/lib/view/screens/history/pending_screen.dart index 005ee72..b883185 100644 --- a/lib/view/screens/history/pending_screen.dart +++ b/lib/view/screens/history/pending_screen.dart @@ -1,9 +1,12 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:get/get.dart'; import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/view/Main_controller/main_controller.dart'; import 'package:taxglide/view/screens/history/detail_screen.dart'; +import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart'; +import 'package:taxglide/view/screens/history/completed_live_chat_screen.dart'; class PendingScreen extends ConsumerWidget { final String status; @@ -17,6 +20,17 @@ class PendingScreen extends ConsumerWidget { final width = size.width; final height = size.height; + // 🔄 Silent refresh when notification trigger changes + ref.listen(notificationTriggerProvider, (previous, next) { + if (previous != null && next != previous) { + debugPrint("🔔 Silent refresh triggered for PendingScreen ($status)"); + ref + .read(serviceHistoryNotifierProvider(status).notifier) + .fetchServiceHistory(isSilent: true); + ref.invalidate(countProvider); + } + }); + return pendingAsync.when( data: (data) { final list = data.data ?? []; @@ -31,7 +45,7 @@ class PendingScreen extends ConsumerWidget { width * 0.04, height * 0.01, width * 0.04, - height * 0.2, + 80.0 + MediaQuery.of(context).padding.bottom, ), itemCount: list.length, separatorBuilder: (_, __) => SizedBox(height: height * 0.01), @@ -58,137 +72,236 @@ class PendingScreen extends ConsumerWidget { children: [ // 🔹 File ID Row Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'File ID : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, - fontSize: width * 0.04, - color: const Color(0xFF111827), - ), - ), - TextSpan( - text: '${item.id}', - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, - fontSize: width * 0.04, - color: const Color(0xFF111827), - ), - ), - ], + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + /// 🔹 File ID + RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'File ID : ', + style: AppTextStyles.semiBold.copyWith( + fontSize: width * 0.04, + color: const Color(0xFF111827), + ), + ), + TextSpan( + text: '${item.id}', + style: AppTextStyles.medium.copyWith( + fontSize: width * 0.04, + color: const Color(0xFF111827), + ), + ), + ], + ), + ), + + /// 🔥 Status + Chat Icon + Row( + children: [ + /// 🔴 Waiting / Pending / Cancelled + if (item.status == 'Waiting for Admin' || + item.status == 'Payment Pending' || + item.status == 'Cancelled By Admin') + Container( + width: width * 0.4, + height: height * 0.04, + decoration: BoxDecoration( + color: const Color(0xFFFFE8E8), + borderRadius: BorderRadius.circular(5.52), + border: Border.all( + color: const Color(0xFFFFD7D7), + width: 1.84, + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.25), + blurRadius: 7.17, + offset: const Offset(0, 3.68), + ), + ], + ), + child: Center( + child: Text( + item.status.toString(), + style: AppTextStyles.regular.copyWith( + fontSize: 11.03, + color: const Color(0xFFFF0F0F), + ), + ), + ), + ), + + /// 🟢 In Progress + if (item.status == 'In Progress') + Container( + width: 98, + height: 34.9, + decoration: BoxDecoration( + color: const Color(0xFFEAFAE6), + borderRadius: BorderRadius.circular(6.21), + border: Border.all( + color: const Color(0xFFDDFFDD), + width: 2.07, + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.25), + blurRadius: 8.08, + offset: const Offset(0, 4.14), + ), + ], + ), + child: Center( + child: Text( + 'In Progress', + style: AppTextStyles.regular.copyWith( + fontSize: 12.43, + color: const Color(0xFF12800C), + ), + ), + ), + ), + + /// 🟡 Completed + if (item.status == 'Completed') + Container( + width: 87, + height: 31, + decoration: BoxDecoration( + color: const Color(0xFFFAF7E6), + borderRadius: BorderRadius.circular(5.52), + border: Border.all( + color: const Color(0xFFFFE9DD), + width: 1.84, + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.25), + blurRadius: 7.17, + offset: const Offset(0, 3.68), + ), + ], + ), + child: Center( + child: Text( + 'Completed', + style: AppTextStyles.regular.copyWith( + fontSize: 11.03, + color: const Color(0xFFFF630F), + ), + ), + ), + ), + + /// 🔥 Space between status & icon + const SizedBox(width: 8), + if ((item.status == 'Completed' || + item.status == 'Cancelled By Admin' || + item.status == 'In Progress') && + item.chatId != null && + item.chatId.toString().isNotEmpty && + item.chatId.toString() != "0") ...[ + + /// 💬 Chat Icon with Badge + Builder(builder: (context) { + final chatIdStr = item.chatId.toString(); + final countAsync = ref.watch(countProvider(chatIdStr)); + + return GestureDetector( + onTap: () { + final chatid = int.tryParse(chatIdStr) ?? 0; + if (chatid == 0) return; + + if (item.status == 'In Progress') { + Get.to(() => LiveChatScreen( + fileid: item.id.toString(), + chatid: chatid, + ))?.then((_) { + ref.read(notificationTriggerProvider.notifier).state++; + ref.invalidate(chatMessagesProvider(chatid)); + ref.invalidate(countProvider(chatIdStr)); + }); + } else { + Get.to(() => CompletedLiveChatScreen( + fileid: item.id.toString(), + chatid: chatid, + ))?.then((_) { + ref.read(notificationTriggerProvider.notifier).state++; + ref.invalidate(chatMessagesProvider(chatid)); + ref.invalidate(countProvider(chatIdStr)); + }); + } + }, + + child: Stack( + clipBehavior: Clip.none, + children: [ + /// 🔵 Chat Icon + Container( + width: 39, + height: 39, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: const Color(0xFF61277A), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.25), + blurRadius: 8.08, + offset: const Offset(0, 4.14), + ), + ], + ), + child: const Center( + child: Icon( + Icons.message, + color: Colors.white, + size: 20, + ), + ), + ), + + /// 🔴 Badge + countAsync.when( + data: (countData) => countData.count > 0 + ? Positioned( + top: -4, + right: -4, + child: Container( + padding: const EdgeInsets.all(4), + decoration: const BoxDecoration( + color: Colors.red, + shape: BoxShape.circle, + ), + constraints: const BoxConstraints( + minWidth: 16, + minHeight: 16, + ), + child: Text( + '${countData.count}', + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.white, + fontSize: 10, + fontWeight: FontWeight.bold, ), ), + ), + ) + : const SizedBox.shrink(), + loading: () => const SizedBox.shrink(), + error: (_, __) => const SizedBox.shrink(), + ), + ], + ), + ); + }), - // 🔹 Status Badges - if (item.status == 'Waiting for Admin' || - item.status == 'Payment Pending' || - item.status == 'Cancelled By Admin') - Container( - width: width * 0.3, - height: height * 0.04, - decoration: BoxDecoration( - color: const Color(0xFFFFE8E8), - borderRadius: BorderRadius.circular(5.52), - border: Border.all( - color: const Color(0xFFFFD7D7), - width: 1.84, - ), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.25), - blurRadius: 7.17, - offset: const Offset(0, 3.68), - ), - ], - ), - child: Center( - child: Text( - item.status.toString(), - style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, - fontSize: 11.03, - color: Color(0xFFFF0F0F), - ), - ), - ), - ), - - // 🔹 In Progress Badge - if (item.status == 'In Progress') - Container( - width: 98, - height: 34.9, - decoration: BoxDecoration( - color: const Color(0xFFEAFAE6), - borderRadius: BorderRadius.circular(6.21), - border: Border.all( - color: const Color(0xFFDDFFDD), - width: 2.07, - ), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.25), - blurRadius: 8.08, - offset: const Offset(0, 4.14), - ), - ], - ), - child: const Center( - child: Text( - 'In Progress', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, - fontSize: 12.43, - letterSpacing: 0.03, - color: Color(0xFF12800C), - ), - ), - ), - ), - - // 🔹 Completed Badge - if (item.status == 'Completed') - Container( - width: 87, - height: 31, - decoration: BoxDecoration( - color: const Color(0xFFFAF7E6), - borderRadius: BorderRadius.circular(5.52), - border: Border.all( - color: const Color(0xFFFFE9DD), - width: 1.84, - ), - boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.25), - blurRadius: 7.17, - offset: const Offset(0, 3.68), - ), - ], - ), - child: const Center( - child: Text( - 'Completed', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, - fontSize: 11.03, - letterSpacing: 0.03, - color: Color(0xFFFF630F), - ), - ), - ), - ), - ], - ), + ], + ] + ), + ], +), SizedBox(height: height * 0.015), @@ -198,18 +311,14 @@ class PendingScreen extends ConsumerWidget { children: [ TextSpan( text: 'Request Type : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, - fontSize: width * 0.035, - color: const Color(0xFF111827), - ), + style: AppTextStyles.semiBold.copyWith( + fontSize: width * 0.035, + color: const Color(0xFF111827), + ), ), TextSpan( text: item.service, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: width * 0.035, color: const Color(0xFF111827), ), @@ -228,21 +337,17 @@ class PendingScreen extends ConsumerWidget { children: [ TextSpan( text: 'Date : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, - fontSize: width * 0.035, - color: const Color(0xFF111827), - ), + style: AppTextStyles.semiBold.copyWith( + fontSize: width * 0.035, + color: const Color(0xFF111827), + ), ), TextSpan( text: item.createdDate, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, - fontSize: width * 0.035, - color: const Color(0xFF111827), - ), + style: AppTextStyles.medium.copyWith( + fontSize: width * 0.035, + color: const Color(0xFF111827), + ), ), ], ), @@ -253,21 +358,17 @@ class PendingScreen extends ConsumerWidget { children: [ TextSpan( text: 'Time : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, - fontSize: width * 0.035, - color: const Color(0xFF111827), - ), + style: AppTextStyles.semiBold.copyWith( + fontSize: width * 0.035, + color: const Color(0xFF111827), + ), ), TextSpan( text: item.createdTime, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, - fontSize: width * 0.035, - color: const Color(0xFF111827), - ), + style: AppTextStyles.medium.copyWith( + fontSize: width * 0.035, + color: const Color(0xFF111827), + ), ), ], ), @@ -283,18 +384,14 @@ class PendingScreen extends ConsumerWidget { children: [ TextSpan( text: 'Message : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, - fontSize: width * 0.035, - color: const Color(0xFF111827), - ), + style: AppTextStyles.semiBold.copyWith( + fontSize: width * 0.035, + color: const Color(0xFF111827), + ), ), TextSpan( text: item.message, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: width * 0.035, color: const Color(0xFF111827), ), @@ -314,9 +411,7 @@ class PendingScreen extends ConsumerWidget { children: [ Text( "Total Amount", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: width * 0.038, color: const Color(0xFF111827), ), @@ -357,14 +452,12 @@ class PendingScreen extends ConsumerWidget { ), ], ), - child: const Center( + child: Center( child: Text( "Pay Now", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 16, - color: Color(0xFF61277A), + color: const Color(0xFF61277A), ), ), ), @@ -399,12 +492,10 @@ class PendingScreen extends ConsumerWidget { ), ], ), - child: const Center( + child: Center( child: Text( "View Details", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 16, color: Colors.white, ), @@ -434,12 +525,10 @@ class PendingScreen extends ConsumerWidget { ], ), alignment: Alignment.center, - child: const Text( + child: Text( "Payment Status: Paid", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: 12.08, letterSpacing: 0.04, height: 1.3, @@ -474,12 +563,10 @@ class PendingScreen extends ConsumerWidget { ), ], ), - child: const Center( + child: Center( child: Text( "View Details", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 16, color: Colors.white, ), @@ -519,12 +606,10 @@ class PendingScreen extends ConsumerWidget { ), ], ), - child: const Center( + child: Center( child: Text( "View Details", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 16, color: Colors.white, ), diff --git a/lib/view/screens/history/serivces_status_screen.dart b/lib/view/screens/history/serivces_status_screen.dart index a22e4c5..caf2359 100644 --- a/lib/view/screens/history/serivces_status_screen.dart +++ b/lib/view/screens/history/serivces_status_screen.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:taxglide/view/screens/history/flitter_popup.dart'; import 'package:taxglide/view/screens/history/pending_screen.dart'; @@ -57,15 +58,13 @@ class _ServicesStatusScreenState extends ConsumerState children: [ const SizedBox(width: 40), // ✅ Left side space balance // ✅ CENTER TITLE - const Text( - "Service Status", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, - fontSize: 24, - color: Color(0xFF111827), - ), - ), + Text( + "My Task Status", + style: AppTextStyles.bold.copyWith( + fontSize: 24, + color: Color(0xFF111827), + ), + ), // ✅ RIGHT SIDE FILTER ICON GestureDetector( @@ -126,21 +125,17 @@ class _ServicesStatusScreenState extends ConsumerState ), labelColor: const Color(0xFF5F297B), unselectedLabelColor: const Color(0xFF6C7278), - labelStyle: const TextStyle( - fontFamily: "Gilroy-SemiBold", - fontWeight: FontWeight.w600, + labelStyle: AppTextStyles.semiBold.copyWith( fontSize: 16, height: 1.4, letterSpacing: 0.03, - color: Color(0xFF5F297B), + color: const Color(0xFF5F297B), ), - unselectedLabelStyle: const TextStyle( - fontFamily: "Gilroy-Regular", - fontWeight: FontWeight.w400, + unselectedLabelStyle: AppTextStyles.regular.copyWith( fontSize: 16, height: 1.4, letterSpacing: 0.03, - color: Color(0xFF6C7278), + color: const Color(0xFF6C7278), ), tabs: _tabs.map((tab) => Tab(text: tab)).toList(), ), diff --git a/lib/view/screens/home_screen.dart b/lib/view/screens/home_screen.dart index 515969a..0d71e77 100644 --- a/lib/view/screens/home_screen.dart +++ b/lib/view/screens/home_screen.dart @@ -1,9 +1,12 @@ +import 'dart:ui'; + import 'package:carousel_slider/carousel_options.dart'; import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:get/get.dart'; import 'package:taxglide/consts/app_asstes.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:taxglide/consts/app_colors.dart'; import 'package:taxglide/consts/comman_serivce.dart'; import 'package:taxglide/consts/home_page_headers.dart'; @@ -128,6 +131,29 @@ class _HomeScreenState extends ConsumerState { final kycTitleSize = r.fontSize(mobile: 16, tablet: 18, desktop: 20); final kycBodySize = r.fontSize(mobile: 10, tablet: 10, desktop: 11); + // My Task Status Button responsive values + final taskStatusGlowWidth = r.getValue( + mobile: 200, + tablet: 220, + desktop: 240, + ); + final taskStatusGlowHeight = r.getValue( + mobile: 45, + tablet: 50, + desktop: 55, + ); + final taskStatusButtonWidth = r.getValue( + mobile: 197.45, + tablet: 215, + desktop: 235, + ); + final taskStatusButtonHeight = r.getValue( + mobile: 41.38, + tablet: 46, + desktop: 50, + ); + final taskStatusFontSize = r.fontSize(mobile: 18, tablet: 20, desktop: 22); + return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -141,8 +167,8 @@ class _HomeScreenState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ // KYC Banner - if (dashboard.isKycCompleted == false) - Container( + if (dashboard.isKycCompleted == true)...[ + Container( width: double.infinity, padding: EdgeInsets.all(cardPadding), decoration: const BoxDecoration( @@ -162,8 +188,7 @@ class _HomeScreenState extends ConsumerState { children: [ Text( "KYC Details", - style: TextStyle( - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: kycTitleSize, color: Colors.white, ), @@ -171,7 +196,7 @@ class _HomeScreenState extends ConsumerState { const SizedBox(height: 8), Text( "Your KYC verification couldn't be completed. Please complete your KYC details to continue exploring more features.", - style: TextStyle( + style: AppTextStyles.regular.copyWith( fontSize: kycBodySize, color: const Color(0xFFFFFFCC), ), @@ -213,15 +238,85 @@ class _HomeScreenState extends ConsumerState { ), ), - SizedBox( + SizedBox( + height: r.spacing(mobile: 26, tablet: 28, desktop: 32), + ),], + + + +Center( + child: Stack( + alignment: Alignment.center, + children: [ + /// 🌈 Gradient + Blur Glow + ClipRRect( + borderRadius: BorderRadius.circular(40), + child: BackdropFilter( + filter: ImageFilter.blur( + sigmaX: 16.54, + sigmaY: 16.54, + ), + child: Container( + width: taskStatusGlowWidth, + height: taskStatusGlowHeight, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(40), + gradient: const LinearGradient( + colors: [ + Color(0xFF7BFAFA), + Color(0xFF8BF0FD), + Color(0xFF8EFFD5), + Color(0xFFC8F895), + Color(0xFFE7F392), + Color(0xFFFBE28D), + Color(0xFFFCDAB1), + Color(0xFFFEDCAA), + ], + ), + ), + ), + ), + ), + + /// 🔲 Black Button + GestureDetector( + onTap: () { + Get.offAll( + () => const MainController( + initialIndex: 2, + sourceTabIndex: 0, + ), + ); + }, + child: Container( + width: taskStatusButtonWidth, + height: taskStatusButtonHeight, + alignment: Alignment.center, + decoration: BoxDecoration( + color: const Color(0xFF000000), + borderRadius: BorderRadius.circular(39.02), + ), + child: Text( + "My Task Status", + textAlign: TextAlign.center, + style: AppTextStyles.semiBold.copyWith( + fontSize: taskStatusFontSize, + height: 1.4, + letterSpacing: 0.03 * taskStatusFontSize, + color: Colors.white, + ), + ), + ), + ), + ], + ), +), + SizedBox( height: r.spacing(mobile: 26, tablet: 28, desktop: 32), ), - Text( "List of Services Offered", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.bold.copyWith( fontSize: sectionTitleSize, height: 1.3, letterSpacing: 0.72, @@ -295,9 +390,7 @@ class _HomeScreenState extends ConsumerState { children: [ Text( "Booking List", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.bold.copyWith( fontSize: bookingTitleSize, height: 1.4, letterSpacing: 0.6, @@ -314,9 +407,7 @@ class _HomeScreenState extends ConsumerState { }, child: Text( "See All", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: seeAllSize, height: 1.4, letterSpacing: 0.45, @@ -369,18 +460,14 @@ class _HomeScreenState extends ConsumerState { children: [ TextSpan( text: 'File ID : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: fileIdSize, color: const Color(0xFF111827), ), ), TextSpan( text: '${item.id}', - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: fileIdSize, color: const Color(0xFF111827), ), @@ -426,9 +513,7 @@ class _HomeScreenState extends ConsumerState { child: Center( child: Text( item.status.toString(), - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: r.fontSize( mobile: 10, tablet: 11, @@ -474,9 +559,7 @@ class _HomeScreenState extends ConsumerState { child: Center( child: Text( 'In Progress', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: r.fontSize( mobile: 11, tablet: 12.43, @@ -523,9 +606,7 @@ class _HomeScreenState extends ConsumerState { child: Center( child: Text( 'Completed', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: r.fontSize( mobile: 10, tablet: 11.03, @@ -548,18 +629,14 @@ class _HomeScreenState extends ConsumerState { children: [ TextSpan( text: 'Request Type : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: labelSize, color: const Color(0xFF111827), ), ), TextSpan( text: item.service, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: valueSize, color: const Color(0xFF111827), ), @@ -578,18 +655,14 @@ class _HomeScreenState extends ConsumerState { children: [ TextSpan( text: 'Date : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: labelSize, color: const Color(0xFF111827), ), ), TextSpan( text: item.createdDate, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: valueSize, color: const Color(0xFF111827), ), @@ -609,18 +682,14 @@ class _HomeScreenState extends ConsumerState { children: [ TextSpan( text: 'Time : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: labelSize, color: const Color(0xFF111827), ), ), TextSpan( text: item.createdTime, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: valueSize, color: const Color(0xFF111827), ), @@ -639,18 +708,14 @@ class _HomeScreenState extends ConsumerState { children: [ TextSpan( text: 'Message : ', - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: labelSize, color: const Color(0xFF111827), ), ), TextSpan( text: item.message, - style: TextStyle( - fontFamily: 'Gilroy-Medium', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: valueSize, color: const Color(0xFF111827), ), @@ -671,18 +736,15 @@ class _HomeScreenState extends ConsumerState { children: [ Text( "Total Amount", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: labelSize, color: const Color(0xFF111827), ), ), Text( '₹ ${item.paymentAmount.toString()}', - style: TextStyle( + style: AppTextStyles.semiBold.copyWith( fontFamily: 'Roboto', - fontWeight: FontWeight.w600, fontSize: amountSize, color: const Color(0xFF111827), ), @@ -719,9 +781,7 @@ class _HomeScreenState extends ConsumerState { child: Center( child: Text( "Pay Now", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: buttonTextSize, color: const Color(0xFF61277A), ), @@ -773,9 +833,7 @@ class _HomeScreenState extends ConsumerState { child: Center( child: Text( "View Details", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: buttonTextSize, color: Colors.white, ), @@ -821,9 +879,7 @@ class _HomeScreenState extends ConsumerState { child: Text( "Payment Status: Paid", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( fontSize: r.fontSize( mobile: 11, tablet: 12.08, @@ -872,9 +928,7 @@ class _HomeScreenState extends ConsumerState { child: Center( child: Text( "View Details", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: buttonTextSize, color: Colors.white, ), @@ -922,9 +976,7 @@ class _HomeScreenState extends ConsumerState { child: Center( child: Text( "View Details", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: buttonTextSize, color: Colors.white, ), @@ -1038,11 +1090,9 @@ class _HomeScreenState extends ConsumerState { children: [ Text( "What Our Customers Say", - style: TextStyle( - fontFamily: "Gilroy-SemiBold", + style: AppTextStyles.semiBold.copyWith( fontSize: reviewTitleSize, color: Colors.white, - fontWeight: FontWeight.w600, ), ), ], @@ -1084,7 +1134,7 @@ class _HomeScreenState extends ConsumerState { ], ), - const SizedBox(height: 200), + SizedBox(height: r.spacing(mobile: 120, tablet: 140, desktop: 160)), ], ), ); @@ -1129,15 +1179,14 @@ class _HomeScreenState extends ConsumerState { children: [ Text( name, - style: TextStyle( + style: AppTextStyles.bold.copyWith( fontSize: r.fontSize(mobile: 13, tablet: 15, desktop: 16), - fontWeight: FontWeight.w700, color: Colors.black87, ), ), Text( position, - style: TextStyle( + style: AppTextStyles.regular.copyWith( fontSize: r.fontSize(mobile: 10, tablet: 11, desktop: 12), color: Colors.grey, ), @@ -1164,7 +1213,7 @@ class _HomeScreenState extends ConsumerState { maxLines: 4, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, - style: TextStyle( + style: AppTextStyles.regular.copyWith( fontSize: r.fontSize(mobile: 11, tablet: 12, desktop: 13), height: 1.3, color: Colors.black87, @@ -1180,13 +1229,12 @@ class _HomeScreenState extends ConsumerState { width: 40, height: 40, decoration: BoxDecoration(color: iconColor, shape: BoxShape.circle), - child: const Center( + child: Center( child: Text( "❝", - style: TextStyle( + style: AppTextStyles.bold.copyWith( color: Colors.white, fontSize: 22, - fontWeight: FontWeight.bold, ), ), ), diff --git a/lib/view/screens/list_service_screen.dart b/lib/view/screens/list_service_screen.dart index 8c770cf..5d9df96 100644 --- a/lib/view/screens/list_service_screen.dart +++ b/lib/view/screens/list_service_screen.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:taxglide/consts/app_asstes.dart'; import 'package:taxglide/consts/comman_serivce.dart'; import 'package:taxglide/controller/api_contoller.dart'; @@ -38,9 +39,7 @@ class _ListServiceScreenState extends ConsumerState { children: [ Text( "List of Services Offered", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontStyle: FontStyle.normal, fontSize: 18, height: 1.3, @@ -54,14 +53,13 @@ class _ListServiceScreenState extends ConsumerState { serviceAsync.when( data: (services) { if (services.isEmpty) { - return const Padding( + return Padding( padding: EdgeInsets.only(top: 40), child: Center( child: Text( "No Services Available", - style: TextStyle( + style: AppTextStyles.regular.copyWith( fontSize: 16, - fontFamily: 'Gilroy-SemiBold', color: Colors.black54, ), ), diff --git a/lib/view/screens/notification_screen.dart b/lib/view/screens/notification_screen.dart index a13181a..f14ccc5 100644 --- a/lib/view/screens/notification_screen.dart +++ b/lib/view/screens/notification_screen.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:get/get.dart'; import 'package:get/get_core/src/get_main.dart'; @@ -55,11 +56,9 @@ class _NotificationScreenState extends ConsumerState { child: Stack( alignment: Alignment.center, children: [ - const Text( + Text( "Notification", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 24, color: Color(0xFF111827), ), @@ -126,9 +125,7 @@ class _NotificationScreenState extends ConsumerState { children: [ Text( item.title, - style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w700, + style: AppTextStyles.bold.copyWith( fontSize: 16, color: Colors.black, ), @@ -136,12 +133,12 @@ class _NotificationScreenState extends ConsumerState { const SizedBox(height: 4), Text( item.description, - style: const TextStyle(fontSize: 14, color: Colors.grey), + style: AppTextStyles.regular.copyWith(fontSize: 14, color: Colors.grey), ), const SizedBox(height: 8), Text( item.createdAt, - style: const TextStyle(fontSize: 12, color: Colors.grey), + style: AppTextStyles.regular.copyWith(fontSize: 12, color: Colors.grey), ), ], ), diff --git a/lib/view/screens/profile/employee_profile/employee_profile_list.dart b/lib/view/screens/profile/employee_profile/employee_profile_list.dart index b019906..bbd4f5a 100644 --- a/lib/view/screens/profile/employee_profile/employee_profile_list.dart +++ b/lib/view/screens/profile/employee_profile/employee_profile_list.dart @@ -71,7 +71,7 @@ class _EmployeeProfileListState extends ConsumerState { "KYC Details", textAlign: TextAlign.center, style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight .w600, // equivalent to 400 (Normal) fontStyle: FontStyle.normal, @@ -117,7 +117,7 @@ class _EmployeeProfileListState extends ConsumerState { const Text( "Personal Details", style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontSize: 20, color: Color(0xFF111827), ), @@ -202,7 +202,7 @@ class _EmployeeProfileListState extends ConsumerState { Text( title, style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontSize: 14, height: 1.3, @@ -216,7 +216,7 @@ class _EmployeeProfileListState extends ConsumerState { softWrap: true, overflow: TextOverflow.visible, style: const TextStyle( - fontFamily: 'Gilroy-Regular', + fontFamily: "Gilroy", fontWeight: FontWeight.w400, fontSize: 14, height: 1.3, diff --git a/lib/view/screens/profile/employee_profile/employee_profile_screen.dart b/lib/view/screens/profile/employee_profile/employee_profile_screen.dart index 1976092..3747358 100644 --- a/lib/view/screens/profile/employee_profile/employee_profile_screen.dart +++ b/lib/view/screens/profile/employee_profile/employee_profile_screen.dart @@ -22,6 +22,12 @@ class _EmployeeProfileScreenState extends ConsumerState { String? selectedItem; bool _isLoggingOut = false; + @override + void initState() { + super.initState(); + selectedItem = 'profile'; // Default selection + } + @override Widget build(BuildContext context) { final profileAsync = ref.watch(employeeProfileProvider); @@ -110,7 +116,7 @@ class _EmployeeProfileScreenState extends ConsumerState { Text( data?.name ?? 'No Company Name', style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontSize: 20, color: Colors.black, @@ -244,7 +250,7 @@ class _EmployeeProfileScreenState extends ConsumerState { const Text( "Note", style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontSize: 20, color: Colors.black, @@ -254,7 +260,7 @@ class _EmployeeProfileScreenState extends ConsumerState { "Are you sure you want to log out?", textAlign: TextAlign.center, style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w500, fontSize: 15, color: Colors.black87, @@ -270,7 +276,7 @@ class _EmployeeProfileScreenState extends ConsumerState { style: TextStyle( color: Color(0xFF535A5B), fontSize: 16, - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w600, ), ), @@ -321,7 +327,7 @@ class _EmployeeProfileScreenState extends ConsumerState { style: TextStyle( color: Color(0xFF5F297B), fontSize: 16, - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w600, ), ), @@ -384,7 +390,7 @@ class _EmployeeProfileScreenState extends ConsumerState { child: Text( title, style: const TextStyle( - fontFamily: 'Gilroy-Medium', + fontFamily: "Gilroy", fontSize: 16, fontWeight: FontWeight.w500, color: Colors.black87, diff --git a/lib/view/screens/profile/kyc_details_list.dart b/lib/view/screens/profile/kyc_details_list.dart index b4ea404..ba368e1 100644 --- a/lib/view/screens/profile/kyc_details_list.dart +++ b/lib/view/screens/profile/kyc_details_list.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:get/get.dart'; import 'package:taxglide/consts/app_asstes.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:taxglide/consts/download_helper.dart'; import 'package:taxglide/controller/api_consts.dart'; import 'package:taxglide/controller/api_contoller.dart'; @@ -65,7 +66,7 @@ class _KycDetailsListState extends ConsumerState { "KYC Details", textAlign: TextAlign.center, style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight .w600, // equivalent to 400 (Normal) fontStyle: FontStyle.normal, @@ -115,7 +116,7 @@ class _KycDetailsListState extends ConsumerState { "Personal Details", textAlign: TextAlign.center, style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight .w400, // equivalent to 400 (Normal) fontStyle: FontStyle.normal, @@ -181,7 +182,7 @@ class _KycDetailsListState extends ConsumerState { 'Edit', textAlign: TextAlign.center, style: TextStyle( - fontFamily: 'Gilroy-SemiBold', + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontStyle: FontStyle.normal, fontSize: 16, @@ -277,9 +278,8 @@ class _KycDetailsListState extends ConsumerState { children: [ Text( title, - style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( + fontSize: 14, height: 1.3, letterSpacing: 0.64, @@ -291,9 +291,8 @@ class _KycDetailsListState extends ConsumerState { value, softWrap: true, overflow: TextOverflow.visible, - style: const TextStyle( - fontFamily: 'Gilroy-Regular', - fontWeight: FontWeight.w400, + style: AppTextStyles.regular.copyWith( + fontSize: 14, height: 1.3, letterSpacing: 0.64, @@ -342,9 +341,9 @@ class _KycDetailsListState extends ConsumerState { maxLines: 1, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, - style: const TextStyle( - fontFamily: 'Roboto', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( + + fontSize: 13, ), ), diff --git a/lib/view/screens/profile/profile_screen.dart b/lib/view/screens/profile/profile_screen.dart index 10dc23c..2335a60 100644 --- a/lib/view/screens/profile/profile_screen.dart +++ b/lib/view/screens/profile/profile_screen.dart @@ -1,6 +1,7 @@ import 'dart:math' as math show sqrt; import 'package:flutter/material.dart'; +import 'package:taxglide/consts/app_style.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:get/get.dart'; import 'package:taxglide/consts/app_asstes.dart'; @@ -28,6 +29,7 @@ class _ProfileScreenState extends ConsumerState { @override void initState() { super.initState(); + selectedItem = 'profile'; // Set default selection _loadRole(); // <-- load role on start } @@ -104,10 +106,9 @@ class _ProfileScreenState extends ConsumerState { data!.companyName!.isNotEmpty) ? data.companyName![0].toUpperCase() : "M", - style: const TextStyle( + style: AppTextStyles.bold.copyWith( color: Colors.white, fontSize: 40, - fontWeight: FontWeight.bold, ), ), ), @@ -120,9 +121,7 @@ class _ProfileScreenState extends ConsumerState { const SizedBox(height: 60), Text( data?.companyName ?? 'No Company Name', - style: const TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 20, color: Colors.black, ), @@ -271,21 +270,17 @@ class _ProfileScreenState extends ConsumerState { child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Text( + Text( "Note", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: 20, color: Colors.black, ), ), - const Text( + Text( "Are you sure you want to log out?", textAlign: TextAlign.center, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w500, + style: AppTextStyles.medium.copyWith( fontSize: 15, color: Colors.black87, ), @@ -295,13 +290,11 @@ class _ProfileScreenState extends ConsumerState { children: [ TextButton( onPressed: () => Navigator.pop(context), - child: const Text( + child: Text( "Cancel", - style: TextStyle( - color: Color(0xFF535A5B), + style: AppTextStyles.semiBold.copyWith( + color: const Color(0xFF535A5B), fontSize: 16, - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, ), ), ), @@ -344,13 +337,11 @@ class _ProfileScreenState extends ConsumerState { color: Color(0xFF5F297B), ), ) - : const Text( + : Text( "Log Out", - style: TextStyle( - color: Color(0xFF5F297B), + style: AppTextStyles.semiBold.copyWith( + color: const Color(0xFF5F297B), fontSize: 16, - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, ), ), ), @@ -411,10 +402,8 @@ class _ProfileScreenState extends ConsumerState { Expanded( child: Text( title, - style: const TextStyle( - fontFamily: 'Gilroy-Medium', + style: AppTextStyles.medium.copyWith( fontSize: 16, - fontWeight: FontWeight.w500, color: Colors.black87, ), ), @@ -445,7 +434,7 @@ class _ProfileScreenState extends ConsumerState { Expanded( child: Text( msg, - style: const TextStyle(color: Colors.white, fontSize: 12), + style: AppTextStyles.regular.copyWith(color: Colors.white, fontSize: 12), maxLines: 2, overflow: TextOverflow.ellipsis, ), diff --git a/lib/view/screens/profile/staff_list_screen.dart b/lib/view/screens/profile/staff_list_screen.dart index 01a0401..8e25272 100644 --- a/lib/view/screens/profile/staff_list_screen.dart +++ b/lib/view/screens/profile/staff_list_screen.dart @@ -16,7 +16,7 @@ class _StaffListScreenState extends ConsumerState { final staffAsync = ref.watch(staffListProvider); const commonTextStyle = TextStyle( - fontFamily: "Gilroy-SemiBold", + fontFamily: "Gilroy", fontWeight: FontWeight.w600, fontSize: 14.7, height: 1.30, // 130% @@ -24,7 +24,7 @@ class _StaffListScreenState extends ConsumerState { color: Color(0xFF111827), ); const commonTextStylevalue = TextStyle( - fontFamily: "Gilroy-SemiBold", + fontFamily: "Gilroy", fontWeight: FontWeight.w400, fontSize: 14.7, height: 1.30, // 130% diff --git a/lib/view/screens/serivce_request_screen.dart b/lib/view/screens/serivce_request_screen.dart index ec2379e..218730f 100644 --- a/lib/view/screens/serivce_request_screen.dart +++ b/lib/view/screens/serivce_request_screen.dart @@ -7,6 +7,7 @@ import 'package:permission_handler/permission_handler.dart'; import 'package:device_info_plus/device_info_plus.dart'; import 'package:file_picker/file_picker.dart'; import 'package:path/path.dart' as path; +import 'package:taxglide/consts/app_style.dart'; import 'package:taxglide/consts/comman_button.dart'; import 'package:taxglide/consts/responsive_helper.dart'; import 'package:taxglide/controller/api_contoller.dart'; @@ -71,7 +72,7 @@ class _ServiceRequestScreenState extends ConsumerState { Expanded( child: Text( msg, - style: const TextStyle(color: Colors.white, fontSize: 12), + style: AppTextStyles.regular.copyWith(color: Colors.white, fontSize: 12), overflow: TextOverflow.ellipsis, maxLines: 2, ), @@ -89,11 +90,11 @@ class _ServiceRequestScreenState extends ConsumerState { }); bool isValid = true; - if (_selectedFiles.isEmpty) { - setState(() => _isFileError = true); - _showSnackBar("Please upload at least one file", isError: true); - isValid = false; - } + // if (_selectedFiles.isEmpty) { + // setState(() => _isFileError = true); + // _showSnackBar("Please upload at least one file", isError: true); + // isValid = false; + // } if (!_isTermsAccepted) { setState(() => _isCheckboxError = true); _showSnackBar("Please accept terms and conditions", isError: true); @@ -374,9 +375,7 @@ class _ServiceRequestScreenState extends ConsumerState { children: [ Text( "New Service Request", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: headerFontSize, color: const Color(0xFF111827), ), @@ -424,9 +423,7 @@ class _ServiceRequestScreenState extends ConsumerState { SizedBox(height: spacingMD), Text( widget.service, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: serviceNameFontSize, color: const Color(0xFF3F3F3F), ), @@ -454,10 +451,8 @@ class _ServiceRequestScreenState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( - "File Upload *", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + "File Upload", + style: AppTextStyles.semiBold.copyWith( fontSize: labelFontSize, color: const Color(0xFF111827), ), @@ -527,9 +522,7 @@ class _ServiceRequestScreenState extends ConsumerState { Expanded( child: Text( "I accept the terms and conditions *", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontStyle: FontStyle.normal, fontSize: checkboxFontSize, height: 25.56 / 12.78, @@ -556,7 +549,7 @@ class _ServiceRequestScreenState extends ConsumerState { ), ), - const SizedBox(height: 250), + SizedBox(height: r.spacing(mobile: 40, tablet: 60, desktop: 80)), ], ), ), @@ -568,9 +561,7 @@ class _ServiceRequestScreenState extends ConsumerState { padding: EdgeInsets.symmetric(horizontal: hPadding), child: Text( title, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: fontSize, color: const Color(0xFF111827), ), @@ -597,9 +588,7 @@ class _ServiceRequestScreenState extends ConsumerState { padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 21), child: Text( text, - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: fontSize, color: const Color(0xFF3F3F3F), ), @@ -619,8 +608,8 @@ class _ServiceRequestScreenState extends ConsumerState { color: Colors.white, borderRadius: BorderRadius.circular(6), border: Border.all( - color: _isFileError ? Colors.red : const Color(0xFFDFDFDF), - width: _isFileError ? 2 : 1, + color: const Color(0xFFDFDFDF), + width: 1, ), ), padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 21), @@ -628,34 +617,22 @@ class _ServiceRequestScreenState extends ConsumerState { children: [ Text( "Upload PDF, IMG, JPG, ZIP", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: fontSize, height: 25.56 / 12.78, letterSpacing: 0.8, - color: _isFileError ? Colors.red : const Color(0xFF4F4C4C), + color: const Color(0xFF4F4C4C), ), ), Text( "(40 MB only allowed File)", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: subFontSize, height: 25.56 / 12.78, letterSpacing: 0.8, - color: _isFileError ? Colors.red : const Color(0xFF4F4C4C), + color: const Color(0xFF4F4C4C), ), ), - if (_isFileError) - const Padding( - padding: EdgeInsets.only(top: 8), - child: Text( - "Please upload at least one file", - style: TextStyle(color: Colors.red, fontSize: 11), - ), - ), ], ), ), @@ -705,9 +682,7 @@ class _ServiceRequestScreenState extends ConsumerState { const SizedBox(width: 8), Text( "Uploaded Files (${_selectedFiles.length})", - style: TextStyle( - fontFamily: 'Gilroy-SemiBold', - fontWeight: FontWeight.w600, + style: AppTextStyles.semiBold.copyWith( fontSize: countFontSize, color: const Color(0xFF111827), ), @@ -894,8 +869,7 @@ class _ServiceRequestScreenState extends ConsumerState { controller: _messageController, maxLines: null, expands: true, - style: TextStyle( - fontFamily: 'Gilroy-Medium', + style: AppTextStyles.regular.copyWith( fontSize: fontSize, color: const Color(0xFF6C7278), ), diff --git a/pubspec.lock b/pubspec.lock index fdde2f4..b9af59f 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "8d7ff3948166b8ec5da0fbb5962000926b8e02f2ed9b3e51d1738905fbd4c98d" + sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f url: "https://pub.dev" source: hosted - version: "93.0.0" + version: "85.0.0" _flutterfire_internals: dependency: transitive description: @@ -21,10 +21,10 @@ packages: dependency: transitive description: name: analyzer - sha256: de7148ed2fcec579b19f122c1800933dfa028f6d9fd38a152b04b1516cec120b + sha256: "974859dc0ff5f37bc4313244b3218c791810d03ab3470a579580279ba971a48d" url: "https://pub.dev" source: hosted - version: "10.0.1" + version: "7.7.1" animated_notch_bottom_bar: dependency: "direct main" description: @@ -101,10 +101,10 @@ packages: dependency: transitive description: name: characters - sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.4.1" + version: "1.4.0" checked_yaml: dependency: transitive description: @@ -185,6 +185,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.8" + curved_labeled_navigation_bar: + dependency: "direct main" + description: + name: curved_labeled_navigation_bar + sha256: "936d8a34128478498e330588dbed3fdd7a6cc55ebada6e67340c080387e1a37e" + url: "https://pub.dev" + source: hosted + version: "2.0.6" dbus: dependency: transitive description: @@ -708,26 +716,26 @@ packages: dependency: transitive description: name: matcher - sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.18" + version: "0.12.17" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec url: "https://pub.dev" source: hosted - version: "0.13.0" + version: "0.11.1" meta: dependency: transitive description: name: meta - sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.17.0" + version: "1.16.0" mime: dependency: transitive description: @@ -1113,26 +1121,26 @@ packages: dependency: transitive description: name: test - sha256: "54c516bbb7cee2754d327ad4fca637f78abfc3cbcc5ace83b3eda117e42cd71a" + sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb" url: "https://pub.dev" source: hosted - version: "1.29.0" + version: "1.26.2" test_api: dependency: transitive description: name: test_api - sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" + sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00" url: "https://pub.dev" source: hosted - version: "0.7.9" + version: "0.7.6" test_core: dependency: transitive description: name: test_core - sha256: "394f07d21f0f2255ec9e3989f21e54d3c7dc0e6e9dbce160e5a9c1a6be0e2943" + sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a" url: "https://pub.dev" source: hosted - version: "0.6.15" + version: "0.6.11" timezone: dependency: transitive description: @@ -1149,6 +1157,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + universal_io: + dependency: transitive + description: + name: universal_io + sha256: f63cbc48103236abf48e345e07a03ce5757ea86285ed313a6a032596ed9301e2 + url: "https://pub.dev" + source: hosted + version: "2.3.1" url_launcher: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index c4b878a..677c539 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: gal: ^2.3.2 web_socket_channel: ^3.0.2 flutter_local_notifications: ^18.0.1 + curved_labeled_navigation_bar: ^2.0.6 @@ -69,55 +70,39 @@ flutter: fonts: + # ========================= + # Gilroy Font Family + # ========================= - family: Gilroy fonts: - - asset: assets/fonts/Gilroy-Thin.ttf - weight: 100 - - asset: assets/fonts/Gilroy-ThinItalic.ttf - weight: 100 - style: italic - - asset: assets/fonts/Gilroy-UltraLight.ttf - weight: 200 - - asset: assets/fonts/Gilroy-UltraLightItalic.ttf - weight: 200 - style: italic - - asset: assets/fonts/Gilroy-Light.ttf - weight: 300 - - asset: assets/fonts/Gilroy-LightItalic.ttf - weight: 300 - style: italic - asset: assets/fonts/Gilroy-Regular.ttf - weight: 400 - - asset: assets/fonts/Gilroy-RegularItalic.ttf - weight: 400 - style: italic + - family: Gilroy-Thin + fonts: + - asset: assets/fonts/Gilroy-Thin.ttf + - family: Gilroy-UltraLight + fonts: + - asset: assets/fonts/Gilroy-UltraLight.ttf + - family: Gilroy-Light + fonts: + - asset: assets/fonts/Gilroy-Light.ttf + - family: Gilroy-Regular + fonts: + - asset: assets/fonts/Gilroy-Regular.ttf + - family: Gilroy-Medium + fonts: - asset: assets/fonts/Gilroy-Medium.ttf - weight: 500 - - asset: assets/fonts/Gilroy-MediumItalic.ttf - weight: 500 - style: italic + - family: Gilroy-SemiBold + fonts: - asset: assets/fonts/Gilroy-SemiBold.ttf - weight: 600 - - asset: assets/fonts/Gilroy-SemiBoldItalic.ttf - weight: 600 - style: italic + - family: Gilroy-Bold + fonts: - asset: assets/fonts/Gilroy-Bold.ttf - weight: 700 - - asset: assets/fonts/Gilroy-BoldItalic.ttf - weight: 700 - style: italic + - family: Gilroy-ExtraBold + fonts: - asset: assets/fonts/Gilroy-ExtraBold.ttf - weight: 800 - - asset: assets/fonts/Gilroy-ExtraBoldItalic.ttf - weight: 800 - style: italic + - family: Gilroy-Black + fonts: - asset: assets/fonts/Gilroy-Black.ttf - weight: 900 - - asset: assets/fonts/Gilroy-BlackItalic.ttf - weight: 900 - style: italic + - family: Gilroy-Heavy + fonts: - asset: assets/fonts/Gilroy-Heavy.ttf - weight: 900 - - asset: assets/fonts/Gilroy-HeavyItalic.ttf - weight: 900 - style: italic