change to map-saas api key and env - 2026-04-12

This commit is contained in:
Hamza-Ayed
2026-04-12 02:25:44 +03:00
parent 454276d1e0
commit 0aa1f15f25
16 changed files with 14974 additions and 13857 deletions

View File

@@ -35,187 +35,675 @@ class LoginPage extends StatelessWidget {
if (box.read(BoxName.agreeTerms) != 'agreed')
_buildAgreementPage(context, controller)
else if (box.read(BoxName.locationPermission) != 'true')
_buildLocationPermissionDialog(controller)
// else if (box.read(BoxName.isTest).toString() == '0')
// buildEmailPasswordForm(controller)
_buildLocationPermissionDialog(context, controller)
else
// _buildLoginContent(controller, authController),
PhoneNumberScreen()
],
),
);
}
Widget _buildAgreementPage(BuildContext context, LoginController controller) {
// This UI can be identical to the one in LoginPage for consistency.
// I am reusing the improved design from the previous request.
return Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.policy_outlined, size: 80, color: AppColor.primaryColor),
const SizedBox(height: 20),
Text("passenger agreement".tr,
textAlign: TextAlign.center, style: AppStyle.headTitle2),
const SizedBox(height: 30),
RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: AppStyle.title.copyWith(height: 1.5),
children: [
TextSpan(
text:
"To become a passenger, you must review and agree to the "
.tr),
TextSpan(
text: 'Terms of Use'.tr,
style: TextStyle(
decoration: TextDecoration.underline,
color: AppColor.cyanBlue,
fontWeight: FontWeight.bold),
recognizer: TapGestureRecognizer()
..onTap = () {
launchUrl(Uri.parse(
'https://intaleq.xyz/intaleq/privacy_policy.php'));
}),
TextSpan(text: " and acknowledge our Privacy Policy.".tr),
],
// ─────────────────────────────────────────────────────────────────────────
// SHARED HELPERS
// ─────────────────────────────────────────────────────────────────────────
/// Subtle geometric background — two soft circles, no heavy blur needed.
Widget _buildBackground(BuildContext context) {
final isDark = Theme.of(context).brightness == Brightness.dark;
return Stack(
children: [
// Base gradient
Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: isDark
? [const Color(0xFF0D0D14), const Color(0xFF161622)]
: [const Color(0xFFF8F9FF), const Color(0xFFEFF1FB)],
),
),
Expanded(
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.grey.shade300),
borderRadius: BorderRadius.circular(8),
),
child: SingleChildScrollView(
padding: const EdgeInsets.all(12),
child: HtmlWidget(box.read(BoxName.lang).toString() == 'ar'
? AppInformation.privacyPolicyArabic
: AppInformation.privacyPolicy),
),
// Top-right accent circle
Positioned(
top: -80,
right: -60,
child: Container(
width: 260,
height: 260,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
AppColor.primaryColor.withOpacity(isDark ? 0.18 : 0.12),
AppColor.primaryColor.withOpacity(0.0),
],
),
),
),
CheckboxListTile(
title: Text('I Agree'.tr, style: AppStyle.title),
value: controller.isAgreeTerms,
onChanged: (value) => controller.changeAgreeTerm(),
activeColor: AppColor.primaryColor,
controlAffinity: ListTileControlAffinity.leading,
),
const SizedBox(height: 16),
SizedBox(
width: double.infinity,
child: MyElevatedButton(
title: 'Continue'.tr,
onPressed: controller.isAgreeTerms
? () => controller.saveAgreementTerms()
: () {},
),
// Bottom-left accent circle
Positioned(
bottom: -100,
left: -80,
child: Container(
width: 320,
height: 320,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: RadialGradient(
colors: [
AppColor.primaryColor.withOpacity(isDark ? 0.12 : 0.08),
AppColor.primaryColor.withOpacity(0.0),
],
),
),
),
],
),
),
],
);
}
Widget buildEmailPasswordForm(LoginController controller) {
/// Glassy card container used across screens.
Widget _glassCard({
required Widget child,
required bool isDark,
EdgeInsets padding = const EdgeInsets.all(20),
double radius = 20,
}) {
return Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(12),
borderRadius: BorderRadius.circular(radius),
color: isDark
? Colors.white.withOpacity(0.05)
: Colors.white.withOpacity(0.75),
border: Border.all(
color: isDark
? Colors.white.withOpacity(0.08)
: Colors.white.withOpacity(0.9),
width: 1,
),
boxShadow: [
BoxShadow(
color: Colors.grey.withOpacity(0.2),
spreadRadius: 2,
blurRadius: 5,
offset: const Offset(0, 3),
color: isDark
? Colors.black.withOpacity(0.3)
: Colors.black.withOpacity(0.06),
blurRadius: 24,
offset: const Offset(0, 8),
),
],
),
child: Form(
key: controller.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextFormField(
keyboardType: TextInputType.emailAddress,
controller: controller.emailController,
decoration: InputDecoration(
labelText: 'Email'.tr,
hintText: 'Your email address'.tr,
border: const OutlineInputBorder(),
),
validator: (value) => value == null ||
value.isEmpty ||
!value.contains('@') ||
!value.contains('.')
? 'Enter a valid email'.tr
: null,
),
const SizedBox(height: 16),
TextFormField(
obscureText: true,
controller: controller.passwordController,
decoration: InputDecoration(
labelText: 'Password'.tr,
hintText: 'Your password'.tr,
border: const OutlineInputBorder(),
),
validator: (value) => value == null || value.isEmpty
? 'Enter your password'.tr
: null,
),
const SizedBox(height: 24),
GetBuilder<LoginController>(
builder: (controller) => controller.isloading
? const Center(child: CircularProgressIndicator())
: ElevatedButton(
onPressed: () {
if (controller.formKey.currentState!.validate()) {
controller.login();
}
},
child: Text('Submit'.tr),
),
),
padding: padding,
child: child,
);
}
/// Pill-shaped icon badge with gradient background.
Widget _iconBadge(IconData icon, bool isDark) {
return Container(
width: 80,
height: 80,
decoration: BoxDecoration(
shape: BoxShape.circle,
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
AppColor.primaryColor,
AppColor.primaryColor.withOpacity(0.7),
],
),
boxShadow: [
BoxShadow(
color: AppColor.primaryColor.withOpacity(0.35),
blurRadius: 20,
offset: const Offset(0, 8),
),
],
),
child: Icon(icon, color: Colors.white, size: 36),
);
}
/// Section divider line.
Widget _divider(bool isDark) => Container(
height: 1,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [
Colors.transparent,
isDark
? Colors.white.withOpacity(0.1)
: Colors.black.withOpacity(0.08),
Colors.transparent,
],
),
),
);
// ─────────────────────────────────────────────────────────────────────────
// AGREEMENT PAGE
// ─────────────────────────────────────────────────────────────────────────
Widget _buildAgreementPage(BuildContext context, LoginController controller) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final textMain = isDark ? Colors.white : const Color(0xFF1A1A2E);
final textSub = isDark ? Colors.white60 : const Color(0xFF6B7280);
return Stack(
children: [
_buildBackground(context),
SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
child: Column(
children: [
// ── Header ──────────────────────────────────────────────
const SizedBox(height: 20),
_iconBadge(Icons.policy_outlined, isDark),
const SizedBox(height: 16),
Text(
"passenger agreement".tr,
textAlign: TextAlign.center,
style: AppStyle.headTitle2.copyWith(
color: textMain,
fontSize: 22,
fontWeight: FontWeight.w700,
letterSpacing: 0.3,
),
),
const SizedBox(height: 10),
// Subtitle with link
RichText(
textAlign: TextAlign.center,
text: TextSpan(
style: AppStyle.title.copyWith(
height: 1.6,
color: textSub,
fontSize: 13.5,
),
children: [
TextSpan(
text:
"To become a passenger, you must review and agree to the "
.tr,
),
TextSpan(
text: 'Terms of Use'.tr,
style: TextStyle(
decoration: TextDecoration.underline,
decorationColor: AppColor.primaryColor,
color: AppColor.primaryColor,
fontWeight: FontWeight.w600,
),
recognizer: TapGestureRecognizer()
..onTap = () {
launchUrl(Uri.parse(
'https://intaleq.xyz/intaleq/privacy_policy.php'));
},
),
TextSpan(text: " and acknowledge our Privacy Policy.".tr),
],
),
),
const SizedBox(height: 16),
_divider(isDark),
const SizedBox(height: 12),
// ── Policy scroll area ──────────────────────────────────
Expanded(
child: _glassCard(
isDark: isDark,
padding: EdgeInsets.zero,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.all(18),
child: HtmlWidget(
box.read(BoxName.lang).toString() == 'ar'
? AppInformation.privacyPolicyArabic
: AppInformation.privacyPolicy,
textStyle: TextStyle(
color: textSub,
fontSize: 13,
height: 1.7,
),
),
),
),
),
),
const SizedBox(height: 12),
_divider(isDark),
// ── Checkbox row ────────────────────────────────────────
_glassCard(
isDark: isDark,
padding:
const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
child: CheckboxListTile(
title: Text(
'I Agree'.tr,
style: AppStyle.title.copyWith(
color: textMain,
fontWeight: FontWeight.w600,
fontSize: 14,
),
),
value: controller.isAgreeTerms,
onChanged: (value) => controller.changeAgreeTerm(),
activeColor: AppColor.primaryColor,
checkColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6)),
controlAffinity: ListTileControlAffinity.leading,
contentPadding: EdgeInsets.zero,
dense: true,
),
),
const SizedBox(height: 12),
// ── CTA Button ──────────────────────────────────────────
_buildPrimaryButton(
label: 'Continue'.tr,
enabled: controller.isAgreeTerms,
onPressed: controller.isAgreeTerms
? () => controller.saveAgreementTerms()
: () {},
isDark: isDark,
),
const SizedBox(height: 8),
],
),
),
),
],
);
}
// ─────────────────────────────────────────────────────────────────────────
// EMAIL / PASSWORD FORM
// ─────────────────────────────────────────────────────────────────────────
Widget buildEmailPasswordForm(
BuildContext context, LoginController controller) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final textMain = isDark ? Colors.white : const Color(0xFF1A1A2E);
final textSub = isDark ? Colors.white60 : const Color(0xFF6B7280);
return Stack(
children: [
_buildBackground(context),
SafeArea(
child: Center(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 32),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Logo / badge
Center(child: _iconBadge(Icons.lock_outline_rounded, isDark)),
const SizedBox(height: 20),
Text(
'Welcome Back'.tr,
textAlign: TextAlign.center,
style: AppStyle.headTitle2.copyWith(
color: textMain,
fontSize: 26,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 6),
Text(
'Sign in to continue'.tr,
textAlign: TextAlign.center,
style:
AppStyle.title.copyWith(color: textSub, fontSize: 14),
),
const SizedBox(height: 32),
_glassCard(
isDark: isDark,
padding: const EdgeInsets.all(24),
child: Form(
key: controller.formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// Email field
_buildTextField(
controller: controller.emailController,
label: 'Email'.tr,
hint: 'Your email address'.tr,
icon: Icons.email_outlined,
isDark: isDark,
keyboardType: TextInputType.emailAddress,
validator: (value) => value == null ||
value.isEmpty ||
!value.contains('@') ||
!value.contains('.')
? 'Enter a valid email'.tr
: null,
),
const SizedBox(height: 16),
// Password field
_buildTextField(
controller: controller.passwordController,
label: 'Password'.tr,
hint: 'Your password'.tr,
icon: Icons.lock_outline,
isDark: isDark,
obscureText: true,
validator: (value) => value == null || value.isEmpty
? 'Enter your password'.tr
: null,
),
const SizedBox(height: 28),
GetBuilder<LoginController>(
builder: (controller) => controller.isloading
? Center(
child: SizedBox(
width: 28,
height: 28,
child: CircularProgressIndicator(
color: AppColor.primaryColor,
strokeWidth: 2.5,
),
),
)
: _buildPrimaryButton(
label: 'Submit'.tr,
enabled: true,
isDark: isDark,
onPressed: () {
if (controller.formKey.currentState!
.validate()) {
controller.login();
}
},
),
),
],
),
),
),
],
),
),
),
),
],
);
}
// ─────────────────────────────────────────────────────────────────────────
// LOCATION PERMISSION PAGE
// ─────────────────────────────────────────────────────────────────────────
Widget _buildLocationPermissionDialog(
BuildContext context, LoginController controller) {
final isDark = Theme.of(context).brightness == Brightness.dark;
final textMain = isDark ? Colors.white : const Color(0xFF1A1A2E);
final textSub = isDark ? Colors.white60 : const Color(0xFF6B7280);
return Stack(
children: [
_buildBackground(context),
SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 24),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Spacer(flex: 2),
// Animated-look stacked circles around icon
Stack(
alignment: Alignment.center,
children: [
// Outer glow ring
Container(
width: 140,
height: 140,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColor.primaryColor.withOpacity(0.08),
border: Border.all(
color: AppColor.primaryColor.withOpacity(0.2),
width: 1,
),
),
),
// Mid ring
Container(
width: 108,
height: 108,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: AppColor.primaryColor.withOpacity(0.12),
border: Border.all(
color: AppColor.primaryColor.withOpacity(0.3),
width: 1,
),
),
),
// Core badge
_iconBadge(Icons.location_on_outlined, isDark),
],
),
const SizedBox(height: 36),
Text(
'Enable Location Access'.tr,
style: AppStyle.headTitle2.copyWith(
color: textMain,
fontSize: 24,
fontWeight: FontWeight.w700,
letterSpacing: 0.2,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 14),
Text(
'We need your location to find nearby drivers for pickups and drop-offs.'
.tr,
textAlign: TextAlign.center,
style: AppStyle.title.copyWith(
color: textSub,
fontSize: 14.5,
height: 1.6,
),
),
const SizedBox(height: 40),
// Feature chips row
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
_featureChip(
Icons.speed_outlined, 'Fast matching'.tr, isDark),
const SizedBox(width: 10),
_featureChip(Icons.shield_outlined, 'Secure'.tr, isDark),
const SizedBox(width: 10),
_featureChip(Icons.near_me_outlined, 'Nearby'.tr, isDark),
],
),
const Spacer(flex: 3),
_buildPrimaryButton(
label: 'Next'.tr,
enabled: true,
isDark: isDark,
onPressed: () async =>
await controller.getLocationPermission(),
),
const SizedBox(height: 16),
],
),
),
),
],
);
}
// ─────────────────────────────────────────────────────────────────────────
// SHARED SMALL WIDGETS
// ─────────────────────────────────────────────────────────────────────────
/// Reusable styled text field.
Widget _buildTextField({
required TextEditingController controller,
required String label,
required String hint,
required IconData icon,
required bool isDark,
bool obscureText = false,
TextInputType? keyboardType,
String? Function(String?)? validator,
}) {
final fill = isDark ? Colors.white.withOpacity(0.05) : Colors.white;
final border =
isDark ? Colors.white.withOpacity(0.1) : const Color(0xFFE5E7EB);
return TextFormField(
controller: controller,
obscureText: obscureText,
keyboardType: keyboardType,
style: TextStyle(
color: isDark ? Colors.white : const Color(0xFF1A1A2E),
fontSize: 14.5,
),
decoration: InputDecoration(
labelText: label,
hintText: hint,
prefixIcon: Icon(icon,
size: 20, color: isDark ? Colors.white38 : const Color(0xFF9CA3AF)),
labelStyle: TextStyle(
color: isDark ? Colors.white38 : const Color(0xFF9CA3AF),
fontSize: 13.5,
),
hintStyle: TextStyle(
color: isDark ? Colors.white24 : const Color(0xFFD1D5DB),
),
filled: true,
fillColor: fill,
contentPadding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 16),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide(color: border, width: 1),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: BorderSide(color: AppColor.primaryColor, width: 1.5),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: const BorderSide(color: Color(0xFFEF4444), width: 1),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(14),
borderSide: const BorderSide(color: Color(0xFFEF4444), width: 1.5),
),
),
validator: validator,
);
}
/// Full-width gradient primary button.
Widget _buildPrimaryButton({
required String label,
required bool enabled,
required VoidCallback onPressed,
required bool isDark,
}) {
return SizedBox(
width: double.infinity,
height: 54,
child: DecoratedBox(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
gradient: enabled
? LinearGradient(
begin: Alignment.centerLeft,
end: Alignment.centerRight,
colors: [
AppColor.primaryColor,
AppColor.primaryColor.withOpacity(0.8),
],
)
: null,
color: enabled
? null
: (isDark ? Colors.white12 : const Color(0xFFE5E7EB)),
boxShadow: enabled
? [
BoxShadow(
color: AppColor.primaryColor.withOpacity(0.32),
blurRadius: 16,
offset: const Offset(0, 6),
)
]
: null,
),
child: ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: Colors.transparent,
shadowColor: Colors.transparent,
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
),
child: Text(
label,
style: TextStyle(
color: enabled
? Colors.white
: (isDark ? Colors.white38 : const Color(0xFF9CA3AF)),
fontWeight: FontWeight.w600,
fontSize: 15,
letterSpacing: 0.4,
),
),
),
),
);
}
Widget _buildLocationPermissionDialog(LoginController controller) {
return Padding(
padding: const EdgeInsets.all(32),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
/// Small chip used on location page.
Widget _featureChip(IconData icon, String text, bool isDark) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(30),
color: isDark
? Colors.white.withOpacity(0.06)
: Colors.white.withOpacity(0.8),
border: Border.all(
color: isDark
? Colors.white.withOpacity(0.1)
: Colors.black.withOpacity(0.07),
width: 1,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.location_on, size: 60, color: AppColor.primaryColor),
const SizedBox(height: 20),
Icon(icon, size: 14, color: AppColor.primaryColor),
const SizedBox(width: 5),
Text(
'Enable Location Access'.tr,
style: AppStyle.headTitle2,
textAlign: TextAlign.center,
text,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
color: isDark ? Colors.white70 : const Color(0xFF374151),
),
),
const SizedBox(height: 10),
Text(
'We need your location to find nearby drivers for pickups and drop-offs.'
.tr,
textAlign: TextAlign.center,
style: AppStyle.title,
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: () async => await controller.getLocationPermission(),
child: Text('Next'.tr),
// child: Text('Allow Location Access'.tr),
),
// TextButton(
// onPressed: () => openAppSettings(),
// child: Text('Open Settings'.tr),
// ),
],
),
);

File diff suppressed because it is too large Load Diff

View File

@@ -1,102 +1,360 @@
import 'package:Intaleq/constant/colors.dart';
import 'package:Intaleq/constant/style.dart';
// ignore: unused_import
import 'package:Intaleq/controller/functions/launch.dart';
import 'package:Intaleq/views/widgets/my_scafold.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_font_icons/flutter_font_icons.dart';
import 'package:get/get.dart';
import '../../../controller/functions/tts.dart';
import '../../../controller/home/contact_us_controller.dart';
import '../../widgets/elevated_btn.dart';
class ContactUsPage extends StatelessWidget {
ContactUsPage({super.key});
@override
Widget build(BuildContext context) {
Get.put(ContactUsController());
return GetBuilder<ContactUsController>(builder: (controller) {
return MyScafolld(
title: "Contact Us".tr,
body: [
Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
// crossAxisAlignment: CrossAxisAlignment.center,
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
decoration: AppStyle.boxDecoration1,
child: Column(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(15),
child: Image.asset('assets/images/logo.gif')),
IconButton(
onPressed: () async {
Get.find<TextToSpeechController>().speakText(
'Intaleq is the safest and most reliable ride-sharing app designed especially for passengers in Syria. We provide a comfortable, respectful, and affordable riding experience with features that prioritize your safety and convenience. Our trusted captains are verified, insured, and supported by regular car maintenance carried out by top engineers. We also offer on-road support services to make sure every trip is smooth and worry-free. With Intaleq, you enjoy quality, safety, and peace of mind—every time you ride.'
.tr);
},
icon: const Icon(Icons.headphones),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Intaleq is the safest and most reliable ride-sharing app designed especially for passengers in Syria. We provide a comfortable, respectful, and affordable riding experience with features that prioritize your safety and convenience. Our trusted captains are verified, insured, and supported by regular car maintenance carried out by top engineers. We also offer on-road support services to make sure every trip is smooth and worry-free. With Intaleq, you enjoy quality, safety, and peace of mind—every time you ride.'
.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
],
),
),
const SizedBox(
height: 30,
),
Container(
decoration: AppStyle.boxDecoration1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
"You can contact us during working hours from 10:00 - 16:00."
.tr,
style: AppStyle.title,
textAlign: TextAlign.center,
),
),
),
InkWell(
onTap: () => controller.showContactDialog(context),
child: const Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Icon(
Icons.phone,
color: AppColor.blueColor,
),
Icon(
FontAwesome.whatsapp,
color: AppColor.greenColor,
),
Icon(
Icons.email,
color: AppColor.redColor,
),
],
),
),
const SizedBox(
height: 30,
)
],
final controller = Get.put(ContactUsController());
final isDark = Theme.of(context).brightness == Brightness.dark;
return MyScafolld(
title: "Contact Us".tr,
isleading: true,
body: [
// Background subtle gradient/shape
Positioned.fill(
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: isDark
? [const Color(0xFF0D0D14), const Color(0xFF161622)]
: [const Color(0xFFF8F9FF), const Color(0xFFEFF1FB)],
),
)
],
isleading: true);
});
),
),
),
SafeArea(
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// ── Hero Section ──────────────────────────────────────────
_buildHeroSection(isDark),
const SizedBox(height: 24),
// ── Availability Status ────────────────────────────────────
_buildAvailabilityStatus(controller, isDark),
const SizedBox(height: 24),
// ── Support Actions ────────────────────────────────────────
Text(
"Reach out to us via".tr,
style: AppStyle.title.copyWith(
fontWeight: FontWeight.bold,
fontSize: 16,
color: isDark ? Colors.white70 : Colors.black54,
),
),
const SizedBox(height: 12),
_buildContactCards(controller, isDark),
const SizedBox(height: 32),
// ── About Section ──────────────────────────────────────────
_buildAboutSection(isDark),
const SizedBox(height: 40),
],
),
),
),
],
);
}
Widget _buildHeroSection(bool isDark) {
return Container(
padding: const EdgeInsets.all(24),
decoration: BoxDecoration(
color: isDark ? Colors.white.withOpacity(0.05) : Colors.white,
borderRadius: BorderRadius.circular(24),
border: Border.all(
color: isDark ? Colors.white12 : Colors.black.withOpacity(0.05),
),
boxShadow: [
BoxShadow(
color: isDark ? Colors.black26 : Colors.black.withOpacity(0.03),
blurRadius: 20,
offset: const Offset(0, 10),
)
],
),
child: Column(
children: [
Container(
padding: const EdgeInsets.all(4),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isDark ? Colors.white10 : Colors.white,
border: Border.all(color: AppColor.primaryColor.withOpacity(0.2)),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(50),
child: Image.asset('assets/images/logo.gif', height: 80),
),
),
const SizedBox(height: 16),
Text(
"Intaleq Support".tr,
style: AppStyle.headTitle2.copyWith(
fontSize: 22,
fontWeight: FontWeight.bold,
color: isDark ? Colors.white : AppColor.primaryColor,
),
),
const SizedBox(height: 4),
Text(
"We're here to help you 24/7".tr,
style: TextStyle(
color: isDark ? Colors.white54 : Colors.black45,
fontSize: 14,
),
),
],
),
);
}
Widget _buildAvailabilityStatus(ContactUsController controller, bool isDark) {
final isOpen = controller.isWorkTime;
return Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
decoration: BoxDecoration(
color: (isOpen ? AppColor.greenColor : Colors.orange).withOpacity(0.1),
borderRadius: BorderRadius.circular(16),
border: Border.all(
color: (isOpen ? AppColor.greenColor : Colors.orange).withOpacity(0.2),
),
),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(8),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: isOpen ? AppColor.greenColor : Colors.orange,
),
child: Icon(
isOpen ? Icons.check_circle_outline : Icons.access_time,
color: Colors.white,
size: 18,
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
isOpen ? "Support is currently Online".tr : "Support is Away".tr,
style: TextStyle(
fontWeight: FontWeight.bold,
color: isOpen ? AppColor.greenColor : Colors.orange,
),
),
Text(
"${"Working Hours:".tr} ${controller.workHoursString}",
style: TextStyle(
fontSize: 12,
color: isDark ? Colors.white60 : Colors.black54,
),
),
],
),
),
],
),
);
}
Widget _buildContactCards(ContactUsController controller, bool isDark) {
return Column(
children: [
_ContactCard(
title: "Voice Call".tr,
subtitle: "Direct talk with our team".tr,
icon: Icons.phone_in_talk_outlined,
color: AppColor.primaryColor,
isDark: isDark,
enabled: controller.isWorkTime,
onTap: controller.makeCall,
trailing: controller.isWorkTime ? null : Icon(Icons.lock_clock_outlined, size: 20, color: isDark ? Colors.white24 : Colors.black26),
),
const SizedBox(height: 12),
_ContactCard(
title: "WhatsApp".tr,
subtitle: "Chat with us anytime".tr,
icon: FontAwesome.whatsapp,
color: AppColor.greenColor,
isDark: isDark,
onTap: controller.sendWhatsApp,
),
const SizedBox(height: 12),
_ContactCard(
title: "Email Support".tr,
subtitle: "For official inquiries".tr,
icon: Icons.alternate_email_outlined,
color: AppColor.redColor,
isDark: isDark,
onTap: controller.sendEmail,
),
],
);
}
Widget _buildAboutSection(bool isDark) {
return Container(
padding: const EdgeInsets.all(20),
decoration: BoxDecoration(
color: isDark ? Colors.white.withOpacity(0.02) : Colors.black.withOpacity(0.02),
borderRadius: BorderRadius.circular(24),
border: Border.all(color: isDark ? Colors.white10 : Colors.black12),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"About Intaleq".tr,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
color: isDark ? Colors.white : Colors.black87,
),
),
IconButton(
onPressed: () {
Get.find<TextToSpeechController>().speakText(
'Intaleq is the safest and most reliable ride-sharing app designed especially for passengers in Syria. We provide a comfortable, respectful, and affordable riding experience with features that prioritize your safety and convenience.'
.tr,
);
},
icon: Icon(Icons.volume_up_outlined, color: AppColor.primaryColor),
),
],
),
const SizedBox(height: 12),
Text(
'Intaleq is the safest and most reliable ride-sharing app designed especially for passengers in Syria. We provide a comfortable, respectful, and affordable riding experience with features that prioritize your safety and convenience. Our trusted captains are verified, insured, and supported by regular car maintenance carried out by top engineers. We also offer on-road support services to make sure every trip is smooth and worry-free. With Intaleq, you enjoy quality, safety, and peace of mind—every time you ride.'
.tr,
style: TextStyle(
color: isDark ? Colors.white70 : Colors.black54,
fontSize: 14,
height: 1.6,
),
),
],
),
);
}
}
class _ContactCard extends StatelessWidget {
final String title;
final String subtitle;
final IconData icon;
final Color color;
final bool isDark;
final bool enabled;
final VoidCallback onTap;
final Widget? trailing;
const _ContactCard({
required this.title,
required this.subtitle,
required this.icon,
required this.color,
required this.isDark,
this.enabled = true,
required this.onTap,
this.trailing,
});
@override
Widget build(BuildContext context) {
return Material(
color: Colors.transparent,
child: InkWell(
onTap: enabled ? onTap : null,
borderRadius: BorderRadius.circular(20),
child: Container(
padding: const EdgeInsets.all(16),
decoration: BoxDecoration(
color: enabled
? (isDark ? Colors.white.withOpacity(0.05) : Colors.white)
: (isDark ? Colors.white.withOpacity(0.02) : Colors.grey.withOpacity(0.05)),
borderRadius: BorderRadius.circular(20),
border: Border.all(
color: enabled
? (isDark ? Colors.white12 : Colors.black.withOpacity(0.05))
: Colors.transparent,
),
boxShadow: enabled ? [
BoxShadow(
color: isDark ? Colors.black12 : Colors.black.withOpacity(0.02),
blurRadius: 10,
offset: const Offset(0, 4),
)
] : null,
),
child: Row(
children: [
Container(
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: (enabled ? color : Colors.grey).withOpacity(0.12),
borderRadius: BorderRadius.circular(14),
),
child: Icon(icon, color: enabled ? color : Colors.grey, size: 24),
),
const SizedBox(width: 16),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
color: enabled
? (isDark ? Colors.white : Colors.black87)
: Colors.grey,
),
),
Text(
subtitle,
style: TextStyle(
fontSize: 13,
color: isDark ? Colors.white38 : Colors.black38,
),
),
],
),
),
trailing ?? Icon(
Icons.arrow_forward_ios,
size: 14,
color: isDark ? Colors.white24 : Colors.black12,
),
],
),
),
),
);
}
}

View File

@@ -14,6 +14,7 @@ import '../../../constant/links.dart';
import '../../../controller/functions/crud.dart';
import '../../../controller/functions/tts.dart';
import '../../../controller/home/decode_polyline_isolate.dart';
import '../../../env/env.dart';
import '../../../main.dart';
import '../../../print.dart';
import 'dart:ui';
@@ -719,7 +720,7 @@ class NavigationController extends GetxController
try {
// 1. Try SaaS first
http.Response response = await http.get(saasUri, headers: {
'x-api-key': 'intaleq_secret_2026',
'x-api-key': Env.mapSaasKey,
});
bool useSaaS = response.statusCode == 200;
@@ -947,7 +948,8 @@ class NavigationController extends GetxController
final destBytes = await rootBundle.load('assets/images/b.png');
await mapController!.addImage('car_icon', carBytes.buffer.asUint8List());
await mapController!.addImage('start_icon', startBytes.buffer.asUint8List());
await mapController!
.addImage('start_icon', startBytes.buffer.asUint8List());
await mapController!.addImage('dest_icon', destBytes.buffer.asUint8List());
}