Commits (2)
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,
),
......