172 lines
5.6 KiB
TypeScript
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>
|
|
);
|
|
};
|