expo-popcore-old/app/settings/index.tsx

212 lines
5.4 KiB
TypeScript

import Ionicons from '@expo/vector-icons/Ionicons';
import { StatusBar } from 'expo-status-bar';
import { type Href, useRouter } from 'expo-router';
import React, { useState } from 'react';
import {
ActivityIndicator,
Alert,
Pressable,
StyleSheet,
Text,
View,
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { authClient } from '@/lib/auth/client';
type Palette = {
canvas: string;
card: string;
textPrimary: string;
textSecondary: string;
icon: string;
stroke: string;
buttonBackground: string;
buttonText: string;
};
type SettingDestination = {
key: string;
label: string;
route?: Href;
};
const palettes: Record<'dark' | 'light', Palette> = {
dark: {
canvas: '#050505',
card: '#141417',
textPrimary: '#F5F5F7',
textSecondary: '#8E8E93',
icon: '#F5F5F7',
stroke: '#232327',
buttonBackground: '#FFFFFF',
buttonText: '#050505',
},
light: {
canvas: '#F7F7F9',
card: '#FFFFFF',
textPrimary: '#131318',
textSecondary: '#5C5C67',
icon: '#131318',
stroke: '#E4E4EA',
buttonBackground: '#131318',
buttonText: '#FFFFFF',
},
};
const destinations: SettingDestination[] = [
{ key: 'change-password', label: 'Change Password', route: '/settings/account' },
{ key: 'terms', label: 'Terms and Policies' },
{ key: 'support', label: 'Feedback and Support' },
];
export default function SettingsHomeScreen() {
const router = useRouter();
const insets = useSafeAreaInsets();
const palette = palettes['dark'];
const [isLoggingOut, setIsLoggingOut] = useState(false);
const topInset = Math.max(insets.top, 16);
const bottomInset = Math.max(insets.bottom + 16, 40);
const handleNavigate = (destination: SettingDestination) => {
if (!destination.route) {
return;
}
router.push(destination.route);
};
const handleLogOut = async () => {
if (isLoggingOut) {
return;
}
setIsLoggingOut(true);
try {
await authClient.signOut();
} catch (error) {
const message =
error instanceof Error ? error.message : 'Please try again in a moment.';
Alert.alert('Unable to log out', message);
} finally {
setIsLoggingOut(false);
}
};
return (
<View style={[styles.screen, { paddingTop: topInset, backgroundColor: palette.canvas }]}>
<StatusBar style={'light'} />
<View style={styles.headerRow}>
<Pressable
accessibilityRole="button"
style={styles.headerControl}
onPress={() => router.back()}
>
<Ionicons name="chevron-back" size={22} color={palette.icon} />
</Pressable>
<Text style={[styles.headerTitle, { color: palette.textPrimary }]}>set up</Text>
<View style={styles.headerControl} />
</View>
<View style={styles.content}>
<View style={[styles.card, { backgroundColor: palette.card }]}>
{destinations.map((destination, index) => {
const isLast = index === destinations.length - 1;
return (
<Pressable
key={destination.key}
accessibilityRole={destination.route ? 'button' : 'none'}
disabled={!destination.route}
onPress={() => handleNavigate(destination)}
style={({ pressed }) => [
styles.optionRow,
!isLast && { borderBottomWidth: StyleSheet.hairlineWidth, borderBottomColor: palette.stroke },
pressed && destination.route && { opacity: 0.6 },
]}
>
<Text style={[styles.optionLabel, { color: palette.textPrimary }]}>
{destination.label}
</Text>
<Ionicons name="chevron-forward" size={18} color={palette.textSecondary} />
</Pressable>
);
})}
</View>
</View>
<View style={[styles.footer, { paddingBottom: bottomInset }]}>
<Pressable
accessibilityRole="button"
disabled={isLoggingOut}
onPress={handleLogOut}
style={({ pressed }) => [
styles.logoutButton,
{ backgroundColor: palette.buttonBackground },
pressed && { opacity: 0.9 },
]}
>
{isLoggingOut ? (
<ActivityIndicator size="small" color={palette.buttonText} />
) : (
<Text style={[styles.logoutLabel, { color: palette.buttonText }]}>Log out</Text>
)}
</Pressable>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: {
flex: 1,
},
headerRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 32,
},
headerControl: {
width: 44,
height: 44,
alignItems: 'center',
justifyContent: 'center',
},
headerTitle: {
fontSize: 18,
fontWeight: '600',
letterSpacing: 0.4,
},
content: {
flex: 1,
},
card: {
borderRadius: 18,
},
optionRow: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
minHeight: 64,
},
optionLabel: {
fontSize: 16,
fontWeight: '500',
},
footer: {
paddingTop: 32,
},
logoutButton: {
borderRadius: 26,
height: 56,
alignItems: 'center',
justifyContent: 'center',
},
logoutLabel: {
fontSize: 16,
fontWeight: '600',
},
});