PWA
This commit is contained in:
parent
9cde9b5cf7
commit
f3927b97a4
21 changed files with 8672 additions and 202 deletions
|
|
@ -1,5 +1,5 @@
|
|||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { Search } from 'lucide-vue-next'
|
||||
import { Input } from '@/components/ui/input'
|
||||
|
|
@ -16,7 +16,7 @@ import {
|
|||
|
||||
const { t } = useI18n()
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
category: string
|
||||
search: string
|
||||
town: string
|
||||
|
|
@ -28,6 +28,18 @@ const emit = defineEmits<{
|
|||
'update:town': [value: string]
|
||||
}>()
|
||||
|
||||
const searchValue = ref('')
|
||||
|
||||
// Watch for changes in the search value
|
||||
watch(searchValue, (newValue) => {
|
||||
emit('update:search', newValue)
|
||||
})
|
||||
|
||||
// Watch for prop changes to update local value
|
||||
watch(() => props.search, (newValue) => {
|
||||
searchValue.value = newValue
|
||||
}, { immediate: true })
|
||||
|
||||
const categoryIcons = {
|
||||
restaurant: UtensilsCrossed,
|
||||
lodging: Bed,
|
||||
|
|
@ -77,27 +89,33 @@ const towns = computed(() => [
|
|||
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<Search class="h-5 w-5 text-muted-foreground" />
|
||||
</div>
|
||||
<Input type="text" :value="search" @input="emit('update:search', ($event.target as HTMLInputElement).value)"
|
||||
class="pl-10" :placeholder="t('directory.search')" />
|
||||
<Input
|
||||
v-model="searchValue"
|
||||
type="text"
|
||||
class="pl-10 w-full"
|
||||
:placeholder="t('directory.search')"
|
||||
inputmode="text"
|
||||
enterkeyhint="search"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col md:flex-row gap-1 sm:gap-2">
|
||||
<!-- Category Filter -->
|
||||
<div class="flex gap-1 sm:gap-2 overflow-x-auto pb-1 sm:pb-2 md:pb-0">
|
||||
<Button v-for="cat in categories" :key="cat.id" @click="emit('update:category', cat.id)"
|
||||
:variant="category === cat.id ? 'default' : 'secondary'" size="sm" class="rounded-full whitespace-nowrap">
|
||||
:variant="props.category === cat.id ? 'default' : 'secondary'" size="sm" class="rounded-full whitespace-nowrap">
|
||||
<!-- Show only icon on mobile for non-'all' categories -->
|
||||
<template v-if="cat.id !== 'all'">
|
||||
<component :is="cat.icon"
|
||||
class="h-4 w-4 md:mr-2"
|
||||
:class="[
|
||||
category === cat.id ? '' : categoryColors[cat.id as keyof typeof categoryColors],
|
||||
props.category === cat.id ? '' : categoryColors[cat.id as keyof typeof categoryColors],
|
||||
'md:hidden'
|
||||
]"
|
||||
/>
|
||||
<component :is="cat.icon"
|
||||
class="h-4 w-4 mr-2 hidden md:inline-block"
|
||||
:class="category === cat.id ? '' : categoryColors[cat.id as keyof typeof categoryColors]"
|
||||
:class="props.category === cat.id ? '' : categoryColors[cat.id as keyof typeof categoryColors]"
|
||||
/>
|
||||
<span class="hidden md:inline">{{ cat.label }}</span>
|
||||
</template>
|
||||
|
|
@ -111,7 +129,7 @@ const towns = computed(() => [
|
|||
<!-- Town Filter -->
|
||||
<div class="flex gap-1 sm:gap-2 overflow-x-auto pb-1 sm:pb-2 md:pb-0">
|
||||
<Button v-for="to in towns" :key="to.id" @click="emit('update:town', to.id)"
|
||||
:variant="town === to.id ? 'default' : 'secondary'" size="sm" class="rounded-full whitespace-nowrap">
|
||||
:variant="props.town === to.id ? 'default' : 'secondary'" size="sm" class="rounded-full whitespace-nowrap">
|
||||
{{ to.label }}
|
||||
</Button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -53,14 +53,14 @@ const filteredItems = computed(() => {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="container mx-auto px-4 py-2 sm:py-8">
|
||||
<div>
|
||||
<!-- Filters -->
|
||||
<div class="mb-4 sm:mb-8 space-y-4 md:space-y-0 md:flex md:items-center md:justify-between">
|
||||
<div class="space-y-2 md:space-y-0 md:flex md:items-center md:justify-between">
|
||||
<DirectoryFilter v-model:category="selectedCategory" v-model:search="searchQuery" v-model:town="selectedTown" />
|
||||
</div>
|
||||
|
||||
<!-- Grid -->
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-4">
|
||||
<DirectoryCard v-for="item in filteredItems" :key="item.id" :item="item" />
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue