'use client'; import ScoreCard from '@/components/ScoreCard'; import ScoreCardRow from '@/components/ScoreCardRow'; import { dateRangeForPhotos } from '@/photo'; import PhotoFilmSimulationIcon from '@/simulation/PhotoFilmSimulationIcon'; import { FaCamera } from 'react-icons/fa'; import { FaTag } from 'react-icons/fa'; import { FaCircleInfo, FaRegCalendar } from 'react-icons/fa6'; import { HiOutlinePhotograph } from 'react-icons/hi'; import { MdAspectRatio } from 'react-icons/md'; import { PiWarningBold } from 'react-icons/pi'; import { TbCone, TbSparkles } from 'react-icons/tb'; import { BiGitBranch, BiGitCommit, BiLogoGithub } from 'react-icons/bi'; import { TEMPLATE_REPO_BRANCH, TEMPLATE_REPO_OWNER, TEMPLATE_REPO_NAME, VERCEL_GIT_COMMIT_SHA_SHORT, VERCEL_GIT_COMMIT_MESSAGE, TEMPLATE_REPO_URL_FORK, TEMPLATE_REPO_URL_README, } from '@/app/config'; import { AdminAppInsights, getGitHubMetaForCurrentApp, hasTemplateRecommendations, PhotoStats, } from '.'; import EnvVar from '@/components/EnvVar'; import { IoSyncCircle } from 'react-icons/io5'; import clsx from 'clsx/lite'; import { PATH_ADMIN_OUTDATED } from '@/app/paths'; import { LiaBroomSolid } from 'react-icons/lia'; import { IoMdGrid } from 'react-icons/io'; import { RiSpeedMiniLine } from 'react-icons/ri'; import AdminLink from '../AdminLink'; import AdminEmptyState from '../AdminEmptyState'; import { pluralize } from '@/utility/string'; import Tooltip from '@/components/Tooltip'; const DEBUG_COMMIT_SHA = '4cd29ed'; const DEBUG_COMMIT_MESSAGE = 'Long commit message for debugging purposes'; const DEBUG_BEHIND_BY = 9; const DEBUG_PHOTOS_COUNT_OUTDATED = 7; const readmeAnchor = (anchor: string) => README/{anchor} ; const renderLabeledEnvVar = (label: string, envVar: string, value = '1') =>
{label}
; const renderHighlightText = ( text: string, color: 'blue' | 'yellow' = 'blue', ) => {text} ; export default function AdminAppInsightsClient({ codeMeta, insights, photoStats: { photosCount, photosCountHidden, photosCountOutdated, tagsCount, camerasCount, filmSimulationsCount, focalLengthsCount, dateRange, }, debug, }: { codeMeta?: Awaited> insights: AdminAppInsights photoStats: PhotoStats debug?: boolean }) { const { noFork, forkBehind, noAi, noAiRateLimiting, outdatedPhotos, photoMatting, gridFirst, noStaticOptimization, } = insights; const { descriptionWithSpaces } = dateRangeForPhotos(undefined, dateRange); const branchLink = {codeMeta?.branch ?? TEMPLATE_REPO_BRANCH} ; return (
{(codeMeta || debug) && <> {codeMeta?.didError ? } content={<> Could not analyze source code } /> : <> {(noFork || debug) && } content="This template is not forked" expandContent={<> Fork original template {' '} to receive the latest fixes and features. {' '} Additional instructions in {' '} {readmeAnchor('receiving-updates')}. } />} {(forkBehind || debug) && } content={<> This fork is {' '} {renderHighlightText( pluralize(codeMeta?.behindBy ?? DEBUG_BEHIND_BY, 'commit'), 'blue', )} {' '} behind } expandContent={<> Sync your fork {' '} to receive the latest fixes and features. } />} } } content={} /> } content={branchLink} /> } content={ {VERCEL_GIT_COMMIT_SHA_SHORT ?? DEBUG_COMMIT_SHA} {VERCEL_GIT_COMMIT_MESSAGE ?? DEBUG_COMMIT_MESSAGE} } /> } {(hasTemplateRecommendations(insights) || debug) ? <> {(noAiRateLimiting || debug) && } content={renderHighlightText( 'AI enabled without rate limiting', 'yellow', )} expandContent={<> Create Upstash Redis store from storage tab on Vercel dashboard and link to this project to prevent abuse by enabling rate limiting. } />} {(noStaticOptimization || debug) && } content="Speed up page load times" expandContent={<> Improve load times by enabling static optimization {' '} on:
{renderLabeledEnvVar( 'Photo pages', 'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTOS', )} {renderLabeledEnvVar( 'Photo OG images', 'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_OG_IMAGES', )} {renderLabeledEnvVar( 'Category pages (tags, cameras, etc.)', 'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_CATEGORIES', )} {renderLabeledEnvVar( 'Category OG images', 'NEXT_PUBLIC_STATICALLY_OPTIMIZE_PHOTO_CATEGORY_OG_IMAGES', )} See {readmeAnchor('performance')} for cost implications.
} />} {(noAi || debug) && } content="Improve SEO + accessibility with AI" expandContent={<> Enable automatic AI text generation {' '} by setting . {' '} Further instruction and cost considerations in {' '} {readmeAnchor('ai-text-generation')}. } />} {(photoMatting || debug) && } content="Vertical photos may benefit from matting" expandContent={<> Enable photo matting to make {' '} portrait and landscape photos appear more consistent {' '} . } />} {(gridFirst || debug) && } content="Grid homepage" expandContent={<> Now that you have enough photos, consider switching your {' '} default view to grid by setting {' '} {/* eslint-disable-next-line max-len */} . } />} : Nothing to report! }
{(outdatedPhotos || debug) && } content={renderHighlightText( // eslint-disable-next-line max-len pluralize(photosCountOutdated || DEBUG_PHOTOS_COUNT_OUTDATED, 'outdated photo'), 'yellow', )} expandPath={PATH_ADMIN_OUTDATED} />} } content={<> {pluralize(photosCount, 'photo')} {photosCountHidden > 0 && ` (${photosCountHidden} hidden)`} } /> } content={pluralize(tagsCount, 'tag')} /> } content={pluralize(camerasCount, 'camera')} /> {filmSimulationsCount > 0 && } content={pluralize(filmSimulationsCount, 'film simulation')} />} } content={pluralize(focalLengthsCount, 'focal length')} /> {descriptionWithSpaces && } content={descriptionWithSpaces} />}
); }