mirror of
https://github.com/aljazceru/landscape-template.git
synced 2026-02-21 22:44:21 +01:00
feat: add more filters, refactor filters state logic
This commit is contained in:
@@ -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 rounded-16 hover:bg-gray-100"
|
||||
className="py-16 select-none px-16 flex items-center gap-16 rounded-16 hover:bg-gray-50 hover:outline outline-1 outline-gray-200"
|
||||
onKeyDown={e => {
|
||||
e.key !== 'Enter' || onClick(project?.id!)
|
||||
}}
|
||||
@@ -20,7 +20,7 @@ export default function ProjectCardMini({ project, onClick }: Props) {
|
||||
tabIndex={0}
|
||||
role='button'
|
||||
>
|
||||
<img src={project?.logo?.[0]['thumbnails']['large'].url} alt={project?.title ?? ''} draggable="false" className="flex-shrink-0 w-64 h-64 object-cover bg-gray-200 border-0 rounded-full hover:cursor-pointer"></img>
|
||||
<img src={project?.logo?.[0]['thumbnails']['large'].url} alt={project?.title ?? ''} draggable="false" className="flex-shrink-0 w-64 h-64 object-cover bg-gray-200 border border-gray-200 rounded-full hover:cursor-pointer"></img>
|
||||
<div className="justify-around items-start min-w-0 flex-1 hover:cursor-pointer"
|
||||
>
|
||||
<p className="text-body4 w-full font-bold overflow-ellipsis overflow-hidden whitespace-nowrap">{project?.title}</p>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useParams, Navigate } from 'react-router-dom'
|
||||
|
||||
import ErrorMessage from 'src/Components/Errors/ErrorMessage/ErrorMessage';
|
||||
import { useExplorePageQuery } from 'src/graphql';
|
||||
import HeaderImage from './Header/Header';
|
||||
import ProjectsGrid from './ProjectsGrid/ProjectsGrid';
|
||||
import { Helmet } from "react-helmet";
|
||||
import Categories, { Category } from '../../Components/Categories/Categories';
|
||||
@@ -13,36 +12,53 @@ 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')({})
|
||||
const UPDATE_FILTERS_ACTION = createAction<Partial<ProjectsFilters>>('PROJECTS_FILTERS_UPDATED')({})
|
||||
|
||||
type QueryFilter = Partial<{
|
||||
categoryId: string[] | null
|
||||
tags: string[] | null
|
||||
yearFounded: number | null
|
||||
dead: boolean | null
|
||||
license: string | null
|
||||
}>
|
||||
|
||||
export default function ExplorePage() {
|
||||
|
||||
const dispatch = useAppDispatch();
|
||||
const [filters, setFilters] = useState<Partial<ProjectsFilters>>()
|
||||
const [filters, setFilters] = useState<Partial<ProjectsFilters> | null>(null)
|
||||
const [selectedCategory, setSelectedCategory] = useState<Category | null>(null)
|
||||
|
||||
const queryFilters = useMemo(() => {
|
||||
let filter: any = {}
|
||||
let filter: QueryFilter = {}
|
||||
|
||||
if (!filters) return null;
|
||||
|
||||
if (filters.categoriesIds && filters.categoriesIds?.length > 0)
|
||||
filter['categoryId'] = filters.categoriesIds
|
||||
filter.categoryId = filters.categoriesIds;
|
||||
|
||||
if (selectedCategory?.id) filter.categoryId = [selectedCategory?.id]
|
||||
|
||||
if (filters.tagsIds && filters.tagsIds?.length > 0)
|
||||
filter['tags'] = filters.tagsIds
|
||||
filter.tags = filters.tagsIds
|
||||
|
||||
if (filters.yearFounded && filters.yearFounded !== "Any")
|
||||
filter['yearFounded'] = Number(filters.yearFounded)
|
||||
if (filters.yearFounded && filters.yearFounded !== 'any')
|
||||
filter.yearFounded = Number(filters.yearFounded)
|
||||
|
||||
if (Object.keys(filter).length === 0) return null
|
||||
if (filters.projectStatus && filters.projectStatus !== 'any')
|
||||
filter.dead = filters.projectStatus === 'alive' ? false : true;
|
||||
|
||||
|
||||
if (filters.projectLicense && filters.projectLicense !== 'any')
|
||||
filter.license = filters.projectLicense
|
||||
|
||||
if (Object.keys(filter).length === 0)
|
||||
return null
|
||||
|
||||
return filter;
|
||||
}, [filters])
|
||||
}, [filters, selectedCategory?.id])
|
||||
|
||||
const { data, networkStatus, error } = useExplorePageQuery({
|
||||
variables: {
|
||||
@@ -55,11 +71,12 @@ export default function ExplorePage() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const onFiltersUpdated = useCallback(({ payload }: typeof UPDATE_FILTERS_ACTION) => {
|
||||
setSelectedCategory(null)
|
||||
setFilters(payload);
|
||||
if (Object.keys(payload).length === 0)
|
||||
setFilters(null);
|
||||
else
|
||||
setFilters(payload);
|
||||
}, [])
|
||||
|
||||
useReduxEffect(onFiltersUpdated, UPDATE_FILTERS_ACTION.type)
|
||||
@@ -83,13 +100,8 @@ export default function ExplorePage() {
|
||||
}))
|
||||
}
|
||||
|
||||
const selectCategoryTab = (category?: Category | null) => {
|
||||
if (!category?.id)
|
||||
return;
|
||||
const selectCategoryTab = (category: Category | null) => {
|
||||
setSelectedCategory(category);
|
||||
setFilters({
|
||||
categoriesIds: [category.id]
|
||||
})
|
||||
}
|
||||
|
||||
if (error) {
|
||||
@@ -98,7 +110,6 @@ export default function ExplorePage() {
|
||||
</div>
|
||||
}
|
||||
|
||||
console.log(networkStatus, NetworkStatus.loading, NetworkStatus.refetch, NetworkStatus.setVariables);
|
||||
|
||||
const isLoading = networkStatus === NetworkStatus.loading || networkStatus === NetworkStatus.refetch || networkStatus === NetworkStatus.setVariables;
|
||||
|
||||
@@ -115,7 +126,14 @@ export default function ExplorePage() {
|
||||
/>
|
||||
<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>
|
||||
<Button
|
||||
className={`self-center ${!!queryFilters ? "!font-bold !bg-primary-50 !text-primary-600 !border-2 !border-primary-400" : "!text-gray-600"}`}
|
||||
variant='outline'
|
||||
color='white'
|
||||
onClick={openFilters}>
|
||||
<FiSliders className="scale-150 mr-12" />
|
||||
<span className='align-middle'>Filters</span>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-40">
|
||||
<ProjectsGrid
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
import React, { FormEvent, useState } from 'react'
|
||||
import { 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';
|
||||
@@ -29,10 +25,11 @@ export interface IFormInputs {
|
||||
export type ProjectsFilters = {
|
||||
categoriesIds: string[]
|
||||
tagsIds: string[]
|
||||
yearFounded: string
|
||||
yearFounded: typeof yearsFoundedOptions[number]['value'],
|
||||
projectStatus: typeof projectStatusOptions[number]['value']
|
||||
projectLicense: typeof licensesOptions[number]['value']
|
||||
}
|
||||
|
||||
const yearsFounded = ['Any', '2016', '2017', '2018', '2019', '2020', '2021', '2022']
|
||||
|
||||
export default function FiltersModal({ onClose, direction, initFilters, callbackAction, ...props }: Props) {
|
||||
|
||||
@@ -41,13 +38,15 @@ export default function FiltersModal({ onClose, direction, initFilters, callback
|
||||
|
||||
const [categoriesFilter, setCategoriesFilter] = useState<string[]>(initFilters?.categoriesIds ?? []);
|
||||
const [tagsFilter, setTagsFilter] = useState<string[]>(initFilters?.tagsIds ?? []);
|
||||
const [yearFoundedFilter, setYearFoundedFilter] = useState(initFilters?.yearFounded ?? yearsFounded[0]);
|
||||
const [yearFoundedFilter, setYearFoundedFilter] = useState(initFilters?.yearFounded ?? "any");
|
||||
const [projectStatusFilter, setProjectStatusFilter] = useState(initFilters?.projectStatus ?? "any");
|
||||
const [projectLicenseFilter, setProjectLicenseFilter] = useState(initFilters?.projectLicense ?? "any");
|
||||
|
||||
const clickCategory = (id: string) => {
|
||||
if (categoriesFilter.includes(id))
|
||||
setCategoriesFilter(categoriesFilter.filter(v => v !== id));
|
||||
setCategoriesFilter([]);
|
||||
else
|
||||
setCategoriesFilter([...categoriesFilter, id]);
|
||||
setCategoriesFilter([id]);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,16 +57,30 @@ export default function FiltersModal({ onClose, direction, initFilters, callback
|
||||
setTagsFilter([...tagsFilter, id]);
|
||||
}
|
||||
|
||||
const clearFilters = () => {
|
||||
setCategoriesFilter([]);
|
||||
setTagsFilter([]);
|
||||
setYearFoundedFilter(yearsFounded[0]);
|
||||
const createActionPayload = (filters: Partial<ProjectsFilters>) => {
|
||||
const action = Object.assign({}, callbackAction);
|
||||
let payload: any = {};
|
||||
for (const [key, value] of Object.entries(filters)) {
|
||||
if (filters[(key as keyof typeof filters)] != null) payload[key] = value;
|
||||
}
|
||||
action.payload = payload;
|
||||
return action
|
||||
}
|
||||
|
||||
const applyFilters = () => {
|
||||
const action = Object.assign({}, callbackAction);
|
||||
action.payload = { categoriesIds: categoriesFilter, tagsIds: tagsFilter, yearFounded: yearFoundedFilter }
|
||||
dispatch(action)
|
||||
dispatch(createActionPayload({
|
||||
categoriesIds: categoriesFilter,
|
||||
tagsIds: tagsFilter,
|
||||
yearFounded: yearFoundedFilter,
|
||||
projectStatus: projectStatusFilter,
|
||||
projectLicense: projectLicenseFilter
|
||||
}))
|
||||
onClose?.();
|
||||
}
|
||||
|
||||
|
||||
const clearFilters = () => {
|
||||
dispatch(dispatch(createActionPayload({ categoriesIds: [], tagsIds: [], yearFounded: 'any', projectStatus: 'any', projectLicense: "any" })))
|
||||
onClose?.();
|
||||
}
|
||||
|
||||
@@ -155,20 +168,57 @@ export default function FiltersModal({ onClose, direction, initFilters, callback
|
||||
<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'>
|
||||
<div className="flex flex-wrap gap-x-48 gap-y-24 mt-24">
|
||||
{yearsFoundedOptions.map(year =>
|
||||
<label key={year.text} className='flex gap-16 items-center'>
|
||||
<input
|
||||
name='yearFounded'
|
||||
value={year}
|
||||
checked={year === yearFoundedFilter}
|
||||
value={year.value}
|
||||
checked={year.value === yearFoundedFilter}
|
||||
className='input-radio self-center'
|
||||
onChange={e => setYearFoundedFilter(e.target.value)}
|
||||
onChange={e => setYearFoundedFilter(e.target.value as typeof year.value)}
|
||||
type="radio" />
|
||||
<label className="text-body4 text-gray-800" >
|
||||
{year}
|
||||
</label>
|
||||
</div>)}
|
||||
<span className="text-body4 text-gray-800">{year.text}</span>
|
||||
</label>)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr className="bg-gray-100" />
|
||||
<div>
|
||||
<h3 className="text-body2 font-bolder">💙 Project status</h3>
|
||||
<p className='text-gray-600 mt-8'>Select an option from below.</p>
|
||||
<div className="flex flex-wrap gap-x-48 gap-y-24 mt-24">
|
||||
{projectStatusOptions.map(status =>
|
||||
<label key={status.text} className='flex gap-16 items-center'>
|
||||
<input
|
||||
name='projectStatus'
|
||||
value={status.value}
|
||||
checked={status.value === projectStatusFilter}
|
||||
className='input-radio self-center'
|
||||
onChange={e => setProjectStatusFilter(e.target.value as typeof status.value)}
|
||||
type="radio" />
|
||||
<span className="text-body4 text-gray-800">{status.text}</span>
|
||||
</label>)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<hr className="bg-gray-100" />
|
||||
<div>
|
||||
<h3 className="text-body2 font-bolder">💻 License type</h3>
|
||||
<p className='text-gray-600 mt-8'>What type of license does this open source project have?</p>
|
||||
<div className="flex flex-wrap gap-16 mt-24">
|
||||
{licensesOptions.map(license =>
|
||||
<button
|
||||
key={license.value}
|
||||
className={`
|
||||
px-12 py-8 border rounded-10 text-body5 font-medium
|
||||
active:scale-95 transition-transform
|
||||
${projectLicenseFilter !== license.value ? "bg-gray-100 hover:bg-gray-200 border-gray-200" : "bg-primary-100 text-primary-600 border-primary-200"}
|
||||
`}
|
||||
onClick={() => setProjectLicenseFilter(license.value)}
|
||||
>{license.text}
|
||||
</button>)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -184,3 +234,34 @@ export default function FiltersModal({ onClose, direction, initFilters, callback
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
const yearsFoundedOptions = [
|
||||
{ value: "any", text: "Any" },
|
||||
{ value: "2016", text: "2016" },
|
||||
{ value: "2017", text: "2017" },
|
||||
{ value: "2018", text: "2018" },
|
||||
{ value: "2019", text: "2019" },
|
||||
{ value: "2020", text: "2020" },
|
||||
{ value: "2021", text: "2021" },
|
||||
{ value: "2022", text: "2022" },
|
||||
] as const
|
||||
|
||||
const projectStatusOptions = [
|
||||
{ value: "any", text: "Any" },
|
||||
{ value: 'alive', text: "Alive 🌱" },
|
||||
{ value: 'dead', text: "RIP 💀" },
|
||||
] as const
|
||||
|
||||
const licensesOptions = [
|
||||
{ value: "any", text: "Any" },
|
||||
{ value: 'MIT License', text: "MIT License" },
|
||||
{ value: 'ISC License', text: "ISC License" },
|
||||
{ value: 'Public domain', text: "Public domain" },
|
||||
{ value: 'Apache License 2.0', text: "Apache License 2.0" },
|
||||
{ value: 'GNU General Public License v2.0', text: "GNU General Public License v2.0" },
|
||||
{ value: 'GNU General Public License v3.0', text: "GNU General Public License v3.0" },
|
||||
{ value: 'Creative Commons Zero v1.0 Universal', text: "Creative Commons Zero v1.0 Universal" },
|
||||
{ value: 'GNU Affero General Public License v3.0', text: "GNU Affero General Public License v3.0" },
|
||||
{ value: 'Other', text: "Other" },
|
||||
] as const
|
||||
@@ -1,5 +1,5 @@
|
||||
query ProjectDetails($projectsId: String) {
|
||||
projects(id: $projectsId) {
|
||||
getProject: projects(id: $projectsId) {
|
||||
id
|
||||
title
|
||||
dead
|
||||
|
||||
@@ -42,12 +42,14 @@ export default function ProjectDetailsCard({ direction, projectId, ...props }: P
|
||||
projectsId: projectId!,
|
||||
},
|
||||
onCompleted: data => {
|
||||
dispatch(setProject((data.projects?.[0] as any) ?? null))
|
||||
dispatch(setProject((data.getProject?.[0] as any) ?? null))
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(setProject(null));
|
||||
},
|
||||
skip: !Boolean(projectId)
|
||||
skip: !Boolean(projectId),
|
||||
fetchPolicy: "no-cache"
|
||||
|
||||
});
|
||||
|
||||
|
||||
@@ -72,7 +74,7 @@ export default function ProjectDetailsCard({ direction, projectId, ...props }: P
|
||||
return <ProjectCardSkeleton onClose={closeModal} direction={direction} isPageModal={props.isPageModal} />;
|
||||
|
||||
|
||||
const project = data?.projects?.[0];
|
||||
const project = data?.getProject?.[0];
|
||||
|
||||
if (!project) return <p>404</p>
|
||||
|
||||
@@ -126,8 +128,8 @@ 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 object-cover" src={project?.logo?.[0]['thumbnails']['large'].url} alt="" />
|
||||
<div className="flex-shrink-0 w-[108px] h-[108px] border-2 border-gray-200 rounded-24 overflow-hidden ">
|
||||
<img className="w-full h-full 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>
|
||||
@@ -173,26 +175,23 @@ export default function ProjectDetailsCard({ direction, projectId, ...props }: P
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className="text-body6 uppercase font-medium text-gray-400 mb-8">DATA</p>
|
||||
<div className="flex flex-wrap gap-8">
|
||||
{project?.dead && <Badge size='sm'>{project.dead}</Badge>}
|
||||
{project?.createdAt && <Badge size='sm'>{project.createdAt}</Badge>}
|
||||
{project?.companyName && <Badge size='sm'>{project.companyName}</Badge>}
|
||||
{project?.endDate && <Badge size='sm'>{project.endDate}</Badge>}
|
||||
{project?.updatedAt && <Badge size='sm'>{project.updatedAt}</Badge>}
|
||||
{project?.watchers && <Badge size='sm'>{project.watchers}</Badge>}
|
||||
{project?.yearFounded && <Badge size='sm'>{project.yearFounded}</Badge>}
|
||||
{project?.subcategory && <Badge size='sm'>{project.subcategory}</Badge>}
|
||||
{project?.stars && <Badge size='sm'>{project.stars}</Badge>}
|
||||
{project?.repository && <Badge size='sm'>{project.repository}</Badge>}
|
||||
{project?.openSource && <Badge size='sm'>{project.openSource}</Badge>}
|
||||
{project?.linkedIn && <Badge size='sm'>{project.linkedIn}</Badge>}
|
||||
{project?.license && <Badge size='sm'>{project.license}</Badge>}
|
||||
{project?.language && <Badge size='sm'>{project.language}</Badge>}
|
||||
{project?.forks && <Badge size='sm'>{project.forks}</Badge>}
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-body6 uppercase font-medium text-gray-400 mb-8">DATA</p>
|
||||
<div className="flex flex-wrap gap-8">
|
||||
{project?.dead !== null && <Badge color='none' className='bg-red-100' size='sm'>Dead</Badge>}
|
||||
{project?.createdAt !== null && <Badge size='sm'>Created at: {new Date(project.createdAt).toLocaleDateString()}</Badge>}
|
||||
{project?.companyName !== null && <Badge size='sm'>Company Name: {project.companyName}</Badge>}
|
||||
{project?.endDate !== null && <Badge size='sm'>End date: {new Date(project.endDate).toLocaleDateString()}</Badge>}
|
||||
{project?.repository !== null && <Badge size='sm'><a href={project.repository} target='_blank' className='text-blue-500' rel="noreferrer">Repository</a> </Badge>}
|
||||
{project?.stars !== null && <Badge size='sm'>Stars: {project.stars}</Badge>}
|
||||
{project?.openSource !== null && <Badge size='sm'>Open source: {project.openSource}</Badge>}
|
||||
{project?.watchers !== null && <Badge size='sm'>Watchers: {project.watchers}</Badge>}
|
||||
{project?.forks !== null && <Badge size='sm'>Number of forks: {project.forks}</Badge>}
|
||||
{project?.license !== null && <Badge size='sm'>License: {project.license}</Badge>}
|
||||
{project?.language !== null && <Badge size='sm'>Language: {project.language}</Badge>}
|
||||
{project?.updatedAt !== null && <Badge size='sm'>Last updated at:{new Date(project.updatedAt).toLocaleDateString()}</Badge>}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-center">
|
||||
<h3 className="text-body4 font-regular">Want to suggest any changes to this project?</h3>
|
||||
|
||||
@@ -425,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, 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 type ProjectDetailsQuery = { __typename?: 'Query', getProject: 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`
|
||||
@@ -570,7 +570,7 @@ export type ExplorePageLazyQueryHookResult = ReturnType<typeof useExplorePageLaz
|
||||
export type ExplorePageQueryResult = Apollo.QueryResult<ExplorePageQuery, ExplorePageQueryVariables>;
|
||||
export const ProjectDetailsDocument = gql`
|
||||
query ProjectDetails($projectsId: String) {
|
||||
projects(id: $projectsId) {
|
||||
getProject: projects(id: $projectsId) {
|
||||
id
|
||||
title
|
||||
dead
|
||||
|
||||
Reference in New Issue
Block a user