987 lines
33 KiB
Dart
987 lines
33 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
import '../../core/controllers/theme_controller.dart';
|
|
import '../../core/controllers/locale_controller.dart';
|
|
import '../../core/services/auth_service.dart';
|
|
import '../../core/services/api_service.dart';
|
|
import '../../core/utils/snackbar_util.dart';
|
|
import '../../l10n/app_localizations.dart';
|
|
|
|
String _themeModeLabel(AppLocalizations l10n) {
|
|
switch (ThemeController.to.themeMode) {
|
|
case ThemeMode.light:
|
|
return l10n.themeLight;
|
|
case ThemeMode.dark:
|
|
return l10n.themeDark;
|
|
case ThemeMode.system:
|
|
return l10n.themeSystem;
|
|
}
|
|
}
|
|
|
|
class SettingsPage extends StatelessWidget {
|
|
const SettingsPage({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final l10n = AppLocalizations.of(context);
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(l10n.settingsTitle),
|
|
),
|
|
body: ListView(
|
|
padding: EdgeInsets.all(16.w),
|
|
children: [
|
|
_buildSectionHeader(context, l10n.sectionAppearance),
|
|
_buildThemeSettings(context, l10n),
|
|
SizedBox(height: 24.h),
|
|
_buildSectionHeader(context, l10n.sectionLanguage),
|
|
_buildLanguageSettings(context, l10n),
|
|
SizedBox(height: 24.h),
|
|
_buildSectionHeader(context, l10n.sectionAccount),
|
|
_buildAccountSettings(context, l10n),
|
|
SizedBox(height: 24.h),
|
|
Obx(() {
|
|
final user = AuthService.to.currentUser.value;
|
|
if (user?.role == 'manager') {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
_buildSectionHeader(context, l10n.sectionPaymentSettings),
|
|
_buildPaymentSettings(context, l10n),
|
|
SizedBox(height: 24.h),
|
|
],
|
|
);
|
|
}
|
|
return const SizedBox.shrink();
|
|
}),
|
|
_buildSectionHeader(context, l10n.sectionNotifications),
|
|
_buildNotificationSettings(context, l10n),
|
|
SizedBox(height: 24.h),
|
|
_buildSectionHeader(context, l10n.sectionAbout),
|
|
_buildAboutSettings(context, l10n),
|
|
SizedBox(height: 32.h),
|
|
_buildLogoutButton(context, l10n),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSectionHeader(BuildContext context, String title) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
return Padding(
|
|
padding: EdgeInsets.only(left: 8.w, bottom: 12.h),
|
|
child: Text(
|
|
title,
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: scheme.onSurfaceVariant,
|
|
letterSpacing: 0.5,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildLanguageSettings(BuildContext context, AppLocalizations l10n) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
return Card(
|
|
child: Obx(
|
|
() => ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.secondaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.language_rounded,
|
|
color: scheme.onSecondaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.languageTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
LocaleController.to.currentLanguageLabel(l10n),
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w),
|
|
onTap: () => _showLanguageDialog(context, l10n),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showLanguageDialog(BuildContext context, AppLocalizations l10n) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
Get.dialog(
|
|
Obx(
|
|
() {
|
|
final code = LocaleController.to.locale.value.languageCode;
|
|
return AlertDialog(
|
|
title: Text(l10n.chooseLanguageTitle),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
RadioListTile<String>(
|
|
title: Text(l10n.languageEnglish),
|
|
value: 'en',
|
|
groupValue: code,
|
|
onChanged: (v) async {
|
|
if (v != null) {
|
|
await LocaleController.to.setLocale(Locale(v));
|
|
Get.back();
|
|
}
|
|
},
|
|
activeColor: scheme.primary,
|
|
),
|
|
RadioListTile<String>(
|
|
title: Text(l10n.languageTelugu),
|
|
value: 'te',
|
|
groupValue: code,
|
|
onChanged: (v) async {
|
|
if (v != null) {
|
|
await LocaleController.to.setLocale(Locale(v));
|
|
Get.back();
|
|
}
|
|
},
|
|
activeColor: scheme.primary,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
},
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildThemeSettings(BuildContext context, AppLocalizations l10n) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
return Card(
|
|
child: Column(
|
|
children: [
|
|
Obx(
|
|
() => ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.primaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
ThemeController.to.getThemeIcon(),
|
|
color: scheme.onPrimaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.themeTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
_themeModeLabel(l10n),
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w),
|
|
onTap: () => _showThemeDialog(context, l10n),
|
|
),
|
|
),
|
|
Divider(height: 1.h, indent: 72.w),
|
|
Obx(
|
|
() => SwitchListTile(
|
|
secondary: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.tertiaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.brightness_6_rounded,
|
|
color: scheme.onTertiaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.darkModeTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
l10n.darkModeSubtitle,
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
value: ThemeController.to.isDarkMode,
|
|
onChanged: (value) {
|
|
ThemeController.to.toggleTheme();
|
|
},
|
|
activeColor: scheme.primary,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildAccountSettings(BuildContext context, AppLocalizations l10n) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
return Card(
|
|
child: Column(
|
|
children: [
|
|
Obx(
|
|
() {
|
|
final user = AuthService.to.currentUser.value;
|
|
return ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.primaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.person_rounded,
|
|
color: scheme.onPrimaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
user?.fullName ?? 'User',
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
user?.mobileNumber ?? '',
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w),
|
|
onTap: () {
|
|
SnackbarUtil.showInfo(l10n.profileComingSoon);
|
|
},
|
|
);
|
|
},
|
|
),
|
|
Divider(height: 1.h, indent: 72.w),
|
|
ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.secondaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.lock_rounded,
|
|
color: scheme.onSecondaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.changePasswordTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
l10n.changePasswordSubtitle,
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w),
|
|
onTap: () {
|
|
SnackbarUtil.showInfo(l10n.changePasswordComingSoon);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildNotificationSettings(
|
|
BuildContext context, AppLocalizations l10n) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
return Card(
|
|
child: Column(
|
|
children: [
|
|
SwitchListTile(
|
|
secondary: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.errorContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.notifications_rounded,
|
|
color: scheme.onErrorContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.pushNotificationsTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
l10n.pushNotificationsSubtitle,
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
value: true,
|
|
onChanged: (value) {
|
|
SnackbarUtil.showInfo(l10n.notificationComingSoon);
|
|
},
|
|
activeColor: scheme.primary,
|
|
),
|
|
Divider(height: 1.h, indent: 72.w),
|
|
SwitchListTile(
|
|
secondary: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.tertiaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.payment_rounded,
|
|
color: scheme.onTertiaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.paymentRemindersTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
l10n.paymentRemindersSubtitle,
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
value: true,
|
|
onChanged: (value) {
|
|
SnackbarUtil.showInfo(l10n.notificationComingSoon);
|
|
},
|
|
activeColor: scheme.primary,
|
|
),
|
|
Divider(height: 1.h, indent: 72.w),
|
|
SwitchListTile(
|
|
secondary: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.primaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.casino_rounded,
|
|
color: scheme.onPrimaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.drawNotificationsTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
l10n.drawNotificationsSubtitle,
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
value: true,
|
|
onChanged: (value) {
|
|
SnackbarUtil.showInfo(l10n.notificationComingSoon);
|
|
},
|
|
activeColor: scheme.primary,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildPaymentSettings(BuildContext context, AppLocalizations l10n) {
|
|
final apiService = ApiService();
|
|
final scheme = Theme.of(context).colorScheme;
|
|
|
|
return Card(
|
|
child: Column(
|
|
children: [
|
|
FutureBuilder<Map<String, dynamic>>(
|
|
future: apiService.get('/payments/phonepe/settings/upi'),
|
|
builder: (ctx, snapshot) {
|
|
if (snapshot.connectionState == ConnectionState.waiting) {
|
|
return ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.secondaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.account_balance_rounded,
|
|
color: scheme.onSecondaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.upiIdTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
l10n.loading,
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
);
|
|
}
|
|
|
|
final upiId = snapshot.data?['data']?['upi_id'] ?? l10n.notConfigured;
|
|
final isConfigured = snapshot.data?['data']?['is_configured'] ?? false;
|
|
|
|
return ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: isConfigured
|
|
? scheme.secondaryContainer
|
|
: scheme.tertiaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.account_balance_rounded,
|
|
color: isConfigured
|
|
? scheme.onSecondaryContainer
|
|
: scheme.onTertiaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Row(
|
|
children: [
|
|
Text(
|
|
l10n.upiIdTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
if (isConfigured) ...[
|
|
SizedBox(width: 8.w),
|
|
Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.h),
|
|
decoration: BoxDecoration(
|
|
color: scheme.primaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Text(
|
|
l10n.active,
|
|
style: TextStyle(
|
|
fontSize: 10.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: scheme.onPrimaryContainer,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
subtitle: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
SizedBox(height: 4.h),
|
|
SelectableText(
|
|
upiId.toString(),
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: isConfigured
|
|
? scheme.onSecondaryContainer
|
|
: scheme.onTertiaryContainer,
|
|
fontFamily: 'monospace',
|
|
),
|
|
),
|
|
if (!isConfigured) ...[
|
|
SizedBox(height: 4.h),
|
|
Text(
|
|
l10n.configureBackend,
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
color: scheme.tertiary,
|
|
fontStyle: FontStyle.italic,
|
|
),
|
|
),
|
|
],
|
|
],
|
|
),
|
|
trailing: isConfigured
|
|
? IconButton(
|
|
onPressed: () {
|
|
Clipboard.setData(ClipboardData(text: upiId.toString()));
|
|
SnackbarUtil.showSuccess(l10n.upiCopiedClipboard);
|
|
},
|
|
icon: Icon(
|
|
Icons.copy_rounded,
|
|
size: 20.w,
|
|
color: scheme.secondary,
|
|
),
|
|
tooltip: l10n.copyUpiIdTooltip,
|
|
)
|
|
: Icon(
|
|
Icons.warning_rounded,
|
|
size: 20.w,
|
|
color: scheme.tertiary,
|
|
),
|
|
onTap: () => _showUPIInfoDialog(context, l10n, upiId.toString(), isConfigured),
|
|
);
|
|
},
|
|
),
|
|
Divider(height: 1.h, indent: 72.w),
|
|
ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.primaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.payment_rounded,
|
|
color: scheme.onPrimaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.paymentStatisticsTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
l10n.paymentStatisticsSubtitle,
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w),
|
|
onTap: () {
|
|
SnackbarUtil.showInfo(l10n.paymentStatsComingSoon);
|
|
},
|
|
),
|
|
Divider(height: 1.h, indent: 72.w),
|
|
ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.primaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.currency_rupee_rounded,
|
|
color: scheme.onPrimaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.transactionFeesTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
l10n.transactionFeesSubtitle,
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
color: scheme.primary,
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
trailing: Container(
|
|
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 4.h),
|
|
decoration: BoxDecoration(
|
|
color: scheme.primaryContainer,
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
),
|
|
child: Text(
|
|
l10n.free,
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
fontWeight: FontWeight.w800,
|
|
color: scheme.onPrimaryContainer,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showUPIInfoDialog(
|
|
BuildContext context,
|
|
AppLocalizations l10n,
|
|
String upiId,
|
|
bool isConfigured,
|
|
) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
Get.dialog(
|
|
AlertDialog(
|
|
title: Row(
|
|
children: [
|
|
Icon(
|
|
Icons.account_balance_rounded,
|
|
color: scheme.secondary,
|
|
size: 24.w,
|
|
),
|
|
SizedBox(width: 12.w),
|
|
Expanded(child: Text(l10n.upiPaymentSettingsTitle)),
|
|
],
|
|
),
|
|
content: SingleChildScrollView(
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
l10n.currentUpiId,
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: scheme.onSurfaceVariant,
|
|
),
|
|
),
|
|
SizedBox(height: 8.h),
|
|
Container(
|
|
width: double.infinity,
|
|
padding: EdgeInsets.all(12.w),
|
|
decoration: BoxDecoration(
|
|
color: isConfigured
|
|
? scheme.secondaryContainer
|
|
: scheme.tertiaryContainer,
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
border: Border.all(
|
|
color: isConfigured
|
|
? scheme.outlineVariant
|
|
: scheme.tertiary.withOpacity(0.4),
|
|
),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: SelectableText(
|
|
upiId,
|
|
style: TextStyle(
|
|
fontSize: 16.sp,
|
|
fontWeight: FontWeight.w700,
|
|
color: isConfigured
|
|
? scheme.onSecondaryContainer
|
|
: scheme.onTertiaryContainer,
|
|
fontFamily: 'monospace',
|
|
),
|
|
),
|
|
),
|
|
if (isConfigured)
|
|
IconButton(
|
|
onPressed: () {
|
|
Clipboard.setData(ClipboardData(text: upiId));
|
|
SnackbarUtil.showSuccess(l10n.copied);
|
|
},
|
|
icon: Icon(
|
|
Icons.copy_rounded,
|
|
size: 20.w,
|
|
color: scheme.secondary,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
if (!isConfigured) ...[
|
|
SizedBox(height: 16.h),
|
|
Container(
|
|
padding: EdgeInsets.all(12.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.tertiaryContainer,
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
),
|
|
child: Row(
|
|
children: [
|
|
Icon(
|
|
Icons.warning_rounded,
|
|
color: scheme.onTertiaryContainer,
|
|
size: 20.w,
|
|
),
|
|
SizedBox(width: 8.w),
|
|
Expanded(
|
|
child: Text(
|
|
l10n.upiNotConfiguredMessage,
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
color: scheme.onTertiaryContainer,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
SizedBox(height: 16.h),
|
|
const Divider(),
|
|
SizedBox(height: 16.h),
|
|
Text(
|
|
l10n.howToUpdateUpi,
|
|
style: TextStyle(
|
|
fontSize: 14.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: scheme.onSurfaceVariant,
|
|
),
|
|
),
|
|
SizedBox(height: 12.h),
|
|
_buildInfoStep(context, '1', l10n.stepOpenEnv),
|
|
_buildInfoStep(context, '2', l10n.stepUpdatePhonepe),
|
|
_buildInfoStep(context, '3', l10n.stepRestartBackend),
|
|
_buildInfoStep(context, '4', l10n.stepRefreshScreen),
|
|
SizedBox(height: 16.h),
|
|
Container(
|
|
padding: EdgeInsets.all(12.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.primaryContainer,
|
|
borderRadius: BorderRadius.circular(8.r),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Icon(
|
|
Icons.lightbulb_rounded,
|
|
color: scheme.onPrimaryContainer,
|
|
size: 18.w,
|
|
),
|
|
SizedBox(width: 8.w),
|
|
Text(
|
|
l10n.proTipTitle,
|
|
style: TextStyle(
|
|
fontSize: 13.sp,
|
|
fontWeight: FontWeight.w600,
|
|
color: scheme.onPrimaryContainer,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
SizedBox(height: 8.h),
|
|
Text(
|
|
l10n.proTipBody,
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
color: scheme.onPrimaryContainer.withOpacity(0.92),
|
|
height: 1.4,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Get.back(),
|
|
child: Text(l10n.close),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildInfoStep(BuildContext context, String number, String text) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
return Padding(
|
|
padding: EdgeInsets.only(bottom: 8.h),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Container(
|
|
width: 24.w,
|
|
height: 24.w,
|
|
decoration: BoxDecoration(
|
|
color: scheme.secondaryContainer,
|
|
shape: BoxShape.circle,
|
|
),
|
|
child: Center(
|
|
child: Text(
|
|
number,
|
|
style: TextStyle(
|
|
fontSize: 12.sp,
|
|
fontWeight: FontWeight.w700,
|
|
color: scheme.onSecondaryContainer,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
SizedBox(width: 12.w),
|
|
Expanded(
|
|
child: Padding(
|
|
padding: EdgeInsets.only(top: 2.h),
|
|
child: Text(
|
|
text,
|
|
style: TextStyle(
|
|
fontSize: 13.sp,
|
|
color: scheme.onSurfaceVariant,
|
|
height: 1.4,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildAboutSettings(BuildContext context, AppLocalizations l10n) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
return Card(
|
|
child: Column(
|
|
children: [
|
|
ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.primaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.info_rounded,
|
|
color: scheme.onPrimaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.appVersionTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: Text(
|
|
'1.0.0',
|
|
style: TextStyle(fontSize: 14.sp),
|
|
),
|
|
),
|
|
Divider(height: 1.h, indent: 72.w),
|
|
ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.primaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.privacy_tip_rounded,
|
|
color: scheme.onPrimaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.privacyPolicyTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w),
|
|
onTap: () {
|
|
SnackbarUtil.showInfo(l10n.privacyComingSoon);
|
|
},
|
|
),
|
|
Divider(height: 1.h, indent: 72.w),
|
|
ListTile(
|
|
leading: Container(
|
|
padding: EdgeInsets.all(10.w),
|
|
decoration: BoxDecoration(
|
|
color: scheme.secondaryContainer,
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
child: Icon(
|
|
Icons.description_rounded,
|
|
color: scheme.onSecondaryContainer,
|
|
size: 24.w,
|
|
),
|
|
),
|
|
title: Text(
|
|
l10n.termsOfServiceTitle,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
trailing: Icon(Icons.arrow_forward_ios_rounded, size: 16.w),
|
|
onTap: () {
|
|
SnackbarUtil.showInfo(l10n.termsComingSoon);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildLogoutButton(BuildContext context, AppLocalizations l10n) {
|
|
return SizedBox(
|
|
width: double.infinity,
|
|
height: 52.h,
|
|
child: ElevatedButton.icon(
|
|
onPressed: () => _showLogoutDialog(context, l10n),
|
|
icon: Icon(Icons.logout_rounded, size: 20.w),
|
|
label: Text(
|
|
l10n.logout,
|
|
style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.w600),
|
|
),
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Theme.of(context).colorScheme.error,
|
|
foregroundColor: Theme.of(context).colorScheme.onError,
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(12.r),
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showThemeDialog(BuildContext context, AppLocalizations l10n) {
|
|
final scheme = Theme.of(context).colorScheme;
|
|
Get.dialog(
|
|
AlertDialog(
|
|
title: Text(l10n.chooseThemeTitle),
|
|
content: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
RadioListTile<ThemeMode>(
|
|
title: Text(l10n.themeLight),
|
|
value: ThemeMode.light,
|
|
groupValue: ThemeController.to.themeMode,
|
|
onChanged: (value) {
|
|
ThemeController.to.setLightTheme();
|
|
Get.back();
|
|
},
|
|
activeColor: scheme.primary,
|
|
),
|
|
RadioListTile<ThemeMode>(
|
|
title: Text(l10n.themeDark),
|
|
value: ThemeMode.dark,
|
|
groupValue: ThemeController.to.themeMode,
|
|
onChanged: (value) {
|
|
ThemeController.to.setDarkTheme();
|
|
Get.back();
|
|
},
|
|
activeColor: scheme.primary,
|
|
),
|
|
RadioListTile<ThemeMode>(
|
|
title: Text(l10n.themeSystem),
|
|
value: ThemeMode.system,
|
|
groupValue: ThemeController.to.themeMode,
|
|
onChanged: (value) {
|
|
ThemeController.to.setSystemTheme();
|
|
Get.back();
|
|
},
|
|
activeColor: scheme.primary,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showLogoutDialog(BuildContext context, AppLocalizations l10n) {
|
|
showDialog(
|
|
context: context,
|
|
builder: (context) => AlertDialog(
|
|
title: Text(l10n.logoutConfirmTitle),
|
|
content: Text(l10n.logoutConfirmMessage),
|
|
actions: [
|
|
TextButton(
|
|
onPressed: () => Navigator.of(context).pop(),
|
|
child: Text(l10n.cancel),
|
|
),
|
|
ElevatedButton(
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
AuthService.to.logout();
|
|
SnackbarUtil.showSuccess(l10n.loggedOutSuccess);
|
|
},
|
|
style: ElevatedButton.styleFrom(
|
|
backgroundColor: Theme.of(context).colorScheme.error,
|
|
foregroundColor: Theme.of(context).colorScheme.onError,
|
|
),
|
|
child: Text(l10n.logout),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|