mirror of
https://github.com/Nezumi-2711/Sink.git
synced 2026-09-22 13:48:35 +00:00
feat: init
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
<script setup>
|
||||
import { CalendarPlus2, Copy, CopyCheck, Eraser, Hourglass, Link as LinkIcon, QrCode, SquareChevronDown, SquarePen } from 'lucide-vue-next'
|
||||
import { useClipboard } from '@vueuse/core'
|
||||
import { toast } from 'vue-sonner'
|
||||
import { parseURL } from 'ufo'
|
||||
import QRCode from './QRCode.vue'
|
||||
|
||||
const props = defineProps({
|
||||
link: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
const emit = defineEmits(['update:link'])
|
||||
|
||||
const editPopoverOpen = ref(false)
|
||||
|
||||
const { host, origin } = location
|
||||
|
||||
function getLinkHost(url) {
|
||||
const { host } = parseURL(url)
|
||||
return host
|
||||
}
|
||||
|
||||
const shortLink = computed(() => `${origin}/${props.link.slug}`)
|
||||
const linkIcon = computed(() => `https://unavatar.io/${getLinkHost(props.link.url)}?fallback=https://sink.cool/sink.png`)
|
||||
|
||||
const { copy, copied } = useClipboard({ source: shortLink.value, copiedDuring: 400 })
|
||||
|
||||
function updateLink(link, type) {
|
||||
emit('update:link', link, type)
|
||||
editPopoverOpen.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Card>
|
||||
<NuxtLink
|
||||
class="flex flex-col p-4 space-y-3"
|
||||
:to="`/dashboard/link?slug=${link.slug}`"
|
||||
>
|
||||
<div class="flex items-center justify-center space-x-3">
|
||||
<Avatar>
|
||||
<AvatarImage
|
||||
:src="linkIcon"
|
||||
alt="@radix-vue"
|
||||
/>
|
||||
<AvatarFallback>
|
||||
<img
|
||||
src="/sink.png"
|
||||
alt="Sink"
|
||||
>
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
|
||||
<div class="flex-1 overflow-hidden">
|
||||
<div class="flex items-center">
|
||||
<div class="font-bold leading-5 truncate text-md">
|
||||
{{ host }}/{{ link.slug }}
|
||||
</div>
|
||||
|
||||
<CopyCheck
|
||||
v-if="copied"
|
||||
class="w-4 h-4 ml-1 shrink-0"
|
||||
@click.prevent
|
||||
/>
|
||||
<Copy
|
||||
v-else
|
||||
class="w-4 h-4 ml-1 shrink-0"
|
||||
@click.prevent="copy(shortLink);toast('Copy successful!')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<p class="text-sm truncate">
|
||||
{{ link.comment || link.title || link.description }}
|
||||
</p>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p class="max-w-[90svw] break-all">
|
||||
{{ link.comment || link.title || link.description }}
|
||||
</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</div>
|
||||
|
||||
<a
|
||||
:href="link.url"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
@click.stop
|
||||
>
|
||||
<LinkIcon class="w-5 h-5" />
|
||||
</a>
|
||||
|
||||
<Popover>
|
||||
<PopoverTrigger>
|
||||
<QrCode
|
||||
class="w-5 h-5"
|
||||
@click.prevent
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent>
|
||||
<QRCode
|
||||
:data="shortLink"
|
||||
:image="linkIcon"
|
||||
/>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
|
||||
<Popover v-model:open="editPopoverOpen">
|
||||
<PopoverTrigger>
|
||||
<SquareChevronDown
|
||||
class="w-5 h-5"
|
||||
@click.prevent
|
||||
/>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
class="w-auto p-0"
|
||||
:hide-when-detached="false"
|
||||
>
|
||||
<DashboardLinksEditor
|
||||
:link="link"
|
||||
@update:link="updateLink"
|
||||
>
|
||||
<div
|
||||
class="cursor-pointer flex select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground"
|
||||
>
|
||||
<SquarePen
|
||||
class="w-5 h-5 mr-2"
|
||||
/>
|
||||
Edit
|
||||
</div>
|
||||
</DashboardLinksEditor>
|
||||
|
||||
<Separator />
|
||||
|
||||
<DashboardLinksDelete
|
||||
:link="link"
|
||||
@update:link="updateLink"
|
||||
>
|
||||
<div
|
||||
class="cursor-pointer flex select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none hover:bg-accent hover:text-accent-foreground"
|
||||
>
|
||||
<Eraser
|
||||
class="w-5 h-5 mr-2"
|
||||
/> Delete
|
||||
</div>
|
||||
</DashboardLinksDelete>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
</div>
|
||||
<div class="flex w-full h-5 space-x-2 text-sm">
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<span class="inline-flex items-center leading-5"><CalendarPlus2 class="w-4 h-4 mr-1" /> {{ shortDate(link.createdAt) }}</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Created At: {{ longDate(link.createdAt) }}</p>
|
||||
<p>Updated At: {{ longDate(link.updatedAt) }}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
<template v-if="link.expiration">
|
||||
<Separator orientation="vertical" />
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<span class="inline-flex items-center leading-5"><Hourglass class="w-4 h-4 mr-1" /> {{ shortDate(link.expiration) }}</span>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Expires At: {{ longDate(link.expiration) }}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
</template>
|
||||
<Separator orientation="vertical" />
|
||||
<span class="truncate">{{ link.url }}</span>
|
||||
</div>
|
||||
</NuxtLink>
|
||||
</Card>
|
||||
</template>
|
||||
Reference in New Issue
Block a user