feat: Hackathons page, hackathons filter, hackathons mocks api

This commit is contained in:
MTG2000
2022-05-22 13:23:37 +03:00
parent b8b6468b77
commit 08222b9935
24 changed files with 392 additions and 135 deletions

View File

@@ -76,6 +76,16 @@ export interface NexusGenObjects {
id: number; // Int!
title: string; // String!
}
Hackathon: { // root type
cover_image: string; // String!
description: string; // String!
end_date: NexusGenScalars['Date']; // Date!
id: number; // Int!
location: string; // String!
start_date: NexusGenScalars['Date']; // Date!
title: string; // String!
website: string; // String!
}
LnurlDetails: { // root type
commentAllowed?: number | null; // Int
maxSendable?: number | null; // Int
@@ -198,6 +208,17 @@ export interface NexusGenFieldTypes {
title: string; // String!
votes_sum: number; // Int!
}
Hackathon: { // field return type
cover_image: string; // String!
description: string; // String!
end_date: NexusGenScalars['Date']; // Date!
id: number; // Int!
location: string; // String!
start_date: NexusGenScalars['Date']; // Date!
title: string; // String!
topics: NexusGenRootTypes['Topic'][]; // [Topic!]!
website: string; // String!
}
LnurlDetails: { // field return type
commentAllowed: number | null; // Int
maxSendable: number | null; // Int
@@ -235,6 +256,7 @@ export interface NexusGenFieldTypes {
allCategories: NexusGenRootTypes['Category'][]; // [Category!]!
allProjects: NexusGenRootTypes['Project'][]; // [Project!]!
allTopics: NexusGenRootTypes['Topic'][]; // [Topic!]!
getAllHackathons: NexusGenRootTypes['Hackathon'][]; // [Hackathon!]!
getCategory: NexusGenRootTypes['Category']; // Category!
getFeed: NexusGenRootTypes['Post'][]; // [Post!]!
getLnurlDetailsForProject: NexusGenRootTypes['LnurlDetails']; // LnurlDetails!
@@ -347,6 +369,17 @@ export interface NexusGenFieldTypeNames {
title: 'String'
votes_sum: 'Int'
}
Hackathon: { // field return type name
cover_image: 'String'
description: 'String'
end_date: 'Date'
id: 'Int'
location: 'String'
start_date: 'Date'
title: 'String'
topics: 'Topic'
website: 'String'
}
LnurlDetails: { // field return type name
commentAllowed: 'Int'
maxSendable: 'Int'
@@ -384,6 +417,7 @@ export interface NexusGenFieldTypeNames {
allCategories: 'Category'
allProjects: 'Project'
allTopics: 'Topic'
getAllHackathons: 'Hackathon'
getCategory: 'Category'
getFeed: 'Post'
getLnurlDetailsForProject: 'LnurlDetails'
@@ -474,6 +508,10 @@ export interface NexusGenArgTypes {
skip?: number | null; // Int
take: number | null; // Int
}
getAllHackathons: { // args
sortBy?: string | null; // String
topic?: number | null; // Int
}
getCategory: { // args
id: number; // Int!
}

View File

@@ -47,6 +47,18 @@ type Category {
"""Date custom scalar type"""
scalar Date
type Hackathon {
cover_image: String!
description: String!
end_date: Date!
id: Int!
location: String!
start_date: Date!
title: String!
topics: [Topic!]!
website: String!
}
type LnurlDetails {
commentAllowed: Int
maxSendable: Int
@@ -105,6 +117,7 @@ type Query {
allCategories: [Category!]!
allProjects(skip: Int = 0, take: Int = 50): [Project!]!
allTopics: [Topic!]!
getAllHackathons(sortBy: String, topic: Int): [Hackathon!]!
getCategory(id: Int!): Category!
getFeed(skip: Int = 0, sortBy: String = "all", take: Int = 10, topic: Int = 0): [Post!]!
getLnurlDetailsForProject(project_id: Int!): LnurlDetails!

View File

@@ -5,6 +5,7 @@ const {
extendType,
nonNull,
} = require('nexus');
const { prisma } = require('../prisma')
@@ -15,13 +16,14 @@ const Hackathon = objectType({
t.nonNull.string('title');
t.nonNull.string('description');
t.nonNull.string('cover_image');
t.nonNull.string('date');
t.nonNull.date('start_date');
t.nonNull.date('end_date');
t.nonNull.string('location');
t.nonNull.string('website');
t.nonNull.list.nonNull.field('topics', {
type: "Topic",
resolve: (parent) => {
return []
return prisma.hackathon.findUnique({ where: { id: parent.id } }).topics();
}
});
}
@@ -29,15 +31,41 @@ const Hackathon = objectType({
const getAllHackathons = extendType({
type: "Query",
args: {
sortBy: stringArg(),
topic: stringArg(),
},
definition(t) {
t.nonNull.list.nonNull.field('getAllHackathons', {
type: "Hackathon",
args: {
sortBy: stringArg(),
topic: intArg(),
},
resolve(_, args) {
return [];
const { sortBy, topic } = args;
return prisma.hackathon.findMany({
where: {
...(sortBy === 'Upcoming' && {
start_date: {
gte: new Date(),
}
}),
...(sortBy === 'Live' && {
start_date: { lte: new Date() },
end_date: { gte: new Date() }
}),
...(sortBy === 'Finished' && {
end_date: {
lt: new Date()
}
}),
...(topic && {
topics: {
some: {
id: topic
}
}
})
}
})
}
})
}

View File

@@ -4,6 +4,7 @@ const project = require('./project')
const vote = require('./vote')
const post = require('./post')
const users = require('./users')
const hackathon = require('./hackathon')
module.exports = {
...scalars,
@@ -11,5 +12,6 @@ module.exports = {
...project,
...vote,
...post,
...users
...users,
...hackathon
}

View File

@@ -9,6 +9,7 @@ import LoadingPage from "./Components/LoadingPage/LoadingPage";
// Pages
const FeedPage = React.lazy(() => import("./features/Posts/pages/FeedPage/FeedPage"))
const HackathonsPage = React.lazy(() => import("./features/Hackathons/pages/HackathonsPage/HackathonsPage"))
const HottestPage = React.lazy(() => import("src/features/Projects/pages/HottestPage/HottestPage"))
const PostDetailsPage = React.lazy(() => import("./features/Posts/pages/PostDetailsPage/PostDetailsPage"))
const CategoryPage = React.lazy(() => import("src/features/Projects/pages/CategoryPage/CategoryPage"))
@@ -47,6 +48,7 @@ function App() {
<Route path="/category/:id" element={<CategoryPage />} />
<Route path="/blog/post/:type/:id" element={<PostDetailsPage />} />
<Route path="/blog" element={<FeedPage />} />
<Route path="/hackathons" element={<HackathonsPage />} />
<Route path="/" element={<ExplorePage />} />
</Routes>
</Suspense>

View File

@@ -8,6 +8,7 @@ import { setNavHeight } from "src/redux/features/ui.slice";
import NavDesktop from "./NavDesktop";
import { useMediaQuery } from "@react-hookz/web";
import { MEDIA_QUERIES } from "src/utils/theme/media_queries";
import { IoMdTrophy } from "react-icons/io";
export const navLinks = [
@@ -18,6 +19,12 @@ export const navLinks = [
icon: MdComment,
color: "text-primary-600",
},
{
text: "Hackathons",
url: "/hackathons",
icon: IoMdTrophy,
color: "text-primary-600",
},
{
text: "Hottest",
url: "/hottest",
@@ -41,6 +48,7 @@ export default function Navbar() {
}));
const isLargeScreen = useMediaQuery(MEDIA_QUERIES.isLarge)
console.log(isLargeScreen, MEDIA_QUERIES.isLarge);
const onConnectWallet = () => {

View File

@@ -1,6 +1,10 @@
import { Hackathon } from "src/features/Hackathons/types"
import { IoLocationOutline } from 'react-icons/io5'
import Button from "src/Components/Button/Button"
import dayjs from "dayjs";
import advancedFormat from 'dayjs/plugin/advancedFormat'
import { trimText } from "src/utils/helperFunctions";
dayjs.extend(advancedFormat)
export type HackathonCardType = Hackathon;
@@ -18,20 +22,20 @@ export default function HackathonCard({ hackathon }: Props) {
{hackathon.title}
</h3>
<p className="text-body3 font-medium text-gray-900">
{hackathon.date}
{`${dayjs(hackathon.start_date).format('Do')} - ${dayjs(hackathon.end_date).format('Do MMMM, YYYY')}`}
</p>
<p className="text-body4 font-medium text-gray-600">
<IoLocationOutline className="mr-8" /> {hackathon.location}
</p>
<p className="text-body4 text-gray-600">
{hackathon.description}
{trimText(hackathon.description, 110)}
</p>
</div>
<div className="mt-16 flex flex-wrap gap-8">
{hackathon.topics.map(topic => <div key={topic.id} className="p-8 bg-gray-50 rounded-8 text-body5">{topic.title}</div>)}
{hackathon.topics.map(topic => <div key={topic.id} className="p-8 bg-gray-50 rounded-8 text-body5">{topic.icon} {topic.title}</div>)}
</div>
<Button href={hackathon.url} newTab color="gray" fullWidth className="mt-16">
<Button href={hackathon.website} newTab color="gray" fullWidth className="mt-16">
Learn more
</Button>
</div>

View File

@@ -6,35 +6,33 @@ const filters = [
value: 'Upcoming'
}, {
text: "Live",
value: 'live'
value: 'Live'
}, {
text: "Complete",
value: 'complete'
text: "Finished",
value: 'Finished'
},
]
interface Props {
filterChanged?: (newFilter: string) => void
filterChanged?: (newFilter: string | null) => void
}
export default function SortByFilter({ filterChanged }: Props) {
const [selected, setSelected] = useState(filters[0].value);
const [selected, setSelected] = useState<string | null>(null);
const filterClicked = (newValue: string) => {
if (selected === newValue)
return
const filterClicked = (_newValue: string) => {
const newValue = selected !== _newValue ? _newValue : null;
setSelected(newValue);
filterChanged?.(newValue);
}
return (
<div className='bg-white border rounded-12 p-16'>
<p className="text-body2 font-bolder text-black mb-16">Sort By</p>
<ul>
{filters.map((f, idx) => <li
key={f.value}
className={`p-12 rounded-8 cursor-pointer font-bold ${f.value === selected && 'bg-gray-100'}`}
className={`p-12 rounded-8 cursor-pointer font-bold ${f.value === selected && 'bg-gray-200'}`}
onClick={() => filterClicked(f.value)}
>
{f.text}

View File

@@ -1,39 +1,22 @@
import { useState } from 'react'
import React, { useState } from 'react'
import Skeleton from 'react-loading-skeleton';
import { useAllTopicsQuery, usePopularTopicsQuery } from 'src/graphql';
const filters = [
{
text: 'Design',
value: 'Design',
icon: "🎨"
},
{
text: 'Development',
value: 'Development',
icon: "💻"
},
{
text: 'Startups',
value: 'Startups',
icon: "🚀"
},
{
text: 'Lightning Network',
value: 'Lightning Network',
icon: "⚡️"
},
]
interface Props {
filterChanged?: (newFilter: string) => void
filterChanged?: (newFilter: number | null) => void
}
export default function TopicsFilter({ filterChanged }: Props) {
export default function PopularTopicsFilter({ filterChanged }: Props) {
const [selected, setSelected] = useState(filters[0].value);
const [selected, setSelected] = useState<number | null>(null);
const filterClicked = (newValue: string) => {
if (selected === newValue)
return
const topicsQuery = useAllTopicsQuery();
const filterClicked = (_newValue: number) => {
const newValue = selected !== _newValue ? _newValue : null;
setSelected(newValue);
filterChanged?.(newValue);
}
@@ -42,16 +25,28 @@ export default function TopicsFilter({ filterChanged }: Props) {
<div className='bg-white border rounded-12 p-16'>
<p className="text-body2 font-bolder text-black mb-16">Topics</p>
<ul className=' flex flex-col gap-16'>
{filters.map((f, idx) => <li
key={f.value}
className={`flex items-start rounded-8 cursor-pointer font-bold ${f.value === selected && 'bg-gray-50'}`}
onClick={() => filterClicked(f.value)}
>
<span className='bg-gray-50 rounded-8 p-8'>{f.icon}</span>
<span className="self-center px-16">
{f.text}
</span>
</li>)}
{topicsQuery.loading ?
Array(4).fill(0).map((_, idx) => <li
key={idx}
className={`flex items-start rounded-8 font-bold`}
>
<span className='bg-gray-50 rounded-8 w-40 h-40 text-center py-8'> </span>
<span className="self-center px-16"><Skeleton width={'7ch'} />
</span>
</li>
)
:
topicsQuery.data?.allTopics.map((f, idx) => <li
key={f.id}
className={`flex items-start rounded-8 cursor-pointer font-bold ${f.id === selected && 'bg-gray-200'}`}
onClick={() => filterClicked(f.id)}
>
<span className={`${f.id !== selected && 'bg-gray-50'} rounded-8 w-40 h-40 text-center py-8`}>{f.icon}</span>
<span className="self-center px-16">
{f.title}
</span>
</li>)}
</ul>
</div>
)

View File

@@ -0,0 +1,7 @@
query allTopics {
allTopics {
id
title
icon
}
}

View File

@@ -0,0 +1,20 @@
import { ComponentStory, ComponentMeta } from '@storybook/react';
import HackathonsPage from './HackathonsPage';
export default {
title: 'Hackathons/Hackathons Page/Page',
component: HackathonsPage,
argTypes: {
backgroundColor: { control: 'color' },
},
} as ComponentMeta<typeof HackathonsPage>;
const Template: ComponentStory<typeof HackathonsPage> = (args) => <HackathonsPage {...args as any} ></HackathonsPage>
export const Default = Template.bind({});
Default.args = {
}

View File

@@ -1,7 +1,9 @@
import { useReducer, useState } from 'react'
import { useFeedQuery } from 'src/graphql'
import Button from 'src/Components/Button/Button'
import { useGetHackathonsQuery } from 'src/graphql'
import { useAppSelector, useInfiniteQuery } from 'src/utils/hooks'
import HackathonsList from '../../Components/HackathonsList/HackathonsList'
import SortByFilter from '../../Components/SortByFilter/SortByFilter'
import TopicsFilter from '../../Components/TopicsFilter/TopicsFilter'
import styles from './styles.module.scss'
@@ -9,19 +11,15 @@ import styles from './styles.module.scss'
export default function HackathonsPage() {
const [sortByFilter, setSortByFilter] = useState('all')
const [topicsFilter, setTopicsFilter] = useState('all')
const [sortByFilter, setSortByFilter] = useState<string | null>(null)
const [topicsFilter, setTopicsFilter] = useState<number | null>(null)
const feedQuery = useFeedQuery({
const hackathonsQuery = useGetHackathonsQuery({
variables: {
take: 10,
skip: 0,
sortBy: sortByFilter,
topic: Number(topicsFilter)
},
})
const { fetchMore, isFetchingMore } = useInfiniteQuery(feedQuery, 'getFeed')
const { navHeight } = useAppSelector((state) => ({
navHeight: state.ui.navHeight
}));
@@ -31,7 +29,7 @@ export default function HackathonsPage() {
className={`page-container pt-16 w-full ${styles.grid}`}
>
<aside className='no-scrollbar'>
<div className="sticky"
<div className="sticky flex flex-col gap-24"
style={{
top: `${navHeight + 16}px`,
maxHeight: `calc(100vh - ${navHeight}px - 16px)`,
@@ -43,9 +41,21 @@ export default function HackathonsPage() {
<TopicsFilter
filterChanged={setTopicsFilter}
/>
<Button
href='https://airtable.com/some-registration-form'
newTab
color='primary'
fullWidth
>
List Your Hackathon
</Button>
</div>
</aside>
<div className="self-start">
<HackathonsList
isLoading={hackathonsQuery.loading}
items={hackathonsQuery.data?.getAllHackathons} />
</div>
</div>
)
}

View File

@@ -0,0 +1,17 @@
query getHackathons($sortBy: String, $topic: Int) {
getAllHackathons(sortBy: $sortBy, topic: $topic) {
id
title
description
cover_image
start_date
end_date
location
website
topics {
id
title
icon
}
}
}

View File

@@ -4,14 +4,11 @@
gap: 0;
@media screen and (min-width: 680px) {
grid-template-columns: 1fr 2fr 0;
grid-template-columns: 1fr 2fr;
gap: 32px;
}
@media screen and (min-width: 1024px) {
grid-template-columns:
minmax(200px, 1fr)
minmax(50%, 70ch)
minmax(200px, 1fr);
grid-template-columns: calc(min(30%, 326px)) 1fr;
}
}

View File

@@ -1,13 +1,3 @@
export interface Hackathon {
id: number
title: string
date: string
location: string
description: string
cover_image: string
topics: Array<{
id: number,
title: string
}>,
url: string
}
import { Hackathon as ApiHackathon, } from "src/graphql"
export type Hackathon = ApiHackathon

View File

@@ -2,27 +2,6 @@ import React, { useState } from 'react'
import Skeleton from 'react-loading-skeleton';
import { usePopularTopicsQuery } from 'src/graphql';
const filters = [
{
text: "🔥 All",
value: 0
}, {
text: "Lightning Network",
value: 1
}, {
text: "Bitcoin",
value: 2
}, {
text: "Cybersecurity",
value: 3
}, {
text: "Bounties",
value: 4
}, {
text: "Grants",
value: 5
},
]
interface Props {
filterChanged?: (newFilter: number | null) => void
@@ -30,7 +9,7 @@ interface Props {
export default function PopularTopicsFilter({ filterChanged }: Props) {
const [selected, setSelected] = useState<number | null>(filters[0].value);
const [selected, setSelected] = useState<number | null>(null);
const topicsQuery = usePopularTopicsQuery();
@@ -59,10 +38,10 @@ export default function PopularTopicsFilter({ filterChanged }: Props) {
:
topicsQuery.data?.popularTopics.map((f, idx) => <li
key={f.id}
className={`flex items-start rounded-8 cursor-pointer font-bold ${f.id === selected && 'bg-gray-50'}`}
className={`flex items-start rounded-8 cursor-pointer font-bold ${f.id === selected && 'bg-gray-200'}`}
onClick={() => filterClicked(f.id)}
>
<span className='bg-gray-50 rounded-8 w-40 h-40 text-center py-8'>{f.icon}</span>
<span className={`${f.id !== selected && 'bg-gray-50'} rounded-8 w-40 h-40 text-center py-8`}>{f.icon}</span>
<span className="self-center px-16">
{f.title}
</span>

View File

@@ -3,8 +3,8 @@ import { Nullable } from 'remirror';
const filters = [
{
text: "🔥 Popular",
value: 'popular'
text: "🔥 Hottest",
value: 'hottest'
}, {
text: "📆 Newest",
value: 'newest'
@@ -34,7 +34,7 @@ export default function SortBy({ filterChanged }: Props) {
<ul>
{filters.map((f, idx) => <li
key={f.value}
className={`p-12 rounded-8 cursor-pointer font-bold ${f.value === selected && 'bg-gray-100'}`}
className={`p-12 rounded-8 cursor-pointer font-bold ${f.value === selected && 'bg-gray-200'}`}
onClick={() => filterClicked(f.value)}
>
{f.text}

View File

@@ -63,6 +63,19 @@ export type Category = {
votes_sum: Scalars['Int'];
};
export type Hackathon = {
__typename?: 'Hackathon';
cover_image: Scalars['String'];
description: Scalars['String'];
end_date: Scalars['Date'];
id: Scalars['Int'];
location: Scalars['String'];
start_date: Scalars['Date'];
title: Scalars['String'];
topics: Array<Topic>;
website: Scalars['String'];
};
export type LnurlDetails = {
__typename?: 'LnurlDetails';
commentAllowed: Maybe<Scalars['Int']>;
@@ -139,6 +152,7 @@ export type Query = {
allCategories: Array<Category>;
allProjects: Array<Project>;
allTopics: Array<Topic>;
getAllHackathons: Array<Hackathon>;
getCategory: Category;
getFeed: Array<Post>;
getLnurlDetailsForProject: LnurlDetails;
@@ -159,6 +173,12 @@ export type QueryAllProjectsArgs = {
};
export type QueryGetAllHackathonsArgs = {
sortBy: InputMaybe<Scalars['String']>;
topic: InputMaybe<Scalars['Int']>;
};
export type QueryGetCategoryArgs = {
id: Scalars['Int'];
};
@@ -297,6 +317,19 @@ 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 AllTopicsQueryVariables = Exact<{ [key: string]: never; }>;
export type AllTopicsQuery = { __typename?: 'Query', allTopics: Array<{ __typename?: 'Topic', id: number, title: string, icon: string }> };
export type GetHackathonsQueryVariables = Exact<{
sortBy: InputMaybe<Scalars['String']>;
topic: InputMaybe<Scalars['Int']>;
}>;
export type GetHackathonsQuery = { __typename?: 'Query', getAllHackathons: Array<{ __typename?: 'Hackathon', id: number, title: string, description: string, cover_image: string, start_date: any, end_date: any, location: string, website: string, topics: Array<{ __typename?: 'Topic', id: number, title: string, icon: string }> }> };
export type TrendingPostsQueryVariables = Exact<{ [key: string]: never; }>;
@@ -450,6 +483,90 @@ 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 AllTopicsDocument = gql`
query allTopics {
allTopics {
id
title
icon
}
}
`;
/**
* __useAllTopicsQuery__
*
* To run a query within a React component, call `useAllTopicsQuery` and pass it any options that fit your needs.
* When your component renders, `useAllTopicsQuery` 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 } = useAllTopicsQuery({
* variables: {
* },
* });
*/
export function useAllTopicsQuery(baseOptions?: Apollo.QueryHookOptions<AllTopicsQuery, AllTopicsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<AllTopicsQuery, AllTopicsQueryVariables>(AllTopicsDocument, options);
}
export function useAllTopicsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AllTopicsQuery, AllTopicsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<AllTopicsQuery, AllTopicsQueryVariables>(AllTopicsDocument, options);
}
export type AllTopicsQueryHookResult = ReturnType<typeof useAllTopicsQuery>;
export type AllTopicsLazyQueryHookResult = ReturnType<typeof useAllTopicsLazyQuery>;
export type AllTopicsQueryResult = Apollo.QueryResult<AllTopicsQuery, AllTopicsQueryVariables>;
export const GetHackathonsDocument = gql`
query getHackathons($sortBy: String, $topic: Int) {
getAllHackathons(sortBy: $sortBy, topic: $topic) {
id
title
description
cover_image
start_date
end_date
location
website
topics {
id
title
icon
}
}
}
`;
/**
* __useGetHackathonsQuery__
*
* To run a query within a React component, call `useGetHackathonsQuery` and pass it any options that fit your needs.
* When your component renders, `useGetHackathonsQuery` 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 } = useGetHackathonsQuery({
* variables: {
* sortBy: // value for 'sortBy'
* topic: // value for 'topic'
* },
* });
*/
export function useGetHackathonsQuery(baseOptions?: Apollo.QueryHookOptions<GetHackathonsQuery, GetHackathonsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<GetHackathonsQuery, GetHackathonsQueryVariables>(GetHackathonsDocument, options);
}
export function useGetHackathonsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetHackathonsQuery, GetHackathonsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<GetHackathonsQuery, GetHackathonsQueryVariables>(GetHackathonsDocument, options);
}
export type GetHackathonsQueryHookResult = ReturnType<typeof useGetHackathonsQuery>;
export type GetHackathonsLazyQueryHookResult = ReturnType<typeof useGetHackathonsLazyQuery>;
export type GetHackathonsQueryResult = Apollo.QueryResult<GetHackathonsQuery, GetHackathonsQueryVariables>;
export const TrendingPostsDocument = gql`
query TrendingPosts {
getTrendingPosts {

View File

@@ -1,3 +1,4 @@
import { Hackathon } from "src/graphql"
import { topics } from "./topics"
import { getCoverImage, getItems } from "./utils"
@@ -12,61 +13,67 @@ export const hackathons = [
{
id: 1,
title: 'Fulmo Hackday',
date: '22nd - 28th March, 2022',
start_date: new Date(2022, 2, 22),
end_date: new Date(2022, 2, 28),
location: "Instanbul, Turkey",
cover_image: getCoverImage(),
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.",
topics: generateTopics(),
url: "https://bolt.fun/hackathons/shock-the-web"
website: "https://bolt.fun/hackathons/shock-the-web"
},
{
id: 2,
title: 'Lightning Leagues',
date: '22nd - 28th March, 2022',
start_date: new Date(2022, 2, 22),
end_date: new Date(2022, 2, 28),
location: "Instanbul, Turkey",
cover_image: getCoverImage(),
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.",
topics: generateTopics(),
url: "https://bolt.fun/hackathons/shock-the-web"
website: "https://bolt.fun/hackathons/shock-the-web"
},
{
id: 3,
title: 'Surfing on Lightning',
date: '22nd - 28th March, 2022',
start_date: new Date(2022, 2, 22),
end_date: new Date(2022, 2, 28),
location: "Instanbul, Turkey",
cover_image: getCoverImage(),
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.",
topics: generateTopics(),
url: "https://bolt.fun/hackathons/shock-the-web"
website: "https://bolt.fun/hackathons/shock-the-web"
},
{
id: 4,
title: 'Lightning Startups',
date: '22nd - 28th March, 2022',
start_date: new Date(2022, 2, 22),
end_date: new Date(2022, 2, 28),
location: "Instanbul, Turkey",
cover_image: getCoverImage(),
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.",
topics: generateTopics(),
url: "https://bolt.fun/hackathons/shock-the-web"
website: "https://bolt.fun/hackathons/shock-the-web"
},
{
id: 5,
title: 'Design-a-thon',
date: '22nd - 28th March, 2022',
start_date: new Date(2022, 2, 22),
end_date: new Date(2022, 2, 28),
location: "Instanbul, Turkey",
cover_image: getCoverImage(),
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.",
topics: generateTopics(),
url: "https://bolt.fun/hackathons/shock-the-web"
website: "https://bolt.fun/hackathons/shock-the-web"
},
{
id: 6,
title: 'Lightning Olympics',
date: '22nd - 28th March, 2022',
start_date: new Date(2022, 2, 22),
end_date: new Date(2022, 2, 28),
location: "Instanbul, Turkey",
cover_image: getCoverImage(),
description: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam quam felis ut interdum commodo, scelerisque.",
topics: generateTopics(),
url: "https://bolt.fun/hackathons/shock-the-web"
website: "https://bolt.fun/hackathons/shock-the-web"
},
]
].map(i => ({ ...i, __typename: "Hackathon" })) as Hackathon[]

View File

@@ -1,6 +1,6 @@
import { graphql } from 'msw'
import { allCategories, getCategory, getFeed, getPostById, getProject, getTrendingPosts, hottestProjects, newProjects, popularTopics, projectsByCategory, searchProjects } from './resolvers'
import { allCategories, getAllHackathons, getCategory, getFeed, getPostById, getProject, getTrendingPosts, hottestProjects, newProjects, popularTopics, projectsByCategory, searchProjects } from './resolvers'
import {
NavCategoriesQuery,
ExploreProjectsQuery,
@@ -21,6 +21,10 @@ import {
TrendingPostsQuery,
PopularTopicsQuery,
PopularTopicsQueryVariables,
GetHackathonsQuery,
GetHackathonsQueryVariables,
AllTopicsQuery,
AllTopicsQueryVariables,
} from 'src/graphql'
const delay = (ms = 1000) => new Promise((res) => setTimeout(res, ms + Math.random() * 1000))
@@ -112,6 +116,15 @@ export const handlers = [
)
}),
graphql.query<AllTopicsQuery, AllTopicsQueryVariables>('allTopics', async (req, res, ctx) => {
await delay()
return res(
ctx.data({
allTopics: popularTopics()
})
)
}),
graphql.query<FeedQuery, FeedQueryVariables>('Feed', async (req, res, ctx) => {
await delay()
@@ -148,4 +161,15 @@ export const handlers = [
)
}),
graphql.query<GetHackathonsQuery, GetHackathonsQueryVariables>('getHackathons', async (req, res, ctx) => {
await delay()
return res(
ctx.data({
getAllHackathons: getAllHackathons()
})
)
}),
]

View File

@@ -2,6 +2,7 @@ import { MOCK_DATA } from "./data";
import { Query, QueryGetFeedArgs, QueryGetPostByIdArgs } from 'src/graphql'
import { Chance } from "chance";
import { topics } from "./data/topics";
import { hackathons } from "./data/hackathon";
const chance = new Chance()
@@ -63,4 +64,8 @@ export function getTrendingPosts(): Query['getTrendingPosts'] {
export function popularTopics() {
return topics;
}
export function getAllHackathons() {
return hackathons;
}

View File

@@ -1,5 +1,4 @@
import { WebLNProvider } from "webln";
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { createSlice } from "@reduxjs/toolkit";

View File

@@ -10,8 +10,6 @@ export function randomItem(...args: any[]) {
}
export function randomItems(cnt: number, ...args: any[]) {
console.log(cnt);
return shuffle(args).slice(0, cnt);
}

View File

@@ -1,5 +1,4 @@
import { QueryResult } from "@apollo/client";
import { useUpdateEffect } from "@react-hookz/web";
import { useCallback, useState } from "react";
export const useInfiniteQuery = (query: QueryResult, dataField: string) => {