mirror of
https://github.com/privacy-scaling-explorations/pse.dev.git
synced 2026-04-23 03:01:03 -04:00
projects library updates (#266)
This commit is contained in:
@@ -84,44 +84,6 @@ export const ThemesStatusMapping = (lang: LocaleTypes): IThemeStatus => {
|
||||
}
|
||||
}
|
||||
|
||||
const FilterButtons = ({
|
||||
searchQuery,
|
||||
lang,
|
||||
}: {
|
||||
lang: LocaleTypes
|
||||
searchQuery?: string
|
||||
}): JSX.Element => {
|
||||
const { activeFilters, onSelectTheme } = useProjectFiltersState(
|
||||
(state) => state
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="relative col-span-1 grid grid-cols-3 gap-2 after:absolute after:right-[-25px] after:h-11 after:w-[1px] after:content-none md:col-span-2 md:gap-4 md:after:content-['']">
|
||||
{Object.entries(ThemesButtonMapping(lang)).map(
|
||||
([key, { label, icon }]) => {
|
||||
const isActive = activeFilters?.themes?.includes(key)
|
||||
const variant = isActive ? "blue" : "white"
|
||||
return (
|
||||
<Button
|
||||
key={key}
|
||||
variant={variant}
|
||||
size="lg"
|
||||
onClick={() => {
|
||||
onSelectTheme(key, searchQuery ?? "")
|
||||
}}
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
{icon}
|
||||
<span>{label}</span>
|
||||
</div>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function ProjectFiltersBar({ lang }: LangProps["params"]) {
|
||||
const { t } = useTranslation(lang as LocaleTypes, "common")
|
||||
const [showModal, setShowModal] = useState(false)
|
||||
@@ -341,9 +303,12 @@ export default function ProjectFiltersBar({ lang }: LangProps["params"]) {
|
||||
<div className="grid items-center justify-between grid-cols-1 gap-3 md:grid-cols-5 md:gap-12">
|
||||
<div className="col-span-1 grid grid-cols-[1fr_auto] gap-2 md:col-span-3 md:gap-3">
|
||||
<Input
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) =>
|
||||
onChange={(e: ChangeEvent<HTMLInputElement>) => {
|
||||
setSearchQuery(e?.target?.value)
|
||||
}
|
||||
useProjectFiltersState.setState({
|
||||
searchQuery: e?.target?.value,
|
||||
})
|
||||
}}
|
||||
value={searchQuery}
|
||||
placeholder={t("searchProjectPlaceholder")}
|
||||
/>
|
||||
|
||||
@@ -51,7 +51,9 @@ export const ProjectList = ({ lang }: LangProps["params"]) => {
|
||||
const [isManualScroll, setIsManualScroll] = useState(false)
|
||||
const [isMounted, setIsMounted] = useState(false)
|
||||
|
||||
const { projects } = useProjectFiltersState((state) => state)
|
||||
const { projects, searchQuery, queryString } = useProjectFiltersState(
|
||||
(state) => state
|
||||
)
|
||||
|
||||
const noItems = projects?.length === 0
|
||||
|
||||
@@ -96,6 +98,8 @@ export const ProjectList = ({ lang }: LangProps["params"]) => {
|
||||
}
|
||||
}, [])
|
||||
|
||||
const hasActiveFilters = searchQuery !== "" || queryString !== ""
|
||||
|
||||
// loading state skeleton
|
||||
if (!isMounted) {
|
||||
return (
|
||||
@@ -126,6 +130,24 @@ export const ProjectList = ({ lang }: LangProps["params"]) => {
|
||||
return acc
|
||||
}, {} as Record<ProjectStatus, ProjectInterface[]>)
|
||||
|
||||
// show all projects without sections if there are active filters
|
||||
if (hasActiveFilters) {
|
||||
return (
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 md:gap-x-6 md:gap-y-10 lg:grid-cols-4">
|
||||
{projects.map((project) => (
|
||||
<ProjectCard
|
||||
key={project?.id}
|
||||
project={project}
|
||||
lang={lang}
|
||||
showBanner
|
||||
showLinks
|
||||
border
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative grid items-start justify-between grid-cols-1">
|
||||
<div className="flex flex-col">
|
||||
@@ -141,12 +163,14 @@ export const ProjectList = ({ lang }: LangProps["params"]) => {
|
||||
return (
|
||||
<div data-section={status} className="flex justify-between gap-10">
|
||||
<div className={cn("flex w-full flex-col gap-10 pt-10")}>
|
||||
<div className="flex flex-col gap-6 overflow-hidden">
|
||||
<h3 className={cn(sectionTitleClass())}>{status}</h3>
|
||||
<span className="font-sans text-base italic text-tuatara-950">
|
||||
{description}
|
||||
</span>
|
||||
</div>
|
||||
{!hasActiveFilters && (
|
||||
<div className="flex flex-col gap-6 overflow-hidden">
|
||||
<h3 className={cn(sectionTitleClass())}>{status}</h3>
|
||||
<span className="font-sans text-base italic text-tuatara-950">
|
||||
{description}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2 md:gap-x-6 md:gap-y-10 lg:grid-cols-4">
|
||||
{projects.map((project) => (
|
||||
<ProjectCard
|
||||
|
||||
@@ -16,7 +16,7 @@ export const ECIPHalo2: ProjectInterface = {
|
||||
id: "ecip-halo2",
|
||||
image: "",
|
||||
category: ProjectCategory.DEVTOOLS,
|
||||
projectStatus: ProjectStatus.MAINTAINED,
|
||||
projectStatus: ProjectStatus.ACTIVE,
|
||||
section: "pse",
|
||||
content,
|
||||
imageAlt: "ECIP + Halo 2",
|
||||
|
||||
@@ -55,6 +55,7 @@ interface ProjectStateProps {
|
||||
filters: FiltersProps
|
||||
activeFilters: Partial<FiltersProps>
|
||||
queryString: string
|
||||
searchQuery: string
|
||||
currentCategory: ProjectCategory | null
|
||||
}
|
||||
|
||||
@@ -211,6 +212,7 @@ export const useProjectFiltersState = create<
|
||||
sortBy: DEFAULT_PROJECT_SORT_BY,
|
||||
projects: sortProjectByFn(projects, DEFAULT_PROJECT_SORT_BY),
|
||||
queryString: "",
|
||||
searchQuery: "",
|
||||
filters: getProjectFilters(), // list of filters with all possible values from projects
|
||||
activeFilters: {}, // list of filters active in the current view by the user
|
||||
toggleFilter: ({ tag: filterKey, value, searchQuery }: toggleFilterProps) =>
|
||||
@@ -264,6 +266,7 @@ export const useProjectFiltersState = create<
|
||||
...state,
|
||||
activeFilters,
|
||||
projects: sortProjectByFn(filteredProjects, state.sortBy),
|
||||
searchQuery,
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user