diff --git a/src/hooks/index.ts b/src/hooks/index.ts new file mode 100644 index 00000000..ea45c748 --- /dev/null +++ b/src/hooks/index.ts @@ -0,0 +1,5 @@ +export { useFeed } from './useFeed'; +export { useItem } from './useItem'; +export { useUser } from './useUser'; +export { usePollResults } from './usePollResults'; +export type { Story, User, PollResult, Comment, FeedType } from './types'; diff --git a/src/hooks/types.ts b/src/hooks/types.ts new file mode 100644 index 00000000..5eb9853d --- /dev/null +++ b/src/hooks/types.ts @@ -0,0 +1,44 @@ +export type FeedType = 'poll' | 'story' | 'job'; + +export interface Comment { + id: number; + level: number; + user: string; + time: number; + time_ago: string; + content: string; + deleted: boolean; + comments: Comment[]; +} + +export interface PollResult { + points: number; + content: string; +} + +export interface Story { + id: number; + title: string; + points: number; + user: string; + time: number; + time_ago: number; + type: FeedType; + url: string; + domain: string; + comments: Comment[]; + comments_count: number; + poll: PollResult[]; + poll_votes_count: number; + deleted: boolean; + dead: boolean; +} + +export interface User { + id: string; + crated_time: number; + created: string; + karma: number; + avg: number; + about: string; +} diff --git a/src/hooks/useFeed.ts b/src/hooks/useFeed.ts new file mode 100644 index 00000000..d0680b8c --- /dev/null +++ b/src/hooks/useFeed.ts @@ -0,0 +1,19 @@ +import { useQuery, UseQueryResult } from '@tanstack/react-query'; +import { Story } from './types'; + +const BASE_URL = 'https://node-hnapi.herokuapp.com'; + +async function fetchFeed(feedType: string, page: number): Promise { + const response = await fetch(`${BASE_URL}/${feedType}?page=${page}`); + if (!response.ok) { + throw new Error(`Failed to fetch feed: ${response.statusText}`); + } + return response.json(); +} + +export function useFeed(feedType: string, page: number): UseQueryResult { + return useQuery({ + queryKey: ['feed', feedType, page], + queryFn: () => fetchFeed(feedType, page), + }); +} diff --git a/src/hooks/useItem.ts b/src/hooks/useItem.ts new file mode 100644 index 00000000..68f70c9e --- /dev/null +++ b/src/hooks/useItem.ts @@ -0,0 +1,44 @@ +import { useQuery, UseQueryResult } from '@tanstack/react-query'; +import { Story, PollResult } from './types'; + +const BASE_URL = 'https://node-hnapi.herokuapp.com'; + +async function fetchPollOption(id: number): Promise { + const response = await fetch(`${BASE_URL}/item/${id}`); + if (!response.ok) { + throw new Error(`Failed to fetch poll option: ${response.statusText}`); + } + return response.json(); +} + +async function fetchItem(id: number): Promise { + const response = await fetch(`${BASE_URL}/item/${id}`); + if (!response.ok) { + throw new Error(`Failed to fetch item: ${response.statusText}`); + } + const story: Story = await response.json(); + + if (story.type === 'poll') { + const numberOfPollOptions = story.poll.length; + const pollPromises: Promise[] = []; + for (let i = 1; i <= numberOfPollOptions; i++) { + pollPromises.push(fetchPollOption(story.id + i)); + } + const pollResults = await Promise.all(pollPromises); + story.poll = pollResults; + story.poll_votes_count = pollResults.reduce( + (total, result) => total + result.points, + 0 + ); + } + + return story; +} + +export function useItem(id: number): UseQueryResult { + return useQuery({ + queryKey: ['item', id], + queryFn: () => fetchItem(id), + enabled: id > 0, + }); +} diff --git a/src/hooks/usePollResults.ts b/src/hooks/usePollResults.ts new file mode 100644 index 00000000..0bcdf9af --- /dev/null +++ b/src/hooks/usePollResults.ts @@ -0,0 +1,20 @@ +import { useQuery, UseQueryResult } from '@tanstack/react-query'; +import { PollResult } from './types'; + +const BASE_URL = 'https://node-hnapi.herokuapp.com'; + +async function fetchPollResults(id: number): Promise { + const response = await fetch(`${BASE_URL}/item/${id}`); + if (!response.ok) { + throw new Error(`Failed to fetch poll results: ${response.statusText}`); + } + return response.json(); +} + +export function usePollResults(id: number): UseQueryResult { + return useQuery({ + queryKey: ['pollResults', id], + queryFn: () => fetchPollResults(id), + enabled: id > 0, + }); +} diff --git a/src/hooks/useUser.ts b/src/hooks/useUser.ts new file mode 100644 index 00000000..36bc116a --- /dev/null +++ b/src/hooks/useUser.ts @@ -0,0 +1,20 @@ +import { useQuery, UseQueryResult } from '@tanstack/react-query'; +import { User } from './types'; + +const BASE_URL = 'https://node-hnapi.herokuapp.com'; + +async function fetchUser(id: string): Promise { + const response = await fetch(`${BASE_URL}/user/${id}`); + if (!response.ok) { + throw new Error(`Failed to fetch user: ${response.statusText}`); + } + return response.json(); +} + +export function useUser(id: string): UseQueryResult { + return useQuery({ + queryKey: ['user', id], + queryFn: () => fetchUser(id), + enabled: id.length > 0, + }); +}