You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
3.2 KiB
TypeScript
166 lines
3.2 KiB
TypeScript
import { isoDateStr } from "../util";
|
|
|
|
type LogBase = {
|
|
name: string;
|
|
started?: Date;
|
|
finished?: Date;
|
|
dropped?: true;
|
|
rating?: number;
|
|
picUrl?: string;
|
|
};
|
|
|
|
const status = (log: LogBase) => {
|
|
if (log.dropped) {
|
|
return "dropped" as const;
|
|
}
|
|
|
|
if (!log.started && !log.finished && !log.rating) {
|
|
return "wantTo" as const;
|
|
}
|
|
|
|
if (log.started && !log.finished) {
|
|
return "inProgress" as const;
|
|
}
|
|
|
|
if (log.finished || log.rating) {
|
|
return "finished" as const;
|
|
}
|
|
|
|
throw new Error("unreachable");
|
|
};
|
|
|
|
const byStatusSorted = (items: LogBase[]) => {
|
|
const inProgress = items.filter((i) => status(i) == "inProgress");
|
|
inProgress.sort((a, b) => +(a.started ?? 0) - +(b.started ?? 0));
|
|
|
|
const finished = items.filter((i) => status(i) == "finished");
|
|
finished.sort((a, b) => (b.rating ?? 0) - (a.rating ?? 0));
|
|
|
|
const wantTo = items.filter((i) => status(i) == "wantTo");
|
|
wantTo.sort((a, b) => a.name.localeCompare(b.name));
|
|
|
|
const dropped = items.filter((i) => status(i) == "dropped");
|
|
dropped.sort((a, b) => +((a.started ?? 0) > (b.started ?? 0)));
|
|
|
|
return { dropped, wantTo, finished, inProgress };
|
|
};
|
|
|
|
type Anime = LogBase & { season?: number };
|
|
const ANIME: Anime[] = [
|
|
{
|
|
name: "Violet Evergarden",
|
|
rating: 10,
|
|
},
|
|
{
|
|
name: "Sugar Apple Fairy Tale",
|
|
started: new Date("2023-01-22"),
|
|
},
|
|
{
|
|
name: "REVENGER",
|
|
started: new Date("2023-01-21"),
|
|
},
|
|
{
|
|
name: "Ice Guy and the Cool Female Colleague",
|
|
},
|
|
{
|
|
name: "High Card",
|
|
started: new Date("2023-01-21"),
|
|
},
|
|
{
|
|
name: "Bocchi the Rock!",
|
|
started: new Date("2023-01-12"),
|
|
season: 1,
|
|
},
|
|
{
|
|
name: "Blue Period",
|
|
started: new Date("2023-01-02"),
|
|
finished: new Date("2023-01-12"),
|
|
season: 1,
|
|
rating: 10,
|
|
},
|
|
{
|
|
name: "Chainsaw Man",
|
|
started: new Date("2022-12-01"),
|
|
finished: new Date("2023-01-04"),
|
|
season: 1,
|
|
rating: 7.5,
|
|
},
|
|
{
|
|
name: "Do it Yourself!!",
|
|
started: new Date("2022-12-01"),
|
|
season: 1,
|
|
},
|
|
{
|
|
name: "Cyberpunk: Edgerunners",
|
|
season: 1,
|
|
rating: 10,
|
|
},
|
|
{
|
|
name: "The Bear",
|
|
rating: 8,
|
|
},
|
|
{
|
|
name: "The Witcher",
|
|
rating: 9,
|
|
},
|
|
{
|
|
name: "Arcane",
|
|
rating: 10,
|
|
},
|
|
{
|
|
name: "Castlevania",
|
|
rating: 10,
|
|
},
|
|
{
|
|
name: "Over the Garden Wall",
|
|
rating: 10,
|
|
},
|
|
];
|
|
const renderAnime = () => {
|
|
const renderSection = (title: string, items: Anime[]) => {
|
|
let out = `<section><h3>${title}</h3>`;
|
|
for (const a of items) {
|
|
out += `<div class="log anime"><h4>${a.name}`;
|
|
if (a.season) {
|
|
out += `, Season ${a.season}`;
|
|
}
|
|
out += "</h4>";
|
|
|
|
if (a.started) {
|
|
out += `<div class="started">Started: ${isoDateStr(a.started)}</div>`;
|
|
}
|
|
|
|
if (a.finished) {
|
|
out += `<div class="finished">Finished: ${isoDateStr(
|
|
a.finished,
|
|
)}</div>`;
|
|
}
|
|
|
|
if (a.rating) {
|
|
out += `<div class="rating">Rating: ${a.rating} / 10</div>`;
|
|
}
|
|
|
|
out += "</div>";
|
|
}
|
|
out += "</section>";
|
|
|
|
return out;
|
|
};
|
|
|
|
const { wantTo, dropped, finished, inProgress } = byStatusSorted(ANIME);
|
|
|
|
return `
|
|
<section>
|
|
<h2>Anime / TV</h2>
|
|
${renderSection("Currently Watching", inProgress)}
|
|
${renderSection("Finished", finished)}
|
|
${renderSection("Dropped", dropped)}
|
|
${renderSection("Want to Watch", wantTo)}
|
|
</section>
|
|
`;
|
|
};
|
|
|
|
export const render = () => {
|
|
return renderAnime();
|
|
};
|