amoriai/lib/screens/onboarding/early_setup_preferences_scr...

359 lines
10 KiB
Dart

import 'package:flutter/material.dart';
import '../../services/firebase_service.dart';
import '../../services/dialog_service.dart';
import '../../models/user_model.dart';
// Colors matching the design
const Color primaryBrown = Color(0xFF4A3C3C);
const Color labelGray = Color(0xFF9E9E9E);
const Color borderGray = Color(0xFFE8E8E8);
class EarlySetupPreferencesScreen extends StatefulWidget {
const EarlySetupPreferencesScreen({super.key});
@override
State<EarlySetupPreferencesScreen> createState() =>
_EarlySetupPreferencesScreenState();
}
class _EarlySetupPreferencesScreenState
extends State<EarlySetupPreferencesScreen> {
bool _isLoading = false;
// Available options
final List<String> _availableAllergies = [
'Gluten',
'Kacang',
'Susu',
'Telur',
'Seafood',
'Kedelai',
'Wijen',
'Sulfit',
];
final List<String> _availableDietaryRestrictions = [
'None',
'Vegetarian',
'Vegan',
'Halal',
'Keto',
'Low Carb',
];
List<String> _selectedAllergies = [];
String _selectedDietaryRestriction = 'None';
@override
void initState() {
super.initState();
_loadExistingPreferences();
}
Future<void> _loadExistingPreferences() async {
try {
final user = FirebaseService().currentUser;
if (user != null) {
final userData = await FirebaseService().getUserData(user.uid);
if (userData != null && mounted) {
setState(() {
_selectedAllergies = userData.preferences.allergies;
_selectedDietaryRestriction =
userData.preferences.dietaryRestriction;
});
}
}
} catch (e) {
debugPrint('Error loading preferences: $e');
}
}
Future<void> _handleContinue() async {
setState(() => _isLoading = true);
try {
final firebaseService = FirebaseService();
final currentUser = firebaseService.currentUser;
if (currentUser == null) throw Exception('User not logged in');
final userData = await firebaseService.getUserData(currentUser.uid);
if (userData != null) {
final updatedPreferences = userData.preferences.copyWith(
allergies: _selectedAllergies,
dietaryRestriction: _selectedDietaryRestriction,
);
await firebaseService.updateUserPreferences(
currentUser.uid,
updatedPreferences,
);
if (mounted) {
// Return true to indicate completion
Navigator.of(context).pop(true);
}
}
} catch (e) {
if (mounted) {
DialogService().showError('Failed to save preferences: $e');
}
} finally {
if (mounted) setState(() => _isLoading = false);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
body: SafeArea(
child: Column(
children: [
// Back button
Align(
alignment: Alignment.topLeft,
child: Padding(
padding: const EdgeInsets.only(left: 8, top: 8),
child: IconButton(
icon: const Icon(
Icons.chevron_left,
color: Colors.black54,
size: 28,
),
onPressed: () => Navigator.of(context).pop(),
),
),
),
// Scrollable content
Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(height: 8),
// Title
const Text(
'Set your dietary\npreferences',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 26,
fontWeight: FontWeight.bold,
color: primaryBrown,
height: 1.25,
),
),
const SizedBox(height: 10),
const Text(
'Help us recommend safer options for you',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 14,
fontWeight: FontWeight.w400,
color: labelGray,
),
),
const SizedBox(height: 32),
// Allergies Section
_buildSectionTitle(
'Alergi & Pantangan',
'Pilih bahan yang harus dihindari',
),
const SizedBox(height: 12),
_buildAllergiesChips(),
const SizedBox(height: 28),
// Dietary Restrictions Section
_buildSectionTitle(
'Pembatasan Diet',
'Pilih pola makan yang Anda ikuti',
),
const SizedBox(height: 12),
_buildDietaryRestrictionsChips(),
const SizedBox(height: 48),
// Continue Button
Align(
alignment: Alignment.centerRight,
child: _buildCircularButton(
onPressed: _isLoading ? null : _handleContinue,
isLoading: _isLoading,
),
),
const SizedBox(height: 32),
],
),
),
),
],
),
),
);
}
Widget _buildSectionTitle(String title, String subtitle) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontFamily: 'Poppins',
fontSize: 16,
fontWeight: FontWeight.w600,
color: primaryBrown,
),
),
const SizedBox(height: 4),
Text(
subtitle,
style: const TextStyle(
fontFamily: 'Poppins',
fontSize: 12,
fontWeight: FontWeight.w400,
color: labelGray,
),
),
],
);
}
Widget _buildAllergiesChips() {
return Wrap(
spacing: 8,
runSpacing: 8,
children: _availableAllergies.map((allergy) {
final isSelected = _selectedAllergies.contains(allergy);
return FilterChip(
label: Text(allergy),
selected: isSelected,
onSelected: (selected) {
setState(() {
if (selected) {
_selectedAllergies.add(allergy);
} else {
_selectedAllergies.remove(allergy);
}
});
},
selectedColor: const Color(0xFFFFEBEE),
checkmarkColor: const Color(0xFFD32F2F),
backgroundColor: Colors.grey[100],
labelStyle: TextStyle(
fontFamily: 'Poppins',
fontSize: 13,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
color: isSelected ? const Color(0xFFD32F2F) : primaryBrown,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
side: BorderSide(
color: isSelected ? const Color(0xFFD32F2F) : borderGray,
width: 1,
),
),
);
}).toList(),
);
}
Widget _buildDietaryRestrictionsChips() {
return Wrap(
spacing: 8,
runSpacing: 8,
children: _availableDietaryRestrictions.map((restriction) {
final isSelected = _selectedDietaryRestriction == restriction;
return ChoiceChip(
label: Text(restriction),
selected: isSelected,
onSelected: (selected) {
if (selected) {
setState(() {
_selectedDietaryRestriction = restriction;
});
}
},
selectedColor: primaryBrown.withOpacity(0.15),
backgroundColor: Colors.grey[100],
labelStyle: TextStyle(
fontFamily: 'Poppins',
fontSize: 13,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
color: isSelected ? primaryBrown : labelGray,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
side: BorderSide(
color: isSelected ? primaryBrown : borderGray,
width: 1,
),
),
);
}).toList(),
);
}
Widget _buildCircularButton({
VoidCallback? onPressed,
bool isLoading = false,
}) {
return Stack(
clipBehavior: Clip.none,
children: [
// Shadow overlay
Positioned(
top: -4,
left: 4,
right: -4,
bottom: 4,
child: Container(
width: 64,
height: 64,
decoration: BoxDecoration(
color: const Color(0xFF5A4A3A).withOpacity(0.3),
shape: BoxShape.circle,
),
),
),
// Main button
Material(
color: const Color(0xFF5A4A3A),
shape: const CircleBorder(),
child: InkWell(
onTap: onPressed,
customBorder: const CircleBorder(),
child: Container(
width: 64,
height: 64,
decoration: const BoxDecoration(shape: BoxShape.circle),
child: isLoading
? const Padding(
padding: EdgeInsets.all(16.0),
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 3,
),
)
: const Icon(
Icons.arrow_forward,
color: Colors.white,
size: 32,
),
),
),
),
],
);
}
}