Add recipes to sidebar

This commit is contained in:
Sam Becker 2025-03-03 20:55:30 -08:00
parent d8ef5e290c
commit 5152c7e994
9 changed files with 54 additions and 9 deletions

View File

@ -28,6 +28,7 @@ export default async function GridPage() {
tags,
cameras,
simulations,
recipes,
] = await Promise.all([
getPhotosCached()
.catch(() => []),
@ -40,7 +41,7 @@ export default async function GridPage() {
return (
photos.length > 0
? <PhotoGridPage
{...{ photos, photosCount, tags, cameras, simulations }}
{...{ photos, photosCount, tags, cameras, simulations, recipes }}
/>
: <PhotosEmptyState />
);

View File

@ -34,6 +34,7 @@ export default async function HomePage() {
tags,
cameras,
simulations,
recipes,
] = await Promise.all([
getPhotosCached()
.catch(() => []),
@ -42,14 +43,14 @@ export default async function HomePage() {
.catch(() => 0),
...(GRID_HOMEPAGE_ENABLED
? getPhotoSidebarData()
: [[], [], []]),
: [[], [], [], []]),
]);
return (
photos.length > 0
? GRID_HOMEPAGE_ENABLED
? <PhotoGridPage
{...{ photos, photosCount, tags, cameras, simulations }}
{...{ photos, photosCount, tags, cameras, simulations, recipes }}
/>
: <PhotoFeedPage
{...{ photos, photosCount }}

View File

@ -33,7 +33,7 @@ export default function HeaderList({
)}
>
{icon &&
<span className="w-[1rem]">
<span className="text-icon w-[1rem]">
{icon}
</span>}
{title}

View File

@ -39,7 +39,7 @@ export default function RecipeImageResponse({
icon: <TbChecklist
size={height * .087}
style={{
transform: `translateY(${height * .006}px)`,
transform: `translateY(${height * .003}px)`,
marginRight: height * .02,
}}
/>,

View File

@ -10,6 +10,7 @@ import PhotoGridContainer from './PhotoGridContainer';
import { useEffect } from 'react';
import { useAppState } from '@/state/AppState';
import clsx from 'clsx/lite';
import { Recipes } from '@/recipe';
export default function PhotoGridPage({
photos,
@ -17,12 +18,14 @@ export default function PhotoGridPage({
tags,
cameras,
simulations,
recipes,
}: {
photos: Photo[]
photosCount: number
tags: Tags
cameras: Cameras
simulations: FilmSimulations
recipes: Recipes
}) {
const { setSelectedPhotoIds } = useAppState();
@ -63,6 +66,7 @@ export default function PhotoGridPage({
tags,
cameras,
simulations,
recipes,
photosCount,
}}
/>

View File

@ -21,17 +21,22 @@ import {
safelyParseFormattedHtml,
} from '@/utility/html';
import { clsx } from 'clsx/lite';
import { Recipes, sortRecipesWithCount } from '@/recipe';
import PhotoRecipe from '@/recipe/PhotoRecipe';
import { TbChecklist } from 'react-icons/tb';
export default function PhotoGridSidebar({
tags,
cameras,
simulations,
recipes,
photosCount,
photosDateRange,
}: {
tags: Tags
cameras: Cameras
simulations: FilmSimulations
recipes: Recipes
photosCount: number
photosDateRange?: PhotoDateRange
}) {
@ -48,7 +53,7 @@ export default function PhotoGridSidebar({
title='Tags'
icon={<FaTag
size={12}
className="text-icon translate-y-[1px]"
className="translate-y-[1px]"
/>}
items={tagsIncludingHidden.map(({ tag, count }) => {
switch (tag) {
@ -90,7 +95,7 @@ export default function PhotoGridSidebar({
title="Cameras"
icon={<IoMdCamera
size={13}
className="text-icon translate-y-[-0.25px]"
className="translate-y-[-0.25px]"
/>}
items={cameras
.sort(sortCamerasWithCount)
@ -108,6 +113,28 @@ export default function PhotoGridSidebar({
/>
: null;
const recipesContent = recipes.length > 0
? <HeaderList
title="Recipes"
icon={<TbChecklist
size={16}
className="translate-x-[-1px]"
/>}
items={recipes
.sort(sortRecipesWithCount)
.map(({ recipe, count }) =>
<PhotoRecipe
key={recipe}
recipe={recipe}
type="text-only"
countOnHover={count}
prefetch={false}
contrast="low"
badged
/>)}
/>
: null;
const filmsContent = simulations.length > 0
? <HeaderList
title="Films"
@ -161,6 +188,7 @@ export default function PhotoGridSidebar({
{SHOW_SIDEBAR_CAMERAS_FIRST
? <>{camerasContent}{tagsContent}</>
: <>{tagsContent}{camerasContent}</>}
{recipesContent}
{filmsContent}
{photoStatsContent}
</div>

View File

@ -6,9 +6,10 @@ import {
import {
getUniqueCameras,
getUniqueFilmSimulations,
getUniqueRecipes,
getUniqueTags,
} from '@/photo/db/query';
import { SHOW_FILM_SIMULATIONS } from '@/app/config';
import { SHOW_FILM_SIMULATIONS, SHOW_RECIPES } from '@/app/config';
import { sortTagsObject } from '@/tag';
export const getPhotoSidebarData = () => [
@ -17,6 +18,9 @@ export const getPhotoSidebarData = () => [
SHOW_FILM_SIMULATIONS
? getUniqueFilmSimulations().catch(() => [])
: [],
SHOW_RECIPES
? getUniqueRecipes().catch(() => [])
: [],
] as const;
export const getPhotoSidebarDataCached = () => [

View File

@ -51,7 +51,8 @@ export default function PhotoRecipe({
className={clsx(
'self-start',
'px-1 py-0.5',
'text-[10px] text-medium tracking-wider',
'text-[10px] text-main font-medium tracking-wider',
'translate-y-[0.5px]',
)}
>
{isOpen ? 'CLOSE' : 'RECIPE'}

View File

@ -63,3 +63,9 @@ export const generateMetaForRecipe = (
export const photoHasRecipe = (photo?: Photo) =>
photo?.filmSimulation && photo?.recipeData;
export const sortRecipesWithCount = (
a: RecipeWithCount,
b: RecipeWithCount,
) =>
a.recipe.localeCompare(b.recipe);