diff --git a/package-lock.json b/package-lock.json
index c8cb542..ba3cfcf 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -67,6 +67,7 @@
"@storybook/node-logger": "^6.3.12",
"@storybook/preset-create-react-app": "^3.2.0",
"@storybook/react": "^6.3.12",
+ "@types/lodash.debounce": "^4.0.6",
"@types/lodash.throttle": "^4.1.6",
"@types/react-copy-to-clipboard": "^5.0.2",
"autoprefixer": "^9.8.8",
@@ -9612,6 +9613,15 @@
"integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==",
"dev": true
},
+ "node_modules/@types/lodash.debounce": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.6.tgz",
+ "integrity": "sha512-4WTmnnhCfDvvuLMaF3KV4Qfki93KebocUF45msxhYyjMttZDQYzHkO639ohhk8+oco2cluAFL3t5+Jn4mleylQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/lodash": "*"
+ }
+ },
"node_modules/@types/lodash.throttle": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/@types/lodash.throttle/-/lodash.throttle-4.1.6.tgz",
@@ -68051,6 +68061,15 @@
"integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==",
"dev": true
},
+ "@types/lodash.debounce": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.6.tgz",
+ "integrity": "sha512-4WTmnnhCfDvvuLMaF3KV4Qfki93KebocUF45msxhYyjMttZDQYzHkO639ohhk8+oco2cluAFL3t5+Jn4mleylQ==",
+ "dev": true,
+ "requires": {
+ "@types/lodash": "*"
+ }
+ },
"@types/lodash.throttle": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/@types/lodash.throttle/-/lodash.throttle-4.1.6.tgz",
diff --git a/package.json b/package.json
index 4f9f345..3286bf5 100644
--- a/package.json
+++ b/package.json
@@ -117,6 +117,7 @@
"@storybook/node-logger": "^6.3.12",
"@storybook/preset-create-react-app": "^3.2.0",
"@storybook/react": "^6.3.12",
+ "@types/lodash.debounce": "^4.0.6",
"@types/lodash.throttle": "^4.1.6",
"@types/react-copy-to-clipboard": "^5.0.2",
"autoprefixer": "^9.8.8",
diff --git a/src/features/Posts/Components/PostCard/BountyCard.stories.tsx b/src/features/Posts/Components/PostCard/BountyCard/BountyCard.stories.tsx
similarity index 100%
rename from src/features/Posts/Components/PostCard/BountyCard.stories.tsx
rename to src/features/Posts/Components/PostCard/BountyCard/BountyCard.stories.tsx
diff --git a/src/features/Posts/Components/PostCard/BountyCard.tsx b/src/features/Posts/Components/PostCard/BountyCard/BountyCard.tsx
similarity index 98%
rename from src/features/Posts/Components/PostCard/BountyCard.tsx
rename to src/features/Posts/Components/PostCard/BountyCard/BountyCard.tsx
index 0bdce44..736116e 100644
--- a/src/features/Posts/Components/PostCard/BountyCard.tsx
+++ b/src/features/Posts/Components/PostCard/BountyCard/BountyCard.tsx
@@ -1,6 +1,6 @@
import VotesCount from "src/Components/VotesCount/VotesCount"
import { Bounty } from "src/features/Posts/types"
-import Header from "./Header"
+import Header from "../Header/Header"
import { FiUsers } from "react-icons/fi"
import Badge from "src/Components/Badge/Badge"
import Button from "src/Components/Button/Button"
diff --git a/src/features/Posts/Components/PostCard/Header/Header.Skeleton.tsx b/src/features/Posts/Components/PostCard/Header/Header.Skeleton.tsx
new file mode 100644
index 0000000..9917276
--- /dev/null
+++ b/src/features/Posts/Components/PostCard/Header/Header.Skeleton.tsx
@@ -0,0 +1,24 @@
+import Avatar from 'src/features/Profiles/Components/Avatar/Avatar';
+import dayjs from 'dayjs'
+import Skeleton from 'react-loading-skeleton';
+
+interface Props {
+ size?: 'sm' | 'md'
+}
+
+export default function HeaderSkeleton({ size = 'md', }: Props) {
+
+ return (
+
+ )
+}
diff --git a/src/features/Posts/Components/PostCard/Header.tsx b/src/features/Posts/Components/PostCard/Header/Header.tsx
similarity index 100%
rename from src/features/Posts/Components/PostCard/Header.tsx
rename to src/features/Posts/Components/PostCard/Header/Header.tsx
diff --git a/src/features/Posts/Components/PostCard/PostCard/PostCard.Skeleton.tsx b/src/features/Posts/Components/PostCard/PostCard/PostCard.Skeleton.tsx
new file mode 100644
index 0000000..9fab751
--- /dev/null
+++ b/src/features/Posts/Components/PostCard/PostCard/PostCard.Skeleton.tsx
@@ -0,0 +1,29 @@
+import Skeleton from "react-loading-skeleton"
+import HeaderSkeleton from "../Header/Header.Skeleton"
+import Badge from 'src/Components/Badge/Badge'
+
+export default function PostCardSkeleton() {
+ return
+}
diff --git a/src/features/Posts/Components/PostCard/PostCard/PostCard.stories.tsx b/src/features/Posts/Components/PostCard/PostCard/PostCard.stories.tsx
new file mode 100644
index 0000000..bc31427
--- /dev/null
+++ b/src/features/Posts/Components/PostCard/PostCard/PostCard.stories.tsx
@@ -0,0 +1,29 @@
+import { ComponentStory, ComponentMeta } from '@storybook/react';
+import { MOCK_DATA } from 'src/mocks/data';
+
+import PostCard from './PostCard';
+import PostCardSkeleton from './PostCard.Skeleton';
+
+export default {
+ title: 'Posts/Components/PostCard',
+ component: PostCard,
+ argTypes: {
+ backgroundColor: { control: 'color' },
+ },
+} as ComponentMeta;
+
+
+const Template: ComponentStory = (args) =>
+
+export const Default = Template.bind({});
+Default.args = {
+ post: MOCK_DATA['posts'].stories[0]
+}
+
+const LoadingTemplate: ComponentStory = (args) =>
+
+export const Loading = LoadingTemplate.bind({});
+Loading.args = {
+}
+
+
diff --git a/src/features/Posts/Components/PostCard/PostCard.tsx b/src/features/Posts/Components/PostCard/PostCard/PostCard.tsx
similarity index 70%
rename from src/features/Posts/Components/PostCard/PostCard.tsx
rename to src/features/Posts/Components/PostCard/PostCard/PostCard.tsx
index bf0802e..324df10 100644
--- a/src/features/Posts/Components/PostCard/PostCard.tsx
+++ b/src/features/Posts/Components/PostCard/PostCard/PostCard.tsx
@@ -1,7 +1,7 @@
import { Post, isStory, isBounty, isQuestion } from "src/features/Posts/types"
-import BountyCard from "./BountyCard"
-import QuestionCard from "./QuestionCard"
-import StoryCard from "./StoryCard"
+import BountyCard from "../BountyCard/BountyCard"
+import QuestionCard from "../QuestionCard/QuestionCard"
+import StoryCard from "../StoryCard/StoryCard"
type Props = {
post: Post
diff --git a/src/features/Posts/Components/PostCard/QuestionCard.stories.tsx b/src/features/Posts/Components/PostCard/QuestionCard/QuestionCard.stories.tsx
similarity index 100%
rename from src/features/Posts/Components/PostCard/QuestionCard.stories.tsx
rename to src/features/Posts/Components/PostCard/QuestionCard/QuestionCard.stories.tsx
diff --git a/src/features/Posts/Components/PostCard/QuestionCard.tsx b/src/features/Posts/Components/PostCard/QuestionCard/QuestionCard.tsx
similarity index 98%
rename from src/features/Posts/Components/PostCard/QuestionCard.tsx
rename to src/features/Posts/Components/PostCard/QuestionCard/QuestionCard.tsx
index 60b073e..47eca06 100644
--- a/src/features/Posts/Components/PostCard/QuestionCard.tsx
+++ b/src/features/Posts/Components/PostCard/QuestionCard/QuestionCard.tsx
@@ -1,6 +1,6 @@
import VotesCount from "src/Components/VotesCount/VotesCount"
import { Question } from "src/features/Posts/types"
-import Header from "./Header"
+import Header from "../Header/Header"
import { FiUsers } from "react-icons/fi"
import Badge from "src/Components/Badge/Badge"
import Avatar from "src/features/Profiles/Components/Avatar/Avatar"
diff --git a/src/features/Posts/Components/PostCard/StoryCard.stories.tsx b/src/features/Posts/Components/PostCard/StoryCard/StoryCard.stories.tsx
similarity index 100%
rename from src/features/Posts/Components/PostCard/StoryCard.stories.tsx
rename to src/features/Posts/Components/PostCard/StoryCard/StoryCard.stories.tsx
diff --git a/src/features/Posts/Components/PostCard/StoryCard.tsx b/src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx
similarity index 96%
rename from src/features/Posts/Components/PostCard/StoryCard.tsx
rename to src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx
index 10af4e4..aa5f3df 100644
--- a/src/features/Posts/Components/PostCard/StoryCard.tsx
+++ b/src/features/Posts/Components/PostCard/StoryCard/StoryCard.tsx
@@ -1,6 +1,6 @@
import VotesCount from "src/Components/VotesCount/VotesCount"
import { Story } from "src/features/Posts/types"
-import Header from "./Header"
+import Header from "../Header/Header"
import { BiComment } from 'react-icons/bi'
interface Props {
diff --git a/src/features/Posts/Components/PostCard/index.tsx b/src/features/Posts/Components/PostCard/index.tsx
index bcdab81..dbbd0ac 100644
--- a/src/features/Posts/Components/PostCard/index.tsx
+++ b/src/features/Posts/Components/PostCard/index.tsx
@@ -1,2 +1,5 @@
+import PostCard from "./PostCard/PostCard";
-export { }
\ No newline at end of file
+export { default as PostCardSkeleton } from './PostCard/PostCard.Skeleton'
+
+export default PostCard;
\ No newline at end of file
diff --git a/src/features/Posts/Components/PostsList/PostsList.stories.tsx b/src/features/Posts/Components/PostsList/PostsList.stories.tsx
index f34894c..4bb226b 100644
--- a/src/features/Posts/Components/PostsList/PostsList.stories.tsx
+++ b/src/features/Posts/Components/PostsList/PostsList.stories.tsx
@@ -16,7 +16,7 @@ const Template: ComponentStory = (args) =>
export default function PostsList(props: Props) {
- const { data, loading } = useFeedQuery()
- if (loading) return
Loading
- return (
-
- {
- data?.getFeed.map(post =>
)
+
+ const reachedBottom = useCallback(() => {
+ console.log("NEW FETCH")
+ }, [])
+
+ const { ref } = useReachedBottom
(reachedBottom)
+
+ if (props.isLoading)
+ return
+
+ return (
+
+ {
+ props.items?.map(post =>
)
+ }
+ {props.isFetching &&
}
+
)
}
diff --git a/src/features/Posts/pages/FeedPage/FeedPage.tsx b/src/features/Posts/pages/FeedPage/FeedPage.tsx
index be484bd..282f0f8 100644
--- a/src/features/Posts/pages/FeedPage/FeedPage.tsx
+++ b/src/features/Posts/pages/FeedPage/FeedPage.tsx
@@ -1,4 +1,5 @@
+import { useFeedQuery } from 'src/graphql'
import { MOCK_DATA } from 'src/mocks/data'
import PostsList from '../../Components/PostsList/PostsList'
import TrendingCard from '../../Components/TrendingCard/TrendingCard'
@@ -7,17 +8,19 @@ import SortBy from './SortBy/SortBy'
import styles from './styles.module.css'
export default function FeedPage() {
+
+ const feedQuery = useFeedQuery()
+
return (
-
+
diff --git a/src/utils/hooks/useReachedBottom.ts b/src/utils/hooks/useReachedBottom.ts
new file mode 100644
index 0000000..1837ef6
--- /dev/null
+++ b/src/utils/hooks/useReachedBottom.ts
@@ -0,0 +1,30 @@
+import _debounce from "lodash.debounce";
+import { useEffect, useRef } from "react";
+
+export const useReachedBottom =
(cb?: () => void, options: Partial<{ offset: number, throttle: number }> = {}) => {
+
+ const { offset = window.innerHeight, throttle = 600 } = options
+
+ const ref = useRef(null);
+
+
+ useEffect(() => {
+ if (!cb) return;
+
+ const cbDebounced = _debounce(cb, throttle)
+ const listener = () => {
+ if (!ref.current) return;
+ const curWindowPosition = window.scrollY + window.innerHeight;
+ const elTriggerPosition = ref.current.offsetTop + ref.current.scrollHeight - offset;
+ if (curWindowPosition > elTriggerPosition) cbDebounced();
+ }
+
+ document.addEventListener('scroll', listener)
+
+ return () => {
+ document.removeEventListener('scroll', listener)
+ }
+ }, [cb, offset, throttle])
+
+ return { ref }
+}
\ No newline at end of file
diff --git a/src/utils/interfaces/misc.interfaces.ts b/src/utils/interfaces/misc.interfaces.ts
index d810cbb..2831c9c 100644
--- a/src/utils/interfaces/misc.interfaces.ts
+++ b/src/utils/interfaces/misc.interfaces.ts
@@ -4,4 +4,12 @@ export type Tag = {
title: string
}
+
+export type ListProps = {
+ items?: T[]
+ isLoading?: boolean;
+ isFetching?: boolean;
+ onReachedBottom?: () => void
+}
+
export type Image = string;
\ No newline at end of file