Cleanup
This commit is contained in:
7
apps/web/app/(marketing)/components/grid-list.tsx
Normal file
7
apps/web/app/(marketing)/components/grid-list.tsx
Normal file
@@ -0,0 +1,7 @@
|
||||
export function GridList({ children }: React.PropsWithChildren) {
|
||||
return (
|
||||
<div className="mb-16 grid grid-cols-1 gap-y-8 md:grid-cols-2 md:gap-x-8 md:gap-y-12 lg:grid-cols-3 lg:gap-x-12">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
132
apps/web/app/(marketing)/components/site-footer.tsx
Normal file
132
apps/web/app/(marketing)/components/site-footer.tsx
Normal file
@@ -0,0 +1,132 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
import { AppLogo } from '~/components/app-logo';
|
||||
import appConfig from '~/config/app.config';
|
||||
|
||||
const YEAR = new Date().getFullYear();
|
||||
|
||||
export function SiteFooter() {
|
||||
return (
|
||||
<footer className={'py-8 lg:py-24'}>
|
||||
<div className={'container mx-auto'}>
|
||||
<div className={'flex flex-col space-y-8 lg:flex-row lg:space-y-0'}>
|
||||
<div
|
||||
className={
|
||||
'flex w-full space-x-2 lg:w-4/12 xl:w-3/12' +
|
||||
' xl:space-x-6 2xl:space-x-8'
|
||||
}
|
||||
>
|
||||
<div className={'flex flex-col space-y-4'}>
|
||||
<div>
|
||||
<AppLogo className={'w-[85px] md:w-[115px]'} />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p className={'text-sm text-gray-500 dark:text-gray-400'}>
|
||||
Add a short tagline about your product
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={'flex text-xs text-gray-500 dark:text-gray-400'}>
|
||||
<p>
|
||||
© Copyright {YEAR} {appConfig.name}. All Rights Reserved.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={
|
||||
'flex flex-col space-y-8 lg:space-x-6 lg:space-y-0' +
|
||||
' xl:space-x-16 2xl:space-x-20' +
|
||||
' w-full lg:flex-row lg:justify-end'
|
||||
}
|
||||
>
|
||||
<div>
|
||||
<div className={'flex flex-col space-y-4'}>
|
||||
<FooterSectionHeading>About</FooterSectionHeading>
|
||||
|
||||
<FooterSectionList>
|
||||
<FooterLink>
|
||||
<Link href={'#'}>Who we are</Link>
|
||||
</FooterLink>
|
||||
<FooterLink>
|
||||
<Link href={'/blog'}>Blog</Link>
|
||||
</FooterLink>
|
||||
<FooterLink>
|
||||
<Link href={'/contact'}>Contact</Link>
|
||||
</FooterLink>
|
||||
</FooterSectionList>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className={'flex flex-col space-y-4'}>
|
||||
<FooterSectionHeading>Product</FooterSectionHeading>
|
||||
|
||||
<FooterSectionList>
|
||||
<FooterLink>
|
||||
<Link href={'/docs'}>Documentation</Link>
|
||||
</FooterLink>
|
||||
<FooterLink>
|
||||
<Link href={'#'}>Help Center</Link>
|
||||
</FooterLink>
|
||||
<FooterLink>
|
||||
<Link href={'#'}>Changelog</Link>
|
||||
</FooterLink>
|
||||
</FooterSectionList>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div className={'flex flex-col space-y-4'}>
|
||||
<FooterSectionHeading>Legal</FooterSectionHeading>
|
||||
|
||||
<FooterSectionList>
|
||||
<FooterLink>
|
||||
<Link href={'#'}>Terms of Service</Link>
|
||||
</FooterLink>
|
||||
<FooterLink>
|
||||
<Link href={'#'}>Privacy Policy</Link>
|
||||
</FooterLink>
|
||||
<FooterLink>
|
||||
<Link href={'#'}>Cookie Policy</Link>
|
||||
</FooterLink>
|
||||
</FooterSectionList>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
}
|
||||
|
||||
function FooterSectionHeading(props: React.PropsWithChildren) {
|
||||
return (
|
||||
<p>
|
||||
<span className={'font-semibold'}>{props.children}</span>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
function FooterSectionList(props: React.PropsWithChildren) {
|
||||
return (
|
||||
<ul className={'flex flex-col space-y-4 text-gray-500 dark:text-gray-400'}>
|
||||
{props.children}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
function FooterLink(props: React.PropsWithChildren) {
|
||||
return (
|
||||
<li
|
||||
className={
|
||||
'text-sm [&>a]:transition-colors [&>a]:hover:text-gray-800' +
|
||||
' dark:[&>a]:hover:text-white'
|
||||
}
|
||||
>
|
||||
{props.children}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
|
||||
import { ChevronRightIcon } from 'lucide-react';
|
||||
import pathsConfig from '~/config/paths.config';
|
||||
|
||||
import { PersonalAccountDropdown } from '@kit/accounts/personal-account-dropdown';
|
||||
import { useSignOut } from '@kit/supabase/hooks/use-sign-out';
|
||||
import { useUserSession } from '@kit/supabase/hooks/use-user-session';
|
||||
import { Button } from '@kit/ui/button';
|
||||
|
||||
export function SiteHeaderAccountSection() {
|
||||
const signOut = useSignOut();
|
||||
const userSession = useUserSession();
|
||||
|
||||
if (userSession.data) {
|
||||
return (
|
||||
<PersonalAccountDropdown
|
||||
session={userSession.data}
|
||||
paths={{
|
||||
home: pathsConfig.app.home,
|
||||
}}
|
||||
signOutRequested={() => signOut.mutateAsync()}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return <AuthButtons />;
|
||||
}
|
||||
|
||||
function AuthButtons() {
|
||||
return (
|
||||
<div className={'hidden space-x-2 lg:flex'}>
|
||||
<Button variant={'link'}>
|
||||
<Link href={pathsConfig.auth.signIn}>Sign In</Link>
|
||||
</Button>
|
||||
|
||||
<Link href={pathsConfig.auth.signUp}>
|
||||
<Button className={'rounded-full'}>
|
||||
Sign Up
|
||||
<ChevronRightIcon className={'h-4'} />
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
29
apps/web/app/(marketing)/components/site-header.tsx
Normal file
29
apps/web/app/(marketing)/components/site-header.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { SiteHeaderAccountSection } from '~/(marketing)/components/site-header-account-section';
|
||||
import { SiteNavigation } from '~/(marketing)/components/site-navigation';
|
||||
import { AppLogo } from '~/components/app-logo';
|
||||
|
||||
export function SiteHeader() {
|
||||
return (
|
||||
<div className={'container mx-auto'}>
|
||||
<div className="flex h-16 items-center justify-between">
|
||||
<div className={'w-4/12'}>
|
||||
<AppLogo />
|
||||
</div>
|
||||
|
||||
<div className={'hidden w-4/12 justify-center lg:flex'}>
|
||||
<SiteNavigation />
|
||||
</div>
|
||||
|
||||
<div className={'flex flex-1 items-center justify-end space-x-4'}>
|
||||
<div className={'flex items-center'}></div>
|
||||
|
||||
<SiteHeaderAccountSection />
|
||||
|
||||
<div className={'flex lg:hidden'}>
|
||||
<SiteNavigation />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
102
apps/web/app/(marketing)/components/site-navigation.tsx
Normal file
102
apps/web/app/(marketing)/components/site-navigation.tsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
import { MenuIcon } from 'lucide-react';
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from '@kit/ui/dropdown-menu';
|
||||
import {
|
||||
NavigationMenu,
|
||||
NavigationMenuItem,
|
||||
NavigationMenuList,
|
||||
} from '@kit/ui/navigation-menu';
|
||||
|
||||
const links = {
|
||||
SignIn: {
|
||||
label: 'Sign In',
|
||||
path: '/auth/sign-in',
|
||||
},
|
||||
Blog: {
|
||||
label: 'Blog',
|
||||
path: '/blog',
|
||||
},
|
||||
Docs: {
|
||||
label: 'Documentation',
|
||||
path: '/docs',
|
||||
},
|
||||
Pricing: {
|
||||
label: 'Pricing',
|
||||
path: '/pricing',
|
||||
},
|
||||
FAQ: {
|
||||
label: 'FAQ',
|
||||
path: '/faq',
|
||||
},
|
||||
};
|
||||
|
||||
export function SiteNavigation() {
|
||||
const className = `hover:underline text-sm`;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={'hidden items-center lg:flex'}>
|
||||
<NavigationMenu>
|
||||
<NavigationMenuList className={'space-x-2.5'}>
|
||||
<NavigationMenuItem>
|
||||
<Link className={className} href={links.Blog.path}>
|
||||
{links.Blog.label}
|
||||
</Link>
|
||||
</NavigationMenuItem>
|
||||
<NavigationMenuItem>
|
||||
<Link className={className} href={links.Docs.path}>
|
||||
{links.Docs.label}
|
||||
</Link>
|
||||
</NavigationMenuItem>
|
||||
<NavigationMenuItem>
|
||||
<Link className={className} href={links.Pricing.path}>
|
||||
{links.Pricing.label}
|
||||
</Link>
|
||||
</NavigationMenuItem>
|
||||
|
||||
<NavigationMenuItem>
|
||||
<Link className={className} href={links.FAQ.path}>
|
||||
{links.FAQ.label}
|
||||
</Link>
|
||||
</NavigationMenuItem>
|
||||
</NavigationMenuList>
|
||||
</NavigationMenu>
|
||||
</div>
|
||||
|
||||
<div className={'flex items-center lg:hidden'}>
|
||||
<MobileDropdown />
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function MobileDropdown() {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger aria-label={'Open Menu'}>
|
||||
<MenuIcon className={'h-9'} />
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent>
|
||||
{Object.values(links).map((item) => {
|
||||
const className = 'flex w-full h-full items-center';
|
||||
|
||||
return (
|
||||
<DropdownMenuItem key={item.path}>
|
||||
<Link className={className} href={item.path}>
|
||||
{item.label}
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
);
|
||||
})}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
}
|
||||
20
apps/web/app/(marketing)/components/site-page-header.tsx
Normal file
20
apps/web/app/(marketing)/components/site-page-header.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { Heading } from '@kit/ui/heading';
|
||||
import { cn } from '@kit/ui/utils';
|
||||
|
||||
export function SitePageHeader(props: {
|
||||
title: string;
|
||||
subtitle: string;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={cn('flex flex-col items-center space-y-2.5', props.className)}
|
||||
>
|
||||
<Heading level={1}>{props.title}</Heading>
|
||||
|
||||
<Heading level={2} className={'text-muted-foreground'}>
|
||||
<span className={'font-normal'}>{props.subtitle}</span>
|
||||
</Heading>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user