11/9/1
This commit is contained in:
@@ -1,101 +1,153 @@
|
||||
import 'package:SEFER/constant/box_name.dart';
|
||||
import 'package:SEFER/constant/style.dart';
|
||||
import 'package:SEFER/main.dart';
|
||||
import 'package:SEFER/views/widgets/my_scafold.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
|
||||
class AboutPage extends StatelessWidget {
|
||||
const AboutPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MyScafolld(
|
||||
title: 'About Us'.tr,
|
||||
body: [
|
||||
// Company Logo (consider adding an image asset)
|
||||
ListView(
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
middle: Text('About Us'.tr),
|
||||
),
|
||||
child: SafeArea(
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// Company Logo
|
||||
Center(
|
||||
child: Image.asset(
|
||||
'assets/images/logo.png', // Replace with your logo image asset path
|
||||
height: 100.0,
|
||||
width: 100.0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Image.asset(
|
||||
'assets/images/logo.png', // Replace with your logo image asset path
|
||||
height: 100.0,
|
||||
width: 100.0,
|
||||
),
|
||||
),
|
||||
), // Company Name and Location
|
||||
),
|
||||
|
||||
// Company Name and Location
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text(
|
||||
'SEFER LLC\n${box.read(BoxName.countryCode).toString().tr}',
|
||||
style: AppStyle.headTitle2,
|
||||
style:
|
||||
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||
fontSize: 22.0,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
|
||||
// About Us Description
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Text(
|
||||
'SEFER is a ride-sharing app designed with your safety and affordability in mind. We connect you with reliable drivers in your area, ensuring a convenient and stress-free travel experience.\n\nHere are some of the key features that set us apart:'
|
||||
.tr,
|
||||
style: AppStyle.title,
|
||||
style:
|
||||
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||
fontSize: 16.0,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
), // Security Features List
|
||||
const SizedBox(
|
||||
height: 20,
|
||||
),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
|
||||
// Security Features
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.lock, color: Colors.blue),
|
||||
const Icon(CupertinoIcons.lock_fill,
|
||||
color: CupertinoColors.activeBlue),
|
||||
const SizedBox(width: 8.0),
|
||||
Text(
|
||||
'Most Secure Methods'.tr,
|
||||
style: AppStyle.title,
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Most Secure Methods'.tr,
|
||||
style: CupertinoTheme.of(context)
|
||||
.textTheme
|
||||
.textStyle
|
||||
.copyWith(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.phone, color: Colors.blue),
|
||||
const Icon(CupertinoIcons.phone_fill,
|
||||
color: CupertinoColors.activeBlue),
|
||||
const SizedBox(width: 8.0),
|
||||
Text(
|
||||
'In-App VOIP Calls'.tr,
|
||||
style: AppStyle.title,
|
||||
Expanded(
|
||||
child: Text(
|
||||
'In-App VOIP Calls'.tr,
|
||||
style: CupertinoTheme.of(context)
|
||||
.textTheme
|
||||
.textStyle
|
||||
.copyWith(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8.0),
|
||||
Row(
|
||||
children: [
|
||||
const Icon(Icons.videocam, color: Colors.blue),
|
||||
const Icon(CupertinoIcons.videocam_fill,
|
||||
color: CupertinoColors.activeBlue),
|
||||
const SizedBox(width: 8.0),
|
||||
Text(
|
||||
'Recorded Trips for Safety'.tr,
|
||||
style: AppStyle.title,
|
||||
Expanded(
|
||||
child: Text(
|
||||
'Recorded Trips for Safety'.tr,
|
||||
style: CupertinoTheme.of(context)
|
||||
.textTheme
|
||||
.textStyle
|
||||
.copyWith(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
), // Affordability Highlight
|
||||
),
|
||||
|
||||
// Affordability Highlight
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: Text(
|
||||
'\nWe also prioritize affordability, offering competitive pricing to make your rides accessible.'
|
||||
.tr,
|
||||
style: AppStyle.title,
|
||||
style:
|
||||
CupertinoTheme.of(context).textTheme.textStyle.copyWith(
|
||||
fontSize: 16.0,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
|
||||
// About Us Text
|
||||
],
|
||||
isleading: true);
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
437
lib/views/home/HomePage/share_app_page.dart
Normal file
437
lib/views/home/HomePage/share_app_page.dart
Normal file
@@ -0,0 +1,437 @@
|
||||
import 'package:SEFER/constant/style.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../constant/box_name.dart';
|
||||
import '../../../constant/colors.dart';
|
||||
import '../../../controller/home/profile/invit_controller.dart';
|
||||
import '../../../main.dart';
|
||||
|
||||
class ShareAppPage extends StatelessWidget {
|
||||
final InviteController controller = Get.put(InviteController());
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: CupertinoColors.systemBackground,
|
||||
appBar: AppBar(
|
||||
backgroundColor: CupertinoColors.systemBackground,
|
||||
elevation: 0,
|
||||
title: Text(
|
||||
'Invite'.tr,
|
||||
style: const TextStyle(color: CupertinoColors.label),
|
||||
),
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back_ios, color: AppColor.blueColor),
|
||||
onPressed: () => Get.back(),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: GetBuilder<InviteController>(
|
||||
builder: (controller) {
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: _buildPassengerTab(context),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPassengerTab(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: CupertinoColors.systemGrey6,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
"Share this code with your friends and earn rewards when they use it!"
|
||||
.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(
|
||||
color: CupertinoColors.secondaryLabel,
|
||||
fontSize: 13,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_buildPhoneInput(),
|
||||
const SizedBox(height: 20),
|
||||
_buildActionButtonsPassengers(),
|
||||
const SizedBox(height: 20),
|
||||
const SizedBox(height: 20),
|
||||
_buildInvitationsListPassengers(context),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPhoneInput() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: CupertinoColors.systemGrey6,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CupertinoTextField.borderless(
|
||||
controller: controller.invitePhoneController,
|
||||
placeholder: 'Enter phone'.tr,
|
||||
padding: const EdgeInsets.all(12),
|
||||
keyboardType: TextInputType.phone,
|
||||
),
|
||||
),
|
||||
CupertinoButton(
|
||||
child: const Icon(CupertinoIcons.person_badge_plus,
|
||||
color: AppColor.blueColor),
|
||||
onPressed: () async {
|
||||
await controller.pickContacts();
|
||||
if (controller.contacts.isNotEmpty) {
|
||||
if (box.read(BoxName.isSavedPhones) == null) {
|
||||
controller.savePhoneToServer();
|
||||
box.write(BoxName.isSavedPhones, true);
|
||||
}
|
||||
_showContactsDialog(Get.context!);
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildActionButtonsPassengers() {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20.0, horizontal: 16.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: CupertinoButton(
|
||||
color: AppColor.blueColor,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
onPressed: controller.sendInviteToPassenger,
|
||||
child: Text(
|
||||
'Send Invite'.tr,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: CupertinoColors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
blurRadius: 6,
|
||||
offset: const Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: CupertinoButton(
|
||||
color: AppColor.blueColor,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
child: Text(
|
||||
'Show Invitations'.tr,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: CupertinoColors.white,
|
||||
),
|
||||
),
|
||||
onPressed: () async {
|
||||
controller.fetchDriverStatsPassengers();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInvitationsListPassengers(BuildContext context) {
|
||||
return SizedBox(
|
||||
height: Get.height * .4,
|
||||
child: controller.driverInvitationDataToPassengers.isEmpty
|
||||
? Center(
|
||||
child: Text(
|
||||
"No invitation found yet!".tr,
|
||||
style: const TextStyle(
|
||||
color: CupertinoColors.secondaryLabel,
|
||||
fontSize: 17,
|
||||
),
|
||||
),
|
||||
)
|
||||
: ListView.builder(
|
||||
itemCount: controller.driverInvitationDataToPassengers.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _buildInvitationItemPassengers(context, index);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildInvitationItemPassengers(BuildContext context, int index) {
|
||||
// Extracting the data from the sample JSON-like structure
|
||||
var invitation = controller.driverInvitationDataToPassengers[index];
|
||||
|
||||
int countOfInvitDriver =
|
||||
int.tryParse(invitation['countOfInvitDriver']?.toString() ?? '0') ?? 0;
|
||||
double progressValue = (countOfInvitDriver / 10.0).clamp(0.0, 1.0);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
controller.onSelectPassengerInvitation(index);
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: CupertinoColors.systemGrey6,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
invitation['passengerName']
|
||||
.toString(), // Handle null or missing data
|
||||
style: const TextStyle(
|
||||
fontSize: 17,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: CupertinoColors.label,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
child: LinearProgressIndicator(
|
||||
value: progressValue,
|
||||
backgroundColor: CupertinoColors.systemGrey4,
|
||||
valueColor:
|
||||
const AlwaysStoppedAnimation<Color>(AppColor.blueColor),
|
||||
minHeight: 6,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'$countOfInvitDriver / 2 ${'Trip'.tr}', // Show trips completed
|
||||
style: const TextStyle(
|
||||
fontSize: 13,
|
||||
color: CupertinoColors.secondaryLabel,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPassengerStats(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: CupertinoColors.systemGrey6,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Your Rewards".tr,
|
||||
style: const TextStyle(
|
||||
fontSize: 17,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: CupertinoColors.label,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildStatItem(
|
||||
context,
|
||||
"Total Invites".tr,
|
||||
controller.driverInvitationDataToPassengers[0]['countOfInvitDriver']
|
||||
.toString(),
|
||||
),
|
||||
_buildStatItem(
|
||||
context,
|
||||
"Active Users".tr,
|
||||
controller.driverInvitationDataToPassengers[0]['passengerName']
|
||||
.toString(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStatItem(BuildContext context, String label, String value) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
color: CupertinoColors.label,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
value,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: AppColor.blueColor,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showContactsDialog(BuildContext context) {
|
||||
showCupertinoModalPopup(
|
||||
context: context,
|
||||
builder: (BuildContext context) => Container(
|
||||
height: 400,
|
||||
decoration: BoxDecoration(
|
||||
color: CupertinoColors.systemBackground,
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(20)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: CupertinoColors.black.withOpacity(0.2),
|
||||
offset: const Offset(0, -4),
|
||||
blurRadius: 10,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Header with cancel and title
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: const BoxDecoration(
|
||||
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
||||
color: CupertinoColors.systemGrey6,
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
CupertinoButton(
|
||||
padding: EdgeInsets.zero,
|
||||
child: Text(
|
||||
'Cancel'.tr,
|
||||
style: const TextStyle(color: CupertinoColors.systemBlue),
|
||||
),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
Container(
|
||||
child: Text('Choose from contact'.tr,
|
||||
style: AppStyle.title)),
|
||||
const SizedBox(width: 60), // Balance for Cancel button
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Contact list
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: controller.contactMaps.length,
|
||||
itemBuilder: (context, index) {
|
||||
final contact = controller.contactMaps[index];
|
||||
return CupertinoButton(
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () {
|
||||
controller.selectPhone(contact['phones'].toString());
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
color: CupertinoColors.systemBackground,
|
||||
border: Border(
|
||||
bottom: BorderSide(
|
||||
color: CupertinoColors.separator.withOpacity(0.5),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
// Display contact name and phone number
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
contact['name'],
|
||||
style: const TextStyle(
|
||||
color: CupertinoColors.label,
|
||||
fontSize: 17,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
controller.formatPhoneNumber(
|
||||
contact['phones'][0].toString()),
|
||||
style: const TextStyle(
|
||||
color: CupertinoColors.secondaryLabel,
|
||||
fontSize: 15,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Chevron icon for selection
|
||||
const Icon(
|
||||
CupertinoIcons.chevron_forward,
|
||||
color: CupertinoColors.systemGrey2,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
import 'package:SEFER/views/widgets/my_scafold.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:share/share.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
import '../../../constant/colors.dart';
|
||||
import '../../../constant/style.dart';
|
||||
import '../../../controller/functions/audio_record1.dart';
|
||||
import '../../../controller/functions/tts.dart';
|
||||
import '../../widgets/elevated_btn.dart';
|
||||
|
||||
class TripsRecordedPage extends StatelessWidget {
|
||||
const TripsRecordedPage({
|
||||
@@ -21,132 +18,193 @@ class TripsRecordedPage extends StatelessWidget {
|
||||
title: 'Trips recorded'.tr,
|
||||
body: [
|
||||
GetBuilder<AudioRecorderController>(builder: (audio) {
|
||||
return Column(
|
||||
children: [
|
||||
FutureBuilder<List<String>>(
|
||||
future: audio.getRecordedFiles(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const CircularProgressIndicator();
|
||||
} else if (snapshot.hasData) {
|
||||
final recordedFiles = snapshot.data!;
|
||||
return DropdownButton<String>(
|
||||
value: audio.selectedFilePath,
|
||||
onChanged: (value) {
|
||||
audio.selectedFilePath = value;
|
||||
audio.playRecordedFile(value!);
|
||||
audio.update();
|
||||
},
|
||||
items: recordedFiles
|
||||
.map((file) => DropdownMenuItem<String>(
|
||||
value: file,
|
||||
child: Text(path.basename(file)),
|
||||
))
|
||||
.toList(),
|
||||
);
|
||||
} else {
|
||||
return Text('Error: ${snapshot.error}');
|
||||
}
|
||||
},
|
||||
),
|
||||
Slider(
|
||||
value: audio.currentPosition,
|
||||
max: audio.totalDuration,
|
||||
inactiveColor: AppColor.accentColor,
|
||||
label: audio.currentPosition.toString(),
|
||||
onChanged: (value) {
|
||||
audio.currentPosition = value;
|
||||
audio.audioPlayer.seek(Duration(seconds: value.toInt()));
|
||||
},
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: Icon(
|
||||
audio.isPlaying ? Icons.pause : Icons.play_arrow),
|
||||
onPressed: () {
|
||||
if (audio.isPlaying) {
|
||||
audio.pausePlayback();
|
||||
} else {
|
||||
audio.resumePlayback();
|
||||
}
|
||||
audio.update();
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.stop),
|
||||
onPressed: () {
|
||||
audio.stopPlayback();
|
||||
audio.update();
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.delete),
|
||||
onPressed: () async {
|
||||
Get.defaultDialog(
|
||||
title: 'Are you sure to delete recorded files'.tr,
|
||||
content: Column(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Get.find<TextToSpeechController>().speakText(
|
||||
'this will delete all files from your device'
|
||||
.tr);
|
||||
},
|
||||
icon: const Icon(Icons.headphones),
|
||||
),
|
||||
Text(
|
||||
'this will delete all files from your device'
|
||||
.tr,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
],
|
||||
),
|
||||
titleStyle: AppStyle.title,
|
||||
confirm: MyElevatedButton(
|
||||
title: 'Delete'.tr,
|
||||
kolor: AppColor.redColor,
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
FutureBuilder<List<String>>(
|
||||
future: audio.getRecordedFiles(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
||||
return const Center(
|
||||
child: CupertinoActivityIndicator());
|
||||
} else if (snapshot.hasData) {
|
||||
final recordedFiles = snapshot.data!;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: CupertinoButton(
|
||||
padding: EdgeInsets.zero,
|
||||
onPressed: () async {
|
||||
await audio.deleteAllRecordedFiles();
|
||||
Get.back();
|
||||
Get.back();
|
||||
String? selectedFile =
|
||||
await showCupertinoModalPopup<String>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return CupertinoActionSheet(
|
||||
title: Text('Select a File'.tr),
|
||||
actions: recordedFiles
|
||||
.map(
|
||||
(file) => CupertinoActionSheetAction(
|
||||
child: Text(path.basename(file)),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(file);
|
||||
},
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
);
|
||||
},
|
||||
);
|
||||
if (selectedFile != null) {
|
||||
audio.selectedFilePath = selectedFile;
|
||||
audio.playRecordedFile(selectedFile);
|
||||
audio.update();
|
||||
}
|
||||
},
|
||||
child: Text(
|
||||
audio.selectedFilePath != null
|
||||
? path.basename(audio.selectedFilePath!)
|
||||
: 'Select a File'.tr,
|
||||
style: CupertinoTheme.of(context)
|
||||
.textTheme
|
||||
.actionTextStyle
|
||||
.copyWith(color: CupertinoColors.activeBlue),
|
||||
),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Text('Error: ${snapshot.error}'),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
// Cupertino-style slider for seeking audio
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16.0),
|
||||
child: CupertinoSlider(
|
||||
value: audio.totalDuration > 0
|
||||
? audio.currentPosition / audio.totalDuration
|
||||
: 0.0, // Normalize to a value between 0.0 and 1.0
|
||||
min: 0.0,
|
||||
max: 1.0, // Maximum value is now 1.0
|
||||
activeColor: CupertinoColors.activeBlue,
|
||||
onChanged: (value) {
|
||||
final newPosition = value * audio.totalDuration;
|
||||
audio.currentPosition = newPosition;
|
||||
audio.audioPlayer
|
||||
.seek(Duration(seconds: newPosition.toInt()));
|
||||
audio.update();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
color: Colors.grey[200],
|
||||
),
|
||||
|
||||
// iOS-style playback controls
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 16.0, horizontal: 16.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Text(
|
||||
audio.selectedFilePath != null
|
||||
? '${'Selected file:'.tr} ${path.basename(audio.selectedFilePath!)}'
|
||||
: 'No file selected'.tr,
|
||||
style: AppStyle.subtitle,
|
||||
),
|
||||
if (audio.selectedFilePath != null)
|
||||
IconButton(
|
||||
icon: const Icon(Icons.share),
|
||||
onPressed: () {
|
||||
Share.shareFiles([audio.selectedFilePath!]);
|
||||
},
|
||||
CupertinoButton(
|
||||
padding: EdgeInsets.zero,
|
||||
child: Icon(
|
||||
audio.isPlaying
|
||||
? CupertinoIcons.pause
|
||||
: CupertinoIcons.play_arrow,
|
||||
color: CupertinoColors.activeBlue,
|
||||
),
|
||||
onPressed: () {
|
||||
if (audio.isPlaying) {
|
||||
audio.pausePlayback();
|
||||
} else {
|
||||
audio.resumePlayback();
|
||||
}
|
||||
audio.update();
|
||||
},
|
||||
),
|
||||
CupertinoButton(
|
||||
padding: EdgeInsets.zero,
|
||||
child: const Icon(CupertinoIcons.stop,
|
||||
color: CupertinoColors.destructiveRed),
|
||||
onPressed: () {
|
||||
audio.stopPlayback();
|
||||
audio.update();
|
||||
},
|
||||
),
|
||||
CupertinoButton(
|
||||
padding: EdgeInsets.zero,
|
||||
child: const Icon(CupertinoIcons.delete,
|
||||
color: CupertinoColors.destructiveRed),
|
||||
onPressed: () async {
|
||||
showCupertinoModalPopup(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return CupertinoActionSheet(
|
||||
title: Text('Are you sure?'.tr),
|
||||
message: Text(
|
||||
'This will delete all recorded files from your device.'
|
||||
.tr,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
actions: [
|
||||
CupertinoActionSheetAction(
|
||||
isDestructiveAction: true,
|
||||
onPressed: () async {
|
||||
await audio.deleteAllRecordedFiles();
|
||||
Navigator.pop(context);
|
||||
audio.update();
|
||||
},
|
||||
child: Text('Delete'.tr),
|
||||
),
|
||||
],
|
||||
cancelButton: CupertinoActionSheetAction(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text('Cancel'.tr),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
// File selection and sharing
|
||||
if (audio.selectedFilePath != null)
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
color: CupertinoColors.systemGrey6,
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Selected file: ${path.basename(audio.selectedFilePath!)}',
|
||||
style: CupertinoTheme.of(context)
|
||||
.textTheme
|
||||
.textStyle,
|
||||
),
|
||||
CupertinoButton(
|
||||
padding: EdgeInsets.zero,
|
||||
child: const Icon(CupertinoIcons.share),
|
||||
onPressed: () {
|
||||
Share.shareFiles([audio.selectedFilePath!]);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}),
|
||||
})
|
||||
],
|
||||
isleading: true);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import 'package:SEFER/views/widgets/my_scafold.dart';
|
||||
|
||||
import 'HomePage/about_page.dart';
|
||||
import 'HomePage/frequentlyQuestionsPage.dart';
|
||||
import 'HomePage/share_app_page.dart';
|
||||
import 'HomePage/trip_record_page.dart';
|
||||
import 'profile/passenger_profile_page.dart';
|
||||
|
||||
@@ -21,7 +22,7 @@ class HomePage extends StatelessWidget {
|
||||
isleading: true,
|
||||
title: 'Home Page'.tr,
|
||||
body: [
|
||||
Column(
|
||||
ListView(
|
||||
children: [
|
||||
ListTile(
|
||||
onTap: () {
|
||||
@@ -116,6 +117,19 @@ class HomePage extends StatelessWidget {
|
||||
),
|
||||
onTap: () => Get.to(() => const AboutPage()),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Icons.share),
|
||||
title: Text(
|
||||
'Share App'.tr,
|
||||
style: AppStyle.headTitle2,
|
||||
),
|
||||
subtitle: Text(
|
||||
'You can share the SEFER App with your friends and earn rewards for rides they take using your code'
|
||||
.tr,
|
||||
style: AppStyle.title,
|
||||
),
|
||||
onTap: () => Get.to(() => ShareAppPage()),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -27,7 +27,7 @@ class ApplyOrderWidget extends StatelessWidget {
|
||||
right: 0,
|
||||
child: Container(
|
||||
decoration: AppStyle.boxDecoration,
|
||||
height: Get.height * .35,
|
||||
height: Get.height * .36,
|
||||
child: ListView(
|
||||
children: [
|
||||
InkWell(
|
||||
@@ -87,11 +87,11 @@ class ApplyOrderWidget extends StatelessWidget {
|
||||
width: 10,
|
||||
),
|
||||
Container(
|
||||
height: Get.height * .3,
|
||||
height: Get.height * .34,
|
||||
width: Get.width * .9,
|
||||
decoration: AppStyle.boxDecoration,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.end,
|
||||
@@ -241,12 +241,13 @@ class ApplyOrderWidget extends StatelessWidget {
|
||||
InkWell(
|
||||
onTap: () {
|
||||
FirebaseMessagesController()
|
||||
.sendNotificationToAnyWithoutData(
|
||||
'message From passenger',
|
||||
.sendNotificationToDriverMAP(
|
||||
'message From passenger'.tr,
|
||||
'Hello, I\'m at the agreed-upon location'
|
||||
.tr,
|
||||
controller.driverToken
|
||||
.toString(),
|
||||
[],
|
||||
'ding.wav',
|
||||
);
|
||||
Get.back();
|
||||
@@ -272,11 +273,12 @@ class ApplyOrderWidget extends StatelessWidget {
|
||||
InkWell(
|
||||
onTap: () {
|
||||
FirebaseMessagesController()
|
||||
.sendNotificationToAnyWithoutData(
|
||||
.sendNotificationToDriverMAP(
|
||||
'message From passenger'.tr,
|
||||
'My location is correct. You can search for me using the navigation app'
|
||||
.tr,
|
||||
controller.driverToken,
|
||||
[],
|
||||
'ding.wav',
|
||||
);
|
||||
Get.back();
|
||||
@@ -302,11 +304,12 @@ class ApplyOrderWidget extends StatelessWidget {
|
||||
InkWell(
|
||||
onTap: () {
|
||||
FirebaseMessagesController()
|
||||
.sendNotificationToAnyWithoutData(
|
||||
.sendNotificationToDriverMAP(
|
||||
'message From passenger',
|
||||
'My location is correct. You can search for me using the navigation app'
|
||||
.tr,
|
||||
controller.driverToken,
|
||||
[],
|
||||
'ding.wav',
|
||||
);
|
||||
Get.back();
|
||||
@@ -331,11 +334,12 @@ class ApplyOrderWidget extends StatelessWidget {
|
||||
InkWell(
|
||||
onTap: () {
|
||||
FirebaseMessagesController()
|
||||
.sendNotificationToAnyWithoutData(
|
||||
.sendNotificationToDriverMAP(
|
||||
'message From passenger',
|
||||
"How much longer will you be?"
|
||||
.tr,
|
||||
controller.driverToken,
|
||||
[],
|
||||
'ding.wav',
|
||||
);
|
||||
Get.back();
|
||||
@@ -385,13 +389,14 @@ class ApplyOrderWidget extends StatelessWidget {
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
FirebaseMessagesController()
|
||||
.sendNotificationToAnyWithoutData(
|
||||
.sendNotificationToDriverMAP(
|
||||
'message From passenger',
|
||||
controller
|
||||
.messageToDriver
|
||||
.text,
|
||||
controller
|
||||
.driverToken,
|
||||
[],
|
||||
'ding.wav');
|
||||
controller
|
||||
.messageToDriver
|
||||
@@ -466,7 +471,7 @@ class DriverArrivePassengerAndWaitMinute extends StatelessWidget {
|
||||
color: controller.remainingTimeDriverWaitPassenger5Minute < 60
|
||||
? AppColor.redColor
|
||||
: AppColor.greenColor,
|
||||
minHeight: 25,
|
||||
minHeight: 15,
|
||||
borderRadius: BorderRadius.circular(15),
|
||||
value:
|
||||
controller.progressTimerDriverWaitPassenger5Minute.toDouble(),
|
||||
@@ -513,7 +518,7 @@ class TimeDriverToPassenger extends StatelessWidget {
|
||||
Container(
|
||||
decoration: AppStyle.boxDecoration,
|
||||
width: Get.width * .7,
|
||||
height: 35,
|
||||
height: 15,
|
||||
// color: AppColor.yellowColor,
|
||||
),
|
||||
Stack(
|
||||
|
||||
@@ -3,11 +3,11 @@ import 'package:get/get.dart';
|
||||
import 'package:SEFER/constant/colors.dart';
|
||||
import 'package:SEFER/constant/style.dart';
|
||||
import 'package:SEFER/controller/home/map_passenger_controller.dart';
|
||||
|
||||
import '../../widgets/elevated_btn.dart';
|
||||
|
||||
GetBuilder<MapPassengerController> cancelRidePage() {
|
||||
Get.put(MapPassengerController());
|
||||
|
||||
final List<String> reasons = [
|
||||
"I don't need a ride anymore".tr,
|
||||
"I was just trying the application".tr,
|
||||
@@ -16,80 +16,74 @@ GetBuilder<MapPassengerController> cancelRidePage() {
|
||||
"I don't have a reason".tr,
|
||||
"Other".tr,
|
||||
];
|
||||
|
||||
return GetBuilder<MapPassengerController>(
|
||||
builder: (controller) => controller.isCancelRidePageShown
|
||||
? Positioned(
|
||||
left: Get.width * .1,
|
||||
top: Get.width * .2,
|
||||
right: Get.width * .1,
|
||||
bottom: Get.width * .15,
|
||||
left: 20,
|
||||
top: Get.height * 0.15,
|
||||
right: 20,
|
||||
bottom: Get.height * 0.15,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: AppColor.secondaryColor,
|
||||
color: Colors.white,
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
color: AppColor.accentColor,
|
||||
offset: Offset(2, 2),
|
||||
blurRadius: 5),
|
||||
BoxShadow(
|
||||
color: AppColor.accentColor.withOpacity(.4),
|
||||
offset: const Offset(-2, -2),
|
||||
blurRadius: 5)
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
offset: const Offset(0, 8),
|
||||
blurRadius: 16,
|
||||
),
|
||||
],
|
||||
borderRadius: const BorderRadius.all(Radius.circular(15)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
height: Get.height * .7,
|
||||
width: Get.width * .7,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10),
|
||||
child: Text(
|
||||
'Can we know why you want to cancel Ride ?'.tr,
|
||||
style: AppStyle.title,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
Text(
|
||||
'Can we know why you want to cancel Ride ?'.tr,
|
||||
style: AppStyle.title
|
||||
.copyWith(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
SizedBox(
|
||||
height: 380,
|
||||
width: 300,
|
||||
child: ListView.builder(
|
||||
const SizedBox(height: 20),
|
||||
Expanded(
|
||||
child: ListView.separated(
|
||||
itemCount: reasons.length,
|
||||
separatorBuilder: (context, index) => const Divider(),
|
||||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
title: InkWell(
|
||||
onTap: () {
|
||||
controller.selectReason(
|
||||
index,
|
||||
reasons[index].toString(),
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
reasons[index],
|
||||
style: AppStyle.title,
|
||||
)),
|
||||
title: Text(
|
||||
reasons[index],
|
||||
style: AppStyle.title.copyWith(fontSize: 16),
|
||||
),
|
||||
leading: Radio(
|
||||
value: index,
|
||||
groupValue: controller.selectedReason,
|
||||
onChanged: (int? value) {
|
||||
controller.selectReason(
|
||||
value!,
|
||||
reasons[index].toString(),
|
||||
);
|
||||
controller.selectReason(value!, reasons[index]);
|
||||
},
|
||||
activeColor: AppColor.primaryColor,
|
||||
),
|
||||
onTap: () {
|
||||
controller.selectReason(index, reasons[index]);
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
MyElevatedButton(
|
||||
title: 'Cancel Ride'.tr,
|
||||
onPressed: () {
|
||||
if (controller.selectedReason == -1) {
|
||||
Get.snackbar('You Should be select reason.'.tr, '',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
backgroundColor: AppColor.redColor);
|
||||
Get.snackbar(
|
||||
'You Should be select reason.'.tr,
|
||||
'',
|
||||
snackPosition: SnackPosition.BOTTOM,
|
||||
backgroundColor: AppColor.redColor,
|
||||
colorText: Colors.white,
|
||||
);
|
||||
} else {
|
||||
controller.cancelRide();
|
||||
}
|
||||
|
||||
@@ -586,7 +586,7 @@ class CarDetailsTypeToChoose extends StatelessWidget {
|
||||
textToSpeechController,
|
||||
image: 'assets/images/freeRide.png',
|
||||
text:
|
||||
'Perfect for adventure seekers who want to experience something new and exciting'
|
||||
"Perfect for passengers seeking the latest car models with the freedom to choose any route they desire"
|
||||
.tr),
|
||||
confirm: MyElevatedButton(
|
||||
kolor: AppColor.greenColor,
|
||||
@@ -656,8 +656,10 @@ class CarDetailsTypeToChoose extends StatelessWidget {
|
||||
title: 'Next'.tr,
|
||||
onPressed: () {
|
||||
Get.back();
|
||||
if (box.read(BoxName.gender) !=
|
||||
null) {
|
||||
if (box
|
||||
.read(BoxName.gender)
|
||||
.toString() !=
|
||||
'') {
|
||||
mapPassengerController
|
||||
.isBottomSheetShown = false;
|
||||
mapPassengerController.update();
|
||||
@@ -710,59 +712,108 @@ class CarDetailsTypeToChoose extends StatelessWidget {
|
||||
MainAxisAlignment
|
||||
.spaceBetween,
|
||||
children: [
|
||||
Container(
|
||||
decoration: AppStyle
|
||||
.boxDecoration1,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets
|
||||
.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text('Awfar Car'
|
||||
.tr),
|
||||
Text(mapPassengerController
|
||||
.totalPassengerRayehGaiBalash
|
||||
.toStringAsFixed(
|
||||
0)),
|
||||
],
|
||||
),
|
||||
)),
|
||||
Container(
|
||||
decoration: AppStyle
|
||||
.boxDecoration1,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets
|
||||
.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text('Speed'.tr),
|
||||
Text(mapPassengerController
|
||||
.totalPassengerRayehGai
|
||||
.toStringAsFixed(
|
||||
0)),
|
||||
],
|
||||
),
|
||||
)),
|
||||
Container(
|
||||
decoration: AppStyle
|
||||
.boxDecoration1,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets
|
||||
.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Comfort'.tr),
|
||||
Text(mapPassengerController
|
||||
.totalPassengerRayehGaiComfort
|
||||
.toStringAsFixed(
|
||||
0)),
|
||||
],
|
||||
),
|
||||
))
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
mapPassengerController
|
||||
.totalPassenger =
|
||||
mapPassengerController
|
||||
.totalPassengerRayehGaiBalash;
|
||||
mapPassengerController
|
||||
.isBottomSheetShown =
|
||||
false;
|
||||
mapPassengerController
|
||||
.update();
|
||||
mapPassengerController
|
||||
.changeCashConfirmPageShown();
|
||||
},
|
||||
child: Container(
|
||||
decoration: AppStyle
|
||||
.boxDecoration1,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets
|
||||
.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text('Awfar Car'
|
||||
.tr),
|
||||
Text(mapPassengerController
|
||||
.totalPassengerRayehGaiBalash
|
||||
.toStringAsFixed(
|
||||
0)),
|
||||
],
|
||||
),
|
||||
)),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
mapPassengerController
|
||||
.totalPassenger =
|
||||
mapPassengerController
|
||||
.totalPassengerRayehGai;
|
||||
mapPassengerController
|
||||
.isBottomSheetShown =
|
||||
false;
|
||||
mapPassengerController
|
||||
.update();
|
||||
mapPassengerController
|
||||
.changeCashConfirmPageShown();
|
||||
},
|
||||
child: Container(
|
||||
decoration: AppStyle
|
||||
.boxDecoration1,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets
|
||||
.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Speed'.tr),
|
||||
Text(mapPassengerController
|
||||
.totalPassengerRayehGai
|
||||
.toStringAsFixed(
|
||||
0)),
|
||||
],
|
||||
),
|
||||
)),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Get.back();
|
||||
mapPassengerController
|
||||
.totalPassenger =
|
||||
mapPassengerController
|
||||
.totalPassengerRayehGaiComfort;
|
||||
mapPassengerController
|
||||
.isBottomSheetShown =
|
||||
false;
|
||||
mapPassengerController
|
||||
.update();
|
||||
mapPassengerController
|
||||
.changeCashConfirmPageShown();
|
||||
},
|
||||
child: Container(
|
||||
decoration: AppStyle
|
||||
.boxDecoration1,
|
||||
child: Padding(
|
||||
padding:
|
||||
const EdgeInsets
|
||||
.all(8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text('Comfort'
|
||||
.tr),
|
||||
Text(mapPassengerController
|
||||
.totalPassengerRayehGaiComfort
|
||||
.toStringAsFixed(
|
||||
0)),
|
||||
],
|
||||
),
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
cancel: MyElevatedButton(
|
||||
@@ -951,9 +1002,16 @@ class BurcMoney extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class HeaderDestination extends StatelessWidget {
|
||||
class HeaderDestination extends StatefulWidget {
|
||||
const HeaderDestination({super.key});
|
||||
|
||||
@override
|
||||
_HeaderDestinationState createState() => _HeaderDestinationState();
|
||||
}
|
||||
|
||||
class _HeaderDestinationState extends State<HeaderDestination> {
|
||||
bool _isExpanded = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GetBuilder<MapPassengerController>(
|
||||
@@ -965,95 +1023,64 @@ class HeaderDestination extends StatelessWidget {
|
||||
top: Get.height * .08,
|
||||
left: 5,
|
||||
right: 5,
|
||||
child: Container(
|
||||
decoration: AppStyle.boxDecoration1,
|
||||
height: Get.height * .15,
|
||||
width: Get.width * .8,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
// mapPassengerController
|
||||
// .getDialog('Are you want to change'.tr, '', () {
|
||||
// Get.back();
|
||||
// mapPassengerController.cancelRide();
|
||||
// });
|
||||
MyDialog().getDialog(
|
||||
"Change Route".tr,
|
||||
'You can change the destination by long-pressing any point on the map'
|
||||
.tr, () {
|
||||
Get.back();
|
||||
});
|
||||
},
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_isExpanded = !_isExpanded;
|
||||
});
|
||||
},
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
decoration: AppStyle.boxDecoration1,
|
||||
height: _isExpanded ? Get.height * .13 : Get.height * .06,
|
||||
width: Get.width * .9,
|
||||
padding: const EdgeInsets.all(8),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 8, vertical: 2),
|
||||
child: SizedBox(
|
||||
height: Get.height * .08,
|
||||
child: ListView(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
//
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'🟢 ',
|
||||
_isExpanded
|
||||
? Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('🟢 ', style: AppStyle.subtitle),
|
||||
Expanded(
|
||||
child: Text(
|
||||
mapPassengerController.startNameAddress,
|
||||
style: AppStyle.subtitle,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
SizedBox(
|
||||
// height: Get.height * .03,
|
||||
width: Get.width * .8,
|
||||
child: Text(
|
||||
mapPassengerController.startNameAddress,
|
||||
style: AppStyle.subtitle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'🔴 ',
|
||||
style: AppStyle.subtitle,
|
||||
),
|
||||
SizedBox(
|
||||
// height: Get.height * .03,
|
||||
width: Get.width * .8,
|
||||
child: Text(
|
||||
mapPassengerController.endNameAddress,
|
||||
style: AppStyle.subtitle,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
: const SizedBox(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text('🔴 ', style: AppStyle.subtitle),
|
||||
Expanded(
|
||||
child: Text(
|
||||
mapPassengerController.endNameAddress,
|
||||
style: AppStyle.subtitle,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Row(
|
||||
if (_isExpanded)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'📍 ',
|
||||
style: AppStyle.subtitle,
|
||||
),
|
||||
SizedBox(
|
||||
width: Get.width * .8,
|
||||
Text('📍', style: AppStyle.subtitle),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'${mapPassengerController.distance} ${'KM'.tr} ⌛ ${mapPassengerController.hours > 0 ? '${'Your Ride Duration is '.tr}${mapPassengerController.hours} ${'H and'.tr} ${mapPassengerController.minutes} ${'m'.tr}' : '${'Your Ride Duration is '.tr} ${mapPassengerController.minutes} ${'m'.tr}'}',
|
||||
style: AppStyle.subtitle,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@@ -29,7 +29,8 @@ class CashConfirmPageShown extends StatelessWidget {
|
||||
? controller.cashConfirmPageShown
|
||||
: 0,
|
||||
decoration: BoxDecoration(
|
||||
color: box.read(BoxName.carType) == 'Lady'
|
||||
color: box.read(BoxName.carType) == 'Lady' ||
|
||||
box.read(BoxName.carType) == 'Pink Bike'
|
||||
? Colors.pink.shade100
|
||||
: AppColor.secondaryColor,
|
||||
borderRadius: BorderRadius.circular(15)),
|
||||
|
||||
@@ -419,7 +419,7 @@ class GoogleMapPassengerWidget extends StatelessWidget {
|
||||
},
|
||||
|
||||
mapType:
|
||||
controller.mapType ? MapType.satellite : MapType.normal,
|
||||
controller.mapType ? MapType.satellite : MapType.terrain,
|
||||
myLocationButtonEnabled: true,
|
||||
// liteModeEnabled: true, tiltGesturesEnabled: false,
|
||||
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:SEFER/views/auth/login_page.dart';
|
||||
import 'package:SEFER/views/auth/sms_verfy_page.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:google_maps_flutter/google_maps_flutter.dart';
|
||||
import '../../../constant/colors.dart';
|
||||
import '../../../constant/notification.dart';
|
||||
import '../../../controller/firebase/local_notification.dart';
|
||||
import '../../../controller/functions/tts.dart';
|
||||
import '../../../controller/home/map_passenger_controller.dart';
|
||||
|
||||
@@ -89,17 +95,14 @@ GetBuilder<MapPassengerController> leftMainMenuIcons() {
|
||||
// borderRadius: BorderRadius.circular(15)),
|
||||
// child: IconButton(
|
||||
// onPressed: () async {
|
||||
// FirebaseMessagesController().sendNotificationToAnyWithoutData(
|
||||
// 'Order'.tr,
|
||||
// 'from: ',
|
||||
// // jsonDecode(value)['message'].toString(),
|
||||
// 'dEugS-JOT4Ka5riF4s5TEN:APA91bEDL_W7BuEQGbyL-RMaKiMWDlURXhFuaybe5WurTUV8K5eIooSGe22yY22_U2hEZcfPr46ig1v--l00dbOGiivazxvmTyhUyQQW6lJsuIN-wordGtBxtREyeYtEKvxIa1J4ApEu',
|
||||
// 'order.wav'
|
||||
|
||||
// // polylineCoordinates.toString()
|
||||
// );
|
||||
// // print(box.read(BoxName.tokenFCM));
|
||||
// //
|
||||
// final random = Random();
|
||||
// final randomMessage =
|
||||
// messages[random.nextInt(messages.length)];
|
||||
// NotificationController().showNotification(
|
||||
// randomMessage.split(':')[0],
|
||||
// randomMessage.split(':')[1],
|
||||
// "ding",
|
||||
// );
|
||||
// },
|
||||
// icon: const Icon(
|
||||
// Icons.voice_chat,
|
||||
|
||||
@@ -30,7 +30,7 @@ class RideBeginPassenger extends StatelessWidget {
|
||||
return Positioned(
|
||||
left: 10,
|
||||
right: 10,
|
||||
bottom: 4,
|
||||
bottom: 10,
|
||||
child: Container(
|
||||
decoration: AppStyle.boxDecoration,
|
||||
height: controller.statusRide == 'Begin' ? Get.height * .33 : 0,
|
||||
|
||||
@@ -8,6 +8,121 @@ import 'package:SEFER/views/widgets/my_textField.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import '../../../constant/links.dart';
|
||||
|
||||
// class SearchingCaptainWindow extends StatelessWidget {
|
||||
// const SearchingCaptainWindow({super.key});
|
||||
|
||||
// Widget _buildDriverAvatars(MapPassengerController controller) {
|
||||
// // If no drivers yet, show loading indicator
|
||||
// if (controller.isSearchingWindow) {
|
||||
// // Check if dataCarsLocationByPassenger or its 'data' is null
|
||||
// if (controller.dataCarsLocationByPassenger == null ||
|
||||
// controller.dataCarsLocationByPassenger['data'] == null ||
|
||||
// controller.dataCarsLocationByPassenger['data'].isEmpty) {
|
||||
// return const SizedBox(
|
||||
// height: 60,
|
||||
// child: Center(
|
||||
// child: CircularProgressIndicator(
|
||||
// valueColor:
|
||||
// AlwaysStoppedAnimation<Color>(AppColor.secondaryColor),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
// return SizedBox(
|
||||
// height: 60,
|
||||
// child: ListView.builder(
|
||||
// scrollDirection: Axis.horizontal,
|
||||
// itemCount: controller.dataCarsLocationByPassenger['data'].length,
|
||||
// padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
// itemBuilder: (context, index) {
|
||||
// final driver = controller.dataCarsLocationByPassenger['data'][index];
|
||||
// return Padding(
|
||||
// padding: const EdgeInsets.only(right: 8),
|
||||
// child: Column(
|
||||
// mainAxisSize: MainAxisSize.min,
|
||||
// children: [
|
||||
// CircleAvatar(
|
||||
// radius: 25,
|
||||
// backgroundColor: AppColor.secondaryColor,
|
||||
// child: ClipOval(
|
||||
// child: Image.network(
|
||||
// '${AppLink.server}/portrate_captain_image/${driver['driver_id']}.jpg',
|
||||
// width: 50,
|
||||
// height: 50,
|
||||
// fit: BoxFit.cover,
|
||||
// errorBuilder: (context, error, stackTrace) {
|
||||
// return const Icon(
|
||||
// Icons.person,
|
||||
// color: Colors.white,
|
||||
// size: 30,
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return GetBuilder<MapPassengerController>(
|
||||
// builder: (mapPassengerController) {
|
||||
// return mapPassengerController.isSearchingWindow
|
||||
// ? Positioned(
|
||||
// bottom: 0,
|
||||
// left: 0,
|
||||
// right: 0,
|
||||
// child: Container(
|
||||
// decoration: AppStyle.boxDecoration1,
|
||||
// height: Get.height *
|
||||
// .3, // Increased height to accommodate avatars
|
||||
// child: Column(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
// children: [
|
||||
// SizedBox(
|
||||
// width: Get.width * .7,
|
||||
// child: const LinearProgressIndicator(
|
||||
// minHeight: 6,
|
||||
// backgroundColor: AppColor.yellowColor,
|
||||
// color: AppColor.secondaryColor,
|
||||
// ),
|
||||
// ),
|
||||
// mapPassengerController.driverOrderStatus == 'recive'
|
||||
// ? Text(
|
||||
// "Drivers received orders".tr,
|
||||
// style: AppStyle.title,
|
||||
// )
|
||||
// : Text(
|
||||
// "We are searching for the nearest driver to you"
|
||||
// .tr,
|
||||
// style: AppStyle.title,
|
||||
// ),
|
||||
// Text(
|
||||
// 'please wait till driver accept your order'.tr,
|
||||
// style: AppStyle.title,
|
||||
// ),
|
||||
// // New: Driver avatars section
|
||||
// _buildDriverAvatars(mapPassengerController),
|
||||
// _buildTimer(mapPassengerController),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// )
|
||||
// : const SizedBox();
|
||||
// },
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
class SearchingCaptainWindow extends StatelessWidget {
|
||||
const SearchingCaptainWindow({super.key});
|
||||
|
||||
|
||||
@@ -116,9 +116,10 @@ class CupertinoDriverListWidget extends StatelessWidget {
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: hexToColor(
|
||||
driver['color_hex'].toString()) ??
|
||||
Colors.amber,
|
||||
color: driver['color_hex'].toString() == 'null'
|
||||
? Colors.amber
|
||||
: hexToColor(
|
||||
driver['color_hex'].toString()),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(),
|
||||
),
|
||||
@@ -151,9 +152,11 @@ class CupertinoDriverListWidget extends StatelessWidget {
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: hexToColor(
|
||||
driver['color_hex'].toString()) ??
|
||||
AppColor.bronze,
|
||||
color:
|
||||
driver['color_hex'].toString() == 'null'
|
||||
? Colors.amber
|
||||
: hexToColor(
|
||||
driver['color_hex'].toString()),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(),
|
||||
),
|
||||
@@ -204,7 +207,9 @@ class CupertinoDriverListWidget extends StatelessWidget {
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
color: hexToColor(driver['color_hex'].toString()),
|
||||
color: driver['color_hex'].toString() == 'null'
|
||||
? Colors.amber
|
||||
: hexToColor(driver['color_hex'].toString()),
|
||||
borderRadius: BorderRadius.circular(4),
|
||||
border: Border.all(),
|
||||
),
|
||||
|
||||
@@ -1,64 +1,199 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:SEFER/views/widgets/my_scafold.dart';
|
||||
import 'package:SEFER/views/widgets/mycircular.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import '../../../controller/home/profile/complaint_controller.dart';
|
||||
import '../../widgets/elevated_btn.dart';
|
||||
import 'package:SEFER/constant/colors.dart';
|
||||
import 'package:SEFER/constant/style.dart';
|
||||
import 'package:SEFER/controller/functions/crud.dart';
|
||||
import 'package:SEFER/controller/home/profile/complaint_controller.dart';
|
||||
import 'package:SEFER/views/widgets/my_dialog.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'dart:io';
|
||||
|
||||
import '../../../controller/functions/audio_record1.dart';
|
||||
|
||||
class ComplaintPage extends StatelessWidget {
|
||||
// Rename class
|
||||
ComplaintPage({super.key});
|
||||
ComplaintController complaintController =
|
||||
Get.put(ComplaintController()); // Update controller instance
|
||||
final ComplaintController complaintController =
|
||||
Get.put(ComplaintController());
|
||||
final AudioRecorderController audioRecorderController =
|
||||
Get.put(AudioRecorderController());
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return MyScafolld(
|
||||
title: 'Complaint'.tr,
|
||||
body: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(26),
|
||||
child: Form(
|
||||
key: complaintController.formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: complaintController.complaintController,
|
||||
decoration: InputDecoration(
|
||||
border: const OutlineInputBorder(),
|
||||
hintText: 'Enter your complaint here'.tr,
|
||||
labelText: 'Complaint'.tr, // Update label
|
||||
),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter your complaint.'.tr;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
complaintController.isLoading
|
||||
? const MyCircularProgressIndicator()
|
||||
: MyElevatedButton(
|
||||
onPressed: () {
|
||||
if (complaintController.formKey.currentState!
|
||||
.validate()) {
|
||||
complaintController
|
||||
.addComplaint(); // Update method name
|
||||
|
||||
// Clear the complaint form
|
||||
complaintController.formKey.currentState!.reset();
|
||||
}
|
||||
},
|
||||
title: 'Submit'.tr,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
return GetBuilder<ComplaintController>(builder: (complaintController) {
|
||||
return CupertinoPageScaffold(
|
||||
navigationBar: CupertinoNavigationBar(
|
||||
middle: Text('Complaint'.tr, style: AppStyle.title),
|
||||
),
|
||||
],
|
||||
isleading: true,
|
||||
);
|
||||
child: complaintController.isLoading
|
||||
? const Center(child: CupertinoActivityIndicator())
|
||||
: SafeArea(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: complaintController.formKey,
|
||||
child: ListView(
|
||||
children: [
|
||||
// Complaint Text Field
|
||||
CupertinoFormSection(
|
||||
header: Text('Submit Your Complaint'.tr),
|
||||
children: [
|
||||
CupertinoTextField(
|
||||
controller:
|
||||
complaintController.complaintController,
|
||||
placeholder: 'Enter your complaint here'.tr,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 12, horizontal: 16),
|
||||
maxLines: 5,
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: CupertinoColors.systemGrey4),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
color: CupertinoColors.white,
|
||||
),
|
||||
style: AppStyle.subtitle,
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// FutureBuilder to load recorded audio files
|
||||
FutureBuilder<List<String>>(
|
||||
future: audioRecorderController.getRecordedFiles(),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState ==
|
||||
ConnectionState.waiting) {
|
||||
return const Center(
|
||||
child: CupertinoActivityIndicator());
|
||||
} else if (snapshot.hasError) {
|
||||
return Text('Error: ${snapshot.error}',
|
||||
style: AppStyle.subtitle);
|
||||
} else if (snapshot.hasData &&
|
||||
snapshot.data!.isEmpty) {
|
||||
return Text('No audio files recorded.'.tr,
|
||||
style: AppStyle.subtitle);
|
||||
}
|
||||
|
||||
// List of recorded audio files
|
||||
return CupertinoFormSection(
|
||||
header: Text('attach audio of complain'.tr),
|
||||
children: snapshot.data!.map((audioFilePath) {
|
||||
final audioFile = File(audioFilePath);
|
||||
return CupertinoListTile(
|
||||
title: Text(audioFilePath.split('/').last,
|
||||
style: AppStyle.title),
|
||||
trailing: const Icon(
|
||||
CupertinoIcons.play_arrow,
|
||||
color: AppColor.accentColor),
|
||||
onTap: () async {
|
||||
MyDialogContent().getDialog(
|
||||
'be sure'.tr,
|
||||
Text('attach correct audio'.tr),
|
||||
() async {
|
||||
await complaintController
|
||||
.uploadAudioFile(audioFile);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Trip Details Section
|
||||
CupertinoFormSection(
|
||||
header: Text('Trip Details'.tr),
|
||||
children: [
|
||||
CupertinoListTile(
|
||||
title: complaintController.feedBack.isEmpty
|
||||
? Text('No Ride found yet'.tr)
|
||||
: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'${'Date'.tr}: ${complaintController.feedBack[0]['date']}',
|
||||
style: AppStyle.title),
|
||||
Text(
|
||||
'${'Price'.tr}: ${complaintController.feedBack[0]['price']}',
|
||||
style: AppStyle.title),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
CupertinoFormSection(
|
||||
header: Text('SEFER answer'.tr),
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 100,
|
||||
child: ListView(
|
||||
children: [
|
||||
// Check if passengerReport is not null
|
||||
if (complaintController.passengerReport !=
|
||||
null)
|
||||
// Access the 'solution' key safely
|
||||
Text(
|
||||
complaintController
|
||||
.passengerReport!['solution']
|
||||
?.toString() ??
|
||||
'No solution available',
|
||||
style: AppStyle.title,
|
||||
)
|
||||
else
|
||||
const SizedBox(), // Fallback if passengerReport is null
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
// Submit Button
|
||||
CupertinoButton(
|
||||
color: AppColor.blueColor,
|
||||
padding: const EdgeInsets.symmetric(
|
||||
vertical: 14, horizontal: 30),
|
||||
onPressed: () async {
|
||||
if (complaintController.formKey.currentState!
|
||||
.validate()) {
|
||||
if (complaintController.audioLink.toString() ==
|
||||
'') {
|
||||
MyDialogContent().getDialog(
|
||||
'title',
|
||||
Text(
|
||||
'the audio file not uploaded yet \nDo you want to upload without audio file'
|
||||
.tr), () async {
|
||||
await complaintController.geminiAudio(
|
||||
jsonEncode(complaintController.feedBack),
|
||||
complaintController.audioLink,
|
||||
complaintController
|
||||
.complaintController.text);
|
||||
complaintController.formKey.currentState!
|
||||
.reset();
|
||||
});
|
||||
Get.back();
|
||||
} else {
|
||||
await complaintController.geminiAudio(
|
||||
jsonEncode(complaintController.feedBack),
|
||||
complaintController.audioLink,
|
||||
complaintController
|
||||
.complaintController.text);
|
||||
complaintController.formKey.currentState!
|
||||
.reset();
|
||||
}
|
||||
complaintController.addComplaint();
|
||||
}
|
||||
},
|
||||
child: Text('Submit'.tr, style: AppStyle.title),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user