fitst commit
This commit is contained in:
218
screens/welcome/ui/Welcome.tsx
Normal file
218
screens/welcome/ui/Welcome.tsx
Normal file
@@ -0,0 +1,218 @@
|
||||
import { ThemedText } from '@/components/themed-text';
|
||||
import AntDesign from '@expo/vector-icons/AntDesign';
|
||||
import Feather from '@expo/vector-icons/Feather';
|
||||
import MaterialCommunityIcons from '@expo/vector-icons/MaterialCommunityIcons';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { useRouter } from 'expo-router';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Animated, RefreshControl, ScrollView, TouchableOpacity, View } from 'react-native';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import { styles } from '../styles/welcomeStyle';
|
||||
import FeatureCard from './FeatureCard';
|
||||
import WelcomeHeader from './WelcomeHeader';
|
||||
|
||||
export default function WelcomePage() {
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
const fadeAnim = new Animated.Value(0);
|
||||
const router = useRouter();
|
||||
const slideAnim = new Animated.Value(50);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
|
||||
const menuHeightAnim = useRef(new Animated.Value(0)).current;
|
||||
const menuOpacityAnim = useRef(new Animated.Value(0)).current;
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
useEffect(() => {
|
||||
Animated.parallel([
|
||||
Animated.timing(fadeAnim, {
|
||||
toValue: 1,
|
||||
duration: 800,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(slideAnim, {
|
||||
toValue: 0,
|
||||
duration: 800,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]).start();
|
||||
}, []);
|
||||
|
||||
// Menu animatsiyasi
|
||||
useEffect(() => {
|
||||
if (menuOpen) {
|
||||
Animated.parallel([
|
||||
Animated.spring(menuHeightAnim, {
|
||||
toValue: 1,
|
||||
tension: 80,
|
||||
friction: 10,
|
||||
useNativeDriver: false,
|
||||
}),
|
||||
Animated.timing(menuOpacityAnim, {
|
||||
toValue: 1,
|
||||
duration: 250,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]).start();
|
||||
} else {
|
||||
Animated.parallel([
|
||||
Animated.timing(menuHeightAnim, {
|
||||
toValue: 0,
|
||||
duration: 200,
|
||||
useNativeDriver: false,
|
||||
}),
|
||||
Animated.timing(menuOpacityAnim, {
|
||||
toValue: 0,
|
||||
duration: 150,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
]).start();
|
||||
}
|
||||
}, [menuOpen]);
|
||||
|
||||
const handleNavigation = (screen: 'announcements' | '(tabs)/login') => {
|
||||
setMenuOpen(false);
|
||||
router.push(`/${screen}`);
|
||||
};
|
||||
|
||||
const onRefresh = () => {
|
||||
setRefreshing(true);
|
||||
|
||||
setTimeout(() => {
|
||||
setRefreshing(false);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<WelcomeHeader onMenuPress={() => setMenuOpen(!menuOpen)} menuOpen={menuOpen} />
|
||||
|
||||
{menuOpen && (
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.mobileMenu,
|
||||
{
|
||||
opacity: menuOpacityAnim,
|
||||
overflow: 'hidden',
|
||||
},
|
||||
]}
|
||||
>
|
||||
<TouchableOpacity style={styles.menuItem} activeOpacity={0.7}>
|
||||
<ThemedText style={styles.menuItemText}>{t('mainPage.sign_in')}</ThemedText>
|
||||
<AntDesign name="right" size={15} color="black" />
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity style={[styles.menuItem]} activeOpacity={0.7}>
|
||||
<ThemedText style={styles.menuItemText}>{t('mainPage.sign_up')}</ThemedText>
|
||||
<AntDesign name="right" size={15} color="black" />
|
||||
</TouchableOpacity>
|
||||
</Animated.View>
|
||||
)}
|
||||
|
||||
<ScrollView
|
||||
contentContainerStyle={styles.scrollContent}
|
||||
showsVerticalScrollIndicator={false}
|
||||
refreshControl={
|
||||
<RefreshControl
|
||||
refreshing={refreshing}
|
||||
onRefresh={onRefresh}
|
||||
tintColor="#155dfc"
|
||||
colors={['#155dfc']}
|
||||
/>
|
||||
}
|
||||
>
|
||||
<View style={[styles.hero]}>
|
||||
<View style={styles.badge}>
|
||||
<ThemedText style={styles.badgeText}> {t('mainPage.safe')}</ThemedText>
|
||||
</View>
|
||||
|
||||
<ThemedText style={styles.title}>{t('mainPage.welcome')}</ThemedText>
|
||||
|
||||
<ThemedText style={styles.subtitle}>{t('mainPage.welcome_desc')}</ThemedText>
|
||||
|
||||
<TouchableOpacity
|
||||
style={styles.mainBtn}
|
||||
activeOpacity={0.9}
|
||||
onPress={() => handleNavigation('announcements')}
|
||||
>
|
||||
<ThemedText style={styles.mainBtnText}> {t('common.enrol')}</ThemedText>
|
||||
<View style={styles.btnArrow}>
|
||||
<AntDesign name="right" size={14} color="white" />
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<View style={styles.features}>
|
||||
<FeatureCard
|
||||
bgColor="#dbeafe"
|
||||
icon={<MaterialCommunityIcons name="shield-outline" size={24} color="#155dfc" />}
|
||||
title={t('mainPage.card1Title')}
|
||||
desc={t('mainPage.card1Desc')}
|
||||
delay={200}
|
||||
/>
|
||||
<FeatureCard
|
||||
bgColor="#dbeafe"
|
||||
icon={<Feather name="zap" size={24} color="#155dfc" />}
|
||||
title={t('mainPage.card2Title')}
|
||||
desc={t('mainPage.card2Desc')}
|
||||
delay={300}
|
||||
/>
|
||||
<FeatureCard
|
||||
bgColor="#f3e8ff"
|
||||
icon={<Feather name="users" size={24} color="#9810fa" />}
|
||||
title={t('mainPage.card3Title')}
|
||||
desc={t('mainPage.card3Desc')}
|
||||
delay={400}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
|
||||
<View style={styles.footer}>
|
||||
<TouchableOpacity
|
||||
style={{
|
||||
...styles.footerBtnOutline,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingVertical: 14,
|
||||
paddingHorizontal: 24,
|
||||
borderRadius: 12,
|
||||
}}
|
||||
activeOpacity={0.8}
|
||||
>
|
||||
<ThemedText style={styles.footerBtnOutlineText}>{t('mainPage.enter')}</ThemedText>
|
||||
</TouchableOpacity>
|
||||
|
||||
<TouchableOpacity onPress={() => handleNavigation('(tabs)/login')} activeOpacity={0.9}>
|
||||
<LinearGradient
|
||||
colors={['#3b82f6', '#6366f1']}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 0 }}
|
||||
style={{
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingVertical: 14,
|
||||
paddingHorizontal: 24,
|
||||
borderRadius: 12,
|
||||
marginBottom: 10,
|
||||
}}
|
||||
>
|
||||
<ThemedText
|
||||
style={{
|
||||
color: '#fff',
|
||||
fontSize: 16,
|
||||
fontWeight: '600',
|
||||
marginRight: 8,
|
||||
}}
|
||||
>
|
||||
{t('mainPage.start')}
|
||||
</ThemedText>
|
||||
<AntDesign name="right" size={14} color="white" />
|
||||
</LinearGradient>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user