URL Parameter fct to a specific Directory Card entry
This commit is contained in:
parent
8dbfd3af2c
commit
e6bc387ebb
7 changed files with 461 additions and 372 deletions
|
|
@ -48,89 +48,91 @@ const socialColors = {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Card class="hover:shadow-md transition-shadow relative overflow-hidden">
|
<router-link :to="`/directory/${item.id}`" class="block">
|
||||||
<!-- Local watermark -->
|
<Card class="hover:shadow-md transition-shadow relative overflow-hidden">
|
||||||
<div v-if="item.local" class="absolute right-3 bottom-2 text-2xl tracking-widest font-bold text-primary opacity-30">
|
<!-- Local watermark -->
|
||||||
LOCAL
|
<div v-if="item.local" class="absolute right-3 bottom-2 text-2xl tracking-widest font-bold text-primary opacity-30">
|
||||||
</div>
|
LOCAL
|
||||||
|
|
||||||
<CardContent class="p-6 space-y-4">
|
|
||||||
<!-- Image -->
|
|
||||||
<div v-if="item.imageUrl" class="aspect-video w-full overflow-hidden rounded-md">
|
|
||||||
<img :src="item.imageUrl" :alt="item.name" class="h-full w-full object-cover" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Content -->
|
<CardContent class="p-6 space-y-4">
|
||||||
<div class="space-y-3">
|
<!-- Image -->
|
||||||
<div class="flex items-start justify-between">
|
<div v-if="item.imageUrl" class="aspect-video w-full overflow-hidden rounded-md">
|
||||||
<CardTitle>{{ item.name }}</CardTitle>
|
<img :src="item.imageUrl" :alt="item.name" class="h-full w-full object-cover" />
|
||||||
<span class="rounded-full px-2.5 py-0.5 text-xs font-semibold" :class="categoryColors[item.category]">
|
|
||||||
{{ item.category }}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<CardDescription>
|
<!-- Content -->
|
||||||
{{ item.description }}
|
<div class="space-y-3">
|
||||||
</CardDescription>
|
<div class="flex items-start justify-between">
|
||||||
|
<CardTitle>{{ item.name }}</CardTitle>
|
||||||
<!-- Contact Info -->
|
<span class="rounded-full px-2.5 py-0.5 text-xs font-semibold" :class="categoryColors[item.category]">
|
||||||
<div class="space-y-2">
|
{{ item.category }}
|
||||||
<div v-if="item.town || item.address" class="flex items-center text-sm group">
|
</span>
|
||||||
<MapPin class="mr-2 h-4 w-4 text-red-400" />
|
|
||||||
<a v-if="item.mapsUrl" :href="item.mapsUrl" target="_blank" rel="noopener noreferrer"
|
|
||||||
class="flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors">
|
|
||||||
<span>{{ [item.address, item.town].filter(Boolean).join(', ') }}</span>
|
|
||||||
<ExternalLink class="h-3 w-3 ml-1" />
|
|
||||||
</a>
|
|
||||||
<span v-else>{{ [item.address, item.town].filter(Boolean).join(', ') }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="item.contact" class="flex items-center text-sm gap-2">
|
<CardDescription>
|
||||||
<Phone class="h-4 w-4" />
|
{{ item.description }}
|
||||||
<span>{{ item.contact }}</span>
|
</CardDescription>
|
||||||
<div v-if="item.contactType" class="flex gap-1">
|
|
||||||
<a v-if="item.contactType.includes('whatsapp')" :href="`https://wa.me/${item.contact.replace(/\D/g, '')}`"
|
<!-- Contact Info -->
|
||||||
target="_blank" rel="noopener noreferrer"
|
<div class="space-y-2">
|
||||||
class="bg-green-100 text-green-800 px-2 py-0.5 rounded-full text-xs font-medium flex items-center gap-1 hover:bg-green-200 transition-colors">
|
<div v-if="item.town || item.address" class="flex items-center text-sm group">
|
||||||
<MessageCircle class="h-3 w-3" />
|
<MapPin class="mr-2 h-4 w-4 text-red-400" />
|
||||||
WhatsApp
|
<a v-if="item.mapsUrl" :href="item.mapsUrl" target="_blank" rel="noopener noreferrer"
|
||||||
|
class="flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors">
|
||||||
|
<span>{{ [item.address, item.town].filter(Boolean).join(', ') }}</span>
|
||||||
|
<ExternalLink class="h-3 w-3 ml-1" />
|
||||||
</a>
|
</a>
|
||||||
<a v-if="item.contactType.includes('telegram')" :href="`https://t.me/${item.contact.replace(/\D/g, '')}`"
|
<span v-else>{{ [item.address, item.town].filter(Boolean).join(', ') }}</span>
|
||||||
target="_blank" rel="noopener noreferrer"
|
</div>
|
||||||
class="bg-blue-100 text-blue-800 px-2 py-0.5 rounded-full text-xs font-medium flex items-center gap-1 hover:bg-blue-200 transition-colors">
|
|
||||||
<MessageCircle class="h-3 w-3" />
|
<div v-if="item.contact" class="flex items-center text-sm gap-2">
|
||||||
Telegram
|
<Phone class="h-4 w-4" />
|
||||||
|
<span>{{ item.contact }}</span>
|
||||||
|
<div v-if="item.contactType" class="flex gap-1">
|
||||||
|
<a v-if="item.contactType.includes('whatsapp')" :href="`https://wa.me/${item.contact.replace(/\D/g, '')}`"
|
||||||
|
target="_blank" rel="noopener noreferrer"
|
||||||
|
class="bg-green-100 text-green-800 px-2 py-0.5 rounded-full text-xs font-medium flex items-center gap-1 hover:bg-green-200 transition-colors">
|
||||||
|
<MessageCircle class="h-3 w-3" />
|
||||||
|
WhatsApp
|
||||||
|
</a>
|
||||||
|
<a v-if="item.contactType.includes('telegram')" :href="`https://t.me/${item.contact.replace(/\D/g, '')}`"
|
||||||
|
target="_blank" rel="noopener noreferrer"
|
||||||
|
class="bg-blue-100 text-blue-800 px-2 py-0.5 rounded-full text-xs font-medium flex items-center gap-1 hover:bg-blue-200 transition-colors">
|
||||||
|
<MessageCircle class="h-3 w-3" />
|
||||||
|
Telegram
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="item.lightning" class="flex items-center text-sm">
|
||||||
|
<Zap class="mr-2 h-4 w-4" />
|
||||||
|
<span>{{ item.lightning }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Website -->
|
||||||
|
<div v-if="item.url" class="flex items-center text-sm">
|
||||||
|
<ExternalLink class="mr-2 h-4 w-4" />
|
||||||
|
<a :href="item.url" target="_blank" rel="noopener noreferrer"
|
||||||
|
class="text-muted-foreground hover:text-foreground transition-colors">
|
||||||
|
{{ item.url.replace(/^https?:\/\//, '').split('/')[0] }}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="item.lightning" class="flex items-center text-sm">
|
<!-- Social Media Links -->
|
||||||
<Zap class="mr-2 h-4 w-4" />
|
<div v-if="item.social" class="flex items-center gap-2 text-sm">
|
||||||
<span>{{ item.lightning }}</span>
|
<template v-for="(url, platform) in item.social" :key="platform">
|
||||||
</div>
|
<a v-if="url" :href="url" target="_blank" rel="noopener noreferrer" :class="[
|
||||||
|
'transition-colors',
|
||||||
<!-- Website -->
|
socialColors[platform as keyof typeof socialColors]
|
||||||
<div v-if="item.url" class="flex items-center text-sm">
|
]" :title="platform.charAt(0).toUpperCase() + platform.slice(1)">
|
||||||
<ExternalLink class="mr-2 h-4 w-4" />
|
<component :is="socials[platform as keyof typeof socials]" class="h-4 w-4" />
|
||||||
<a :href="item.url" target="_blank" rel="noopener noreferrer"
|
</a>
|
||||||
class="text-muted-foreground hover:text-foreground transition-colors">
|
</template>
|
||||||
{{ item.url.replace(/^https?:\/\//, '').split('/')[0] }}
|
</div>
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Social Media Links -->
|
|
||||||
<div v-if="item.social" class="flex items-center gap-2 text-sm">
|
|
||||||
<template v-for="(url, platform) in item.social" :key="platform">
|
|
||||||
<a v-if="url" :href="url" target="_blank" rel="noopener noreferrer" :class="[
|
|
||||||
'transition-colors',
|
|
||||||
socialColors[platform as keyof typeof socialColors]
|
|
||||||
]" :title="platform.charAt(0).toUpperCase() + platform.slice(1)">
|
|
||||||
<component :is="socials[platform as keyof typeof socials]" class="h-4 w-4" />
|
|
||||||
</a>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</CardContent>
|
||||||
</CardContent>
|
</Card>
|
||||||
</Card>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
297
src/data/directory.ts
Normal file
297
src/data/directory.ts
Normal file
|
|
@ -0,0 +1,297 @@
|
||||||
|
import { type DirectoryItem } from '@/types/directory'
|
||||||
|
|
||||||
|
export const mockDirectoryItems: DirectoryItem[] = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: 'Ixchel Cafe & Bakery',
|
||||||
|
category: 'restaurant',
|
||||||
|
description: 'A cozy cafe serving great coffee and accepting Bitcoin Lightning payments.',
|
||||||
|
url: 'https://ixchel.atitlan.io',
|
||||||
|
town: 'San Marcos',
|
||||||
|
mapsUrl: 'https://maps.app.goo.gl/sbjmvqP8U4SB4FS29',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/emporium.atitlan'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: 'Axel',
|
||||||
|
category: 'taxi',
|
||||||
|
town: 'San Marcos',
|
||||||
|
contact: '+502 3846 1220',
|
||||||
|
contactType: ['whatsapp', 'telegram'],
|
||||||
|
lightning: 'axel@atitlan.io'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
name: 'Bitcoin Lake Lancha (fake)',
|
||||||
|
category: 'lancha',
|
||||||
|
address: 'Pier 21, Harbor Front',
|
||||||
|
contact: '+1 234-567-8902'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
name: 'Tor\'s Drums',
|
||||||
|
category: 'goods',
|
||||||
|
town: 'San Marcos',
|
||||||
|
contact: '+502 4900 1279',
|
||||||
|
contactType: ['whatsapp'],
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/share/1DcBdJhuFH/'
|
||||||
|
},
|
||||||
|
lightning: 'tor@atitlan.io'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
name: 'Jade Maya',
|
||||||
|
category: 'goods',
|
||||||
|
local: true,
|
||||||
|
town: 'San Marcos',
|
||||||
|
mapsUrl: 'https://maps.app.goo.gl/kZiKdM2FFAw1TQMN8',
|
||||||
|
lightning: 'osman@atitlan.io',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
name: 'La Sala del Lago',
|
||||||
|
category: 'restaurant',
|
||||||
|
town: 'San Marcos',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/La-Sala-Del-Lago-100220539146301'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '7',
|
||||||
|
name: 'Nectar',
|
||||||
|
category: 'restaurant',
|
||||||
|
town: 'San Marcos',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/lovenectar'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '8',
|
||||||
|
name: 'Arati Cafe',
|
||||||
|
category: 'restaurant',
|
||||||
|
town: 'San Marcos',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/Arati-Cafe-105767784719695'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '9',
|
||||||
|
name: 'Fe Restaurant',
|
||||||
|
category: 'restaurant',
|
||||||
|
town: 'San Marcos',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/fesanmarcos'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '10',
|
||||||
|
name: 'Hostal del Lago',
|
||||||
|
category: 'lodging',
|
||||||
|
town: 'San Marcos',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/Hostel-Del-Lago-605530306467708'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '12',
|
||||||
|
name: 'Hostel Fe San Marcos',
|
||||||
|
category: 'lodging',
|
||||||
|
town: 'San Marcos',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/HostelFeSanMarcos'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '13',
|
||||||
|
name: 'Hotel Casa Maya',
|
||||||
|
category: 'lodging',
|
||||||
|
town: 'San Marcos',
|
||||||
|
mapsUrl: 'https://www.google.com/maps/place/Hotel+Casa+Maya'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '15',
|
||||||
|
name: 'Artesanias San Marcos La Laguna',
|
||||||
|
category: 'goods',
|
||||||
|
town: 'San Marcos',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/Artesanias-San-Marcos-La-Laguna-102826589071628/'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '16',
|
||||||
|
name: 'Textiles Felix San Marcos La Laguna',
|
||||||
|
category: 'goods',
|
||||||
|
town: 'San Marcos',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/Textiles-Felix-San-Marcos-La-Laguna-102732085750559'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '17',
|
||||||
|
name: 'Health Food Store San Jose',
|
||||||
|
category: 'goods',
|
||||||
|
town: 'San Marcos',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/Health-Food-Store-San-Jose-719299235179691'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '18',
|
||||||
|
name: 'Tienda San Jose 2',
|
||||||
|
category: 'goods',
|
||||||
|
town: 'San Marcos',
|
||||||
|
mapsUrl: 'https://www.google.com/maps/place/Tienda+San+José+%232',
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '19',
|
||||||
|
name: 'Sound Temple San Marcos',
|
||||||
|
category: 'services',
|
||||||
|
town: 'San Marcos',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/SoundTempleSanMarcos'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '20',
|
||||||
|
name: 'Granja Tz\'ikin',
|
||||||
|
category: 'restaurant',
|
||||||
|
town: 'Tzununa',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/granjatzikin'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '21',
|
||||||
|
name: 'Veda',
|
||||||
|
category: 'restaurant',
|
||||||
|
town: 'Tzununa',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/vedafoodismedicine'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '22',
|
||||||
|
name: 'Bambu Guest House',
|
||||||
|
category: 'lodging',
|
||||||
|
town: 'Tzununa',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/bambuguesthousegt'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '23',
|
||||||
|
name: 'Atitlan Organics',
|
||||||
|
category: 'goods',
|
||||||
|
town: 'Tzununa',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/atitlanorganics'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '24',
|
||||||
|
name: 'Holy Wow Cacao',
|
||||||
|
category: 'goods',
|
||||||
|
town: 'Tzununa',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/HolyWowCacao'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '25',
|
||||||
|
name: 'Multiservicios Yaxon',
|
||||||
|
category: 'services',
|
||||||
|
town: 'Tzununa',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/Multiservicios-Yaxón-299907600397260'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '26',
|
||||||
|
name: 'Utz Kab',
|
||||||
|
category: 'goods',
|
||||||
|
town: 'San Pablo',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/UTZ-KAB-534232490075686'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '27',
|
||||||
|
name: 'Utz Color Fashion',
|
||||||
|
category: 'goods',
|
||||||
|
town: 'San Pedro',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/UtzColorFashion'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '28',
|
||||||
|
name: 'Do Bau',
|
||||||
|
category: 'goods',
|
||||||
|
town: 'San Pedro',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/Adrianamatrioshka'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '29',
|
||||||
|
name: 'Full Print',
|
||||||
|
category: 'services',
|
||||||
|
town: 'San Pedro',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/profile.php?id=100057645572968'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '30',
|
||||||
|
name: 'Atitlan Muay Thai',
|
||||||
|
category: 'services',
|
||||||
|
town: 'San Pedro',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/muaythaiatitlan'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '31',
|
||||||
|
name: 'Caffé Kitsch',
|
||||||
|
category: 'restaurant',
|
||||||
|
town: 'Panajachel',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/Kitschers'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '32',
|
||||||
|
name: 'Zoe Nails & Spa',
|
||||||
|
category: 'services',
|
||||||
|
town: 'Panajachel',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/zoenailsyspapanajachel'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '33',
|
||||||
|
name: 'Hotel Corazon del Mundo Fresh',
|
||||||
|
category: 'lodging',
|
||||||
|
town: 'Jaibalito',
|
||||||
|
social: {
|
||||||
|
facebook: 'https://www.facebook.com/corazondelmundofresh'
|
||||||
|
},
|
||||||
|
local: true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
@ -31,7 +31,10 @@ export default {
|
||||||
contact: 'Contact',
|
contact: 'Contact',
|
||||||
location: 'Location',
|
location: 'Location',
|
||||||
viewMap: 'View on Map',
|
viewMap: 'View on Map',
|
||||||
lightning: 'Lightning Address'
|
lightning: 'Lightning Address',
|
||||||
|
itemNotFound: 'Directory Item Not Found',
|
||||||
|
itemNotFoundDesc: 'The directory item you are looking for could not be found.',
|
||||||
|
backToDirectory: 'Back to Directory',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
poweredBy: 'Powered by',
|
poweredBy: 'Powered by',
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,10 @@ export default {
|
||||||
contact: 'Contacto',
|
contact: 'Contacto',
|
||||||
location: 'Ubicación',
|
location: 'Ubicación',
|
||||||
viewMap: 'Ver en Mapa',
|
viewMap: 'Ver en Mapa',
|
||||||
lightning: 'Dirección Lightning'
|
lightning: 'Dirección Lightning',
|
||||||
|
itemNotFound: 'Elemento del Directorio No Encontrado',
|
||||||
|
itemNotFoundDesc: 'No se pudo encontrar el elemento del directorio que estás buscando.',
|
||||||
|
backToDirectory: 'Volver al Directorio',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
poweredBy: 'Alimentado por',
|
poweredBy: 'Alimentado por',
|
||||||
|
|
|
||||||
|
|
@ -2,305 +2,12 @@
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import DirectoryGrid from '@/components/directory/DirectoryGrid.vue'
|
import DirectoryGrid from '@/components/directory/DirectoryGrid.vue'
|
||||||
import { type DirectoryItem } from '@/types/directory'
|
import { type DirectoryItem } from '@/types/directory'
|
||||||
|
import { mockDirectoryItems } from '@/data/directory'
|
||||||
|
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
// This is temporary mock data - we'll replace it with real data later
|
// Use the imported mock data
|
||||||
const mockItems: DirectoryItem[] = [
|
const items = mockDirectoryItems
|
||||||
{
|
|
||||||
id: '1',
|
|
||||||
name: 'Ixchel Cafe & Bakery',
|
|
||||||
category: 'restaurant',
|
|
||||||
description: 'A cozy cafe serving great coffee and accepting Bitcoin Lightning payments.',
|
|
||||||
url: 'https://ixchel.atitlan.io',
|
|
||||||
town: 'San Marcos',
|
|
||||||
mapsUrl: 'https://maps.app.goo.gl/sbjmvqP8U4SB4FS29',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/emporium.atitlan'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '2',
|
|
||||||
name: 'Axel',
|
|
||||||
category: 'taxi',
|
|
||||||
town: 'San Marcos',
|
|
||||||
contact: '+502 3846 1220',
|
|
||||||
contactType: ['whatsapp', 'telegram'],
|
|
||||||
lightning: 'axel@atitlan.io'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '3',
|
|
||||||
name: 'Bitcoin Lake Lancha (fake)',
|
|
||||||
category: 'lancha',
|
|
||||||
address: 'Pier 21, Harbor Front',
|
|
||||||
contact: '+1 234-567-8902'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '4',
|
|
||||||
name: 'Tor\'s Drums',
|
|
||||||
category: 'goods',
|
|
||||||
town: 'San Marcos',
|
|
||||||
contact: '+502 4900 1279',
|
|
||||||
contactType: ['whatsapp'],
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/share/1DcBdJhuFH/'
|
|
||||||
},
|
|
||||||
lightning: 'tor@atitlan.io'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '5',
|
|
||||||
name: 'Jade Maya',
|
|
||||||
category: 'goods',
|
|
||||||
local: true,
|
|
||||||
town: 'San Marcos',
|
|
||||||
mapsUrl: 'https://maps.app.goo.gl/kZiKdM2FFAw1TQMN8',
|
|
||||||
lightning: 'osman@atitlan.io',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '6',
|
|
||||||
name: 'La Sala del Lago',
|
|
||||||
category: 'restaurant',
|
|
||||||
town: 'San Marcos',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/La-Sala-Del-Lago-100220539146301'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '7',
|
|
||||||
name: 'Nectar',
|
|
||||||
category: 'restaurant',
|
|
||||||
town: 'San Marcos',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/lovenectar'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '8',
|
|
||||||
name: 'Arati Cafe',
|
|
||||||
category: 'restaurant',
|
|
||||||
town: 'San Marcos',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/Arati-Cafe-105767784719695'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '9',
|
|
||||||
name: 'Fe Restaurant',
|
|
||||||
category: 'restaurant',
|
|
||||||
town: 'San Marcos',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/fesanmarcos'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '10',
|
|
||||||
name: 'Hostal del Lago',
|
|
||||||
category: 'lodging',
|
|
||||||
town: 'San Marcos',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/Hostel-Del-Lago-605530306467708'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '12',
|
|
||||||
name: 'Hostel Fe San Marcos',
|
|
||||||
category: 'lodging',
|
|
||||||
town: 'San Marcos',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/HostelFeSanMarcos'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '13',
|
|
||||||
name: 'Hotel Casa Maya',
|
|
||||||
category: 'lodging',
|
|
||||||
town: 'San Marcos',
|
|
||||||
mapsUrl: 'https://www.google.com/maps/place/Hotel+Casa+Maya'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '15',
|
|
||||||
name: 'Artesanias San Marcos La Laguna',
|
|
||||||
category: 'goods',
|
|
||||||
town: 'San Marcos',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/Artesanias-San-Marcos-La-Laguna-102826589071628/'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '16',
|
|
||||||
name: 'Textiles Felix San Marcos La Laguna',
|
|
||||||
category: 'goods',
|
|
||||||
town: 'San Marcos',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/Textiles-Felix-San-Marcos-La-Laguna-102732085750559'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '17',
|
|
||||||
name: 'Health Food Store San Jose',
|
|
||||||
category: 'goods',
|
|
||||||
town: 'San Marcos',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/Health-Food-Store-San-Jose-719299235179691'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '18',
|
|
||||||
name: 'Tienda San Jose 2',
|
|
||||||
category: 'goods',
|
|
||||||
town: 'San Marcos',
|
|
||||||
mapsUrl: 'https://www.google.com/maps/place/Tienda+San+José+%232',
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '19',
|
|
||||||
name: 'Sound Temple San Marcos',
|
|
||||||
category: 'services',
|
|
||||||
town: 'San Marcos',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/SoundTempleSanMarcos'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '20',
|
|
||||||
name: 'Granja Tz\'ikin',
|
|
||||||
category: 'restaurant',
|
|
||||||
town: 'Tzununa',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/granjatzikin'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '21',
|
|
||||||
name: 'Veda',
|
|
||||||
category: 'restaurant',
|
|
||||||
town: 'Tzununa',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/vedafoodismedicine'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '22',
|
|
||||||
name: 'Bambu Guest House',
|
|
||||||
category: 'lodging',
|
|
||||||
town: 'Tzununa',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/bambuguesthousegt'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '23',
|
|
||||||
name: 'Atitlan Organics',
|
|
||||||
category: 'goods',
|
|
||||||
town: 'Tzununa',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/atitlanorganics'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '24',
|
|
||||||
name: 'Holy Wow Cacao',
|
|
||||||
category: 'goods',
|
|
||||||
town: 'Tzununa',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/HolyWowCacao'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '25',
|
|
||||||
name: 'Multiservicios Yaxon',
|
|
||||||
category: 'services',
|
|
||||||
town: 'Tzununa',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/Multiservicios-Yaxón-299907600397260'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '26',
|
|
||||||
name: 'Utz Kab',
|
|
||||||
category: 'goods',
|
|
||||||
town: 'San Pablo',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/UTZ-KAB-534232490075686'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '27',
|
|
||||||
name: 'Utz Color Fashion',
|
|
||||||
category: 'goods',
|
|
||||||
town: 'San Pedro',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/UtzColorFashion'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '28',
|
|
||||||
name: 'Do Bau',
|
|
||||||
category: 'goods',
|
|
||||||
town: 'San Pedro',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/Adrianamatrioshka'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '29',
|
|
||||||
name: 'Full Print',
|
|
||||||
category: 'services',
|
|
||||||
town: 'San Pedro',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/profile.php?id=100057645572968'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '30',
|
|
||||||
name: 'Atitlan Muay Thai',
|
|
||||||
category: 'services',
|
|
||||||
town: 'San Pedro',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/muaythaiatitlan'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '31',
|
|
||||||
name: 'Caffé Kitsch',
|
|
||||||
category: 'restaurant',
|
|
||||||
town: 'Panajachel',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/Kitschers'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '32',
|
|
||||||
name: 'Zoe Nails & Spa',
|
|
||||||
category: 'services',
|
|
||||||
town: 'Panajachel',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/zoenailsyspapanajachel'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: '33',
|
|
||||||
name: 'Hotel Corazon del Mundo Fresh',
|
|
||||||
category: 'lodging',
|
|
||||||
town: 'Jaibalito',
|
|
||||||
social: {
|
|
||||||
facebook: 'https://www.facebook.com/corazondelmundofresh'
|
|
||||||
},
|
|
||||||
local: true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -317,7 +24,7 @@ const mockItems: DirectoryItem[] = [
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Directory Grid -->
|
<!-- Directory Grid -->
|
||||||
<DirectoryGrid :items="mockItems" />
|
<DirectoryGrid :items="items" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
71
src/pages/DirectoryItem.vue
Normal file
71
src/pages/DirectoryItem.vue
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import DirectoryCard from '@/components/directory/DirectoryCard.vue'
|
||||||
|
import { type DirectoryItem } from '@/types/directory'
|
||||||
|
import { mockDirectoryItems } from '@/data/directory'
|
||||||
|
|
||||||
|
const { t } = useI18n()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
id: string
|
||||||
|
}>()
|
||||||
|
|
||||||
|
// This should eventually be replaced with an API call
|
||||||
|
const item = ref<DirectoryItem | null>(null)
|
||||||
|
const loading = ref(true)
|
||||||
|
const error = ref(false)
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
const found = mockDirectoryItems.find(i => i.id === props.id)
|
||||||
|
if (!found) {
|
||||||
|
error.value = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
item.value = found
|
||||||
|
} catch (e) {
|
||||||
|
error.value = true
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="container mx-auto px-4 py-8">
|
||||||
|
<div class="max-w-2xl mx-auto">
|
||||||
|
<!-- Loading State -->
|
||||||
|
<div v-if="loading" class="text-center py-12">
|
||||||
|
<div class="animate-pulse">
|
||||||
|
<div class="h-8 bg-muted rounded w-3/4 mx-auto mb-4"></div>
|
||||||
|
<div class="h-4 bg-muted rounded w-1/2 mx-auto"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Error State -->
|
||||||
|
<div v-else-if="error" class="text-center py-12">
|
||||||
|
<h2 class="text-xl font-semibold mb-2">{{ t('directory.itemNotFound') }}</h2>
|
||||||
|
<p class="text-muted-foreground mb-4">{{ t('directory.itemNotFoundDesc') }}</p>
|
||||||
|
<router-link to="/directory"
|
||||||
|
class="inline-flex items-center justify-center rounded-md bg-primary px-6 py-3 text-sm font-medium text-primary-foreground hover:bg-primary/90">
|
||||||
|
{{ t('directory.backToDirectory') }}
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Directory Item -->
|
||||||
|
<template v-else-if="item">
|
||||||
|
<div class="mb-6">
|
||||||
|
<router-link to="/directory"
|
||||||
|
class="text-sm text-muted-foreground hover:text-foreground transition-colors">
|
||||||
|
← {{ t('directory.backToDirectory') }}
|
||||||
|
</router-link>
|
||||||
|
</div>
|
||||||
|
<DirectoryCard :item="item" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -20,6 +20,12 @@ const router = createRouter({
|
||||||
path: '/faq',
|
path: '/faq',
|
||||||
name: 'faq',
|
name: 'faq',
|
||||||
component: FAQ
|
component: FAQ
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/directory/:id',
|
||||||
|
name: 'directory-item',
|
||||||
|
component: () => import('@/pages/DirectoryItem.vue'),
|
||||||
|
props: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue