Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[react] Fetch reactions to story for content card #87

Merged
merged 21 commits into from
Apr 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/app/(tabs)/author/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import * as cheerio from 'cheerio';
import { useLocalSearchParams, router } from 'expo-router';
import { decode } from 'html-entities';
import { useEffect, useState } from 'react';
import { ActivityIndicator, ScrollView, View, Text, Image } from 'react-native';
import { ActivityIndicator, ScrollView, View, Text } from 'react-native';
import { Image } from 'expo-image';
import { SafeAreaView } from 'react-native-safe-area-context';

import styles from './styles';
Expand Down
2 changes: 2 additions & 0 deletions src/app/(tabs)/home/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ function HomeScreen() {
>
{recommendedStories.map(story => (
<ContentCard
id={story.id}
key={story.title}
title={story.title}
author={story.author_name}
Expand Down Expand Up @@ -159,6 +160,7 @@ function HomeScreen() {
>
{newStories.map(story => (
<ContentCard
id={story.id}
key={story.title}
title={story.title}
author={story.author_name}
Expand Down
22 changes: 15 additions & 7 deletions src/app/(tabs)/search/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,12 @@ import PreviewCard from '../../../components/PreviewCard/PreviewCard';
import RecentSearchCard from '../../../components/RecentSearchCard/RecentSearchCard';
import { fetchGenres } from '../../../queries/genres';
import { fetchAllStoryPreviews } from '../../../queries/stories';
import { StoryPreview, RecentSearch, Genre } from '../../../queries/types';
import {
StoryPreview,
RecentSearch,
Genre,
StoryPreviewWithPreloadedReactions,
} from '../../../queries/types';
import colors from '../../../styles/colors';
import globalStyles from '../../../styles/globalStyles';
import { GenreType } from '../genre';
Expand Down Expand Up @@ -62,9 +67,13 @@ const setRecentStory = async (recentStories: StoryPreview[]) => {
};

function SearchScreen() {
const [allStories, setAllStories] = useState<StoryPreview[]>([]);
const [allStories, setAllStories] = useState<
StoryPreviewWithPreloadedReactions[]
>([]);
const [allGenres, setAllGenres] = useState<Genre[]>([]);
const [searchResults, setSearchResults] = useState<StoryPreview[]>([]);
const [searchResults, setSearchResults] = useState<
StoryPreviewWithPreloadedReactions[]
>([]);
const [search, setSearch] = useState('');
const [filterVisible, setFilterVisible] = useState(false);
const [recentSearches, setRecentSearches] = useState<RecentSearch[]>([]);
Expand All @@ -75,9 +84,7 @@ function SearchScreen() {

useEffect(() => {
(async () => {
fetchAllStoryPreviews().then((stories: StoryPreview[]) =>
setAllStories(stories),
);
fetchAllStoryPreviews().then(stories => setAllStories(stories));
fetchGenres().then((genres: Genre[]) => setAllGenres(genres));
getRecentSearch().then((searches: RecentSearch[]) =>
setRecentSearches(searches),
Expand All @@ -99,7 +106,7 @@ function SearchScreen() {
return;
}

const updatedData = allStories.filter((item: StoryPreview) => {
const updatedData = allStories.filter(item => {
const title = `${item.title.toUpperCase()})`;
const author = `${item.author_name.toUpperCase()})`;
const text_data = text.toUpperCase();
Expand Down Expand Up @@ -400,6 +407,7 @@ function SearchScreen() {
storyId={item.id}
title={item.title}
image={item.featured_media}
reactions={item.reactions}
author={item.author_name}
authorImage={item.author_image}
excerpt={item.excerpt}
Expand Down
2 changes: 1 addition & 1 deletion src/app/(tabs)/story/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ import React, { useEffect, useState } from 'react';
import {
ActivityIndicator,
FlatList,
Image,
ScrollView,
Share,
Text,
TouchableOpacity,
View,
useWindowDimensions,
} from 'react-native';
import { Image } from 'expo-image';
import { Button } from 'react-native-paper';
import { RenderHTML } from 'react-native-render-html';
import { SafeAreaView } from 'react-native-safe-area-context';
Expand Down
5 changes: 2 additions & 3 deletions src/app/auth/verify/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { Link, Redirect, router, useLocalSearchParams } from 'expo-router';
import { Redirect, router, useLocalSearchParams } from 'expo-router';
import { useState, useRef, useEffect } from 'react';
import { View, Text } from 'react-native';
import { Icon } from 'react-native-elements';
import OTPTextInput from 'react-native-otp-textinput';
import { SafeAreaView } from 'react-native-safe-area-context';
import Toast, { BaseToast, BaseToastProps } from 'react-native-toast-message';
import Toast from 'react-native-toast-message';

import styles from './styles';
import BackButton from '../../../components/BackButton/BackButton';
Expand Down
3 changes: 2 additions & 1 deletion src/components/AuthorCard/AuthorCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Image, Text, View } from 'react-native';
import { Image } from 'expo-image';
import { Text, View } from 'react-native';
import styles from './styles';

type AuthorCardProps = {
Expand Down
42 changes: 23 additions & 19 deletions src/components/ContentCard/ContentCard.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import { Image } from 'expo-image';
import { useEffect, useState } from 'react';
import {
GestureResponderEvent,
Pressable,
Text,
View,
TouchableOpacity,
} from 'react-native';
import { Image } from 'expo-image';
import Emoji from 'react-native-emoji';

import styles from './styles';
import { fetchAllReactionsToStory } from '../../queries/reactions';
import { Reactions } from '../../queries/types';
import globalStyles from '../../styles/globalStyles';
import Emoji from 'react-native-emoji';
import SaveStoryButton from '../SaveStoryButton/SaveStoryButton';
import ReactionDisplay from '../ReactionDisplay/ReactionDisplay';

type ContentCardProps = {
id: number;
title: string;
author: string;
image: string;
Expand All @@ -22,13 +27,28 @@ type ContentCardProps = {
};

function ContentCard({
id,
title,
author,
image,
authorImage,
storyId,
pressFunction,
}: ContentCardProps) {
const [reactions, setReactions] = useState<string[]>();

useEffect(() => {
(async () => {
const temp = await fetchAllReactionsToStory(id);
if (temp != null) {
setReactions(temp.map(r => r.reaction));
return;
}

setReactions([]);
})();
}, []);

return (
<Pressable onPress={pressFunction}>
<View style={styles.contentCard}>
Expand Down Expand Up @@ -58,23 +78,7 @@ function ContentCard({
</Text>
</View>
<View style={styles.buttons}>
<View style={{ flexDirection: 'row', gap: -7 }}>
<View style={[styles.reactions, { backgroundColor: '#FFCCCB' }]}>
<Emoji name="heart" />
</View>
<View style={[styles.reactions, { backgroundColor: '#FFD580' }]}>
<Emoji name="clap" />
</View>
<View style={[styles.reactions, { backgroundColor: '#89CFF0' }]}>
<Emoji name="muscle" />
</View>
{/* heart, clap, muscle, cry, ??? */}
<View style={styles.reactionNumber}>
<Text style={[globalStyles.subtext, styles.reactionText]}>
14{/*change number to work*/}
</Text>
</View>
</View>
<ReactionDisplay reactions={reactions ?? []} />
<TouchableOpacity>
<SaveStoryButton storyId={storyId} />
</TouchableOpacity>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import {
GestureResponderEvent,
Text,
Image,
View,
TouchableOpacity,
} from 'react-native';
import { Image } from 'expo-image';

import styles from './styles';
import globalStyles from '../../styles/globalStyles';
Expand Down
46 changes: 25 additions & 21 deletions src/components/PreviewCard/PreviewCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import * as cheerio from 'cheerio';
import { Image } from 'expo-image';
import { useEffect, useState } from 'react';
import {
GestureResponderEvent,
Pressable,
Expand All @@ -7,11 +9,13 @@ import {
View,
} from 'react-native';
import Emoji from 'react-native-emoji';
import { Image } from 'expo-image';

import styles from './styles';
import { fetchAllReactionsToStory } from '../../queries/reactions';
import { Reactions } from '../../queries/types';
import globalStyles from '../../styles/globalStyles';
import SaveStoryButton from '../SaveStoryButton/SaveStoryButton';
import ReactionDisplay from '../ReactionDisplay/ReactionDisplay';

const placeholderImage =
'https://gwn-uploads.s3.amazonaws.com/wp-content/uploads/2021/10/10120952/Girls-Write-Now-logo-avatar.png';
Expand All @@ -24,6 +28,7 @@ type PreviewCardProps = {
authorImage: string;
excerpt: { html: string };
tags: string[];
reactions?: string[] | null;
pressFunction: (event: GestureResponderEvent) => void;
};

Expand All @@ -36,10 +41,25 @@ function PreviewCard({
excerpt,
tags,
pressFunction,
reactions: preloadedReactions = null,
}: PreviewCardProps) {
const saveStory = () => {
console.log("testing '+' icon does something for story " + title);
};
const [reactions, setReactions] = useState<string[] | null>(
preloadedReactions,
);
useEffect(() => {
if (preloadedReactions != null) {
return;
}

(async () => {
const temp = await fetchAllReactionsToStory(storyId);
if (temp != null) {
setReactions(temp.map(r => r.reaction));
return;
}
setReactions([]);
})();
}, []);

return (
<Pressable onPress={pressFunction}>
Expand Down Expand Up @@ -76,23 +96,7 @@ function PreviewCard({
</View>
</View>
<View style={styles.tagsContainer}>
<View style={{ flexDirection: 'row', gap: -7 }}>
<View style={[styles.reactions, { backgroundColor: '#FFCCCB' }]}>
<Emoji name="heart" />
</View>
<View style={[styles.reactions, { backgroundColor: '#FFD580' }]}>
<Emoji name="clap" />
</View>
<View style={[styles.reactions, { backgroundColor: '#89CFF0' }]}>
<Emoji name="muscle" />
</View>
{/* heart, clap, muscle, cry, ??? */}
<View style={styles.reactionNumber}>
<Text style={[globalStyles.subtext, styles.reactionText]}>
14{/*change number to work*/}
</Text>
</View>
</View>
<ReactionDisplay reactions={reactions ?? []} />
<View style={styles.tagsRow}>
{(tags?.length ?? 0) > 0 && (
<View style={styles.tag}>
Expand Down
60 changes: 60 additions & 0 deletions src/components/ReactionDisplay/ReactionDisplay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Text, View } from 'react-native';
import styles from './styles';
import Emoji from 'react-native-emoji';
import globalStyles from '../../styles/globalStyles';

type ReactionDisplayProps = {
reactions: string[];
};

function ReactionDisplay({ reactions }: ReactionDisplayProps) {
const reactionColors: Record<string, string> = {
heart: '#FFCCCB',
clap: '#FFD580',
cry: '#89CFF0',
hugging_face: '#ffc3bf',
muscle: '#eddcf7',
};
const defaultColor = reactionColors['heart'];
const setOfReactions = [...reactions];
setOfReactions.push('heart');
setOfReactions.push('clap');
setOfReactions.push('muscle');

const reactionDisplay = [...new Set(setOfReactions)].slice(0, 3);

return (
<View
style={{
flexDirection: 'row',
gap: -7,
}}
>
{reactionDisplay.map(reaction => {
return (
<View
key={reaction}
style={[
styles.reactions,
{
backgroundColor:
reaction in reactionColors
? reactionColors[reaction]
: defaultColor,
},
]}
>
<Emoji name={reaction} />
</View>
);
})}
<View style={styles.reactionNumber}>
<Text style={[globalStyles.subtext, styles.reactionText]}>
{reactions?.length ?? 0}
</Text>
</View>
</View>
);
}

export default ReactionDisplay;
27 changes: 27 additions & 0 deletions src/components/ReactionDisplay/styles.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { StyleSheet } from 'react-native';
import colors from '../../styles/colors';

const styles = StyleSheet.create({
reactions: {
width: 32,
height: 32,
borderRadius: 32 / 2,
borderWidth: 1,
backgroundColor: '#89CFF0', //different per emoji reaction
borderColor: 'white',
marginTop: 10,
marginRight: -5, // -10
overflow: 'hidden',
justifyContent: 'center',
paddingLeft: 4,
},
reactionText: {
color: colors.grey,
},
reactionNumber: {
marginLeft: 16,
marginTop: 16,
},
});

export default styles;
Loading
Loading