Files
immich-folio/lib/siteNav.ts

53 lines
1.8 KiB
TypeScript
Raw Normal View History

/**
* The site's navigation entries, in the one order the header and the home
* page hero share (#696): subpages and content pages (gallery.yaml order),
* standalone albums, Journal, About, Map.
*
* Client-safe: callers do the fetching and pass the results in.
*/
import type { Dictionary } from './i18n';
import type { MenuItem } from './pages';
export interface SiteNavLink {
key: string;
href: string;
label: string;
/** "3 albums" / "12 photos" — only the hero shows it, and only presets that want it. */
count?: string;
}
export interface SiteNavInput {
/** Subpages and content pages, from `resolveMenu()`. */
menu: readonly MenuItem[];
/** Album count per subpage slug, for the hero's count line. */
subpageAlbumCounts?: ReadonlyMap<string, number>;
albums: ReadonlyArray<{ id: string; slug: string; albumName: string; assetCount?: number }>;
/** At least one published (non-draft) journal entry. */
hasJournal: boolean;
aboutEnabled: boolean;
map: boolean;
}
export function siteNavLinks(input: SiteNavInput, t: Dictionary): SiteNavLink[] {
const links: SiteNavLink[] = input.menu.map((item) => {
const n = input.subpageAlbumCounts?.get(item.href.slice(1));
return {
...item,
...(item.key.startsWith('sp-') && n !== undefined ? { count: t.common.albums(n) } : {}),
};
});
for (const a of input.albums) {
links.push({
key: `al-${a.id}`,
href: `/${a.slug}`,
label: a.albumName,
...(a.assetCount !== undefined ? { count: t.common.photos(a.assetCount) } : {}),
});
}
if (input.hasJournal) links.push({ key: 'journal', href: '/journal', label: t.nav.journal });
if (input.aboutEnabled) links.push({ key: 'about', href: '/about', label: t.nav.about });
if (input.map) links.push({ key: 'map', href: '/map', label: t.nav.map });
return links;
}