Files
velo-park/src/components/BikeFilters.vue
2026-03-30 21:55:22 +02:00

150 lines
6.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script lang="ts" setup>
import { useMap } from '@/stores/map';
import { PhCheck, PhMinus, PhPlus } from '@phosphor-icons/vue';
import { storeToRefs } from 'pinia';
import { CheckboxIndicator, CheckboxRoot, NumberFieldDecrement, NumberFieldIncrement, NumberFieldInput, NumberFieldRoot, SliderRange, SliderRoot, SliderThumb, SliderTrack } from 'reka-ui'
import { ref, watch } from 'vue';
const { filterCovered, filterUncovered, filterKorrigo } = storeToRefs(useMap())
defineProps<{
nbUncovered?: number
nbCovered?: number
nbKorrigo?: number
}>()
const MIN = 0
const MAX = 100
const minSpots = ref(MIN)
const maxSpots = ref(MAX)
const spotsRange = ref([minSpots.value, maxSpots.value])
watch(spotsRange, ([newMin, newMax]) => {
if (newMin === undefined || newMax === undefined) return
minSpots.value = newMin
maxSpots.value = newMax
})
watch(minSpots, (val) => {
if (val !== spotsRange.value[0])
spotsRange.value = [Math.min(val, spotsRange.value[1]!), spotsRange.value[1]!]
})
watch(maxSpots, (val) => {
if (val !== spotsRange.value[1])
spotsRange.value = [spotsRange.value[0]!, Math.max(val, spotsRange.value[0]!)]
})
</script>
<template>
<aside class="max-w-xs absolute top-5 left-5 z-10 p-2 bg-slate-50 text-slate-950 text-xs rounded-xs">
<form>
<div class="grid grid-cols-2 gap-1.5">
<div class="col-span-2">
<label class="flex flex-row gap-1.5 items-center text-sm cursor-pointer">
<CheckboxRoot v-model="filterUncovered"
class="hover:bg-stone-100 flex size-4 appearance-none items-center justify-center rounded-xs bg-foreground shadow-sm border focus-within:ring-1 cursor-pointer">
<CheckboxIndicator class="size-full flex items-center justify-center bg-primary text-primary-foreground">
<PhCheck :size="10" weight="bold" />
</CheckboxIndicator>
</CheckboxRoot>
<span class="select-none">
Non-abrités
<small v-if="nbUncovered">({{ nbUncovered }})</small>
</span>
</label>
</div>
<div class="col-span-2">
<label class="flex flex-row gap-1.5 items-center text-sm cursor-pointer">
<CheckboxRoot v-model="filterCovered"
class="hover:bg-stone-100 flex size-4 appearance-none items-center justify-center rounded-xs bg-foreground shadow-sm border focus-within:ring-1 cursor-pointer">
<CheckboxIndicator class="size-full flex items-center justify-center bg-primary text-primary-foreground">
<PhCheck :size="10" weight="bold" />
</CheckboxIndicator>
</CheckboxRoot>
<span class="select-none">
Abrités
<small v-if="nbCovered">({{ nbCovered }})</small>
</span>
</label>
</div>
<div class="col-span-2">
<label class="flex flex-row gap-1.5 items-center text-sm cursor-pointer">
<CheckboxRoot v-model="filterKorrigo"
class="hover:bg-stone-100 flex size-4 appearance-none items-center justify-center rounded-xs bg-foreground shadow-sm border focus-within:ring-1 cursor-pointer">
<CheckboxIndicator class="size-full flex items-center justify-center bg-primary text-primary-foreground">
<PhCheck :size="10" weight="bold" />
</CheckboxIndicator>
</CheckboxRoot>
<span class="select-none">
Abonnement Korrigo
<small v-if="nbKorrigo">({{ nbKorrigo }})</small>
</span>
</label>
</div>
<div class="mt-1 col-span-2">
<label class="flex justify-between">
<span>Nombre de places</span>
<span class="text-muted-foreground">
{{ spotsRange[0] }}
{{ spotsRange[1] }}<template v-if="spotsRange[1] === 100">+</template>
</span>
</label>
<div class="mt-1">
<SliderRoot v-model="spotsRange" class="relative flex items-center select-none touch-none w-full py-2"
:min="MIN" :max="MAX" :step="5">
<SliderTrack class="bg-muted/10 relative grow rounded-full h-1.5">
<SliderRange class="absolute bg-primary rounded-full h-full" />
</SliderTrack>
<SliderThumb
class="cursor-pointer size-4 bg-white rounded-full hover:bg-primary shadow-sm focus:outline-none focus:ring-2" />
<SliderThumb
class="cursor-pointer size-4 bg-white rounded-full hover:bg-primary shadow-sm focus:outline-none focus:ring-2" />
</SliderRoot>
</div>
</div>
<!-- <div>
<NumberFieldRoot :min="MIN" :max="maxSpots" :step="5" v-model="minSpots" class="max-w-full">
<label>Min.</label>
<div
class="mt-1 flex items-center justify-center overflow-hidden border bg-white hover:bg-stone-50 rounded-lg shadow-sm h-8 focus-within:ring-2">
<NumberFieldDecrement class="p-2 pr-1 disabled:opacity-20 shrink-0">
<PhMinus :size="10" />
</NumberFieldDecrement>
<NumberFieldInput class="w-0 min-w-0 flex-1 bg-transparent text-center focus:outline-0 p-1" />
<NumberFieldIncrement class="p-2 pl-1 disabled:opacity-20 shrink-0">
<PhPlus :size="10" />
</NumberFieldIncrement>
</div>
</NumberFieldRoot>
</div>
<div>
<NumberFieldRoot :min="minSpots" :max="MAX" :step="5" v-model="maxSpots" class="max-w-full">
<label>Max.</label>
<div
class="mt-1 flex items-center justify-center overflow-hidden border bg-white hover:bg-stone-50 rounded-lg shadow-sm h-8 focus-within:ring-2">
<NumberFieldDecrement class="p-2 pr-1 disabled:opacity-20 shrink-0">
<PhMinus :size="10" />
</NumberFieldDecrement>
<NumberFieldInput class="w-0 min-w-0 flex-1 bg-transparent text-center focus:outline-0 p-1" />
<NumberFieldIncrement class="p-2 pl-1 disabled:opacity-20 shrink-0">
<PhPlus :size="10" />
</NumberFieldIncrement>
</div>
</NumberFieldRoot>
</div> -->
</div>
</form>
</aside>
</template>