Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expose news page to users #124

Merged
merged 5 commits into from
Jan 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/components/Header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import type { NavItem } from "../types";
import HeaderNavigation from "./HeaderNavigation.astro";

const NAVIGATION: NavItem[] = [
{
title: "Aktuelt",
path: "/news",
},
{
title: "Om TG",
path: "/about",
Expand Down
92 changes: 42 additions & 50 deletions src/components/NewsComp.astro
Original file line number Diff line number Diff line change
@@ -1,56 +1,48 @@
---
import H2 from "./H2.astro";
import { fetchArticles } from "../utils";
import type { FetchArticlesProps } from "../utils";
import type { Article } from "../types";

type Props = {} & Omit<FetchArticlesProps, "api_url">;
type Props = { articles: Article[] };

const articles = await fetchArticles({
...Astro.props,
api_url: import.meta.env.API_URL,
});
const { articles } = Astro.props;
---

<section>
<H2 text="Nyheter >_" />
<div class="grid grid-cols-1 sm:grid-cols-2 gap-y-4 gap-x-5 lg:px-28">
{
articles.map((article) => (
<a href={`/news/${article.meta.slug}`}>
<article class="overflow-hidden flex flex-row p-4">
<div class="flex-1">
<div class="text-sm text-orange-500">
{article.tags
.map((tag) => {
return tag.name.charAt(0).toUpperCase() + tag.name.slice(1);
})
.join(", ")}
</div>
<h3 class="text-xl text-white font-bold mt-2">{article.title}</h3>
<time
datetime={article.meta.first_published_at}
class="text-sm text-gray-500"
>
{new Date(article.meta.first_published_at).toLocaleDateString(
"en-US",
{
year: "numeric",
month: "long",
day: "numeric",
},
)}
</time>
<div class="grid grid-cols-1 sm:grid-cols-2 gap-y-4 gap-x-5 lg:px-28 mb-10">
{
articles.map((article) => (
<a href={`/news/${article.meta.slug}`}>
<article class="overflow-hidden flex flex-row p-4">
<div class="flex-1">
<div class="text-sm text-orange-500">
{article.tags
.map((tag) => {
return tag.name.charAt(0).toUpperCase() + tag.name.slice(1);
})
.join(", ")}
</div>
{article.main_image && (
<img
src={article.main_image.sizes.thumbnail.url}
alt={article.main_image.alt}
class="w-24 h-24 object-cover ml-4 rounded-lg"
/>
)}
</article>
</a>
))
}
</div>
</section>
<h3 class="text-xl text-white font-bold mt-2">{article.title}</h3>
<time
datetime={article.meta.first_published_at}
class="text-sm text-gray-500"
>
{new Date(article.meta.first_published_at).toLocaleDateString(
"en-US",
{
year: "numeric",
month: "long",
day: "numeric",
},
)}
</time>
</div>
{article.main_image && (
<img
src={article.main_image.sizes.thumbnail.url}
alt={article.main_image.alt}
class="w-24 h-24 object-cover ml-4 rounded-lg"
/>
)}
</article>
</a>
))
}
</div>
81 changes: 81 additions & 0 deletions src/components/Pagination.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
---
type Props = { pages: number; page: number; path: string };

const { pages, path } = Astro.props;
const page = Math.min(Math.max(Astro.props.page, 1), pages);
const isFirstPage = page < 2;
const isLastPage = page >= pages;
const pageUrls = Array.from({
length: pages,
}).map((_, index) => {
const pageIndex = index + 1;
return {
url: pageIndex > 1 ? `?page=${pageIndex}` : path,
label: pageIndex,
};
});

const disabledStyles =
"pointer-events-none opacity-50 shadow-none text-slate-500";
const activeStyles = "text-black font-bold bg-orange-500";
const inactiveStyles = "text-white";
const styles =
"flex items-center border border-slate-500 py-2 px-3 text-center text-sm transition-all shadow-sm hover:shadow-lg hover:text-black hover:bg-orange-500 focus:text-black focus:bg-orange-500 active:text-black active:bg-orange-500";
---

<div class="row flex">
<a
class={`${styles} rounded-md rounded-r-none border-r-0 ${
isFirstPage ? disabledStyles : inactiveStyles
}`}
aria-disabled={isFirstPage}
href={path}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M11.03 3.97a.75.75 0 0 1 0 1.06l-6.22 6.22H21a.75.75 0 0 1 0 1.5H4.81l6.22 6.22a.75.75 0 1 1-1.06 1.06l-7.5-7.5a.75.75 0 0 1 0-1.06l7.5-7.5a.75.75 0 0 1 1.06 0Z"
clip-rule="evenodd"></path>
</svg>
</a>
{
pageUrls.map(({ label, url }, index) => (
<a
class:list={[
styles,
"border-r-0",
index + 1 === page ? activeStyles : inactiveStyles,
]}
href={url}
>
{label}
</a>
))
}
<a
class:list={[
styles,
"rounded-md rounded-l-none",
isLastPage ? disabledStyles : inactiveStyles,
]}
aria-disabled={isLastPage}
href={`?page=${pages}`}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-4 h-4"
>
<path
fill-rule="evenodd"
d="M12.97 3.97a.75.75 0 0 1 1.06 0l7.5 7.5a.75.75 0 0 1 0 1.06l-7.5 7.5a.75.75 0 1 1-1.06-1.06l6.22-6.22H3a.75.75 0 0 1 0-1.5h16.19l-6.22-6.22a.75.75 0 0 1 0-1.06Z"
clip-rule="evenodd"></path>
</svg>
</a>
</div>
128 changes: 59 additions & 69 deletions src/components/frontpage/NewsComp.astro
Original file line number Diff line number Diff line change
@@ -1,84 +1,74 @@
---
import type { FetchArticlesProps } from "../../types";
import { fetchArticles } from "../../utils";
import type { FetchArticlesProps } from "../../utils";
import Button from "../Button.astro";

type Props = {
singleColumn?: boolean;
} & Omit<FetchArticlesProps, "api_url">;

const articles = await fetchArticles({
...Astro.props,
api_url: import.meta.env.API_URL,
limit: 6,
});
const articles =
(
await fetchArticles({
...Astro.props,
api_url: import.meta.env.API_URL,
limit: 6,
})
)?.items || [];

const { singleColumn = false } = Astro.props;
const gridStyles = singleColumn
? "grid grid-cols-1"
: "grid grid-cols-1 sm:grid-cols-2 gap-y-4 gap-x-5 lg:px-28";
---

{
(() => {
if (articles.length === 0) {
return (
<section class="text-white p-8 rounded-3xl border-solid border-4 border-backgroundSecondary my-2">
<a href="https://wannabe.tg.no" class="container mx-auto">
<h1 class="text-3xl font-bold text-center mb-6">
Ser ut som noe mangler her...
</h1>
<h1 class="text-3xl font-bold text-center mb-6">
Kan du hjelpe oss å finne det?
</h1>
</a>
</section>
);
} else {
return (
<section class="text-white sm:p-8 rounded-3xl border-solid border-4 border-backgroundSecondary">
<div class={gridStyles}>
{articles.map((article) => (
<a href={`/news/${article.meta.slug}`}>
<article class="overflow-hidden flex flex-row p-4">
<div class="flex-1">
<div class="text-sm text-orange-500">
{article.tags
.map((tag) => {
return (
tag.name.charAt(0).toUpperCase() + tag.name.slice(1)
);
})
.join(", ")}
</div>
<h3 class="text-xl text-white font-bold mt-2">
{article.title}
</h3>
<time
datetime={article.meta.first_published_at}
class="text-sm text-gray-500"
>
{new Date(
article.meta.first_published_at,
).toLocaleDateString("en-US", {
year: "numeric",
month: "long",
day: "numeric",
})}
</time>
</div>
{article.main_image && (
<img
src={article.main_image.sizes.thumbnail.url}
alt={article.main_image.alt}
class="w-24 h-24 object-cover ml-4 rounded-lg"
/>
)}
</article>
</a>
))}
</div>
</section>
);
<section
class="flex flex-col items-center text-white sm:p-8 rounded-3xl border-solid sm:border-4 border-backgroundSecondary"
>
<div class={gridStyles}>
{
articles.map((article, index) => (
<a
href={`/news/${article.meta.slug}`}
class={`${index > 3 ? "hidden md:block" : ""}`}
>
<article class="overflow-hidden flex flex-row pb-4 sm:p-4">
<div class="flex-1">
<div class="text-sm text-orange-500">
{article.tags
.map((tag) => {
return tag.name.charAt(0).toUpperCase() + tag.name.slice(1);
})
.join(", ")}
</div>
<h3 class="text-xl text-white font-bold mt-2">{article.title}</h3>
<time
datetime={article.meta.first_published_at}
class="text-sm text-gray-500"
>
{new Date(article.meta.first_published_at).toLocaleDateString(
"en-US",
{
year: "numeric",
month: "long",
day: "numeric",
},
)}
</time>
</div>
{article.main_image && (
<img
src={article.main_image.sizes.thumbnail.url}
alt={article.main_image.alt}
class="w-24 h-24 object-cover ml-4 rounded-lg"
/>
)}
</article>
</a>
))
}
})()
}
</div>
<Button href="/news" theme="secondary" class="w-full sm:w-fit text-center"
>Les alle</Button
>
</section>
7 changes: 6 additions & 1 deletion src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,12 @@ const randomFact = TG_FACTS[Math.floor(Math.random() * TG_FACTS.length)];
</div>
<div class="sm:col-start-2 sm:col-span-7">
<h2 class="text-2xl sm:text-6xl font-bold text-white text-center">
Aktuelt
<a
href="news"
class="hover:text-orange-500 active:text-orange-500 focus:text-orange-500"
>
Aktuelt
</a>
</h2>
</div>
<div class="sm:col-span-9">
Expand Down
31 changes: 30 additions & 1 deletion src/pages/news/index.astro
Original file line number Diff line number Diff line change
@@ -1,11 +1,40 @@
---
import H2 from "../../components/H2.astro";
import Main from "../../components/Main.astro";
import NewsComp from "../../components/NewsComp.astro";
import Pagination from "../../components/Pagination.astro";
import Layout from "../../layouts/Layout.astro";
import { fetchArticles } from "../../utils";

const limit = 10;
const page = parseInt(Astro.url.searchParams.get("page") || "1") || 1;
const offset = (page - 1) * limit;

if (Astro.url.searchParams.has("page") && page <= 1) {
return Astro.redirect(Astro.url.pathname);
}

const articles = await fetchArticles({
limit,
offset,
api_url: import.meta.env.API_URL,
});
const pages = Math.ceil(articles.meta.total_count / limit);

if ((pages && page > pages) || !articles?.items) {
Astro.response.status = 404;
Astro.response.statusText = "Invalid page number";
}
---

<Layout title="The Gathering - News">
<Main>
<NewsComp limit={20} offset={0} />
<section>
<H2 text="Nyheter >_" />
<NewsComp articles={articles?.items} />
<aside class="col-span-2 flex justify-center">
<Pagination pages={pages} path={Astro.url.pathname} page={page} />
</aside>
</section>
</Main>
</Layout>
Loading
Loading