bug fixes and more changes
This commit is contained in:
@@ -13,12 +13,13 @@ class ForgotPasswordBloc extends Bloc<ForgotPasswordEvent, ForgotPasswordState>
|
||||
super(const ForgotPasswordState()) {
|
||||
on<ForgotPasswordSubmitted>(_onForgotPasswordSubmitted);
|
||||
on<ForgotPasswordEmailErrorToggled>(_onEmailErrorToggled);
|
||||
on<ForgotPasswordReset>(_onReset);
|
||||
}
|
||||
|
||||
Future<void> _onForgotPasswordSubmitted(
|
||||
ForgotPasswordSubmitted event,
|
||||
Emitter<ForgotPasswordState> emit,
|
||||
) async {
|
||||
ForgotPasswordSubmitted event,
|
||||
Emitter<ForgotPasswordState> emit,
|
||||
) async {
|
||||
emit(state.copyWith(status: ForgotPasswordStatus.loading, errorMessage: null));
|
||||
|
||||
try {
|
||||
@@ -36,9 +37,16 @@ class ForgotPasswordBloc extends Bloc<ForgotPasswordEvent, ForgotPasswordState>
|
||||
}
|
||||
|
||||
void _onEmailErrorToggled(
|
||||
ForgotPasswordEmailErrorToggled event,
|
||||
Emitter<ForgotPasswordState> emit,
|
||||
) {
|
||||
ForgotPasswordEmailErrorToggled event,
|
||||
Emitter<ForgotPasswordState> emit,
|
||||
) {
|
||||
emit(state.copyWith(showEmailError: event.show));
|
||||
}
|
||||
|
||||
Future<void> _onReset(
|
||||
ForgotPasswordReset event,
|
||||
Emitter<ForgotPasswordState> emit,
|
||||
) async {
|
||||
emit(const ForgotPasswordState());
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,16 @@ class ForgotPasswordSubmitted extends ForgotPasswordEvent {
|
||||
|
||||
class ForgotPasswordEmailErrorToggled extends ForgotPasswordEvent {
|
||||
final bool show;
|
||||
|
||||
const ForgotPasswordEmailErrorToggled(this.show);
|
||||
|
||||
@override
|
||||
List<Object?> get props => [show];
|
||||
}
|
||||
|
||||
class ForgotPasswordReset extends ForgotPasswordEvent {
|
||||
const ForgotPasswordReset();
|
||||
|
||||
@override
|
||||
List<Object?> get props => [];
|
||||
}
|
||||
@@ -16,14 +16,20 @@ class VerifyOtpBloc extends Bloc<VerifyOtpEvent, VerifyOtpState> {
|
||||
}
|
||||
|
||||
void _onOtpChanged(OtpChanged event, Emitter<VerifyOtpState> emit) {
|
||||
emit(state.copyWith(otp: event.otp));
|
||||
emit(state.copyWith(
|
||||
otp: event.otp,
|
||||
status: VerifyOtpStatus.initial,
|
||||
clearError: true,
|
||||
));
|
||||
}
|
||||
|
||||
Future<void> _onVerifyOtpSubmitted(
|
||||
VerifyOtpSubmitted event,
|
||||
Emitter<VerifyOtpState> emit,
|
||||
) async {
|
||||
emit(state.copyWith(status: VerifyOtpStatus.loading, errorMessage: null));
|
||||
if (state.status == VerifyOtpStatus.loading) return;
|
||||
|
||||
emit(state.copyWith(status: VerifyOtpStatus.loading, clearError: true));
|
||||
|
||||
try {
|
||||
await _otpRepository.verifyOtp(
|
||||
|
||||
@@ -16,11 +16,12 @@ class VerifyOtpState extends Equatable {
|
||||
VerifyOtpState copyWith({
|
||||
VerifyOtpStatus? status,
|
||||
String? errorMessage,
|
||||
bool clearError = false,
|
||||
String? otp,
|
||||
}) {
|
||||
return VerifyOtpState(
|
||||
status: status ?? this.status,
|
||||
errorMessage: errorMessage ?? this.errorMessage,
|
||||
errorMessage: clearError ? null : (errorMessage ?? this.errorMessage),
|
||||
otp: otp ?? this.otp,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class ForgotPasswordRepository {
|
||||
data: {"emailAddress": emailAddress},
|
||||
);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to send forgot password request: $e');
|
||||
throw Exception('$e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ class OtpRepository {
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to verify OTP: $e');
|
||||
throw Exception('$e');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,13 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
|
||||
final _emailController = TextEditingController();
|
||||
final _emailFocusNode = FocusNode();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// Reset the form state when entering the page
|
||||
context.read<ForgotPasswordBloc>().add(ForgotPasswordReset());
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_emailController.dispose();
|
||||
@@ -28,7 +35,8 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
|
||||
}
|
||||
|
||||
bool _isEmailValid(String email) {
|
||||
return RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")
|
||||
return RegExp(
|
||||
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$')
|
||||
.hasMatch(email);
|
||||
}
|
||||
|
||||
@@ -100,7 +108,7 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
|
||||
),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
"Partner’s App",
|
||||
"Partner's App",
|
||||
style: GoogleFonts.poppins(
|
||||
color: AppColors.primaryRed,
|
||||
fontSize: 20.sp,
|
||||
@@ -124,11 +132,11 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
|
||||
),
|
||||
SizedBox(height: 12.h),
|
||||
Text(
|
||||
"Enter your email to update your password\nand secure your account",
|
||||
"Enter your email to update your password and secure your account",
|
||||
textAlign: TextAlign.center,
|
||||
style: GoogleFonts.poppins(
|
||||
color: AppColors.textGrey,
|
||||
fontSize: 16.sp,
|
||||
fontSize: 15.sp,
|
||||
height: 1.4,
|
||||
),
|
||||
),
|
||||
@@ -147,6 +155,7 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
|
||||
textInputAction: TextInputAction.done,
|
||||
readOnly: isLoading,
|
||||
onChanged: (val) {
|
||||
// Only validate and update error if user has attempted submission
|
||||
if (state.showEmailError) {
|
||||
context.read<ForgotPasswordBloc>().add(
|
||||
ForgotPasswordEmailErrorToggled(!_isEmailValid(val.trim())),
|
||||
|
||||
@@ -32,7 +32,8 @@ class _LoginPageState extends State<LoginPage> {
|
||||
}
|
||||
|
||||
bool _isEmailValid(String email) {
|
||||
return RegExp(r"^[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+")
|
||||
return RegExp(
|
||||
r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$')
|
||||
.hasMatch(email);
|
||||
}
|
||||
|
||||
@@ -70,6 +71,12 @@ class _LoginPageState extends State<LoginPage> {
|
||||
body: BlocConsumer<LoginBloc, LoginState>(
|
||||
listener: (context, state) {
|
||||
if (state.status == LoginStatus.success) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text("Login Successful."),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
Navigator.pushNamedAndRemoveUntil(
|
||||
context,
|
||||
AppRouter.qrScanScreen,
|
||||
@@ -292,4 +299,4 @@ class _LoginPageState extends State<LoginPage> {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@ class OtpVerificationPage extends StatelessWidget {
|
||||
arguments: email,
|
||||
);
|
||||
} else if (state.status == VerifyOtpStatus.failure) {
|
||||
ScaffoldMessenger.of(context).hideCurrentSnackBar();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(state.errorMessage ?? "Verification failed"),
|
||||
@@ -116,6 +117,7 @@ class OtpVerificationPage extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
onSubmit: (String verificationCode) {
|
||||
if (isLoading) return;
|
||||
context.read<VerifyOtpBloc>().add(
|
||||
OtpChanged(otp: verificationCode),
|
||||
);
|
||||
@@ -136,7 +138,7 @@ class OtpVerificationPage extends StatelessWidget {
|
||||
CustomButton(
|
||||
text: "Verify",
|
||||
isLoading: isLoading,
|
||||
onPressed: state.otp.length == 6
|
||||
onPressed: state.otp.length == 6 && !isLoading
|
||||
? () {
|
||||
context.read<VerifyOtpBloc>().add(
|
||||
VerifyOtpSubmitted(
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import '../../core/app_router.dart';
|
||||
import '../blocs/onboarding_bloc.dart';
|
||||
import '../models/onboarding_model.dart';
|
||||
@@ -58,7 +59,7 @@ class OnboardingPage extends StatelessWidget {
|
||||
if (current.title != "Manage Booking Seamlessly")
|
||||
SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: Align(
|
||||
alignment: Alignment.topRight,
|
||||
child: OutlinedButton(
|
||||
@@ -66,14 +67,23 @@ class OnboardingPage extends StatelessWidget {
|
||||
context.read<OnboardingBloc>().add(OnboardingSkipPressed());
|
||||
},
|
||||
style: OutlinedButton.styleFrom(
|
||||
side: const BorderSide(color: Colors.white),
|
||||
side: BorderSide(color: Colors.white, width: 2.w),
|
||||
foregroundColor: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 8,
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 34.w,
|
||||
vertical: 10.h,
|
||||
),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(16.r),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
"Skip",
|
||||
style: TextStyle(
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
child: const Text("Skip"),
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -83,7 +93,7 @@ class OnboardingPage extends StatelessWidget {
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
padding: EdgeInsets.all(16.r),
|
||||
child: AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 500),
|
||||
transitionBuilder: (Widget child, Animation<double> animation) {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'dart:ui';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
|
||||
class GlassCard extends StatelessWidget {
|
||||
final String title;
|
||||
@@ -20,15 +21,15 @@ class GlassCard extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderRadius: BorderRadius.circular(10.r),
|
||||
child: BackdropFilter(
|
||||
filter: ImageFilter.blur(sigmaX: 6, sigmaY: 6),
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
padding: const EdgeInsets.all(20),
|
||||
padding: EdgeInsets.all(20.r),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white.withOpacity(0.3),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderRadius: BorderRadius.circular(10.r),
|
||||
border: Border.all(color: Colors.white.withOpacity(0.2)),
|
||||
),
|
||||
child: Column(
|
||||
@@ -37,52 +38,52 @@ class GlassCard extends StatelessWidget {
|
||||
Text(
|
||||
title,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 20,
|
||||
fontSize: 20.sp,
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(height: 8.h),
|
||||
Text(
|
||||
description,
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Colors.white.withOpacity(0.9),
|
||||
fontSize: 14,
|
||||
fontSize: 14.sp,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
SizedBox(height: 16.h),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(
|
||||
total,
|
||||
(index) => AnimatedContainer(
|
||||
(index) => AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||
height: 6,
|
||||
width: currentIndex == index ? 24 : 12,
|
||||
margin: EdgeInsets.symmetric(horizontal: 4.w),
|
||||
height: 6.h,
|
||||
width: currentIndex == index ? 24.w : 12.w,
|
||||
decoration: BoxDecoration(
|
||||
color: currentIndex == index
|
||||
? const Color(0xFFE25E5E)
|
||||
: Colors.white24,
|
||||
borderRadius: BorderRadius.circular(3),
|
||||
borderRadius: BorderRadius.circular(3.r),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SizedBox(height: 20.h),
|
||||
ElevatedButton(
|
||||
onPressed: onContinue,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: const Color(0xFFE25E5E),
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderRadius: BorderRadius.circular(12.r),
|
||||
),
|
||||
minimumSize: const Size(double.infinity, 48),
|
||||
minimumSize: Size(double.infinity, 48.h),
|
||||
),
|
||||
child: const Text(
|
||||
child: Text(
|
||||
'Continue',
|
||||
style: TextStyle(fontSize: 16, color: Colors.white),
|
||||
style: TextStyle(fontSize: 16.sp, color: Colors.white),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@@ -36,7 +36,7 @@ class SubmitQrCodeBloc
|
||||
|
||||
final success = response['success'] == true;
|
||||
final message = response['message']?.toString();
|
||||
final error = response['error']?.toString();
|
||||
final error = response['suggestedReason']?.toString();
|
||||
|
||||
if (success) {
|
||||
emit(SubmitQrCodeSuccess(
|
||||
|
||||
@@ -6,6 +6,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||
import 'package:mobile_scanner/mobile_scanner.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import '../../local_peference/local_preference.dart';
|
||||
import '../bloc/submit_qr_code/submit_qr_code_bloc.dart';
|
||||
import '../bloc/recent_scan_history/recent_scan_history_bloc.dart';
|
||||
import '../models/recent_scan_history_model.dart';
|
||||
@@ -599,7 +600,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
SizedBox(height: 25.h),
|
||||
Text(
|
||||
"Quick Links",
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16.sp),
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 18.sp),
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
Row(
|
||||
@@ -611,6 +612,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
"assets/scan/ticket-fill.png",
|
||||
AppRouter.ticketRedemptionScreen,
|
||||
initFraction,
|
||||
10.h, // Added padding
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8.w),
|
||||
@@ -621,6 +623,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
"assets/scan/support.png",
|
||||
AppRouter.helpSupportPage,
|
||||
initFraction,
|
||||
10.h, // Added padding
|
||||
),
|
||||
),
|
||||
SizedBox(width: 8.w),
|
||||
@@ -631,10 +634,12 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
"assets/scan/page.png",
|
||||
AppRouter.bookingPage,
|
||||
initFraction,
|
||||
10.h, // Added padding
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
SizedBox(height: 10.h), // Empty space at bottom
|
||||
],
|
||||
);
|
||||
}
|
||||
@@ -722,7 +727,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
final index = entry.key;
|
||||
final item = entry.value;
|
||||
final isSuccess = item.status.toLowerCase() == "success";
|
||||
final label = index == 0 ? "Last Scan" : "Previous";
|
||||
final label = index == 0 ? "Last Scan" : "Previous Scan";
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
@@ -751,7 +756,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
|
||||
Text(
|
||||
"Quick Links",
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 16.sp),
|
||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 18.sp),
|
||||
),
|
||||
SizedBox(height: 10.h),
|
||||
Row(
|
||||
@@ -763,6 +768,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
"assets/scan/support.png",
|
||||
AppRouter.helpSupportPage,
|
||||
initFraction,
|
||||
22.h, // Added padding
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10.w),
|
||||
@@ -773,6 +779,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
"assets/scan/page.png",
|
||||
AppRouter.bookingPage,
|
||||
initFraction,
|
||||
22.h, // Added padding
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -787,6 +794,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
"assets/scan/ticket-fill.png",
|
||||
AppRouter.ticketRedemptionScreen,
|
||||
initFraction,
|
||||
22.h, // Added padding
|
||||
),
|
||||
),
|
||||
SizedBox(width: 10.w),
|
||||
@@ -797,6 +805,7 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
"assets/scan/qr.png",
|
||||
AppRouter.qrScanScreen,
|
||||
initFraction,
|
||||
22.h, // Added padding
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -865,7 +874,8 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
"Reason: $reason",
|
||||
style: TextStyle(
|
||||
fontSize: 12.sp,
|
||||
color: Colors.red[700],
|
||||
// color: Colors.red[700],
|
||||
color: Colors.black87,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -885,14 +895,16 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
}
|
||||
|
||||
Widget _quickLink(
|
||||
BuildContext context,
|
||||
String label,
|
||||
String icon,
|
||||
String route,
|
||||
double initFraction,
|
||||
) {
|
||||
BuildContext context,
|
||||
String label,
|
||||
String icon,
|
||||
String route,
|
||||
double initFraction,
|
||||
double? verticalPadding, // Add this parameter
|
||||
) {
|
||||
return InkWell(
|
||||
onTap: () async {
|
||||
// await LocalPreference.clearAccessToken();
|
||||
if (label == "Scan Image") {
|
||||
if (sheetController.isAttached) {
|
||||
await sheetController.animateTo(
|
||||
@@ -909,10 +921,12 @@ class _QrScanScreenState extends State<QrScanScreen>
|
||||
},
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.red[100],
|
||||
color: Colors.red[100]?.withValues(alpha: 0.6),
|
||||
borderRadius: BorderRadius.circular(10.r),
|
||||
),
|
||||
padding: EdgeInsets.symmetric(vertical: 10.h),
|
||||
padding: EdgeInsets.symmetric(
|
||||
vertical: verticalPadding ?? 12.h, // Use parameter, default to 12 if not provided
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
|
||||
@@ -82,12 +82,22 @@ class ScanHistory {
|
||||
);
|
||||
}
|
||||
|
||||
/// 🔥 Safe Date Parser
|
||||
/// 🔥 Safe Date Parser - Handles multiple formats
|
||||
static DateTime? _parseDate(dynamic date) {
|
||||
if (date == null) return null;
|
||||
try {
|
||||
return DateTime.parse(date.toString());
|
||||
final dateStr = date.toString().trim();
|
||||
|
||||
// Try ISO 8601 format first (2026-04-20T16:21:00)
|
||||
try {
|
||||
return DateTime.parse(dateStr);
|
||||
} catch (e) {
|
||||
// If that fails, try DD-MM-YYYY HH:MM format (20-04-2026 16:21)
|
||||
final dateFormat = DateFormat('dd-MM-yyyy HH:mm');
|
||||
return dateFormat.parse(dateStr);
|
||||
}
|
||||
} catch (e) {
|
||||
print('❌ Failed to parse date: $date, Error: $e');
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -143,6 +153,6 @@ class ScanHistory {
|
||||
String get statusColorHex {
|
||||
if (isSuccess) return '#4CAF50'; // green
|
||||
if (isFailed) return '#F44336'; // red
|
||||
return '#9E9E9E'; // grey
|
||||
return '#9E9E9E'; // gre
|
||||
}
|
||||
}
|
||||
@@ -10,23 +10,20 @@ class ScanHistoryDetailPage extends StatelessWidget {
|
||||
const ScanHistoryDetailPage({super.key, required this.passId});
|
||||
|
||||
TextStyle _headerStyle() => const TextStyle(
|
||||
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 24,
|
||||
fontSize: 28,
|
||||
height: 1.0,
|
||||
);
|
||||
|
||||
TextStyle _labelStyle() => const TextStyle(
|
||||
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14,
|
||||
fontSize: 18,
|
||||
color: Color(0xFF9E9E9E),
|
||||
);
|
||||
|
||||
TextStyle _valueStyle() => const TextStyle(
|
||||
|
||||
fontWeight: FontWeight.w400,
|
||||
fontSize: 12,
|
||||
fontSize: 16,
|
||||
color: Colors.black,
|
||||
);
|
||||
|
||||
@@ -100,10 +97,10 @@ class ScanHistoryDetailPage extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Center(
|
||||
child: Text(
|
||||
'#${data.bookingNumber}',
|
||||
data.bookingNumber,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w700,
|
||||
fontSize: 28,
|
||||
fontSize: 22,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -175,10 +172,4 @@ class ScanHistoryDetailPage extends StatelessWidget {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user