Implement Fluid Emerald app redesign
This commit is contained in:
@@ -1,9 +1,24 @@
|
||||
<script setup lang="ts">
|
||||
import { Head } from '@inertiajs/vue3';
|
||||
import PlaceholderPattern from '@/components/PlaceholderPattern.vue';
|
||||
import { Head, Link, usePage } from '@inertiajs/vue3';
|
||||
import {
|
||||
ArrowRight,
|
||||
FolderKanban,
|
||||
Layers3,
|
||||
Plus,
|
||||
ShieldCheck,
|
||||
Users,
|
||||
} from 'lucide-vue-next';
|
||||
import AppLayout from '@/layouts/AppLayout.vue';
|
||||
import { dashboard } from '@/routes/index';
|
||||
import type { BreadcrumbItem } from '@/types';
|
||||
import { index as adminUsers } from '@/routes/admin/users';
|
||||
import { index as projectTemplates } from '@/routes/project-templates';
|
||||
import {
|
||||
create as projectCreate,
|
||||
index as projectsIndex,
|
||||
} from '@/routes/projects';
|
||||
import { index as teamsIndex } from '@/routes/teams';
|
||||
import type { BreadcrumbItem, NavItem } from '@/types';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const breadcrumbs: BreadcrumbItem[] = [
|
||||
{
|
||||
@@ -11,37 +26,131 @@ const breadcrumbs: BreadcrumbItem[] = [
|
||||
href: dashboard(),
|
||||
},
|
||||
];
|
||||
|
||||
const page = usePage();
|
||||
|
||||
const quickLinks = computed<NavItem[]>(() => {
|
||||
const items: NavItem[] = [
|
||||
{
|
||||
title: 'Browse projects',
|
||||
href: projectsIndex(),
|
||||
icon: FolderKanban,
|
||||
},
|
||||
];
|
||||
|
||||
if (page.props.auth.permissions.projectCreate) {
|
||||
items.push(
|
||||
{ title: 'Create a project', href: projectCreate(), icon: Plus },
|
||||
{
|
||||
title: 'Project templates',
|
||||
href: projectTemplates(),
|
||||
icon: Layers3,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if (page.props.auth.permissions.globalAdmin) {
|
||||
items.push({
|
||||
title: 'Manage users',
|
||||
href: adminUsers(),
|
||||
icon: ShieldCheck,
|
||||
});
|
||||
}
|
||||
|
||||
if (page.props.auth.permissions.canManageTeams) {
|
||||
items.push({ title: 'Manage teams', href: teamsIndex(), icon: Users });
|
||||
}
|
||||
|
||||
return items;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head title="Dashboard" />
|
||||
|
||||
<AppLayout :breadcrumbs="breadcrumbs">
|
||||
<div
|
||||
class="flex h-full flex-1 flex-col gap-4 overflow-x-auto rounded-xl p-4"
|
||||
>
|
||||
<div class="grid auto-rows-min gap-4 md:grid-cols-3">
|
||||
<div
|
||||
class="border-sidebar-border/70 dark:border-sidebar-border relative aspect-video overflow-hidden rounded-xl border"
|
||||
>
|
||||
<PlaceholderPattern />
|
||||
</div>
|
||||
<div
|
||||
class="border-sidebar-border/70 dark:border-sidebar-border relative aspect-video overflow-hidden rounded-xl border"
|
||||
>
|
||||
<PlaceholderPattern />
|
||||
</div>
|
||||
<div
|
||||
class="border-sidebar-border/70 dark:border-sidebar-border relative aspect-video overflow-hidden rounded-xl border"
|
||||
>
|
||||
<PlaceholderPattern />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="border-sidebar-border/70 dark:border-sidebar-border relative min-h-[100vh] flex-1 rounded-xl border md:min-h-min"
|
||||
<div class="app-page">
|
||||
<section
|
||||
class="border-outline-variant bg-surface-container-lowest shadow-xs relative overflow-hidden rounded-xl border px-5 py-8 sm:px-8 sm:py-10"
|
||||
>
|
||||
<PlaceholderPattern />
|
||||
</div>
|
||||
<div
|
||||
class="bg-primary/12 absolute -right-16 -top-20 size-64 rounded-full blur-3xl"
|
||||
aria-hidden="true"
|
||||
/>
|
||||
<div class="relative max-w-3xl">
|
||||
<div class="eyebrow">Your workspace</div>
|
||||
<h1
|
||||
class="mt-3 text-3xl font-semibold tracking-[-0.035em] sm:text-4xl"
|
||||
>
|
||||
Welcome back, {{ $page.props.auth.user.name }}.
|
||||
</h1>
|
||||
<p
|
||||
class="text-muted-foreground mt-3 max-w-2xl text-sm leading-6 sm:text-base"
|
||||
>
|
||||
Pick up a project, shape its workflow, or manage the
|
||||
people who make the work happen.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<div class="mb-4 flex items-end justify-between gap-4">
|
||||
<div>
|
||||
<div class="eyebrow">Shortcuts</div>
|
||||
<h2 class="mt-1 text-xl font-semibold tracking-tight">
|
||||
Where do you want to go?
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-4 sm:grid-cols-2 xl:grid-cols-3">
|
||||
<Link
|
||||
v-for="item in quickLinks"
|
||||
:key="item.title"
|
||||
:href="item.href"
|
||||
class="border-outline-variant bg-surface-container-lowest shadow-xs hover:border-primary/45 hover:shadow-kanban-card group flex min-h-36 flex-col justify-between rounded-xl border p-5 transition-all hover:-translate-y-0.5"
|
||||
>
|
||||
<div
|
||||
class="bg-primary/10 text-primary flex size-10 items-center justify-center rounded-lg"
|
||||
>
|
||||
<component :is="item.icon" class="size-5" />
|
||||
</div>
|
||||
<div
|
||||
class="mt-6 flex items-center justify-between gap-4"
|
||||
>
|
||||
<span class="font-semibold">{{ item.title }}</span>
|
||||
<ArrowRight
|
||||
class="text-muted-foreground group-hover:text-primary size-4 transition-transform group-hover:translate-x-1"
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section
|
||||
class="border-outline-variant bg-surface-container-low rounded-xl border p-5 sm:p-6"
|
||||
>
|
||||
<div
|
||||
class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between"
|
||||
>
|
||||
<div>
|
||||
<h2 class="font-semibold">
|
||||
Built for focused delivery
|
||||
</h2>
|
||||
<p class="text-muted-foreground mt-1 text-sm">
|
||||
Projects keep boards, backlog, metadata,
|
||||
repositories, and notifications together.
|
||||
</p>
|
||||
</div>
|
||||
<Link
|
||||
:href="projectsIndex()"
|
||||
class="text-primary inline-flex items-center gap-2 text-sm font-semibold hover:underline"
|
||||
>
|
||||
View all projects
|
||||
<ArrowRight class="size-4" />
|
||||
</Link>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</AppLayout>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user