feat: Add Settings Screen and related functionality
- Implemented SettingsScreen with tabs for Account, Social, and Devices. - Added various settings pages including Email, Notifications, Privacy, Security, Display Mode, Language, Text Size, and Terms of Service. - Integrated navigation to new settings pages from the main settings screen. - Updated navigation menu to include the new SettingsScreen. - Refactored authentication flow to navigate to the main navigation menu after successful login. - Enhanced UI with theme consistency across new settings pages.
This commit is contained in:
parent
1967fdb6b8
commit
61fb40bc0f
|
@ -1,6 +1,7 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:sigap/src/features/panic/presentation/pages/panic_button_page.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/setting_screen.dart';
|
||||
import 'package:sigap/src/shared/widgets/navigation/custom_bottom_navigation_bar.dart';
|
||||
|
||||
class NavigationMenu extends StatelessWidget {
|
||||
|
@ -10,8 +11,10 @@ class NavigationMenu extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
// Using GetX controller to manage navigation state
|
||||
final controller = Get.put(NavigationController());
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
backgroundColor: theme.scaffoldBackgroundColor,
|
||||
body: Obx(
|
||||
() => IndexedStack(
|
||||
index: controller.selectedIndex.value,
|
||||
|
@ -20,7 +23,7 @@ class NavigationMenu extends StatelessWidget {
|
|||
// SearchPage(),
|
||||
PanicButtonPage(),
|
||||
// HistoryPage(),
|
||||
// AccountPage(),
|
||||
SettingsScreen(),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -96,8 +96,6 @@ class AuthenticationRepository extends GetxController {
|
|||
}
|
||||
}
|
||||
|
||||
Logger().d('Available session: $session');
|
||||
|
||||
if (session != null) {
|
||||
if (!isEmailVerified) {
|
||||
_navigateToRoute(AppRoutes.emailVerification);
|
||||
|
@ -109,7 +107,7 @@ class AuthenticationRepository extends GetxController {
|
|||
}
|
||||
_navigateToRoute(AppRoutes.registrationForm);
|
||||
} else {
|
||||
_navigateToRoute(AppRoutes.panicButton);
|
||||
_navigateToRoute(AppRoutes.navigationMenu);
|
||||
}
|
||||
} else {
|
||||
await _handleUnauthenticatedUser(isFirstTime);
|
||||
|
@ -135,8 +133,7 @@ class AuthenticationRepository extends GetxController {
|
|||
|
||||
// Pisahkan logic untuk user yang belum login
|
||||
Future<void> _handleUnauthenticatedUser(bool isFirstTime) async {
|
||||
if (Get.currentRoute != AppRoutes.signIn &&
|
||||
Get.currentRoute != AppRoutes.onboarding) {
|
||||
if (Get.currentRoute != AppRoutes.onboarding) {
|
||||
bool biometricSuccess = await attemptBiometricLogin();
|
||||
if (!biometricSuccess) {
|
||||
if (isFirstTime) {
|
||||
|
@ -210,9 +207,12 @@ class AuthenticationRepository extends GetxController {
|
|||
|
||||
// Check for errors
|
||||
if (user == null) {
|
||||
Logger().e('User is null after sign in');
|
||||
throw 'User is null after sign in';
|
||||
}
|
||||
|
||||
Logger().i('User signed in: ${user.email}');
|
||||
|
||||
// Return user
|
||||
return user;
|
||||
} on AuthException catch (e) {
|
||||
|
|
|
@ -0,0 +1,284 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/contact_screen.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/display_mode_setting.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/email_setting.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/language_setting.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/notifications_setting.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/privacy_setting.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/security_setting.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/terms_services_screen.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/text_size_setting.dart';
|
||||
|
||||
class SettingsScreen extends StatefulWidget {
|
||||
const SettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
_SettingsScreenState createState() => _SettingsScreenState();
|
||||
}
|
||||
|
||||
class _SettingsScreenState extends State<SettingsScreen>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late TabController _tabController;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_tabController = TabController(length: 3, vsync: this);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_tabController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Settings', style: theme.textTheme.headlineMedium),
|
||||
backgroundColor: theme.scaffoldBackgroundColor,
|
||||
elevation: 0,
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
// Profile Section
|
||||
Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
color: theme.scaffoldBackgroundColor,
|
||||
child: Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
radius: 30,
|
||||
backgroundColor: theme.hintColor,
|
||||
child: Icon(
|
||||
Icons.person,
|
||||
size: 35,
|
||||
color: theme.scaffoldBackgroundColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Anita Rose', style: theme.textTheme.titleLarge),
|
||||
Text('anitarose', style: theme.textTheme.bodySmall),
|
||||
],
|
||||
),
|
||||
),
|
||||
Icon(Icons.chevron_right, color: theme.hintColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Tab Bar
|
||||
Container(
|
||||
color: theme.scaffoldBackgroundColor,
|
||||
child: TabBar(
|
||||
controller: _tabController,
|
||||
labelColor: theme.primaryColor,
|
||||
unselectedLabelColor: theme.hintColor,
|
||||
indicatorColor: theme.primaryColor,
|
||||
indicatorWeight: 2,
|
||||
labelStyle: theme.textTheme.labelLarge?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
tabs: const [
|
||||
Tab(text: 'ACCOUNT'),
|
||||
Tab(text: 'SOCIAL'),
|
||||
Tab(text: 'DEVICES'),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Tab Content
|
||||
Expanded(
|
||||
child: TabBarView(
|
||||
controller: _tabController,
|
||||
children: [
|
||||
_buildAccountTab(),
|
||||
_buildSocialTab(),
|
||||
_buildDevicesTab(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildAccountTab() {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
color: theme.scaffoldBackgroundColor,
|
||||
child: ListView(
|
||||
children: [
|
||||
_buildSettingsItem(
|
||||
icon: Icons.email_outlined,
|
||||
title: 'Email',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const EmailSettingsScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildSettingsItem(
|
||||
icon: Icons.notifications_outlined,
|
||||
title: 'Notifications',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const NotificationsSettingsScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildSettingsItem(
|
||||
icon: Icons.lock_outline,
|
||||
title: 'Privacy',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const PrivacySettingsScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildSettingsItem(
|
||||
icon: Icons.security_outlined,
|
||||
title: 'Security',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const SecuritySettingsScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_buildSettingsItem(
|
||||
icon: Icons.dark_mode_outlined,
|
||||
title: 'Display mode',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const DisplayModeSettingsScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildSettingsItem(
|
||||
icon: Icons.text_fields_outlined,
|
||||
title: 'Text size',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TextSizeSettingsScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildSettingsItem(
|
||||
icon: Icons.language_outlined,
|
||||
title: 'Language',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const LanguageSettingsScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_buildSettingsItem(
|
||||
icon: Icons.description_outlined,
|
||||
title: 'Terms and services',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TermsServicesScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildSettingsItem(
|
||||
icon: Icons.help_outline,
|
||||
title: 'Contact',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const ContactScreen()),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSocialTab() {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
color: theme.scaffoldBackgroundColor,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Social Settings',
|
||||
style: theme.textTheme.titleLarge?.copyWith(color: theme.hintColor),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildDevicesTab() {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
color: theme.scaffoldBackgroundColor,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'Device Settings',
|
||||
style: theme.textTheme.titleLarge?.copyWith(color: theme.hintColor),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSettingsItem({
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, size: 24, color: theme.iconTheme.color),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(child: Text(title, style: theme.textTheme.bodyLarge)),
|
||||
Icon(Icons.chevron_right, color: theme.hintColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class BaseDetailScreen extends StatelessWidget {
|
||||
final String title;
|
||||
final Widget content;
|
||||
|
||||
const BaseDetailScreen({
|
||||
super.key,
|
||||
required this.title,
|
||||
required this.content,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
centerTitle: true,
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: theme.iconTheme.color),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
title: Text(title, style: theme.textTheme.titleLarge),
|
||||
backgroundColor: theme.scaffoldBackgroundColor,
|
||||
elevation: 0,
|
||||
),
|
||||
body: Container(color: theme.scaffoldBackgroundColor, child: content),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/base_detail_screen.dart';
|
||||
|
||||
class ContactScreen extends StatelessWidget {
|
||||
const ContactScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseDetailScreen(
|
||||
title: 'Contact',
|
||||
content: ListView(
|
||||
padding: const EdgeInsets.all(20),
|
||||
children: [
|
||||
_buildContactItem(
|
||||
context,
|
||||
icon: Icons.email_outlined,
|
||||
title: 'Email',
|
||||
value: 'support@sigap.com',
|
||||
),
|
||||
_buildContactItem(
|
||||
context,
|
||||
icon: Icons.phone_outlined,
|
||||
title: 'Phone',
|
||||
value: '+62 21 1234 5678',
|
||||
),
|
||||
_buildContactItem(
|
||||
context,
|
||||
icon: Icons.location_on_outlined,
|
||||
title: 'Address',
|
||||
value: 'Jl. Sudirman No. 123, Jakarta 12190, Indonesia',
|
||||
),
|
||||
const SizedBox(height: 40),
|
||||
_buildSupportSection(context),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildContactItem(
|
||||
BuildContext context, {
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required String value,
|
||||
}) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 20),
|
||||
padding: const EdgeInsets.all(15),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: theme.dividerColor),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.primaryColor.withOpacity(0.1),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Icon(icon, size: 24, color: theme.primaryColor),
|
||||
),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.hintColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(value, style: theme.textTheme.bodyLarge),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSupportSection(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Need Help?', style: theme.textTheme.titleLarge),
|
||||
const SizedBox(height: 15),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
decoration: BoxDecoration(
|
||||
color: theme.cardColor,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(
|
||||
'Our support team is available Monday through Friday, 9:00 AM to 5:00 PM (GMT+7).',
|
||||
style: theme.textTheme.bodyMedium?.copyWith(height: 1.5),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: theme.elevatedButtonTheme.style,
|
||||
child: const Text('Contact Support'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/base_detail_screen.dart';
|
||||
|
||||
class DisplayModeSettingsScreen extends StatefulWidget {
|
||||
const DisplayModeSettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
_DisplayModeSettingsScreenState createState() =>
|
||||
_DisplayModeSettingsScreenState();
|
||||
}
|
||||
|
||||
class _DisplayModeSettingsScreenState extends State<DisplayModeSettingsScreen> {
|
||||
String selectedMode = 'System default';
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseDetailScreen(
|
||||
title: 'Display Mode',
|
||||
content: ListView(
|
||||
children: [
|
||||
_buildSectionHeader('Theme'),
|
||||
_buildRadioItem('System default'),
|
||||
_buildRadioItem('Light mode'),
|
||||
_buildRadioItem('Dark mode'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSectionHeader(String title) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(20, 30, 20, 10),
|
||||
child: Text(
|
||||
title,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRadioItem(String mode) {
|
||||
final theme = Theme.of(context);
|
||||
IconData icon;
|
||||
switch (mode) {
|
||||
case 'System default':
|
||||
icon = Icons.brightness_auto;
|
||||
break;
|
||||
case 'Light mode':
|
||||
icon = Icons.light_mode_outlined;
|
||||
break;
|
||||
case 'Dark mode':
|
||||
icon = Icons.dark_mode_outlined;
|
||||
break;
|
||||
default:
|
||||
icon = Icons.brightness_auto;
|
||||
}
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
selectedMode = mode;
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, size: 24, color: theme.iconTheme.color),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(child: Text(mode, style: theme.textTheme.bodyLarge)),
|
||||
Radio<String>(
|
||||
value: mode,
|
||||
groupValue: selectedMode,
|
||||
activeColor: theme.primaryColor,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
selectedMode = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,124 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/base_detail_screen.dart';
|
||||
|
||||
class EmailSettingsScreen extends StatefulWidget {
|
||||
const EmailSettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
_EmailSettingsScreenState createState() => _EmailSettingsScreenState();
|
||||
}
|
||||
|
||||
class _EmailSettingsScreenState extends State<EmailSettingsScreen> {
|
||||
String currentEmail = "anitarose@example.com";
|
||||
bool receiveNewsletter = true;
|
||||
bool receivePromotions = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseDetailScreen(
|
||||
title: 'Email Settings',
|
||||
content: ListView(
|
||||
children: [
|
||||
_buildSectionHeader('Email Address'),
|
||||
_buildEmailItem(),
|
||||
|
||||
_buildSectionHeader('Email Preferences'),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.newspaper_outlined,
|
||||
title: 'Receive newsletter',
|
||||
value: receiveNewsletter,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
receiveNewsletter = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.local_offer_outlined,
|
||||
title: 'Receive promotions',
|
||||
value: receivePromotions,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
receivePromotions = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSectionHeader(String title) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(20, 30, 20, 10),
|
||||
child: Text(
|
||||
title,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildEmailItem() {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(Icons.email_outlined, size: 24, color: theme.iconTheme.color),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Primary Email', style: theme.textTheme.bodyLarge),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
currentEmail,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
color: theme.hintColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {},
|
||||
style: TextButton.styleFrom(foregroundColor: theme.primaryColor),
|
||||
child: const Text('Change'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSwitchItem({
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required bool value,
|
||||
required ValueChanged<bool> onChanged,
|
||||
}) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, size: 24, color: theme.iconTheme.color),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(child: Text(title, style: theme.textTheme.bodyLarge)),
|
||||
Switch(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
activeColor: theme.primaryColor,
|
||||
activeTrackColor: theme.primaryColor.withOpacity(0.4),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/base_detail_screen.dart';
|
||||
|
||||
class LanguageSettingsScreen extends StatefulWidget {
|
||||
const LanguageSettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
_LanguageSettingsScreenState createState() => _LanguageSettingsScreenState();
|
||||
}
|
||||
|
||||
class _LanguageSettingsScreenState extends State<LanguageSettingsScreen> {
|
||||
String selectedLanguage = 'English (US)';
|
||||
|
||||
final List<Map<String, String>> languages = [
|
||||
{'name': 'English (US)', 'code': 'en_US'},
|
||||
{'name': 'Bahasa Indonesia', 'code': 'id_ID'},
|
||||
{'name': 'Español', 'code': 'es_ES'},
|
||||
{'name': 'Français', 'code': 'fr_FR'},
|
||||
{'name': '日本語', 'code': 'ja_JP'},
|
||||
{'name': '한국어', 'code': 'ko_KR'},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseDetailScreen(
|
||||
title: 'Language',
|
||||
content: ListView(
|
||||
children: [
|
||||
_buildSectionHeader('Select Language'),
|
||||
...languages.map((lang) => _buildLanguageItem(lang['name']!)),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSectionHeader(String title) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(20, 30, 20, 10),
|
||||
child: Text(
|
||||
title,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLanguageItem(String language) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
selectedLanguage = language;
|
||||
});
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
decoration: BoxDecoration(
|
||||
border: Border(
|
||||
bottom: BorderSide(color: theme.dividerColor.withOpacity(0.5)),
|
||||
),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(child: Text(language, style: theme.textTheme.bodyLarge)),
|
||||
if (language == selectedLanguage)
|
||||
Icon(Icons.check, color: theme.primaryColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/base_detail_screen.dart';
|
||||
|
||||
class NotificationsSettingsScreen extends StatefulWidget {
|
||||
const NotificationsSettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
_NotificationsSettingsScreenState createState() =>
|
||||
_NotificationsSettingsScreenState();
|
||||
}
|
||||
|
||||
class _NotificationsSettingsScreenState
|
||||
extends State<NotificationsSettingsScreen> {
|
||||
bool messagesNotify = true;
|
||||
bool commentsNotify = true;
|
||||
bool followersNotify = true;
|
||||
bool mentionsNotify = false;
|
||||
bool systemNotify = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseDetailScreen(
|
||||
title: 'Notifications',
|
||||
content: ListView(
|
||||
children: [
|
||||
_buildSectionHeader('Push Notifications'),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.message_outlined,
|
||||
title: 'Messages',
|
||||
value: messagesNotify,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
messagesNotify = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.comment_outlined,
|
||||
title: 'Comments',
|
||||
value: commentsNotify,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
commentsNotify = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.person_add_outlined,
|
||||
title: 'New followers',
|
||||
value: followersNotify,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
followersNotify = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.alternate_email,
|
||||
title: 'Mentions',
|
||||
value: mentionsNotify,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
mentionsNotify = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.info_outline,
|
||||
title: 'System notifications',
|
||||
value: systemNotify,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
systemNotify = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSectionHeader(String title) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(20, 30, 20, 10),
|
||||
child: Text(
|
||||
title,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSwitchItem({
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required bool value,
|
||||
required ValueChanged<bool> onChanged,
|
||||
}) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, size: 24, color: theme.iconTheme.color),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(child: Text(title, style: theme.textTheme.bodyLarge)),
|
||||
Switch(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
activeColor: theme.primaryColor,
|
||||
activeTrackColor: theme.primaryColor.withOpacity(0.4),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/base_detail_screen.dart';
|
||||
|
||||
class PrivacySettingsScreen extends StatefulWidget {
|
||||
const PrivacySettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
_PrivacySettingsScreenState createState() => _PrivacySettingsScreenState();
|
||||
}
|
||||
|
||||
class _PrivacySettingsScreenState extends State<PrivacySettingsScreen> {
|
||||
bool showActivityStatus = true;
|
||||
bool allowComments = false;
|
||||
bool shareUsageData = true;
|
||||
bool allowPersonalizedAds = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseDetailScreen(
|
||||
title: 'Privacy Settings',
|
||||
content: ListView(
|
||||
children: [
|
||||
_buildSectionHeader('Profile Visibility'),
|
||||
_buildNavigationItem(
|
||||
icon: Icons.visibility_outlined,
|
||||
title: 'Who can see my profile?',
|
||||
onTap: () {},
|
||||
),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.access_time_outlined,
|
||||
title: 'Show activity status',
|
||||
value: showActivityStatus,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
showActivityStatus = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
_buildSectionHeader('Interactions'),
|
||||
_buildNavigationItem(
|
||||
icon: Icons.chat_bubble_outline,
|
||||
title: 'Who can message me?',
|
||||
onTap: () {},
|
||||
),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.comment_outlined,
|
||||
title: 'Allow comments',
|
||||
value: allowComments,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
allowComments = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
_buildSectionHeader('Data Sharing'),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.analytics_outlined,
|
||||
title: 'Share usage data',
|
||||
value: shareUsageData,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
shareUsageData = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.ads_click_outlined,
|
||||
title: 'Allow personalized ads',
|
||||
value: allowPersonalizedAds,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
allowPersonalizedAds = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSectionHeader(String title) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(20, 30, 20, 10),
|
||||
child: Text(
|
||||
title,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNavigationItem({
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, size: 24, color: theme.iconTheme.color),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(child: Text(title, style: theme.textTheme.bodyLarge)),
|
||||
Icon(Icons.chevron_right, color: theme.hintColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSwitchItem({
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required bool value,
|
||||
required ValueChanged<bool> onChanged,
|
||||
}) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, size: 24, color: theme.iconTheme.color),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(child: Text(title, style: theme.textTheme.bodyLarge)),
|
||||
Switch(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
activeColor: theme.primaryColor,
|
||||
activeTrackColor: theme.primaryColor.withOpacity(0.4),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/base_detail_screen.dart';
|
||||
|
||||
class SecuritySettingsScreen extends StatefulWidget {
|
||||
const SecuritySettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
_SecuritySettingsScreenState createState() => _SecuritySettingsScreenState();
|
||||
}
|
||||
|
||||
class _SecuritySettingsScreenState extends State<SecuritySettingsScreen> {
|
||||
bool requireBiometric = true;
|
||||
bool enable2FA = false;
|
||||
bool sendEmailAlerts = true;
|
||||
bool sendPushNotification = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BaseDetailScreen(
|
||||
title: 'Security Settings',
|
||||
content: ListView(
|
||||
children: [
|
||||
_buildSectionHeader('App Lock'),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.fingerprint_outlined,
|
||||
title: 'Require biometric',
|
||||
value: requireBiometric,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
requireBiometric = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
_buildNavigationItem(
|
||||
icon: Icons.lock_outline,
|
||||
title: 'Change passcode',
|
||||
onTap: () {},
|
||||
),
|
||||
|
||||
_buildSectionHeader('Two-Factor Authentication'),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.security_outlined,
|
||||
title: 'Enable 2FA',
|
||||
value: enable2FA,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
enable2FA = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
_buildNavigationItem(
|
||||
icon: Icons.backup_outlined,
|
||||
title: 'Manage backup codes',
|
||||
onTap: () {},
|
||||
),
|
||||
|
||||
_buildSectionHeader('Login Alerts'),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.email_outlined,
|
||||
title: 'Send email alerts',
|
||||
value: sendEmailAlerts,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
sendEmailAlerts = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
_buildSwitchItem(
|
||||
icon: Icons.notifications_outlined,
|
||||
title: 'Send push notification',
|
||||
value: sendPushNotification,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
sendPushNotification = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSectionHeader(String title) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.fromLTRB(20, 30, 20, 10),
|
||||
child: Text(
|
||||
title,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildNavigationItem({
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, size: 24, color: theme.iconTheme.color),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(child: Text(title, style: theme.textTheme.bodyLarge)),
|
||||
Icon(Icons.chevron_right, color: theme.hintColor),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSwitchItem({
|
||||
required IconData icon,
|
||||
required String title,
|
||||
required bool value,
|
||||
required ValueChanged<bool> onChanged,
|
||||
}) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Icon(icon, size: 24, color: theme.iconTheme.color),
|
||||
const SizedBox(width: 15),
|
||||
Expanded(child: Text(title, style: theme.textTheme.bodyLarge)),
|
||||
Switch(
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
activeColor: theme.primaryColor,
|
||||
activeTrackColor: theme.primaryColor.withOpacity(0.4),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/base_detail_screen.dart';
|
||||
|
||||
class TermsServicesScreen extends StatelessWidget {
|
||||
const TermsServicesScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return BaseDetailScreen(
|
||||
title: 'Terms and Services',
|
||||
content: ListView(
|
||||
padding: const EdgeInsets.all(20),
|
||||
children: [
|
||||
Text('Terms of Service', style: theme.textTheme.headlineSmall),
|
||||
const SizedBox(height: 15),
|
||||
Text(
|
||||
'Last updated: January 1, 2023',
|
||||
style: theme.textTheme.bodyMedium?.copyWith(color: theme.hintColor),
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
_buildSectionText(
|
||||
context,
|
||||
'Introduction',
|
||||
'Welcome to SIGAP. These Terms of Service govern your use of our application and website. By using our services, you agree to these terms.',
|
||||
),
|
||||
_buildSectionText(
|
||||
context,
|
||||
'Using Our Services',
|
||||
'You must follow any policies made available to you within the Services. You may use our Services only as permitted by law. We may suspend or stop providing our Services to you if you do not comply with our terms or policies or if we are investigating suspected misconduct.',
|
||||
),
|
||||
_buildSectionText(
|
||||
context,
|
||||
'Privacy Policy',
|
||||
'Our privacy policy explains how we treat your personal data and protect your privacy when you use our Services. By using our Services, you agree that we can use such data in accordance with our privacy policy.',
|
||||
),
|
||||
_buildSectionText(
|
||||
context,
|
||||
'About These Terms',
|
||||
'We may modify these terms or any additional terms that apply to a Service to, for example, reflect changes to the law or changes to our Services.',
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
ElevatedButton(
|
||||
onPressed: () {},
|
||||
style: theme.elevatedButtonTheme.style,
|
||||
child: const Text('Download Full Terms'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSectionText(BuildContext context, String title, String content) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 20),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
content,
|
||||
style: theme.textTheme.bodyMedium?.copyWith(height: 1.5),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:sigap/src/features/personalization/presentasion/pages/settings/widgets/base_detail_screen.dart';
|
||||
|
||||
class TextSizeSettingsScreen extends StatefulWidget {
|
||||
const TextSizeSettingsScreen({super.key});
|
||||
|
||||
@override
|
||||
_TextSizeSettingsScreenState createState() => _TextSizeSettingsScreenState();
|
||||
}
|
||||
|
||||
class _TextSizeSettingsScreenState extends State<TextSizeSettingsScreen> {
|
||||
double _currentTextSize = 1.0; // 1.0 is default
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return BaseDetailScreen(
|
||||
title: 'Text Size',
|
||||
content: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildSectionHeader('Adjust Text Size'),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||
child: Text(
|
||||
'Sample text at current size',
|
||||
style: theme.textTheme.bodyLarge?.copyWith(
|
||||
fontSize: 16 * _currentTextSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text('A', style: theme.textTheme.bodyMedium),
|
||||
Expanded(
|
||||
child: SliderTheme(
|
||||
data: SliderTheme.of(context).copyWith(
|
||||
activeTrackColor: theme.primaryColor,
|
||||
thumbColor: theme.primaryColor,
|
||||
inactiveTrackColor: theme.primaryColor.withOpacity(0.2),
|
||||
),
|
||||
child: Slider(
|
||||
value: _currentTextSize,
|
||||
min: 0.8,
|
||||
max: 1.4,
|
||||
divisions: 6,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_currentTextSize = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
Text('A', style: theme.textTheme.titleLarge),
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Text(
|
||||
'This is a preview of how text will appear throughout the app. '
|
||||
'Adjust the slider to make text smaller or larger.',
|
||||
style: theme.textTheme.bodyMedium?.copyWith(
|
||||
fontSize: 14 * _currentTextSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSectionHeader(String title) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
padding: EdgeInsets.fromLTRB(20, 30, 20, 10),
|
||||
child: Text(
|
||||
title,
|
||||
style: theme.textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_tabler_icons/flutter_tabler_icons.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:sigap/navigation_menu.dart';
|
||||
|
||||
|
@ -8,15 +9,15 @@ class CustomBottomNavigationBar extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final controller = NavigationController.instance;
|
||||
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
color: theme.scaffoldBackgroundColor,
|
||||
borderRadius: const BorderRadius.vertical(top: Radius.circular(30)),
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.1),
|
||||
color: theme.shadowColor.withOpacity(0.1),
|
||||
blurRadius: 10,
|
||||
offset: const Offset(0, -5),
|
||||
),
|
||||
|
@ -74,6 +75,8 @@ class CustomBottomNavigationBar extends StatelessWidget {
|
|||
int index,
|
||||
bool isSelected,
|
||||
) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => NavigationController.instance.changeIndex(index),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
|
@ -82,14 +85,14 @@ class CustomBottomNavigationBar extends StatelessWidget {
|
|||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
color: isSelected ? const Color(0xFF5E39F1) : Colors.grey,
|
||||
color: isSelected ? theme.primaryColor : theme.hintColor,
|
||||
size: 24,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
label,
|
||||
style: TextStyle(
|
||||
color: isSelected ? const Color(0xFF5E39F1) : Colors.grey,
|
||||
color: isSelected ? theme.primaryColor : theme.hintColor,
|
||||
fontSize: 12,
|
||||
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
|
||||
),
|
||||
|
@ -100,23 +103,22 @@ class CustomBottomNavigationBar extends StatelessWidget {
|
|||
}
|
||||
|
||||
Widget _buildPanicButton(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
return GestureDetector(
|
||||
onTap: () => NavigationController.instance.changeIndex(2),
|
||||
child: Container(
|
||||
width: 60,
|
||||
height: 60,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFF5E39F1),
|
||||
color: theme.primaryColor,
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: const Color(0xFF5E39F1).withOpacity(0.3),
|
||||
blurRadius: 8,
|
||||
offset: const Offset(0, 4),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: const Icon(Icons.qr_code_scanner, color: Colors.white, size: 30),
|
||||
child: Icon(
|
||||
TablerIcons.plus,
|
||||
color: theme.scaffoldBackgroundColor,
|
||||
size: 30,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue