Improve song lists

This commit is contained in:
Maciej Jur 2023-04-26 22:48:15 +02:00
parent 8cddb5706e
commit e089245be2
11 changed files with 127 additions and 23 deletions

View file

@ -29,10 +29,13 @@ export const collections = {
songs: defineCollection({ songs: defineCollection({
schema: z.object({ schema: z.object({
title: z.string(), title: z.string(),
composer: z.string().optional(),
lyrics: z.string().optional(),
album: z.record( album: z.record(
z.string(), z.string(),
z.object({ z.object({
track: z.number() track: z.number(),
vocal: z.array(z.string()).optional()
}) })
) )
}) })

View file

@ -1,8 +1,12 @@
--- ---
title: Black Eyes title: Black Eyes
composer: Kirin (EastNewSound)
lyrics: Mei Ayakura
album: album:
ARCD0051: ARCD0051:
track: 7 track: 7
vocal:
- Mei Ayakura
--- ---
{% lyrics %} {% lyrics %}

9
src/data/circles.json Normal file
View file

@ -0,0 +1,9 @@
{
"Alstroemeria Records": {
"albums": {
"ARCD0051": {
"title": "Engaged Dancehall"
}
}
}
}

View file

@ -1,6 +1,7 @@
--- ---
import Lyrics from "../../layouts/Lyrics.astro"; import Base from "../../layouts/Base.astro";
import { getCollection } from "astro:content"; import Header from '../../components/headers/Base.astro';
import { CollectionEntry, getCollection } from "astro:content";
export async function getStaticPaths() { export async function getStaticPaths() {
return (await getCollection('songs')) return (await getCollection('songs'))
@ -9,10 +10,20 @@ export async function getStaticPaths() {
.flat() .flat()
} }
interface Props {
song: CollectionEntry<'songs'>;
}
const { song } = Astro.props; const { song } = Astro.props;
const { Content } = await song.render(); const { Content } = await song.render();
--- ---
<Lyrics frontmatter={song.data}> <Base>
<Content /> <main class="l-songs-song">
</Lyrics> <article class="l-songs-song__page">
<Header title={song.data.title} />
<Content />
</article>
</main>
</Base>

View file

@ -1,7 +1,8 @@
--- ---
import List from "../../layouts/List.astro"; import Base from "../../layouts/Base.astro";
import { getCollection } from 'astro:content'; import Header from '../../components/headers/Base.astro';
import { getAllCats } from "../../utils/songs"; import { CollectionEntry, getCollection } from 'astro:content';
import { ALBUMS, getAllCats } from "../../utils/songs";
export async function getStaticPaths() { export async function getStaticPaths() {
@ -13,12 +14,33 @@ export async function getStaticPaths() {
props: { props: {
songs: songs songs: songs
.filter(entry => cat in entry.data.album) .filter(entry => cat in entry.data.album)
.map(song => ({ title: song.data.title, slug: `/songs/${cat}/${song.slug}/` })) } .map(song => ({ frontmatter: song.data, slug: `/songs/${cat}/${song.slug}/` }))
}
})) }))
} }
interface Props {
songs: Array<{
frontmatter: CollectionEntry<'songs'>['data'],
slug: string,
}>
}
const { cat } = Astro.params; const { cat } = Astro.params;
const { songs } = Astro.props; const { songs } = Astro.props;
const album = ALBUMS[cat!];
--- ---
<List title={cat!} pages={songs} /> <Base>
<main class="l-songs-cat">
<article class="l-songs-cat__article">
<Header title={`${cat} - ${album.title}`} />
<div class="l-songs-cat__list">
{songs.map(song => [
<span>{song.frontmatter.album[cat!].track}</span>
<a href={song.slug}>{song.frontmatter.title}</a>
])}
</div>
</article>
</main>
</Base>

View file

@ -1,13 +1,16 @@
--- ---
import List from "../../layouts/List.astro"; import List from "../../layouts/List.astro";
import { getCollection } from 'astro:content'; import { getCollection } from 'astro:content';
import { getAllCats } from "../../utils/songs"; import { ALBUMS, getAllCats } from "../../utils/songs";
const pages = [...getAllCats(await getCollection('songs'))] const pages = [...getAllCats(await getCollection('songs'))]
.sort((a, b) => a < b ? 1 : -1) .sort((a, b) => a < b ? 1 : -1)
.map(catalog => ({ title: catalog, slug: `/songs/${catalog}/` })); .map(catalog => ({
title: `${catalog} - ${ALBUMS[catalog].title}`,
slug: `/songs/${catalog}/`
}));
--- ---
<List title="Songs" pages={pages} /> <List title="Albums" pages={pages} />

12
src/schema.d.ts vendored Normal file
View file

@ -0,0 +1,12 @@
/** @file src/data/circles.json */
interface CirclesSchema {
/** Circle name */
[key: string]: {
albums: {
/** Catalog number */
[key: string]: {
title: string;
}
}
}
}

View file

@ -1,8 +0,0 @@
.l-lyrics {
display: flex;
padding: 2em 0;
&__page {
margin: 0 auto;
}
}

View file

@ -0,0 +1,23 @@
.l-songs-cat {
padding: 1.5em;
&__article {
max-width: 40em;
margin: 0 auto;
}
&__list {
display: grid;
grid-template-columns: 3em 1fr;
}
}
.l-songs-song {
padding: 1.5em;
&__page {
max-width: 40em;
margin: 0 auto;
}
}

View file

@ -32,4 +32,4 @@
@use 'layouts/home'; @use 'layouts/home';
@use 'layouts/pages'; @use 'layouts/pages';
@use 'layouts/article'; @use 'layouts/article';
@use 'layouts/lyrics'; @use 'layouts/songs';

View file

@ -1,8 +1,16 @@
import circles from "../data/circles.json";
import type { CollectionEntry } from "astro:content"; import type { CollectionEntry } from "astro:content";
type Song = CollectionEntry<'songs'>; type Song = CollectionEntry<'songs'>;
interface Metadata {
[key: string]: {
circle: string,
title: string
}
}
export function getAllCats(songs: Song[]): Set<string> { export function getAllCats(songs: Song[]): Set<string> {
return songs.reduce( return songs.reduce(
@ -13,3 +21,20 @@ export function getAllCats(songs: Song[]): Set<string> {
new Set<string>() new Set<string>()
); );
} }
function createMetadata(circles: CirclesSchema): Metadata {
const metadata: Metadata = {};
for (const circle of Object.keys(circles)) {
const data = circles[circle];
for (const cat of Object.keys(data.albums))
metadata[cat] = {
circle,
title: data.albums[cat].title,
}
}
return metadata;
}
export const ALBUMS: Metadata = createMetadata(circles);