feat: added schema to backend

This commit is contained in:
MTG2000
2022-04-16 17:31:17 +03:00
parent 9b7afbffcd
commit ae5cd27b5a
26 changed files with 1044 additions and 120 deletions

View File

@@ -1,5 +1,5 @@
overwrite: true
schema: "https://makers-bolt-fun-preview.netlify.app/.netlify/functions/graphql"
schema: "http://localhost:8888/dev/graphql"
documents: "./src/**/*.{ts,graphql}"
generates:
src/graphql/index.tsx:

View File

@@ -34,6 +34,19 @@ export interface NexusGenObjects {
title: string; // String!
url: string; // String!
}
Bounty: { // root type
applicants_count: number; // Int!
author: NexusGenRootTypes['User']; // User!
cover_image: string; // String!
date: string; // String!
deadline: string; // String!
excerpt: string; // String!
id: number; // Int!
reward_amount: number; // Int!
tags: NexusGenRootTypes['Tag'][]; // [Tag!]!
title: string; // String!
votes_count: number; // Int!
}
Category: { // root type
cover_image?: string | null; // String
icon?: string | null; // String
@@ -47,6 +60,12 @@ export interface NexusGenObjects {
minSendable?: number | null; // Int
}
Mutation: {};
PostComment: { // root type
author: NexusGenRootTypes['User']; // User!
body: string; // String!
date: string; // String!
id: number; // Int!
}
Project: { // root type
cover_image: string; // String!
description: string; // String!
@@ -60,10 +79,40 @@ export interface NexusGenObjects {
website: string; // String!
}
Query: {};
Question: { // root type
answers_count: number; // Int!
author: NexusGenRootTypes['User']; // User!
comments: NexusGenRootTypes['PostComment'][]; // [PostComment!]!
cover_image: string; // String!
date: string; // String!
deadline: string; // String!
excerpt: string; // String!
id: number; // Int!
reward_amount: number; // Int!
tags: NexusGenRootTypes['Tag'][]; // [Tag!]!
title: string; // String!
votes_count: number; // Int!
}
Story: { // root type
author: NexusGenRootTypes['User']; // User!
comments_count: number; // Int!
cover_image: string; // String!
date: string; // String!
excerpt: string; // String!
id: number; // Int!
tags: NexusGenRootTypes['Tag'][]; // [Tag!]!
title: string; // String!
votes_count: number; // Int!
}
Tag: { // root type
id: number; // Int!
title: string; // String!
}
User: { // root type
id: number; // Int!
image: string; // String!
name: string; // String!
}
Vote: { // root type
amount_in_sat: number; // Int!
id: number; // Int!
@@ -74,12 +123,14 @@ export interface NexusGenObjects {
}
export interface NexusGenInterfaces {
PostBase: NexusGenRootTypes['Bounty'] | NexusGenRootTypes['Question'] | NexusGenRootTypes['Story'];
}
export interface NexusGenUnions {
Post: NexusGenRootTypes['Bounty'] | NexusGenRootTypes['Question'] | NexusGenRootTypes['Story'];
}
export type NexusGenRootTypes = NexusGenObjects
export type NexusGenRootTypes = NexusGenInterfaces & NexusGenObjects & NexusGenUnions
export type NexusGenAllTypes = NexusGenRootTypes & NexusGenScalars
@@ -91,6 +142,20 @@ export interface NexusGenFieldTypes {
title: string; // String!
url: string; // String!
}
Bounty: { // field return type
applicants_count: number; // Int!
author: NexusGenRootTypes['User']; // User!
cover_image: string; // String!
date: string; // String!
deadline: string; // String!
excerpt: string; // String!
id: number; // Int!
reward_amount: number; // Int!
tags: NexusGenRootTypes['Tag'][]; // [Tag!]!
title: string; // String!
type: string; // String!
votes_count: number; // Int!
}
Category: { // field return type
apps_count: number; // Int!
cover_image: string | null; // String
@@ -110,6 +175,12 @@ export interface NexusGenFieldTypes {
confirmVote: NexusGenRootTypes['Vote']; // Vote!
vote: NexusGenRootTypes['Vote']; // Vote!
}
PostComment: { // field return type
author: NexusGenRootTypes['User']; // User!
body: string; // String!
date: string; // String!
id: number; // Int!
}
Project: { // field return type
awards: NexusGenRootTypes['Award'][]; // [Award!]!
category: NexusGenRootTypes['Category']; // Category!
@@ -129,18 +200,52 @@ export interface NexusGenFieldTypes {
allCategories: NexusGenRootTypes['Category'][]; // [Category!]!
allProjects: NexusGenRootTypes['Project'][]; // [Project!]!
getCategory: NexusGenRootTypes['Category']; // Category!
getFeed: NexusGenRootTypes['Post'][]; // [Post!]!
getLnurlDetailsForProject: NexusGenRootTypes['LnurlDetails']; // LnurlDetails!
getPostById: NexusGenRootTypes['Post']; // Post!
getProject: NexusGenRootTypes['Project']; // Project!
hottestProjects: NexusGenRootTypes['Project'][]; // [Project!]!
newProjects: NexusGenRootTypes['Project'][]; // [Project!]!
projectsByCategory: NexusGenRootTypes['Project'][]; // [Project!]!
searchProjects: NexusGenRootTypes['Project'][]; // [Project!]!
}
Question: { // field return type
answers_count: number; // Int!
author: NexusGenRootTypes['User']; // User!
comments: NexusGenRootTypes['PostComment'][]; // [PostComment!]!
cover_image: string; // String!
date: string; // String!
deadline: string; // String!
excerpt: string; // String!
id: number; // Int!
reward_amount: number; // Int!
tags: NexusGenRootTypes['Tag'][]; // [Tag!]!
title: string; // String!
type: string; // String!
votes_count: number; // Int!
}
Story: { // field return type
author: NexusGenRootTypes['User']; // User!
comments_count: number; // Int!
cover_image: string; // String!
date: string; // String!
excerpt: string; // String!
id: number; // Int!
tags: NexusGenRootTypes['Tag'][]; // [Tag!]!
title: string; // String!
type: string; // String!
votes_count: number; // Int!
}
Tag: { // field return type
id: number; // Int!
project: NexusGenRootTypes['Project'][]; // [Project!]!
title: string; // String!
}
User: { // field return type
id: number; // Int!
image: string; // String!
name: string; // String!
}
Vote: { // field return type
amount_in_sat: number; // Int!
id: number; // Int!
@@ -149,6 +254,15 @@ export interface NexusGenFieldTypes {
payment_request: string; // String!
project: NexusGenRootTypes['Project']; // Project!
}
PostBase: { // field return type
author: NexusGenRootTypes['User']; // User!
date: string; // String!
excerpt: string; // String!
id: number; // Int!
tags: NexusGenRootTypes['Tag'][]; // [Tag!]!
title: string; // String!
votes_count: number; // Int!
}
}
export interface NexusGenFieldTypeNames {
@@ -159,6 +273,20 @@ export interface NexusGenFieldTypeNames {
title: 'String'
url: 'String'
}
Bounty: { // field return type name
applicants_count: 'Int'
author: 'User'
cover_image: 'String'
date: 'String'
deadline: 'String'
excerpt: 'String'
id: 'Int'
reward_amount: 'Int'
tags: 'Tag'
title: 'String'
type: 'String'
votes_count: 'Int'
}
Category: { // field return type name
apps_count: 'Int'
cover_image: 'String'
@@ -178,6 +306,12 @@ export interface NexusGenFieldTypeNames {
confirmVote: 'Vote'
vote: 'Vote'
}
PostComment: { // field return type name
author: 'User'
body: 'String'
date: 'String'
id: 'Int'
}
Project: { // field return type name
awards: 'Award'
category: 'Category'
@@ -197,18 +331,52 @@ export interface NexusGenFieldTypeNames {
allCategories: 'Category'
allProjects: 'Project'
getCategory: 'Category'
getFeed: 'Post'
getLnurlDetailsForProject: 'LnurlDetails'
getPostById: 'Post'
getProject: 'Project'
hottestProjects: 'Project'
newProjects: 'Project'
projectsByCategory: 'Project'
searchProjects: 'Project'
}
Question: { // field return type name
answers_count: 'Int'
author: 'User'
comments: 'PostComment'
cover_image: 'String'
date: 'String'
deadline: 'String'
excerpt: 'String'
id: 'Int'
reward_amount: 'Int'
tags: 'Tag'
title: 'String'
type: 'String'
votes_count: 'Int'
}
Story: { // field return type name
author: 'User'
comments_count: 'Int'
cover_image: 'String'
date: 'String'
excerpt: 'String'
id: 'Int'
tags: 'Tag'
title: 'String'
type: 'String'
votes_count: 'Int'
}
Tag: { // field return type name
id: 'Int'
project: 'Project'
title: 'String'
}
User: { // field return type name
id: 'Int'
image: 'String'
name: 'String'
}
Vote: { // field return type name
amount_in_sat: 'Int'
id: 'Int'
@@ -217,6 +385,15 @@ export interface NexusGenFieldTypeNames {
payment_request: 'String'
project: 'Project'
}
PostBase: { // field return type name
author: 'User'
date: 'String'
excerpt: 'String'
id: 'Int'
tags: 'Tag'
title: 'String'
votes_count: 'Int'
}
}
export interface NexusGenArgTypes {
@@ -238,9 +415,16 @@ export interface NexusGenArgTypes {
getCategory: { // args
id: number; // Int!
}
getFeed: { // args
skip?: number | null; // Int
take: number | null; // Int
}
getLnurlDetailsForProject: { // args
project_id: number; // Int!
}
getPostById: { // args
id: number; // Int!
}
getProject: { // args
id: number; // Int!
}
@@ -266,9 +450,14 @@ export interface NexusGenArgTypes {
}
export interface NexusGenAbstractTypeMembers {
Post: "Bounty" | "Question" | "Story"
PostBase: "Bounty" | "Question" | "Story"
}
export interface NexusGenTypeInterfaces {
Bounty: "PostBase"
Question: "PostBase"
Story: "PostBase"
}
export type NexusGenObjectNames = keyof NexusGenObjects;
@@ -277,15 +466,15 @@ export type NexusGenInputNames = never;
export type NexusGenEnumNames = never;
export type NexusGenInterfaceNames = never;
export type NexusGenInterfaceNames = keyof NexusGenInterfaces;
export type NexusGenScalarNames = keyof NexusGenScalars;
export type NexusGenUnionNames = never;
export type NexusGenUnionNames = keyof NexusGenUnions;
export type NexusGenObjectsUsingAbstractStrategyIsTypeOf = never;
export type NexusGenAbstractsUsingStrategyResolveType = never;
export type NexusGenAbstractsUsingStrategyResolveType = "Post" | "PostBase";
export type NexusGenFeaturesConfig = {
abstractTypeStrategies: {

View File

@@ -10,6 +10,21 @@ type Award {
url: String!
}
type Bounty implements PostBase {
applicants_count: Int!
author: User!
cover_image: String!
date: String!
deadline: String!
excerpt: String!
id: Int!
reward_amount: Int!
tags: [Tag!]!
title: String!
type: String!
votes_count: Int!
}
type Category {
apps_count: Int!
cover_image: String
@@ -32,6 +47,25 @@ type Mutation {
vote(amount_in_sat: Int!, project_id: Int!): Vote!
}
union Post = Bounty | Question | Story
interface PostBase {
author: User!
date: String!
excerpt: String!
id: Int!
tags: [Tag!]!
title: String!
votes_count: Int!
}
type PostComment {
author: User!
body: String!
date: String!
id: Int!
}
type Project {
awards: [Award!]!
category: Category!
@@ -52,7 +86,9 @@ type Query {
allCategories: [Category!]!
allProjects(skip: Int = 0, take: Int = 50): [Project!]!
getCategory(id: Int!): Category!
getFeed(skip: Int = 0, take: Int = 15): [Post!]!
getLnurlDetailsForProject(project_id: Int!): LnurlDetails!
getPostById(id: Int!): Post!
getProject(id: Int!): Project!
hottestProjects(skip: Int = 0, take: Int = 50): [Project!]!
newProjects(skip: Int = 0, take: Int = 50): [Project!]!
@@ -60,12 +96,47 @@ type Query {
searchProjects(search: String!, skip: Int = 0, take: Int = 50): [Project!]!
}
type Question implements PostBase {
answers_count: Int!
author: User!
comments: [PostComment!]!
cover_image: String!
date: String!
deadline: String!
excerpt: String!
id: Int!
reward_amount: Int!
tags: [Tag!]!
title: String!
type: String!
votes_count: Int!
}
type Story implements PostBase {
author: User!
comments_count: Int!
cover_image: String!
date: String!
excerpt: String!
id: Int!
tags: [Tag!]!
title: String!
type: String!
votes_count: Int!
}
type Tag {
id: Int!
project: [Project!]!
title: String!
}
type User {
id: Int!
image: String!
name: String!
}
type Vote {
amount_in_sat: Int!
id: Int!

View File

@@ -1,9 +1,13 @@
const category = require('./category')
const project = require('./project')
const vote = require('./vote')
const post = require('./post')
const users = require('./users')
module.exports = {
...category,
...project,
...vote,
...post,
...users
}

View File

@@ -0,0 +1,144 @@
const {
intArg,
objectType,
stringArg,
extendType,
nonNull,
interfaceType,
unionType,
} = require('nexus');
const { paginationArgs } = require('./helpers');
const PostBase = interfaceType({
name: 'PostBase',
resolveType(post) {
return post.type
},
definition(t) {
t.nonNull.int('id');
t.nonNull.string('title');
t.nonNull.string('date');
t.nonNull.field('author', {
type: "User"
});
t.nonNull.string('excerpt');
t.nonNull.list.nonNull.field('tags', {
type: "Tag"
});
t.nonNull.int('votes_count');
},
})
const Story = objectType({
name: 'Story',
definition(t) {
t.implements('PostBase');
t.nonNull.string('type', {
resolve: () => 'story'
});
t.nonNull.string('cover_image');
t.nonNull.int('comments_count');
},
})
const Bounty = objectType({
name: 'Bounty',
definition(t) {
t.implements('PostBase');
t.nonNull.string('type', {
resolve: () => 'bounty'
});
t.nonNull.string('cover_image');
t.nonNull.string('deadline');
t.nonNull.int('reward_amount');
t.nonNull.int('applicants_count');
},
})
const Question = objectType({
name: 'Question',
definition(t) {
t.implements('PostBase');
t.nonNull.string('type', {
resolve: () => 'question'
});
t.nonNull.string('cover_image');
t.nonNull.string('deadline');
t.nonNull.int('reward_amount');
t.nonNull.int('answers_count');
t.nonNull.list.nonNull.field('comments', {
type: "PostComment"
})
},
})
const PostComment = objectType({
name: 'PostComment',
definition(t) {
t.nonNull.int('id');
t.nonNull.string('date');
t.nonNull.string('body');
t.nonNull.field('author', {
type: "User"
});
}
})
const Post = unionType({
name: 'Post',
definition(t) {
t.members('Story', 'Bounty', 'Question')
},
resolveType: (item) => item.type,
})
const getFeed = extendType({
type: "Query",
definition(t) {
t.nonNull.list.nonNull.field('getFeed', {
type: "Post",
args: {
...paginationArgs({ take: 15 })
},
resolve(_, { take, skip }) {
return []
}
})
}
})
const getPostById = extendType({
type: "Query",
definition(t) {
t.nonNull.field('getPostById', {
type: "Post",
args: {
id: nonNull(intArg())
},
resolve(_, { id }) {
return {}
}
})
}
})
module.exports = {
// Types
PostBase,
Bounty,
Story,
Question,
PostComment,
Post,
// Queries
getFeed,
getPostById
}

View File

@@ -0,0 +1,17 @@
const { objectType } = require("nexus");
const User = objectType({
name: 'User',
definition(t) {
t.nonNull.int('id');
t.nonNull.string('name');
t.nonNull.string('image');
}
})
module.exports = {
// Types
User
}

View File

@@ -12,7 +12,7 @@ export default {
} as ComponentMeta<typeof BountyCard>;
const Template: ComponentStory<typeof BountyCard> = (args) => <div className="max-w-[660px]"><BountyCard {...args} ></BountyCard></div>
const Template: ComponentStory<typeof BountyCard> = (args) => <div className="max-w-[70ch]"><BountyCard {...args} ></BountyCard></div>
export const Default = Template.bind({});
Default.args = {

View File

@@ -13,7 +13,7 @@ export default function BountyCard({ bounty }: Props) {
<div className="bg-white rounded-12 overflow-hidden border">
<img src={bounty.cover_image} className='h-[200px] w-full object-cover' alt="" />
<div className="p-24">
<Header name={bounty.author.name} avatar={bounty.author.image} date={bounty.date} />
<Header author={bounty.author} date={bounty.date} />
<div className="flex justify-between">
<div>
<h2 className="text-h5 font-medium mt-16">{bounty.title}</h2>
@@ -26,7 +26,7 @@ export default function BountyCard({ bounty }: Props) {
Apply
</Button>
</div>
<p className="text-body5 text-gray-600 mt-8">{bounty.excerpt}</p>
<p className="text-body4 text-gray-600 mt-8">{bounty.excerpt}</p>
<div className="flex gap-8 mt-8">
{bounty.tags.map(tag => <Badge key={tag.id} size='sm'>

View File

@@ -1,24 +1,27 @@
import React from 'react'
import Avatar from 'src/features/Profiles/Components/Avatar/Avatar';
import dayjs from 'dayjs'
interface Props {
name: string;
avatar: string;
date: string
author: {
id: number,
name: string,
image: string
}
date: string;
size?: 'sm' | 'md'
}
export default function Header(props: Props) {
export default function Header({ size = 'md', ...props }: Props) {
return (
<div className='flex gap-8'>
<Avatar width={40} src={props.avatar} />
<Avatar width={size === 'md' ? 40 : 32} src={props.author.image} />
<div>
<p className='text-body4 text-black font-medium'>{props.name}</p>
<p className='text-body6 text-gray-600'>{dayjs(props.date).format('MMMM DD')}</p>
<p className={`${size === 'md' ? 'text-body4' : "text-body5"} text-black font-medium`}>{props.author.name}</p>
<p className={`text-body6 text-gray-600`}>{dayjs(props.date).format('MMMM DD')}</p>
</div>
<p className="text-body5 text-gray-500 ml-auto ">
3h ago
<p className={`${size === 'md' ? 'text-body4' : " text-body5"} text-gray-500 ml-auto `}>
{dayjs().diff(props.date, 'hour') < 24 ? `${dayjs().diff(props.date, 'hour')}h ago` : undefined}
</p>
</div>
)

View File

@@ -1,19 +1,21 @@
import { Post } from "src/features/Posts/types"
import BountyCard from "./BountyCard"
import QuestionCard from "./QuestionCard"
import StoryCard from "./StoryCard"
type Props =
| {
type: 'story'
}
| {
type: 'question'
}
| {
type: 'bounty'
}
export default function PostCard(props: Props) {
if ('question' in props) {
}
return (
<div>StoryCard</div>
)
type Props = {
post: Post
}
export default function PostCard({ post }: Props) {
if (post.type === 'story')
return <StoryCard story={post} />
if (post.type === 'bounty')
return <BountyCard bounty={post} />
if (post.type === 'question')
return <QuestionCard question={post} />
return null
}

View File

@@ -12,7 +12,7 @@ export default {
} as ComponentMeta<typeof QuestionCard>;
const Template: ComponentStory<typeof QuestionCard> = (args) => <div className="max-w-[660px]"><QuestionCard {...args} ></QuestionCard></div>
const Template: ComponentStory<typeof QuestionCard> = (args) => <div className="max-w-[70ch]"><QuestionCard {...args} ></QuestionCard></div>
export const Default = Template.bind({});
Default.args = {

View File

@@ -15,11 +15,11 @@ export default function QuestionCard({ question }: Props) {
<div className="bg-white rounded-12 overflow-hidden border">
{/* <img src={question.cover_image} className='h-[200px] w-full object-cover' alt="" /> */}
<div className="p-24">
<Header name={question.author.name} avatar={question.author.image} date={question.date} />
<Header author={question.author} date={question.date} />
<div className="flex justify-between">
<h2 className="text-h5 font-medium mt-16">{question.title}</h2>
</div>
<p className="text-body5 text-gray-600 mt-8">{question.excerpt}</p>
<p className="text-body4 text-gray-600 mt-8">{question.excerpt}</p>
<div className="flex gap-8 mt-8">
<Badge key={'991199'} size='sm' color="none" className="bg-red-200 text-red-600">
@@ -39,16 +39,12 @@ export default function QuestionCard({ question }: Props) {
</div>
<div className="flex p-16 mt-16 flex-col gap-10 bg-gray-50">
{question.comments.map(comment => <div className="border-b last-of-type:border-b-0 pb-8 ">
<div className='flex gap-8'>
<Avatar width={32} src={comment.author.image} />
<div>
<p className='text-body4 text-black font-medium'>{comment.author.name}</p>
<p className='text-body6 text-gray-600'>{dayjs(comment.date).format('MMMM DD')}</p>
</div>
</div>
<p className="text-body5 text-gray-600 mt-8">{comment.body}</p>
</div>)}
<div className="flex flex-col gap-10">
{question.comments.map(comment => <div key={comment.id} className="border-b last-of-type:border-b-0 pb-8 " >
<Header author={comment.author} size='sm' date={comment.date} />
<p className="text-body5 text-gray-600 mt-8">{comment.body}</p>
</div>)}
</div>
<div className="flex">
<Link to='#' className="text-black font-medium p-8 hover:bg-gray-100 rounded">

View File

@@ -12,7 +12,7 @@ export default {
} as ComponentMeta<typeof StoryCard>;
const Template: ComponentStory<typeof StoryCard> = (args) => <div className="max-w-[660px]"><StoryCard {...args} ></StoryCard></div>
const Template: ComponentStory<typeof StoryCard> = (args) => <div className="max-w-[70ch]"><StoryCard {...args} ></StoryCard></div>
export const Default = Template.bind({});
Default.args = {

View File

@@ -11,9 +11,9 @@ export default function StoryCard({ story }: Props) {
<div className="bg-white rounded-12 overflow-hidden border">
<img src={story.cover_image} className='h-[200px] w-full object-cover' alt="" />
<div className="p-24">
<Header name={story.author.name} avatar={story.author.image} date={story.date} />
<Header author={story.author} date={story.date} />
<h2 className="text-h5 font-medium mt-16">{story.title}</h2>
<p className="text-body5 text-gray-600 mt-8">{story.excerpt}</p>
<p className="text-body4 text-gray-600 mt-8">{story.excerpt}</p>
<hr className="my-16 bg-gray-200" />
<div className="flex gap-24">

View File

@@ -0,0 +1,22 @@
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { MOCK_DATA } from 'src/mocks/data';
import PostsList from './PostsList';
export default {
title: 'Posts/Components/PostsList',
component: PostsList,
argTypes: {
backgroundColor: { control: 'color' },
},
} as ComponentMeta<typeof PostsList>;
const Template: ComponentStory<typeof PostsList> = (args) => <div className="max-w-[70ch]"><PostsList {...args} ></PostsList></div>
export const Default = Template.bind({});
Default.args = {
posts: MOCK_DATA['feed']
}

View File

@@ -0,0 +1,16 @@
import { Post } from "src/features/Posts/types"
import PostCard from "../PostCard/PostCard"
interface Props {
posts: Post[]
}
export default function PostsList(props: Props) {
return (
<div className="flex flex-col gap-24">
{
props.posts.map(post => <PostCard key={post.id} post={post} />)
}
</div>
)
}

View File

@@ -0,0 +1 @@
export { }

View File

@@ -0,0 +1,75 @@
query FeedQuery {
getFeed {
... on Story {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
comments_count
}
... on Bounty {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
deadline
reward_amount
applicants_count
}
... on Question {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
deadline
reward_amount
answers_count
comments {
id
date
body
author {
id
name
image
}
}
}
}
}

View File

@@ -0,0 +1 @@
export { }

View File

@@ -0,0 +1,75 @@
query PostDetailsQuery($postId: Int!) {
getPostById(id: $postId) {
... on Story {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
comments_count
}
... on Bounty {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
deadline
reward_amount
applicants_count
}
... on Question {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
deadline
reward_amount
answers_count
comments {
id
date
body
author {
id
name
image
}
}
}
}
}

View File

@@ -1,50 +1 @@
import { Tag } from "src/utils/interfaces"
export type User = {
id: number
name: string
image: string
}
export type Author = User & {
join_date: string
}
export type PostBase = {
id: number
title: string
date: string
author: Author
excerpt: string
tags: Tag[]
votes_count: number
}
export type Story = PostBase & {
type: 'story'
cover_image: string;
comments_count: number
}
export type Bounty = PostBase & {
type: 'bounty'
cover_image: string;
reward_amount: number
deadline: string
applicants_count: number
}
export type Question = PostBase & {
type: 'question'
answers_count: number
comments: PostComment[]
}
export type PostComment = {
id: number;
author: Author
date: string
body: string
}
export type Post = Story | Question | Bounty
export * from './posts.interface'

View File

@@ -0,0 +1,50 @@
import { Tag } from "src/utils/interfaces"
export type User = {
id: number
name: string
image: string
}
export type Author = User & {
join_date: string
}
export type PostBase = {
id: number
title: string
date: string
author: Author
excerpt: string
tags: Tag[]
votes_count: number
}
export type Story = PostBase & {
type: 'story'
cover_image: string;
comments_count: number
}
export type Bounty = PostBase & {
type: 'bounty'
cover_image: string;
reward_amount: number
deadline: string
applicants_count: number
}
export type Question = PostBase & {
type: 'question'
answers_count: number
comments: PostComment[]
}
export type PostComment = {
id: number;
author: Author
date: string
body: string
}
export type Post = Story | Question | Bounty

View File

@@ -24,6 +24,22 @@ export type Award = {
url: Scalars['String'];
};
export type Bounty = PostBase & {
__typename?: 'Bounty';
applicants_count: Scalars['Int'];
author: User;
cover_image: Scalars['String'];
date: Scalars['String'];
deadline: Scalars['String'];
excerpt: Scalars['String'];
id: Scalars['Int'];
reward_amount: Scalars['Int'];
tags: Array<Tag>;
title: Scalars['String'];
type: Scalars['String'];
votes_count: Scalars['Int'];
};
export type Category = {
__typename?: 'Category';
apps_count: Scalars['Int'];
@@ -61,6 +77,26 @@ export type MutationVoteArgs = {
project_id: Scalars['Int'];
};
export type Post = Bounty | Question | Story;
export type PostBase = {
author: User;
date: Scalars['String'];
excerpt: Scalars['String'];
id: Scalars['Int'];
tags: Array<Tag>;
title: Scalars['String'];
votes_count: Scalars['Int'];
};
export type PostComment = {
__typename?: 'PostComment';
author: User;
body: Scalars['String'];
date: Scalars['String'];
id: Scalars['Int'];
};
export type Project = {
__typename?: 'Project';
awards: Array<Award>;
@@ -83,7 +119,9 @@ export type Query = {
allCategories: Array<Category>;
allProjects: Array<Project>;
getCategory: Category;
getFeed: Array<Post>;
getLnurlDetailsForProject: LnurlDetails;
getPostById: Post;
getProject: Project;
hottestProjects: Array<Project>;
newProjects: Array<Project>;
@@ -103,11 +141,22 @@ export type QueryGetCategoryArgs = {
};
export type QueryGetFeedArgs = {
skip?: InputMaybe<Scalars['Int']>;
take?: InputMaybe<Scalars['Int']>;
};
export type QueryGetLnurlDetailsForProjectArgs = {
project_id: Scalars['Int'];
};
export type QueryGetPostByIdArgs = {
id: Scalars['Int'];
};
export type QueryGetProjectArgs = {
id: Scalars['Int'];
};
@@ -138,6 +187,37 @@ export type QuerySearchProjectsArgs = {
take?: InputMaybe<Scalars['Int']>;
};
export type Question = PostBase & {
__typename?: 'Question';
answers_count: Scalars['Int'];
author: User;
comments: Array<PostComment>;
cover_image: Scalars['String'];
date: Scalars['String'];
deadline: Scalars['String'];
excerpt: Scalars['String'];
id: Scalars['Int'];
reward_amount: Scalars['Int'];
tags: Array<Tag>;
title: Scalars['String'];
type: Scalars['String'];
votes_count: Scalars['Int'];
};
export type Story = PostBase & {
__typename?: 'Story';
author: User;
comments_count: Scalars['Int'];
cover_image: Scalars['String'];
date: Scalars['String'];
excerpt: Scalars['String'];
id: Scalars['Int'];
tags: Array<Tag>;
title: Scalars['String'];
type: Scalars['String'];
votes_count: Scalars['Int'];
};
export type Tag = {
__typename?: 'Tag';
id: Scalars['Int'];
@@ -145,6 +225,13 @@ export type Tag = {
title: Scalars['String'];
};
export type User = {
__typename?: 'User';
id: Scalars['Int'];
image: Scalars['String'];
name: Scalars['String'];
};
export type Vote = {
__typename?: 'Vote';
amount_in_sat: Scalars['Int'];
@@ -167,6 +254,18 @@ 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 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 PostDetailsQueryQueryVariables = 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 CategoryPageQueryVariables = Exact<{
categoryId: Scalars['Int'];
}>;
@@ -291,6 +390,215 @@ 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 {
getFeed {
... on Story {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
comments_count
}
... on Bounty {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
deadline
reward_amount
applicants_count
}
... on Question {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
deadline
reward_amount
answers_count
comments {
id
date
body
author {
id
name
image
}
}
}
}
}
`;
/**
* __useFeedQueryQuery__
*
* 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
* 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({
* variables: {
* },
* });
*/
export function useFeedQueryQuery(baseOptions?: Apollo.QueryHookOptions<FeedQueryQuery, FeedQueryQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<FeedQueryQuery, FeedQueryQueryVariables>(FeedQueryDocument, options);
}
export function useFeedQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<FeedQueryQuery, FeedQueryQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<FeedQueryQuery, FeedQueryQueryVariables>(FeedQueryDocument, 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!) {
getPostById(id: $postId) {
... on Story {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
comments_count
}
... on Bounty {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
deadline
reward_amount
applicants_count
}
... on Question {
id
title
date
author {
id
name
image
}
excerpt
tags {
id
title
}
votes_count
type
cover_image
deadline
reward_amount
answers_count
comments {
id
date
body
author {
id
name
image
}
}
}
}
}
`;
/**
* __usePostDetailsQueryQuery__
*
* 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
* 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({
* variables: {
* postId: // value for 'postId'
* },
* });
*/
export function usePostDetailsQueryQuery(baseOptions: Apollo.QueryHookOptions<PostDetailsQueryQuery, PostDetailsQueryQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<PostDetailsQueryQuery, PostDetailsQueryQueryVariables>(PostDetailsQueryDocument, options);
}
export function usePostDetailsQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PostDetailsQueryQuery, PostDetailsQueryQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<PostDetailsQueryQuery, PostDetailsQueryQueryVariables>(PostDetailsQueryDocument, options);
}
export type PostDetailsQueryQueryHookResult = ReturnType<typeof usePostDetailsQueryQuery>;
export type PostDetailsQueryLazyQueryHookResult = ReturnType<typeof usePostDetailsQueryLazyQuery>;
export type PostDetailsQueryQueryResult = Apollo.QueryResult<PostDetailsQueryQuery, PostDetailsQueryQueryVariables>;
export const CategoryPageDocument = gql`
query CategoryPage($categoryId: Int!) {
projectsByCategory(category_id: $categoryId) {

View File

@@ -1,9 +1,9 @@
import { Project, ProjectCategory } from "src/utils/interfaces";
import { posts } from "./data/posts";
import { posts, feed } from "./data/posts";
import { categories, projects } from "./data/projects";
export const MOCK_DATA = {
projects: projects,
categories: categories,
posts: posts
projects,
categories,
posts,
feed
}

View File

@@ -1,5 +1,6 @@
import { Bounty, Question, Story } from "src/features/Posts/types";
import dayjs from "dayjs";
import { Bounty, Post, Question, Story } from "src/features/Posts/types";
import { getAvatarImage, getCoverImage } from "./utils";
const getAuthor = () => ({
@@ -8,9 +9,9 @@ const getAuthor = () => ({
image: getAvatarImage()
})
const date = 'Mon Mar 14 2022 20:33:17 GMT+0200 (Eastern European Standard Time)'
const date = dayjs().subtract(5, 'hour').toString();
let posts = {
export let posts = {
stories: [
{
id: 1,
@@ -86,7 +87,9 @@ posts.bounties = posts.bounties.map(b => ({ ...b, __typename: "Bounty" }))
posts.questions = posts.questions.map(b => ({ ...b, __typename: "Question" }))
posts.stories = posts.stories.map(b => ({ ...b, __typename: "Story" }))
export const feed: Post[] = [
...posts.stories,
...posts.bounties,
...posts.questions,
]
export {
posts,
}

View File

@@ -1,7 +1,7 @@
import { Project, ProjectCategory } from "src/utils/interfaces";
let categories = [
export let categories = [
{
"title": "Shock the Web ⚡️",
"id": 11,
@@ -79,9 +79,9 @@ let categories = [
"icon": "🔁",
"votes_sum": 0
}
]
] as ProjectCategory[]
let projects = [
export let projects = [
{
"id": 16,
"title": "Alby",
@@ -555,7 +555,7 @@ let projects = [
"title": "Gaming"
}
}
]
] as Project[]
categories = categories.map(c => ({ ...c, __typename: "Category" }))
@@ -564,7 +564,3 @@ projects = projects.map(p => ({ ...p, __typename: "Project" }))
// 2- Computed Fields
categories = categories.map(c => ({ ...c, apps_count: projects.reduce((acc, p) => acc + (p.category.id === c.id ? 1 : 0), 0) }))
export {
projects,
categories
}