'use client'; import { ComponentProps, ReactNode, useTransition } from 'react'; import { useRouter } from 'next/navigation'; import { clsx } from 'clsx/lite'; import ChecklistRow from '../components/ChecklistRow'; import { FiExternalLink } from 'react-icons/fi'; import { BiCog, BiCopy, BiData, BiLockAlt, BiPencil, BiRefresh, } from 'react-icons/bi'; import IconButton from '@/components/IconButton'; import InfoBlock from '@/components/InfoBlock'; import Checklist from '@/components/Checklist'; import { toastSuccess } from '@/toast'; import { ConfigChecklistStatus } from './config'; import StatusIcon from '@/components/StatusIcon'; import { labelForStorage } from '@/services/storage'; export default function SiteChecklistClient({ hasPostgres, hasStorage, hasVercelBlobStorage, hasCloudflareR2Storage, hasAwsS3Storage, hasMultipleStorageProviders, currentStorage, hasAuth, hasAdminUser, hasTitle, hasDomain, showRepoLink, showFilmSimulations, showExifInfo, isProModeEnabled, isBlurEnabled, isGeoPrivacyEnabled, isPriorityOrderEnabled, isPublicApiEnabled, isOgTextBottomAligned, gridAspectRatio, showRefreshButton, secret, }: ConfigChecklistStatus & { showRefreshButton?: boolean secret: string }) { const router = useRouter(); const [isPendingPage, startTransitionPage] = useTransition(); const [isPendingSecret, startTransitionSecret] = useTransition(); const refreshPage = () => { startTransitionPage(router.refresh); }; const refreshSecret = () => { startTransitionSecret(router.refresh); }; const renderLink = (href: string, text: string, external = true) => <> {text} {external && <>   } ; const renderCopyButton = (label: string, text: string, subtle?: boolean) => } className={clsx(subtle && 'text-gray-300 dark:text-gray-700')} onClick={() => { navigator.clipboard.writeText(text); toastSuccess(`${label} copied to clipboard`); }} />; const renderEnvVar = (variable: string) =>
`{variable}` {renderCopyButton(variable, variable, true)}
; const renderEnvVars = (variables: string[]) =>
{variables.map(renderEnvVar)}
; const renderSubStatus = ( type: ComponentProps['type'], label: ReactNode, ) =>
{label}
; return (
} > {renderLink( // eslint-disable-next-line max-len 'https://vercel.com/docs/storage/vercel-postgres/quickstart#create-a-postgres-database', 'Create Vercel Postgres store', )} {' '} and connect to project {renderSubStatus( hasVercelBlobStorage ? 'checked' : 'optional', <> {labelForStorage('vercel-blob')}: {' '} {renderLink( // eslint-disable-next-line max-len 'https://vercel.com/docs/storage/vercel-blob/quickstart#create-a-blob-store', 'create store', )} {' '} and connect to project , )} {renderSubStatus( hasCloudflareR2Storage ? 'checked' : 'optional', <> {labelForStorage('cloudflare-r2')}: {' '} {renderLink( 'https://github.com/sambecker/exif-photo-blog#cloudflare-r2', 'create/configure bucket', )} )} {renderSubStatus( hasAwsS3Storage ? 'checked' : 'optional', <> {labelForStorage('aws-s3')}: {' '} {renderLink( 'https://github.com/sambecker/exif-photo-blog#aws-s3', 'create/configure bucket', )} )} } > Store auth secret in environment variable:
{secret}
{renderCopyButton('Secret', secret)} } onClick={refreshSecret} isLoading={isPendingSecret} spinnerColor="text" />
{renderEnvVars(['AUTH_SECRET'])}
Store admin email/password {' '} in environment variables: {renderEnvVars([ 'ADMIN_EMAIL', 'ADMIN_PASSWORD', ])}
} > Store in environment variable (used in page titles): {renderEnvVars(['NEXT_PUBLIC_SITE_TITLE'])} Store in environment variable (displayed in top-right nav): {renderEnvVars(['NEXT_PUBLIC_SITE_DOMAIN'])} } > Set environment variable to {'"1"'} to enable higher quality image storage: {renderEnvVars(['NEXT_PUBLIC_PRO_MODE'])} Set environment variable to {'"1"'} to prevent image blur data being stored and displayed {renderEnvVars(['NEXT_PUBLIC_BLUR_DISABLED'])} Set environment variable to {'"1"'} to disable collection/display of location-based data {renderEnvVars(['NEXT_PUBLIC_GEO_PRIVACY'])} Set environment variable to {'"1"'} to prevent priority order photo field affecting photo order {renderEnvVars(['NEXT_PUBLIC_IGNORE_PRIORITY_ORDER'])} Set environment variable to {'"1"'} to enable a public API available at /api: {renderEnvVars(['NEXT_PUBLIC_PUBLIC_API'])} Set environment variable to {'"1"'} to hide footer link: {renderEnvVars(['NEXT_PUBLIC_HIDE_REPO_LINK'])} Set environment variable to {'"1"'} to prevent simulations showing up in /grid sidebar: {renderEnvVars(['NEXT_PUBLIC_HIDE_FILM_SIMULATIONS'])} Set environment variable to {'"1"'} to hide EXIF data: {renderEnvVars(['NEXT_PUBLIC_HIDE_EXIF_DATA'])} Set environment variable to any number to enforce aspect ratio {' '} (defaults to {'"1"'}, i.e., square)—set to {'"0"'} to disable: {renderEnvVars(['NEXT_PUBLIC_GRID_ASPECT_RATIO'])} Set environment variable to {'"BOTTOM"'} to keep OG image text bottom aligned (default is top): {renderEnvVars(['NEXT_PUBLIC_OG_TEXT_ALIGNMENT'])} {showRefreshButton &&
}
Changes to environment variables require a redeploy or reboot of local dev server
); }