Refactor footer auth data handling

This commit is contained in:
Sam Becker 2024-01-06 13:50:15 -06:00
parent 1d179bd504
commit b77b4a3f61
13 changed files with 122 additions and 168 deletions

View File

@ -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} />
</>
);
}

View File

@ -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 />
</>
);
}

View File

@ -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
View File

@ -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>) => {

View File

@ -1,11 +0,0 @@
export default function PageContentContainer({
children,
}: {
children: React.ReactNode
}) {
return (
<div className="min-h-[16rem] sm:min-h-[30rem]">
{children}
</div>
);
}

View File

@ -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
View 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>
);
}

View File

@ -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
View 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>]
: []}
/>}
/>
);
}

View File

@ -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>}
/>
);
}

View File

@ -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)}

View File

@ -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'}
/>}

View File

@ -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