amoriai/lib/screens/onboarding/early_setup_demographics_sc...

358 lines
10 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import '../../services/firebase_service.dart';
import '../../services/dialog_service.dart';
import 'early_setup_preferences_screen.dart';
// Colors matching the design
const Color primaryBrown = Color(0xFF4A3C3C);
const Color labelGray = Color(0xFF9E9E9E);
const Color borderGray = Color(0xFFE8E8E8);
class EarlySetupDemographicsScreen extends StatefulWidget {
const EarlySetupDemographicsScreen({super.key});
@override
State<EarlySetupDemographicsScreen> createState() =>
_EarlySetupDemographicsScreenState();
}
class _EarlySetupDemographicsScreenState
extends State<EarlySetupDemographicsScreen> {
bool _isLoading = false;
// Options
final List<String> _ageRanges = ['< 18', '1824', '2534', '35+'];
final List<String> _genders = ['Male', 'Female', 'Prefer not to say'];
String? _selectedAgeRange;
String? _selectedGender;
@override
void initState() {
super.initState();
_loadExistingData();
}
Future<void> _loadExistingData() async {
try {
final user = FirebaseService().currentUser;
if (user != null) {
final userData = await FirebaseService().getUserData(user.uid);
if (userData != null && mounted) {
setState(() {
_selectedGender = userData.gender;
// Load age range if stored in preferences
final ageRange = userData.preferences.ageRange;
if (ageRange != null && _ageRanges.contains(ageRange)) {
_selectedAgeRange = ageRange;
}
});
}
}
} catch (e) {
debugPrint('Error loading data: $e');
}
}
Future<void> _handleContinue() async {
if (_selectedAgeRange == null) {
DialogService().showError('Silakan pilih rentang usia');
return;
}
if (_selectedGender == null) {
DialogService().showError('Silakan pilih gender');
return;
}
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) {
// Update gender in user model
final updatedUser = userData.copyWith(gender: _selectedGender);
await firebaseService.updateUserData(updatedUser);
// Update age range in preferences
final updatedPreferences = userData.preferences.copyWith(
ageRange: _selectedAgeRange,
);
await firebaseService.updateUserPreferences(
currentUser.uid,
updatedPreferences,
);
if (mounted) {
// Navigate to next screen
await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const EarlySetupPreferencesScreen(),
),
);
if (mounted) {
Navigator.of(context).pop(true);
}
}
}
} catch (e) {
if (mounted) {
DialogService().showError('Gagal menyimpan: $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(
'Tell us about\nyourself',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 26,
fontWeight: FontWeight.bold,
color: primaryBrown,
height: 1.25,
),
),
const SizedBox(height: 10),
const Text(
'This helps personalize your experience',
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Poppins',
fontSize: 14,
fontWeight: FontWeight.w400,
color: labelGray,
),
),
const SizedBox(height: 40),
// Age Range Section
_buildSectionTitle('Age Range', 'Pilih rentang usia Anda'),
const SizedBox(height: 12),
_buildAgeRangeChips(),
const SizedBox(height: 32),
// Gender Section
_buildSectionTitle('Gender', 'Pilih jenis kelamin Anda'),
const SizedBox(height: 12),
_buildGenderChips(),
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 _buildAgeRangeChips() {
return Wrap(
spacing: 10,
runSpacing: 10,
children: _ageRanges.map((ageRange) {
final isSelected = _selectedAgeRange == ageRange;
return ChoiceChip(
label: Text(ageRange),
selected: isSelected,
onSelected: (selected) {
if (selected) {
setState(() {
_selectedAgeRange = ageRange;
});
}
},
selectedColor: primaryBrown.withOpacity(0.15),
backgroundColor: Colors.grey[100],
labelStyle: TextStyle(
fontFamily: 'Poppins',
fontSize: 14,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
color: isSelected ? primaryBrown : labelGray,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
side: BorderSide(
color: isSelected ? primaryBrown : borderGray,
width: 1,
),
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
);
}).toList(),
);
}
Widget _buildGenderChips() {
return Wrap(
spacing: 10,
runSpacing: 10,
children: _genders.map((gender) {
final isSelected = _selectedGender == gender;
return ChoiceChip(
label: Text(gender),
selected: isSelected,
onSelected: (selected) {
if (selected) {
setState(() {
_selectedGender = gender;
});
}
},
selectedColor: primaryBrown.withOpacity(0.15),
backgroundColor: Colors.grey[100],
labelStyle: TextStyle(
fontFamily: 'Poppins',
fontSize: 14,
fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
color: isSelected ? primaryBrown : labelGray,
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
side: BorderSide(
color: isSelected ? primaryBrown : borderGray,
width: 1,
),
),
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
);
}).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,
),
),
),
),
],
);
}
}