246 lines
10 KiB
Vue
246 lines
10 KiB
Vue
<script setup lang="ts">
|
|
import { Head, Link } from '@inertiajs/vue3';
|
|
import { ArrowRight, Columns3, GitBranch, ListChecks } from 'lucide-vue-next';
|
|
import { computed } from 'vue';
|
|
import AppLogo from '@/components/AppLogo.vue';
|
|
import { Button } from '@/components/ui/button';
|
|
import { useLocalization } from '@/composables/useLocalization';
|
|
import { dashboard, home, login } from '@/routes/index';
|
|
|
|
const { t } = useLocalization();
|
|
|
|
const features = computed(() => [
|
|
{
|
|
icon: Columns3,
|
|
title: t('welcome.features.workflows.title'),
|
|
description: t('welcome.features.workflows.description'),
|
|
},
|
|
{
|
|
icon: ListChecks,
|
|
title: t('welcome.features.tickets.title'),
|
|
description: t('welcome.features.tickets.description'),
|
|
},
|
|
{
|
|
icon: GitBranch,
|
|
title: t('welcome.features.git.title'),
|
|
description: t('welcome.features.git.description'),
|
|
},
|
|
]);
|
|
|
|
const previewColumns = computed(() => [
|
|
{
|
|
title: t('welcome.preview.backlog'),
|
|
tickets: [
|
|
t('welcome.preview.ticketOnboarding'),
|
|
t('welcome.preview.ticketRelease'),
|
|
],
|
|
},
|
|
{
|
|
title: t('welcome.preview.inProgress'),
|
|
tickets: [t('welcome.preview.ticketRepository')],
|
|
},
|
|
{
|
|
title: t('welcome.preview.review'),
|
|
tickets: [t('welcome.preview.ticketPullRequest')],
|
|
},
|
|
]);
|
|
</script>
|
|
|
|
<template>
|
|
<div
|
|
class="bg-background text-foreground relative isolate min-h-dvh overflow-x-hidden"
|
|
>
|
|
<Head :title="t('welcome.metaTitle')" />
|
|
|
|
<div
|
|
aria-hidden="true"
|
|
class="bg-brand/10 mask-[linear-gradient(to_bottom,black,transparent)] absolute inset-x-0 top-0 -z-10 h-[34rem]"
|
|
/>
|
|
<div
|
|
aria-hidden="true"
|
|
class="bg-primary/15 absolute left-1/2 top-12 -z-10 size-80 -translate-x-1/2 rounded-full blur-3xl sm:size-[32rem]"
|
|
/>
|
|
|
|
<header
|
|
class="mx-auto flex w-full min-w-0 max-w-6xl items-center justify-between gap-3 px-4 py-4 sm:gap-4 sm:px-6 lg:px-8"
|
|
>
|
|
<Link
|
|
:href="home()"
|
|
:aria-label="t('welcome.homeLabel')"
|
|
class="focus-visible:ring-ring/35 min-w-0 rounded-md outline-none focus-visible:ring-2"
|
|
>
|
|
<AppLogo />
|
|
</Link>
|
|
|
|
<nav :aria-label="t('welcome.navigation')" class="shrink-0">
|
|
<Button as-child variant="outline" size="sm">
|
|
<Link v-if="$page.props.auth.user" :href="dashboard()">
|
|
{{ t('welcome.action.dashboardShort') }}
|
|
<ArrowRight aria-hidden="true" />
|
|
</Link>
|
|
<Link v-else :href="login()">
|
|
{{ t('welcome.action.signInShort') }}
|
|
<ArrowRight aria-hidden="true" />
|
|
</Link>
|
|
</Button>
|
|
</nav>
|
|
</header>
|
|
|
|
<main class="min-w-0">
|
|
<section
|
|
aria-labelledby="welcome-title"
|
|
class="mx-auto grid w-full min-w-0 max-w-6xl gap-10 px-4 pb-16 pt-12 sm:px-6 sm:pt-20 lg:px-8 lg:pt-24"
|
|
>
|
|
<div
|
|
class="mx-auto grid w-full min-w-0 max-w-3xl justify-items-center gap-6 text-center"
|
|
>
|
|
<p
|
|
class="border-primary/20 bg-card/80 text-primary text-label shadow-xs rounded-full border px-3 py-1.5 uppercase backdrop-blur"
|
|
>
|
|
{{ t('welcome.eyebrow') }}
|
|
</p>
|
|
<div class="grid gap-4">
|
|
<h1
|
|
id="welcome-title"
|
|
class="text-balance text-4xl font-semibold leading-tight tracking-[-0.04em] sm:text-5xl lg:text-6xl"
|
|
>
|
|
{{ t('welcome.title') }}
|
|
</h1>
|
|
<p
|
|
class="text-muted-foreground mx-auto max-w-2xl text-pretty text-base leading-7 sm:text-lg"
|
|
>
|
|
{{ t('welcome.description') }}
|
|
</p>
|
|
</div>
|
|
<Button as-child size="lg">
|
|
<Link v-if="$page.props.auth.user" :href="dashboard()">
|
|
{{ t('welcome.action.dashboard') }}
|
|
<ArrowRight aria-hidden="true" />
|
|
</Link>
|
|
<Link v-else :href="login()">
|
|
{{ t('welcome.action.signIn') }}
|
|
<ArrowRight aria-hidden="true" />
|
|
</Link>
|
|
</Button>
|
|
<p class="text-caption text-muted-foreground">
|
|
{{ t('welcome.actionHint') }}
|
|
</p>
|
|
</div>
|
|
|
|
<section
|
|
:aria-label="t('welcome.preview.label')"
|
|
class="bg-card/90 min-w-0 rounded-xl border p-3 shadow-[0_24px_80px_-32px_rgba(0,110,47,0.35)] backdrop-blur sm:p-5 dark:shadow-[0_24px_80px_-32px_rgba(74,225,118,0.22)]"
|
|
>
|
|
<div
|
|
class="border-border/80 mb-3 flex min-w-0 items-center justify-between gap-3 border-b px-1 pb-3 sm:mb-5 sm:gap-4 sm:px-2 sm:pb-4"
|
|
>
|
|
<div class="flex shrink-0 gap-1.5" aria-hidden="true">
|
|
<span class="bg-border size-2 rounded-full" />
|
|
<span class="bg-border size-2 rounded-full" />
|
|
<span class="bg-brand size-2 rounded-full" />
|
|
</div>
|
|
<p
|
|
class="text-caption text-muted-foreground min-w-0 truncate"
|
|
>
|
|
{{ t('welcome.preview.project') }}
|
|
</p>
|
|
<span
|
|
class="bg-success text-success-foreground text-label shrink-0 rounded-full px-2 py-1 uppercase"
|
|
>
|
|
{{ t('welcome.preview.connected') }}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="grid min-w-0 gap-3 md:grid-cols-3">
|
|
<section
|
|
v-for="column in previewColumns"
|
|
:key="column.title"
|
|
class="bg-muted/70 grid min-w-0 content-start gap-3 rounded-lg border p-3 sm:p-4"
|
|
>
|
|
<h2 class="text-caption font-semibold">
|
|
{{ column.title }}
|
|
</h2>
|
|
<article
|
|
v-for="ticket in column.tickets"
|
|
:key="ticket"
|
|
class="bg-card text-card-foreground shadow-xs grid min-w-0 gap-3 rounded-md border p-3"
|
|
>
|
|
<p class="text-body break-words font-medium">
|
|
{{ ticket }}
|
|
</p>
|
|
<div
|
|
class="flex items-center justify-between gap-3"
|
|
aria-hidden="true"
|
|
>
|
|
<span
|
|
class="bg-accent h-1.5 w-16 rounded-full"
|
|
/>
|
|
<span
|
|
class="bg-brand size-5 rounded-full"
|
|
/>
|
|
</div>
|
|
</article>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
</section>
|
|
|
|
<section
|
|
aria-labelledby="welcome-features-title"
|
|
class="border-border/80 bg-card/60 border-y"
|
|
>
|
|
<div
|
|
class="mx-auto grid w-full max-w-6xl gap-8 px-4 py-14 sm:px-6 lg:px-8"
|
|
>
|
|
<div class="mx-auto grid max-w-2xl gap-3 text-center">
|
|
<p class="text-label text-primary uppercase">
|
|
{{ t('welcome.features.eyebrow') }}
|
|
</p>
|
|
<h2
|
|
id="welcome-features-title"
|
|
class="text-headline-mobile sm:text-headline"
|
|
>
|
|
{{ t('welcome.features.title') }}
|
|
</h2>
|
|
</div>
|
|
|
|
<ul class="grid gap-4 md:grid-cols-3">
|
|
<li
|
|
v-for="feature in features"
|
|
:key="feature.title"
|
|
class="bg-card shadow-xs grid gap-4 rounded-lg border p-5"
|
|
>
|
|
<span
|
|
class="bg-accent text-primary flex size-10 items-center justify-center rounded-md"
|
|
>
|
|
<component
|
|
:is="feature.icon"
|
|
class="size-5"
|
|
aria-hidden="true"
|
|
/>
|
|
</span>
|
|
<div class="grid gap-2">
|
|
<h3 class="text-title">
|
|
{{ feature.title }}
|
|
</h3>
|
|
<p
|
|
class="text-muted-foreground text-pretty leading-6"
|
|
>
|
|
{{ feature.description }}
|
|
</p>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
|
|
<footer
|
|
class="text-caption text-muted-foreground mx-auto flex w-full max-w-6xl flex-col gap-2 px-4 py-8 text-center sm:px-6 lg:px-8"
|
|
>
|
|
<p class="text-foreground font-semibold">KanbanGit</p>
|
|
<p>{{ t('welcome.footer') }}</p>
|
|
</footer>
|
|
</div>
|
|
</template>
|