243 lines
7.7 KiB
Dart
243 lines
7.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:shared_preferences/shared_preferences.dart';
|
|
import '../../core/theme/app_theme.dart';
|
|
import '../../core/constants/app_constants.dart';
|
|
import '../../services/firebase_service.dart';
|
|
import '../../services/dialog_service.dart';
|
|
|
|
class NotificationSettingsScreen extends StatefulWidget {
|
|
const NotificationSettingsScreen({super.key});
|
|
|
|
@override
|
|
State<NotificationSettingsScreen> createState() =>
|
|
_NotificationSettingsScreenState();
|
|
}
|
|
|
|
class _NotificationSettingsScreenState
|
|
extends State<NotificationSettingsScreen> {
|
|
static const _keyMain = 'notif_main';
|
|
static const _keyRekomendasi = 'notif_rekomendasi';
|
|
static const _keyCheckin = 'notif_checkin';
|
|
static const _keyPromo = 'notif_promo';
|
|
|
|
bool _mainEnabled = true;
|
|
bool _rekomendasiEnabled = true;
|
|
bool _checkinEnabled = true;
|
|
bool _promoEnabled = false;
|
|
bool _isLoading = true;
|
|
bool _isSaving = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_loadSettings();
|
|
}
|
|
|
|
Future<void> _loadSettings() async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
setState(() {
|
|
_mainEnabled = prefs.getBool(_keyMain) ?? true;
|
|
_rekomendasiEnabled = prefs.getBool(_keyRekomendasi) ?? true;
|
|
_checkinEnabled = prefs.getBool(_keyCheckin) ?? true;
|
|
_promoEnabled = prefs.getBool(_keyPromo) ?? false;
|
|
_isLoading = false;
|
|
});
|
|
}
|
|
|
|
Future<void> _setMain(bool value) async {
|
|
setState(() => _isSaving = true);
|
|
try {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setBool(_keyMain, value);
|
|
|
|
final firebaseService = FirebaseService();
|
|
final uid = firebaseService.currentUser?.uid;
|
|
if (uid != null) {
|
|
final userData = await firebaseService.getUserData(uid);
|
|
if (userData != null) {
|
|
await firebaseService.updateUserData(
|
|
userData.copyWith(
|
|
preferences: userData.preferences.copyWith(
|
|
enableNotifications: value,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
if (value) await firebaseService.initializeNotifications();
|
|
|
|
setState(() => _mainEnabled = value);
|
|
} catch (e) {
|
|
DialogService().showError('Gagal menyimpan: $e');
|
|
} finally {
|
|
if (mounted) setState(() => _isSaving = false);
|
|
}
|
|
}
|
|
|
|
Future<void> _toggle(
|
|
String key,
|
|
bool value,
|
|
void Function(bool) setter,
|
|
) async {
|
|
final prefs = await SharedPreferences.getInstance();
|
|
await prefs.setBool(key, value);
|
|
setState(() => setter(value));
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
backgroundColor: AppTheme.warmWhite,
|
|
appBar: AppBar(
|
|
title: const Text(
|
|
'Pengaturan Notifikasi',
|
|
style: TextStyle(
|
|
color: AppTheme.primaryBrown,
|
|
fontWeight: FontWeight.bold,
|
|
),
|
|
),
|
|
backgroundColor: AppTheme.warmWhite,
|
|
elevation: 0,
|
|
iconTheme: const IconThemeData(color: AppTheme.primaryBrown),
|
|
),
|
|
body: _isLoading
|
|
? const Center(
|
|
child: CircularProgressIndicator(color: AppTheme.primaryBrown),
|
|
)
|
|
: SingleChildScrollView(
|
|
padding: const EdgeInsets.all(AppConstants.defaultPadding),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
// Notifikasi utama
|
|
_buildSwitchCard(
|
|
icon: Icons.notifications_outlined,
|
|
title: 'Aktifkan Notifikasi',
|
|
subtitle:
|
|
'Izinkan MuningAI mengirim notifikasi ke perangkatmu',
|
|
value: _mainEnabled,
|
|
onChanged: _isSaving ? null : _setMain,
|
|
),
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
// Jenis notifikasi
|
|
_buildSwitchCard(
|
|
icon: Icons.restaurant_menu_outlined,
|
|
title: 'Rekomendasi Menu',
|
|
subtitle:
|
|
'Notifikasi saat ada rekomendasi menu baru untukmu',
|
|
value: _mainEnabled && _rekomendasiEnabled,
|
|
onChanged: _mainEnabled
|
|
? (v) => _toggle(
|
|
_keyRekomendasi,
|
|
v,
|
|
(val) => _rekomendasiEnabled = val,
|
|
)
|
|
: null,
|
|
),
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
_buildSwitchCard(
|
|
icon: Icons.today_outlined,
|
|
title: 'Reminder Check-in',
|
|
subtitle: 'Pengingat harian untuk mengisi check-in mood',
|
|
value: _mainEnabled && _checkinEnabled,
|
|
onChanged: _mainEnabled
|
|
? (v) => _toggle(
|
|
_keyCheckin,
|
|
v,
|
|
(val) => _checkinEnabled = val,
|
|
)
|
|
: null,
|
|
),
|
|
|
|
const SizedBox(height: 8),
|
|
|
|
_buildSwitchCard(
|
|
icon: Icons.local_offer_outlined,
|
|
title: 'Promo & Penawaran',
|
|
subtitle: 'Info promo dan menu spesial dari kafe',
|
|
value: _mainEnabled && _promoEnabled,
|
|
onChanged: _mainEnabled
|
|
? (v) => _toggle(
|
|
_keyPromo,
|
|
v,
|
|
(val) => _promoEnabled = val,
|
|
)
|
|
: null,
|
|
),
|
|
|
|
const SizedBox(height: 16),
|
|
|
|
Center(
|
|
child: Text(
|
|
'Kamu juga dapat mengatur izin notifikasi\nmelalui Pengaturan perangkatmu.',
|
|
textAlign: TextAlign.center,
|
|
style: TextStyle(fontSize: 12, color: AppTheme.grey500),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _buildSwitchCard({
|
|
required IconData icon,
|
|
required String title,
|
|
required String subtitle,
|
|
required bool value,
|
|
required ValueChanged<bool>? onChanged,
|
|
}) {
|
|
final active = onChanged != null;
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.white,
|
|
borderRadius: BorderRadius.circular(AppConstants.borderRadius),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: Colors.black.withOpacity(0.03),
|
|
blurRadius: 8,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
],
|
|
),
|
|
child: SwitchListTile(
|
|
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4),
|
|
secondary: Container(
|
|
padding: const EdgeInsets.all(8),
|
|
decoration: BoxDecoration(
|
|
color: AppTheme.primaryBrown.withOpacity(active ? 0.1 : 0.04),
|
|
borderRadius: BorderRadius.circular(8),
|
|
),
|
|
child: Icon(
|
|
icon,
|
|
color: active ? AppTheme.primaryBrown : AppTheme.grey300,
|
|
size: 20,
|
|
),
|
|
),
|
|
title: Text(
|
|
title,
|
|
style: TextStyle(
|
|
fontWeight: FontWeight.w600,
|
|
fontSize: 14,
|
|
color: active ? const Color(0xFF424242) : AppTheme.grey400,
|
|
),
|
|
),
|
|
subtitle: Text(
|
|
subtitle,
|
|
style: TextStyle(
|
|
fontSize: 12,
|
|
color: active ? AppTheme.grey600 : AppTheme.grey300,
|
|
),
|
|
),
|
|
value: value,
|
|
onChanged: onChanged,
|
|
activeColor: AppTheme.primaryBrown,
|
|
),
|
|
);
|
|
}
|
|
}
|