feat: add posts mocks handlesr, add post type gurads

This commit is contained in:
MTG2000
2022-04-17 12:23:46 +03:00
parent 7206910670
commit e5a0dc0843
10 changed files with 109 additions and 52 deletions

View File

@@ -37,7 +37,7 @@ const Story = objectType({
definition(t) {
t.implements('PostBase');
t.nonNull.string('type', {
resolve: () => 'story'
resolve: () => 'Story'
});
t.nonNull.string('cover_image');
t.nonNull.int('comments_count');
@@ -49,7 +49,7 @@ const Bounty = objectType({
definition(t) {
t.implements('PostBase');
t.nonNull.string('type', {
resolve: () => 'bounty'
resolve: () => 'Bounty'
});
t.nonNull.string('cover_image');
t.nonNull.string('deadline');
@@ -63,7 +63,8 @@ const Question = objectType({
definition(t) {
t.implements('PostBase');
t.nonNull.string('type', {
resolve: () => 'question'
resolve: () => 'Question',
});
t.nonNull.string('cover_image');
t.nonNull.string('deadline');

View File

@@ -1,4 +1,4 @@
import { Post } from "src/features/Posts/types"
import { Post, isStory, isBounty, isQuestion } from "src/features/Posts/types"
import BountyCard from "./BountyCard"
import QuestionCard from "./QuestionCard"
import StoryCard from "./StoryCard"
@@ -8,13 +8,13 @@ type Props = {
}
export default function PostCard({ post }: Props) {
if (post.type === 'story')
if (isStory(post))
return <StoryCard story={post} />
if (post.type === 'bounty')
if (isBounty(post))
return <BountyCard bounty={post} />
if (post.type === 'question')
if (isQuestion(post))
return <QuestionCard question={post} />
return null

View File

@@ -1,4 +1,5 @@
import { Post } from "src/features/Posts/types"
import { useFeedQuery } from "src/graphql"
import PostCard from "../PostCard/PostCard"
interface Props {
@@ -6,10 +7,13 @@ interface Props {
}
export default function PostsList(props: Props) {
const { data, loading } = useFeedQuery()
if (loading) return <h2>Loading</h2>
return (
<div className="flex flex-col gap-24">
{
props.posts.map(post => <PostCard key={post.id} post={post} />)
data?.getFeed.map(post => <PostCard key={post.id} post={post} />)
}
</div>
)

View File

@@ -1,4 +1,4 @@
query FeedQuery {
query Feed {
getFeed {
... on Story {
id

View File

@@ -1,4 +1,4 @@
query PostDetailsQuery($postId: Int!) {
query PostDetails($postId: Int!) {
getPostById(id: $postId) {
... on Story {
id

View File

@@ -7,7 +7,7 @@ export type User = {
}
export type Author = User & {
join_date: string
join_date?: string
}
export type PostBase = {
@@ -18,28 +18,38 @@ export type PostBase = {
excerpt: string
tags: Tag[]
votes_count: number
type: string
}
export type Story = PostBase & {
type: 'story'
cover_image: string;
comments_count: number
}
export function isStory(post: Post): post is Story {
return post.type === 'Story'
}
export type Bounty = PostBase & {
type: 'bounty'
cover_image: string;
reward_amount: number
deadline: string
applicants_count: number
}
export function isBounty(post: Post): post is Bounty {
return post.type === 'Bounty'
}
export type Question = PostBase & {
type: 'question'
answers_count: number
comments: PostComment[]
}
export function isQuestion(post: Post): post is Question {
return post.type === 'Question'
}
export type PostComment = {
id: number;
author: Author

View File

@@ -254,17 +254,17 @@ export type SearchProjectsQueryVariables = Exact<{
export type SearchProjectsQuery = { __typename?: 'Query', searchProjects: Array<{ __typename?: 'Project', id: number, thumbnail_image: string, title: string, category: { __typename?: 'Category', title: string, id: number } }> };
export type FeedQueryQueryVariables = Exact<{ [key: string]: never; }>;
export type FeedQueryVariables = Exact<{ [key: string]: never; }>;
export type FeedQueryQuery = { __typename?: 'Query', getFeed: Array<{ __typename?: 'Bounty', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Question', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, answers_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, date: string, body: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } | { __typename?: 'Story', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, comments_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> }> };
export type FeedQuery = { __typename?: 'Query', getFeed: Array<{ __typename?: 'Bounty', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Question', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, answers_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, date: string, body: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } | { __typename?: 'Story', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, comments_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> }> };
export type PostDetailsQueryQueryVariables = Exact<{
export type PostDetailsQueryVariables = Exact<{
postId: Scalars['Int'];
}>;
export type PostDetailsQueryQuery = { __typename?: 'Query', getPostById: { __typename?: 'Bounty', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Question', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, answers_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, date: string, body: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } | { __typename?: 'Story', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, comments_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } };
export type PostDetailsQuery = { __typename?: 'Query', getPostById: { __typename?: 'Bounty', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, applicants_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } | { __typename?: 'Question', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, deadline: string, reward_amount: number, answers_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }>, comments: Array<{ __typename?: 'PostComment', id: number, date: string, body: string, author: { __typename?: 'User', id: number, name: string, image: string } }> } | { __typename?: 'Story', id: number, title: string, date: string, excerpt: string, votes_count: number, type: string, cover_image: string, comments_count: number, author: { __typename?: 'User', id: number, name: string, image: string }, tags: Array<{ __typename?: 'Tag', id: number, title: string }> } };
export type CategoryPageQueryVariables = Exact<{
categoryId: Scalars['Int'];
@@ -390,8 +390,8 @@ export function useSearchProjectsLazyQuery(baseOptions?: Apollo.LazyQueryHookOpt
export type SearchProjectsQueryHookResult = ReturnType<typeof useSearchProjectsQuery>;
export type SearchProjectsLazyQueryHookResult = ReturnType<typeof useSearchProjectsLazyQuery>;
export type SearchProjectsQueryResult = Apollo.QueryResult<SearchProjectsQuery, SearchProjectsQueryVariables>;
export const FeedQueryDocument = gql`
query FeedQuery {
export const FeedDocument = gql`
query Feed {
getFeed {
... on Story {
id
@@ -469,33 +469,33 @@ export const FeedQueryDocument = gql`
`;
/**
* __useFeedQueryQuery__
* __useFeedQuery__
*
* To run a query within a React component, call `useFeedQueryQuery` and pass it any options that fit your needs.
* When your component renders, `useFeedQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties
* To run a query within a React component, call `useFeedQuery` and pass it any options that fit your needs.
* When your component renders, `useFeedQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useFeedQueryQuery({
* const { data, loading, error } = useFeedQuery({
* variables: {
* },
* });
*/
export function useFeedQueryQuery(baseOptions?: Apollo.QueryHookOptions<FeedQueryQuery, FeedQueryQueryVariables>) {
export function useFeedQuery(baseOptions?: Apollo.QueryHookOptions<FeedQuery, FeedQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<FeedQueryQuery, FeedQueryQueryVariables>(FeedQueryDocument, options);
return Apollo.useQuery<FeedQuery, FeedQueryVariables>(FeedDocument, options);
}
export function useFeedQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<FeedQueryQuery, FeedQueryQueryVariables>) {
export function useFeedLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<FeedQuery, FeedQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<FeedQueryQuery, FeedQueryQueryVariables>(FeedQueryDocument, options);
return Apollo.useLazyQuery<FeedQuery, FeedQueryVariables>(FeedDocument, options);
}
export type FeedQueryQueryHookResult = ReturnType<typeof useFeedQueryQuery>;
export type FeedQueryLazyQueryHookResult = ReturnType<typeof useFeedQueryLazyQuery>;
export type FeedQueryQueryResult = Apollo.QueryResult<FeedQueryQuery, FeedQueryQueryVariables>;
export const PostDetailsQueryDocument = gql`
query PostDetailsQuery($postId: Int!) {
export type FeedQueryHookResult = ReturnType<typeof useFeedQuery>;
export type FeedLazyQueryHookResult = ReturnType<typeof useFeedLazyQuery>;
export type FeedQueryResult = Apollo.QueryResult<FeedQuery, FeedQueryVariables>;
export const PostDetailsDocument = gql`
query PostDetails($postId: Int!) {
getPostById(id: $postId) {
... on Story {
id
@@ -573,32 +573,32 @@ export const PostDetailsQueryDocument = gql`
`;
/**
* __usePostDetailsQueryQuery__
* __usePostDetailsQuery__
*
* To run a query within a React component, call `usePostDetailsQueryQuery` and pass it any options that fit your needs.
* When your component renders, `usePostDetailsQueryQuery` returns an object from Apollo Client that contains loading, error, and data properties
* To run a query within a React component, call `usePostDetailsQuery` and pass it any options that fit your needs.
* When your component renders, `usePostDetailsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = usePostDetailsQueryQuery({
* const { data, loading, error } = usePostDetailsQuery({
* variables: {
* postId: // value for 'postId'
* },
* });
*/
export function usePostDetailsQueryQuery(baseOptions: Apollo.QueryHookOptions<PostDetailsQueryQuery, PostDetailsQueryQueryVariables>) {
export function usePostDetailsQuery(baseOptions: Apollo.QueryHookOptions<PostDetailsQuery, PostDetailsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PostDetailsQueryQuery, PostDetailsQueryQueryVariables>(PostDetailsQueryDocument, options);
return Apollo.useQuery<PostDetailsQuery, PostDetailsQueryVariables>(PostDetailsDocument, options);
}
export function usePostDetailsQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PostDetailsQueryQuery, PostDetailsQueryQueryVariables>) {
export function usePostDetailsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PostDetailsQuery, PostDetailsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PostDetailsQueryQuery, PostDetailsQueryQueryVariables>(PostDetailsQueryDocument, options);
return Apollo.useLazyQuery<PostDetailsQuery, PostDetailsQueryVariables>(PostDetailsDocument, options);
}
export type PostDetailsQueryQueryHookResult = ReturnType<typeof usePostDetailsQueryQuery>;
export type PostDetailsQueryLazyQueryHookResult = ReturnType<typeof usePostDetailsQueryLazyQuery>;
export type PostDetailsQueryQueryResult = Apollo.QueryResult<PostDetailsQueryQuery, PostDetailsQueryQueryVariables>;
export type PostDetailsQueryHookResult = ReturnType<typeof usePostDetailsQuery>;
export type PostDetailsLazyQueryHookResult = ReturnType<typeof usePostDetailsLazyQuery>;
export type PostDetailsQueryResult = Apollo.QueryResult<PostDetailsQuery, PostDetailsQueryVariables>;
export const CategoryPageDocument = gql`
query CategoryPage($categoryId: Int!) {
projectsByCategory(category_id: $categoryId) {

View File

@@ -14,14 +14,14 @@ const date = dayjs().subtract(5, 'hour').toString();
export let posts = {
stories: [
{
id: 1,
id: 4,
title: 'Digital Editor, Mars Review of Books',
cover_image: getCoverImage(),
comments_count: 31,
date,
votes_count: 120,
excerpt: 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. In odio libero accumsan...',
type: "story",
type: "Story",
tags: [
{ id: 1, title: "lnurl" },
{ id: 2, title: "webln" },
@@ -32,8 +32,8 @@ export let posts = {
] as Story[],
bounties: [
{
type: "bounty",
id: 1,
type: "Bounty",
id: 2,
title: 'Digital Editor, Mars Review of Books',
cover_image: getCoverImage(),
applicants_count: 31,
@@ -52,8 +52,8 @@ export let posts = {
] as Bounty[],
questions: [
{
type: "question",
id: 1,
type: "Question",
id: 3,
title: 'Digital Editor, Mars Review of Books',
answers_count: 31,
date,

View File

@@ -1,6 +1,6 @@
import { graphql } from 'msw'
import { allCategories, getCategory, getProject, hottestProjects, newProjects, projectsByCategory, searchProjects } from './resolvers'
import { allCategories, getCategory, getFeed, getPostById, getProject, hottestProjects, newProjects, projectsByCategory, searchProjects } from './resolvers'
import {
NavCategoriesQuery,
ExploreProjectsQuery,
@@ -13,7 +13,10 @@ import {
HottestProjectsQuery,
HottestProjectsQueryVariables,
AllCategoriesQuery,
AllCategoriesQueryVariables
AllCategoriesQueryVariables,
FeedQuery,
PostDetailsQuery,
PostDetailsQueryVariables,
} from 'src/graphql'
const delay = (ms = 1000) => new Promise((res) => setTimeout(res, ms))
@@ -96,4 +99,25 @@ export const handlers = [
)
}),
graphql.query<FeedQuery>('Feed', async (req, res, ctx) => {
await delay()
return res(
ctx.data({
getFeed: getFeed()
})
)
}),
graphql.query<PostDetailsQuery, PostDetailsQueryVariables>('PostDetails', async (req, res, ctx) => {
await delay()
const { postId } = req.variables
return res(
ctx.data({
getPostById: getPostById(postId)
})
)
}),
]

View File

@@ -1,5 +1,6 @@
import ASSETS from "src/assets";
import { MOCK_DATA } from "./data";
import { Query } from 'src/graphql'
export function getCategory(id: number) {
@@ -39,5 +40,22 @@ export function searchProjects(search: string) {
export function hottestProjects() {
return MOCK_DATA.projects.sort((p1, p2) => p2.votes_count - p1.votes_count).slice(0, 20)
}
export function getFeed(): Query['getFeed'] {
return MOCK_DATA.feed as any;
}
export function getPostById(postId: number): Query['getPostById'] {
for (const key in MOCK_DATA.posts) {
if (Object.prototype.hasOwnProperty.call(MOCK_DATA.posts, key)) {
const t = key as keyof typeof MOCK_DATA.posts
for (const p of MOCK_DATA.posts[t]) {
if (p.id === postId) return p as any;
}
}
}
throw new Error("Post doesn't exist")
}