mirror of
https://github.com/aljazceru/landscape-template.git
synced 2026-02-23 07:24:32 +01:00
feat: projects filters
This commit is contained in:
@@ -30,7 +30,11 @@ export default function Modal({ onClose, children, ...props }: Props) {
|
||||
className=' '
|
||||
closeTimeoutMS={1000}
|
||||
onAfterClose={onAfterClose}
|
||||
contentElement={(_props, children) => <div {..._props} className={`${_props.className} w-screen min-h-screen relative flex flex-col justify-center items-center md:py-64 md:px-16 inset-0`}>
|
||||
contentElement={(_props, children) => <div {..._props} className={`
|
||||
${_props.className}
|
||||
w-screen min-h-screen relative flex flex-col justify-center items-center inset-0
|
||||
${!props.isPageModal && "md:py-64 md:px-16 "}
|
||||
`}>
|
||||
<div
|
||||
onClick={onClose}
|
||||
className={`absolute w-full h-full top-0 left-0 bg-gray-300 bg-opacity-50 ${props.isPageModal && "hidden md:block"}`}
|
||||
|
||||
@@ -50,21 +50,11 @@ export default function ModalsContainer() {
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
// let prevOverflow = document.body.style.overflow;
|
||||
|
||||
// if (isOpen) {
|
||||
// const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
||||
// prevOverflow = document.body.style.overflow;
|
||||
// console.log(prevOverflow);
|
||||
// document.body.style.overflow = 'hidden';
|
||||
// if (scrollbarWidth) {
|
||||
// document.documentElement.style.paddingRight = `${scrollbarWidth}px`;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// document.body.style.overflow = prevOverflow;
|
||||
// document.documentElement.style.paddingRight = "";
|
||||
// }
|
||||
if (isOpen) {
|
||||
document.body.style.overflow = 'hidden';
|
||||
} else {
|
||||
document.body.style.overflow = 'unset';
|
||||
}
|
||||
}, [isOpen]);
|
||||
|
||||
return (
|
||||
|
||||
@@ -35,7 +35,7 @@ export default function Categories(props: Props) {
|
||||
|
||||
|
||||
if (loading || !data)
|
||||
return <div className="flex gap-32 border-b border-gray-200">
|
||||
return <div className="flex overflow-hidden gap-32 border-b border-gray-200">
|
||||
{Array(15).fill(0).map((_, idx) =>
|
||||
<div
|
||||
key={idx}
|
||||
@@ -50,14 +50,14 @@ export default function Categories(props: Props) {
|
||||
return (
|
||||
|
||||
<div className="relative group">
|
||||
<div className="overflow-hidden" ref={viewportRef}>
|
||||
<div className="select-none w-full flex gap-32 border-b border-gray-200">
|
||||
<div className="overflow-hidden border-b border-gray-200" ref={viewportRef}>
|
||||
<div className="select-none w-full flex gap-8">
|
||||
<button
|
||||
onClick={() => {
|
||||
props.onChange?.(null)
|
||||
}}
|
||||
className={`
|
||||
flex flex-col font-medium py-16 min-w-max
|
||||
flex flex-col font-medium hover:bg-gray-100 active:bg-gray-200 rounded-t-8 px-16 py-16 min-w-max
|
||||
${props.value === null ? "text-primary-500 border-b-2 border-primary-500" : "text-gray-500"}
|
||||
`}
|
||||
>All projects</button>
|
||||
@@ -69,7 +69,7 @@ export default function Categories(props: Props) {
|
||||
props.onChange?.(isSame ? null : category)
|
||||
}}
|
||||
className={`
|
||||
flex flex-col font-medium py-16 min-w-max
|
||||
flex flex-col font-medium hover:bg-gray-100 active:bg-gray-200 rounded-t-8 px-8 py-16 min-w-max
|
||||
${props.value?.id === category?.id ? "text-primary-500 border-b-2 border-primary-500" : "text-gray-500"}
|
||||
`}
|
||||
>{category!.name} ({category?.projectsCount!})</button>
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function ProjectCardMini({ project, onClick }: Props) {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="py-16 select-none px-16 flex items-center gap-16 border-2 border-gray-100 rounded-16 bg-white hover:bg-gray-50"
|
||||
className="py-16 select-none px-16 flex items-center gap-16 rounded-16 hover:bg-gray-100"
|
||||
onKeyDown={e => {
|
||||
e.key !== 'Enter' || onClick(project?.id!)
|
||||
}}
|
||||
|
||||
@@ -5,30 +5,102 @@ import HeaderImage from './Header/Header';
|
||||
import ProjectsGrid from './ProjectsGrid/ProjectsGrid';
|
||||
import { Helmet } from "react-helmet";
|
||||
import Categories, { Category } from '../../Components/Categories/Categories';
|
||||
import { useState } from 'react';
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import Header from './Header/Header';
|
||||
import Button from 'src/Components/Button/Button';
|
||||
import { useAppDispatch } from 'src/utils/hooks';
|
||||
import { openModal } from 'src/redux/features/modals.slice';
|
||||
import { createAction } from '@reduxjs/toolkit';
|
||||
import { useReduxEffect } from 'src/utils/hooks/useReduxEffect';
|
||||
import { NetworkStatus } from '@apollo/client';
|
||||
import { GoSettings } from 'react-icons/go'
|
||||
import { FiSliders } from 'react-icons/fi';
|
||||
import { ProjectsFilters } from './Filters/FiltersModal';
|
||||
|
||||
const UPDATE_FILTERS_ACTION = createAction<{ categoriesIds?: string[], tagsIds?: string[], yearFounded?: string }>('PROJECTS_FILTERS_UPDATED')({})
|
||||
|
||||
export default function ExplorePage() {
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const [filters, setFilters] = useState<Partial<ProjectsFilters>>()
|
||||
const [selectedCategory, setSelectedCategory] = useState<Category | null>(null)
|
||||
const { data, loading, error } = useExplorePageQuery({
|
||||
|
||||
const queryFilters = useMemo(() => {
|
||||
let filter: any = {}
|
||||
|
||||
if (!filters) return null;
|
||||
|
||||
if (filters.categoriesIds && filters.categoriesIds?.length > 0)
|
||||
filter['categoryId'] = filters.categoriesIds
|
||||
|
||||
if (filters.tagsIds && filters.tagsIds?.length > 0)
|
||||
filter['tags'] = filters.tagsIds
|
||||
|
||||
if (filters.yearFounded && filters.yearFounded !== "Any")
|
||||
filter['yearFounded'] = Number(filters.yearFounded)
|
||||
|
||||
if (Object.keys(filter).length === 0) return null
|
||||
|
||||
return filter;
|
||||
}, [filters])
|
||||
|
||||
const { data, networkStatus, error } = useExplorePageQuery({
|
||||
variables: {
|
||||
page: 1,
|
||||
pageSize: 20,
|
||||
filter: selectedCategory ? {
|
||||
"categoryId": selectedCategory?.id
|
||||
} : null
|
||||
}
|
||||
filter: queryFilters
|
||||
},
|
||||
notifyOnNetworkStatusChange: true,
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const onFiltersUpdated = useCallback(({ payload }: typeof UPDATE_FILTERS_ACTION) => {
|
||||
setSelectedCategory(null)
|
||||
setFilters(payload);
|
||||
}, [])
|
||||
|
||||
useReduxEffect(onFiltersUpdated, UPDATE_FILTERS_ACTION.type)
|
||||
|
||||
|
||||
const openFilters = () => {
|
||||
dispatch(openModal({
|
||||
Modal: "FiltersModal",
|
||||
isPageModal: true,
|
||||
props: {
|
||||
callbackAction: {
|
||||
type: UPDATE_FILTERS_ACTION.type,
|
||||
payload: {
|
||||
|
||||
}
|
||||
},
|
||||
initFilters: {
|
||||
...filters
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
const selectCategoryTab = (category?: Category | null) => {
|
||||
if (!category?.id)
|
||||
return;
|
||||
setSelectedCategory(category);
|
||||
setFilters({
|
||||
categoriesIds: [category.id]
|
||||
})
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <div className="p-32">
|
||||
<ErrorMessage type='fetching' />
|
||||
</div>
|
||||
}
|
||||
|
||||
console.log(networkStatus, NetworkStatus.loading, NetworkStatus.refetch, NetworkStatus.setVariables);
|
||||
|
||||
const isLoading = networkStatus === NetworkStatus.loading || networkStatus === NetworkStatus.refetch || networkStatus === NetworkStatus.setVariables;
|
||||
|
||||
|
||||
return (
|
||||
@@ -41,10 +113,13 @@ export default function ExplorePage() {
|
||||
<Header
|
||||
category={selectedCategory}
|
||||
/>
|
||||
<Categories value={selectedCategory} onChange={v => setSelectedCategory(v)} />
|
||||
<div className="grid grid-cols-[1fr_auto] items-center gap-32">
|
||||
<div className="min-w-0"><Categories value={selectedCategory} onChange={v => selectCategoryTab(v)} /></div>
|
||||
<Button className='self-center' variant='outline' color='white' onClick={openFilters}><FiSliders className="scale-150 mr-8 text-primary-500" /> <span className='align-middle'>Filters</span></Button>
|
||||
</div>
|
||||
<div className="mt-40">
|
||||
<ProjectsGrid
|
||||
isLoading={loading}
|
||||
isLoading={isLoading}
|
||||
projects={data?.projects?.filter((p) => p !== null) as any[] ?? []}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||
|
||||
import FiltersModal from './FiltersModal';
|
||||
|
||||
import { ModalsDecorator } from 'src/utils/storybook/decorators';
|
||||
|
||||
export default {
|
||||
title: 'Projects/Filters Modal',
|
||||
component: FiltersModal,
|
||||
|
||||
decorators: [ModalsDecorator]
|
||||
} as ComponentMeta<typeof FiltersModal>;
|
||||
|
||||
const Template: ComponentStory<typeof FiltersModal> = (args) => <FiltersModal {...args} />;
|
||||
|
||||
export const Default = Template.bind({});
|
||||
|
||||
186
src/features/Projects/pages/ExplorePage/Filters/FiltersModal.tsx
Normal file
186
src/features/Projects/pages/ExplorePage/Filters/FiltersModal.tsx
Normal file
@@ -0,0 +1,186 @@
|
||||
import React, { FormEvent, useState } from 'react'
|
||||
import { ModalCard, modalCardVariants } from 'src/Components/Modals/ModalsContainer/ModalsContainer'
|
||||
import { motion } from 'framer-motion'
|
||||
import { IoClose } from 'react-icons/io5'
|
||||
import Button from 'src/Components/Button/Button'
|
||||
import { useAppDispatch } from 'src/utils/hooks'
|
||||
import { PayloadAction } from '@reduxjs/toolkit'
|
||||
import * as yup from "yup";
|
||||
import { SubmitHandler, useForm } from "react-hook-form"
|
||||
import { yupResolver } from "@hookform/resolvers/yup";
|
||||
import IconButton from 'src/Components/IconButton/IconButton'
|
||||
import Badge from 'src/Components/Badge/Badge'
|
||||
import { useGetFiltersQuery } from 'src/graphql'
|
||||
import Skeleton from 'react-loading-skeleton';
|
||||
import { random } from 'src/utils/helperFunctions';
|
||||
|
||||
interface Props extends ModalCard {
|
||||
initFilters?: Partial<ProjectsFilters>
|
||||
callbackAction: PayloadAction<Partial<ProjectsFilters>>
|
||||
}
|
||||
|
||||
|
||||
|
||||
export interface IFormInputs {
|
||||
text: string,
|
||||
href: string,
|
||||
}
|
||||
|
||||
export type ProjectsFilters = {
|
||||
categoriesIds: string[]
|
||||
tagsIds: string[]
|
||||
yearFounded: string
|
||||
}
|
||||
|
||||
const yearsFounded = ['Any', '2016', '2017', '2018', '2019', '2020', '2021', '2022']
|
||||
|
||||
export default function FiltersModal({ onClose, direction, initFilters, callbackAction, ...props }: Props) {
|
||||
|
||||
const dispatch = useAppDispatch()
|
||||
const query = useGetFiltersQuery();
|
||||
|
||||
const [categoriesFilter, setCategoriesFilter] = useState<string[]>(initFilters?.categoriesIds ?? []);
|
||||
const [tagsFilter, setTagsFilter] = useState<string[]>(initFilters?.tagsIds ?? []);
|
||||
const [yearFoundedFilter, setYearFoundedFilter] = useState(initFilters?.yearFounded ?? yearsFounded[0]);
|
||||
|
||||
const clickCategory = (id: string) => {
|
||||
if (categoriesFilter.includes(id))
|
||||
setCategoriesFilter(categoriesFilter.filter(v => v !== id));
|
||||
else
|
||||
setCategoriesFilter([...categoriesFilter, id]);
|
||||
}
|
||||
|
||||
|
||||
const clickTag = (id: string) => {
|
||||
if (tagsFilter.includes(id))
|
||||
setTagsFilter(tagsFilter.filter(v => v !== id));
|
||||
else
|
||||
setTagsFilter([...tagsFilter, id]);
|
||||
}
|
||||
|
||||
const clearFilters = () => {
|
||||
setCategoriesFilter([]);
|
||||
setTagsFilter([]);
|
||||
setYearFoundedFilter(yearsFounded[0]);
|
||||
}
|
||||
|
||||
const applyFilters = () => {
|
||||
const action = Object.assign({}, callbackAction);
|
||||
action.payload = { categoriesIds: categoriesFilter, tagsIds: tagsFilter, yearFounded: yearFoundedFilter }
|
||||
dispatch(action)
|
||||
onClose?.();
|
||||
}
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
custom={direction}
|
||||
variants={modalCardVariants}
|
||||
initial='initial'
|
||||
animate="animate"
|
||||
exit='exit'
|
||||
className="modal-card p-24 min-h-screen !rounded-0 relative"
|
||||
>
|
||||
|
||||
<div className="page-container relative">
|
||||
<div className="flex justify-between items-center">
|
||||
<h2 className='text-h2 font-bolder'>Filter Projects</h2>
|
||||
<IconButton onClick={onClose} className='!bg-gray-100 hover:!bg-gray-200'>
|
||||
<IoClose className='text-h3 text-gray-400' />
|
||||
</IconButton>
|
||||
</div>
|
||||
<div className="flex flex-col gap-24 mt-24">
|
||||
<hr className="bg-gray-100" />
|
||||
<div>
|
||||
<h3 className="text-body2 font-bolder">🌈 Category</h3>
|
||||
<p className='text-gray-600 mt-8'>Select one or more tags to search from.</p>
|
||||
<ul className="flex flex-wrap gap-16 mt-24">
|
||||
{query.data?.categoryList
|
||||
?.filter(c => !!(c && c.name))
|
||||
.map(category => <li
|
||||
key={category?.id}
|
||||
>
|
||||
<button
|
||||
className={`
|
||||
px-12 py-8 border rounded-10 text-body5 font-medium
|
||||
active:scale-95 transition-transform
|
||||
${!categoriesFilter.includes(category?.id!) ? "bg-gray-100 hover:bg-gray-200 border-gray-200" : "bg-primary-100 text-primary-600 border-primary-200"}
|
||||
`}
|
||||
onClick={() => clickCategory(category?.id!)}
|
||||
>{category?.icon} {category?.name}
|
||||
</button>
|
||||
</li>)}
|
||||
{query.loading &&
|
||||
Array(10).fill(0).map((_, idx) => {
|
||||
|
||||
return <div
|
||||
key={idx}
|
||||
className={`px-12 py-8 border bg-gray-100 hover:bg-gray-200 border-gray-200 rounded-10 text-body5 font-medium`}
|
||||
><Skeleton width={`${Math.round(random(8, 15))}ch`} />
|
||||
</div>
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
<hr className="bg-gray-100" />
|
||||
<div>
|
||||
<h3 className="text-body2 font-bolder">🔖 Tags</h3>
|
||||
<p className='text-gray-600 mt-8'>Select one or more tags to search from.</p>
|
||||
<ul className="flex flex-wrap gap-16 mt-24">
|
||||
{query.data?.tags
|
||||
?.filter(t => !!(t && t.name))
|
||||
.map(tag => <li
|
||||
key={tag?.id}
|
||||
>
|
||||
<button
|
||||
className={`
|
||||
px-12 py-8 border rounded-10 text-body5 font-medium
|
||||
active:scale-95 transition-transform
|
||||
${!tagsFilter.includes(tag?.id!) ? "bg-gray-100 hover:bg-gray-200 border-gray-200" : "bg-primary-100 text-primary-600 border-primary-200"}
|
||||
`}
|
||||
onClick={() => clickTag(tag?.id!)}
|
||||
>{tag?.icon} {tag?.name}
|
||||
</button>
|
||||
</li>)}
|
||||
{query.loading &&
|
||||
Array(8).fill(0).map((_, idx) => {
|
||||
|
||||
return <div
|
||||
key={idx}
|
||||
className={`px-12 py-8 border bg-gray-100 hover:bg-gray-200 border-gray-200 rounded-10 text-body5 font-medium`}
|
||||
><Skeleton width={`${Math.round(random(8, 15))}ch`} />
|
||||
</div>
|
||||
})}
|
||||
</ul>
|
||||
</div>
|
||||
<hr className="bg-gray-100" />
|
||||
<div>
|
||||
<h3 className="text-body2 font-bolder">📆 Founded</h3>
|
||||
<p className='text-gray-600 mt-8'>Select the year you wish to see companies founded in.</p>
|
||||
<div className="flex flex-wrap gap-48 mt-24">
|
||||
{yearsFounded.map(year =>
|
||||
<div key={year} className='flex gap-16 items-center'>
|
||||
<input
|
||||
name='yearFounded'
|
||||
value={year}
|
||||
checked={year === yearFoundedFilter}
|
||||
className='input-radio self-center'
|
||||
onChange={e => setYearFoundedFilter(e.target.value)}
|
||||
type="radio" />
|
||||
<label className="text-body4 text-gray-800" >
|
||||
{year}
|
||||
</label>
|
||||
</div>)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="my-48"></div>
|
||||
<div className='w-full bg-white content-container fixed bottom-0 left-0 py-24 border-t border-gray-200'>
|
||||
<div className="flex justify-end gap-16">
|
||||
<Button onClick={clearFilters}>Clear all</Button>
|
||||
<Button color='primary' onClick={applyFilters}>Apply filters</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
query GetFilters {
|
||||
categoryList {
|
||||
id
|
||||
name
|
||||
icon
|
||||
}
|
||||
tags {
|
||||
id
|
||||
name
|
||||
icon
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
|
||||
import { lazyModal } from 'src/utils/helperFunctions';
|
||||
|
||||
export const { LazyComponent: InsertLinkModal } = lazyModal(() => import('./FiltersModal'))
|
||||
@@ -18,7 +18,11 @@ query ProjectDetails($projectsId: String) {
|
||||
website
|
||||
yearFounded
|
||||
telegram
|
||||
subcategory
|
||||
tags {
|
||||
id
|
||||
name
|
||||
icon
|
||||
}
|
||||
stars
|
||||
repository
|
||||
openSource
|
||||
|
||||
@@ -127,7 +127,7 @@ export default function ProjectDetailsCard({ direction, projectId, ...props }: P
|
||||
{/* Title & Basic Info */}
|
||||
<div className="flex flex-col mt-[-80px] md:flex-row md:mt-0 gap-24 md:items-center relative">
|
||||
<div className="flex-shrink-0 w-[108px] h-[108px]">
|
||||
<img className="w-full h-full border-2 border-white rounded-24" src={project?.logo?.[0]['thumbnails']['large'].url} alt="" />
|
||||
<img className="w-full h-full border-2 border-white rounded-24 object-cover" src={project?.logo?.[0]['thumbnails']['large'].url} alt="" />
|
||||
</div>
|
||||
<div className='flex flex-col gap-8 items-start justify-between'>
|
||||
<a href={project?.website!} target='_blank' rel="noreferrer"><h3 className="text-body1 font-bold">{project?.title}</h3></a>
|
||||
|
||||
@@ -23,7 +23,9 @@ export type Query = {
|
||||
backup: Maybe<Array<Maybe<Backup>>>;
|
||||
categories: Maybe<Array<Maybe<Categories>>>;
|
||||
categoryList: Maybe<Array<Maybe<CategoryList>>>;
|
||||
companies: Maybe<Array<Maybe<Companies>>>;
|
||||
projects: Maybe<Array<Maybe<Projects>>>;
|
||||
stats: Maybe<Array<Maybe<Stats>>>;
|
||||
tags: Maybe<Array<Maybe<Tags>>>;
|
||||
};
|
||||
|
||||
@@ -137,6 +139,27 @@ export type QueryCategoryListArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type QueryCompaniesArgs = {
|
||||
_filter: InputMaybe<Scalars['JSON']>;
|
||||
_order_by: InputMaybe<Scalars['JSON']>;
|
||||
_page: InputMaybe<Scalars['JSON']>;
|
||||
_page_size: InputMaybe<Scalars['JSON']>;
|
||||
angelList: InputMaybe<Scalars['String']>;
|
||||
assignee: InputMaybe<Scalars['String']>;
|
||||
crunchbase: InputMaybe<Scalars['String']>;
|
||||
description: InputMaybe<Scalars['String']>;
|
||||
id: InputMaybe<Scalars['String']>;
|
||||
industry: InputMaybe<Scalars['String']>;
|
||||
location: InputMaybe<Scalars['String']>;
|
||||
logo: InputMaybe<Array<InputMaybe<Scalars['JSON']>>>;
|
||||
name: InputMaybe<Scalars['String']>;
|
||||
projects: InputMaybe<Array<InputMaybe<Scalars['String']>>>;
|
||||
status: InputMaybe<Scalars['String']>;
|
||||
type: InputMaybe<Scalars['String']>;
|
||||
website: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
||||
export type QueryProjectsArgs = {
|
||||
_filter: InputMaybe<Scalars['JSON']>;
|
||||
_order_by: InputMaybe<Scalars['JSON']>;
|
||||
@@ -148,6 +171,7 @@ export type QueryProjectsArgs = {
|
||||
categoryId: InputMaybe<Array<InputMaybe<Scalars['String']>>>;
|
||||
categoryList: InputMaybe<Array<InputMaybe<Scalars['String']>>>;
|
||||
comment: InputMaybe<Scalars['String']>;
|
||||
company: InputMaybe<Array<InputMaybe<Scalars['String']>>>;
|
||||
companyName: InputMaybe<Scalars['String']>;
|
||||
createdAt: InputMaybe<Scalars['String']>;
|
||||
dead: InputMaybe<Scalars['Boolean']>;
|
||||
@@ -165,6 +189,7 @@ export type QueryProjectsArgs = {
|
||||
stars: InputMaybe<Scalars['Float']>;
|
||||
status: InputMaybe<Scalars['String']>;
|
||||
subcategory: InputMaybe<Array<InputMaybe<Scalars['String']>>>;
|
||||
tags: InputMaybe<Array<InputMaybe<Scalars['String']>>>;
|
||||
telegram: InputMaybe<Scalars['String']>;
|
||||
title: InputMaybe<Scalars['String']>;
|
||||
twitter: InputMaybe<Scalars['String']>;
|
||||
@@ -176,6 +201,17 @@ export type QueryProjectsArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type QueryStatsArgs = {
|
||||
_filter: InputMaybe<Scalars['JSON']>;
|
||||
_order_by: InputMaybe<Scalars['JSON']>;
|
||||
_page: InputMaybe<Scalars['JSON']>;
|
||||
_page_size: InputMaybe<Scalars['JSON']>;
|
||||
id: InputMaybe<Scalars['String']>;
|
||||
stat: InputMaybe<Scalars['String']>;
|
||||
totalProjects: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
||||
export type QueryTagsArgs = {
|
||||
_filter: InputMaybe<Scalars['JSON']>;
|
||||
_order_by: InputMaybe<Scalars['JSON']>;
|
||||
@@ -190,6 +226,8 @@ export type QueryTagsArgs = {
|
||||
importedTableCopy2: InputMaybe<Array<InputMaybe<Scalars['String']>>>;
|
||||
name: InputMaybe<Scalars['String']>;
|
||||
projectProductFromFeatured: InputMaybe<Array<InputMaybe<Scalars['String']>>>;
|
||||
projects: InputMaybe<Array<InputMaybe<Scalars['String']>>>;
|
||||
projectsCount: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type ApiTesting = {
|
||||
@@ -285,6 +323,23 @@ export type CategoryList = {
|
||||
projectsCount: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type Companies = {
|
||||
__typename?: 'companies';
|
||||
angelList: Maybe<Scalars['String']>;
|
||||
assignee: Maybe<Scalars['String']>;
|
||||
crunchbase: Maybe<Scalars['String']>;
|
||||
description: Maybe<Scalars['String']>;
|
||||
id: Maybe<Scalars['String']>;
|
||||
industry: Maybe<Scalars['String']>;
|
||||
location: Maybe<Scalars['String']>;
|
||||
logo: Maybe<Array<Maybe<Scalars['JSON']>>>;
|
||||
name: Maybe<Scalars['String']>;
|
||||
projects: Maybe<Array<Maybe<Projects>>>;
|
||||
status: Maybe<Scalars['String']>;
|
||||
type: Maybe<Scalars['String']>;
|
||||
website: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type Projects = {
|
||||
__typename?: 'projects';
|
||||
categories: Maybe<Array<Maybe<Categories>>>;
|
||||
@@ -293,6 +348,7 @@ export type Projects = {
|
||||
categoryId: Maybe<Array<Maybe<Scalars['String']>>>;
|
||||
categoryList: Maybe<Array<Maybe<CategoryList>>>;
|
||||
comment: Maybe<Scalars['String']>;
|
||||
company: Maybe<Array<Maybe<Companies>>>;
|
||||
companyName: Maybe<Scalars['String']>;
|
||||
createdAt: Maybe<Scalars['String']>;
|
||||
dead: Maybe<Scalars['Boolean']>;
|
||||
@@ -310,6 +366,7 @@ export type Projects = {
|
||||
stars: Maybe<Scalars['Float']>;
|
||||
status: Maybe<Scalars['String']>;
|
||||
subcategory: Maybe<Array<Maybe<Scalars['String']>>>;
|
||||
tags: Maybe<Array<Maybe<Tags>>>;
|
||||
telegram: Maybe<Scalars['String']>;
|
||||
title: Maybe<Scalars['String']>;
|
||||
twitter: Maybe<Scalars['String']>;
|
||||
@@ -320,6 +377,13 @@ export type Projects = {
|
||||
yearFounded: Maybe<Scalars['Float']>;
|
||||
};
|
||||
|
||||
export type Stats = {
|
||||
__typename?: 'stats';
|
||||
id: Maybe<Scalars['String']>;
|
||||
stat: Maybe<Scalars['String']>;
|
||||
totalProjects: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type Tags = {
|
||||
__typename?: 'tags';
|
||||
description: Maybe<Scalars['String']>;
|
||||
@@ -331,6 +395,8 @@ export type Tags = {
|
||||
importedTableCopy2: Maybe<Array<Maybe<Backup>>>;
|
||||
name: Maybe<Scalars['String']>;
|
||||
projectProductFromFeatured: Maybe<Array<Maybe<Scalars['String']>>>;
|
||||
projects: Maybe<Array<Maybe<Projects>>>;
|
||||
projectsCount: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type AllCategoriesQueryVariables = Exact<{
|
||||
@@ -340,6 +406,11 @@ export type AllCategoriesQueryVariables = Exact<{
|
||||
|
||||
export type AllCategoriesQuery = { __typename?: 'Query', categoryList: Array<{ __typename?: 'categoryList', projectsCount: string | null, id: string | null, name: string | null, description: string | null, icon: string | null } | null> | null };
|
||||
|
||||
export type GetFiltersQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type GetFiltersQuery = { __typename?: 'Query', categoryList: Array<{ __typename?: 'categoryList', id: string | null, name: string | null, icon: string | null } | null> | null, tags: Array<{ __typename?: 'tags', id: string | null, name: string | null, icon: string | null } | null> | null };
|
||||
|
||||
export type ExplorePageQueryVariables = Exact<{
|
||||
filter: InputMaybe<Scalars['JSON']>;
|
||||
page: InputMaybe<Scalars['JSON']>;
|
||||
@@ -354,7 +425,7 @@ export type ProjectDetailsQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ProjectDetailsQuery = { __typename?: 'Query', projects: Array<{ __typename?: 'projects', id: string | null, title: string | null, dead: boolean | null, createdAt: string | null, companyName: string | null, category: string | null, description: string | null, discord: string | null, endDate: string | null, twitter: string | null, updatedAt: string | null, watchers: number | null, website: string | null, yearFounded: number | null, telegram: string | null, subcategory: Array<string | null> | null, stars: number | null, repository: string | null, openSource: string | null, logo: Array<any | null> | null, linkedIn: string | null, license: string | null, language: string | null, forks: number | null, categoryList: Array<{ __typename?: 'categoryList', name: string | null } | null> | null } | null> | null };
|
||||
export type ProjectDetailsQuery = { __typename?: 'Query', projects: Array<{ __typename?: 'projects', id: string | null, title: string | null, dead: boolean | null, createdAt: string | null, companyName: string | null, category: string | null, description: string | null, discord: string | null, endDate: string | null, twitter: string | null, updatedAt: string | null, watchers: number | null, website: string | null, yearFounded: number | null, telegram: string | null, stars: number | null, repository: string | null, openSource: string | null, logo: Array<any | null> | null, linkedIn: string | null, license: string | null, language: string | null, forks: number | null, categoryList: Array<{ __typename?: 'categoryList', name: string | null } | null> | null, tags: Array<{ __typename?: 'tags', id: string | null, name: string | null, icon: string | null } | null> | null } | null> | null };
|
||||
|
||||
|
||||
export const AllCategoriesDocument = gql`
|
||||
@@ -396,6 +467,47 @@ export function useAllCategoriesLazyQuery(baseOptions?: Apollo.LazyQueryHookOpti
|
||||
export type AllCategoriesQueryHookResult = ReturnType<typeof useAllCategoriesQuery>;
|
||||
export type AllCategoriesLazyQueryHookResult = ReturnType<typeof useAllCategoriesLazyQuery>;
|
||||
export type AllCategoriesQueryResult = Apollo.QueryResult<AllCategoriesQuery, AllCategoriesQueryVariables>;
|
||||
export const GetFiltersDocument = gql`
|
||||
query GetFilters {
|
||||
categoryList {
|
||||
id
|
||||
name
|
||||
icon
|
||||
}
|
||||
tags {
|
||||
id
|
||||
name
|
||||
icon
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useGetFiltersQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useGetFiltersQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useGetFiltersQuery` 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 } = useGetFiltersQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useGetFiltersQuery(baseOptions?: Apollo.QueryHookOptions<GetFiltersQuery, GetFiltersQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<GetFiltersQuery, GetFiltersQueryVariables>(GetFiltersDocument, options);
|
||||
}
|
||||
export function useGetFiltersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<GetFiltersQuery, GetFiltersQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<GetFiltersQuery, GetFiltersQueryVariables>(GetFiltersDocument, options);
|
||||
}
|
||||
export type GetFiltersQueryHookResult = ReturnType<typeof useGetFiltersQuery>;
|
||||
export type GetFiltersLazyQueryHookResult = ReturnType<typeof useGetFiltersLazyQuery>;
|
||||
export type GetFiltersQueryResult = Apollo.QueryResult<GetFiltersQuery, GetFiltersQueryVariables>;
|
||||
export const ExplorePageDocument = gql`
|
||||
query ExplorePage($filter: JSON, $page: JSON, $pageSize: JSON) {
|
||||
projects(_filter: $filter, _page: $page, _page_size: $pageSize) {
|
||||
@@ -477,7 +589,11 @@ export const ProjectDetailsDocument = gql`
|
||||
website
|
||||
yearFounded
|
||||
telegram
|
||||
subcategory
|
||||
tags {
|
||||
id
|
||||
name
|
||||
icon
|
||||
}
|
||||
stars
|
||||
repository
|
||||
openSource
|
||||
|
||||
@@ -15,6 +15,7 @@ import { ConfirmModal } from "src/Components/Modals/ConfirmModal";
|
||||
import { ComponentProps } from "react";
|
||||
import { generateId } from "src/utils/helperFunctions";
|
||||
import { NoWeblnModal } from "src/Components/Modals/NoWeblnModal";
|
||||
import FiltersModal from "src/features/Projects/pages/ExplorePage/Filters/FiltersModal";
|
||||
// import { ConnectToMakerModal } from "src/features/Tournaments/pages/MakersPage/ConnectToMakerModal";
|
||||
// import { RegistrationModals } from "src/features/Tournaments/pages/OverviewPage/RegisterationModals";
|
||||
|
||||
@@ -30,6 +31,7 @@ export enum Direction {
|
||||
export const ALL_MODALS = {
|
||||
//Projects
|
||||
ProjectDetailsCard,
|
||||
FiltersModal,
|
||||
|
||||
// Auth
|
||||
Login_ScanningWalletCard,
|
||||
|
||||
@@ -12,7 +12,7 @@ html {
|
||||
|
||||
body {
|
||||
overflow-x: hidden;
|
||||
background-color: #f9fafb;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.content-container,
|
||||
|
||||
Reference in New Issue
Block a user