Skip to content
Snippets Groups Projects
Commit b7b6fd34 authored by Mark Kane's avatar Mark Kane
Browse files

planning#401: implement filter logic

parent 8376d2ea
No related branches found
No related tags found
1 merge request!7planning#401: add resource filters
......@@ -22,6 +22,7 @@ export type ServiceType = {
contactInformation: object
status: string
documentationURL: string
tags?: any[]
sourcecodeURL?: string
tosURL?: string
description: object
......
import React, { useEffect, useState } from "react";
import { useRouter } from 'next/router'
import Link from 'next/link'
import { fetchServices } from '@/lib/contentful'
import { fetchServices, ServiceType } from '@/lib/contentful'
import { documentToHtmlString } from '@contentful/rich-text-html-renderer'
import { IconArrowBigRight, IconSearch } from '@tabler/icons'
export default function ({ services }) {
const router = useRouter()
const filters = [
{
label: 'Art des Dienstes',
......@@ -12,62 +14,19 @@ export default function ({ services }) {
options: [{
label: 'Plattformen',
id: 'platform',
value: 'platform',
},{
label: 'Basisdienste',
id: '',
value: '',
id: 'base',
value: 'base',
},{
label: 'Software',
id: '',
value: '',
id: 'software',
value: 'software',
},{
label: 'APIs',
id: '',
value: '',
}]
},
{
label: 'Use Cases',
id: 'use-case',
options: [{
label: 'Bezahlsystem',
id: 'platform',
},{
label: 'Übertragungssystem',
id: '',
value: '',
},{
label: 'Referenzarchitektur',
id: '',
value: '',
}]
},
{
label: 'Region',
id: 'region',
options: [{
label: 'Niedersachsen',
id: 'platform',
},{
label: 'Baden-Württemberg',
id: '',
value: '',
},{
label: 'Bayern',
id: '',
value: '',
},{
label: 'Thüringen',
id: '',
value: '',
},{
label: 'Hessen',
id: '',
value: '',
},{
label: 'Nordrhein-Westfalen',
id: '',
value: '',
id: 'api',
value: 'api',
}]
},
{
......@@ -76,19 +35,95 @@ export default function ({ services }) {
options: [{
label: 'Produktiv',
id: 'production',
value: 'production',
},{
label: 'Beta',
id: '',
value: '',
id: 'beta',
value: 'beta',
},{
label: 'In Entwicklung',
id: '',
value: '',
id: 'development',
value: 'development',
}]
}
]
const defaultFilters: any = {
type: [],
status: [],
}
const [activeFilters, setActiveFilters] = useState(defaultFilters)
const [filteredServices, setFilteredServices] = useState(services)
useEffect(() => {
// filter param change, update filter and filter servicves
if (router.query.filter) {
setActiveFilters(paramsToFilter(router.query.filter))
} else {
setActiveFilters(defaultFilters)
}
setFilteredServices(filterServices())
}, [router.query.filter])
function filterToParams() {
const res = []
Object.keys(activeFilters).forEach(f => {
if (activeFilters[f].length > 0) {
activeFilters[f].forEach(i => res.push(i))
}
})
return [...new Set(res)].join('&')
}
function paramsToFilter(str) {
if (!str) return defaultFilters
const filters = str.split('&')
filters.forEach(f => {
const filter = f.split(':')[0]
if (activeFilters[filter].indexOf(f) < 0) {
activeFilters[filter].push(f)
}
})
return activeFilters
}
function filterServices() {
return services.filter((s: ServiceType) => {
const tags: string[] = s.tags ? s.tags.map(o => o.fields.name) : []
const groups: any = {}
let match = true
tags.forEach(tag => {
const t = tag.split(':')
if (!groups[t[0]]) groups[t[0]] = []
groups[t[0]].push(tag)
})
Object.keys(activeFilters).forEach(f => {
if (activeFilters[f].length > 0) {
if (activeFilters[f].length === 0) return
if (!groups[f]) return match = false
groups[f].forEach(item => {
if (item.startsWith(f + ':') && !activeFilters[f].includes(item)) {
match = false
}
})
}
})
return match
})
}
function handleFilters(event) {
const filter = event.target.id.split('-')[0]
if (event.target.checked) {
activeFilters[filter].push(event.target.value)
} else if (activeFilters[filter].indexOf(event.target.value) >= 0) {
activeFilters[filter].splice(activeFilters[filter].indexOf(event.target.value), 1)
}
// we always track filters in query params, param change will trigger filtering
router.push(`?filter=${encodeURIComponent(filterToParams())}`, undefined, { shallow: true })
}
return (
<div className="py-10">
......@@ -100,11 +135,11 @@ export default function ({ services }) {
>
<h1>
<span className="mt-1 block text-4xl tracking-tight font-extrabold sm:text-5xl xl:text-7xl">
<span className="block text-gray-900">Verfügbare Plattformen & Basisdienste</span>
<span className="block text-gray-900">Verfügbare Plattformen &amp; Basisdienste</span>
</span>
</h1>
</header>
<div className="hidden lg:block lg:col-span-3 xl:col-span-2">
<form name="filters" className="hidden lg:block lg:col-span-3 xl:col-span-2">
<nav
aria-label="Sidebar"
className="sticky top-4 divide-y divide-gray-300"
......@@ -122,27 +157,29 @@ export default function ({ services }) {
aria-labelledby={`${filter.id}-headline`}
>
{filter.options.map((option) => (
<div key={option.value} className="flex items-center">
<input
id={`${filter.id}-${option.id}`}
name={`${filter.id}[]`}
defaultValue={option.value}
type="checkbox"
className="h-4 w-4 border-gray-300 rounded text-indigo-600 focus:ring-indigo-500"
/>
<label
htmlFor={`${filter.id}-${option.id}`}
className="ml-3 text-sm text-gray-500"
>
{option.label}
</label>
</div>
<div key={option.value} className="flex items-center">
<input
onClick={handleFilters}
id={`${filter.id}-${option.id}`}
name={`${filter.id}[]`}
defaultValue={`${filter.id}:${option.id}`}
defaultChecked={router.query.filter ? router.query.filter.includes(`${filter.id}:${option.id}`) : false}
type="checkbox"
className="h-4 w-4 border-gray-300 rounded text-indigo-600 focus:ring-indigo-500"
/>
<label
htmlFor={`${filter.id}-${option.id}`}
className="ml-3 text-sm text-gray-500"
>
{option.label}
</label>
</div>
))}
</div>
</div>
))}
</nav>
</div>
</form>
<main className="lg:col-span-9 xl:col-span-9">
{/*
<div className="px-4 sm:px-0">
......@@ -171,9 +208,9 @@ export default function ({ services }) {
<div className="mt-4">
<h1 className="sr-only">Gelistete Services</h1>
<ul role="list" className="space-y-4">
{services.map((service, key) => (
{filteredServices.map((service, key) => (
<li
key={key}
key={service.slug}
className="bg-white px-4 py-6 shadow sm:p-6 sm:rounded-lg"
>
<div aria-labelledby={'service-' + key}>
......@@ -251,13 +288,3 @@ export async function getStaticProps(context) {
}
}
/*
<a
key={community.name}
href={community.href}
className="group flex items-center px-3 py-2 text-sm font-medium text-gray-600 rounded-md hover:text-gray-900 hover:bg-gray-50"
>
<span className="truncate">{community.name}</span>
</a>
*/
......@@ -4,6 +4,7 @@
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"downlevelIteration": true,
"strict": false,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment