Commit ba590246 authored by Sai Srinivas's avatar Sai Srinivas
Browse files

All testes clear and updated

parents 558ac0d8 cdbe1e86
This image diff could not be displayed because it is too large. You can view the blob instead.
......@@ -271,6 +271,7 @@ class HelpAndEnquiryProvider extends ChangeNotifier {
orderId,
otherReason,
images,
);
// Check if widget is still mounted before showing dialogs
......@@ -282,10 +283,7 @@ class HelpAndEnquiryProvider extends ChangeNotifier {
);
//Navigator.pop(context); // close bottom sheet or dialog if open
if (context.mounted) {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HelpScreen(sessionId: sessionId, accId: accId))
);
Navigator.pop(context);
}
} else {
......
......@@ -257,33 +257,33 @@ class _BillDetailScreenState extends State<BillDetailScreen> {
child: Row(
children: [
// Pay Now Button (only if not paid)
if (!isPaid) ...[
Expanded(
child: ElevatedButton(
onPressed: () {
_showPayNowDialog(screenWidth, screenHeight);
},
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.buttonColor,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(screenWidth * 0.03),
),
padding: EdgeInsets.symmetric(vertical: screenHeight * 0.018),
elevation: 0,
),
child: Text(
"Pay Now",
style: TextStyle(
fontSize: getResponsiveTextSize(context, 14),
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
),
),
),
),
SizedBox(width: screenWidth * 0.03),
],
// if (!isPaid) ...[
// Expanded(
// child: ElevatedButton(
// onPressed: () {
// _showPayNowDialog(screenWidth, screenHeight);
// },
// style: ElevatedButton.styleFrom(
// backgroundColor: AppColors.buttonColor,
// foregroundColor: Colors.white,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(screenWidth * 0.03),
// ),
// padding: EdgeInsets.symmetric(vertical: screenHeight * 0.018),
// elevation: 0,
// ),
// child: Text(
// "Pay Now",
// style: TextStyle(
// fontSize: getResponsiveTextSize(context, 14),
// fontFamily: "Poppins",
// fontWeight: FontWeight.w600,
// ),
// ),
// ),
// ),
// SizedBox(width: screenWidth * 0.03),
// ],
// Download Receipt Button
Expanded(
......@@ -315,7 +315,7 @@ class _BillDetailScreenState extends State<BillDetailScreen> {
label: Text(
provider.isDownloading
? "Downloading..."
: "Download Receipt",
: "Download Bill",
style: TextStyle(
fontSize: getResponsiveTextSize(context, 14),
fontFamily: "Plus Jakarta Sans",
......
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gen_rentals/Screens/HelpScreens/EnquiryScreen.dart';
import 'package:gen_rentals/Screens/HelpScreens/HelpScreen.dart';
......@@ -48,7 +51,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
}
}
// Handle back button press
// Handle back button press
Future<bool> _onWillPop() async {
DateTime now = DateTime.now();
if (currentBackPressTime == null ||
......@@ -61,9 +64,12 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
);
return false;
}
return true;
// Close the entire app immediately
exit(0);
}
// Responsive text size function
double getResponsiveTextSize(BuildContext context, double baseSize) {
final double width = MediaQuery.of(context).size.width;
......@@ -212,7 +218,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
// Header with profile
Container(
width: double.infinity,
height: screenHeight * 0.55,
height: screenHeight * 0.51,
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
......@@ -228,7 +234,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
),
child: Column(
children: [
SizedBox(height: screenHeight * 0.06),
SizedBox(height: screenHeight * 0.09),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
......@@ -260,10 +266,11 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
mainAxisAlignment: MainAxisAlignment.start,
children: [
Image.asset(
'assets/images/gene_png.png',
'assets/images/dashboard_gen.png',
height: screenHeight * 0.25,
width: screenWidth * 0.6,
),
SizedBox(height: 5,),
Text(
"Welcome!",
style: TextStyle(
......@@ -288,8 +295,6 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
),
),
SizedBox(height: screenHeight * 0.01),
// Main content section
Container(
padding: EdgeInsets.symmetric(horizontal: getResponsivePadding(context)),
......@@ -387,7 +392,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
// Subscribed Orders
Container(
width: double.infinity,
padding: EdgeInsets.symmetric(horizontal: screenWidth * 0.005, vertical: screenHeight * 0.012),
padding: EdgeInsets.symmetric(horizontal: screenWidth * 0.0009, vertical: screenHeight * 0.012),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
......@@ -896,9 +901,10 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
bottomRight: Radius.circular(screenWidth * 0.05),
),
),
child: Center(
child: Row(
children: [
SizedBox(width: screenWidth * 0.03),
SizedBox(width: screenWidth * 0.02),
Icon(Icons.info_outline, color: Colors.red, size: getResponsiveIconSize(context, 15)),
SizedBox(width: screenWidth * 0.01),
Expanded(
......@@ -907,16 +913,16 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
"Payment Pending. Please Pay before incurring fines.",
style: TextStyle(
fontFamily: "Poppins",
color: Colors.red,
fontSize: getResponsiveTextSize(context, 11),
color: Colors.black87,
fontSize: getResponsiveTextSize(context, 10),
fontWeight: FontWeight.w400,
),
),
),
SizedBox(width: screenWidth * 0.03),
],
),
),
),
],
),
),
......@@ -952,7 +958,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
width: getResponsiveIconSize(context, 40),
fit: BoxFit.contain,
errorBuilder: (context, error, stack) =>
Image.asset('assets/images/gene_png.png',
Image.asset('assets/images/dashboard_gen.png',
height: getResponsiveIconSize(context, 40),
width: getResponsiveIconSize(context, 40)),
),
......@@ -985,7 +991,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
],
),
// Gradient expiry badge
// Gradient expiry badge
if (product.expiringText != null && product.expiringText!.isNotEmpty)
Container(
padding: EdgeInsets.symmetric(
......@@ -1038,7 +1044,7 @@ class _DashboardScreenState extends State<DashboardScreen> with WidgetsBindingOb
"• ",
style: TextStyle(
color: Colors.black,
fontSize: getResponsiveTextSize(context, 16)
fontSize: getResponsiveTextSize(context, 14)
),
),
Expanded(
......
......@@ -32,6 +32,9 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
List<File> _selectedImages = [];
String _selectedReason = 'Payment Issues';
// Success dialog state
bool _showSuccessDialog = false;
final List<Map<String, dynamic>> createNewTickets = [
{
'title': 'Payment \nIssues',
......@@ -130,15 +133,17 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
"Help?",
style: TextStyle(
fontSize: getResponsiveTextSize(context, 16),
fontFamily: "Plus Jakarta Sans",
fontWeight: FontWeight.w600,
fontFamily: "Poppins",
fontWeight: FontWeight.w500,
color: Colors.black87,
),
),
],
),
),
body: SingleChildScrollView(
body: Stack(
children: [
SingleChildScrollView(
padding: EdgeInsets.all(getResponsivePadding(context)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
......@@ -149,6 +154,7 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
SectionHeading(
title: 'Create New Ticket',
textStyle: TextStyle(
fontFamily: "Poppins",
fontSize: getResponsiveTextSize(context, 16),
fontWeight: FontWeight.w500
),
......@@ -163,10 +169,10 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
borderRadius: BorderRadius.circular(screenWidth * 0.025),
),
child: Text(
"order #${widget.orderId}",
"Order #${widget.orderId}",
style: TextStyle(
fontSize: getResponsiveTextSize(context, 12),
fontFamily: "Plus Jakarta Sans",
fontFamily: "Poppins",
fontWeight: FontWeight.w400,
color: Colors.black87,
),
......@@ -199,6 +205,7 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
style: TextStyle(
fontSize: getResponsiveTextSize(context, 14),
fontStyle: FontStyle.normal,
fontFamily: "Poppins",
fontWeight: FontWeight.w400,
color: Colors.black87,
),
......@@ -208,7 +215,7 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
SizedBox(width: screenWidth * 0.008),
SvgPicture.asset(
"assets/svg/edit_ic.svg",
height: getResponsiveIconSize(context, 22),
height: getResponsiveIconSize(context, 19),
),
],
),
......@@ -250,6 +257,10 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Add file button
Container(
width: getResponsiveIconSize(context, 60),
height: getResponsiveIconSize(context, 60),
......@@ -266,20 +277,23 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
),
),
),
SizedBox(height: screenHeight * 0.01),
SizedBox(width: screenWidth * 0.02),
// Attached images in horizontal scroll
if (_selectedImages.isNotEmpty)
GridView.builder(
Expanded(
child: SizedBox(
height: getResponsiveIconSize(context, 60),
child: ListView.builder(
scrollDirection: Axis.horizontal,
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: isSmallScreen ? 3 : 4,
crossAxisSpacing: screenWidth * 0.02,
mainAxisSpacing: screenWidth * 0.02,
childAspectRatio: 1.0,
),
itemCount: _selectedImages.length,
itemBuilder: (context, index) {
return Stack(
return Container(
margin: EdgeInsets.only(right: screenWidth * 0.02),
width: getResponsiveIconSize(context, 60),
height: getResponsiveIconSize(context, 60),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(screenWidth * 0.02),
......@@ -310,20 +324,106 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
),
),
],
),
);
},
),
),
),
],
),
SizedBox(height: screenHeight * 0.01),
],
),
),
SizedBox(height: screenHeight * 0.03),
],
),
),
// Success Dialog
if (_showSuccessDialog)
Container(
color: Colors.black54,
child: Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
"Submitted",
style: TextStyle(
fontSize: 18,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
const SizedBox(height: 16),
Text(
"Thanks for reaching out!",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 12,
fontFamily: "Poppins",
fontWeight: FontWeight.w400,
color: AppColors.subtitleText,
),
),
const Text(
"Our team will review your ticket and reply to you soon.",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
fontFamily: "Poppins",
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
setState(() {
_showSuccessDialog = false;
});
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.buttonColor,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(28),
),
),
child: const Text(
"Close",
style: TextStyle(
fontFamily: "Poppins",
fontSize: 15,
fontWeight: FontWeight.w400,
),
),
),
),
],
),
),
),
),
],
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.all(14.0),
padding: const EdgeInsets.all(15.0),
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
......@@ -331,7 +431,7 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.buttonColor,
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: getResponsiveButtonHeight(context) * 0.34),
padding: EdgeInsets.symmetric(vertical: getResponsiveButtonHeight(context) * 0.32),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(screenWidth * 0.07),
),
......@@ -349,8 +449,9 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
: Text(
'Submit',
style: TextStyle(
fontFamily: "Poppins",
fontSize: getResponsiveTextSize(context, 14),
fontWeight: FontWeight.w400,
fontWeight: FontWeight.w500,
),
),
),
......@@ -363,6 +464,7 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
Widget _fieldLabel(String text) => Text(
text,
style: TextStyle(
fontFamily: "Poppins",
fontSize: getResponsiveTextSize(context, 14),
fontStyle: FontStyle.normal,
fontWeight: FontWeight.w400,
......@@ -386,11 +488,13 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
style: TextStyle(
fontSize: getResponsiveTextSize(context, 14),
fontWeight: FontWeight.w400,
fontFamily: "Poppins",
color: Colors.black87,
),
decoration: InputDecoration(
hintText: hint,
hintStyle: TextStyle(
fontFamily: "Poppins",
fontSize: getResponsiveTextSize(context, 14),
fontWeight: FontWeight.w400,
color: Colors.grey[400],
......@@ -451,21 +555,45 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
reason = "Other";
}
// If user selected "Other Issues", use the custom reason text
final customReason = _selectedReason == 'Other Issues' ? otherReason : null;
debugPrint("Reason ========= $reason");
final helpProvider = Provider.of<HelpAndEnquiryProvider>(context, listen: false);
final helpProvider =
Provider.of<HelpAndEnquiryProvider>(context, listen: false);
// Show success dialog
setState(() {
_showSuccessDialog = true;
});
// Clear form
_issueController.clear();
_otherReasonController.clear();
setState(() {
_selectedImages.clear();
});
// Wait for 2 seconds to show the success dialog
await Future.delayed(Duration(seconds: 2));
if (!mounted) return;
// Close the dialog
setState(() {
_showSuccessDialog = false;
});
// Wait a brief moment for dialog to close, then call the API
await Future.delayed(Duration(milliseconds: 300));
if (!mounted) return;
// Now call the provider method which will handle navigation
await helpProvider.createTicket(
sessionId: widget.sessionId,
accId: widget.accId,
type: reason,
description: issue,
orderId: "1235",
otherReason: customReason.toString(),
orderId: widget.orderId,
otherReason: customReason?.toString() ?? "",
images: _selectedImages,
context: context,
);
......@@ -498,7 +626,7 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
"Select Your Reason",
style: TextStyle(
fontSize: getResponsiveTextSize(context, 16),
fontFamily: "Plus Jakarta Sans",
fontFamily: "Poppins",
fontWeight: FontWeight.w500,
color: Colors.black87,
),
......@@ -583,7 +711,7 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
fontSize: isSmallScreen ? 11 : 13, // Same font sizing logic
fontStyle: FontStyle.normal,
fontWeight: FontWeight.w400,
fontFamily: "Plus Jakarta Sans",
fontFamily: "Poppins",
),
maxLines: 2,
overflow: TextOverflow.ellipsis,
......@@ -595,6 +723,7 @@ class _HelpTicketScreenState extends State<HelpTicketScreen> {
),
);
}
@override
void dispose() {
_issueController.dispose();
......
......@@ -28,6 +28,15 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
final TextEditingController requirementController = TextEditingController();
final TextEditingController noteController = TextEditingController();
// Track field validation states for real-time validation
bool _nameValid = true;
bool _emailValid = true;
bool _phoneValid = true;
bool _requirementValid = true;
// Success dialog state
bool _showSuccessDialog = false;
@override
Widget build(BuildContext context) {
final enquiryProvider = Provider.of<HelpAndEnquiryProvider>(context);
......@@ -65,7 +74,9 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
),
// Main Body
body: SingleChildScrollView(
body: Stack(
children: [
SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
child: Form(
key: _formKey,
......@@ -77,6 +88,11 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
controller: nameController,
hint: "Enter Name",
fieldName: "Name",
onChanged: (value) {
setState(() {
_nameValid = value.trim().isNotEmpty;
});
},
),
const SizedBox(height: 16),
......@@ -96,6 +112,14 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
}
return null;
},
onChanged: (value) {
setState(() {
_emailValid = value != null &&
value.trim().isNotEmpty &&
RegExp(r'^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$')
.hasMatch(value.trim());
});
},
),
const SizedBox(height: 16),
......@@ -114,6 +138,13 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
}
return null;
},
onChanged: (value) {
setState(() {
_phoneValid = value != null &&
value.trim().isNotEmpty &&
value.trim().length >= 10;
});
},
),
const SizedBox(height: 16),
......@@ -122,6 +153,11 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
controller: requirementController,
hint: "Enter Requirement",
fieldName: "Requirement",
onChanged: (value) {
setState(() {
_requirementValid = value.trim().isNotEmpty;
});
},
),
const SizedBox(height: 16),
......@@ -131,6 +167,7 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
hint: "Write a short note",
fieldName: "Note",
maxLines: 5,
isOptional: true,
),
const SizedBox(height: 32),
......@@ -143,7 +180,41 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
: () async {
FocusScope.of(context).unfocus();
if (!_formKey.currentState!.validate()) return;
// Validate all fields
bool isValid = true;
if (nameController.text.trim().isEmpty) {
setState(() {
_nameValid = false;
});
isValid = false;
}
if (emailController.text.trim().isEmpty ||
!RegExp(r'^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$')
.hasMatch(emailController.text.trim())) {
setState(() {
_emailValid = false;
});
isValid = false;
}
if (phoneController.text.trim().isEmpty ||
phoneController.text.trim().length < 10) {
setState(() {
_phoneValid = false;
});
isValid = false;
}
if (requirementController.text.trim().isEmpty) {
setState(() {
_requirementValid = false;
});
isValid = false;
}
if (!isValid) return;
final success =
await enquiryProvider.submitEnquiry(
......@@ -159,22 +230,25 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
if (!mounted) return;
if (success) {
CustomSnackBar.showSuccess(
context: context,
message: enquiryProvider.message ??
"Enquiry submitted successfully!",
);
// Show success dialog instead of snackbar
setState(() {
_showSuccessDialog = true;
});
// Clear form
_formKey.currentState!.reset();
nameController.clear();
emailController.clear();
phoneController.clear();
requirementController.clear();
noteController.clear();
Future.delayed(Duration(seconds: 1), () {
// Reset validation states
setState(() {
Navigator.pop(context);
});
_nameValid = true;
_emailValid = true;
_phoneValid = true;
_requirementValid = true;
});
} else {
......@@ -217,6 +291,77 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
),
),
),
// Success Dialog
if (_showSuccessDialog)
Container(
color: Colors.black54,
child: Center(
child: Container(
width: MediaQuery.of(context).size.width * 0.8,
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(16),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const Text(
"Submitted",
style: TextStyle(
fontSize: 18,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
const SizedBox(height: 16),
const Text(
"Thanks for reaching out!\n\nWe've got your application.\nOur representative will call you soon.",
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 14,
fontFamily: "Poppins",
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
setState(() {
_showSuccessDialog = false;
});
Navigator.pop(context);
},
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.buttonColor,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(28),
),
),
child: const Text(
"Close",
style: TextStyle(
fontFamily: "Poppins",
fontSize: 15,
fontWeight: FontWeight.w400,
),
),
),
),
],
),
),
),
),
],
),
),
);
}
......@@ -242,17 +387,36 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
required String fieldName,
TextInputType keyboardType = TextInputType.text,
int maxLines = 1,
bool isOptional = false,
String? Function(String?)? validator,
Function(String)? onChanged,
}) {
return FormField<String>(
validator: validator ??
(value) {
if (controller.text.trim().isEmpty) {
return '$fieldName is required';
bool hasError = false;
String errorText = '';
// Determine validation state based on field type
if (fieldName == "Name" && !_nameValid) {
hasError = true;
errorText = "Name is required";
} else if (fieldName == "Email" && !_emailValid) {
hasError = true;
if (emailController.text.trim().isEmpty) {
errorText = "Please enter your email";
} else {
errorText = "Enter a valid email";
}
return null;
},
builder: (field) {
} else if (fieldName == "Phone Number" && !_phoneValid) {
hasError = true;
if (phoneController.text.trim().isEmpty) {
errorText = "Please enter your phone number";
} else {
errorText = "Enter a valid phone number";
}
} else if (fieldName == "Requirement" && !_requirementValid) {
hasError = true;
errorText = "Requirement is required";
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
......@@ -261,7 +425,7 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
color: Color(0xffF6F6F8),
borderRadius: BorderRadius.circular(12),
// border: Border.all(
// color: field.hasError ? Colors.red : Colors.transparent,
// color: hasError ? Colors.red : Colors.transparent,
// width: 1,
// ),
),
......@@ -269,7 +433,26 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
controller: controller,
keyboardType: keyboardType,
maxLines: maxLines,
onChanged: (_) => field.didChange(controller.text),
onChanged: (value) {
if (onChanged != null) onChanged(value);
// Clear error when user starts typing
if (value.isNotEmpty) {
setState(() {
if (fieldName == "Name") _nameValid = true;
if (fieldName == "Email") {
_emailValid = value.trim().isNotEmpty &&
RegExp(r'^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$')
.hasMatch(value.trim());
}
if (fieldName == "Phone Number") {
_phoneValid = value.trim().isNotEmpty &&
value.trim().length >= 10;
}
if (fieldName == "Requirement") _requirementValid = true;
});
}
},
style: TextStyle(
fontSize: 14,
fontFamily: "Poppins",
......@@ -291,11 +474,11 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
),
),
),
if (field.hasError)
if (hasError)
Padding(
padding: const EdgeInsets.only(top: 5, left: 4),
child: Text(
field.errorText ?? '',
errorText,
style: const TextStyle(
fontFamily: "Poppins",
color: Colors.red,
......@@ -305,8 +488,6 @@ class _EnquiryScreenState extends State<EnquiryScreen> {
),
],
);
},
);
}
@override
......
......@@ -135,17 +135,28 @@ class _HelpScreenState extends State<HelpScreen> {
_buildCreateNewTicketSection(),
const SizedBox(height: 12),
if (closedTickets.isEmpty && processingTickets.isEmpty)
Center(
child: SectionHeading(
title: 'No issues have been raised yet.',
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
),
),
// Processing Tickets Section
if (processingTickets.isNotEmpty)
SectionHeading(
title: 'Processing Tickets',
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
),
const SizedBox(height: 2),
if (processingTickets.isNotEmpty)
_buildProcessingTicketsSection(processingTickets),
const SizedBox(height: 10),
// Closed Tickets Section
if (closedTickets.isNotEmpty)
SectionHeading(
title: 'Closed Tickets',
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
......@@ -153,6 +164,7 @@ class _HelpScreenState extends State<HelpScreen> {
),
const SizedBox(height: 2),
if (closedTickets.isNotEmpty)
_buildClosedTicketsSection(closedTickets),
],
),
......
......@@ -127,7 +127,7 @@ class _OrderHelpScreenState extends State<OrderHelpScreen> {
// Create New Ticket Section
SectionHeading(
title: 'Select the order you are having issues with',
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, fontFamily: "Poppins",),
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 2),
),
......@@ -280,7 +280,7 @@ class _OrderHelpScreenState extends State<OrderHelpScreen> {
width: 42,
fit: BoxFit.contain,
errorBuilder: (context, error, stack) =>
Image.asset('assets/images/gene_png.png',
Image.asset('assets/images/dashboard_gen.png',
height: 40, width: 40),
),
),
......@@ -369,6 +369,7 @@ class _OrderHelpScreenState extends State<OrderHelpScreen> {
visibleItems[i],
style: const TextStyle(
color: Colors.black,
fontFamily: "Poppins",
fontSize: 14,
fontWeight: FontWeight.w400,
),
......@@ -430,10 +431,7 @@ class _OrderHelpScreenState extends State<OrderHelpScreen> {
}
}
void _showReasonBottomSheet(
Orders product,
) {
// Your existing bottom sheet implementation
void _showReasonBottomSheet(Orders product) {
showModalBottomSheet(
context: context,
backgroundColor: Colors.white,
......@@ -461,7 +459,7 @@ class _OrderHelpScreenState extends State<OrderHelpScreen> {
),
),
),
SizedBox(height: 12,),
SizedBox(height: 12),
Text(
"Select Your Reason",
style: TextStyle(
......@@ -496,6 +494,7 @@ class _OrderHelpScreenState extends State<OrderHelpScreen> {
orderId: product.orderid.toString(),
icon: icon,
color: color,
bottomSheetContext: context, // Pass the bottom sheet context
);
},
),
......@@ -513,9 +512,15 @@ class _OrderHelpScreenState extends State<OrderHelpScreen> {
required String icon,
required String orderId,
required Color color,
required BuildContext bottomSheetContext, // Add this parameter
}) {
return GestureDetector(
onTap: () {
// Close the bottom sheet first
Navigator.pop(bottomSheetContext);
// Then navigate to HelpTicketScreen after a small delay
Future.delayed(Duration(milliseconds: 300), () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => HelpTicketScreen(
......@@ -531,7 +536,7 @@ class _OrderHelpScreenState extends State<OrderHelpScreen> {
accId: widget.accId,
);
});
});
},
child: Container(
padding: const EdgeInsets.symmetric(horizontal: 2, vertical: 1),
......@@ -565,6 +570,7 @@ class _OrderHelpScreenState extends State<OrderHelpScreen> {
title,
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: "Poppins",
color: AppColors.nearDarkText,
fontSize: 13,
height: 1,
......
......@@ -275,6 +275,16 @@ class _TicketChatScreenState extends State<TicketChatScreen> {
),
);
},
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(12),
border: Border.all(
color: Colors.grey, // Border color
width: 1, // Border width
style: BorderStyle.solid, // Optional: solid, none
),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(12),
child: Image.network(
......@@ -293,6 +303,7 @@ class _TicketChatScreenState extends State<TicketChatScreen> {
),
),
),
),
),
if (imageName.length > index)
......
......@@ -90,8 +90,9 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
),
SizedBox(width: screenWidth * 0.025),
Text(
"Bill List",
"Bill Details",
style: TextStyle(
fontFamily: "Poppins",
fontSize: isSmallScreen ? 14 : 16,
fontWeight: FontWeight.w400,
color: Colors.black87,
......@@ -114,9 +115,9 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
child: _buildBody(provider, screenWidth, screenHeight),
),
bottomNavigationBar: Container(
height: screenHeight * 0.09, // Responsive height
height: screenHeight * 0.085, // Responsive height
padding: EdgeInsets.symmetric(
horizontal: screenWidth * 0.04,
horizontal: screenWidth * 0.048,
vertical: screenHeight * 0.012,
),
width: double.infinity,
......@@ -147,8 +148,9 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
child: Text(
"View Bill",
style: TextStyle(
fontFamily: "Poppins",
fontSize: isSmallScreen ? 13 : 14,
fontWeight: FontWeight.w400,
fontWeight: FontWeight.w500,
fontStyle: FontStyle.normal,
),
),
......@@ -492,15 +494,11 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
SizedBox(height: screenHeight * 0.015),
// Table-like layout for dates and price
Table(
columnWidths: const {
0: FlexColumnWidth(2),
1: FlexColumnWidth(1),
},
children: [
TableRow(
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TableCell(
Expanded(
flex: 8,
child: Text(
product.dispatchDate != null
? "Dispatched On ${product.dispatchDate!}"
......@@ -513,9 +511,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
),
),
),
TableCell(
child: Align(
alignment: Alignment.centerRight,
Expanded(
child: Text(
"Plan",
style: TextStyle(
......@@ -526,12 +522,13 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
),
),
),
),
],
),
TableRow(
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
TableCell(
Expanded(
flex: 7,
child: Text(
product.receivedDate != null
? "Received On ${product.receivedDate!}"
......@@ -544,12 +541,9 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
),
),
),
TableCell(
child: Align(
alignment: Alignment.centerRight,
child: Text(
Text(
product.totalPrice != null
? "${product.totalPrice!}${product.per ?? 'mo'}"
? "${product.totalPrice!}${product.per ?? 'mo'}"
: 'Price not available',
style: TextStyle(
fontSize: isSmallScreen ? 12 : 14,
......@@ -559,10 +553,6 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
color: Colors.black87,
),
),
),
),
],
),
],
),
],
......@@ -663,7 +653,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
showModalBottomSheet(
context: context,
backgroundColor: Colors.white,
isScrollControlled: true, // Add this to allow scrolling
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
......@@ -679,7 +669,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
vertical: screenHeight * 0.016,
),
constraints: BoxConstraints(
maxHeight: screenHeight * 0.7, // Limit maximum height
maxHeight: screenHeight * 0.7,
),
child: Column(
mainAxisSize: MainAxisSize.min,
......@@ -706,7 +696,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
),
),
SizedBox(height: screenHeight * 0.025),
Expanded( // Wrap GridView with Expanded
Expanded(
child: GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
......@@ -714,7 +704,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
crossAxisCount: 3,
crossAxisSpacing: screenWidth * 0.03,
mainAxisSpacing: screenWidth * 0.03,
childAspectRatio: 0.85, // Reduced from 0.99 to prevent overflow
childAspectRatio: 0.85,
),
itemCount: createNewTickets.length,
itemBuilder: (context, index) {
......@@ -731,6 +721,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
icon: icon,
color: color,
screenWidth: screenWidth,
bottomSheetContext: context, // Pass bottom sheet context
);
},
),
......@@ -751,13 +742,19 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
required String icon,
required Color color,
required double screenWidth,
required BuildContext bottomSheetContext, // Add this parameter
}) {
final isSmallScreen = screenWidth < 360;
final iconSize = screenWidth * 0.20; // Slightly reduced
final imageSize = screenWidth * 0.09; // Slightly reduced
final iconSize = screenWidth * 0.20;
final imageSize = screenWidth * 0.09;
return GestureDetector(
onTap: () {
// Close the bottom sheet first
Navigator.pop(bottomSheetContext);
// Then navigate to HelpTicketScreen after a small delay for smooth transition
Future.delayed(Duration(milliseconds: 300), () {
Navigator.push(
context,
MaterialPageRoute(
......@@ -769,6 +766,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
),
),
);
});
},
child: Container(
padding: EdgeInsets.symmetric(
......@@ -776,7 +774,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
vertical: screenWidth * 0.002
),
child: Column(
mainAxisSize: MainAxisSize.min, // Use min to prevent overflow
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Icon container
......@@ -798,9 +796,9 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
),
),
),
SizedBox(height: screenWidth * 0.015), // Reduced spacing
SizedBox(height: screenWidth * 0.015),
// Title
SizedBox( //
SizedBox(
width: iconSize,
child: Text(
title,
......@@ -808,7 +806,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
style: TextStyle(
color: AppColors.nearDarkText,
fontFamily: "Poppins",
fontSize: isSmallScreen ? 11 : 13, // Slightly smaller font
fontSize: isSmallScreen ? 11 : 13,
fontStyle: FontStyle.normal,
fontWeight: FontWeight.w400,
),
......@@ -816,7 +814,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
overflow: TextOverflow.ellipsis,
),
),
SizedBox(height: screenWidth * 0.005), // Reduced spacing
SizedBox(height: screenWidth * 0.005),
],
),
),
......
......@@ -388,7 +388,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
style: TextStyle(
fontSize: 16,
fontFamily: "Poppins",
fontWeight: FontWeight.w400,
fontWeight: FontWeight.w500,
color: AppColors.normalText,
),
),
......@@ -428,7 +428,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
style: TextStyle(
fontSize: 18,
fontFamily: "Poppins",
fontWeight: FontWeight.w500,
fontWeight: FontWeight.w600,
color: AppColors.normalText,
),
),
......@@ -536,13 +536,13 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
const SizedBox(height: 6),
Text(title,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.w400, fontFamily: "Poppins", color: Colors.black87)),
style: TextStyle(
fontSize: 14, fontWeight: FontWeight.w600, fontFamily: "Poppins", color: Colors.black87)),
const SizedBox(height: 2),
Text(value,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.w400, fontFamily: "Poppins", color: Colors.black54)),
style: TextStyle(
fontSize: 14, fontWeight: FontWeight.w400, fontFamily: "Poppins", color: AppColors.subtitleText)),
],
);
}
......@@ -551,12 +551,12 @@ class _ProfileScreenState extends State<ProfileScreen> {
return Column(
children: [
Text(title,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.w400, fontFamily: "Poppins", color: Colors.black87)),
style: TextStyle(
fontSize: 14, fontWeight: FontWeight.w600, fontFamily: "Poppins", color: Colors.black87)),
const SizedBox(height: 4),
Text(value,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.w400, fontFamily: "Poppins", color: Colors.black54)),
style: TextStyle(
fontSize: 14, fontWeight: FontWeight.w400, fontFamily: "Poppins", color: AppColors.subtitleText)),
],
);
}
......
......@@ -61,6 +61,22 @@ class _BillPendingToastState extends State<BillPendingToast> {
: Column(
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
InkResponse(
onTap: () => Navigator.pop(context),
child: CircleAvatar(
radius: 16,
backgroundColor: Colors.black12,
child: Icon(
Icons.close,
size: 16,
),
),
)
],
),
// 🔴 Red Pending Icon
Container(
height: 60,
......@@ -209,17 +225,18 @@ class _BillPendingToastState extends State<BillPendingToast> {
),
)
: const Icon(Icons.download_rounded,
color: Colors.black),
color: Colors.white),
label: const Text(
"Download",
style: TextStyle(
fontSize: 14,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.black,
color: Colors.white,
),
),
style: OutlinedButton.styleFrom(
backgroundColor: Colors.blue,
side: const BorderSide(color: Colors.black26),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
......@@ -229,27 +246,27 @@ class _BillPendingToastState extends State<BillPendingToast> {
),
),
const SizedBox(width: 12),
Expanded(
child: ElevatedButton(
onPressed: widget.onPayNow,
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.amountText,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
padding: const EdgeInsets.symmetric(vertical: 14),
),
child: const Text(
"Pay Now",
style: TextStyle(
fontSize: 15,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
),
// Expanded(
// child: ElevatedButton(
// onPressed: widget.onPayNow,
// style: ElevatedButton.styleFrom(
// backgroundColor: AppColors.amountText,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(50),
// ),
// padding: const EdgeInsets.symmetric(vertical: 14),
// ),
// child: const Text(
// "Pay Now",
// style: TextStyle(
// fontSize: 15,
// fontFamily: "Poppins",
// fontWeight: FontWeight.w600,
// color: Colors.white,
// ),
// ),
// ),
// ),
],
),
],
......
......@@ -73,7 +73,23 @@ class _BillStatusToastState extends State<BillStatusToast> {
: Column(
mainAxisSize: MainAxisSize.min,
children: [
// ✅ Success Tick
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
InkResponse(
onTap: () => Navigator.pop(context),
child: CircleAvatar(
radius: 16,
backgroundColor: Colors.black12,
child: Icon(
Icons.close,
size: 16,
),
),
)
],
),
// Success Tick
Container(
height: 60,
width: 60,
......
......@@ -94,7 +94,7 @@ class _LoginScreenState extends State<LoginScreen> {
// Fixed background image
Positioned.fill(
child: Image.asset(
'assets/images/background.jpg',
'assets/images/login_background.png',
fit: BoxFit.cover,
),
),
......@@ -168,10 +168,10 @@ class _LoginScreenState extends State<LoginScreen> {
keyboardType: TextInputType.phone,
onChanged: _validatePhone,
maxLength: 10,
style: const TextStyle(color: Colors.black),
style: const TextStyle(color: Colors.black, fontFamily: "Poppins",fontSize: 14),
decoration: InputDecoration(
hintText: "Enter Mobile No.",
hintStyle: const TextStyle(color: Colors.grey,fontFamily: "Poppins",),
hintStyle: const TextStyle(color: Colors.grey,fontFamily: "Poppins", fontSize: 14),
filled: true,
fillColor: Colors.white,
counterText: "", // Remove character counter
......
......@@ -97,9 +97,15 @@ class _OtpScreenState extends State<OtpScreen> {
// Navigate to dashboard
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (_) => DashboardScreen(
accId: rentalProvider.otpResponse!.accId!,
sessionId: rentalProvider.otpResponse!.sessionId!,)
PageRouteBuilder(
pageBuilder: (_, __, ___) => DashboardScreen(accId: rentalProvider.otpResponse!.accId!, sessionId: rentalProvider.otpResponse!.sessionId.toString(),),
transitionsBuilder: (_, animation, __, child) {
return FadeTransition(
opacity: animation,
child: child,
);
},
transitionDuration: const Duration(milliseconds: 800),
),
);
} else {
......@@ -243,7 +249,7 @@ class _OtpScreenState extends State<OtpScreen> {
// Background image
Positioned.fill(
child: Image.asset(
'assets/images/background.jpg',
'assets/images/login_background.png',
fit: BoxFit.cover,
),
),
......
......@@ -99,8 +99,8 @@ class CustomSnackBar {
style: const TextStyle(
color: Colors.white,
fontFamily: "Poppins",
fontWeight: FontWeight.w700,
fontSize: 15,
fontWeight: FontWeight.w500,
fontSize: 14,
letterSpacing: -0.2,
),
),
......@@ -111,7 +111,7 @@ class CustomSnackBar {
style: TextStyle(
fontFamily: "Poppins",
color: Colors.white.withOpacity(0.9),
fontSize: 14,
fontSize: 13,
height: 1.3,
fontWeight: FontWeight.w400,
),
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment