172 lines
5.6 KiB
TypeScript

import React, { useEffect, useState } from 'react';
import {
View,
Text,
TouchableOpacity,
Switch,
ScrollView,
ActivityIndicator,
Alert,
} from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { StackNavigationProp } from '@react-navigation/stack';
import { getStyles } from './preferencesScreen.styles';
import { PrimaryButton } from '@components';
import { useAppTheme } from '@theme';
import { AuthStackParamList } from '../../../navigation/authStack';
import { useAppDispatch, useAppSelector } from '@store';
import { fetchCategories, completeOnboard } from './thunk';
import { OnboardingStackParamList } from '@navigation/onboardingStack';
type NavProp = StackNavigationProp<
OnboardingStackParamList,
'PreferencesScreen'
>;
export const PreferencesScreen: React.FC = () => {
const { colors } = useAppTheme();
const styles = getStyles(colors);
const navigation = useNavigation<NavProp>();
const dispatch = useAppDispatch();
// ─── Redux state ──────────────────────────────────────────────────────────
const { categories, isLoading, error, isSubmitting, submitError } =
useAppSelector(state => state.preferences);
const locationData = useAppSelector(state => state.setLocation);
const profileData = useAppSelector(state => state.completeProfile);
// ─── Local state ──────────────────────────────────────────────────────────
const [selectedCategories, setSelectedCategories] = useState<string[]>([]);
const [notificationsEnabled, setNotificationsEnabled] = useState(true);
// ─── Fetch categories on mount ────────────────────────────────────────────
useEffect(() => {
dispatch(fetchCategories());
}, [dispatch]);
const toggleCategory = (id: string) => {
setSelectedCategories(prev =>
prev.includes(id) ? prev.filter(c => c !== id) : [...prev, id],
);
};
// ─── Continue → call onboard API ─────────────────────────────────────────
const handleContinue = async () => {
if (!locationData.latitude || !locationData.longitude) {
Alert.alert('Location missing', 'Please set your location first.');
return;
}
if (!profileData.name || !profileData.email) {
Alert.alert('Profile incomplete', 'Please complete your profile first.');
return;
}
const payload = {
name: profileData.name,
email: profileData.email,
gender: profileData.gender,
latitude: locationData.latitude,
longitude: locationData.longitude,
addressLabel: profileData.addressLabel,
addressLine1: profileData.addressLine1,
mapAddress: locationData.mapAddress,
houseNumber: profileData.houseNumber,
landmark: profileData.landmark,
city: profileData.city,
state: profileData.state,
postalCode: profileData.postalCode,
addressPhone: profileData.addressPhone,
categoryPreferences: selectedCategories,
};
const result = await dispatch(completeOnboard(payload));
if (completeOnboard.fulfilled.match(result)) {
navigation.navigate('OnboardingCompleteScreen');
} else {
Alert.alert(
'Onboarding failed',
(result.payload as string) ?? 'Something went wrong. Please try again.',
);
}
};
return (
<ScrollView style={styles.container} contentContainerStyle={styles.content}>
<Text style={styles.title}>Preferences</Text>
<Text style={styles.subtitle}>Select your interests</Text>
{isLoading && (
<ActivityIndicator
size="large"
color={colors.primary}
style={{ marginVertical: 32 }}
/>
)}
{!!error && (
<Text
style={{
color: colors.error ?? 'red',
textAlign: 'center',
marginBottom: 16,
}}
>
{error}
</Text>
)}
{!!submitError && (
<Text
style={{
color: colors.error ?? 'red',
textAlign: 'center',
marginBottom: 16,
}}
>
{submitError}
</Text>
)}
{!isLoading && (
<View style={styles.grid}>
{(categories || []).map(cat => (
<TouchableOpacity
key={cat.id}
style={[
styles.gridItem,
selectedCategories.includes(cat.id) && styles.gridItemSelected,
]}
onPress={() => toggleCategory(cat.id)}
activeOpacity={0.7}
>
<Text style={styles.gridLabel}>{cat.name}</Text>
</TouchableOpacity>
))}
</View>
)}
<View style={styles.toggleRow}>
<View>
<Text style={styles.toggleLabel}>Enable Notifications</Text>
<Text style={styles.toggleSubtext}>Get order updates and offers</Text>
</View>
<Switch
value={notificationsEnabled}
onValueChange={setNotificationsEnabled}
trackColor={{ false: colors.border, true: colors.primary }}
thumbColor={colors.white}
/>
</View>
<PrimaryButton
title={isSubmitting ? 'Please wait…' : 'Continue'}
onPress={handleContinue}
disabled={isSubmitting}
style={{ marginTop: 32 }}
/>
</ScrollView>
);
};