Refactor footer auth data handling
This commit is contained in:
parent
1d179bd504
commit
b77b4a3f61
@ -1,19 +0,0 @@
|
||||
import FooterAuth from '@/site/FooterAuth';
|
||||
import PageContentContainer from '@/components/PageContentContainer';
|
||||
import { auth } from '@/auth';
|
||||
|
||||
export default async function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const session = await auth();
|
||||
return (
|
||||
<>
|
||||
<PageContentContainer>
|
||||
{children}
|
||||
</PageContentContainer>
|
||||
<FooterAuth email={session?.user?.email} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
import FooterStatic from '@/site/FooterStatic';
|
||||
import PageContentContainer from '@/components/PageContentContainer';
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<>
|
||||
<PageContentContainer>
|
||||
{children}
|
||||
</PageContentContainer>
|
||||
<FooterStatic />
|
||||
</>
|
||||
);
|
||||
}
|
||||
@ -9,6 +9,7 @@ import ThemeProviderClient from '@/site/ThemeProviderClient';
|
||||
import Nav from '@/site/Nav';
|
||||
import ToasterWithThemes from '@/toast/ToasterWithThemes';
|
||||
import PhotoEscapeHandler from '@/photo/PhotoEscapeHandler';
|
||||
import Footer from '@/site/Footer';
|
||||
|
||||
import '../site/globals.css';
|
||||
|
||||
@ -68,21 +69,27 @@ export default function RootLayout({
|
||||
suppressHydrationWarning
|
||||
>
|
||||
<body className={ibmPlexMono.variable}>
|
||||
<ThemeProviderClient>
|
||||
<main className={clsx(
|
||||
'px-3 pb-3',
|
||||
'lg:px-6 lg:pb-6',
|
||||
)}>
|
||||
<Nav />
|
||||
<StateProvider>
|
||||
{children}
|
||||
</StateProvider>
|
||||
<Analytics />
|
||||
<SpeedInsights />
|
||||
</main>
|
||||
<PhotoEscapeHandler />
|
||||
<ToasterWithThemes />
|
||||
</ThemeProviderClient>
|
||||
<StateProvider>
|
||||
<ThemeProviderClient>
|
||||
<main className={clsx(
|
||||
'mx-3 mb-3',
|
||||
'lg:mx-6 lg:mb-6',
|
||||
)}>
|
||||
<Nav />
|
||||
<div className={clsx(
|
||||
'min-h-[16rem] sm:min-h-[30rem]',
|
||||
'mb-12',
|
||||
)}>
|
||||
{children}
|
||||
</div>
|
||||
<Footer />
|
||||
</main>
|
||||
</ThemeProviderClient>
|
||||
</StateProvider>
|
||||
<Analytics />
|
||||
<SpeedInsights />
|
||||
<PhotoEscapeHandler />
|
||||
<ToasterWithThemes />
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
|
||||
4
src/cache/index.ts
vendored
4
src/cache/index.ts
vendored
@ -28,6 +28,8 @@ import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/blob';
|
||||
import type { Session } from 'next-auth';
|
||||
import { createCameraKey } from '@/camera';
|
||||
import { PATHS_ADMIN } from '@/site/paths';
|
||||
import { cache } from 'react';
|
||||
import { auth } from '@/auth';
|
||||
|
||||
// Table key
|
||||
const KEY_PHOTOS = 'photos';
|
||||
@ -207,6 +209,8 @@ export const getUniqueFilmSimulationsCached =
|
||||
[KEY_PHOTOS, KEY_FILM_SIMULATIONS],
|
||||
);
|
||||
|
||||
export const authCached = cache(auth);
|
||||
|
||||
// No Store
|
||||
|
||||
export const getPhotoNoStore = (...args: Parameters<typeof getPhoto>) => {
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
export default function PageContentContainer({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<div className="min-h-[16rem] sm:min-h-[30rem]">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -12,12 +12,15 @@ export default function RepoLink() {
|
||||
href="http://github.com/sambecker/exif-photo-blog"
|
||||
target="_blank"
|
||||
className={clsx(
|
||||
'flex items-center gap-1',
|
||||
'text-black dark:text-white',
|
||||
'flex items-center gap-0.5',
|
||||
'text-main hover:text-main',
|
||||
'hover:underline',
|
||||
)}
|
||||
>
|
||||
<BiLogoGithub className="translate-y-[1px] hidden xs:inline-block" />
|
||||
<BiLogoGithub
|
||||
size={16}
|
||||
className="translate-y-[0.5px] hidden xs:inline-block"
|
||||
/>
|
||||
exif-photo-blog
|
||||
</Link>
|
||||
</span>
|
||||
|
||||
12
src/site/Footer.tsx
Normal file
12
src/site/Footer.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
import FooterClient from './FooterClient';
|
||||
import { Suspense } from 'react';
|
||||
import { authCached } from '@/cache';
|
||||
|
||||
export default async function Footer() {
|
||||
const session = await authCached();
|
||||
return (
|
||||
<Suspense fallback={<FooterClient />}>
|
||||
<FooterClient userEmail={session?.user?.email} />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { clsx } from 'clsx/lite';
|
||||
import ThemeSwitcher from '@/site/ThemeSwitcher';
|
||||
import SiteGrid from '../components/SiteGrid';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { isPathSignIn } from '@/site/paths';
|
||||
import { signOutAction } from '@/auth/action';
|
||||
import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus';
|
||||
|
||||
const LINK_STYLE = clsx(
|
||||
'cursor-pointer',
|
||||
'hover:text-gray-300',
|
||||
'hover:dark:text-gray-600',
|
||||
);
|
||||
|
||||
export default function FooterAuth({
|
||||
email,
|
||||
}: {
|
||||
email: string | null | undefined
|
||||
}) {
|
||||
const path = usePathname();
|
||||
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={<div className={clsx(
|
||||
'flex items-center',
|
||||
'my-8',
|
||||
'text-dim',
|
||||
)}>
|
||||
<div className="flex gap-x-4 gap-y-1 flex-wrap items-center flex-grow">
|
||||
<div>{email}</div>
|
||||
<form action={signOutAction}>
|
||||
<SubmitButtonWithStatus
|
||||
className={LINK_STYLE}
|
||||
styleAsLink
|
||||
>
|
||||
Sign Out
|
||||
</SubmitButtonWithStatus>
|
||||
</form>
|
||||
</div>
|
||||
{!isPathSignIn(path) && <ThemeSwitcher />}
|
||||
</div>}
|
||||
/>
|
||||
);
|
||||
};
|
||||
70
src/site/FooterClient.tsx
Normal file
70
src/site/FooterClient.tsx
Normal file
@ -0,0 +1,70 @@
|
||||
'use client';
|
||||
|
||||
import { clsx } from 'clsx/lite';
|
||||
import SiteGrid from '../components/SiteGrid';
|
||||
import ThemeSwitcher from '@/site/ThemeSwitcher';
|
||||
import Link from 'next/link';
|
||||
import { SHOW_REPO_LINK } from '@/site/config';
|
||||
import RepoLink from '../components/RepoLink';
|
||||
import { usePathname } from 'next/navigation';
|
||||
import { isPathAdmin, isPathSignIn, pathForAdminPhotos } from './paths';
|
||||
import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus';
|
||||
import { signOutAction } from '@/auth/action';
|
||||
import Spinner from '@/components/Spinner';
|
||||
import AnimateItems from '@/components/AnimateItems';
|
||||
|
||||
export default function FooterClient({
|
||||
userEmail,
|
||||
}: {
|
||||
userEmail?: string | null | undefined
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
|
||||
const showFooter = !isPathSignIn(pathname);
|
||||
|
||||
const shouldAnimate = !isPathAdmin(pathname);
|
||||
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={
|
||||
<AnimateItems
|
||||
type={!shouldAnimate ? 'none' : 'bottom'}
|
||||
distanceOffset={10}
|
||||
items={showFooter
|
||||
? [<div
|
||||
key="footer"
|
||||
className={clsx(
|
||||
'flex items-center',
|
||||
'text-dim min-h-[4rem]',
|
||||
)}>
|
||||
<div className="flex gap-x-4 gap-y-1 flex-grow flex-wrap h-4">
|
||||
{isPathAdmin(pathname)
|
||||
? <>
|
||||
{userEmail === undefined &&
|
||||
<Spinner />}
|
||||
{userEmail && <>
|
||||
<div>{userEmail}</div>
|
||||
<form action={signOutAction}>
|
||||
<SubmitButtonWithStatus styleAsLink>
|
||||
Sign out
|
||||
</SubmitButtonWithStatus>
|
||||
</form>
|
||||
</>}
|
||||
</>
|
||||
: <>
|
||||
<Link href={pathForAdminPhotos()}>
|
||||
Admin
|
||||
</Link>
|
||||
{SHOW_REPO_LINK &&
|
||||
<RepoLink />}
|
||||
</>}
|
||||
</div>
|
||||
<div className="flex items-center h-4">
|
||||
<ThemeSwitcher />
|
||||
</div>
|
||||
</div>]
|
||||
: []}
|
||||
/>}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { clsx } from 'clsx/lite';
|
||||
import SiteGrid from '../components/SiteGrid';
|
||||
import ThemeSwitcher from '@/site/ThemeSwitcher';
|
||||
import { signOut } from 'next-auth/react';
|
||||
import Link from 'next/link';
|
||||
import { SHOW_REPO_LINK } from '@/site/config';
|
||||
import RepoLink from '../components/RepoLink';
|
||||
|
||||
export default function FooterStatic({
|
||||
showSignOut,
|
||||
}: {
|
||||
showSignOut?: boolean
|
||||
}) {
|
||||
return (
|
||||
<SiteGrid
|
||||
contentMain={<div className={clsx(
|
||||
'my-8',
|
||||
'flex items-center',
|
||||
'text-dim',
|
||||
)}>
|
||||
<div className="flex gap-x-4 gap-y-1 flex-grow flex-wrap">
|
||||
<Link
|
||||
href="/admin/photos"
|
||||
className="hover:text-gray-600 dark:hover:text-gray-400"
|
||||
>
|
||||
Admin
|
||||
</Link>
|
||||
{SHOW_REPO_LINK &&
|
||||
<RepoLink />}
|
||||
{showSignOut &&
|
||||
<div
|
||||
className={clsx(
|
||||
'cursor-pointer',
|
||||
'hover:text-gray-600 dark:hover:text-gray-400',
|
||||
)}
|
||||
onClick={() => signOut()}
|
||||
>
|
||||
Sign out
|
||||
</div>}
|
||||
</div>
|
||||
<ThemeSwitcher />
|
||||
</div>}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@ -7,7 +7,6 @@ import SiteGrid from '../components/SiteGrid';
|
||||
import { SITE_DOMAIN_OR_TITLE } from '@/site/config';
|
||||
import ViewSwitcher, { SwitcherSelection } from '@/site/ViewSwitcher';
|
||||
import {
|
||||
PATH_ADMIN,
|
||||
PATH_ROOT,
|
||||
isPathAdmin,
|
||||
isPathGrid,
|
||||
@ -17,9 +16,7 @@ import {
|
||||
} from '@/site/paths';
|
||||
import AnimateItems from '../components/AnimateItems';
|
||||
|
||||
export default function Nav({ showTextLinks }: { showTextLinks?: boolean }) {
|
||||
const isLoggedIn = false;
|
||||
|
||||
export default function Nav() {
|
||||
const pathname = usePathname();
|
||||
|
||||
const showNav = !isPathSignIn(pathname);
|
||||
@ -63,12 +60,8 @@ export default function Nav({ showTextLinks }: { showTextLinks?: boolean }) {
|
||||
<div className="flex flex-grow items-center gap-4">
|
||||
<ViewSwitcher
|
||||
currentSelection={switcherSelectionForPath()}
|
||||
showAdmin={isLoggedIn}
|
||||
showAdmin={true}
|
||||
/>
|
||||
{showTextLinks && <>
|
||||
{renderLink('Home', PATH_ROOT)}
|
||||
{renderLink('Admin', PATH_ADMIN)}
|
||||
</>}
|
||||
</div>
|
||||
<div className="hidden xs:block">
|
||||
{renderLink(SITE_DOMAIN_OR_TITLE, PATH_ROOT)}
|
||||
|
||||
@ -38,7 +38,7 @@ export default function ViewSwitcher({
|
||||
/>
|
||||
{showAdmin &&
|
||||
<SwitcherItem
|
||||
icon={<BiLockAlt size={15} className="-translate-y-[1px]" />}
|
||||
icon={<BiLockAlt size={16} className="translate-y-[-0.5px]" />}
|
||||
href="/admin/photos"
|
||||
active={currentSelection === 'admin'}
|
||||
/>}
|
||||
|
||||
@ -107,6 +107,11 @@
|
||||
p-0 min-h-0
|
||||
border-none active:bg-transparent shadow-none
|
||||
}
|
||||
a, .link {
|
||||
@apply
|
||||
hover:text-gray-600
|
||||
hover:dark:text-gray-400
|
||||
}
|
||||
/* Common Utilities */
|
||||
.text-main {
|
||||
@apply
|
||||
|
||||
Loading…
Reference in New Issue
Block a user