Commit 81ba1294 authored by Sai Srinivas's avatar Sai Srinivas
Browse files

Profile and some more changes

parent 97cb09f8
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
......
<svg width="38" height="38" viewBox="0 0 38 38" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M36.3669 9.51123C35.3826 5.88794 31.6143 2.1189 27.9902 1.13452C25.7681 0.580811 22.7915 0.0102539 18.75 0C14.71 0.0102539 11.7334 0.580811 9.51123 1.13452C5.88794 2.1189 2.1189 5.88721 1.13452 9.51123C0.580811 11.7327 0.0102539 14.71 0 18.75C0.0102539 22.7908 0.580811 25.7673 1.13452 27.9895C2.1189 31.6135 5.88794 35.3818 9.51123 36.3662C11.7334 36.9199 14.7114 37.4905 18.7507 37.5C22.7908 37.4905 25.7681 36.9199 27.9902 36.3662C31.6143 35.3818 35.3826 31.6135 36.3669 27.9895C36.9207 25.7673 37.4912 22.7893 37.5007 18.75C37.4912 14.71 36.9207 11.7334 36.3669 9.51123Z" fill="#FFE5E5"/>
<path d="M17.3699 21.9792V29.8271C17.3782 30.1877 17.5272 30.5307 17.7852 30.7828C18.0431 31.0348 18.3895 31.176 18.7501 31.176C19.1108 31.176 19.4571 31.0348 19.7151 30.7828C19.973 30.5307 20.1221 30.1877 20.1304 29.8271V21.9792H17.3699ZM14.3823 11.3115C14.3823 10.9527 14.4887 10.6019 14.6881 10.3035C14.8875 10.0052 15.1709 9.77264 15.5024 9.63534C15.834 9.49805 16.1988 9.46217 16.5507 9.53223C16.9027 9.60229 17.2259 9.77515 17.4796 10.0289C17.7333 10.2827 17.9061 10.6061 17.976 10.958C18.0459 11.31 18.0099 11.6748 17.8724 12.0063C17.735 12.3378 17.5024 12.6211 17.2039 12.8203C16.9055 13.0196 16.5546 13.1259 16.1958 13.1257C15.7148 13.1255 15.2535 12.9343 14.9134 12.5941C14.5734 12.2539 14.3823 11.7926 14.3823 11.3115Z" fill="url(#paint0_linear_1079_367)"/>
<path d="M18.75 22.0994C23.1146 22.0994 26.6528 18.5611 26.6528 14.1965C26.6528 9.83192 23.1146 6.2937 18.75 6.2937C14.3854 6.2937 10.8472 9.83192 10.8472 14.1965C10.8472 18.5611 14.3854 22.0994 18.75 22.0994Z" fill="url(#paint1_linear_1079_367)"/>
<path d="M14.3823 11.3115C14.3823 10.9527 14.4887 10.6019 14.6881 10.3035C14.8875 10.0052 15.1709 9.77264 15.5024 9.63534C15.834 9.49805 16.1988 9.46217 16.5507 9.53223C16.9027 9.60229 17.2259 9.77515 17.4796 10.0289C17.7333 10.2827 17.9061 10.6061 17.976 10.958C18.0459 11.31 18.0099 11.6748 17.8724 12.0063C17.735 12.3378 17.5024 12.6211 17.2039 12.8203C16.9055 13.0196 16.5546 13.1259 16.1958 13.1257C15.7148 13.1255 15.2535 12.9343 14.9134 12.5941C14.5734 12.2539 14.3823 11.7926 14.3823 11.3115Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_1079_367" x1="25.1248" y1="27.9148" x2="15.0576" y2="17.8469" gradientUnits="userSpaceOnUse">
<stop stop-color="#34344F"/>
<stop offset="0.54" stop-color="#353551"/>
<stop offset="1" stop-color="#666684"/>
</linearGradient>
<linearGradient id="paint1_linear_1079_367" x1="24.3384" y1="19.7849" x2="13.1624" y2="8.60816" gradientUnits="userSpaceOnUse">
<stop stop-color="#EF3739"/>
<stop offset="0.54" stop-color="#EF3739"/>
<stop offset="1" stop-color="#FF8C8B"/>
</linearGradient>
</defs>
</svg>
<svg width="25" height="21" viewBox="0 0 25 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.3713 5.02075C23.9033 2.90552 21.8525 0.968262 19.7322 0.552979C18.4871 0.304688 15.1128 0 12.7346 0C12.637 0 12.5425 0 12.4512 0C12.3599 0 12.2654 0 12.1677 0C9.79028 0 6.41235 0.304688 5.17017 0.552979C3.0498 0.9646 0.999023 2.90186 0.531006 5.02075C0.263672 6.30542 0 8.05225 0 10.437C0 12.8218 0.266601 14.5686 0.533203 15.8533C1.00122 17.9685 3.052 19.9058 5.17236 20.3174C6.41748 20.5657 9.79248 20.8704 12.1699 20.8704C12.2676 20.8704 12.3621 20.8704 12.4534 20.8704C12.5447 20.8704 12.6392 20.8704 12.7368 20.8704C15.1143 20.8704 18.4922 20.5657 19.7344 20.3174C21.8547 19.9058 23.9055 17.9685 24.3735 15.8533C24.6387 14.5686 24.9023 12.8218 24.9023 10.437C24.9023 8.05225 24.6379 6.30542 24.3713 5.02075Z" fill="url(#paint0_linear_1079_362)"/>
<path d="M24.3713 5.02075C23.9033 2.90552 21.8525 0.968262 19.7322 0.552979C18.4871 0.304688 15.1128 0 12.7354 0C12.6387 0 12.5442 0 12.4512 0C12.3582 0 12.2637 0 12.1677 0C9.79028 0 6.41235 0.304688 5.17017 0.552979C3.05054 0.9646 1.00049 2.90112 0.531006 5.01562L0.512695 5.10571L10.3821 11.2749C11.0061 11.6622 11.7259 11.8674 12.4603 11.8674C13.1947 11.8674 13.9146 11.6622 14.5386 11.2749L24.3896 5.10645L24.3713 5.02075Z" fill="url(#paint1_linear_1079_362)"/>
<defs>
<linearGradient id="paint0_linear_1079_362" x1="21.7061" y1="19.6919" x2="3.19629" y2="1.18213" gradientUnits="userSpaceOnUse">
<stop stop-color="#1EB4EB"/>
<stop offset="0.54" stop-color="#1EB4EB"/>
<stop offset="1" stop-color="#92F4FE"/>
</linearGradient>
<linearGradient id="paint1_linear_1079_362" x1="18.731" y1="10.7651" x2="6.17212" y2="-1.7937" gradientUnits="userSpaceOnUse">
<stop stop-color="#5FD9F9"/>
<stop offset="0.52" stop-color="#5BD7F8"/>
<stop offset="1" stop-color="#B0F0FF"/>
</linearGradient>
</defs>
</svg>
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M24.2449 17.7605C24.2573 17.6726 19.5713 13.8442 18.0874 14.2192C17.4019 14.373 16.98 14.866 16.1392 15.8474C16.0549 15.9456 15.8989 16.1279 15.7327 16.3169C15.6414 16.4211 15.5215 16.4961 15.3879 16.5327C15.2543 16.5693 15.1129 16.5658 14.9812 16.5227C14.6516 16.4143 14.3277 16.2891 14.0108 16.1477C11.6624 15.1267 9.78878 13.2528 8.76808 10.9043C8.62636 10.5878 8.50119 10.2641 8.39308 9.93457C8.34992 9.80288 8.34634 9.66142 8.3828 9.52771C8.41925 9.39401 8.49413 9.27394 8.59815 9.18237C8.78785 9.01538 8.97169 8.85791 9.07276 8.77149C10.0505 7.93506 10.5449 7.51245 10.6973 6.82617C11.0635 5.34961 7.24391 0.658447 7.15601 0.669434C6.7898 0.244629 6.22071 0.00439453 5.61793 0C4.10328 0.0783692 0.0654383 5.3335 0.00171762 6.2959C-0.00633902 6.33106 -0.0136634 7.6875 0.668221 10.0027C1.37135 12.2966 2.76368 15.5479 6.02223 18.8987C9.37013 22.1536 12.6192 23.5444 14.9116 24.2454C17.2254 24.9265 18.5825 24.9192 18.6177 24.9111C19.5801 24.8438 24.8359 20.8037 24.9165 19.2927C24.9041 18.6929 24.6668 18.1245 24.2449 17.7605Z" fill="url(#paint0_linear_1066_355)"/>
<defs>
<linearGradient id="paint0_linear_1066_355" x1="20.8347" y1="24.0286" x2="-0.247304" y2="2.94727" gradientUnits="userSpaceOnUse">
<stop stop-color="#13B601"/>
<stop offset="0.57" stop-color="#13B601"/>
<stop offset="1" stop-color="#CBF4B4"/>
</linearGradient>
</defs>
</svg>
......@@ -2,9 +2,10 @@ class DashboardResponse {
String? error;
String? mobNum;
String? raname;
int? balanceAmount;
String? balanceAmount;
String? message;
List<Orders>? orders;
int? sessionExists;
DashboardResponse(
{this.error,
......@@ -12,7 +13,8 @@ class DashboardResponse {
this.raname,
this.balanceAmount,
this.message,
this.orders});
this.orders,
this.sessionExists});
DashboardResponse.fromJson(Map<String, dynamic> json) {
error = json['error'];
......@@ -26,6 +28,7 @@ class DashboardResponse {
orders!.add(new Orders.fromJson(v));
});
}
sessionExists = json['session_exists'];
}
Map<String, dynamic> toJson() {
......@@ -38,6 +41,7 @@ class DashboardResponse {
if (this.orders != null) {
data['orders'] = this.orders!.map((v) => v.toJson()).toList();
}
data['session_exists'] = this.sessionExists;
return data;
}
}
......
class ProfileResponse {
String? error;
String? mobNum;
String? name;
String? mail;
String? state;
String? subLocality;
String? address;
String? message;
int? sessionExists;
String? profileUrl;
ProfileResponse(
{this.error,
this.mobNum,
this.name,
this.mail,
this.state,
this.subLocality,
this.address,
this.message,
this.sessionExists,
this.profileUrl
});
ProfileResponse.fromJson(Map<String, dynamic> json) {
error = json['error'];
mobNum = json['mob_num'];
name = json['name'];
mail = json['mail'];
state = json['state'];
subLocality = json['sub_locality'];
address = json['address'];
message = json['message'];
sessionExists = json['session_exists'];
profileUrl = json['profile_url'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['error'] = this.error;
data['mob_num'] = this.mobNum;
data['name'] = this.name;
data['mail'] = this.mail;
data['state'] = this.state;
data['sub_locality'] = this.subLocality;
data['address'] = this.address;
data['message'] = this.message;
data['session_exists'] = this.sessionExists;
data['profile_url'] = this.profileUrl;
return data;
}
}
......@@ -3,9 +3,11 @@ import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:gen_rentals/Services/api_calling.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:gen_rentals/Utility/CustomSnackbar.dart';
import 'dart:io';
import '../Models/CommonResponse.dart';
import '../Models/ProfileResponse.dart';
class RentalProvider extends ChangeNotifier {
FetchMobileResponse? _response;
......@@ -69,7 +71,7 @@ class RentalProvider extends ChangeNotifier {
"product": androidInfo.product ?? "",
"manufacturer": androidInfo.manufacturer ?? "",
"brand": androidInfo.brand ?? "",
"user": "",
"user": androidInfo.data['user'].toString().trim(),
"display": androidInfo.display ?? "",
"hardware": androidInfo.hardware ?? "",
"board": androidInfo.board ?? "",
......@@ -81,9 +83,11 @@ class RentalProvider extends ChangeNotifier {
"cpuAbi2": androidInfo.supportedAbis.length > 1 ? androidInfo.supportedAbis[1] : "",
"fingerprint": androidInfo.fingerprint ?? "",
};
}else{
return {};
}
return {};
}
bool _isLoggingOut = false;
......@@ -103,48 +107,80 @@ class RentalProvider extends ChangeNotifier {
BuildContext context,
String accId,
String sessionId,
Map<String, String> deviceDetails,
) async {
try {
_setLoggingOut(true);
log("📡 Calling Logout API...");
final response =
await ApiCalling.logoutApi(accId, sessionId, deviceDetails);
await ApiCalling.logoutApi(accId, sessionId);
_logoutResponse = response;
_setLoggingOut(false);
if (response != null && response.error == 0) {
log("✅ Logout successful: ${response.message}");
// Clear user data if needed
// await SharedPrefHelper.clearAll();
// Show toast/snackbar
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(response.message ?? "Logout successful"),
backgroundColor: Colors.green,
),
CustomSnackBar.showSuccess(
context: context,
message: response.message ?? "Logout successful"
);
// Navigate to login screen
// Navigator.pushNamedAndRemoveUntil(context, '/login', (_) => false);
} else {
log("❌ Logout failed: ${response?.message}");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(response?.message ?? "Logout failed"),
backgroundColor: Colors.red,
),
CustomSnackBar.showError(
context: context,
message: response?.message ?? "Logout failed"
);
}
} catch (e) {
_setLoggingOut(false);
log("🚨 Logout Error: $e");
CustomSnackBar.showError(
context: context,
message: "Something went wrong: $e"
);
}
}
ProfileResponse? _profileData;
ProfileResponse? get profileData => _profileData;
/// Set loading state
void setLoading(bool value) {
_isLoading = value;
notifyListeners();
}
/// Fetch Profile Data
Future<void> fetchProfile(BuildContext context, String accId, String sessionId) async {
setLoading(true);
try {
final response = await ApiCalling.fetchProfileApi(accId, sessionId);
if (response != null && response.error == "0") {
_profileData = response;
notifyListeners();
} else {
debugPrint("⚠️ Profile fetch failed: ${response?.message}");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(response?.message ?? "Failed to fetch profile")),
);
}
} catch (e) {
debugPrint("❌ Profile fetch error: $e");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text("Something went wrong: $e")),
const SnackBar(content: Text("Error fetching profile")),
);
} finally {
setLoading(false);
}
}
......@@ -181,3 +217,6 @@ class FetchMobileResponse {
}
......@@ -28,7 +28,7 @@ class _BillDetailScreenState extends State<BillDetailScreen> {
super.initState();
Future.microtask(() {
final provider = Provider.of<BillProvider>(context, listen: false);
provider.fetchBillDetails(widget.sessionId, widget.accId, "15068");
provider.fetchBillDetails(widget.sessionId, widget.accId, widget.billId);
});
}
......@@ -83,13 +83,13 @@ class _BillDetailScreenState extends State<BillDetailScreen> {
],
),
),
backgroundColor: AppColors.backgroundRegular,
backgroundColor: Colors.white,
body: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// Green Tick Circle
// Green Tick Circle
Container(
height: 70,
width: 70,
......@@ -197,53 +197,57 @@ class _BillDetailScreenState extends State<BillDetailScreen> {
const SizedBox(height: 40),
// Download Button
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: provider.isDownloading
? null
: () {
provider.downloadBill(
context,
widget.sessionId,
widget.billId,
widget.accId,
);
},
icon: provider.isDownloading
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
),
)
: const Icon(Icons.download, color: Colors.white),
label: Text(
provider.isDownloading
? "Downloading..."
: "Download Receipt",
style: const TextStyle(
fontSize: 16,
fontFamily: "Plus Jakarta Sans",
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.amountText,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
padding: const EdgeInsets.symmetric(vertical: 14),
),
),
),
],
),
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 14),
child: SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: provider.isDownloading
? null
: () {
provider.downloadBill(
context,
widget.sessionId,
widget.billId,
widget.accId,
);
},
icon: provider.isDownloading
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
),
)
: const Icon(Icons.download, color: Colors.white),
label: Text(
provider.isDownloading
? "Downloading..."
: "Download Receipt",
style: const TextStyle(
fontSize: 16,
fontFamily: "Plus Jakarta Sans",
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.amountText,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
padding: const EdgeInsets.symmetric(vertical: 14),
),
),
),
),
),
);
},
......
This diff is collapsed.
......@@ -63,90 +63,102 @@ class _HelpScreenState extends State<HelpScreen> {
Widget build(BuildContext context) {
return SafeArea(
top: false,
child: Scaffold(
backgroundColor: AppColors.backgroundRegular,
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
title: Row(
children: [
InkResponse(
onTap: () => Navigator.pop(context, true),
child: SvgPicture.asset(
"assets/svg/continue_left_ic.svg",
height: 30,
child: RefreshIndicator.adaptive(
color: AppColors.amountText,
onRefresh: () async {
await Future.delayed(const Duration(milliseconds: 600));
final provider = Provider.of<HelpAndEnquiryProvider>(context, listen: false);
await provider.fetchTicketList(
sessionId: widget.sessionId,
accId: widget.accId,
);
},
child: Scaffold(
backgroundColor: AppColors.backgroundRegular,
appBar: AppBar(
automaticallyImplyLeading: false,
backgroundColor: Colors.white,
title: Row(
children: [
InkResponse(
onTap: () => Navigator.pop(context, true),
child: SvgPicture.asset(
"assets/svg/continue_left_ic.svg",
height: 30,
),
),
),
const SizedBox(width: 10),
const Text(
"Help?",
style: TextStyle(
fontSize: 16,
fontFamily: "Plus Jakarta Sans",
fontWeight: FontWeight.w400,
color: Colors.black87,
const SizedBox(width: 10),
const Text(
"Help?",
style: TextStyle(
fontSize: 16,
fontFamily: "Plus Jakarta Sans",
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
),
],
],
),
),
),
// ✅ Provider Consumer used here
body: Consumer<HelpAndEnquiryProvider>(
builder: (context, provider, _) {
if (provider.isLoading) {
return const Center(child: CircularProgressIndicator());
}
// ✅ Provider Consumer used here
body: Consumer<HelpAndEnquiryProvider>(
builder: (context, provider, _) {
if (provider.isLoading) {
return const Center(child: CircularProgressIndicator());
}
if (provider.errorMessage != null) {
return Center(
child: Text(provider.errorMessage!,
style: const TextStyle(color: Colors.red)),
);
}
if (provider.errorMessage != null) {
return Center(
child: Text(provider.errorMessage!,
style: const TextStyle(color: Colors.red)),
);
}
final ticketData = provider.ticketListResponse?.tickets;
final processingTickets = ticketData?.inProgress ?? [];
final closedTickets = ticketData?.closed ?? [];
final ticketData = provider.ticketListResponse?.tickets;
final processingTickets = ticketData?.inProgress ?? [];
final closedTickets = ticketData?.closed ?? [];
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Create New Ticket Section
SectionHeading(
title: 'Create New Ticket',
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
),
const SizedBox(height: 12),
_buildCreateNewTicketSection(),
const SizedBox(height: 12),
return SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Create New Ticket Section
SectionHeading(
title: 'Create New Ticket',
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
),
const SizedBox(height: 12),
_buildCreateNewTicketSection(),
const SizedBox(height: 12),
// Processing Tickets Section
SectionHeading(
title: 'Processing Tickets',
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
),
const SizedBox(height: 2),
_buildProcessingTicketsSection(processingTickets),
const SizedBox(height: 10),
// Processing Tickets Section
SectionHeading(
title: 'Processing Tickets',
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
),
const SizedBox(height: 2),
_buildProcessingTicketsSection(processingTickets),
const SizedBox(height: 10),
// Closed Tickets Section
SectionHeading(
title: 'Closed Tickets',
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
),
// Closed Tickets Section
SectionHeading(
title: 'Closed Tickets',
textStyle: TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
padding: EdgeInsets.symmetric(horizontal: 2, vertical: 4),
),
const SizedBox(height: 2),
_buildClosedTicketsSection(closedTickets),
],
),
);
},
const SizedBox(height: 2),
_buildClosedTicketsSection(closedTickets),
],
),
);
},
),
),
),
);
......
......@@ -101,50 +101,61 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
),
),
backgroundColor: AppColors.backgroundRegular,
body: _buildBody(provider, screenHeight, bottomPadding),
bottomNavigationBar: Container(
height: 80,
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
width: double.infinity,
child: ElevatedButton(
onPressed: () {
final order = provider.orderDetails!;
Navigator.push(
context,
MaterialPageRoute(builder: (context) => BillDetailListScreen(
sessionId: widget.sessionId,
orderId: order.orderid.toString(),
accId: widget.accId,
))
body: RefreshIndicator.adaptive(
color: AppColors.subtitleText,
onRefresh: () async {
final provider = Provider.of<SubscribeOrderDetailsProvider>(context, listen: false);
await provider.fetchSubscribeOrderDetails(
widget.sessionId,
widget.orderId,
widget.accId,
);
// Handle view bill action
FocusScope.of(context).unfocus();
},
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.buttonColor,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(28),
child: _buildBody(provider, screenHeight, bottomPadding),
),
bottomNavigationBar: Container(
height: 80,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
width: double.infinity,
child: ElevatedButton(
onPressed: () {
final order = provider.orderDetails!;
Navigator.push(
context,
MaterialPageRoute(builder: (context) => BillDetailListScreen(
sessionId: widget.sessionId,
orderId: order.orderid.toString(),
accId: widget.accId,
))
);
FocusScope.of(context).unfocus();
},
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.buttonColor,
foregroundColor: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(28),
),
elevation: 0,
),
elevation: 0,
),
child: const Text(
"View Bill",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.normal,
child: const Text(
"View Bill",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
fontStyle: FontStyle.normal,
),
),
),
),
),
),
);
},
);
}
Widget _buildBody(SubscribeOrderDetailsProvider provider, double screenHeight, double bottomPadding) {
if (provider.isLoading) {
return const Center(
......@@ -248,7 +259,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
color: AppColors.amountText,
),
),
SizedBox(height: 4,),
Text(
"${order.fromDate} - ${order.toDate ?? 'Duration unavailable'}",
......@@ -256,7 +267,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
fontSize: 12,
fontFamily: "Poppins",
fontWeight: FontWeight.w400,
color: AppColors.subtitleText,
color: AppColors.normalText,
),
),
],
......@@ -294,7 +305,7 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
fontSize: 12,
fontFamily: "Poppins",
fontWeight: FontWeight.w400,
color: Colors.black87,
color: AppColors.normalText,
),
),
const SizedBox(height: 8),
......@@ -302,9 +313,9 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
Text(
order.accName ?? ' A/c not available',
style: TextStyle(
fontSize: 12,
fontSize: 14,
fontFamily: "Poppins",
fontWeight: FontWeight.w400,
fontWeight: FontWeight.w500,
color: Colors.black87,
),
),
......@@ -384,10 +395,10 @@ class _ProductsDetailScreenState extends State<ProductsDetailScreen> {
// Divider
const Divider(
color: Color(0xFFE5E5E5),
thickness: 1,
),
// const Divider(
// color: Color(0xFFE5E5E5),
// thickness: 1,
// ),
const SizedBox(height: 16),
// Help section
......
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gen_rentals/Screens/HelpScreens/OrderHelpScreen.dart';
import 'package:gen_rentals/Screens/HelpScreens/TicketChatScreen.dart';
import 'package:gen_rentals/Utility/Reusablewidgets.dart';
import 'package:provider/provider.dart';
import '../../Notifier/HelpAndEnquiryProvider.dart';
import '../../Utility/AppColors.dart';
import 'package:provider/provider.dart';
import '../Notifier/RentalContactProvider .dart';
import '../Utility/SharedpreferencesService.dart';
import 'authScreen/LoginScreen.dart';
class ProfileScreen extends StatefulWidget {
final String sessionId;
final String accId;
ProfileScreen({
const ProfileScreen({
super.key,
required this.sessionId,
required this.accId,
......@@ -31,13 +26,10 @@ class _ProfileScreenState extends State<ProfileScreen> {
void initState() {
super.initState();
/// ✅ Fetch ticket list on screen load
// Fetch profile data when screen loads
Future.microtask(() async {
final provider = Provider.of<HelpAndEnquiryProvider>(context, listen: false);
await provider.fetchTicketList(
sessionId: widget.sessionId,
accId: widget.accId,
);
final profileProvider = Provider.of<RentalProvider>(context, listen: false);
await profileProvider.fetchProfile(context,widget.accId, widget.sessionId);
});
}
......@@ -238,7 +230,6 @@ class _ProfileScreenState extends State<ProfileScreen> {
context,
widget.accId,
widget.sessionId,
deviceDetails,
);
// Step 5: Clear SharedPreferences
......@@ -319,37 +310,27 @@ class _ProfileScreenState extends State<ProfileScreen> {
}
}
@override
Widget build(BuildContext context) {
double screenWidth = MediaQuery.of(context).size.width;
double screenHeight = MediaQuery.of(context).size.height;
double bottomPadding = MediaQuery.of(context).padding.bottom;
final profileProvider = Provider.of<RentalProvider>(context);
final profile = profileProvider.profileData;
return SafeArea(
top: false,
child: Scaffold(
body: Container(
body: profileProvider.isLoading
? const Center(child: CircularProgressIndicator())
: Container(
color: const Color(0xFFF3F3F3),
height: screenHeight,
height: MediaQuery.of(context).size.height,
child: SingleChildScrollView(
child: Column(
children: [
// Top background image section
Stack(
children: [
// Background image
Container(
width: double.infinity,
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [
Colors.white54,
Color(0xFFF3F3F3),
],
),
),
child: Image.asset(
'assets/images/sky_blue_bg.jpg',
width: double.infinity,
......@@ -358,11 +339,9 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
),
// Content overlay
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Header with profile
Container(
width: double.infinity,
height: 400,
......@@ -387,7 +366,6 @@ class _ProfileScreenState extends State<ProfileScreen> {
mainAxisAlignment: MainAxisAlignment.start,
children: [
const SizedBox(width: 20),
// Profile icon
InkResponse(
onTap: () {
Navigator.pop(context);
......@@ -395,16 +373,14 @@ class _ProfileScreenState extends State<ProfileScreen> {
child: Container(
width: 32,
height: 32,
decoration: BoxDecoration(
color: Colors.transparent,
),
color: Colors.transparent,
child: SvgPicture.asset(
"assets/svg/continue_left_ic.svg",
fit: BoxFit.contain,
),
),
),
SizedBox(width: 5,),
const SizedBox(width: 5),
Text(
"Profile",
style: TextStyle(
......@@ -414,10 +390,10 @@ class _ProfileScreenState extends State<ProfileScreen> {
color: AppColors.normalText,
),
),
],
),
SizedBox(height: 120,),
const SizedBox(height: 120),
// ✅ Profile image
Container(
height: 140,
width: 140,
......@@ -426,23 +402,19 @@ class _ProfileScreenState extends State<ProfileScreen> {
shape: BoxShape.circle,
),
clipBehavior: Clip.antiAlias,
child: (widget.accId.isNotEmpty)
child: (profile?.profileUrl?.isNotEmpty ?? false)
? Image.network(
widget.accId,
// You can replace mail with image URL field if you have one
profile!.profileUrl!,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return const Icon(Icons.person, color: Color(0xFF2d2d2d), size: 100,);
},
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return const Center(
child: CircularProgressIndicator(strokeWidth: 2));
},
errorBuilder: (context, error, stackTrace) =>
const Icon(Icons.person, color: Color(0xFF2d2d2d), size: 100),
)
: CircleAvatar(
radius: 80,
backgroundColor: Colors.blue.shade100,
backgroundColor: Color(0xFFE0F4FF),
child: SvgPicture.asset(
height: 80,
"assets/svg/person_ic.svg",
fit: BoxFit.contain,
),
......@@ -450,21 +422,20 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
const SizedBox(height: 10),
Text(
"Blink Commerce PVT. LTD - TN",
profile?.name ?? "User Name",
style: TextStyle(
fontSize: 16,
fontSize: 18,
fontFamily: "Poppins",
fontWeight: FontWeight.w400,
fontWeight: FontWeight.w500,
color: AppColors.normalText,
),
),
const SizedBox(height: 10),
],
),
),
// Main content section
// Main info section
Container(
margin: const EdgeInsets.all(14),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 20),
......@@ -475,73 +446,39 @@ class _ProfileScreenState extends State<ProfileScreen> {
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// 📞 Phone
_infoItem(
iconPath: "assets/svg/phone_ic.svg",
title: "Phone No.",
value: "+91 9639919XX",
value: profile?.mobNum ?? "N/A",
iconBgColor: const Color(0xFFDFF6E3),
),
const SizedBox(height: 16),
// 📧 Email
_infoItem(
iconPath: "assets/svg/email_ic.svg",
iconPath: "assets/svg/message_ic.svg",
title: "Email ID",
value: "xyz@gmail.com",
value: profile?.mail ?? "N/A",
iconBgColor: const Color(0xFFDDEEFF),
),
const SizedBox(height: 16),
// 📍 Address
_infoItem(
iconPath: "assets/svg/location_ic.svg", title: "Address",
value: "No.1/398 O.M. Road, Navallur, Chennai - 600130",
iconPath: "assets/svg/lolipop_ic.svg",
title: "Address",
value: profile?.address ?? "N/A",
iconBgColor: const Color(0xFFFFE9E9),
),
const SizedBox(height: 20),
// 🌏 State / Sub locality
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_twoColumnItem("State", "Tamil Nadu"),
_twoColumnItem("Sub Locality", "Chennai"),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_twoColumnItem("State", profile?.state ?? "N/A"),
_twoColumnItem("Sub Locality", profile?.subLocality ?? "N/A"),
],
),
const SizedBox(height: 30),
// 🚪 Logout Button
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () => onLogout(context),
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.amountText,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
padding: const EdgeInsets.symmetric(vertical: 14),
),
child: const Text(
"Logout",
style: TextStyle(
fontSize: 16,
fontFamily: "Plus Jakarta Sans",
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
),
],
),
)
),
],
),
],
......@@ -550,11 +487,35 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
),
),
bottomNavigationBar: Padding(
padding: const EdgeInsets.all(14),
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () => onLogout(context),
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.amountText,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
padding: const EdgeInsets.symmetric(vertical: 14),
),
child: const Text(
"Logout",
style: TextStyle(
fontSize: 16,
fontFamily: "Plus Jakarta Sans",
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
),
),
),
);
}
Widget _infoItem({
required String iconPath,
required String title,
......@@ -569,33 +530,17 @@ class _ProfileScreenState extends State<ProfileScreen> {
color: iconBgColor,
borderRadius: BorderRadius.circular(14),
),
child: SvgPicture.asset(
iconPath,
height: 28,
width: 28,
),
child: SvgPicture.asset(iconPath, height: 28, width: 28),
),
const SizedBox(height: 6),
Text(
title,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w600,
fontFamily: "Plus Jakarta Sans",
color: Colors.black87,
),
),
Text(title,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.w400, fontFamily: "Plus Jakarta Sans", color: Colors.black87)),
const SizedBox(height: 2),
Text(
value,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w400,
fontFamily: "Plus Jakarta Sans",
color: Colors.black54,
),
),
Text(value,
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.w400, fontFamily: "Plus Jakarta Sans", color: Colors.black54)),
],
);
}
......@@ -603,33 +548,14 @@ class _ProfileScreenState extends State<ProfileScreen> {
Widget _twoColumnItem(String title, String value) {
return Column(
children: [
Text(
title,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w600,
fontFamily: "Plus Jakarta Sans",
color: Colors.black87,
),
),
Text(title,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.w400, fontFamily: "Plus Jakarta Sans", color: Colors.black87)),
const SizedBox(height: 4),
Text(
value,
style: const TextStyle(
fontSize: 13,
fontWeight: FontWeight.w400,
fontFamily: "Plus Jakarta Sans",
color: Colors.black54,
),
),
Text(value,
style: const TextStyle(
fontSize: 14, fontWeight: FontWeight.w400, fontFamily: "Plus Jakarta Sans", color: Colors.black54)),
],
);
}
}
......@@ -163,7 +163,8 @@ class _SplashScreenState extends State<SplashScreen> with SingleTickerProviderSt
// Method 1: Using connectivity_plus
final connectivity = Connectivity();
final results = await connectivity.checkConnectivity();
final hasInternet = results.any((result) => result != ConnectivityResult.none);
final hasInternet = results.any((element) => element == ConnectivityResult.wifi || element == ConnectivityResult.mobile);
// Method 2: Fallback with socket test
if (hasInternet) {
......
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../../Utility/AppColors.dart';
import '../../Notifier/TransactionsProvider.dart';
class BillPendingToast extends StatefulWidget {
final String sessionId;
final String accId;
final String ledgerId;
final VoidCallback onPayNow;
const BillPendingToast({
super.key,
required this.sessionId,
required this.accId,
required this.ledgerId,
required this.onPayNow,
});
@override
State<BillPendingToast> createState() => _BillPendingToastState();
}
class _BillPendingToastState extends State<BillPendingToast> {
@override
void initState() {
super.initState();
/// 🔹 Fetch data after one frame (safe after build)
WidgetsBinding.instance.addPostFrameCallback((_) {
final provider = Provider.of<TransactionsProvider>(context, listen: false);
provider.fetchPaymentReceiptDetails(
widget.sessionId,
widget.accId,
widget.ledgerId,
);
});
}
@override
Widget build(BuildContext context) {
final provider = Provider.of<TransactionsProvider>(context);
final data = provider.receiptDetails;
return Dialog(
insetPadding: const EdgeInsets.symmetric(horizontal: 24),
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
child: Container(
width: 360,
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.white,
),
child: provider.isLoading
? const SizedBox(
height: 200,
child: Center(child: CircularProgressIndicator()))
: Column(
mainAxisSize: MainAxisSize.min,
children: [
// 🔴 Red Pending Icon
Container(
height: 60,
width: 60,
decoration: const BoxDecoration(
color: Color(0xFFFFEBEB),
shape: BoxShape.circle,
),
child: const Icon(
Icons.access_time_filled,
color: Colors.redAccent,
size: 40,
),
),
const SizedBox(height: 16),
// Title + Amount
const Text(
"Bill Pending",
style: TextStyle(
fontSize: 18,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
const SizedBox(height: 8),
Text(
"₹${data?.dAmount ?? "--"}",
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.bold,
fontFamily: "Plus Jakarta Sans",
color: Colors.black,
),
),
const SizedBox(height: 12),
const Divider(thickness: 1, color: Color(0xFFE6E6E6)),
const SizedBox(height: 12),
// Payment Details
const Align(
alignment: Alignment.centerLeft,
child: Text(
"Payment Details",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
fontFamily: "Poppins",
color: Colors.black,
),
),
),
const SizedBox(height: 8),
_buildRow("Order ID", "#${data?.id ?? "--"}", Colors.blue),
_buildRow("Date", data?.prDate ?? "--", Colors.black),
const SizedBox(height: 12),
const Divider(thickness: 1, color: Color(0xFFE6E6E6)),
const SizedBox(height: 12),
// Products Section
const Align(
alignment: Alignment.centerLeft,
child: Text(
"Products",
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
fontFamily: "Poppins",
color: Colors.black,
),
),
),
const SizedBox(height: 8),
_buildRow(
data?.narration ?? "Product Item",
"₹${data?.dAmount ?? "--"}",
Colors.black,
),
const SizedBox(height: 12),
const Divider(thickness: 1, color: Color(0xFFE6E6E6)),
const SizedBox(height: 8),
// SubTotal + Gross + Tax + Total
_buildRow(
"Sub Total", "₹${data?.dAmount ?? "--"}", Colors.black),
_buildRow("Gross Amount",
"₹${data?.cAmount ?? "--"}", Colors.black),
_buildRow("SGST", "0", Colors.black),
_buildRow("CGST", "0", Colors.black),
_buildRow("IGST", "0", Colors.black),
const Divider(thickness: 1, color: Color(0xFFE6E6E6)),
const SizedBox(height: 4),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Total",
style: TextStyle(
fontSize: 15,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
Text(
"₹${data?.cAmount ?? "--"}",
style: const TextStyle(
fontSize: 15,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
],
),
const SizedBox(height: 24),
// Buttons Row
Row(
children: [
Expanded(
child: OutlinedButton.icon(
onPressed: provider.isDownloading
? null
: () async {
await provider.downloadPaymentReceipt(
context,
widget.sessionId,
widget.ledgerId,
widget.accId,
);
},
icon: provider.isDownloading
? const SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Colors.black54,
),
)
: const Icon(Icons.download_rounded,
color: Colors.black),
label: const Text(
"Download",
style: TextStyle(
fontSize: 14,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
style: OutlinedButton.styleFrom(
side: const BorderSide(color: Colors.black26),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
padding: const EdgeInsets.symmetric(vertical: 14),
),
),
),
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,
),
),
),
),
],
),
],
),
),
);
}
Widget _buildRow(String title, String value, Color valueColor) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 3),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
title,
style: const TextStyle(
fontSize: 14,
fontFamily: "Poppins",
color: Colors.black54,
),
),
Text(
value,
style: TextStyle(
fontSize: 14,
fontFamily: "Poppins",
fontWeight: FontWeight.w500,
color: valueColor,
),
),
],
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
import 'package:gen_rentals/Utility/AppColors.dart';
enum BillStatusType { paid, pending }
class BillStatusToast extends StatelessWidget {
final BillStatusType type;
final String amount;
final String orderId;
final String date;
final String product;
final String productPrice;
final String total;
final VoidCallback onDownload;
final VoidCallback? onPayNow;
import 'package:gen_rentals/Notifier/TransactionsProvider.dart';
import 'package:provider/provider.dart';
import '../../Utility/AppColors.dart';
import '../../Utility/Reusablewidgets.dart'; // for CustomSnackBar if needed
class BillStatusToast extends StatefulWidget {
final String sessionId;
final String accId;
final String ledgerId;
const BillStatusToast({
super.key,
required this.type,
required this.amount,
required this.orderId,
required this.date,
required this.product,
required this.productPrice,
required this.total,
required this.onDownload,
this.onPayNow,
required this.sessionId,
required this.accId,
required this.ledgerId,
});
@override
State<BillStatusToast> createState() => _BillStatusToastState();
}
class _BillStatusToastState extends State<BillStatusToast> {
@override
void initState() {
super.initState();
// ✅ Automatically fetch data when dialog opens
Future.microtask(() {
final provider =
Provider.of<TransactionsProvider>(context, listen: false);
provider.fetchPaymentReceiptDetails(
widget.sessionId,
widget.accId,
widget.ledgerId,
);
});
}
@override
Widget build(BuildContext context) {
final isPaid = type == BillStatusType.paid;
final provider = Provider.of<TransactionsProvider>(context);
final data = provider.receiptDetails;
return Dialog(
insetPadding: const EdgeInsets.all(16),
insetPadding: const EdgeInsets.symmetric(horizontal: 24),
backgroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
child: Padding(
child: Container(
width: 360,
padding: const EdgeInsets.all(20),
child: Column(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.white,
),
child: provider.isLoading
? const SizedBox(
height: 200,
child: Center(child: CircularProgressIndicator()))
: data == null
? const Padding(
padding: EdgeInsets.all(32),
child: Center(
child: Text(
"No receipt details found.",
style: TextStyle(
fontFamily: "Poppins",
color: Colors.black54,
),
),
),
)
: Column(
mainAxisSize: MainAxisSize.min,
children: [
// ✅ or ❌ icon
// ✅ Success Tick
Container(
decoration: BoxDecoration(
color: isPaid
? Colors.green.withOpacity(0.1)
: Colors.red.withOpacity(0.1),
height: 60,
width: 60,
decoration: const BoxDecoration(
color: Color(0xFFDFFFEB),
shape: BoxShape.circle,
),
padding: const EdgeInsets.all(12),
child: Icon(
isPaid ? Icons.check_circle : Icons.access_time_filled,
color: isPaid ? Colors.green : Colors.red,
child: const Icon(
Icons.check_circle,
color: Colors.green,
size: 40,
),
),
const SizedBox(height: 12),
const SizedBox(height: 16),
Text(
isPaid ? "Payment Receipt" : "Bill Pending",
style: const TextStyle(
// ✅ Title & Amount
const Text(
"Payment Receipt",
style: TextStyle(
fontSize: 18,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
fontFamily: "Plus Jakarta Sans",
color: Colors.black,
),
),
const SizedBox(height: 6),
const SizedBox(height: 8),
Text(
"₹$amount",
"₹${data.cAmount ?? "--"}",
style: const TextStyle(
fontSize: 28,
fontWeight: FontWeight.w700,
fontWeight: FontWeight.bold,
fontFamily: "Plus Jakarta Sans",
color: Colors.black,
),
),
const SizedBox(height: 18),
// Details
const Divider(thickness: 1),
Align(
const SizedBox(height: 12),
const Divider(thickness: 1, color: Color(0xFFE6E6E6)),
const SizedBox(height: 12),
// ✅ Payment Details
const Align(
alignment: Alignment.centerLeft,
child: Text(
"Payment Details",
style: TextStyle(
fontSize: 15,
color: Colors.grey[700],
fontWeight: FontWeight.w500,
fontSize: 14,
fontWeight: FontWeight.w600,
fontFamily: "Poppins",
color: Colors.black,
),
),
),
const SizedBox(height: 10),
_detailRow("Order ID", "#$orderId", true),
_detailRow("Date", date, false),
if (isPaid) _detailRow("Payment Mode", "UPI", false),
const SizedBox(height: 8),
_buildRow("Order ID", "#${data.id ?? "--"}", Colors.blue),
_buildRow("Date", data.prDate ?? "--", Colors.black),
_buildRow("Payment Mode", data.mode ?? "--",
Colors.black),
const SizedBox(height: 10),
const Divider(thickness: 1),
const SizedBox(height: 12),
const Divider(thickness: 1, color: Color(0xFFE6E6E6)),
const SizedBox(height: 12),
Align(
// ✅ Products
const Align(
alignment: Alignment.centerLeft,
child: Text(
"Products",
style: TextStyle(
fontSize: 15,
color: Colors.grey[700],
fontWeight: FontWeight.w500,
fontSize: 14,
fontWeight: FontWeight.w600,
fontFamily: "Poppins",
color: Colors.black,
),
),
),
const SizedBox(height: 10),
_detailRow(product, "₹${productPrice}", false),
const SizedBox(height: 10),
const Divider(thickness: 1),
_detailRow("Total", "₹$total", true),
const SizedBox(height: 20),
// Bottom buttons
if (isPaid)
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: onDownload,
icon: const Icon(Icons.download, color: Colors.white),
label: const Text(
"Download Receipt",
style: TextStyle(
fontSize: 16,
fontFamily: "Plus Jakarta Sans",
fontWeight: FontWeight.w600,
color: Colors.white,
),
const SizedBox(height: 8),
_buildRow(
data.narration ?? "Product Item",
"₹${data.dAmount ?? "--"}",
Colors.black,
),
const SizedBox(height: 12),
const Divider(thickness: 1, color: Color(0xFFE6E6E6)),
const SizedBox(height: 8),
// ✅ Total
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Total",
style: TextStyle(
fontSize: 15,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.black,
),
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.amountText,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
padding: const EdgeInsets.symmetric(vertical: 14),
),
Text(
"₹${data.cAmount ?? "--"}",
style: const TextStyle(
fontSize: 15,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
)
else
Row(
children: [
Expanded(
child: OutlinedButton.icon(
onPressed: onDownload,
icon: const Icon(Icons.download, color: Colors.black),
label: const Text(
"Download",
style: TextStyle(
color: Colors.black,
fontWeight: FontWeight.w600,
),
),
style: OutlinedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
side: const BorderSide(color: Colors.black26),
padding: const EdgeInsets.symmetric(vertical: 14),
),
),
],
),
const SizedBox(height: 22),
// ✅ Download Button
SizedBox(
width: double.infinity,
child: ElevatedButton.icon(
onPressed: provider.isDownloading
? null
: () async {
await provider.downloadPaymentReceipt(
context,
widget.sessionId,
widget.ledgerId,
widget.accId,
);
},
icon: provider.isDownloading
? const SizedBox(
width: 18,
height: 18,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Colors.white,
),
)
: const Icon(Icons.download,
color: Colors.white, size: 18),
label: Text(
provider.isDownloading
? "Downloading..."
: "Download Receipt",
style: const TextStyle(
fontSize: 15,
fontFamily: "Poppins",
fontWeight: FontWeight.w600,
color: Colors.white,
),
const SizedBox(width: 10),
Expanded(
child: ElevatedButton(
onPressed: 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: 16,
fontFamily: "Plus Jakarta Sans",
fontWeight: FontWeight.w600,
color: Colors.white,
),
),
),
),
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.amountText,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(50),
),
],
padding:
const EdgeInsets.symmetric(vertical: 14),
),
),
),
],
),
),
);
}
Widget _detailRow(String title, String value, bool highlight) {
Widget _buildRow(String title, String value, Color valueColor) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(title,
style: const TextStyle(
fontSize: 14,
color: Colors.black54,
)),
Text(
title,
style: const TextStyle(
fontSize: 14,
fontFamily: "Poppins",
color: Colors.black54,
),
),
Text(
value,
style: TextStyle(
fontSize: 14,
fontWeight: highlight ? FontWeight.w600 : FontWeight.w500,
color: highlight ? Colors.black : Colors.black87,
fontFamily: "Poppins",
fontWeight: FontWeight.w500,
color: valueColor,
),
),
],
......
import 'package:flutter/material.dart';
import 'package:gen_rentals/Utility/Reusablewidgets.dart';
import '../Utility/AppColors.dart';
import '../../Utility/AppColors.dart';
import 'package:flutter_svg/flutter_svg.dart';
class PaymentSuccessfulScreen extends StatefulWidget {
......
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