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