58 lines
1.7 KiB
TypeScript
58 lines
1.7 KiB
TypeScript
import "server-only";
|
|
import { and, asc, count, desc, eq, like, or, sql } from "drizzle-orm";
|
|
import { db, WebsiteArticles } from "@/lib/db";
|
|
|
|
export async function loadNewsArchive(
|
|
options: { search?: string; page?: number; order?: string } = {},
|
|
) {
|
|
const search = (typeof options.search === "string" ? options.search : "")
|
|
.trim()
|
|
.slice(0, 191);
|
|
const order = options.order === "oldest" ? "oldest" : "newest";
|
|
const publishedAt =
|
|
sql<Date | null>`COALESCE(${WebsiteArticles.publishAt}, ${WebsiteArticles.createdAt})`.mapWith(
|
|
WebsiteArticles.createdAt,
|
|
);
|
|
const where = and(
|
|
eq(WebsiteArticles.status, "published"),
|
|
or(
|
|
sql`${WebsiteArticles.publishAt} IS NULL`,
|
|
sql`${WebsiteArticles.publishAt} <= NOW()`,
|
|
),
|
|
search
|
|
? or(
|
|
like(WebsiteArticles.title, `%${search}%`),
|
|
like(WebsiteArticles.shortStory, `%${search}%`),
|
|
)
|
|
: undefined,
|
|
);
|
|
const totals = await db
|
|
.select({ value: count() })
|
|
.from(WebsiteArticles)
|
|
.where(where);
|
|
const total = Number(totals[0]?.value ?? 0);
|
|
const perPage = 24;
|
|
const lastPage = Math.max(1, Math.ceil(total / perPage));
|
|
const page = Math.min(
|
|
lastPage,
|
|
Number.isFinite(options.page)
|
|
? Math.max(1, Math.trunc(options.page ?? 1))
|
|
: 1,
|
|
);
|
|
const sort = order === "oldest" ? asc : desc;
|
|
const rows = await db
|
|
.select({
|
|
slug: WebsiteArticles.slug,
|
|
title: WebsiteArticles.title,
|
|
shortStory: WebsiteArticles.shortStory,
|
|
image: WebsiteArticles.image,
|
|
createdAt: publishedAt,
|
|
})
|
|
.from(WebsiteArticles)
|
|
.where(where)
|
|
.orderBy(sort(publishedAt), sort(WebsiteArticles.id))
|
|
.limit(perPage)
|
|
.offset((page - 1) * perPage);
|
|
return { rows, total, page, perPage, lastPage, search, order };
|
|
}
|