Initial project setup for a privacy-focused, self-hosted scheduling app: - Go backend with JWT auth, SQLite storage, and chi router - Calendar integrations via Google OAuth (FreeBusy), CalDAV, and ICS links - Public booking pages with configurable slots and booking requests - AES-256-GCM encryption for stored provider tokens - Vue 3 + TypeScript frontend with Vite, Pinia, and Vue Router - Docs, .gitignore, and .env.example for local development
46 lines
1.3 KiB
Vue
46 lines
1.3 KiB
Vue
<script setup lang="ts">
|
||
import { computed, ref } from 'vue'
|
||
import { useAuth } from '../stores/auth'
|
||
import { useToast } from '../stores/toast'
|
||
import GlassCard from './GlassCard.vue'
|
||
|
||
const auth = useAuth()
|
||
const toast = useToast()
|
||
const copied = ref(false)
|
||
|
||
const link = computed(() => `${location.origin}/b/${auth.user?.slug ?? ''}`)
|
||
|
||
async function copy() {
|
||
try {
|
||
await navigator.clipboard.writeText(link.value)
|
||
copied.value = true
|
||
toast.ok('Link kopiert!')
|
||
setTimeout(() => (copied.value = false), 2000)
|
||
} catch {
|
||
toast.error('Kopieren nicht möglich – bitte manuell markieren.')
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<template>
|
||
<GlassCard title="🔗 Dein Buchungslink" subtitle="Teile diesen Link – andere sehen nur frei/belegt und können anfragen.">
|
||
<div class="row link-row">
|
||
<code class="link glass-soft grow">{{ link }}</code>
|
||
<button class="btn btn-primary" @click="copy">{{ copied ? 'Kopiert ✓' : 'Kopieren' }}</button>
|
||
</div>
|
||
<p class="faint small" style="margin: 0">
|
||
Tipp: QR-Code oder Link in Signatur, Website oder Nachrichtenaustausch einbauen.
|
||
</p>
|
||
</GlassCard>
|
||
</template>
|
||
|
||
<style scoped>
|
||
.link-row { flex-wrap: wrap; }
|
||
.link {
|
||
padding: 12px 16px;
|
||
font-size: 14px;
|
||
overflow-x: auto;
|
||
white-space: nowrap;
|
||
color: var(--accent);
|
||
}
|
||
</style>
|