11<script setup>
2- import { computed , ref } from ' vue' ;
2+ import { computed , ref , nextTick } from ' vue' ;
33import BaseListCard from ' ./BaseListCard.vue' ;
44import { makeFilterButtonHTML } from ' ../utils/make-filter-button-html' ;
55import { makeMapButtonHTML } from ' ../utils/make-map-button-html' ;
6+ import BaseFilters from ' ./BaseFilters.vue' ;
67
78const props = defineProps ({
89 datasets: {
@@ -29,7 +30,7 @@ const filteredLocations = computed(() => {
2930 })));
3031});
3132
32- const emits = defineEmits ([' toggleView' ]);
33+ const emits = defineEmits ([' toggleView' , ' datasetChange ' ]);
3334
3435const showFilters = ref (false );
3536
@@ -44,36 +45,116 @@ const toggleView = () => {
4445const filterButtonHTML = computed (() => makeFilterButtonHTML (' Filter' , props .primaryColor ));
4546const mapButtonHTML = computed (() => makeMapButtonHTML (' Kaart' , props .primaryColor ));
4647
47- // @TODO: Implement the actual filtering logic here
48- // ...
48+ const handleDatasetChange = (id , checked ) => {
49+ emits (' datasetChange' , id, checked);
50+ };
51+
52+ const closeFilters = () => {
53+ showFilters .value = false ;
54+ };
55+
56+ const ITEMS_PER_PAGE = 12 ;
57+ const displayLimit = ref (ITEMS_PER_PAGE );
58+ const listItemRefs = ref ([]);
59+
60+ const paginatedLocations = computed (() => {
61+ return filteredLocations .value .slice (0 , displayLimit .value );
62+ });
63+
64+ const hasMoreItems = computed (() => {
65+ return displayLimit .value < filteredLocations .value .length ;
66+ });
67+
68+ const loadMore = () => {
69+ const newLimit = displayLimit .value + ITEMS_PER_PAGE ;
70+ displayLimit .value = Math .min (newLimit, filteredLocations .value .length );
71+
72+ nextTick (() => {
73+ const newItemIndex = displayLimit .value - ITEMS_PER_PAGE ;
74+ const newItemRef = listItemRefs .value [newItemIndex];
75+ if (newItemRef) {
76+ newItemRef .focus ();
77+ }
78+ });
79+ };
4980 </script >
5081
5182<template >
52- <div class =" list-view" >
83+ <div
84+ class =" list-view"
85+ :style =" {
86+ '--owc-filters-primary': primaryColor,
87+ '--owc-openkaarten-streetmap--primary-color': primaryColor,
88+ '--owc-filters-secondary': '#d2d2d2'
89+ }"
90+ >
5391 <div class =" list-view__controls" >
5492 <button @click =" toggleView" class =" list-view__map-button" v-html =" mapButtonHTML" ></button >
5593 <button @click =" toggleFilters" class =" list-view__filters-button" v-html =" filterButtonHTML" ></button >
5694 </div >
57- <div v-for =" location in filteredLocations" :key =" `${location.datasetId}-${location.properties.id}`" class =" list-view__item" >
58- <BaseListCard
59- :title =" location.properties.title || location.datasetTitle"
60- :address =" location.properties.address || 'Zorg | Beatrixlaan 32 C, 3273 AB Westmaas'"
61- :description =" location.properties.description || 'Huisartsenpraktijk Westmaas B.V. ligt in het gelijknamige dorp in de regio Hoeksche Waard. Westmaas telt circa 2.065 inwoners en levert huisartsenzorg aan 2.380 patiënten.'"
62- :image =" location.properties.image || 'https://images.unsplash.com/photo-1494526585095-c41746248156?q=80&w=1740&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'"
95+
96+ <!-- Add fade transition for overlay -->
97+ <Transition name =" fade" >
98+ <div
99+ v-if =" showFilters"
100+ class =" owc-openkaarten-streetmap__overlay"
101+ ></div >
102+ </Transition >
103+
104+ <!-- Add slide transition for filters -->
105+ <Transition name =" slide" >
106+ <BaseFilters
107+ v-if =" showFilters"
108+ :open =" showFilters"
109+ :datasets =" datasets.filter((set) => set.features.length)"
110+ :selectedDatasets =" selectedDatasets"
63111 :primaryColor =" primaryColor"
112+ @closeFilters =" closeFilters"
113+ @datasetChange =" handleDatasetChange"
114+ />
115+ </Transition >
116+
117+ <div class =" list-view__results" >
118+ <div
119+ v-for =" (location, index) in paginatedLocations"
120+ :key =" `${location.datasetId}-${location.properties.id}`"
121+ class =" list-view__item"
122+ :ref =" el => { listItemRefs[index] = el }"
123+ tabindex =" 0"
64124 >
65- <template #footer >
66- </template >
67- </BaseListCard >
125+ <BaseListCard
126+ :title =" location.properties.title || location.datasetTitle"
127+ :address =" location.properties.address || 'Zorg | Beatrixlaan 32 C, 3273 AB Westmaas'"
128+ :description =" location.properties.description || 'Huisartsenpraktijk Westmaas B.V. ligt in het gelijknamige dorp in de regio Hoeksche Waard. Westmaas telt circa 2.065 inwoners en levert huisartsenzorg aan 2.380 patiënten.'"
129+ :image =" location.properties.image || 'https://images.unsplash.com/photo-1494526585095-c41746248156?q=80&w=1740&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D'"
130+ :primaryColor =" primaryColor"
131+ >
132+ <template #footer >
133+ </template >
134+ </BaseListCard >
135+ </div >
136+
137+ <!-- Add Load More button -->
138+ <button
139+ v-if =" hasMoreItems"
140+ @click =" loadMore"
141+ class =" list-view__load-more"
142+ :style =" { '--button-color': primaryColor }"
143+ >
144+ Toon meer resultaten ({{ paginatedLocations.length }} van {{ filteredLocations.length }})
145+ </button >
68146 </div >
69147 </div >
70148</template >
71149
72- <style lang="scss" scoped >
150+ <style lang="scss">
73151.list-view {
74152 display : flex ;
75153 flex-direction : column ;
76154 gap : 1rem ;
155+ min-block-size : 660px ;
156+ position : relative ;
157+ overflow : hidden ;
77158
78159 & __controls {
79160 display : flex ;
@@ -93,13 +174,12 @@ const mapButtonHTML = computed(() => makeMapButtonHTML('Kaart', props.primaryCol
93174 min-height : 50px ;
94175 padding : 10px 24px ;
95176
96- // @TODO: styles are not being applied, why?
97177 span {
98178 color : #328725 ;
99179 font-size : 20px ;
100180 font-style : normal ;
101181 font-weight : 500 ;
102- line-height : 130% ;
182+ line-height : 130% ;
103183 }
104184
105185 & :hover {
@@ -113,10 +193,74 @@ const mapButtonHTML = computed(() => makeMapButtonHTML('Kaart', props.primaryCol
113193 }
114194 }
115195
196+ & __results {
197+ display : flex ;
198+ flex-direction : column ;
199+ gap : 1rem ;
200+ }
201+
116202 & __item {
117203 display : flex ;
118204 flex-direction : column ;
119205 gap : 1rem ;
206+
207+ & :focus {
208+ outline : 2px solid var (--owc-openkaarten-streetmap--primary-color );
209+ outline-offset : 4px ;
210+ }
211+ }
212+
213+ & __load-more {
214+ margin-top : 1rem ;
215+ padding : 1rem 2rem ;
216+ background-color : white ;
217+ border : 2px solid var (--button-color );
218+ color : var (--button-color );
219+ border-radius : 4px ;
220+ font-weight : 500 ;
221+ cursor : pointer ;
222+ transition : background-color 0.2s ease ;
223+
224+ & :hover {
225+ background-color : rgb (244 , 244 , 244 );
226+ }
227+
228+ & :focus-visible {
229+ outline : 2px solid var (--button-color );
230+ outline-offset : 2px ;
231+ }
120232 }
121233}
234+
235+ .fade-enter-active ,
236+ .fade-leave-active {
237+ transition : opacity 0.5s ease-in-out ;
238+ }
239+
240+ .fade-enter-from ,
241+ .fade-leave-to {
242+ opacity : 0 ;
243+ }
244+
245+ .slide-enter-active ,
246+ .slide-leave-active {
247+ transform : translateX (0 );
248+ transition : transform 0.5s ease-in-out ;
249+ }
250+
251+ .slide-enter-from ,
252+ .slide-leave-to {
253+ transform : translateX (120% );
254+ }
255+
256+ .owc-openkaarten-streetmap__overlay {
257+ background-color : var (--owc-map-overlay , rgba (0 , 0 , 0 , 0.25 ));
258+ position : absolute ;
259+ content : ' ' ;
260+ top : 0 ;
261+ left : 0 ;
262+ width : 100% ;
263+ height : 100% ;
264+ z-index : 999 ;
265+ }
122266 </style >
0 commit comments