Skip to content

Commit

Permalink
abstract out the species info into component
Browse files Browse the repository at this point in the history
  • Loading branch information
in-mai-space committed Nov 27, 2024
1 parent b09e32c commit 8816ae4
Show file tree
Hide file tree
Showing 9 changed files with 222 additions and 130 deletions.
67 changes: 60 additions & 7 deletions frontend/app/(app)/(tabs)/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,54 @@ import { DEFAULT_SHERM_LOCATION } from '../../../consts/location';
import { PROFILE_PHOTO } from '../../../consts/profile';
import { useNearbyDiveLogs } from '../../../hooks/divelog';
import FilterMenu from '../../../components/home/filter';
import InfoPopup from '../../../components/info-popup';
import usePulsingAnimation from '../../../utils/skeleton';
import { useInfoPopup } from '../../../contexts/info-popup-context';
import InfoPopup from '../../../components/info-popup';
import SpeciesInfo from '../../../components/species-info';

const speciesData = {
_id: '6746410540c040de1093b6a2',
domain: 'Q19088',
kingdom: 'Q729',
phylum: 'Q10915',
class: 'Q127282',
order: 'Q127595',
family: 'Q465563',
genus: 'Q1515467',
species: 'Q674381',
aphiaId: '219665',
scientificName: 'Naso lituratus',
articleUrl: 'https://en.wikipedia.org/wiki/Naso_lituratus',
articleTitle: 'Naso lituratus',
commonNames: [
'Naso trang',
'Pacific orange-spine Unicorn',
'Striped Unicornfish',
'Orange-spine Unicornfish',
'Clown Tang',
'Poll Unicornfish',
'Redlip Surgeonfish',
'Masked Unicornfish',
'Striped-faced Unicornfish',
'Smooth-head Unicornfish',
'Barcheek Unicornfish',
'Orange Spine Surgeonfish',
],
imageUrls: [
'http://commons.wikimedia.org/wiki/Special:FilePath/Orangespine%20Unicornfish%20-%20Naso%20lituratus.jpg',
'http://commons.wikimedia.org/wiki/Special:FilePath/Orangespine%20unicornfish%20Naso%20lituratus.jpg',
],
locations: ['South China Sea'],
visibility: true,
introduction: `Naso lituratus, the clown unicornfish, orangespined unicornfish, black-finned unicornfish, Pacific orangespined unicornfish, blackfinned unicornfish or stripefaced unicornfish, is a species of marine ray-finned fish belonging to the family Acanthuridae, the surgeonfishes, unicornfishes and tangs. This fish is found in the eastern Indian Ocean and western Pacific Ocean.
Unique to members of Acanthuridae, including Naso lituratus, are the Epulopiscium bacteria. These bacteria influence the digestion of Naso lituratus, helping them process the algae in their diet.
Naso lituratus can be found in the Indian Ocean and the Pacific Ocean. This species can be easily recognised by two bright orange forward-hooked spines on the caudal peduncle (the tail base), its orange lips and black face mask. The body is brownish grey with yellow nape and there is a broad black band on the dorsal fin. It reaches about 45 cm (18 in) in length.
It can be found on coral reefs, often in pairs.`,
iconUrl: 'https://dodo.ac/np/images/0/00/Black_Bass_NH_Icon.png',
};

const Home = () => {
const { setClose } = useInfoPopup();
const { mongoDBId } = useAuthStore();
const [selectedCategory, setSelectedCategory] = useState<Category>(
Category.FOLLOWING,
Expand All @@ -37,6 +81,7 @@ const Home = () => {
]);
const opacity = usePulsingAnimation();

// hooks call for following posts
const {
data: followingPosts,
isLoading: isLoadingFollowingPosts,
Expand All @@ -47,6 +92,7 @@ const Home = () => {
isRefetching: isRefetchingFollowingPosts,
} = useUserFollowingPosts(mongoDBId!, selectedFilters);

// hooks call for nearby posts
const {
data: nearbyPosts,
isLoading: isLoadingNearby,
Expand All @@ -60,6 +106,7 @@ const Home = () => {
selectedFilters,
);

// fetch the current location of user
useEffect(() => {
const fetchLocation = async () => {
const { status } = await Location.requestForegroundPermissionsAsync();
Expand All @@ -77,14 +124,17 @@ const Home = () => {
fetchLocation();
}, [selectedCategory]);

// refetch to when filters or categories change
useEffect(() => {
setClose();
if (selectedCategory === Category.NEARBY) {
refetchNearByPosts();
} else {
refetchFollowingPosts();
}
}, [selectedFilters, selectedCategory]);

// render a following post
const renderFollowingPost = ({ item }: { item: any }) => (
<View className="w-full">
<BigDiveLog
Expand All @@ -101,6 +151,7 @@ const Home = () => {
</View>
);

// render a nearby post
const renderNearbyPost = ({ item, index }: { item: any; index: number }) => (
<View className={`mb-4 ${index % 2 === 0 ? 'mr-2' : 'ml-2'}`}>
<NearbyDiveLog
Expand All @@ -118,19 +169,21 @@ const Home = () => {
}
};

// component to show no post found
const NoPostFound = () => (
<View className="w-full items-center mt-5">
<Text className="text-gray-500">No posts found</Text>
</View>
);

// render posts based on category selected
const renderPosts = () => {
if (selectedCategory === Category.FOLLOWING) {
return renderFollowingPosts();
}
return renderNearbyPosts();
};

const NoPostFound = () => (
<View className="w-full items-center mt-5">
<Text className="text-gray-500">No posts found</Text>
</View>
);

const renderFollowingPosts = () => {
if (isLoadingFollowingPosts || isRefetchingFollowingPosts) {
return (
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/(app)/divelog/[id].tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useLocalSearchParams } from 'expo-router';
import { Dimensions, SafeAreaView, ScrollView, Text, View } from 'react-native';
import InfoPopup from '../../../components/info-popup';
import { useDiveLog } from '../../../hooks/divelog';
import React, { useState, useCallback } from 'react';
import DiveLogSkeleton from './components/skeleton';
import BigDiveLog from '../../../components/divelog/divelog';
import { PROFILE_PHOTO } from '../../../consts/profile';
import InfoPopup from '../../../components/info-popup';

const DiveLog = () => {
const { id: diveLogId } = useLocalSearchParams<{ id: string }>();
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/(app)/user/components/menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import Animated, {
useAnimatedStyle,
withTiming,
} from 'react-native-reanimated';
import PopulatedInfoPopupButton from '../../../../components/populated-info-popup';
import { PROFILE_PHOTO } from '../../../../consts/profile';
import {
useUserById,
Expand All @@ -22,6 +21,7 @@ import DiveLogSkeleton from './skeleton/divelog-skeleton';
import SpeciesSkeleton from './skeleton/species-skeleton';
import Species from './species';
import BigDiveLog from '../../../../components/divelog/divelog';
import PopulatedInfoPopupButton from '../../../../components/populated-info-popup';

const Menu = ({ id }: { id: string }) => {
const { width } = Dimensions.get('window');
Expand Down
2 changes: 1 addition & 1 deletion frontend/app/(app)/user/components/user-profile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { FlatList, View } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import { useAuthStore } from '../../../../auth/authStore';
import Arrow from '../../../../components/arrow';
import InfoPopup from '../../../../components/info-popup';
import Badges from '.././components/badges';
import Header from '.././components/header';
import Menu from '.././components/menu';
import InfoPopup from '../../../../components/info-popup';

const User = ({ id }: { id: string }) => {
const { mongoDBId } = useAuthStore();
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/divelog/divelog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@ import { PROFILE_PHOTO } from '../../consts/profile';
import ImageCarousel from './carousel';
import LikeAndShare from './like-share';
import Caption from './caption';
import PopulatedInfoPopupButton from '../populated-info-popup';
import { useState, useEffect } from 'react';
import useLike from '../../hooks/like';
import { router } from 'expo-router';
import { timeAgo } from '../../utils/profile';
import { reverseGeocode } from '../../api/location';
import { useAuthStore } from '../../auth/authStore';
import PopulatedInfoPopupButton from '../populated-info-popup';

interface DiveLogProps {
userId: string;
Expand Down
116 changes: 7 additions & 109 deletions frontend/components/info-popup.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
import { useEffect, useRef, useState } from 'react';
import { useEffect, useRef } from 'react';
import {
Animated,
Dimensions,
Easing,
Modal,
PanResponder,
Pressable,
ScrollView,
Text,
View,
} from 'react-native';
import SpeciesInfo from './species-info';
import { useInfoPopup } from '../contexts/info-popup-context';
import { Image } from 'expo-image';
import ImageCarousel from './divelog/carousel';

const InfoPopup = () => {
const { speciesContent, isOpen, setClose } = useInfoPopup();
const [fullscreenIndex, setFullscreenIndex] = useState<number | null>(null);
const modalOpacity = useRef(new Animated.Value(0)).current;
const screenHeight = Dimensions.get('window').height;
const translateY = useRef(new Animated.Value(screenHeight)).current;
const scrollViewRef = useRef<ScrollView>(null);
Expand Down Expand Up @@ -55,22 +49,6 @@ const InfoPopup = () => {
}),
).current;

useEffect(() => {
if (fullscreenIndex !== null) {
Animated.timing(modalOpacity, {
toValue: 1,
duration: 300,
useNativeDriver: true,
}).start();
} else {
Animated.timing(modalOpacity, {
toValue: 0,
duration: 300,
useNativeDriver: true,
}).start();
}
}, [fullscreenIndex]);

useEffect(() => {
Animated.timing(translateY, {
toValue: isOpen ? 0 : screenHeight,
Expand All @@ -94,92 +72,12 @@ const InfoPopup = () => {
>
<View className="bg-slate-400 opacity-60 h-[6px] w-12 rounded-lg" />
</View>
<View
{...panResponder.panHandlers}
className="bg-primary-blue pt-12 pb-12 px-8 flex flex-row justify-between"
>
<View className="flex flex-col gap-1">
<Text className="text-sm">
📍{' '}
{speciesContent.locations?.length > 0
? speciesContent.locations.join(', ')
: 'Unknown'}
</Text>
<Text className="text-2xl font-semibold">
{speciesContent.commonNames && speciesContent.commonNames[0]}
</Text>
<Text className="text-sm italic">
{speciesContent.scientificName}
</Text>
</View>
<Image
className="h-32 w-32"
source={{
uri:
speciesContent.iconUrl ||
'https://dodo.ac/np/images/0/00/Black_Bass_NH_Icon.png',
}}
/>
</View>
<ScrollView ref={scrollViewRef} className="bg-white px-8 py-8 gap-y-2">
<View>
<View className="flex flex-row justify-between pb-2">
<Text className="text-xs font-bold">Photos:</Text>
</View>
{speciesContent.imageUrls?.length > 0 ? (
<ScrollView horizontal className="flex flex-row gap-2">
{speciesContent.imageUrls.map((url, i) => (
<Pressable key={i} onPress={() => setFullscreenIndex(i)}>
<Image
style={{ overlayColor: 'white' }}
className="w-20 h-20 rounded-xl overlay"
source={{ uri: url }}
/>
</Pressable>
))}
</ScrollView>
) : (
<View>
<Text>No Images Available</Text>
</View>
)}
</View>
<View className="border-background border-b-2" />
<View className="flex flex-col gap-y-2 h-full">
<Text className="text-xs font-bold">Description:</Text>
<Text className="text-xs">{speciesContent.introduction}</Text>
</View>
<View className="flex flex-col gap-y-2">
<Text className="text-xs font-bold">More Facts:</Text>
</View>
<View className="py-8"></View>
</ScrollView>
<SpeciesInfo
speciesContent={speciesContent}
scrollViewRef={scrollViewRef}
panResponder={panResponder}
/>
</View>

{fullscreenIndex !== null && (
<Modal transparent={true} visible={true}>
<Pressable
className="flex-1"
onPress={() => setFullscreenIndex(null)}
>
<Animated.View
className="absolute top-0 left-0 right-0 bottom-0"
style={{
opacity: modalOpacity,
backgroundColor: 'rgba(0, 0, 0, 0.8)',
}}
>
<View className="flex-1 pt-[60%]">
<ImageCarousel
rounded={false}
initialPage={fullscreenIndex}
data={speciesContent.imageUrls}
/>
</View>
</Animated.View>
</Pressable>
</Modal>
)}
</Animated.View>
);
};
Expand Down
1 change: 0 additions & 1 deletion frontend/components/search-result.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import Profile from './profile';
import { PROFILE_PHOTO } from '../consts/profile';
import { router } from 'expo-router';
import PopulatedInfoPopupButton from './populated-info-popup';
import SpeciesTag from '../app/(app)/user/components/species-tag';

type UserResult = {
profilePicture?: string;
Expand Down
Loading

0 comments on commit 8816ae4

Please sign in to comment.