diff --git a/src/components/HomeSlider/SliderDots.tsx b/src/components/HomeSlider/SliderDots.tsx new file mode 100644 index 0000000..8d7b27f --- /dev/null +++ b/src/components/HomeSlider/SliderDots.tsx @@ -0,0 +1,20 @@ +import { View } from 'react-native'; + +const SliderDots = ({ count = 0, activeIndex = 0 }) => ( + + {Array(count) + .fill('') + .map((_, index) => ( + + ))} + +); + +export default SliderDots; diff --git a/src/components/HomeSlider/SliderItem.tsx b/src/components/HomeSlider/SliderItem.tsx new file mode 100644 index 0000000..06d22f7 --- /dev/null +++ b/src/components/HomeSlider/SliderItem.tsx @@ -0,0 +1,49 @@ +import { text } from '@theme/text'; +import { ImageBackground, Pressable, StyleSheet, Text, View } from 'react-native'; + +import { SLIDER_ITEM_HEIGHT, SLIDER_ITEM_WIDTH } from '.'; + +type Props = { + image: string; + title: string; + onPress: () => void; + categoryName: string; +}; + +const SliderItem = ({ image, categoryName, title, onPress }: Props) => ( + + + + + + + + {categoryName} + + + + {title} + + + + + +); + +const styles = StyleSheet.create({ + sliderContent: { paddingRight: 16 }, + sliderItemContainer: { width: SLIDER_ITEM_WIDTH, height: SLIDER_ITEM_HEIGHT, overflow: 'hidden' }, + sliderImageBg: { width: SLIDER_ITEM_WIDTH - 16, height: SLIDER_ITEM_HEIGHT - 16 }, +}); + +export default SliderItem; diff --git a/src/components/HomeSlider/index.tsx b/src/components/HomeSlider/index.tsx new file mode 100644 index 0000000..e2b2ed0 --- /dev/null +++ b/src/components/HomeSlider/index.tsx @@ -0,0 +1,73 @@ +import categoryStore from '@store/CategoryStore'; +import { PostType } from '@store/PostStore'; +import { width } from '@utils/helpers'; +import { observer } from 'mobx-react-lite'; +import { useState } from 'react'; +import { + FlatList, + ListRenderItem, + NativeScrollEvent, + NativeSyntheticEvent, + StyleSheet, + View, +} from 'react-native'; + +import SliderDots from './SliderDots'; +import SliderItem from './SliderItem'; + +export const SLIDER_ITEM_HEIGHT = width / 2; + +export const SLIDER_PADDING_HORIZONTAL = 32; + +export const SLIDER_ITEM_WIDTH = width - SLIDER_PADDING_HORIZONTAL; + +type Props = { + posts: PostType[]; + onPressPost: (post: PostType) => void; +}; + +const HomeSlider = ({ posts, onPressPost }: Props) => { + const [sliderIndex, setSliderIndex] = useState(0); + const onScroll = (event: NativeSyntheticEvent) => { + const index = Math.round(event.nativeEvent.contentOffset.x / width); + + if (index >= 0) { + setSliderIndex(index); + } + }; + + const RenderItem: ListRenderItem = ({ item }) => ( + onPressPost(item)} + categoryName={item.category || categoryStore.categoryName(item.categories || [])} + /> + ); + + return ( + + + + + ); +}; + +const styles = StyleSheet.create({ + sliderContent: { paddingRight: 16 }, + sliderItemContainer: { width: SLIDER_ITEM_WIDTH, height: SLIDER_ITEM_HEIGHT }, +}); + +export default observer(HomeSlider); diff --git a/src/screens/Blog/HomeScreen.tsx b/src/screens/Blog/HomeScreen.tsx index 52f6662..12692d6 100644 --- a/src/screens/Blog/HomeScreen.tsx +++ b/src/screens/Blog/HomeScreen.tsx @@ -1,30 +1,49 @@ +import HomeSlider from '@components/HomeSlider'; import Post from '@containers/Post'; import { BlogStackNavigatorParamList } from '@navigators/BlogNavigator'; import { NavigationProp, useNavigation } from '@react-navigation/native'; import postStore, { PostType } from '@store/PostStore'; +import savedStore from '@store/SavedStore'; +import searchStore from '@store/SearchStore'; import colors from '@theme/colors'; +import { text } from '@theme/text'; import { observer } from 'mobx-react-lite'; import { useEffect } from 'react'; -import { ActivityIndicator, FlatList, ListRenderItem, View } from 'react-native'; +import { ActivityIndicator, FlatList, ListRenderItem, Text, View } from 'react-native'; const BlogHomeScreen = () => { const { navigate } = useNavigation>(); - const posts = Array.from(postStore.posts.values()); useEffect( () => () => { postStore.clearAll(); + savedStore.clearAll(); + searchStore.clearAll(); }, [], ); const RenderItem: ListRenderItem = ({ item: post }) => ( - navigate('PostDetail', { post })} /> + + navigate('PostDetail', { post })} /> + + ); + + const RenderListHeader = () => ( + + navigate('PostDetail', { post })} + /> + + All Posts + + ); return ( - - {postStore.loading && posts.length > 0 && ( + + {postStore.loading && postStore.listingPosts.length > 0 && ( { /> )} } /> diff --git a/src/store/PostStore.ts b/src/store/PostStore.ts index e66c50e..fcc93f1 100644 --- a/src/store/PostStore.ts +++ b/src/store/PostStore.ts @@ -53,12 +53,15 @@ const PostStore = t loading: t.optional(t.boolean, false), }) .views(self => ({ - get fetchPosts() { - return Array.from(self.posts.values()); + get listingPosts() { + return Array.from(self.posts.values()).slice(4, self.posts.size); }, getSelectedPost(id: string) { return self.posts.get(id); }, + get sliderPosts() { + return Array.from(self.posts.values()).slice(0, 4); + }, })) .actions(self => ({ setUrl: (url: string) => { diff --git a/src/theme/colors.js b/src/theme/colors.js index d0107e0..6454b37 100644 --- a/src/theme/colors.js +++ b/src/theme/colors.js @@ -1,6 +1,10 @@ module.exports = { white: '#ffffff', black: '#000000', + 'black-o': { + 40: 'rgba(0,0,0,0.4)', + 50: 'rgba(0,0,0,0.5)', + }, zinc: { 50: '#fafafa', 100: '#f4f4f5',