Loading mobile/src/screens/activity_description/activity_description_page.tsx 0 → 100644 +128 −0 Original line number Diff line number Diff line import { View, Text, TouchableOpacity, StyleSheet, Image, Animated, ScrollView, Dimensions, } from "react-native"; import { FullPageLoader } from "../../components/full_page_loader/full_page_loader"; import { ApiRequestStatus } from "../../constants/api_request_states"; import { useGetActivityInfo } from "../../hooks/useGetActivityInfo"; import { router } from "expo-router"; import { Ionicons } from "@expo/vector-icons"; import { useCallback, useEffect, useRef, useState } from "react"; import { ActivityBottomSheet } from "../../components/activity_bottom_sheet/activity_bottom_sheet"; import * as ScreenOrientation from "expo-screen-orientation"; import { LIGTHT_THEME } from "../../constants/theme"; import { useScreenOrientation } from "../../hooks/useScreenOrientation"; import { useRotationEnabled } from "../../hooks/useRotationEnabled"; import { FloatingBackButton } from "../../components/floating_back_button/floating_back_button"; interface ActivityDescriptionPageProps { activityId: number; } const startSnapPoint = 2; const revertedSnapPoints = [0.9, 0.5, 0.3]; const snapPoints = ["10%", "50%", "70%"]; const heigth = Dimensions.get("window").height; export const ActivityDescriptionPage = ({ activityId, }: ActivityDescriptionPageProps) => { const { isPortrait } = useScreenOrientation(); const { activityInfo, requestStatus } = useGetActivityInfo(activityId); useRotationEnabled(); const animationRef = useRef( new Animated.Value(heigth * revertedSnapPoints[startSnapPoint]) ).current; useEffect(() => { Animated.timing(animationRef, { toValue: Dimensions.get("window").height * revertedSnapPoints[startSnapPoint], duration: 100, useNativeDriver: false, }).start(); }, [isPortrait]); if (requestStatus === ApiRequestStatus.LOADING) { return <FullPageLoader />; } if (activityInfo === undefined) { return ( <View> <Text>Activity not found</Text> </View> ); } const handleSnapPointChange = (index: number) => { Animated.timing(animationRef, { toValue: heigth * revertedSnapPoints[index], duration: 100, useNativeDriver: false, }).start(); }; //TODO: Check if description is available if (!activityInfo.description) { activityInfo.description = "No description available"; } return ( <View style={styles.container}> <FloatingBackButton /> <Animated.Image source={{ uri: activityInfo.imageUri }} style={{ height: isPortrait ? animationRef : "100%", width: "100%", }} resizeMode="contain" /> {isPortrait && ( <ActivityBottomSheet activity={activityInfo} startSnapPoint={startSnapPoint} snapPoints={snapPoints} onSnapPointChange={handleSnapPointChange} /> )} </View> ); }; const styles = StyleSheet.create({ container: { height: "100%", width: "100%", backgroundColor: LIGTHT_THEME.color.black, alignItems: "center", justifyContent: "flex-start", }, activity_info_container: { borderTopLeftRadius: 20, borderTopRightRadius: 20, borderWidth: 5, padding: 20, }, name_text: { fontSize: 24, fontWeight: "bold", }, description_container: { marginTop: 10, gap: 5, }, description_text: { fontSize: 18, fontWeight: "bold", }, show_more_text: { fontWeight: "600", }, }); Loading
mobile/src/screens/activity_description/activity_description_page.tsx 0 → 100644 +128 −0 Original line number Diff line number Diff line import { View, Text, TouchableOpacity, StyleSheet, Image, Animated, ScrollView, Dimensions, } from "react-native"; import { FullPageLoader } from "../../components/full_page_loader/full_page_loader"; import { ApiRequestStatus } from "../../constants/api_request_states"; import { useGetActivityInfo } from "../../hooks/useGetActivityInfo"; import { router } from "expo-router"; import { Ionicons } from "@expo/vector-icons"; import { useCallback, useEffect, useRef, useState } from "react"; import { ActivityBottomSheet } from "../../components/activity_bottom_sheet/activity_bottom_sheet"; import * as ScreenOrientation from "expo-screen-orientation"; import { LIGTHT_THEME } from "../../constants/theme"; import { useScreenOrientation } from "../../hooks/useScreenOrientation"; import { useRotationEnabled } from "../../hooks/useRotationEnabled"; import { FloatingBackButton } from "../../components/floating_back_button/floating_back_button"; interface ActivityDescriptionPageProps { activityId: number; } const startSnapPoint = 2; const revertedSnapPoints = [0.9, 0.5, 0.3]; const snapPoints = ["10%", "50%", "70%"]; const heigth = Dimensions.get("window").height; export const ActivityDescriptionPage = ({ activityId, }: ActivityDescriptionPageProps) => { const { isPortrait } = useScreenOrientation(); const { activityInfo, requestStatus } = useGetActivityInfo(activityId); useRotationEnabled(); const animationRef = useRef( new Animated.Value(heigth * revertedSnapPoints[startSnapPoint]) ).current; useEffect(() => { Animated.timing(animationRef, { toValue: Dimensions.get("window").height * revertedSnapPoints[startSnapPoint], duration: 100, useNativeDriver: false, }).start(); }, [isPortrait]); if (requestStatus === ApiRequestStatus.LOADING) { return <FullPageLoader />; } if (activityInfo === undefined) { return ( <View> <Text>Activity not found</Text> </View> ); } const handleSnapPointChange = (index: number) => { Animated.timing(animationRef, { toValue: heigth * revertedSnapPoints[index], duration: 100, useNativeDriver: false, }).start(); }; //TODO: Check if description is available if (!activityInfo.description) { activityInfo.description = "No description available"; } return ( <View style={styles.container}> <FloatingBackButton /> <Animated.Image source={{ uri: activityInfo.imageUri }} style={{ height: isPortrait ? animationRef : "100%", width: "100%", }} resizeMode="contain" /> {isPortrait && ( <ActivityBottomSheet activity={activityInfo} startSnapPoint={startSnapPoint} snapPoints={snapPoints} onSnapPointChange={handleSnapPointChange} /> )} </View> ); }; const styles = StyleSheet.create({ container: { height: "100%", width: "100%", backgroundColor: LIGTHT_THEME.color.black, alignItems: "center", justifyContent: "flex-start", }, activity_info_container: { borderTopLeftRadius: 20, borderTopRightRadius: 20, borderWidth: 5, padding: 20, }, name_text: { fontSize: 24, fontWeight: "bold", }, description_container: { marginTop: 10, gap: 5, }, description_text: { fontSize: 18, fontWeight: "bold", }, show_more_text: { fontWeight: "600", }, });