add copy button
This commit is contained in:
parent
e6bc387ebb
commit
23d3bd35dd
3 changed files with 66 additions and 3 deletions
|
|
@ -35,6 +35,10 @@ export default {
|
||||||
itemNotFound: 'Directory Item Not Found',
|
itemNotFound: 'Directory Item Not Found',
|
||||||
itemNotFoundDesc: 'The directory item you are looking for could not be found.',
|
itemNotFoundDesc: 'The directory item you are looking for could not be found.',
|
||||||
backToDirectory: 'Back to Directory',
|
backToDirectory: 'Back to Directory',
|
||||||
|
share: 'Share',
|
||||||
|
shareTitle: 'Share this listing',
|
||||||
|
copyLink: 'Copy Link',
|
||||||
|
linkCopied: 'Link copied to clipboard!',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
poweredBy: 'Powered by',
|
poweredBy: 'Powered by',
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,10 @@ export default {
|
||||||
itemNotFound: 'Elemento del Directorio No Encontrado',
|
itemNotFound: 'Elemento del Directorio No Encontrado',
|
||||||
itemNotFoundDesc: 'No se pudo encontrar el elemento del directorio que estás buscando.',
|
itemNotFoundDesc: 'No se pudo encontrar el elemento del directorio que estás buscando.',
|
||||||
backToDirectory: 'Volver al Directorio',
|
backToDirectory: 'Volver al Directorio',
|
||||||
|
share: 'Compartir',
|
||||||
|
shareTitle: 'Compartir este listado',
|
||||||
|
copyLink: 'Copiar enlace',
|
||||||
|
linkCopied: '¡Enlace copiado al portapapeles!',
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
poweredBy: 'Alimentado por',
|
poweredBy: 'Alimentado por',
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted, computed } from 'vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import { Share2, Copy, Check } from 'lucide-vue-next'
|
||||||
|
import { Button } from '@/components/ui/button'
|
||||||
import DirectoryCard from '@/components/directory/DirectoryCard.vue'
|
import DirectoryCard from '@/components/directory/DirectoryCard.vue'
|
||||||
import { type DirectoryItem } from '@/types/directory'
|
import { type DirectoryItem } from '@/types/directory'
|
||||||
import { mockDirectoryItems } from '@/data/directory'
|
import { mockDirectoryItems } from '@/data/directory'
|
||||||
|
|
@ -13,10 +15,50 @@ const props = defineProps<{
|
||||||
id: string
|
id: string
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
// This should eventually be replaced with an API call
|
|
||||||
const item = ref<DirectoryItem | null>(null)
|
const item = ref<DirectoryItem | null>(null)
|
||||||
const loading = ref(true)
|
const loading = ref(true)
|
||||||
const error = ref(false)
|
const error = ref(false)
|
||||||
|
const justCopied = ref(false)
|
||||||
|
|
||||||
|
// Check if Web Share API is available
|
||||||
|
const canShare = computed(() => typeof navigator !== 'undefined' && !!navigator.share)
|
||||||
|
|
||||||
|
// Share functionality
|
||||||
|
const shareItem = async () => {
|
||||||
|
if (!item.value) return
|
||||||
|
|
||||||
|
const shareData = {
|
||||||
|
title: item.value.name,
|
||||||
|
text: item.value.description || `Check out ${item.value.name} on Atitlan Directory`,
|
||||||
|
url: window.location.href
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canShare.value) {
|
||||||
|
try {
|
||||||
|
await navigator.share(shareData)
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof Error && err.name !== 'AbortError') {
|
||||||
|
console.error('Error sharing:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback to copying the URL
|
||||||
|
await copyToClipboard()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy to clipboard functionality
|
||||||
|
const copyToClipboard = async () => {
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(window.location.href)
|
||||||
|
justCopied.value = true
|
||||||
|
setTimeout(() => {
|
||||||
|
justCopied.value = false
|
||||||
|
}, 2000)
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to copy:', err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -58,11 +100,24 @@ onMounted(async () => {
|
||||||
|
|
||||||
<!-- Directory Item -->
|
<!-- Directory Item -->
|
||||||
<template v-else-if="item">
|
<template v-else-if="item">
|
||||||
<div class="mb-6">
|
<div class="mb-6 flex justify-between items-center">
|
||||||
<router-link to="/directory"
|
<router-link to="/directory"
|
||||||
class="text-sm text-muted-foreground hover:text-foreground transition-colors">
|
class="text-sm text-muted-foreground hover:text-foreground transition-colors">
|
||||||
← {{ t('directory.backToDirectory') }}
|
← {{ t('directory.backToDirectory') }}
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
|
<!-- Share Button -->
|
||||||
|
<Button variant="outline" size="sm" @click="shareItem">
|
||||||
|
<template v-if="canShare">
|
||||||
|
<Share2 class="h-4 w-4 mr-2" />
|
||||||
|
{{ t('directory.share') }}
|
||||||
|
</template>
|
||||||
|
<template v-else>
|
||||||
|
<Copy v-if="!justCopied" class="h-4 w-4 mr-2" />
|
||||||
|
<Check v-else class="h-4 w-4 mr-2" />
|
||||||
|
{{ justCopied ? t('directory.linkCopied') : t('directory.copyLink') }}
|
||||||
|
</template>
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<DirectoryCard :item="item" />
|
<DirectoryCard :item="item" />
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue