feat: add expo mobile application source code

This commit is contained in:
2026-05-21 16:06:35 +07:00
parent 76d7a5c5c6
commit 0c65a7811b
77 changed files with 20356 additions and 0 deletions
+100
View File
@@ -0,0 +1,100 @@
import React, { useEffect, useRef } from 'react';
import { View, Text, StyleSheet, Animated, TouchableOpacity, Platform } from 'react-native';
import { Feather } from '@expo/vector-icons';
import { useAppTheme } from '../context/ThemeContext';
interface AnnouncementProps {
visible: boolean;
message: string;
type?: 'info' | 'warning' | 'danger';
onClose?: () => void;
}
export const AnnouncementBanner = ({ visible, message, type = 'info', onClose }: AnnouncementProps) => {
const { colors, isDark } = useAppTheme();
const slideAnim = useRef(new Animated.Value(-100)).current;
const hasShownRef = useRef(false);
useEffect(() => {
if (visible) {
hasShownRef.current = true;
Animated.spring(slideAnim, {
toValue: 0,
useNativeDriver: true,
tension: 40,
friction: 7
}).start();
} else {
Animated.timing(slideAnim, {
toValue: -150,
duration: 300,
useNativeDriver: true,
}).start();
}
}, [visible]);
if (!visible && !hasShownRef.current) return null;
const getTheme = () => {
switch (type) {
case 'warning': return { bg: '#FFB000', icon: 'alert-circle', text: '#000' };
case 'danger': return { bg: colors.error, icon: 'slash', text: '#FFF' };
default: return { bg: colors.primary, icon: 'info', text: isDark ? '#000' : '#000' };
}
};
const theme = getTheme();
return (
<Animated.View
style={[
styles.container,
{
backgroundColor: theme.bg,
transform: [{ translateY: slideAnim }]
}
]}
>
<View style={styles.content}>
<Feather name={theme.icon as any} size={18} color={theme.text} />
<Text style={[styles.message, { color: theme.text }]}>{message}</Text>
<TouchableOpacity onPress={onClose} style={styles.closeBtn}>
<Feather name="x" size={18} color={theme.text} />
</TouchableOpacity>
</View>
</Animated.View>
);
};
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
left: 0,
right: 0,
zIndex: 2000,
paddingTop: Platform.OS === 'ios' ? 50 : 30,
paddingBottom: 15,
paddingHorizontal: 20,
shadowColor: '#000',
shadowOffset: { width: 0, height: 4 },
shadowOpacity: 0.15,
shadowRadius: 10,
elevation: 10,
},
content: {
flexDirection: 'row',
alignItems: 'center',
gap: 12,
},
message: {
flex: 1,
fontSize: 13,
fontFamily: 'Outfit_600SemiBold',
lineHeight: 18,
},
closeBtn: {
padding: 4,
opacity: 0.7,
}
});