Sort categories by count

This commit is contained in:
Sam Becker 2025-03-23 12:02:57 -05:00
parent 6c967b9970
commit 7c3db85600
4 changed files with 60 additions and 55 deletions

View File

@ -14,6 +14,7 @@ import {
SHOW_RECIPES, SHOW_RECIPES,
} from './config'; } from './config';
import { getUniqueFocalLengths } from '@/photo/db/query'; import { getUniqueFocalLengths } from '@/photo/db/query';
import { sortCategoryByCount } from '@/category';
export default async function CommandK() { export default async function CommandK() {
const [ const [
@ -41,12 +42,12 @@ export default async function CommandK() {
]); ]);
return <CommandKClient return <CommandKClient
cameras={cameras} cameras={cameras.sort(sortCategoryByCount)}
lenses={lenses} lenses={lenses.sort(sortCategoryByCount)}
tags={tags} tags={tags.sort(sortCategoryByCount)}
simulations={filmSimulations} simulations={filmSimulations.sort(sortCategoryByCount)}
recipes={recipes} recipes={recipes.sort(sortCategoryByCount)}
focalLengths={focalLengths} focalLengths={focalLengths.sort(sortCategoryByCount)}
showDebugTools={ADMIN_DEBUG_TOOLS_ENABLED} showDebugTools={ADMIN_DEBUG_TOOLS_ENABLED}
footer={photoQuantityText(count, false)} footer={photoQuantityText(count, false)}
/>; />;

View File

@ -66,3 +66,8 @@ export const getOrderedCategoriesFromString = (
.map(category => category.trim().toLocaleLowerCase() as CategoryKey) .map(category => category.trim().toLocaleLowerCase() as CategoryKey)
.filter(category => CATEGORY_KEYS.includes(category)) .filter(category => CATEGORY_KEYS.includes(category))
: DEFAULT_CATEGORY_KEYS; : DEFAULT_CATEGORY_KEYS;
export const sortCategoryByCount = (
a: { count: number },
b: { count: number },
) => b.count - a.count;

View File

@ -1,13 +1,11 @@
'use client'; 'use client';
import { sortCamerasWithCount } from '@/camera';
import PhotoCamera from '@/camera/PhotoCamera'; import PhotoCamera from '@/camera/PhotoCamera';
import HeaderList from '@/components/HeaderList'; import HeaderList from '@/components/HeaderList';
import PhotoTag from '@/tag/PhotoTag'; import PhotoTag from '@/tag/PhotoTag';
import { PhotoDateRange, dateRangeForPhotos, photoQuantityText } from '.'; import { PhotoDateRange, dateRangeForPhotos, photoQuantityText } from '.';
import { TAG_FAVS, TAG_HIDDEN, addHiddenToTags } from '@/tag'; import { TAG_FAVS, TAG_HIDDEN, addHiddenToTags } from '@/tag';
import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation'; import PhotoFilmSimulation from '@/simulation/PhotoFilmSimulation';
import { sortFilmSimulationsWithCount } from '@/simulation';
import FavsTag from '../tag/FavsTag'; import FavsTag from '../tag/FavsTag';
import { useAppState } from '@/state/AppState'; import { useAppState } from '@/state/AppState';
import { useMemo } from 'react'; import { useMemo } from 'react';
@ -18,17 +16,15 @@ import {
safelyParseFormattedHtml, safelyParseFormattedHtml,
} from '@/utility/html'; } from '@/utility/html';
import { clsx } from 'clsx/lite'; import { clsx } from 'clsx/lite';
import { sortRecipesWithCount } from '@/recipe';
import PhotoRecipe from '@/recipe/PhotoRecipe'; import PhotoRecipe from '@/recipe/PhotoRecipe';
import IconCamera from '@/components/icons/IconCamera'; import IconCamera from '@/components/icons/IconCamera';
import IconRecipe from '@/components/icons/IconRecipe'; import IconRecipe from '@/components/icons/IconRecipe';
import IconTag from '@/components/icons/IconTag'; import IconTag from '@/components/icons/IconTag';
import IconFilmSimulation from '@/components/icons/IconFilmSimulation'; import IconFilmSimulation from '@/components/icons/IconFilmSimulation';
import IconLens from '@/components/icons/IconLens'; import IconLens from '@/components/icons/IconLens';
import { sortLensesWithCount } from '@/lens';
import PhotoLens from '@/lens/PhotoLens'; import PhotoLens from '@/lens/PhotoLens';
import IconFocalLength from '@/components/icons/IconFocalLength'; import IconFocalLength from '@/components/icons/IconFocalLength';
import { PhotoSetCategories } from '@/category'; import { PhotoSetCategories, sortCategoryByCount } from '@/category';
import PhotoFocalLength from '@/focal/PhotoFocalLength'; import PhotoFocalLength from '@/focal/PhotoFocalLength';
export default function PhotoGridSidebar({ export default function PhotoGridSidebar({
@ -61,7 +57,7 @@ export default function PhotoGridSidebar({
className="translate-x-[0.5px]" className="translate-x-[0.5px]"
/>} />}
items={cameras items={cameras
.sort(sortCamerasWithCount) .sort(sortCategoryByCount)
.map(({ cameraKey, camera, count }) => .map(({ cameraKey, camera, count }) =>
<PhotoCamera <PhotoCamera
key={cameraKey} key={cameraKey}
@ -82,7 +78,7 @@ export default function PhotoGridSidebar({
title="Lenses" title="Lenses"
icon={<IconLens size={15} />} icon={<IconLens size={15} />}
items={lenses items={lenses
.sort(sortLensesWithCount) .sort(sortCategoryByCount)
.map(({ lensKey, lens, count }) => .map(({ lensKey, lens, count }) =>
<PhotoLens <PhotoLens
key={lensKey} key={lensKey}
@ -104,38 +100,39 @@ export default function PhotoGridSidebar({
size={14} size={14}
className="translate-x-[1px] translate-y-[1px]" className="translate-x-[1px] translate-y-[1px]"
/>} />}
items={tagsIncludingHidden.map(({ tag, count }) => { items={tagsIncludingHidden
switch (tag) { .map(({ tag, count }) => {
case TAG_FAVS: switch (tag) {
return <FavsTag case TAG_FAVS:
key={TAG_FAVS} return <FavsTag
countOnHover={count} key={TAG_FAVS}
type="icon-last" countOnHover={count}
prefetch={false} type="icon-last"
contrast="low" prefetch={false}
badged contrast="low"
/>; badged
case TAG_HIDDEN: />;
return <HiddenTag case TAG_HIDDEN:
key={TAG_HIDDEN} return <HiddenTag
countOnHover={count} key={TAG_HIDDEN}
type="icon-last" countOnHover={count}
prefetch={false} type="icon-last"
contrast="low" prefetch={false}
badged contrast="low"
/>; badged
default: />;
return <PhotoTag default:
key={tag} return <PhotoTag
tag={tag} key={tag}
type="text-only" tag={tag}
countOnHover={count} type="text-only"
prefetch={false} countOnHover={count}
contrast="low" prefetch={false}
badged contrast="low"
/>; badged
} />;
})} }
})}
/> />
: null; : null;
@ -147,7 +144,8 @@ export default function PhotoGridSidebar({
size={16} size={16}
className="translate-x-[-1px]" className="translate-x-[-1px]"
/>} />}
items={sortRecipesWithCount(recipes) items={recipes
.sort(sortCategoryByCount)
.map(({ recipe, count }) => .map(({ recipe, count }) =>
<PhotoRecipe <PhotoRecipe
key={recipe} key={recipe}
@ -167,7 +165,7 @@ export default function PhotoGridSidebar({
title="Films" title="Films"
icon={<IconFilmSimulation size={15} />} icon={<IconFilmSimulation size={15} />}
items={simulations items={simulations
.sort(sortFilmSimulationsWithCount) .sort(sortCategoryByCount)
.map(({ simulation, count }) => .map(({ simulation, count }) =>
<PhotoFilmSimulation <PhotoFilmSimulation
key={simulation} key={simulation}

View File

@ -15,6 +15,7 @@ import {
formatCount, formatCount,
formatCountDescriptive, formatCountDescriptive,
} from '@/utility/string'; } from '@/utility/string';
import { sortCategoryByCount } from '@/category';
// Reserved tags // Reserved tags
export const TAG_FAVS = 'favs'; export const TAG_FAVS = 'favs';
@ -105,16 +106,16 @@ export const isPathFavs = (pathname?: string) =>
export const isTagHidden = (tag: string) => tag.toLowerCase() === TAG_HIDDEN; export const isTagHidden = (tag: string) => tag.toLowerCase() === TAG_HIDDEN;
export const addHiddenToTags = (tags: Tags, photosCountHidden = 0) => { export const addHiddenToTags = (tags: Tags, photosCountHidden = 0) =>
if (photosCountHidden > 0) { photosCountHidden > 0
return tags ? tags
.filter(({ tag }) => tag === TAG_FAVS) .filter(({ tag }) => tag === TAG_FAVS)
.concat({ tag: TAG_HIDDEN, count: photosCountHidden }) .concat({ tag: TAG_HIDDEN, count: photosCountHidden })
.concat(tags.filter(({ tag }) => tag !== TAG_FAVS)); .concat(tags
} else { .filter(({ tag }) => tag !== TAG_FAVS)
return tags; .sort(sortCategoryByCount),
} )
}; : tags;
export const convertTagsForForm = (tags: Tags = []) => export const convertTagsForForm = (tags: Tags = []) =>
sortTagsObjectWithoutFavs(tags) sortTagsObjectWithoutFavs(tags)