2026-04-15

This commit is contained in:
MAGESHWARAN 2026-04-15 12:32:30 +05:30
parent d01e5ba860
commit 96de59e9be
46 changed files with 1299 additions and 1191 deletions

Binary file not shown.

View File

@ -4,6 +4,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:taxglide/consts/app_asstes.dart'; import 'package:taxglide/consts/app_asstes.dart';
import 'package:taxglide/consts/app_colors.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_button.dart';
import 'package:taxglide/consts/comman_container_auth.dart'; import 'package:taxglide/consts/comman_container_auth.dart';
import 'package:taxglide/consts/comman_textformfileds.dart'; import 'package:taxglide/consts/comman_textformfileds.dart';
@ -100,7 +101,13 @@ class _EmployeeLoginScreenState extends ConsumerState<EmployeeLoginScreen> {
final spacingMD = r.spacing(mobile: 20, tablet: 20, desktop: 24); final spacingMD = r.spacing(mobile: 20, tablet: 20, desktop: 24);
final spacingLG = r.spacing(mobile: 20, tablet: 22, desktop: 28); 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, resizeToAvoidBottomInset: true,
body: Container( body: Container(
width: double.infinity, width: double.infinity,
@ -141,10 +148,8 @@ class _EmployeeLoginScreenState extends ConsumerState<EmployeeLoginScreen> {
Text( Text(
"Login", "Login",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontSize: titleFontSize, fontSize: titleFontSize,
fontWeight: FontWeight.w600,
height: 1.3, height: 1.3,
letterSpacing: 0.01 * titleFontSize, letterSpacing: 0.01 * titleFontSize,
color: AppColors.authheading, color: AppColors.authheading,
@ -156,10 +161,8 @@ class _EmployeeLoginScreenState extends ConsumerState<EmployeeLoginScreen> {
Text( Text(
"Enter your registered Mobile Number", "Enter your registered Mobile Number",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontSize: subtitleFontSize, fontSize: subtitleFontSize,
fontWeight: FontWeight.w600,
height: 1.4, height: 1.4,
letterSpacing: 0.03 * subtitleFontSize, letterSpacing: 0.03 * subtitleFontSize,
color: AppColors.authleading, color: AppColors.authleading,
@ -180,9 +183,7 @@ class _EmployeeLoginScreenState extends ConsumerState<EmployeeLoginScreen> {
Text.rich( Text.rich(
TextSpan( TextSpan(
text: "By signing up, you agree to the ", text: "By signing up, you agree to the ",
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: termsFontSize, fontSize: termsFontSize,
height: 1.8, height: 1.8,
letterSpacing: 0.01, letterSpacing: 0.01,
@ -191,9 +192,7 @@ class _EmployeeLoginScreenState extends ConsumerState<EmployeeLoginScreen> {
children: [ children: [
TextSpan( TextSpan(
text: "Terms of Service ", text: "Terms of Service ",
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontFamily: 'Gilroy-Bold',
fontWeight: FontWeight.w700,
fontSize: termsFontSize, fontSize: termsFontSize,
height: 1.8, height: 1.8,
letterSpacing: 0.01, letterSpacing: 0.01,
@ -202,20 +201,16 @@ class _EmployeeLoginScreenState extends ConsumerState<EmployeeLoginScreen> {
), ),
TextSpan( TextSpan(
text: "and ", text: "and ",
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium', fontSize: termsFontSize,
fontWeight: FontWeight.w500, height: 1.8,
fontSize: termsFontSize, letterSpacing: 0.01,
height: 1.8, color: AppColors.authleading,
letterSpacing: 0.01, ),
color: AppColors.authleading,
),
), ),
TextSpan( TextSpan(
text: "Data Processing Agreement", text: "Data Processing Agreement",
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontFamily: 'Gilroy-Bold',
fontWeight: FontWeight.w700,
fontSize: termsFontSize, fontSize: termsFontSize,
height: 1.8, height: 1.8,
letterSpacing: 0.01, letterSpacing: 0.01,
@ -242,13 +237,11 @@ class _EmployeeLoginScreenState extends ConsumerState<EmployeeLoginScreen> {
Text( Text(
"Other Login", "Other Login",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
fontSize: otherLoginFontSize, fontSize: otherLoginFontSize,
height: 1.8, height: 1.8,
letterSpacing: 0.13, letterSpacing: 0.13,
color: const Color(0xFF6C7278), color: AppColors.authleading,
), ),
), ),
@ -257,14 +250,16 @@ class _EmployeeLoginScreenState extends ConsumerState<EmployeeLoginScreen> {
Text.rich( Text.rich(
TextSpan( TextSpan(
text: "User Login? ", text: "User Login? ",
style: TextStyle(fontSize: linkFontSize), style: AppTextStyles.bold.copyWith(
fontSize: linkFontSize,
color: AppColors.black,
),
children: [ children: [
TextSpan( TextSpan(
text: "Click Here", text: "Click Here",
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontSize: linkFontSize, fontSize: linkFontSize,
color: AppColors.authsignup, color: AppColors.authsignup,
fontWeight: FontWeight.bold,
), ),
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
@ -282,6 +277,7 @@ class _EmployeeLoginScreenState extends ConsumerState<EmployeeLoginScreen> {
), ),
), ),
), ),
),
); );
} }
} }

View File

@ -247,7 +247,7 @@ class _EmployeeOtpScreenState extends ConsumerState<EmployeeOtpScreen> {
"Enter OTP", "Enter OTP",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontSize: titleFontSize, fontSize: titleFontSize,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
height: 1.3, height: 1.3,
@ -262,7 +262,7 @@ class _EmployeeOtpScreenState extends ConsumerState<EmployeeOtpScreen> {
"OTP has been sent to your registered mobile number", "OTP has been sent to your registered mobile number",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontSize: subtitleFontSize, fontSize: subtitleFontSize,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
height: 1.4, height: 1.4,
@ -277,7 +277,7 @@ class _EmployeeOtpScreenState extends ConsumerState<EmployeeOtpScreen> {
TextSpan( TextSpan(
text: mobile, text: mobile,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-Medium', fontFamily: "Gilroy",
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontSize: mobileFontSize, fontSize: mobileFontSize,
height: 1.8, height: 1.8,
@ -288,7 +288,7 @@ class _EmployeeOtpScreenState extends ConsumerState<EmployeeOtpScreen> {
TextSpan( TextSpan(
text: " ( Change Number )", text: " ( Change Number )",
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-ExtraBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w800, fontWeight: FontWeight.w800,
fontSize: mobileFontSize, fontSize: mobileFontSize,
height: 1.8, height: 1.8,
@ -347,7 +347,7 @@ class _EmployeeOtpScreenState extends ConsumerState<EmployeeOtpScreen> {
maxLength: 1, maxLength: 1,
enabled: !isLoading, enabled: !isLoading,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-Medium', fontFamily: "Gilroy",
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: otpFontSize, fontSize: otpFontSize,
letterSpacing: 0.03 * otpFontSize, letterSpacing: 0.03 * otpFontSize,
@ -375,7 +375,7 @@ class _EmployeeOtpScreenState extends ConsumerState<EmployeeOtpScreen> {
"Resend", "Resend",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-Medium', fontFamily: "Gilroy",
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontSize: resendFontSize, fontSize: resendFontSize,
height: 1.4, height: 1.4,
@ -393,7 +393,7 @@ class _EmployeeOtpScreenState extends ConsumerState<EmployeeOtpScreen> {
Text( Text(
_formatTime(_remainingSeconds), _formatTime(_remainingSeconds),
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-Medium', fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: timerFontSize, fontSize: timerFontSize,
color: _remainingSeconds > 0 color: _remainingSeconds > 0

View File

@ -12,6 +12,7 @@ import 'package:taxglide/consts/responsive_helper.dart';
import 'package:taxglide/consts/validation_popup.dart'; import 'package:taxglide/consts/validation_popup.dart';
import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/controller/api_contoller.dart';
import 'package:taxglide/router/consts_routers.dart'; import 'package:taxglide/router/consts_routers.dart';
import 'package:taxglide/consts/app_style.dart';
class LoginScreen extends ConsumerStatefulWidget { class LoginScreen extends ConsumerStatefulWidget {
const LoginScreen({super.key}); const LoginScreen({super.key});
@ -102,7 +103,12 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
final spacingMD = r.spacing(mobile: 20, tablet: 22, desktop: 26); final spacingMD = r.spacing(mobile: 20, tablet: 22, desktop: 26);
final spacingLG = r.spacing(mobile: 20, tablet: 22, desktop: 28); 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, resizeToAvoidBottomInset: true,
body: Container( body: Container(
width: double.infinity, width: double.infinity,
@ -141,10 +147,8 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
// Title // Title
Text( Text(
"Login", "Login",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontSize: titleFontSize, fontSize: titleFontSize,
fontWeight: FontWeight.w600,
color: AppColors.authheading, color: AppColors.authheading,
), ),
), ),
@ -154,8 +158,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
Text( Text(
"Enter your Mobile Number", "Enter your Mobile Number",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontSize: subtitleFontSize, fontSize: subtitleFontSize,
color: AppColors.authleading, color: AppColors.authleading,
), ),
@ -175,15 +178,14 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
Text.rich( Text.rich(
TextSpan( TextSpan(
text: "By signing up, you agree to the ", text: "By signing up, you agree to the ",
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontSize: termsFontSize, fontSize: termsFontSize,
color: AppColors.authleading, color: AppColors.authleading,
), ),
children: [ children: [
TextSpan( TextSpan(
text: "Terms of Service ", text: "Terms of Service ",
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontWeight: FontWeight.w700,
fontSize: termsFontSize, fontSize: termsFontSize,
color: AppColors.authtermsandcondition, color: AppColors.authtermsandcondition,
), ),
@ -259,21 +261,26 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
), ),
SizedBox(height: spacingSM), SizedBox(height: spacingSM),
const Text("Or"), Text("Or",style: AppTextStyles.medium.copyWith(
fontSize: spacingSM,
color: AppColors.authleading,
),),
SizedBox(height: spacingSM), SizedBox(height: spacingSM),
// Sign up // Sign up
Text.rich( Text.rich(
TextSpan( TextSpan(
text: "Didn't Have account? ", text: "Didn't Have account? ",
style: TextStyle(fontSize: signupFontSize), style: AppTextStyles.bold.copyWith(
fontSize: signupFontSize,
color: AppColors.black,
),
children: [ children: [
TextSpan( TextSpan(
text: "Sign Up", text: "Sign Up",
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontSize: signupFontSize, fontSize: signupFontSize,
color: AppColors.authsignup, color: AppColors.authsignup,
fontWeight: FontWeight.bold,
), ),
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
@ -298,13 +305,11 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
Text( Text(
"Other Login", "Other Login",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Inter',
fontWeight: FontWeight.w500,
fontSize: otherLoginFontSize, fontSize: otherLoginFontSize,
height: 1.8, height: 1.8,
letterSpacing: 0.13, letterSpacing: 0.13,
color: const Color(0xFF6C7278), color: AppColors.authleading,
), ),
), ),
@ -313,14 +318,16 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
Text.rich( Text.rich(
TextSpan( TextSpan(
text: "Staff Login? ", text: "Staff Login? ",
style: TextStyle(fontSize: signupFontSize), style: AppTextStyles.bold.copyWith(
fontSize: signupFontSize,
color: AppColors.black,
),
children: [ children: [
TextSpan( TextSpan(
text: "Click Here", text: "Click Here",
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontSize: signupFontSize, fontSize: signupFontSize,
color: AppColors.authsignup, color: AppColors.authsignup,
fontWeight: FontWeight.bold,
), ),
recognizer: TapGestureRecognizer() recognizer: TapGestureRecognizer()
..onTap = () { ..onTap = () {
@ -338,6 +345,7 @@ class _LoginScreenState extends ConsumerState<LoginScreen> {
), ),
), ),
), ),
),
); );
} }
} }

View File

@ -13,6 +13,7 @@ import 'package:taxglide/controller/api_contoller.dart';
import 'package:taxglide/router/consts_routers.dart'; import 'package:taxglide/router/consts_routers.dart';
import 'package:taxglide/view/Main_controller/main_controller.dart'; import 'package:taxglide/view/Main_controller/main_controller.dart';
import 'package:taxglide/consts/app_style.dart';
class OtpScreen extends ConsumerStatefulWidget { class OtpScreen extends ConsumerStatefulWidget {
const OtpScreen({super.key}); const OtpScreen({super.key});
@ -248,10 +249,8 @@ class _OtpScreenState extends ConsumerState<OtpScreen> {
Text( Text(
"Enter OTP", "Enter OTP",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontSize: titleFontSize, fontSize: titleFontSize,
fontWeight: FontWeight.w600,
height: 1.3, height: 1.3,
letterSpacing: 0.01 * titleFontSize, letterSpacing: 0.01 * titleFontSize,
color: AppColors.authheading, color: AppColors.authheading,
@ -263,10 +262,8 @@ class _OtpScreenState extends ConsumerState<OtpScreen> {
Text( Text(
"OTP has been sent to your registered mobile number", "OTP has been sent to your registered mobile number",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontSize: subtitleFontSize, fontSize: subtitleFontSize,
fontWeight: FontWeight.w600,
height: 1.4, height: 1.4,
letterSpacing: 0.03 * subtitleFontSize, letterSpacing: 0.03 * subtitleFontSize,
color: AppColors.authleading, color: AppColors.authleading,
@ -278,9 +275,7 @@ class _OtpScreenState extends ConsumerState<OtpScreen> {
Text.rich( Text.rich(
TextSpan( TextSpan(
text: mobile, text: mobile,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: mobileFontSize, fontSize: mobileFontSize,
height: 1.8, height: 1.8,
letterSpacing: 0.01, letterSpacing: 0.01,
@ -289,9 +284,7 @@ class _OtpScreenState extends ConsumerState<OtpScreen> {
children: [ children: [
TextSpan( TextSpan(
text: " ( Change Number )", text: " ( Change Number )",
style: TextStyle( style: AppTextStyles.extraBold.copyWith(
fontFamily: 'Gilroy-ExtraBold',
fontWeight: FontWeight.w800,
fontSize: mobileFontSize, fontSize: mobileFontSize,
height: 1.8, height: 1.8,
letterSpacing: 0.04, letterSpacing: 0.04,
@ -349,7 +342,7 @@ class _OtpScreenState extends ConsumerState<OtpScreen> {
maxLength: 1, maxLength: 1,
enabled: !isLoading, enabled: !isLoading,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-Medium', fontFamily: "Gilroy",
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: otpFontSize, fontSize: otpFontSize,
letterSpacing: 0.03 * otpFontSize, letterSpacing: 0.03 * otpFontSize,
@ -376,9 +369,7 @@ class _OtpScreenState extends ConsumerState<OtpScreen> {
child: Text( child: Text(
"Resend", "Resend",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: resendFontSize, fontSize: resendFontSize,
height: 1.4, height: 1.4,
letterSpacing: 0.02 * resendFontSize, letterSpacing: 0.02 * resendFontSize,
@ -394,9 +385,7 @@ class _OtpScreenState extends ConsumerState<OtpScreen> {
// Timer // Timer
Text( Text(
_formatTime(_remainingSeconds), _formatTime(_remainingSeconds),
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w600,
fontSize: timerFontSize, fontSize: timerFontSize,
color: _remainingSeconds > 0 color: _remainingSeconds > 0
? AppColors.authheading ? AppColors.authheading

View File

@ -11,6 +11,7 @@ import 'package:taxglide/consts/validation_popup.dart';
import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/controller/api_contoller.dart';
import 'package:taxglide/router/consts_routers.dart'; import 'package:taxglide/router/consts_routers.dart';
import 'package:taxglide/view/Main_controller/main_controller.dart'; import 'package:taxglide/view/Main_controller/main_controller.dart';
import 'package:taxglide/consts/app_style.dart';
class RegisterOtpScreen extends ConsumerStatefulWidget { class RegisterOtpScreen extends ConsumerStatefulWidget {
const RegisterOtpScreen({super.key}); const RegisterOtpScreen({super.key});
@ -247,10 +248,8 @@ class _RegisterOtpScreenState extends ConsumerState<RegisterOtpScreen> {
Text( Text(
"Enter OTP", "Enter OTP",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.w600,
height: 1.3, height: 1.3,
letterSpacing: 0.01 * 32, letterSpacing: 0.01 * 32,
color: AppColors.authheading, color: AppColors.authheading,
@ -260,10 +259,8 @@ class _RegisterOtpScreenState extends ConsumerState<RegisterOtpScreen> {
Text( Text(
"OTP has been sent to your registered mobile number", "OTP has been sent to your registered mobile number",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontSize: 14, fontSize: 14,
fontWeight: FontWeight.w600,
height: 1.4, height: 1.4,
letterSpacing: 0.03 * 14, letterSpacing: 0.03 * 14,
color: AppColors.authleading, color: AppColors.authleading,
@ -273,9 +270,7 @@ class _RegisterOtpScreenState extends ConsumerState<RegisterOtpScreen> {
Text.rich( Text.rich(
TextSpan( TextSpan(
text: mobile, text: mobile,
style: const TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: 13, fontSize: 13,
height: 1.8, height: 1.8,
letterSpacing: 0.01, letterSpacing: 0.01,
@ -284,9 +279,7 @@ class _RegisterOtpScreenState extends ConsumerState<RegisterOtpScreen> {
children: [ children: [
TextSpan( TextSpan(
text: " ( Change Number )", text: " ( Change Number )",
style: const TextStyle( style: AppTextStyles.extraBold.copyWith(
fontFamily: 'Gilroy-ExtraBold',
fontWeight: FontWeight.w800,
fontSize: 13, fontSize: 13,
height: 1.8, height: 1.8,
letterSpacing: 0.04, letterSpacing: 0.04,
@ -346,7 +339,7 @@ class _RegisterOtpScreenState extends ConsumerState<RegisterOtpScreen> {
maxLength: 1, maxLength: 1,
enabled: !isLoading, enabled: !isLoading,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-Medium', fontFamily: "Gilroy",
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: 28, fontSize: 28,
letterSpacing: 0.03 * 28, letterSpacing: 0.03 * 28,
@ -373,9 +366,7 @@ class _RegisterOtpScreenState extends ConsumerState<RegisterOtpScreen> {
child: Text( child: Text(
"Resend", "Resend",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: 14, fontSize: 14,
height: 1.4, height: 1.4,
letterSpacing: 0.02 * 14, letterSpacing: 0.02 * 14,
@ -391,9 +382,7 @@ class _RegisterOtpScreenState extends ConsumerState<RegisterOtpScreen> {
// Timer Display // Timer Display
Text( Text(
_formatTime(_remainingSeconds), _formatTime(_remainingSeconds),
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
color: _remainingSeconds > 0 color: _remainingSeconds > 0
? AppColors.authheading ? AppColors.authheading

View File

@ -9,6 +9,7 @@ import 'package:taxglide/consts/comman_textformfileds.dart';
import 'package:taxglide/consts/validation_popup.dart'; import 'package:taxglide/consts/validation_popup.dart';
import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/controller/api_contoller.dart';
import 'package:taxglide/router/consts_routers.dart'; import 'package:taxglide/router/consts_routers.dart';
import 'package:taxglide/consts/app_style.dart';
class SignupScreen extends ConsumerStatefulWidget { class SignupScreen extends ConsumerStatefulWidget {
const SignupScreen({super.key}); const SignupScreen({super.key});
@ -89,7 +90,13 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
); );
}); });
return Scaffold( return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
Get.offAllNamed(ConstRouters.login);
},
child: Scaffold(
body: Stack( body: Stack(
children: [ children: [
// 🌈 Background gradient // 🌈 Background gradient
@ -131,10 +138,8 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
Text( Text(
"Sign Up", "Sign Up",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontSize: 32, fontSize: 32,
fontWeight: FontWeight.w600,
height: 1.3, height: 1.3,
letterSpacing: 0.01 * 32, letterSpacing: 0.01 * 32,
color: AppColors.authheading, color: AppColors.authheading,
@ -148,10 +153,9 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text( child: Text(
"Name*", "Name*",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-Medium',
fontSize: 14, fontSize: 14,
color: AppColors.authleading, color: AppColors.authheading,
), ),
), ),
), ),
@ -177,10 +181,9 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text( child: Text(
"Contact Number *", "Contact Number *",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-Medium',
fontSize: 14, fontSize: 14,
color: AppColors.authleading, color: AppColors.authheading,
), ),
), ),
), ),
@ -206,10 +209,9 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: Text( child: Text(
"Email *", "Email *",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-Medium',
fontSize: 14, fontSize: 14,
color: AppColors.authleading, color: AppColors.authheading,
), ),
), ),
), ),
@ -247,6 +249,7 @@ class _SignupScreenState extends ConsumerState<SignupScreen> {
), ),
], ],
), ),
),
); );
} }

47
lib/consts/app_style.dart Normal file
View File

@ -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',
);
}

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:taxglide/consts/app_colors.dart'; import 'package:taxglide/consts/app_colors.dart';
import 'package:taxglide/consts/app_style.dart';
class CommanButton extends StatelessWidget { class CommanButton extends StatelessWidget {
final String text; final String text;
@ -51,9 +52,7 @@ class CommanButton extends StatelessWidget {
], ],
Text( Text(
text, text,
style: const TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: 16, fontSize: 16,
height: 1.4, height: 1.4,
letterSpacing: 0.03 * 16, letterSpacing: 0.03 * 16,

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:taxglide/consts/app_style.dart';
class CommonInfoPopup { class CommonInfoPopup {
/// 🔹 Show a reusable popup dialog /// 🔹 Show a reusable popup dialog
@ -22,10 +23,8 @@ class CommonInfoPopup {
contentPadding: const EdgeInsets.fromLTRB(20, 0, 20, 10), contentPadding: const EdgeInsets.fromLTRB(20, 0, 20, 10),
title: Text( title: Text(
title, title,
style: const TextStyle( style: AppTextStyles.bold.copyWith(
fontFamily: 'Gilroy-Bold',
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.w700,
color: Colors.black87, color: Colors.black87,
), ),
), ),
@ -48,8 +47,7 @@ class CommonInfoPopup {
child: Text( child: Text(
content, content,
textAlign: TextAlign.justify, textAlign: TextAlign.justify,
style: const TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-Medium',
fontSize: 14, fontSize: 14,
height: 1.6, height: 1.6,
color: Colors.black54, color: Colors.black54,
@ -63,15 +61,14 @@ class CommonInfoPopup {
actions: [ actions: [
TextButton( TextButton(
onPressed: () => Navigator.of(ctx).pop(), onPressed: () => Navigator.of(ctx).pop(),
child: const Text( child: Text(
"Close", "Close",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold', fontSize: 14,
fontSize: 14, color: const Color(0xFF6A4BFC),
color: Color(0xFF6A4BFC),
),
), ),
), ),
),
], ],
); );
}, },

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:taxglide/consts/app_style.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:taxglide/consts/app_colors.dart'; import 'package:taxglide/consts/app_colors.dart';
import 'package:taxglide/model/serivce_list_model.dart'; import 'package:taxglide/model/serivce_list_model.dart';
@ -67,9 +68,7 @@ class CommonServiceItem extends StatelessWidget {
textAlign: TextAlign.center, textAlign: TextAlign.center,
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
style: const TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 13, fontSize: 13,
height: 1.3, height: 1.3,
letterSpacing: 0.02, letterSpacing: 0.02,

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:taxglide/consts/app_colors.dart'; import 'package:taxglide/consts/app_colors.dart';
import 'package:taxglide/consts/app_style.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
class CommanTextFormField extends StatelessWidget { class CommanTextFormField extends StatelessWidget {
@ -69,15 +70,13 @@ class CommanTextFormField extends StatelessWidget {
prefixIcon: prefixIcon != null prefixIcon: prefixIcon != null
? Icon(prefixIcon, color: AppColors.authleading) ? Icon(prefixIcon, color: AppColors.authleading)
: null, : null,
hintStyle: TextStyle( hintStyle: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w400,
fontSize: 11.31, fontSize: 11.31,
height: 1.4, height: 1.4,
letterSpacing: 0.03, letterSpacing: 0.03,
color: hasError color: hasError
? Colors.red.withOpacity(0.6) ? Colors.red.withOpacity(0.6)
: Colors.grey.shade500, : AppColors.authleading
), ),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
@ -85,7 +84,7 @@ class CommanTextFormField extends StatelessWidget {
color: hasError color: hasError
? Colors.red ? Colors.red
: readOnly : readOnly
? Colors.grey.shade300 ? AppColors.authleading
: const Color(0xFFDFDFDF), : const Color(0xFFDFDFDF),
width: 1, width: 1,
), ),
@ -113,13 +112,11 @@ class CommanTextFormField extends StatelessWidget {
), ),
), ),
), ),
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: 11.31, fontSize: 11.31,
height: 1.4, height: 1.4,
letterSpacing: 0.03, letterSpacing: 0.03,
color: readOnly ? Colors.grey.shade600 : AppColors.authleading, color: readOnly ? AppColors.authleading : AppColors.authleading,
), ),
), ),
); );

View File

@ -1,10 +1,13 @@
import 'dart:io'; import 'dart:io';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:open_filex/open_filex.dart'; import 'package:open_filex/open_filex.dart';
import 'package:gal/gal.dart'; import 'package:gal/gal.dart';
import 'package:taxglide/services/notification_service.dart';
class DownloadHelper { class DownloadHelper {
static const String API_BASE_URL = "https://www.taxglide.amrithaa.net/api/"; static const String API_BASE_URL = "https://www.taxglide.amrithaa.net/api/";
@ -255,6 +258,13 @@ class DownloadHelper {
print("✅ File downloaded to: $savePath"); print("✅ File downloaded to: $savePath");
// Show Download Notification
try {
Get.find<NotificationService>().showDownloadNotification(fileName, savePath);
} catch (e) {
debugPrint('⚠️ Could not show download notification: $e');
}
// Open the downloaded file // Open the downloaded file
await openDownloadedFile(savePath); await openDownloadedFile(savePath);
@ -349,6 +359,28 @@ class DownloadHelper {
} }
} }
/// NEW: Open folder in system file manager
static Future<void> 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 /// Get all files from Send folder
static Future<List<File>> getSentFiles() async { static Future<List<File>> getSentFiles() async {
try { try {

View File

@ -318,7 +318,7 @@ class LabeledTextField extends StatelessWidget {
Text( Text(
label, label,
style: const TextStyle( style: const TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
height: 1.3, height: 1.3,
@ -391,7 +391,7 @@ class SingleImageSectionField extends StatelessWidget {
Text( Text(
title, title,
style: const TextStyle( style: const TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
height: 1.3, height: 1.3,
@ -527,7 +527,7 @@ class FileUploadSectionField extends StatelessWidget {
Text( Text(
title, title,
style: const TextStyle( style: const TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
height: 1.3, height: 1.3,

View File

@ -1,3 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class LocalStore { class LocalStore {
@ -10,7 +11,8 @@ class LocalStore {
Future<void> saveLoginData(Map<String, dynamic> data) async { Future<void> saveLoginData(Map<String, dynamic> data) async {
final token = data['access_token'] ?? ''; final token = data['access_token'] ?? '';
final role = data['role'] ?? ''; final role = data['role'] ?? '';
debugPrint('token: $token');
debugPrint('role: $role');
// Keep existing FCM token (do not overwrite) // Keep existing FCM token (do not overwrite)
String? existingFcmToken = await _storage.read(key: 'fcm_token'); String? existingFcmToken = await _storage.read(key: 'fcm_token');

View File

@ -55,6 +55,16 @@ class NotificationWebSocket {
_subscribeToChatChannel(chatId); _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). /// Connect (or skip if already connected for the same user).
Future<void> connect({ Future<void> connect({
required String userId, required String userId,

View File

@ -185,10 +185,14 @@ class ServiceHistoryNotifier
fetchServiceHistory(); fetchServiceHistory();
} }
Future<void> fetchServiceHistory() async { Future<void> fetchServiceHistory({bool isSilent = false}) async {
try { try {
if (!mounted) return; if (!mounted) return;
state = const AsyncValue.loading();
// 🔄 Skip loading state for silent refresh
if (!isSilent) {
state = const AsyncValue.loading();
}
final repo = ref.read(apiRepositoryProvider); final repo = ref.read(apiRepositoryProvider);
@ -238,8 +242,6 @@ final notificationTriggerProvider = StateProvider<int>((ref) => 0);
// 🔥 fetch notification count API // 🔥 fetch notification count API
final notificationCountProvider = final notificationCountProvider =
FutureProvider.autoDispose<NotificationCountModel>((ref) async { FutureProvider.autoDispose<NotificationCountModel>((ref) async {
ref.watch(notificationTriggerProvider); // listen for refresh trigger
final repo = ref.read(apiRepositoryProvider); final repo = ref.read(apiRepositoryProvider);
return await repo.fetchNotificationCount(); return await repo.fetchNotificationCount();
}); });
@ -409,34 +411,55 @@ class ChatMessagesNotifier
return dateA.compareTo(dateB); return dateA.compareTo(dateB);
}); });
// Check if we have any new messages // Merge strategy:
final lastMessageId = _messages.isNotEmpty ? _messages.last.id : -1; // 1. Update existing messages (read/delivered status)
final latestMessageId = result.last.id; // 2. Add new messages
bool hasChanges = false;
if (latestMessageId != lastMessageId) { for (var incomingMsg in result) {
// New messages found - merge them smoothly final existingIndex = _messages.indexWhere((m) => m.id == incomingMsg.id);
print("✅ Found new messages, updating list");
// Add only new messages that don't exist in current list if (existingIndex != -1) {
for (var newMsg in result) { // Check if status changed
final exists = _messages.any((m) => m.id == newMsg.id); final existingMsg = _messages[existingIndex];
if (!exists) { if (existingMsg.isRead != incomingMsg.isRead ||
_messages.add(newMsg); 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)
);
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) { _messages.sort((a, b) {
final dateA = final dateA = DateTime.tryParse(a.createdAt ?? '') ?? DateTime(1970);
DateTime.tryParse(a.createdAt ?? '') ?? DateTime(1970); final dateB = DateTime.tryParse(b.createdAt ?? '') ?? DateTime(1970);
final dateB =
DateTime.tryParse(b.createdAt ?? '') ?? DateTime(1970);
return dateA.compareTo(dateB); return dateA.compareTo(dateB);
}); });
if (mounted) state = AsyncData(List.from(_messages)); if (mounted) state = AsyncData(List.from(_messages));
} else { } else {
print("✅ No new messages"); print("✅ No new messages or status changes");
} }
} }
} catch (e) { } catch (e) {
@ -472,10 +495,8 @@ class ChatMessagesNotifier
// 2. Check if this is a server confirmation of an optimistic message // 2. Check if this is a server confirmation of an optimistic message
// Optimistic messages have large positive IDs from DateTime.now().millisecondsSinceEpoch // Optimistic messages have large positive IDs from DateTime.now().millisecondsSinceEpoch
// OR content match for very recent messages
final optimisticIndex = _messages.indexWhere( final optimisticIndex = _messages.indexWhere(
(m) => (m) =>
// Match by content and sender if it's a very recent "local" message
(m.id > 1000000000000 && (m.id > 1000000000000 &&
m.message == msg.message && m.message == msg.message &&
m.chatBy == msg.chatBy), m.chatBy == msg.chatBy),
@ -489,6 +510,13 @@ class ChatMessagesNotifier
_messages.add(msg); _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)); if (mounted) state = AsyncData(List.from(_messages));
} }

View File

@ -458,7 +458,7 @@ class ApiRepository {
headers: await _authorizedHeaders(), headers: await _authorizedHeaders(),
); );
}); });
debugPrint("response: ${response.body}");
if (response.statusCode == 200) { if (response.statusCode == 200) {
final data = jsonDecode(response.body); final data = jsonDecode(response.body);
return DetailModel.fromJson(data); return DetailModel.fromJson(data);
@ -635,17 +635,17 @@ class ApiRepository {
File? panFile, File? panFile,
File? gstFile, File? gstFile,
File? incorporationFile, File? incorporationFile,
required int countryId, int? countryId,
required int stateId, int? stateId,
required int cityId, int? cityId,
required String companyPincode, String? companyPincode,
required String companyAddress, String? companyAddress,
required String panNumber, String? panNumber,
required String gstNumber, String? gstNumber,
required String tanNumber, String? tanNumber,
required String cinNumber, String? cinNumber,
required String yearOfIncorporation, String? yearOfIncorporation,
required String address, String? address,
}) async { }) async {
try { try {
final token = await _localStore.getToken(); final token = await _localStore.getToken();
@ -658,17 +658,17 @@ class ApiRepository {
'Connection': 'keep-alive', 'Connection': 'keep-alive',
}) })
..fields.addAll({ ..fields.addAll({
'country_id': countryId.toString(), if (countryId != null) 'country_id': countryId.toString(),
'state_id': stateId.toString(), if (stateId != null) 'state_id': stateId.toString(),
'district_id': cityId.toString(), if (cityId != null) 'district_id': cityId.toString(),
'company_pincode': companyPincode, if (companyPincode != null) 'company_pincode': companyPincode,
'company_address': companyAddress, if (companyAddress != null) 'company_address': companyAddress,
'pan_number': panNumber, if (panNumber != null) 'pan_number': panNumber,
'gst_number': gstNumber, if (gstNumber != null) 'gst_number': gstNumber,
'tan_number': tanNumber, if (tanNumber != null) 'tan_number': tanNumber,
'cin': cinNumber, if (cinNumber != null) 'cin': cinNumber,
'year_of_incorporation': yearOfIncorporation, if (yearOfIncorporation != null) 'year_of_incorporation': yearOfIncorporation,
'address': address, if (address != null) 'address': address,
}); });
await Future.wait([ await Future.wait([
@ -686,7 +686,8 @@ class ApiRepository {
); );
final response = await http.Response.fromStream(streamedResponse); final response = await http.Response.fromStream(streamedResponse);
debugPrint('📦 KYC Response Status: ${response.statusCode}');
debugPrint('📦 KYC Response Body: ${response.body}');
// Handle token expiry // Handle token expiry
if (response.statusCode == 401 || response.statusCode == 403) { if (response.statusCode == 401 || response.statusCode == 403) {
await _handleUnauthorized(); await _handleUnauthorized();

View File

@ -6,6 +6,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:permission_handler/permission_handler.dart'; import 'package:permission_handler/permission_handler.dart';
import 'package:taxglide/consts/notification_webscoket.dart';
import 'firebase_options.dart'; import 'firebase_options.dart';
import 'package:taxglide/router/router.dart'; import 'package:taxglide/router/router.dart';
@ -138,6 +139,9 @@ void _setupFcmListeners() {
message, message,
tag: dedupTag, tag: dedupTag,
); );
// 🔄 Trigger live refresh for detail screens/badge counts
NotificationWebSocket().triggerRefresh();
} }
}); });
@ -232,6 +236,7 @@ class _TaxglideAppState extends State<TaxglideApp> {
getPages: AppRoutes.routes, getPages: AppRoutes.routes,
theme: ThemeData( theme: ThemeData(
useMaterial3: true, useMaterial3: true,
fontFamily: 'Gilroy',
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue), colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
), ),
); );

View File

@ -50,12 +50,13 @@ class DetailData {
final String? proforma; final String? proforma;
final int? proformaId; final int? proformaId;
final String? proformaNumber; final String? proformaNumber;
final String? proformastatus; final String? proformaStatus;
final String? createdDate; final String? createdDate;
final String? createdTime; final String? createdTime;
final String? createdBy; final String? createdBy;
final String? message; final String? message;
final String? subject;
final String? completedDate; final String? completedDate;
final String? paidBy; final String? paidBy;
@ -70,7 +71,7 @@ class DetailData {
this.firmId, this.firmId,
this.dueDate, this.dueDate,
this.service, this.service,
this.proformastatus, this.proformaStatus,
this.serviceStatus, this.serviceStatus,
this.paymentStatus, this.paymentStatus,
this.paidStatus, this.paidStatus,
@ -85,6 +86,7 @@ class DetailData {
this.createdTime, this.createdTime,
this.createdBy, this.createdBy,
this.message, this.message,
this.subject,
this.completedDate, this.completedDate,
this.paidBy, this.paidBy,
required this.userUploadedDocuments, required this.userUploadedDocuments,
@ -102,7 +104,7 @@ class DetailData {
serviceStatus: json["service_status"], serviceStatus: json["service_status"],
paymentStatus: json["payment_status"], paymentStatus: json["payment_status"],
proformastatus: json["proforma_status"], proformaStatus: json["proforma_status"],
paidStatus: json["paid_status"], paidStatus: json["paid_status"],
paymentDate: json["payment_date"], paymentDate: json["payment_date"],
paymentAmount: json["payment_amount"]?.toString(), paymentAmount: json["payment_amount"]?.toString(),
@ -119,6 +121,7 @@ class DetailData {
createdBy: json["created_by"], createdBy: json["created_by"],
message: json["message"], message: json["message"],
subject: json["subject"],
completedDate: json["completed_date"], completedDate: json["completed_date"],
paidBy: json["paid_by"], paidBy: json["paid_by"],
@ -153,7 +156,7 @@ class DetailData {
"payment_date": paymentDate, "payment_date": paymentDate,
"payment_amount": paymentAmount, "payment_amount": paymentAmount,
"invoice": invoice, "invoice": invoice,
"proforma_status": proformastatus, "proforma_status": proformaStatus,
"invoice_number": invoiceNumber, "invoice_number": invoiceNumber,
"proforma": proforma, "proforma": proforma,
"proforma_id": proformaId, "proforma_id": proformaId,
@ -162,6 +165,7 @@ class DetailData {
"created_time": createdTime, "created_time": createdTime,
"created_by": createdBy, "created_by": createdBy,
"message": message, "message": message,
"subject": subject,
"completed_date": completedDate, "completed_date": completedDate,
"paid_by": paidBy, "paid_by": paidBy,
"user_uploaded_documents": userUploadedDocuments "user_uploaded_documents": userUploadedDocuments

View File

@ -42,23 +42,41 @@ class ServiceListHistoryModel {
class ServiceHistoryData { class ServiceHistoryData {
final int? id; final int? id;
final String? name;
final String? firmName;
final String? paymentStatus; final String? paymentStatus;
final String? paymentAmount; final String? paymentAmount;
final String? status; final String? status;
final String? service; final String? service;
final String? message; final String? message;
final String? subject;
final String? assignee;
final String? createdDate; final String? createdDate;
final String? createdTime; final String? createdTime;
final String? createdAt;
final int? actions;
final int? chatId;
final int? isProformaGenerated;
final String? paymentId;
ServiceHistoryData({ ServiceHistoryData({
this.id, this.id,
this.name,
this.firmName,
this.paymentStatus, this.paymentStatus,
this.paymentAmount, this.paymentAmount,
this.status, this.status,
this.service, this.service,
this.message, this.message,
this.subject,
this.assignee,
this.createdDate, this.createdDate,
this.createdTime, this.createdTime,
this.createdAt,
this.actions,
this.chatId,
this.isProformaGenerated,
this.paymentId,
}); });
factory ServiceHistoryData.fromJson(Map<String, dynamic> json) { factory ServiceHistoryData.fromJson(Map<String, dynamic> json) {
@ -66,26 +84,50 @@ class ServiceHistoryData {
id: json['id'] is int id: json['id'] is int
? json['id'] ? json['id']
: int.tryParse(json['id']?.toString() ?? ''), : int.tryParse(json['id']?.toString() ?? ''),
name: json['name']?.toString(),
firmName: json['firm_name']?.toString(),
paymentStatus: json['payment_status']?.toString(), paymentStatus: json['payment_status']?.toString(),
paymentAmount: json['payment_amount']?.toString(), paymentAmount: json['payment_amount']?.toString(),
status: json['status']?.toString(), status: json['status']?.toString(),
service: json['service']?.toString(), service: json['service']?.toString(),
message: json['message']?.toString(), message: json['message']?.toString(),
subject: json['subject']?.toString(),
assignee: json['assignee']?.toString(),
createdDate: json['created_date']?.toString(), createdDate: json['created_date']?.toString(),
createdTime: json['created_time']?.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<String, dynamic> toJson() { Map<String, dynamic> toJson() {
return { return {
'id': id, 'id': id,
'name': name,
'firm_name': firmName,
'payment_status': paymentStatus, 'payment_status': paymentStatus,
'payment_amount': paymentAmount, 'payment_amount': paymentAmount,
'status': status, 'status': status,
'service': service, 'service': service,
'message': message, 'message': message,
'subject': subject,
'assignee': assignee,
'created_date': createdDate, 'created_date': createdDate,
'created_time': createdTime, 'created_time': createdTime,
'created_at': createdAt,
'actions': actions,
'chat_id': chatId,
'is_proforma_generated': isProformaGenerated,
'payment_id': paymentId,
}; };
} }
} }

View File

@ -2,6 +2,7 @@ import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:taxglide/consts/download_helper.dart';
import 'package:taxglide/consts/local_store.dart'; import 'package:taxglide/consts/local_store.dart';
import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart'; import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart';
import 'package:taxglide/view/Main_controller/main_controller.dart'; import 'package:taxglide/view/Main_controller/main_controller.dart';
@ -26,6 +27,16 @@ const AndroidNotificationChannel _channel = AndroidNotificationChannel(
enableVibration: true, 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(). /// Call once in main() after Firebase.initializeApp().
Future<void> initLocalNotifications() async { Future<void> initLocalNotifications() async {
const initSettings = InitializationSettings( const initSettings = InitializationSettings(
@ -37,19 +48,34 @@ Future<void> initLocalNotifications() async {
initSettings, initSettings,
onDidReceiveNotificationResponse: (NotificationResponse response) { onDidReceiveNotificationResponse: (NotificationResponse response) {
// Notification tapped while app is open handled inside NotificationService. // 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<NotificationService>().handleNavigationFromPayload( Get.find<NotificationService>().handleNavigationFromPayload(
response.payload, response.payload,
); );
}, },
); );
// Create the Android channel (no-op on iOS). // Create the channels
await flutterLocalNotificationsPlugin final androidPlugin = flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation< .resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin AndroidFlutterLocalNotificationsPlugin
>() >();
?.createNotificationChannel(_channel);
await androidPlugin?.createNotificationChannel(_channel);
await androidPlugin?.createNotificationChannel(_downloadChannel);
debugPrint('✅ LocalNotifications initialized'); 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: <AndroidNotificationAction>[
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 // Navigation helpers
/// Called when a local notification is tapped (payload = "type:id"). /// Called when a local notification is tapped (payload = "type:id").
@ -131,6 +206,15 @@ class NotificationService extends GetxController {
_safeNavigate(() => Get.offAll(() => MainController())); _safeNavigate(() => Get.offAll(() => MainController()));
return; 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 parts = payload.split(':');
final type = parts.isNotEmpty ? parts[0] : null; final type = parts.isNotEmpty ? parts[0] : null;
final idStr = parts.length > 1 ? parts[1] : null; final idStr = parts.length > 1 ? parts[1] : null;

View File

@ -39,7 +39,7 @@ class ChatProfileScreen extends ConsumerWidget {
title: const Text( title: const Text(
"Profile", "Profile",
style: TextStyle( style: TextStyle(
fontFamily: "Gilroy-SemiBold", fontFamily: "Gilroy",
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: 20, fontSize: 20,
height: 1.4, height: 1.4,
@ -113,7 +113,7 @@ class ChatProfileScreen extends ConsumerWidget {
const Text( const Text(
"Shared By Taxglide", "Shared By Taxglide",
style: TextStyle( style: TextStyle(
fontFamily: "Gilroy-SemiBold", fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 20, fontSize: 20,
height: 1.4, height: 1.4,
@ -213,7 +213,7 @@ class ChatProfileScreen extends ConsumerWidget {
const Text( const Text(
"Shared By Client", "Shared By Client",
style: TextStyle( style: TextStyle(
fontFamily: "Gilroy-SemiBold", fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 20, fontSize: 20,
height: 1.4, height: 1.4,

View File

@ -7,6 +7,7 @@ import 'package:permission_handler/permission_handler.dart';
import 'package:taxglide/consts/download_helper.dart'; import 'package:taxglide/consts/download_helper.dart';
import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/controller/api_contoller.dart';
import 'package:taxglide/controller/api_repository.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'; import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart';
// CHAT INPUT BOX WITH FILE TAG SUPPORT // CHAT INPUT BOX WITH FILE TAG SUPPORT
@ -246,49 +247,61 @@ class _ChatInputBoxState extends ConsumerState<ChatInputBox> {
setState(() => _isSending = true); setState(() => _isSending = true);
// Show loading dialog // OPTIMISTIC UI: Create a temporary message and add it immediately
showDialog( final tempId = DateTime.now().millisecondsSinceEpoch;
context: context, final tempMsg = MessageModel(
barrierDismissible: false, id: tempId,
builder: (context) => WillPopScope( chatBy: "user", // User
onWillPop: () async => false, message: text,
child: const Center( type: selectedFiles.isNotEmpty ? "file" : "text",
child: Card( isDelivered: 0,
child: Padding( isRead: 0,
padding: EdgeInsets.all(20), createdAt: DateTime.now().toIso8601String(),
child: Column( userId: 0,
mainAxisSize: MainAxisSize.min, tagId: tagId > 0 ? tagId : null,
children: [ parentTag: taggedMessage != null ? ParentTagModel(
CircularProgressIndicator(), id: taggedMessage.id,
SizedBox(height: 16), message: taggedMessage.message,
Text("Sending 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<File>.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 { try {
List<File> filesToUpload = []; List<File> filesToUpload = [];
// Save files to Send folder // Save files to Send folder
if (selectedFiles.isNotEmpty) { if (savedSelectedFiles.isNotEmpty) {
print("📤 Saving ${selectedFiles.length} files to Send folder..."); for (File file in savedSelectedFiles) {
for (File file in selectedFiles) {
try { try {
// Try to save to Send folder, fallback to original if fails // Try to save to Send folder, fallback to original if fails
final savedPath = await DownloadHelper.saveToSendFolder(file); final savedPath = await DownloadHelper.saveToSendFolder(file);
filesToUpload.add(File(savedPath)); filesToUpload.add(File(savedPath));
} catch (e) { } catch (e) {
print("⚠️ Could not save file, using original: $e");
filesToUpload.add(file); filesToUpload.add(file);
} }
} }
print("✅ Files prepared for upload: ${filesToUpload.length}");
} }
// Send message with files // Send message with files
@ -299,37 +312,22 @@ class _ChatInputBoxState extends ConsumerState<ChatInputBox> {
files: filesToUpload, files: filesToUpload,
); );
// Refresh chat messages // Refresh chat messages (this will replace the temp message with the real one)
await ref.read(chatMessagesProvider(widget.chatId).notifier).refresh(); await notifier.refresh();
ref.invalidate(chatDocumentProvider); ref.invalidate(chatDocumentProvider);
print("✅ Message sent successfully with tagId: $tagId");
// Close loading dialog
if (mounted) Navigator.pop(context);
// Clear input
if (mounted) { if (mounted) {
setState(() { setState(() => _isSending = false);
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!();
} }
} catch (e) { } catch (e) {
print("❌ Error sending message: $e"); print("❌ Error sending message: $e");
// Close loading dialog if (mounted) {
if (mounted) Navigator.pop(context); setState(() => _isSending = false);
}
setState(() => _isSending = false); // If it failed, delete the temporary message
notifier.deleteMessage(tempId);
// Show error message // Show error message
if (mounted) { if (mounted) {
@ -361,6 +359,7 @@ class _ChatInputBoxState extends ConsumerState<ChatInputBox> {
} }
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final taggedMessage = ref.watch(taggedMessageProvider); final taggedMessage = ref.watch(taggedMessageProvider);

View File

@ -270,7 +270,7 @@ class _DownloadsScreenState extends State<DownloadsScreen>
title: const Text( title: const Text(
"Downloads", "Downloads",
style: TextStyle( style: TextStyle(
fontFamily: "Gilroy-SemiBold", fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),

View File

@ -9,7 +9,7 @@ class SwipeableMessageBubble extends StatefulWidget {
final MessageModel message; final MessageModel message;
final DateTime msgDate; final DateTime msgDate;
final String Function(DateTime) formatTime; final String Function(DateTime) formatTime;
final Widget Function(int, int) buildTick; final Widget Function(MessageModel) buildTick;
final VoidCallback onSwipe; final VoidCallback onSwipe;
final Function(int?)? onParentTagTap; final Function(int?)? onParentTagTap;
final Function(List<String> imageUrls, int initialIndex)? final Function(List<String> imageUrls, int initialIndex)?
@ -669,10 +669,7 @@ class SwipeableMessageBubbleState extends State<SwipeableMessageBubble>
), ),
), ),
const SizedBox(width: 4), const SizedBox(width: 4),
widget.buildTick( widget.buildTick(widget.message),
widget.message.isDelivered,
widget.message.isRead,
),
], ],
), ),
], ],

View File

@ -160,8 +160,11 @@ class _LiveChatScreenState extends ConsumerState<LiveChatScreen>
try { try {
final event = message['event'] as String?; final event = message['event'] as String?;
if (event == 'message.sent' || event == 'message.received') { if (event == 'message.sent' ||
debugPrint("🔔 New message detected!"); event == 'message.received' ||
event == 'message.read' ||
event == 'message.delivered') {
debugPrint("🔔 Message status/new message event: $event");
if (WidgetsBinding.instance.lifecycleState == if (WidgetsBinding.instance.lifecycleState ==
AppLifecycleState.resumed) { AppLifecycleState.resumed) {
@ -409,7 +412,16 @@ class _LiveChatScreenState extends ConsumerState<LiveChatScreen>
return "$hour:$minute $period"; 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) { if (isRead == 1) {
return const Icon(Icons.done_all, size: 16, color: Colors.blue); return const Icon(Icons.done_all, size: 16, color: Colors.blue);
} else if (isDelivered == 1) { } else if (isDelivered == 1) {
@ -445,7 +457,7 @@ class _LiveChatScreenState extends ConsumerState<LiveChatScreen>
? 'File ID : ${widget.fileid.toString()}' ? 'File ID : ${widget.fileid.toString()}'
: "Live Chat", : "Live Chat",
style: const TextStyle( style: const TextStyle(
fontFamily: "Gilroy-SemiBold", fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),

View File

@ -1,12 +1,14 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:taxglide/consts/app_asstes.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/comman_webscoket.dart';
import 'package:taxglide/consts/local_store.dart'; import 'package:taxglide/consts/local_store.dart';
import 'package:taxglide/consts/notification_webscoket.dart'; import 'package:taxglide/consts/notification_webscoket.dart';
import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/controller/api_contoller.dart';
import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart'; import 'package:taxglide/view/Mahi_chat/live_chat_screen.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:taxglide/consts/responsive_helper.dart';
class CommanChatBox extends ConsumerStatefulWidget { class CommanChatBox extends ConsumerStatefulWidget {
final String? chatId; final String? chatId;
@ -86,11 +88,12 @@ class _CommanChatBoxState extends ConsumerState<CommanChatBox> {
} }
final id = snapshot.data ?? "0"; final id = snapshot.data ?? "0";
final r = ResponsiveUtils(context);
final countAsync = ref.watch(countProvider(id)); final countAsync = ref.watch(countProvider(id));
return Positioned( return Positioned(
right: 20, right: 20,
bottom: 120, bottom: r.spacing(mobile: 35, tablet: 45, desktop: 55),
child: Stack( child: Stack(
clipBehavior: Clip.none, clipBehavior: Clip.none,
children: [ children: [
@ -154,10 +157,9 @@ class _CommanChatBoxState extends ConsumerState<CommanChatBox> {
), ),
child: Text( child: Text(
data.count.toString(), data.count.toString(),
style: const TextStyle( style: AppTextStyles.bold.copyWith(
color: Colors.white, color: Colors.white,
fontSize: 11, fontSize: 10,
fontWeight: FontWeight.bold,
), ),
), ),
); );

View File

@ -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/list_service_screen.dart';
import 'package:taxglide/view/screens/profile/employee_profile/employee_profile_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: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 { class MainController extends ConsumerStatefulWidget {
final Widget? child; // Optional child (like ServiceRequestScreen) final Widget? child; // Optional child (like ServiceRequestScreen)
@ -39,7 +42,7 @@ class _MainControllerState extends ConsumerState<MainController> {
final List<String> _labels = [ final List<String> _labels = [
'Home', 'Home',
'Services', 'Services',
'Service Details', 'Task Status',
'Profile', 'Profile',
]; ];
@ -177,65 +180,6 @@ class _MainControllerState extends ConsumerState<MainController> {
body: Stack( body: Stack(
children: [ children: [
mainContent, 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( dashboardAsync.when(
data: (dashboard) { data: (dashboard) {
final int? chatIdInt = dashboard.generalChatId; final int? chatIdInt = dashboard.generalChatId;
@ -253,199 +197,89 @@ class _MainControllerState extends ConsumerState<MainController> {
), ),
], ],
), ),
), bottomNavigationBar: SafeArea(
); top: false,
} child: CurvedNavigationBar(
backgroundColor: Color(0xFF61277A),
/// Navigation Logic with Refresh buttonBackgroundColor: Colors.white,
Widget _buildNavItem(IconData icon, int index, String label) { color: Colors.white,
bool isSelected = currentIndex == index; animationDuration: const Duration(milliseconds: 300),
index: currentIndex,
return GestureDetector( items: [
onTap: () { CurvedNavigationBarItem(
// 🔹 If inside ServiceRequestScreen child: Icon(
if (widget.child != null) { Icons.home,
if (widget.initialIndex == index) return; color: currentIndex == 0 ? Colors.black : const Color(0xFF6C7278),
),
if (widget.sourceTabIndex == 0 && index == 1) { label: _labels[0],
Get.offAll(() => const MainController(initialIndex: 1)); labelStyle: (currentIndex == 0 ? AppTextStyles.bold : AppTextStyles.bold).copyWith(
return; color: currentIndex == 0 ? const Color(0xFF61277A) : const Color(0xFF6C7278),
}
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),
fontSize: 12, 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<Offset> 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;
} }

View File

@ -4,6 +4,7 @@ import 'package:flutter_riverpod/legacy.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get/get_core/src/get_main.dart'; import 'package:get/get_core/src/get_main.dart';
import 'package:taxglide/consts/app_asstes.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/controller/api_contoller.dart';
import 'package:taxglide/model/chat_model.dart'; import 'package:taxglide/model/chat_model.dart';
import 'package:taxglide/view/Mahi_chat/chat_profile_screen.dart'; import 'package:taxglide/view/Mahi_chat/chat_profile_screen.dart';
@ -193,8 +194,11 @@ class _CompletedLiveChatScreenState
try { try {
final event = message['event'] as String?; final event = message['event'] as String?;
if (event == 'message.sent' || event == 'message.received') { if (event == 'message.sent' ||
debugPrint("🔔 New message detected!"); event == 'message.received' ||
event == 'message.read' ||
event == 'message.delivered') {
debugPrint("🔔 Message status/new message event: $event");
if (WidgetsBinding.instance.lifecycleState == if (WidgetsBinding.instance.lifecycleState ==
AppLifecycleState.resumed) { AppLifecycleState.resumed) {
@ -332,7 +336,11 @@ class _CompletedLiveChatScreenState
return "$hour:$minute $period"; 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) { if (isRead == 1) {
return const Icon(Icons.done_all, size: 16, color: Colors.blue); return const Icon(Icons.done_all, size: 16, color: Colors.blue);
} else if (isDelivered == 1) { } else if (isDelivered == 1) {
@ -357,9 +365,9 @@ class _CompletedLiveChatScreenState
widget.fileid.toString() != "0") widget.fileid.toString() != "0")
? 'File ID : ${widget.fileid.toString()}' ? 'File ID : ${widget.fileid.toString()}'
: "Live Chat", : "Live Chat",
style: const TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: "Gilroy-SemiBold", fontSize: 16,
fontWeight: FontWeight.w600, color: Colors.black,
), ),
), ),
backgroundColor: Colors.white, backgroundColor: Colors.white,

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:taxglide/consts/app_style.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:taxglide/consts/app_asstes.dart'; import 'package:taxglide/consts/app_asstes.dart';
import 'package:taxglide/consts/comman_button.dart'; import 'package:taxglide/consts/comman_button.dart';
@ -183,9 +184,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
label: Text( label: Text(
"Invoice Not Available", "Invoice Not Available",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w400,
fontSize: width * 0.045, fontSize: width * 0.045,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 17.64, letterSpacing: 0.04 * 17.64,
@ -239,9 +238,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
? "View Invoice" ? "View Invoice"
: "Download Invoice", : "Download Invoice",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w400,
fontSize: width * 0.045, fontSize: width * 0.045,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 17.64, letterSpacing: 0.04 * 17.64,
@ -312,9 +309,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
: isDownloaded : isDownloaded
? "View Proforma" ? "View Proforma"
: "Download Proforma", : "Download Proforma",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 12, fontSize: 12,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 14.47, letterSpacing: 0.04 * 14.47,
@ -337,6 +332,22 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
final detailAsync = ref.watch(serviceDetailProvider(widget.id)); 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( return Scaffold(
body: Container( body: Container(
height: height, height: height,
@ -349,16 +360,16 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
), ),
child: SafeArea( child: SafeArea(
child: detailAsync.when( child: detailAsync.when(
skipLoadingOnRefresh: true,
loading: () => const Center( loading: () => const Center(
child: CircularProgressIndicator(color: Colors.deepPurple), child: CircularProgressIndicator(color: Colors.deepPurple),
), ),
error: (e, _) => Center( error: (e, _) => Center(
child: Text( child: Text(
"Error: $e", "Error: $e",
style: const TextStyle( style: AppTextStyles.regular.copyWith(
color: Colors.red, color: Colors.red,
fontSize: 16, fontSize: 16,
fontFamily: 'Gilroy-Medium',
), ),
), ),
), ),
@ -391,9 +402,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
Text( Text(
"Service Details", "Service Details",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.055, fontSize: width * 0.055,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -474,9 +483,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
Text( Text(
"Detailed Information", "Detailed Information",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.047, fontSize: width * 0.047,
height: 1.4, height: 1.4,
letterSpacing: 0.03 * 20, letterSpacing: 0.03 * 20,
@ -508,9 +515,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
child: Center( child: Center(
child: Text( child: Text(
data.serviceStatus.toString(), data.serviceStatus.toString(),
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w400,
fontSize: width * 0.029, fontSize: width * 0.029,
color: const Color(0xFFFF0F0F), color: const Color(0xFFFF0F0F),
), ),
@ -541,9 +546,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
child: Center( child: Center(
child: Text( child: Text(
data.serviceStatus.toString(), data.serviceStatus.toString(),
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w400,
fontSize: width * 0.032, fontSize: width * 0.032,
letterSpacing: 0.03, letterSpacing: 0.03,
color: const Color(0xFF12800C), color: const Color(0xFF12800C),
@ -575,9 +578,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
child: Center( child: Center(
child: Text( child: Text(
data.serviceStatus.toString(), data.serviceStatus.toString(),
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w400,
fontSize: width * 0.029, fontSize: width * 0.029,
letterSpacing: 0.03, letterSpacing: 0.03,
color: const Color(0xFFFF630F), color: const Color(0xFFFF630F),
@ -616,18 +617,16 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Task Final Report", "This is your final task document",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold', fontSize: width * 0.042,
fontWeight: FontWeight.w600, height: 1.4,
fontSize: width * 0.042, letterSpacing: 0.03 * 16,
height: 1.4, color: const Color(0xFF111827),
letterSpacing: 0.03 * 16,
color: const Color(0xFF111827),
),
textAlign: TextAlign.start,
), ),
textAlign: TextAlign.start,
),
const SizedBox(height: 15), const SizedBox(height: 15),
Row( Row(
mainAxisAlignment: mainAxisAlignment:
@ -640,9 +639,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'Date: ', text: 'Date: ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 13.97, letterSpacing: 0.04 * 13.97,
@ -651,9 +648,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
), ),
TextSpan( TextSpan(
text: data.createdDate ?? "-", text: data.createdDate ?? "-",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w400,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 13.97, letterSpacing: 0.04 * 13.97,
@ -673,9 +668,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'Payment : ', text: 'Payment : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 13.97, letterSpacing: 0.04 * 13.97,
@ -684,9 +677,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
), ),
TextSpan( TextSpan(
text: data.paymentStatus ?? "-", text: data.paymentStatus ?? "-",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w400,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 13.97, letterSpacing: 0.04 * 13.97,
@ -899,7 +890,10 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
], ],
Column( Column(
children: [ children: [
if (data.paymentStatus == "Un Paid") ...[ if (data.paymentStatus == "Un Paid" &&
!(data.serviceStatus ?? "")
.toLowerCase()
.contains("cancelled")) ...[
Padding( Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
vertical: 31, vertical: 31,
@ -932,9 +926,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
Text( Text(
"Payment Advice", "Payment Advice",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.042, fontSize: width * 0.042,
height: 1.4, height: 1.4,
letterSpacing: 0.03 * 16, letterSpacing: 0.03 * 16,
@ -953,36 +945,22 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'Date: ', text: 'Date: ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily:
'Gilroy-SemiBold',
fontWeight:
FontWeight.w600,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: letterSpacing: 0.04 * 13.97,
0.04 * 13.97, color: const Color(0xFF111827),
color: const Color(
0xFF111827,
),
), ),
), ),
TextSpan( TextSpan(
text: text:
data.createdDate ?? data.createdDate ??
"-", "-",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily:
'Gilroy-Medium',
fontWeight:
FontWeight.w400,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: letterSpacing: 0.04 * 13.97,
0.04 * 13.97, color: const Color(0xFF111827),
color: const Color(
0xFF111827,
),
), ),
), ),
], ],
@ -998,36 +976,22 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'Payment : ', text: 'Payment : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily:
'Gilroy-SemiBold',
fontWeight:
FontWeight.w600,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: letterSpacing: 0.04 * 13.97,
0.04 * 13.97, color: const Color(0xFF111827),
color: const Color(
0xFF111827,
),
), ),
), ),
TextSpan( TextSpan(
text: text:
data.paymentStatus ?? data.paymentStatus ??
"-", "-",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily:
'Gilroy-Medium',
fontWeight:
FontWeight.w400,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: letterSpacing: 0.04 * 13.97,
0.04 * 13.97, color: const Color(0xFF111827),
color: const Color(
0xFF111827,
),
), ),
), ),
], ],
@ -1045,18 +1009,15 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
Text( Text(
"Total Amount", "Total Amount",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.04, fontSize: width * 0.04,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
), ),
Text( Text(
"${data.paymentAmount ?? '0'}", "${data.paymentAmount ?? '0'}",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Roboto', fontFamily: 'Roboto',
fontWeight: FontWeight.w600,
fontSize: width * 0.045, fontSize: width * 0.045,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -1105,9 +1066,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
Text( Text(
"Payment Advice", "Payment Advice",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.042, fontSize: width * 0.042,
height: 1.4, height: 1.4,
letterSpacing: 0.03 * 16, letterSpacing: 0.03 * 16,
@ -1126,36 +1085,22 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'Date: ', text: 'Date: ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily:
'Gilroy-SemiBold',
fontWeight:
FontWeight.w600,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: letterSpacing: 0.04 * 13.97,
0.04 * 13.97, color: const Color(0xFF111827),
color: const Color(
0xFF111827,
),
), ),
), ),
TextSpan( TextSpan(
text: text:
data.createdDate ?? data.createdDate ??
"-", "-",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily:
'Gilroy-Medium',
fontWeight:
FontWeight.w400,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: letterSpacing: 0.04 * 13.97,
0.04 * 13.97, color: const Color(0xFF111827),
color: const Color(
0xFF111827,
),
), ),
), ),
], ],
@ -1171,36 +1116,22 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'Payment: ', text: 'Payment: ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily:
'Gilroy-SemiBold',
fontWeight:
FontWeight.w600,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: letterSpacing: 0.04 * 13.97,
0.04 * 13.97, color: const Color(0xFF111827),
color: const Color(
0xFF111827,
),
), ),
), ),
TextSpan( TextSpan(
text: text:
data.paymentStatus ?? data.paymentStatus ??
"-", "-",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily:
'Gilroy-Medium',
fontWeight:
FontWeight.w400,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: letterSpacing: 0.04 * 13.97,
0.04 * 13.97, color: const Color(0xFF111827),
color: const Color(
0xFF111827,
),
), ),
), ),
], ],
@ -1218,18 +1149,15 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
Text( Text(
"Total Amount", "Total Amount",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.04, fontSize: width * 0.04,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
), ),
Text( Text(
"${data.paymentAmount ?? '0'}", "${data.paymentAmount ?? '0'}",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Roboto', fontFamily: 'Roboto',
fontWeight: FontWeight.w600,
fontSize: width * 0.045, fontSize: width * 0.045,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -1248,10 +1176,8 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
], ],
), ),
), ),
] else if (data.paymentStatus == "Waiting") ...[
const SizedBox.shrink(),
] else ...[ ] else ...[
Text("Unknown Status: ${data.paymentStatus}"), const SizedBox.shrink(),
], ],
if (data.proforma != null && if (data.proforma != null &&
@ -1285,10 +1211,8 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text( Text(
"Payment Advice", "Profoma Advice",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.042, fontSize: width * 0.042,
height: 1.4, height: 1.4,
letterSpacing: 0.03 * 16, letterSpacing: 0.03 * 16,
@ -1308,10 +1232,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'proforma Number : ', text: 'proforma Number : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily:
'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 13.97, letterSpacing: 0.04 * 13.97,
@ -1321,12 +1242,9 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
), ),
), ),
TextSpan( TextSpan(
text: text: data.proformaNumber ??
data.proformaNumber ??
"-", "-",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w400,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 13.97, letterSpacing: 0.04 * 13.97,
@ -1349,9 +1267,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'proforma Status : ', text: 'proforma Status : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.035, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 13.97, letterSpacing: 0.04 * 13.97,
@ -1359,10 +1275,35 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
), ),
), ),
TextSpan( TextSpan(
text: data.proformastatus ?? "-", text: data.proformaStatus ?? "-",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-Medium', fontSize: width * 0.035,
fontWeight: FontWeight.w400, 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, fontSize: width * 0.035,
height: 1.3, height: 1.3,
letterSpacing: 0.04 * 13.97, letterSpacing: 0.04 * 13.97,
@ -1372,15 +1313,12 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
], ],
), ),
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
if (data.proformastatus != "Accepted") ...[ if (data.proformaStatus != "Accepted") ...[
Text( Text(
"Note : Once you accept this proforma only you can pay the amount for the service", "Note : Once you accept this proforma only you can pay the amount for the service",
textAlign: TextAlign.start, textAlign: TextAlign.start,
style: const TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 13, fontSize: 13,
height: 1.78, // 178% line-height height: 1.78, // 178% line-height
letterSpacing: 0.04 * 13, // 4% letterSpacing: 0.04 * 13, // 4%
@ -1404,7 +1342,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
const SizedBox(width: 8), const SizedBox(width: 8),
if (data.proformastatus != "Accepted") if (data.proformaStatus != "Accepted")
/// Accept (Less width) /// Accept (Less width)
Expanded( Expanded(
flex: 2, flex: 2,
@ -1525,9 +1463,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
/// 🔹 File List Section /// 🔹 File List Section
Text( Text(
"File Attachments:", "File Attachments:",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.04, fontSize: width * 0.04,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -1714,18 +1650,19 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
), ),
) )
else else
const Text( Text(
"No documents uploaded", "No documents uploaded",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-Medium', color: const Color(0xFF6B7280),
color: Color(0xFF6B7280),
), ),
), ),
], ],
), ),
), ),
), ),
if (data.chatId != null && data.chatId!.isNotEmpty) if (data.chatId != null &&
data.chatId!.isNotEmpty &&
!(data.serviceStatus ?? "").toLowerCase().contains("cancelled"))
Padding( Padding(
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 20, horizontal: 20,
@ -1821,7 +1758,7 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
), ),
), ),
const SizedBox(height: 150), SizedBox(height: 80.0 + MediaQuery.of(context).padding.bottom),
], ],
), ),
); );
@ -1839,18 +1776,14 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
children: [ children: [
TextSpan( TextSpan(
text: '$label: ', text: '$label: ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.04, fontSize: width * 0.04,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
), ),
TextSpan( TextSpan(
text: value.isEmpty ? '' : value, text: value.isEmpty ? '' : value,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: width * 0.04, fontSize: width * 0.04,
height: 1.5, height: 1.5,
color: const Color(0xFF374151), color: const Color(0xFF374151),
@ -1879,10 +1812,9 @@ class _DetailScreenState extends ConsumerState<DetailScreen> {
), ),
child: Text( child: Text(
count.toString(), count.toString(),
style: const TextStyle( style: AppTextStyles.bold.copyWith(
color: Colors.white, color: Colors.white,
fontSize: 10, fontSize: 10,
fontWeight: FontWeight.bold,
), ),
), ),
), ),

View File

@ -145,7 +145,7 @@ class _FilterBottomSheetState extends State<_FilterBottomSheet>
child: const Text( child: const Text(
"Cancel", "Cancel",
style: TextStyle( style: TextStyle(
fontFamily: "Gilroy-SemiBold", // Font fontFamily: "Gilroy", // Font
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: 16, fontSize: 16,
height: 1.3, // line-height 130% height: 1.3, // line-height 130%

View File

@ -1,9 +1,12 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:taxglide/consts/app_style.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/controller/api_contoller.dart';
import 'package:taxglide/view/Main_controller/main_controller.dart'; import 'package:taxglide/view/Main_controller/main_controller.dart';
import 'package:taxglide/view/screens/history/detail_screen.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 { class PendingScreen extends ConsumerWidget {
final String status; final String status;
@ -17,6 +20,17 @@ class PendingScreen extends ConsumerWidget {
final width = size.width; final width = size.width;
final height = size.height; 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( return pendingAsync.when(
data: (data) { data: (data) {
final list = data.data ?? []; final list = data.data ?? [];
@ -31,7 +45,7 @@ class PendingScreen extends ConsumerWidget {
width * 0.04, width * 0.04,
height * 0.01, height * 0.01,
width * 0.04, width * 0.04,
height * 0.2, 80.0 + MediaQuery.of(context).padding.bottom,
), ),
itemCount: list.length, itemCount: list.length,
separatorBuilder: (_, __) => SizedBox(height: height * 0.01), separatorBuilder: (_, __) => SizedBox(height: height * 0.01),
@ -58,137 +72,236 @@ class PendingScreen extends ConsumerWidget {
children: [ children: [
// 🔹 File ID Row // 🔹 File ID Row
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
RichText( /// 🔹 File ID
text: TextSpan( RichText(
children: [ text: TextSpan(
TextSpan( children: [
text: 'File ID : ', TextSpan(
style: TextStyle( text: 'File ID : ',
fontFamily: 'Gilroy-SemiBold', style: AppTextStyles.semiBold.copyWith(
fontWeight: FontWeight.w600, fontSize: width * 0.04,
fontSize: width * 0.04, color: const Color(0xFF111827),
color: const Color(0xFF111827), ),
), ),
), TextSpan(
TextSpan( text: '${item.id}',
text: '${item.id}', style: AppTextStyles.medium.copyWith(
style: TextStyle( fontSize: width * 0.04,
fontFamily: 'Gilroy-Medium', color: const Color(0xFF111827),
fontWeight: FontWeight.w500, ),
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), SizedBox(height: height * 0.015),
@ -198,18 +311,14 @@ class PendingScreen extends ConsumerWidget {
children: [ children: [
TextSpan( TextSpan(
text: 'Request Type : ', text: 'Request Type : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold', fontSize: width * 0.035,
fontWeight: FontWeight.w600, color: const Color(0xFF111827),
fontSize: width * 0.035, ),
color: const Color(0xFF111827),
),
), ),
TextSpan( TextSpan(
text: item.service, text: item.service,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: width * 0.035, fontSize: width * 0.035,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -228,21 +337,17 @@ class PendingScreen extends ConsumerWidget {
children: [ children: [
TextSpan( TextSpan(
text: 'Date : ', text: 'Date : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold', fontSize: width * 0.035,
fontWeight: FontWeight.w600, color: const Color(0xFF111827),
fontSize: width * 0.035, ),
color: const Color(0xFF111827),
),
), ),
TextSpan( TextSpan(
text: item.createdDate, text: item.createdDate,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium', fontSize: width * 0.035,
fontWeight: FontWeight.w500, color: const Color(0xFF111827),
fontSize: width * 0.035, ),
color: const Color(0xFF111827),
),
), ),
], ],
), ),
@ -253,21 +358,17 @@ class PendingScreen extends ConsumerWidget {
children: [ children: [
TextSpan( TextSpan(
text: 'Time : ', text: 'Time : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold', fontSize: width * 0.035,
fontWeight: FontWeight.w600, color: const Color(0xFF111827),
fontSize: width * 0.035, ),
color: const Color(0xFF111827),
),
), ),
TextSpan( TextSpan(
text: item.createdTime, text: item.createdTime,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium', fontSize: width * 0.035,
fontWeight: FontWeight.w500, color: const Color(0xFF111827),
fontSize: width * 0.035, ),
color: const Color(0xFF111827),
),
), ),
], ],
), ),
@ -283,18 +384,14 @@ class PendingScreen extends ConsumerWidget {
children: [ children: [
TextSpan( TextSpan(
text: 'Message : ', text: 'Message : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold', fontSize: width * 0.035,
fontWeight: FontWeight.w600, color: const Color(0xFF111827),
fontSize: width * 0.035, ),
color: const Color(0xFF111827),
),
), ),
TextSpan( TextSpan(
text: item.message, text: item.message,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: width * 0.035, fontSize: width * 0.035,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -314,9 +411,7 @@ class PendingScreen extends ConsumerWidget {
children: [ children: [
Text( Text(
"Total Amount", "Total Amount",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: width * 0.038, fontSize: width * 0.038,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -357,14 +452,12 @@ class PendingScreen extends ConsumerWidget {
), ),
], ],
), ),
child: const Center( child: Center(
child: Text( child: Text(
"Pay Now", "Pay Now",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
color: Color(0xFF61277A), color: const Color(0xFF61277A),
), ),
), ),
), ),
@ -399,12 +492,10 @@ class PendingScreen extends ConsumerWidget {
), ),
], ],
), ),
child: const Center( child: Center(
child: Text( child: Text(
"View Details", "View Details",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
color: Colors.white, color: Colors.white,
), ),
@ -434,12 +525,10 @@ class PendingScreen extends ConsumerWidget {
], ],
), ),
alignment: Alignment.center, alignment: Alignment.center,
child: const Text( child: Text(
"Payment Status: Paid", "Payment Status: Paid",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w400,
fontSize: 12.08, fontSize: 12.08,
letterSpacing: 0.04, letterSpacing: 0.04,
height: 1.3, height: 1.3,
@ -474,12 +563,10 @@ class PendingScreen extends ConsumerWidget {
), ),
], ],
), ),
child: const Center( child: Center(
child: Text( child: Text(
"View Details", "View Details",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
color: Colors.white, color: Colors.white,
), ),
@ -519,12 +606,10 @@ class PendingScreen extends ConsumerWidget {
), ),
], ],
), ),
child: const Center( child: Center(
child: Text( child: Text(
"View Details", "View Details",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
color: Colors.white, color: Colors.white,
), ),

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.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/flitter_popup.dart';
import 'package:taxglide/view/screens/history/pending_screen.dart'; import 'package:taxglide/view/screens/history/pending_screen.dart';
@ -57,15 +58,13 @@ class _ServicesStatusScreenState extends ConsumerState<ServicesStatusScreen>
children: [ children: [
const SizedBox(width: 40), // Left side space balance const SizedBox(width: 40), // Left side space balance
// CENTER TITLE // CENTER TITLE
const Text( Text(
"Service Status", "My Task Status",
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontFamily: 'Gilroy-SemiBold', fontSize: 24,
fontWeight: FontWeight.w600, color: Color(0xFF111827),
fontSize: 24, ),
color: Color(0xFF111827), ),
),
),
// RIGHT SIDE FILTER ICON // RIGHT SIDE FILTER ICON
GestureDetector( GestureDetector(
@ -126,21 +125,17 @@ class _ServicesStatusScreenState extends ConsumerState<ServicesStatusScreen>
), ),
labelColor: const Color(0xFF5F297B), labelColor: const Color(0xFF5F297B),
unselectedLabelColor: const Color(0xFF6C7278), unselectedLabelColor: const Color(0xFF6C7278),
labelStyle: const TextStyle( labelStyle: AppTextStyles.semiBold.copyWith(
fontFamily: "Gilroy-SemiBold",
fontWeight: FontWeight.w600,
fontSize: 16, fontSize: 16,
height: 1.4, height: 1.4,
letterSpacing: 0.03, letterSpacing: 0.03,
color: Color(0xFF5F297B), color: const Color(0xFF5F297B),
), ),
unselectedLabelStyle: const TextStyle( unselectedLabelStyle: AppTextStyles.regular.copyWith(
fontFamily: "Gilroy-Regular",
fontWeight: FontWeight.w400,
fontSize: 16, fontSize: 16,
height: 1.4, height: 1.4,
letterSpacing: 0.03, letterSpacing: 0.03,
color: Color(0xFF6C7278), color: const Color(0xFF6C7278),
), ),
tabs: _tabs.map((tab) => Tab(text: tab)).toList(), tabs: _tabs.map((tab) => Tab(text: tab)).toList(),
), ),

View File

@ -1,9 +1,12 @@
import 'dart:ui';
import 'package:carousel_slider/carousel_options.dart'; import 'package:carousel_slider/carousel_options.dart';
import 'package:carousel_slider/carousel_slider.dart'; import 'package:carousel_slider/carousel_slider.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:taxglide/consts/app_asstes.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/app_colors.dart';
import 'package:taxglide/consts/comman_serivce.dart'; import 'package:taxglide/consts/comman_serivce.dart';
import 'package:taxglide/consts/home_page_headers.dart'; import 'package:taxglide/consts/home_page_headers.dart';
@ -128,6 +131,29 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
final kycTitleSize = r.fontSize(mobile: 16, tablet: 18, desktop: 20); final kycTitleSize = r.fontSize(mobile: 16, tablet: 18, desktop: 20);
final kycBodySize = r.fontSize(mobile: 10, tablet: 10, desktop: 11); final kycBodySize = r.fontSize(mobile: 10, tablet: 10, desktop: 11);
// My Task Status Button responsive values
final taskStatusGlowWidth = r.getValue<double>(
mobile: 200,
tablet: 220,
desktop: 240,
);
final taskStatusGlowHeight = r.getValue<double>(
mobile: 45,
tablet: 50,
desktop: 55,
);
final taskStatusButtonWidth = r.getValue<double>(
mobile: 197.45,
tablet: 215,
desktop: 235,
);
final taskStatusButtonHeight = r.getValue<double>(
mobile: 41.38,
tablet: 46,
desktop: 50,
);
final taskStatusFontSize = r.fontSize(mobile: 18, tablet: 20, desktop: 22);
return SingleChildScrollView( return SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -141,8 +167,8 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
// KYC Banner // KYC Banner
if (dashboard.isKycCompleted == false) if (dashboard.isKycCompleted == true)...[
Container( Container(
width: double.infinity, width: double.infinity,
padding: EdgeInsets.all(cardPadding), padding: EdgeInsets.all(cardPadding),
decoration: const BoxDecoration( decoration: const BoxDecoration(
@ -162,8 +188,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
children: [ children: [
Text( Text(
"KYC Details", "KYC Details",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontWeight: FontWeight.w600,
fontSize: kycTitleSize, fontSize: kycTitleSize,
color: Colors.white, color: Colors.white,
), ),
@ -171,7 +196,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
"Your KYC verification couldn't be completed. Please complete your KYC details to continue exploring more features.", "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, fontSize: kycBodySize,
color: const Color(0xFFFFFFCC), color: const Color(0xFFFFFFCC),
), ),
@ -213,15 +238,85 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
), ),
), ),
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), height: r.spacing(mobile: 26, tablet: 28, desktop: 32),
), ),
Text( Text(
"List of Services Offered", "List of Services Offered",
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: sectionTitleSize, fontSize: sectionTitleSize,
height: 1.3, height: 1.3,
letterSpacing: 0.72, letterSpacing: 0.72,
@ -295,9 +390,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
children: [ children: [
Text( Text(
"Booking List", "Booking List",
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: bookingTitleSize, fontSize: bookingTitleSize,
height: 1.4, height: 1.4,
letterSpacing: 0.6, letterSpacing: 0.6,
@ -314,9 +407,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
}, },
child: Text( child: Text(
"See All", "See All",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: seeAllSize, fontSize: seeAllSize,
height: 1.4, height: 1.4,
letterSpacing: 0.45, letterSpacing: 0.45,
@ -369,18 +460,14 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'File ID : ', text: 'File ID : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: fileIdSize, fontSize: fileIdSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
), ),
TextSpan( TextSpan(
text: '${item.id}', text: '${item.id}',
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: fileIdSize, fontSize: fileIdSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -426,9 +513,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
child: Center( child: Center(
child: Text( child: Text(
item.status.toString(), item.status.toString(),
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w400,
fontSize: r.fontSize( fontSize: r.fontSize(
mobile: 10, mobile: 10,
tablet: 11, tablet: 11,
@ -474,9 +559,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
child: Center( child: Center(
child: Text( child: Text(
'In Progress', 'In Progress',
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w400,
fontSize: r.fontSize( fontSize: r.fontSize(
mobile: 11, mobile: 11,
tablet: 12.43, tablet: 12.43,
@ -523,9 +606,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
child: Center( child: Center(
child: Text( child: Text(
'Completed', 'Completed',
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w400,
fontSize: r.fontSize( fontSize: r.fontSize(
mobile: 10, mobile: 10,
tablet: 11.03, tablet: 11.03,
@ -548,18 +629,14 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'Request Type : ', text: 'Request Type : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: labelSize, fontSize: labelSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
), ),
TextSpan( TextSpan(
text: item.service, text: item.service,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: valueSize, fontSize: valueSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -578,18 +655,14 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'Date : ', text: 'Date : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: labelSize, fontSize: labelSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
), ),
TextSpan( TextSpan(
text: item.createdDate, text: item.createdDate,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: valueSize, fontSize: valueSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -609,18 +682,14 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'Time : ', text: 'Time : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: labelSize, fontSize: labelSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
), ),
TextSpan( TextSpan(
text: item.createdTime, text: item.createdTime,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: valueSize, fontSize: valueSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -639,18 +708,14 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
children: [ children: [
TextSpan( TextSpan(
text: 'Message : ', text: 'Message : ',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: labelSize, fontSize: labelSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
), ),
TextSpan( TextSpan(
text: item.message, text: item.message,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontWeight: FontWeight.w500,
fontSize: valueSize, fontSize: valueSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -671,18 +736,15 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
children: [ children: [
Text( Text(
"Total Amount", "Total Amount",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: labelSize, fontSize: labelSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
), ),
Text( Text(
'${item.paymentAmount.toString()}', '${item.paymentAmount.toString()}',
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Roboto', fontFamily: 'Roboto',
fontWeight: FontWeight.w600,
fontSize: amountSize, fontSize: amountSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -719,9 +781,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
child: Center( child: Center(
child: Text( child: Text(
"Pay Now", "Pay Now",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: buttonTextSize, fontSize: buttonTextSize,
color: const Color(0xFF61277A), color: const Color(0xFF61277A),
), ),
@ -773,9 +833,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
child: Center( child: Center(
child: Text( child: Text(
"View Details", "View Details",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: buttonTextSize, fontSize: buttonTextSize,
color: Colors.white, color: Colors.white,
), ),
@ -821,9 +879,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
child: Text( child: Text(
"Payment Status: Paid", "Payment Status: Paid",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w400,
fontSize: r.fontSize( fontSize: r.fontSize(
mobile: 11, mobile: 11,
tablet: 12.08, tablet: 12.08,
@ -872,9 +928,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
child: Center( child: Center(
child: Text( child: Text(
"View Details", "View Details",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: buttonTextSize, fontSize: buttonTextSize,
color: Colors.white, color: Colors.white,
), ),
@ -922,9 +976,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
child: Center( child: Center(
child: Text( child: Text(
"View Details", "View Details",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: buttonTextSize, fontSize: buttonTextSize,
color: Colors.white, color: Colors.white,
), ),
@ -1038,11 +1090,9 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
children: [ children: [
Text( Text(
"What Our Customers Say", "What Our Customers Say",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: "Gilroy-SemiBold",
fontSize: reviewTitleSize, fontSize: reviewTitleSize,
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.w600,
), ),
), ),
], ],
@ -1084,7 +1134,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
], ],
), ),
const SizedBox(height: 200), SizedBox(height: r.spacing(mobile: 120, tablet: 140, desktop: 160)),
], ],
), ),
); );
@ -1129,15 +1179,14 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
children: [ children: [
Text( Text(
name, name,
style: TextStyle( style: AppTextStyles.bold.copyWith(
fontSize: r.fontSize(mobile: 13, tablet: 15, desktop: 16), fontSize: r.fontSize(mobile: 13, tablet: 15, desktop: 16),
fontWeight: FontWeight.w700,
color: Colors.black87, color: Colors.black87,
), ),
), ),
Text( Text(
position, position,
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontSize: r.fontSize(mobile: 10, tablet: 11, desktop: 12), fontSize: r.fontSize(mobile: 10, tablet: 11, desktop: 12),
color: Colors.grey, color: Colors.grey,
), ),
@ -1164,7 +1213,7 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
maxLines: 4, maxLines: 4,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontSize: r.fontSize(mobile: 11, tablet: 12, desktop: 13), fontSize: r.fontSize(mobile: 11, tablet: 12, desktop: 13),
height: 1.3, height: 1.3,
color: Colors.black87, color: Colors.black87,
@ -1180,13 +1229,12 @@ class _HomeScreenState extends ConsumerState<HomeScreen> {
width: 40, width: 40,
height: 40, height: 40,
decoration: BoxDecoration(color: iconColor, shape: BoxShape.circle), decoration: BoxDecoration(color: iconColor, shape: BoxShape.circle),
child: const Center( child: Center(
child: Text( child: Text(
"", "",
style: TextStyle( style: AppTextStyles.bold.copyWith(
color: Colors.white, color: Colors.white,
fontSize: 22, fontSize: 22,
fontWeight: FontWeight.bold,
), ),
), ),
), ),

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.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/app_asstes.dart';
import 'package:taxglide/consts/comman_serivce.dart'; import 'package:taxglide/consts/comman_serivce.dart';
import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/controller/api_contoller.dart';
@ -38,9 +39,7 @@ class _ListServiceScreenState extends ConsumerState<ListServiceScreen> {
children: [ children: [
Text( Text(
"List of Services Offered", "List of Services Offered",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal, fontStyle: FontStyle.normal,
fontSize: 18, fontSize: 18,
height: 1.3, height: 1.3,
@ -54,14 +53,13 @@ class _ListServiceScreenState extends ConsumerState<ListServiceScreen> {
serviceAsync.when( serviceAsync.when(
data: (services) { data: (services) {
if (services.isEmpty) { if (services.isEmpty) {
return const Padding( return Padding(
padding: EdgeInsets.only(top: 40), padding: EdgeInsets.only(top: 40),
child: Center( child: Center(
child: Text( child: Text(
"No Services Available", "No Services Available",
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontSize: 16, fontSize: 16,
fontFamily: 'Gilroy-SemiBold',
color: Colors.black54, color: Colors.black54,
), ),
), ),

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:taxglide/consts/app_style.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:get/get_core/src/get_main.dart'; import 'package:get/get_core/src/get_main.dart';
@ -55,11 +56,9 @@ class _NotificationScreenState extends ConsumerState<NotificationScreen> {
child: Stack( child: Stack(
alignment: Alignment.center, alignment: Alignment.center,
children: [ children: [
const Text( Text(
"Notification", "Notification",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 24, fontSize: 24,
color: Color(0xFF111827), color: Color(0xFF111827),
), ),
@ -126,9 +125,7 @@ class _NotificationScreenState extends ConsumerState<NotificationScreen> {
children: [ children: [
Text( Text(
item.title, item.title,
style: const TextStyle( style: AppTextStyles.bold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w700,
fontSize: 16, fontSize: 16,
color: Colors.black, color: Colors.black,
), ),
@ -136,12 +133,12 @@ class _NotificationScreenState extends ConsumerState<NotificationScreen> {
const SizedBox(height: 4), const SizedBox(height: 4),
Text( Text(
item.description, item.description,
style: const TextStyle(fontSize: 14, color: Colors.grey), style: AppTextStyles.regular.copyWith(fontSize: 14, color: Colors.grey),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),
Text( Text(
item.createdAt, item.createdAt,
style: const TextStyle(fontSize: 12, color: Colors.grey), style: AppTextStyles.regular.copyWith(fontSize: 12, color: Colors.grey),
), ),
], ],
), ),

View File

@ -71,7 +71,7 @@ class _EmployeeProfileListState extends ConsumerState<EmployeeProfileList> {
"KYC Details", "KYC Details",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight fontWeight: FontWeight
.w600, // equivalent to 400 (Normal) .w600, // equivalent to 400 (Normal)
fontStyle: FontStyle.normal, fontStyle: FontStyle.normal,
@ -117,7 +117,7 @@ class _EmployeeProfileListState extends ConsumerState<EmployeeProfileList> {
const Text( const Text(
"Personal Details", "Personal Details",
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontSize: 20, fontSize: 20,
color: Color(0xFF111827), color: Color(0xFF111827),
), ),
@ -202,7 +202,7 @@ class _EmployeeProfileListState extends ConsumerState<EmployeeProfileList> {
Text( Text(
title, title,
style: const TextStyle( style: const TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 14, fontSize: 14,
height: 1.3, height: 1.3,
@ -216,7 +216,7 @@ class _EmployeeProfileListState extends ConsumerState<EmployeeProfileList> {
softWrap: true, softWrap: true,
overflow: TextOverflow.visible, overflow: TextOverflow.visible,
style: const TextStyle( style: const TextStyle(
fontFamily: 'Gilroy-Regular', fontFamily: "Gilroy",
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: 14, fontSize: 14,
height: 1.3, height: 1.3,

View File

@ -22,6 +22,12 @@ class _EmployeeProfileScreenState extends ConsumerState<EmployeeProfileScreen> {
String? selectedItem; String? selectedItem;
bool _isLoggingOut = false; bool _isLoggingOut = false;
@override
void initState() {
super.initState();
selectedItem = 'profile'; // Default selection
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final profileAsync = ref.watch(employeeProfileProvider); final profileAsync = ref.watch(employeeProfileProvider);
@ -110,7 +116,7 @@ class _EmployeeProfileScreenState extends ConsumerState<EmployeeProfileScreen> {
Text( Text(
data?.name ?? 'No Company Name', data?.name ?? 'No Company Name',
style: const TextStyle( style: const TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 20, fontSize: 20,
color: Colors.black, color: Colors.black,
@ -244,7 +250,7 @@ class _EmployeeProfileScreenState extends ConsumerState<EmployeeProfileScreen> {
const Text( const Text(
"Note", "Note",
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 20, fontSize: 20,
color: Colors.black, color: Colors.black,
@ -254,7 +260,7 @@ class _EmployeeProfileScreenState extends ConsumerState<EmployeeProfileScreen> {
"Are you sure you want to log out?", "Are you sure you want to log out?",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
fontSize: 15, fontSize: 15,
color: Colors.black87, color: Colors.black87,
@ -270,7 +276,7 @@ class _EmployeeProfileScreenState extends ConsumerState<EmployeeProfileScreen> {
style: TextStyle( style: TextStyle(
color: Color(0xFF535A5B), color: Color(0xFF535A5B),
fontSize: 16, fontSize: 16,
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
@ -321,7 +327,7 @@ class _EmployeeProfileScreenState extends ConsumerState<EmployeeProfileScreen> {
style: TextStyle( style: TextStyle(
color: Color(0xFF5F297B), color: Color(0xFF5F297B),
fontSize: 16, fontSize: 16,
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
@ -384,7 +390,7 @@ class _EmployeeProfileScreenState extends ConsumerState<EmployeeProfileScreen> {
child: Text( child: Text(
title, title,
style: const TextStyle( style: const TextStyle(
fontFamily: 'Gilroy-Medium', fontFamily: "Gilroy",
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
color: Colors.black87, color: Colors.black87,

View File

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:taxglide/consts/app_asstes.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/consts/download_helper.dart';
import 'package:taxglide/controller/api_consts.dart'; import 'package:taxglide/controller/api_consts.dart';
import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/controller/api_contoller.dart';
@ -65,7 +66,7 @@ class _KycDetailsListState extends ConsumerState<KycDetailsList> {
"KYC Details", "KYC Details",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight fontWeight: FontWeight
.w600, // equivalent to 400 (Normal) .w600, // equivalent to 400 (Normal)
fontStyle: FontStyle.normal, fontStyle: FontStyle.normal,
@ -115,7 +116,7 @@ class _KycDetailsListState extends ConsumerState<KycDetailsList> {
"Personal Details", "Personal Details",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight fontWeight: FontWeight
.w400, // equivalent to 400 (Normal) .w400, // equivalent to 400 (Normal)
fontStyle: FontStyle.normal, fontStyle: FontStyle.normal,
@ -181,7 +182,7 @@ class _KycDetailsListState extends ConsumerState<KycDetailsList> {
'Edit', 'Edit',
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontFamily: 'Gilroy-SemiBold', fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal, fontStyle: FontStyle.normal,
fontSize: 16, fontSize: 16,
@ -277,9 +278,8 @@ class _KycDetailsListState extends ConsumerState<KycDetailsList> {
children: [ children: [
Text( Text(
title, title,
style: const TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 14, fontSize: 14,
height: 1.3, height: 1.3,
letterSpacing: 0.64, letterSpacing: 0.64,
@ -291,9 +291,8 @@ class _KycDetailsListState extends ConsumerState<KycDetailsList> {
value, value,
softWrap: true, softWrap: true,
overflow: TextOverflow.visible, overflow: TextOverflow.visible,
style: const TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-Regular',
fontWeight: FontWeight.w400,
fontSize: 14, fontSize: 14,
height: 1.3, height: 1.3,
letterSpacing: 0.64, letterSpacing: 0.64,
@ -342,9 +341,9 @@ class _KycDetailsListState extends ConsumerState<KycDetailsList> {
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: const TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Roboto',
fontWeight: FontWeight.w600,
fontSize: 13, fontSize: 13,
), ),
), ),

View File

@ -1,6 +1,7 @@
import 'dart:math' as math show sqrt; import 'dart:math' as math show sqrt;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:taxglide/consts/app_style.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:get/get.dart'; import 'package:get/get.dart';
import 'package:taxglide/consts/app_asstes.dart'; import 'package:taxglide/consts/app_asstes.dart';
@ -28,6 +29,7 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
selectedItem = 'profile'; // Set default selection
_loadRole(); // <-- load role on start _loadRole(); // <-- load role on start
} }
@ -104,10 +106,9 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
data!.companyName!.isNotEmpty) data!.companyName!.isNotEmpty)
? data.companyName![0].toUpperCase() ? data.companyName![0].toUpperCase()
: "M", : "M",
style: const TextStyle( style: AppTextStyles.bold.copyWith(
color: Colors.white, color: Colors.white,
fontSize: 40, fontSize: 40,
fontWeight: FontWeight.bold,
), ),
), ),
), ),
@ -120,9 +121,7 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
const SizedBox(height: 60), const SizedBox(height: 60),
Text( Text(
data?.companyName ?? 'No Company Name', data?.companyName ?? 'No Company Name',
style: const TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 20, fontSize: 20,
color: Colors.black, color: Colors.black,
), ),
@ -271,21 +270,17 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
const Text( Text(
"Note", "Note",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: 20, fontSize: 20,
color: Colors.black, color: Colors.black,
), ),
), ),
const Text( Text(
"Are you sure you want to log out?", "Are you sure you want to log out?",
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w500,
fontSize: 15, fontSize: 15,
color: Colors.black87, color: Colors.black87,
), ),
@ -295,13 +290,11 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
children: [ children: [
TextButton( TextButton(
onPressed: () => Navigator.pop(context), onPressed: () => Navigator.pop(context),
child: const Text( child: Text(
"Cancel", "Cancel",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
color: Color(0xFF535A5B), color: const Color(0xFF535A5B),
fontSize: 16, fontSize: 16,
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
), ),
), ),
), ),
@ -344,13 +337,11 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
color: Color(0xFF5F297B), color: Color(0xFF5F297B),
), ),
) )
: const Text( : Text(
"Log Out", "Log Out",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
color: Color(0xFF5F297B), color: const Color(0xFF5F297B),
fontSize: 16, fontSize: 16,
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
), ),
), ),
), ),
@ -411,10 +402,8 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
Expanded( Expanded(
child: Text( child: Text(
title, title,
style: const TextStyle( style: AppTextStyles.medium.copyWith(
fontFamily: 'Gilroy-Medium',
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.black87, color: Colors.black87,
), ),
), ),
@ -445,7 +434,7 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
Expanded( Expanded(
child: Text( child: Text(
msg, msg,
style: const TextStyle(color: Colors.white, fontSize: 12), style: AppTextStyles.regular.copyWith(color: Colors.white, fontSize: 12),
maxLines: 2, maxLines: 2,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),

View File

@ -16,7 +16,7 @@ class _StaffListScreenState extends ConsumerState<StaffListScreen> {
final staffAsync = ref.watch(staffListProvider); final staffAsync = ref.watch(staffListProvider);
const commonTextStyle = TextStyle( const commonTextStyle = TextStyle(
fontFamily: "Gilroy-SemiBold", fontFamily: "Gilroy",
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
fontSize: 14.7, fontSize: 14.7,
height: 1.30, // 130% height: 1.30, // 130%
@ -24,7 +24,7 @@ class _StaffListScreenState extends ConsumerState<StaffListScreen> {
color: Color(0xFF111827), color: Color(0xFF111827),
); );
const commonTextStylevalue = TextStyle( const commonTextStylevalue = TextStyle(
fontFamily: "Gilroy-SemiBold", fontFamily: "Gilroy",
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: 14.7, fontSize: 14.7,
height: 1.30, // 130% height: 1.30, // 130%

View File

@ -7,6 +7,7 @@ import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:path/path.dart' as path; 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/comman_button.dart';
import 'package:taxglide/consts/responsive_helper.dart'; import 'package:taxglide/consts/responsive_helper.dart';
import 'package:taxglide/controller/api_contoller.dart'; import 'package:taxglide/controller/api_contoller.dart';
@ -71,7 +72,7 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
Expanded( Expanded(
child: Text( child: Text(
msg, msg,
style: const TextStyle(color: Colors.white, fontSize: 12), style: AppTextStyles.regular.copyWith(color: Colors.white, fontSize: 12),
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
maxLines: 2, maxLines: 2,
), ),
@ -89,11 +90,11 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
}); });
bool isValid = true; bool isValid = true;
if (_selectedFiles.isEmpty) { // if (_selectedFiles.isEmpty) {
setState(() => _isFileError = true); // setState(() => _isFileError = true);
_showSnackBar("Please upload at least one file", isError: true); // _showSnackBar("Please upload at least one file", isError: true);
isValid = false; // isValid = false;
} // }
if (!_isTermsAccepted) { if (!_isTermsAccepted) {
setState(() => _isCheckboxError = true); setState(() => _isCheckboxError = true);
_showSnackBar("Please accept terms and conditions", isError: true); _showSnackBar("Please accept terms and conditions", isError: true);
@ -374,9 +375,7 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
children: [ children: [
Text( Text(
"New Service Request", "New Service Request",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: headerFontSize, fontSize: headerFontSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -424,9 +423,7 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
SizedBox(height: spacingMD), SizedBox(height: spacingMD),
Text( Text(
widget.service, widget.service,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: serviceNameFontSize, fontSize: serviceNameFontSize,
color: const Color(0xFF3F3F3F), color: const Color(0xFF3F3F3F),
), ),
@ -454,10 +451,8 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
"File Upload *", "File Upload",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: labelFontSize, fontSize: labelFontSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -527,9 +522,7 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
Expanded( Expanded(
child: Text( child: Text(
"I accept the terms and conditions *", "I accept the terms and conditions *",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontStyle: FontStyle.normal, fontStyle: FontStyle.normal,
fontSize: checkboxFontSize, fontSize: checkboxFontSize,
height: 25.56 / 12.78, height: 25.56 / 12.78,
@ -556,7 +549,7 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
), ),
), ),
const SizedBox(height: 250), SizedBox(height: r.spacing(mobile: 40, tablet: 60, desktop: 80)),
], ],
), ),
), ),
@ -568,9 +561,7 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
padding: EdgeInsets.symmetric(horizontal: hPadding), padding: EdgeInsets.symmetric(horizontal: hPadding),
child: Text( child: Text(
title, title,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: fontSize, fontSize: fontSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -597,9 +588,7 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 21), padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 21),
child: Text( child: Text(
text, text,
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: fontSize, fontSize: fontSize,
color: const Color(0xFF3F3F3F), color: const Color(0xFF3F3F3F),
), ),
@ -619,8 +608,8 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(6), borderRadius: BorderRadius.circular(6),
border: Border.all( border: Border.all(
color: _isFileError ? Colors.red : const Color(0xFFDFDFDF), color: const Color(0xFFDFDFDF),
width: _isFileError ? 2 : 1, width: 1,
), ),
), ),
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 21), padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 21),
@ -628,34 +617,22 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
children: [ children: [
Text( Text(
"Upload PDF, IMG, JPG, ZIP", "Upload PDF, IMG, JPG, ZIP",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: fontSize, fontSize: fontSize,
height: 25.56 / 12.78, height: 25.56 / 12.78,
letterSpacing: 0.8, letterSpacing: 0.8,
color: _isFileError ? Colors.red : const Color(0xFF4F4C4C), color: const Color(0xFF4F4C4C),
), ),
), ),
Text( Text(
"(40 MB only allowed File)", "(40 MB only allowed File)",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: subFontSize, fontSize: subFontSize,
height: 25.56 / 12.78, height: 25.56 / 12.78,
letterSpacing: 0.8, 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<ServiceRequestScreen> {
const SizedBox(width: 8), const SizedBox(width: 8),
Text( Text(
"Uploaded Files (${_selectedFiles.length})", "Uploaded Files (${_selectedFiles.length})",
style: TextStyle( style: AppTextStyles.semiBold.copyWith(
fontFamily: 'Gilroy-SemiBold',
fontWeight: FontWeight.w600,
fontSize: countFontSize, fontSize: countFontSize,
color: const Color(0xFF111827), color: const Color(0xFF111827),
), ),
@ -894,8 +869,7 @@ class _ServiceRequestScreenState extends ConsumerState<ServiceRequestScreen> {
controller: _messageController, controller: _messageController,
maxLines: null, maxLines: null,
expands: true, expands: true,
style: TextStyle( style: AppTextStyles.regular.copyWith(
fontFamily: 'Gilroy-Medium',
fontSize: fontSize, fontSize: fontSize,
color: const Color(0xFF6C7278), color: const Color(0xFF6C7278),
), ),

View File

@ -5,10 +5,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: "8d7ff3948166b8ec5da0fbb5962000926b8e02f2ed9b3e51d1738905fbd4c98d" sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "93.0.0" version: "85.0.0"
_flutterfire_internals: _flutterfire_internals:
dependency: transitive dependency: transitive
description: description:
@ -21,10 +21,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
sha256: de7148ed2fcec579b19f122c1800933dfa028f6d9fd38a152b04b1516cec120b sha256: "974859dc0ff5f37bc4313244b3218c791810d03ab3470a579580279ba971a48d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "10.0.1" version: "7.7.1"
animated_notch_bottom_bar: animated_notch_bottom_bar:
dependency: "direct main" dependency: "direct main"
description: description:
@ -101,10 +101,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: characters name: characters
sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.1" version: "1.4.0"
checked_yaml: checked_yaml:
dependency: transitive dependency: transitive
description: description:
@ -185,6 +185,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.8" 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: dbus:
dependency: transitive dependency: transitive
description: description:
@ -708,26 +716,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.18" version: "0.12.17"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.13.0" version: "0.11.1"
meta: meta:
dependency: transitive dependency: transitive
description: description:
name: meta name: meta
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.17.0" version: "1.16.0"
mime: mime:
dependency: transitive dependency: transitive
description: description:
@ -1113,26 +1121,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test name: test
sha256: "54c516bbb7cee2754d327ad4fca637f78abfc3cbcc5ace83b3eda117e42cd71a" sha256: "65e29d831719be0591f7b3b1a32a3cda258ec98c58c7b25f7b84241bc31215bb"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.29.0" version: "1.26.2"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.9" version: "0.7.6"
test_core: test_core:
dependency: transitive dependency: transitive
description: description:
name: test_core name: test_core
sha256: "394f07d21f0f2255ec9e3989f21e54d3c7dc0e6e9dbce160e5a9c1a6be0e2943" sha256: "80bf5a02b60af04b09e14f6fe68b921aad119493e26e490deaca5993fef1b05a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.15" version: "0.6.11"
timezone: timezone:
dependency: transitive dependency: transitive
description: description:
@ -1149,6 +1157,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.0" 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: url_launcher:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -39,6 +39,7 @@ dependencies:
gal: ^2.3.2 gal: ^2.3.2
web_socket_channel: ^3.0.2 web_socket_channel: ^3.0.2
flutter_local_notifications: ^18.0.1 flutter_local_notifications: ^18.0.1
curved_labeled_navigation_bar: ^2.0.6
@ -69,55 +70,39 @@ flutter:
fonts: fonts:
# =========================
# Gilroy Font Family
# =========================
- family: Gilroy - family: Gilroy
fonts: 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 - asset: assets/fonts/Gilroy-Regular.ttf
weight: 400 - family: Gilroy-Thin
- asset: assets/fonts/Gilroy-RegularItalic.ttf fonts:
weight: 400 - asset: assets/fonts/Gilroy-Thin.ttf
style: italic - 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 - asset: assets/fonts/Gilroy-Medium.ttf
weight: 500 - family: Gilroy-SemiBold
- asset: assets/fonts/Gilroy-MediumItalic.ttf fonts:
weight: 500
style: italic
- asset: assets/fonts/Gilroy-SemiBold.ttf - asset: assets/fonts/Gilroy-SemiBold.ttf
weight: 600 - family: Gilroy-Bold
- asset: assets/fonts/Gilroy-SemiBoldItalic.ttf fonts:
weight: 600
style: italic
- asset: assets/fonts/Gilroy-Bold.ttf - asset: assets/fonts/Gilroy-Bold.ttf
weight: 700 - family: Gilroy-ExtraBold
- asset: assets/fonts/Gilroy-BoldItalic.ttf fonts:
weight: 700
style: italic
- asset: assets/fonts/Gilroy-ExtraBold.ttf - asset: assets/fonts/Gilroy-ExtraBold.ttf
weight: 800 - family: Gilroy-Black
- asset: assets/fonts/Gilroy-ExtraBoldItalic.ttf fonts:
weight: 800
style: italic
- asset: assets/fonts/Gilroy-Black.ttf - asset: assets/fonts/Gilroy-Black.ttf
weight: 900 - family: Gilroy-Heavy
- asset: assets/fonts/Gilroy-BlackItalic.ttf fonts:
weight: 900
style: italic
- asset: assets/fonts/Gilroy-Heavy.ttf - asset: assets/fonts/Gilroy-Heavy.ttf
weight: 900
- asset: assets/fonts/Gilroy-HeavyItalic.ttf
weight: 900
style: italic