Skip to content

Commit 0e8a0c5

Browse files
committed
Adding filter for projects view
Changes: - Adding new MenuTagsProjects component to hnadle menu tags - Adding new utilities file to handle common methods - Adding new methods on projects component to filter and show the projects - Getting array tags from projects
1 parent b98be79 commit 0e8a0c5

File tree

4 files changed

+107
-15
lines changed

4 files changed

+107
-15
lines changed

src/components/MenuTagsProject.svelte

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<script>
2+
export let tags;
3+
export let addToFilter;
4+
export let removeFromFilter;
5+
let tagsToShow = [...tags.map((tag = '') => ({ isActive: false, text: tag }))];
6+
7+
const handleAdd = (tag = '', index = 0) => {
8+
tagsToShow[index] = {...tagsToShow[index], isActive: true};
9+
addToFilter(tag);
10+
}
11+
12+
const handleDelete = (e = event, tag = '', index = 0) => {
13+
e?.stopPropagation();
14+
tagsToShow[index] = {...tagsToShow[index], isActive: false};
15+
removeFromFilter(tag);
16+
}
17+
</script>
18+
19+
{#each tagsToShow as tag, tagInd}
20+
<a
21+
href={null}
22+
class={`flex rounded-full px-3 py-1 text-xs${tag.isActive ? ' active' : ''}`}
23+
on:click={() => handleAdd(tag.text, tagInd)}
24+
>
25+
{tag.text.charAt(0).toUpperCase() + tag.text.slice(1)}
26+
{#if (tag.isActive)}
27+
<button
28+
class="flex justify-center items-center w-4 h-4 rounded-full ml-2 text-cmxblack bg-gray-100"
29+
on:click={(e) => handleDelete(e, tag.text, tagInd)}
30+
>
31+
<svg class="h-3 w-3" fill="none" viewBox="0 0 24 24" stroke-width="4" stroke="currentColor" aria-hidden="true">
32+
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
33+
</svg>
34+
</button>
35+
{/if}
36+
</a>
37+
{/each}
38+
39+
<!-- To avoid increase a lot the anchor's classes -->
40+
<style>
41+
a {
42+
color: #030304;
43+
background-color: #f3f3f4;
44+
}
45+
a:hover {
46+
cursor: pointer;
47+
filter: brightness(0.95);
48+
}
49+
a.active {
50+
color: #f3f3f4;
51+
background-color: #030304;
52+
}
53+
</style>

src/lib/utilities.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const interfaceElement = [
2+
{ tags: [''] }
3+
];
4+
5+
export function getFlatArrayUnrepeated(elements = interfaceElement) {
6+
let unrepeated = [];
7+
const setToLowerCase = (item = '') => item.toLowerCase();
8+
9+
elements.forEach(item => {
10+
unrepeated = [...new Set([...unrepeated, ...new Set(item?.tags?.map(setToLowerCase))])]
11+
})
12+
13+
return unrepeated;
14+
}

src/routes/proyectos/+page.server.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import client from '$lib/apiClient'
2+
import { getFlatArrayUnrepeated } from '$lib/utilities';
23
import { readItems } from '@directus/sdk'
34

45
export async function load() {
@@ -11,8 +12,11 @@ export async function load() {
1112
}
1213
}))
1314

15+
const tags = getFlatArrayUnrepeated(projects);
16+
1417
return {
15-
projects
18+
projects,
19+
tags
1620
}
1721
}
1822

src/routes/proyectos/+page.svelte

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,37 @@
22
import Hero from '@/components/Hero.svelte';
33
import IconTextAction from '@/components/IconTextAction.svelte';
44
import SubscribeBox from '@/components/SubscribeBox.svelte';
5-
import Badge from '@/components/Badge.svelte';
65
import ProjectCard from '@/components/Cards/ProjectCard.svelte';
7-
export let data
8-
const { projects } = data
6+
import MenuTagsProject from '@/components/MenuTagsProject.svelte';
7+
export let data;
8+
const { projects, tags } = data;
9+
let activeTags = [];
10+
let filteredProjects = [...projects];
11+
12+
const getFilteredProjects = () => {
13+
const setToLowerCase = (item = '') => item?.toLowerCase();
14+
const areTagsIncluded = (item = '') => activeTags?.includes(item);
15+
16+
filteredProjects = Boolean(activeTags?.length)
17+
? projects.filter(project => project.tags?.map(setToLowerCase).some(areTagsIncluded))
18+
: [...projects];
19+
}
20+
21+
const addToFilter = (tag = '') => {
22+
if (activeTags.includes(tag)) {
23+
return false;
24+
}
25+
26+
tag = tag.toLowerCase();
27+
activeTags.push(tag);
28+
getFilteredProjects();
29+
}
30+
31+
const removeFromFilter = (tag = '') => {
32+
tag = tag.toLowerCase();
33+
activeTags = activeTags.filter(val => val !== tag);
34+
getFilteredProjects();
35+
}
936
</script>
1037
1138
<Hero title="Proyectos" subtitle="Colaboramos desde el diseño hasta la implementación de tecnología cívica." image="/proyectos.png"/>
@@ -27,17 +54,11 @@
2754
2855
<section id="nuestros-proyectos" class="container mx-auto my-12 p-3">
2956
<h1 class="text-4xl font-bold my-3">Conoce nuestros proyectos</h1>
30-
<!-- TODO: Habilitar Badges -->
31-
<!-- <div class="flex gap-4 my-6 flex-wrap">
32-
<Badge text="Movilidad" color="#F3F3F4"/>
33-
<Badge text="Educación" color="#F2D301"/>
34-
<Badge text="Legislativo" color="#F3F3F4"/>
35-
<Badge text="Datos abiertos" color="#F3F3F4"/>
36-
<Badge text="Código abierto" color="#F3F3F4"/>
37-
</div> -->
38-
<!-- <div class="flex flex-col basis-1/3 md:flex-row columns-3 container my-8 mx-auto gap-20"> -->
39-
<div class="grid grid-cols-1 md:grid-cols-3 container my-8 mx-auto gap-20">
40-
{#each projects as project}
57+
<div class="flex gap-4 my-6 flex-wrap">
58+
<MenuTagsProject tags={tags} addToFilter={addToFilter} removeFromFilter={removeFromFilter} />
59+
</div>
60+
<div class="grid grid-cols-1 md:grid-cols-3 container my-8 mx-auto gap-20">
61+
{#each filteredProjects as project}
4162
<div class="my-5">
4263
<ProjectCard
4364
title={project.title}

0 commit comments

Comments
 (0)