Skip to content

Commit

Permalink
Merge pull request #2 from sardinedev/feat/story-arcs
Browse files Browse the repository at this point in the history
feat: Story arcs
  • Loading branch information
Marabyte authored Mar 29, 2024
2 parents c0cfa59 + 28d07c4 commit 0b52001
Show file tree
Hide file tree
Showing 14 changed files with 100 additions and 42 deletions.
15 changes: 7 additions & 8 deletions src/components/IssueGrid/IssueGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import { useEffect, useState } from "preact/hooks";
import { useStore } from "@nanostores/preact";
import { $sort } from "../../stores/sort.store";
import { PageNavigator } from "../PageNavigator";
import type {
ComicvineImage,
ShortIssue,
} from "../../pages/api/comicvine.types";
import type { ComicvineImage, ShortIssue } from "../../util/comicvine.types";
import type { Sort } from "../../stores/sort.store";

export type Props = {
Expand Down Expand Up @@ -37,10 +34,12 @@ function clampIssuesPerPage({
(a, b) => parseInt(a.issue_number) - parseInt(b.issue_number)
);
}
return issueList.slice(
const trimmedList = issueList.slice(
(currentPage - 1) * issuesPerPage,
currentPage * issuesPerPage
);

return trimmedList;
}

function Issue({ id, name, image, issue_number }: ShortIssue) {
Expand All @@ -54,9 +53,9 @@ function Issue({ id, name, image, issue_number }: ShortIssue) {
}
if (!image) {
getIssue();
console.warn("Issue", id, "is missing an image");
}
}, [image]);
}, []);

return (
<li>
<a href={"/comic/" + id}>
Expand All @@ -83,7 +82,6 @@ export function IssueGrid({
issuesPerPage = 50,
}: Props) {
const $sortDirection = useStore($sort);

const [issues, setIssues] = useState<ShortIssue[] | undefined>(
clampIssuesPerPage({
issuesPerPage,
Expand All @@ -103,6 +101,7 @@ export function IssueGrid({
})
);
}, [issueList, currentPage, issuesPerPage, $sortDirection]);

return (
<>
<ul class="grid gap-4 grid-cols-2 sm:grid-cols-3 md:grid-cols-5 mt-8">
Expand Down
7 changes: 6 additions & 1 deletion src/components/PageNavigator.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { $sort } from "../stores/sort.store";

type Props = {
/** The series ID is used to compose the URL on the link navigation */
id: number | string;
numberOfPages: number;
currentPage: number;
};
export function PageNavigator({ id, numberOfPages, currentPage }: Props) {
const sort = $sort.get();
let pagesArray: (string | number)[] = [];

if (numberOfPages > 8) {
if (currentPage < 5) {
pagesArray = [1, 2, 3, 4, 5, "...", numberOfPages];
Expand Down Expand Up @@ -41,7 +46,7 @@ export function PageNavigator({ id, numberOfPages, currentPage }: Props) {
<span>{page}</span>
) : (
<a
href={`/series/${id}/${page}`}
href={`/series/${id}/${page}?sort=${sort}`}
class={page === currentPage ? "underline" : ""}
>
{page}
Expand Down
12 changes: 7 additions & 5 deletions src/layouts/Layout.astro
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
---
import { ViewTransitions } from "astro:transitions";
import Header from "../components/Header.astro";
interface Props {
title: string;
Expand All @@ -16,6 +17,7 @@ const { title } = Astro.props;
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<title>{title}</title>
<ViewTransitions />
</head>
<body class="bg-slate-900 font-sans text-slate-50">
<Header />
Expand All @@ -25,10 +27,10 @@ const { title } = Astro.props;
<footer class="p-4 text-center text-xs">
<p>&copy; 2024 Sardines Reading Comics</p>
</footer>
<style is:global>
.hide-scrollbar {
scrollbar-width: none;
}
</style>
</body>
<style is:global>
.hide-scrollbar {
scrollbar-width: none;
}
</style>
</html>
2 changes: 1 addition & 1 deletion src/pages/api/followSeries.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { APIRoute, APIContext } from "astro";
import { kvAddFollowSeries, kvGetFollowSeries } from "./kv";
import { kvAddFollowSeries, kvGetFollowSeries } from "../../util/kv";

export const GET: APIRoute = async ({ locals }: APIContext) => {
const kv = locals.runtime.env.COMICS;
Expand Down
2 changes: 1 addition & 1 deletion src/pages/api/issue/[id].ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { kvGetComicIssue } from "../kv";
import { kvGetComicIssue } from "../../../util/kv";

import type { APIContext } from "astro";

Expand Down
4 changes: 2 additions & 2 deletions src/pages/comic/[id]/index.astro
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
---
import IssueSlider from "../../../components/IssueSlider.astro";
import Layout from "../../../layouts/Layout.astro";
import { kvGetComicIssue, kvGetVolume } from "../../api/kv";
import { kvGetComicIssue, kvGetVolume } from "../../../util/kv";
import type { ComicvineSingleIssueResponse } from "../../api/comicvine.types";
import type { ComicvineSingleIssueResponse } from "../../../util/comicvine.types";
import type { SingleIssuePreview } from "../../../components/IssueSlider.astro";
const kv = Astro.locals.runtime.env.COMICS;
Expand Down
4 changes: 1 addition & 3 deletions src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import Layout from "../layouts/Layout.astro";
import IssueSlider from "../components/IssueSlider.astro";
import { thisWeekBookendsDates } from "../util/date";
import { kvGetFollowSeries, kvGetWeeklyComics } from "./api/kv";
import { kvGetFollowSeries, kvGetWeeklyComics } from "../util/kv";
import type { SingleIssuePreview } from "../components/IssueSlider.astro";
Expand Down Expand Up @@ -68,5 +68,3 @@ try {
)
}
</Layout>

<style></style>
9 changes: 7 additions & 2 deletions src/pages/series/[id]/[...slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@ import Layout from "../../../layouts/Layout.astro";
import CoverStack from "../../../components/CoverStack.astro";
import { IssueGrid } from "../../../components/IssueGrid/IssueGrid";
import { SortButton } from "../../../components/SortButton";
import { kvGetVolume, kvGetFollowSeries } from "../../api/kv";
import { kvGetVolume, kvGetFollowSeries } from "../../../util/kv";
import { $sort } from "../../../stores/sort.store";
import type { ComicvineVolumeResponse } from "../../api/comicvine.types";
import type { ComicvineVolumeResponse } from "../../../util/comicvine.types";
const sort = Astro.url.searchParams.get("sort") === "asc" ? "asc" : "desc";
$sort.set(sort);
const kv = Astro.locals.runtime.env.COMICS;
const { id, slug } = Astro.params;
let volume: ComicvineVolumeResponse | undefined;
let currentPage = 1;
let isFollowing = false;
if (slug) {
currentPage = parseInt(slug);
}
Expand Down
2 changes: 2 additions & 0 deletions src/pages/story-arc/[storyArcId].astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
24 changes: 22 additions & 2 deletions src/stores/sort.store.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,32 @@
import { persistentAtom } from "@nanostores/persistent";
import { atom } from "nanostores";
export type Sort = "asc" | "desc";

export const $sort = persistentAtom<Sort>("sortIssues", "asc");
function getSortfromURL() {
if (typeof document === "undefined") {
return "desc";
}
const url = new URL(document.location.href);
const sort = url.searchParams.get("sort");

if (sort === "asc") {
return "asc";
}
return "desc";
}

function setSortInURL(sort: Sort) {
const url = new URL(document.location.href);
url.searchParams.set("sort", sort);
history.pushState({}, "", url.href);
}

export const $sort = atom<Sort>(getSortfromURL());

export function toggleSort(sort: Sort) {
if (sort === "asc") {
$sort.set("desc");
} else {
$sort.set("asc");
}
setSortInURL($sort.get());
}
31 changes: 31 additions & 0 deletions src/util/clampIssuesPerPage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import type { Sort } from "../stores/sort.store";
import type { ShortIssue } from "./comicvine.types";

export function clampIssuesPerPage({
issuesPerPage,
currentPage,
issueList,
sortDirection,
}: {
issuesPerPage: number;
currentPage: number;
issueList: ShortIssue[];
sortDirection: Sort;
}) {
// sort the issues by issue number
if (sortDirection === "desc") {
issueList.sort(
(a, b) => parseInt(b.issue_number) - parseInt(a.issue_number)
);
} else {
issueList.sort(
(a, b) => parseInt(a.issue_number) - parseInt(b.issue_number)
);
}
const trimmedList = issueList.slice(
(currentPage - 1) * issuesPerPage,
currentPage * issuesPerPage
);

return trimmedList;
}
File renamed without changes.
File renamed without changes.
30 changes: 13 additions & 17 deletions src/pages/api/kv.ts → src/util/kv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,35 +67,31 @@ export async function kvGetVolume(
} else {
const response = await getVolumeDetails(id);
if (response) {
const issuesFromVolume = await kvGetIssuesFromVolume(id, kv);
let cover_image: string[] = [];
if (issuesFromVolume) {
cover_image = issuesFromVolume
.reverse()
.slice(0, 5)
.map((issue) => issue.image.medium_url);

// sort by issue number
response.issues.sort(
(a, b) => parseInt(a.issue_number) - parseInt(b.issue_number)
);
// sort by issue number
response.issues.sort(
(a, b) => parseInt(a.issue_number) - parseInt(b.issue_number)
);

for (const responseIssue of response.issues) {
const issue = issuesFromVolume.find(
(issue) => issue.id === responseIssue.id
);
if (issue) {
responseIssue.image = issue.image;
}
const firstFiveIssues = response.issues.slice(0, 5);

for (const issue of firstFiveIssues) {
const issueDetails = await kvGetComicIssue(issue.id, kv);
if (issueDetails) {
cover_image.push(issueDetails.image.medium_url);
}
}

const fullResponse = {
...response,
cover_image,
};

await kv.put(`4050-${id}`, JSON.stringify(fullResponse), {
expirationTtl: 60 * 60 * 24 * 7, // 7 days
});

return fullResponse;
}
}
Expand Down

0 comments on commit 0b52001

Please sign in to comment.