Initial
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import AppLayout from '@/layouts/app/AppSidebarLayout.vue';
|
||||
import type { BreadcrumbItem } from '@/types';
|
||||
|
||||
const { breadcrumbs = [] } = defineProps<{
|
||||
breadcrumbs?: BreadcrumbItem[];
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppLayout :breadcrumbs="breadcrumbs">
|
||||
<slot />
|
||||
</AppLayout>
|
||||
</template>
|
||||
@@ -1,14 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import AuthLayout from '@/layouts/auth/AuthSimpleLayout.vue';
|
||||
|
||||
const { title = '', description = '' } = defineProps<{
|
||||
title?: string;
|
||||
description?: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AuthLayout :title="title" :description="description">
|
||||
<slot />
|
||||
</AuthLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,201 @@
|
||||
<script setup lang="ts">
|
||||
import { Head } from '@inertiajs/vue3';
|
||||
import { ref } from 'vue';
|
||||
import { useDisplay } from 'vuetify';
|
||||
import Masthead from '@/components/Masthead.vue';
|
||||
|
||||
defineProps<{
|
||||
title?: string;
|
||||
}>();
|
||||
|
||||
const { mobile } = useDisplay();
|
||||
const drawer = ref(false);
|
||||
|
||||
const navItems = [
|
||||
{ label: 'Top Stories', href: '/' },
|
||||
{ label: 'World', href: '/world' },
|
||||
{ label: 'Technology', href: '/technology' },
|
||||
{ label: 'Business', href: '/business' },
|
||||
{ label: 'Science', href: '/science' },
|
||||
];
|
||||
|
||||
const subItems = [
|
||||
'Headlines',
|
||||
'Australia',
|
||||
'UK',
|
||||
'USA',
|
||||
'Politics',
|
||||
'Climate',
|
||||
'Health',
|
||||
'Sport',
|
||||
'Arts',
|
||||
];
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head :title="title" />
|
||||
|
||||
<VApp>
|
||||
<!-- Header -->
|
||||
<VAppBar flat height="56" color="surface" border="b">
|
||||
<VAppBarTitle>
|
||||
<Masthead dark />
|
||||
</VAppBarTitle>
|
||||
|
||||
<!-- Desktop nav -->
|
||||
<template v-if="!mobile">
|
||||
<div class="d-flex ga-2 mr-4">
|
||||
<VBtn variant="text" href="/login" class="nav-btn">
|
||||
Login
|
||||
</VBtn>
|
||||
<VBtn variant="outlined" href="/register" class="nav-btn">
|
||||
Register
|
||||
</VBtn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Mobile hamburger -->
|
||||
<VAppBarNavIcon v-else @click="drawer = !drawer" />
|
||||
</VAppBar>
|
||||
|
||||
<VAppBar flat :height="37" color="surface" style="top: 56px">
|
||||
<div class="red-rule" />
|
||||
<div class="subbar">
|
||||
<a
|
||||
v-for="item in subItems"
|
||||
:key="item"
|
||||
href="#"
|
||||
class="subbar-link"
|
||||
>
|
||||
{{ item }}
|
||||
</a>
|
||||
</div>
|
||||
</VAppBar>
|
||||
|
||||
<VNavigationDrawer v-model="drawer" temporary>
|
||||
<VList>
|
||||
<VListItem href="/login" title="Login" />
|
||||
<VListItem href="/register" title="Register" />
|
||||
</VList>
|
||||
</VNavigationDrawer>
|
||||
|
||||
<!-- Main content -->
|
||||
<VMain class="bg-background">
|
||||
<VContainer class="content-well pa-6">
|
||||
<slot />
|
||||
</VContainer>
|
||||
</VMain>
|
||||
|
||||
<!-- Footer -->
|
||||
<VFooter app color="#111111" class="footer">
|
||||
<Masthead small light />
|
||||
<VSpacer />
|
||||
<nav class="d-flex ga-4">
|
||||
<a
|
||||
v-for="link in ['About', 'Donate']"
|
||||
:key="link"
|
||||
:href="`/${link.toLowerCase()}`"
|
||||
class="footer-link"
|
||||
>
|
||||
{{ link }}
|
||||
</a>
|
||||
</nav>
|
||||
<v-spacer />
|
||||
<span class="footer-copy"
|
||||
>© {{ new Date().getFullYear() }} DredgeNews</span
|
||||
>
|
||||
</VFooter>
|
||||
</VApp>
|
||||
</template>
|
||||
|
||||
<style scoped lang="sass">
|
||||
@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Inter:wght@400;500&display=swap')
|
||||
|
||||
.nav-btn
|
||||
font-family: 'Inter', sans-serif
|
||||
font-size: 13px
|
||||
font-weight: 500
|
||||
letter-spacing: 0
|
||||
text-transform: none
|
||||
|
||||
|
||||
.nav-link
|
||||
font-family: 'Inter', sans-serif
|
||||
font-size: 13px
|
||||
font-weight: 500
|
||||
color: #444
|
||||
text-decoration: none
|
||||
padding: 0 14px
|
||||
height: 56px
|
||||
display: flex
|
||||
align-items: center
|
||||
border-bottom: 3px solid transparent
|
||||
transition: color 0.15s
|
||||
|
||||
&:hover
|
||||
color: #111
|
||||
|
||||
&.active
|
||||
color: #111
|
||||
border-bottom-color: #C0392B
|
||||
|
||||
.red-rule
|
||||
height: 3px
|
||||
background: #C0392B
|
||||
width: 100%
|
||||
position: absolute
|
||||
top: 0
|
||||
left: 0
|
||||
z-index: 1
|
||||
|
||||
.subbar
|
||||
width: 100%
|
||||
background: #fff
|
||||
border-bottom: 1px solid #E8E8E8
|
||||
display: flex
|
||||
overflow-x: auto
|
||||
padding: 0 1.5rem
|
||||
position: absolute
|
||||
top: 3px
|
||||
left: 0
|
||||
|
||||
&::-webkit-scrollbar
|
||||
display: none
|
||||
|
||||
.subbar-link
|
||||
font-family: 'Inter', sans-serif
|
||||
font-size: 12px
|
||||
color: #666
|
||||
text-decoration: none
|
||||
padding: 8px 12px
|
||||
white-space: nowrap
|
||||
border-bottom: 2px solid transparent
|
||||
flex-shrink: 0
|
||||
|
||||
&:hover
|
||||
color: #111
|
||||
|
||||
&.active
|
||||
color: #111
|
||||
border-bottom-color: #111
|
||||
|
||||
.content-well
|
||||
max-width: 1080px
|
||||
|
||||
.footer
|
||||
padding: 1.25rem 1.5rem
|
||||
display: flex
|
||||
align-items: center
|
||||
|
||||
.footer-link
|
||||
font-size: 12px
|
||||
color: #aaa
|
||||
text-decoration: none
|
||||
|
||||
&:hover
|
||||
color: #fff
|
||||
|
||||
.footer-copy
|
||||
font-size: 11px
|
||||
color: #666
|
||||
</style>
|
||||
@@ -1,25 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import AppContent from '@/components/AppContent.vue';
|
||||
import AppHeader from '@/components/AppHeader.vue';
|
||||
import AppShell from '@/components/AppShell.vue';
|
||||
import { Toaster } from '@/components/ui/sonner';
|
||||
import type { BreadcrumbItem } from '@/types';
|
||||
|
||||
type Props = {
|
||||
breadcrumbs?: BreadcrumbItem[];
|
||||
};
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
breadcrumbs: () => [],
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppShell variant="header">
|
||||
<AppHeader :breadcrumbs="breadcrumbs" />
|
||||
<AppContent variant="header">
|
||||
<slot />
|
||||
</AppContent>
|
||||
<Toaster />
|
||||
</AppShell>
|
||||
</template>
|
||||
@@ -1,27 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import AppContent from '@/components/AppContent.vue';
|
||||
import AppShell from '@/components/AppShell.vue';
|
||||
import AppSidebar from '@/components/AppSidebar.vue';
|
||||
import AppSidebarHeader from '@/components/AppSidebarHeader.vue';
|
||||
import { Toaster } from '@/components/ui/sonner';
|
||||
import type { BreadcrumbItem } from '@/types';
|
||||
|
||||
type Props = {
|
||||
breadcrumbs?: BreadcrumbItem[];
|
||||
};
|
||||
|
||||
withDefaults(defineProps<Props>(), {
|
||||
breadcrumbs: () => [],
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<AppShell variant="sidebar">
|
||||
<AppSidebar />
|
||||
<AppContent variant="sidebar" class="overflow-x-hidden">
|
||||
<AppSidebarHeader :breadcrumbs="breadcrumbs" />
|
||||
<slot />
|
||||
</AppContent>
|
||||
<Toaster />
|
||||
</AppShell>
|
||||
</template>
|
||||
@@ -1,50 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { Link } from '@inertiajs/vue3';
|
||||
import AppLogoIcon from '@/components/AppLogoIcon.vue';
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@/components/ui/card';
|
||||
import { home } from '@/routes';
|
||||
|
||||
defineProps<{
|
||||
title?: string;
|
||||
description?: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex min-h-svh flex-col items-center justify-center gap-6 bg-muted p-6 md:p-10"
|
||||
>
|
||||
<div class="flex w-full max-w-md flex-col gap-6">
|
||||
<Link
|
||||
:href="home()"
|
||||
class="flex items-center gap-2 self-center font-medium"
|
||||
>
|
||||
<div class="flex h-9 w-9 items-center justify-center">
|
||||
<AppLogoIcon
|
||||
class="size-9 fill-current text-black dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
<Card class="rounded-xl">
|
||||
<CardHeader class="px-10 pt-8 pb-0 text-center">
|
||||
<CardTitle class="text-xl">{{ title }}</CardTitle>
|
||||
<CardDescription>
|
||||
{{ description }}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent class="px-10 py-8">
|
||||
<slot />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,43 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { Link } from '@inertiajs/vue3';
|
||||
import AppLogoIcon from '@/components/AppLogoIcon.vue';
|
||||
import { home } from '@/routes';
|
||||
|
||||
defineProps<{
|
||||
title?: string;
|
||||
description?: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex min-h-svh flex-col items-center justify-center gap-6 bg-background p-6 md:p-10"
|
||||
>
|
||||
<div class="w-full max-w-sm">
|
||||
<div class="flex flex-col gap-8">
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
<Link
|
||||
:href="home()"
|
||||
class="flex flex-col items-center gap-2 font-medium"
|
||||
>
|
||||
<div
|
||||
class="mb-1 flex h-9 w-9 items-center justify-center rounded-md"
|
||||
>
|
||||
<AppLogoIcon
|
||||
class="size-9 fill-current text-[var(--foreground)] dark:text-white"
|
||||
/>
|
||||
</div>
|
||||
<span class="sr-only">{{ title }}</span>
|
||||
</Link>
|
||||
<div class="space-y-2 text-center">
|
||||
<h1 class="text-xl font-medium">{{ title }}</h1>
|
||||
<p class="text-center text-sm text-muted-foreground">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,47 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { Link, usePage } from '@inertiajs/vue3';
|
||||
import AppLogoIcon from '@/components/AppLogoIcon.vue';
|
||||
import { home } from '@/routes';
|
||||
|
||||
const page = usePage();
|
||||
const name = page.props.name;
|
||||
|
||||
defineProps<{
|
||||
title?: string;
|
||||
description?: string;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="relative grid h-dvh flex-col items-center justify-center px-8 sm:px-0 lg:max-w-none lg:grid-cols-2 lg:px-0"
|
||||
>
|
||||
<div
|
||||
class="relative hidden h-full flex-col bg-muted p-10 text-white lg:flex dark:border-r"
|
||||
>
|
||||
<div class="absolute inset-0 bg-zinc-900" />
|
||||
<Link
|
||||
:href="home()"
|
||||
class="relative z-20 flex items-center text-lg font-medium"
|
||||
>
|
||||
<AppLogoIcon class="mr-2 size-8 fill-current text-white" />
|
||||
{{ name }}
|
||||
</Link>
|
||||
</div>
|
||||
<div class="lg:p-8">
|
||||
<div
|
||||
class="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]"
|
||||
>
|
||||
<div class="flex flex-col space-y-2 text-center">
|
||||
<h1 class="text-xl font-medium tracking-tight" v-if="title">
|
||||
{{ title }}
|
||||
</h1>
|
||||
<p class="text-sm text-muted-foreground" v-if="description">
|
||||
{{ description }}
|
||||
</p>
|
||||
</div>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -1,71 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
import { Link } from '@inertiajs/vue3';
|
||||
import Heading from '@/components/Heading.vue';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Separator } from '@/components/ui/separator';
|
||||
import { useCurrentUrl } from '@/composables/useCurrentUrl';
|
||||
import { toUrl } from '@/lib/utils';
|
||||
import { edit as editAppearance } from '@/routes/appearance';
|
||||
import { edit as editProfile } from '@/routes/profile';
|
||||
import { edit as editSecurity } from '@/routes/security';
|
||||
import type { NavItem } from '@/types';
|
||||
|
||||
const sidebarNavItems: NavItem[] = [
|
||||
{
|
||||
title: 'Profile',
|
||||
href: editProfile(),
|
||||
},
|
||||
{
|
||||
title: 'Security',
|
||||
href: editSecurity(),
|
||||
},
|
||||
{
|
||||
title: 'Appearance',
|
||||
href: editAppearance(),
|
||||
},
|
||||
];
|
||||
|
||||
const { isCurrentOrParentUrl } = useCurrentUrl();
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="px-4 py-6">
|
||||
<Heading
|
||||
title="Settings"
|
||||
description="Manage your profile and account settings"
|
||||
/>
|
||||
|
||||
<div class="flex flex-col lg:flex-row lg:space-x-12">
|
||||
<aside class="w-full max-w-xl lg:w-48">
|
||||
<nav
|
||||
class="flex flex-col space-y-1 space-x-0"
|
||||
aria-label="Settings"
|
||||
>
|
||||
<Button
|
||||
v-for="item in sidebarNavItems"
|
||||
:key="toUrl(item.href)"
|
||||
variant="ghost"
|
||||
:class="[
|
||||
'w-full justify-start',
|
||||
{ 'bg-muted': isCurrentOrParentUrl(item.href) },
|
||||
]"
|
||||
as-child
|
||||
>
|
||||
<Link :href="item.href">
|
||||
<component :is="item.icon" class="h-4 w-4" />
|
||||
{{ item.title }}
|
||||
</Link>
|
||||
</Button>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<Separator class="my-6 lg:hidden" />
|
||||
|
||||
<div class="flex-1 md:max-w-2xl">
|
||||
<section class="max-w-xl space-y-12">
|
||||
<slot />
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
Reference in New Issue
Block a user