Compare commits

...

19 Commits

Author SHA1 Message Date
6521e2a057 Merge branch 'main' of https://git.log101.dev/log101/log101-dot-dev into release
Some checks failed
/ Build (push) Failing after 1m28s
2024-06-25 15:16:02 +03:00
709c97acfb feat: add error messages to forms 2024-06-23 13:11:06 +03:00
3b59273c12 style: change favicon 2024-06-23 11:53:34 +03:00
d6aa507e1a feat: fill empty anchor tags 2024-06-22 18:28:25 +03:00
82af925f46 feat: add header links 2024-06-22 18:15:56 +03:00
82d2c69e11 chore: add validation and debounce to forms 2024-06-22 16:53:51 +03:00
2b9d6d8657 feat: add about page 2024-06-22 16:34:55 +03:00
8fbe06a4fa style: change border styling 2024-06-22 14:04:01 +03:00
92ab6c07ad feat: add htmx as npm dependency 2024-06-22 13:41:37 +03:00
ea496f4182 feat: dynamically determine game of life width
chore: format astro files
2024-06-22 13:02:22 +03:00
a2c28ef377 feat: add about page 2024-06-21 20:21:15 +03:00
2885cd1b86 style: hide pagination if there is only one page 2024-06-21 17:01:58 +03:00
b71e3faaf9 feat: add pagination 2024-06-21 16:45:23 +03:00
393aa52757 feat: add pagination to category page 2024-06-21 12:53:17 +03:00
8faa7f472d feat: implement commenting 2024-06-20 19:40:55 +03:00
6c0b81c883 style: add spacing to emoji form 2024-06-18 21:36:47 +03:00
132174d0c6 style: add no content text 2024-06-18 16:50:21 +03:00
68fd34c830 feat: add comment and comment form component 2024-06-18 16:44:05 +03:00
53c5203f23 feat: add comments section 2024-06-16 22:05:58 +03:00
24 changed files with 751 additions and 1186 deletions

View File

@ -1 +1,12 @@
{} {
"plugins": ["prettier-plugin-astro"],
"bracketSameLine": true,
"overrides": [
{
"files": "*.astro",
"options": {
"parser": "astro"
}
}
]
}

12
.vscode/settings.json vendored
View File

@ -1,8 +1,8 @@
{ {
"eslint.format.enable": true, "eslint.format.enable": true,
"prettier.configPath": ".prettierrc", "prettier.configPath": ".prettierrc",
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "esbenp.prettier-vscode",
"[javascript]": { "[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode" "editor.defaultFormatter": "esbenp.prettier-vscode"
} }
} }

1359
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -13,12 +13,14 @@
"dependencies": { "dependencies": {
"@astrojs/check": "^0.5.10", "@astrojs/check": "^0.5.10",
"@astrojs/tailwind": "^5.1.0", "@astrojs/tailwind": "^5.1.0",
"astro": "^4.7.0", "astro": "^4.10.0",
"htmx.org": "^1.9.12",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"typescript": "^5.4.5" "typescript": "^5.4.5"
}, },
"devDependencies": { "devDependencies": {
"cypress": "^13.11.0", "cypress": "^13.11.0",
"prettier": "3.2.5" "prettier": "^3.2.5",
"prettier-plugin-astro": "^0.14.0"
} }
} }

BIN
public/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,9 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
<style>
path { fill: #000; }
@media (prefers-color-scheme: dark) {
path { fill: #FFF; }
}
</style>
</svg>

Before

Width:  |  Height:  |  Size: 749 B

BIN
public/furkan_erdem_cv.pdf Normal file

Binary file not shown.

View File

@ -0,0 +1,14 @@
---
---
<div class="comment border-gray-400 border border-solid pt-1 pb-6 ml-4">
<p
class="font-semibold pl-3 pr-2 pb-1 border-b border-x-0 border-t-0 border-gray-400 border-solid">
Arafat Candan
</p>
<p class="pl-3 py-2 pr-4">
Daha önce hiç bu açıdan bakmamıştım, harika bir yazı olmuş.
</p>
</div>

View File

@ -0,0 +1,90 @@
---
const { entryId } = Astro.props;
const backendHost = import.meta.env.PUBLIC_BACKEND_HOST;
---
<style>
.textarea {
resize: none;
}
textarea {
@apply font-sans text-base;
}
input {
@apply font-sans text-base;
}
button {
@apply text-sm;
}
</style>
<form
id="comment-form"
hx-post=`${backendHost}/api/blog/comments`
hx-target="#comments-container"
hx-swap="afterbegin"
hx-on:htmx:after-request="document.getElementById('no-comments-text')?.remove();this.reset()">
<div class="p-1 flex flex-col flex-end items-end gap-3">
<textarea
class="textarea py-2 px-3 w-full box-border"
rows="5"
placeholder="Yazı hakkındaki düşünceleriniz nelerdir?"
name="commentBody"
required></textarea>
<input
type="text"
class="w-full py-2 px-3 box-border"
placeholder="İsminiz (Yazmazsanız yorumunuz anonim kalacaktır)"
name="username"
/>
<input type="hidden" name="postId" value=`${entryId}` />
<button type="submit" class="px-3 py-1 w-fit" id="comment-form-button"
>Yorum Yap</button
>
</div>
<div id="comment-form-error-container" class="mt-4">
<p id="comment-form-error-text" class="text-red-600"></p>
</div>
</form>
<script>
function showError(errorString: string) {
const errorTextElement = document.getElementById("comment-form-error-text");
if (errorTextElement) {
errorTextElement.innerText = errorString;
}
setTimeout(() => {
if (errorTextElement) {
errorTextElement.innerText = "";
}
}, 5000);
}
const formElement = document.getElementById("comment-form");
if (formElement) {
formElement.addEventListener(
"htmx:sendError" as keyof HTMLElementEventMap,
() => {
showError(
"Sunucuya ulaşılamadığı için yorumunuz kaydedilemedi, biraz bekledikten sonra tekrar deneyebilirsiniz.",
);
},
);
formElement.addEventListener(
"htmx:responseError" as keyof HTMLElementEventMap,
() => {
showError(
"Suncudan kaynaklı bir hatadan dolayı yorumunuz kaydedilemedi, biraz bekledikten sonra tekrar deneyebilirsiniz.",
);
},
);
}
</script>

View File

@ -15,35 +15,79 @@ const backendHost = import.meta.env.PUBLIC_BACKEND_HOST;
</style> </style>
<form <form
hx-post=`${backendHost}/blog/api/forms/emoji/post` id="emoji-reaction-form"
hx-post=`${backendHost}/api/blog/forms/emoji`
hx-target="#reaction-buttons" hx-target="#reaction-buttons"
> hx-trigger="submit delay:0.5s">
<input type="hidden" name="postId" value=`${entryId}` /> <input type="hidden" name="postId" value=`${entryId}` />
<div <div
id="reaction-buttons" id="reaction-buttons"
hx-get=`${backendHost}/blog/api/forms/emoji?postId=${entryId}` hx-get=`${backendHost}/api/blog/forms/emoji?postId=${entryId}`
hx-trigger="load" hx-trigger="load"
hx-swap="innerHTML" hx-swap="innerHTML">
>
<div class="emoji-buttons-container"> <div class="emoji-buttons-container">
<button name="emojiInput" value="👍" type="submit" class="emoji-button" <button name="emojiInput" value="👍" type="submit" class="emoji-button">
>👍&nbsp;</button &nbsp;👍&nbsp;
> </button>
<button name="emojiInput" value="👎" type="submit" class="emoji-button" <button name="emojiInput" value="👎" type="submit" class="emoji-button">
>👎&nbsp;</button &nbsp;👎&nbsp;
> </button>
<button name="emojiInput" value="😀" type="submit" class="emoji-button" <button name="emojiInput" value="😀" type="submit" class="emoji-button">
>😀&nbsp;</button &nbsp;😀&nbsp;
> </button>
<button name="emojiInput" value="😑" type="submit" class="emoji-button" <button name="emojiInput" value="😑" type="submit" class="emoji-button">
>😑&nbsp;</button &nbsp;😑&nbsp;
> </button>
<button name="emojiInput" value="🤢" type="submit" class="emoji-button" <button name="emojiInput" value="🤢" type="submit" class="emoji-button">
>🤢&nbsp;</button &nbsp;🤢&nbsp;
> </button>
<button name="emojiInput" value="👀" type="submit" class="emoji-button" <button name="emojiInput" value="👀" type="submit" class="emoji-button">
>👀&nbsp;</button &nbsp;👀&nbsp;
> </button>
</div> </div>
</div> </div>
<div id="emoji-form-error-container" class="mt-4">
<p id="emoji-form-error-text" class="text-red-600"></p>
</div>
</form> </form>
<script>
function showError(errorString: string) {
const errorTextElement = document.getElementById("emoji-form-error-text");
if (errorTextElement) {
errorTextElement.innerText = errorString;
}
setTimeout(() => {
if (errorTextElement) {
errorTextElement.innerText = "";
}
}, 5000);
}
const formElement = document.getElementById("emoji-reaction-form");
if (formElement) {
formElement.addEventListener(
"htmx:sendError" as keyof HTMLElementEventMap,
(event) => {
// @ts-ignore detail attribute is added by htmx
if (event.detail.elt.id != "reaction-buttons") {
showError(
"Sunucuya ulaşılamadığı için tepkiniz kaydedilemedi, biraz bekledikten sonra tekrar deneyebilirsiniz.",
);
}
},
);
formElement.addEventListener(
"htmx:responseError" as keyof HTMLElementEventMap,
() => {
showError(
"Sunucudan kaynaklanan bir hatadan dolayı tepkiniz kaydedilemedi, biraz bekledikten sonra tekrar deneyebilirsiniz.",
);
},
);
}
</script>

View File

@ -4,5 +4,5 @@
<div class="flex flex-row items-center gap-2 text-gray-500 text-sm"> <div class="flex flex-row items-center gap-2 text-gray-500 text-sm">
<p class="copyright">© 2024 Furkan Erdem</p> <p class="copyright">© 2024 Furkan Erdem</p>
<a class="text-inherit" href="#">Hakkımda</a> <a class="text-inherit" href="/about">Hakkımda</a>
</div> </div>

View File

@ -18,50 +18,61 @@
<div class="flex flex-col justify-start gap-2"> <div class="flex flex-col justify-start gap-2">
<ul class="flex flex-row items-center list-none p-0 gap-3 contact-links"> <ul class="flex flex-row items-center list-none p-0 gap-3 contact-links">
<li><a href="#">Eposta</a></li> <li><a href="mailto:ffrknerdm@gmail.com">Eposta</a></li>
<li><a href="#">Github</a></li> <li><a href="https://github.com/log101" target="_blank">Github</a></li>
<li><a href="#">LinkedIn</a></li> <li>
<li><a href="#">CV</a></li> <a
href="https://www.linkedin.com/in/furkan-erdem-506548218/"
target="_blank">LinkedIn</a
>
</li>
<li><a href="/furkan_erdem_cv.pdf" target="_blank">CV</a></li>
</ul> </ul>
<div class="flex flex-col gap-4"> <div class="flex flex-col gap-4">
<div class="flex flex-row gap-2 items-center md:h-20 h-16"> <div
<a href="/" class="no-underline text-inherit" class="flex flex-row gap-2 items-center md:h-20 h-16"
><h1 class="font-mono md:text-6xl text-5xl -ml-[0.27rem]">Log101</h1></a id="title-container">
> <a href="/" class="no-underline text-inherit -ml-[0.27rem]" id="title">
<h1 class="font-mono md:text-6xl text-5xl">Log101</h1>
</a>
<div id="board" class="board"></div> <div id="board" class="board"></div>
</div> </div>
<div> <div class="border-b border-x-0 border-t-0 border-slate-900 border-solid">
<ul <ul
class="flex md:flex-row flex-col md:items-center justify-between list-none p-0 gap-3 nav-links" class="flex md:flex-row flex-col md:items-center justify-between list-none p-0 gap-3 nav-links">
>
<li> <li>
<a href="/category/fikir">Fikir</a> <a href="/fikir/1">Fikir</a>
</li> </li>
<li> <li>
<a href="/category/teknik">Teknik</a> <a href="/teknik/1">Teknik</a>
</li> </li>
<li> <li>
<a href="/category/edebiyat">Babür'ün Serüvenleri</a> <a href="/edebiyat/1">Babür'ün Serüvenleri</a>
</li> </li>
<li> <li>
<a href="/category/ansiklopedi">Ansiklopedi</a> <a href="/ansiklopedi/1">Ansiklopedi</a>
</li> </li>
</ul> </ul>
<hr class="mb-0 mt-2" />
</div> </div>
</div> </div>
</div> </div>
<script> <script>
import ConwaySimulator from "../scripts/conway-simulator"; import ConwaySimulator from "../scripts/conway-simulator";
let rows = 8; const title = document.getElementById("title");
let cols = 24; const titleContainer = document.getElementById("title-container");
const titleWidth = title?.offsetWidth ?? 194;
const titleContainerWidth = titleContainer?.offsetWidth ?? 750;
let pixelSize = 6; let pixelSize = 6;
let rows = 8;
let cols = (titleContainerWidth - titleWidth) / pixelSize;
let delay = 250; let delay = 250;
if (screen.availWidth > 768) { if (screen.availWidth > 768) {
cols = 46; cols = 60;
pixelSize = 8; pixelSize = 8;
} }

View File

@ -0,0 +1,5 @@
---
---
<div class="border-b border-x-0 border-t-0 border-solid border-slate-700"></div>

View File

@ -39,7 +39,7 @@ switch (componentType) {
// Options should not mutated further // Options should not mutated further
Object.freeze(options); Object.freeze(options);
// Format datae // Format date
const postDateFormatted = post.data.date.toLocaleDateString("tr-TR", { const postDateFormatted = post.data.date.toLocaleDateString("tr-TR", {
day: "numeric", day: "numeric",
month: "long", month: "long",
@ -47,7 +47,7 @@ const postDateFormatted = post.data.date.toLocaleDateString("tr-TR", {
}); });
// Create post link // Create post link
const postLink = `/category/${post.data.category}/${post.slug}`; const postLink = `/${post.data.category}/${post.slug}`;
// Create post content as an astro component // Create post content as an astro component
const { Content } = await post.render(); const { Content } = await post.render();
@ -71,9 +71,9 @@ import calendar from "@/images/calendar.svg";
<div class="flex flex-col gap-3"> <div class="flex flex-col gap-3">
<div class="flex flex-col"> <div class="flex flex-col">
<p class="tracking-wide text-slate-700">{post.data.subcategory}</p> <p class="tracking-wide text-slate-700">{post.data.subcategory}</p>
<a class="no-underline text-inherit" href={postLink} <a class="no-underline text-inherit" href={postLink}>
><h4 class="text-3xl font-normal">{post.data.title}</h4></a <h4 class="text-3xl font-normal">{post.data.title}</h4>
> </a>
<div class="flex flex-row gap-2"> <div class="flex flex-row gap-2">
{ {
options.showTags && ( options.showTags && (
@ -107,8 +107,7 @@ import calendar from "@/images/calendar.svg";
{post.body.length > 500 && ( {post.body.length > 500 && (
<a <a
class="text-inherit text-sm" class="text-inherit text-sm"
href={`/category/${post.data.category}/${post.slug}`} href={`/${post.data.category}/${post.slug}`}>
>
Devamını Oku Devamını Oku
</a> </a>
)} )}

6
src/env.d.ts vendored
View File

@ -1,2 +1,8 @@
/// <reference path="../.astro/types.d.ts" /> /// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" /> /// <reference types="astro/client" />
export declare global {
interface Window {
htmx: any;
}
}

View File

@ -13,16 +13,20 @@ import "../styles/main.css";
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<meta name="description" content="Astro description" /> <meta name="description" content="Astro description" />
<meta name="viewport" content="width=device-width" /> <meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" /> <link rel="icon" type="image/png" href="/favicon.png" />
<meta name="generator" content={Astro.generator} /> <meta name="generator" content={Astro.generator} />
<script src="../scripts/htmx.min.js"></script> <meta name="htmx-config" content='{code:"204", swap: false}' />
<title>{title}</title> <title>{title}</title>
</head> </head>
<body class="flex justify-center font-sans"> <body class="flex justify-center font-sans">
<div <div
class="md:max-w-[750px] w-full flex flex-col gap-8 md:gap-6 my-6 md:mx-0 mx-4 overflow-hidden" class="md:max-w-[750px] w-full flex flex-col gap-8 md:gap-6 my-6 md:mx-0 mx-4 overflow-hidden">
>
<slot /> <slot />
</div> </div>
</body> </body>
<script>
import htmx from "htmx.org";
window.htmx = htmx;
</script>
</html> </html>

View File

@ -0,0 +1,86 @@
---
import type { Page } from "astro";
import { getCollection } from "astro:content";
import { CATEGORIES } from "@/content/config";
import Header from "@/components/Header.astro";
import Footer from "@/components/Footer.astro";
import Layout from "@/layouts/Layout.astro";
import Post from "@/components/Post.astro";
export async function getStaticPaths({ paginate }: { paginate: any }) {
const blogEntries = await getCollection("blog");
return CATEGORIES.flatMap((category) => {
const filteredPosts = blogEntries.filter(
(post) => post.data.category == category,
);
return paginate(filteredPosts, {
params: { category },
pageSize: 3,
});
});
}
interface Props {
page: Page;
}
const { page } = Astro.props;
const posts = page.data;
const pages = Array.from({ length: page.lastPage }, (_, i) => i + 1);
---
<Layout title="log101">
<Header />
<div class="posts">
{
posts.length > 0 ? (
posts
.sort((p1, p2) => p2.data.date.getTime() - p1.data.date.getTime())
.map((p) => <Post post={p} componentType="long" />)
) : (
<p>
Henüz bu kategoride bir yazı yayınlanmadı. Yazarımızın ilhama veya
teşviğe ihtiyacı olabilir!
</p>
)
}
</div>
{
page.lastPage != 1 && (
<>
<div id="pagination-container" class="flex gap-2">
<button>
<a href={page.url.prev} class="no-underline text-inherit">
geri git
</a>
</button>
{pages.map((pageNumber) => {
switch (pageNumber) {
case page.currentPage:
return <a>{pageNumber}</a>;
default:
return (
<a
href={`${page.url.current.slice(0, -1)}${pageNumber}`}
class="text-inherit">
{pageNumber}
</a>
);
}
})}
<button>
<a href={page.url.next} class="no-underline text-inherit">
ileri git
</a>
</button>
</div>
</>
)
}
<Footer />
</Layout>

View File

@ -6,11 +6,16 @@ import Header from "@/components/Header.astro";
import Layout from "@/layouts/Layout.astro"; import Layout from "@/layouts/Layout.astro";
import Post from "@/components/Post.astro"; import Post from "@/components/Post.astro";
import EmojiReactionForm from "@/components/EmojiReactionForm.astro"; import EmojiReactionForm from "@/components/EmojiReactionForm.astro";
import CommentForm from "@/components/CommentForm.astro";
import HorizontalLine from "@/components/HorizontalLine.astro";
const { entry } = Astro.props; const { entry } = Astro.props;
const backendHost = import.meta.env.PUBLIC_BACKEND_HOST;
export async function getStaticPaths() { export async function getStaticPaths() {
const blogEntries = await getCollection("blog"); const blogEntries = await getCollection("blog");
return blogEntries.map((entry) => ({ return blogEntries.map((entry) => ({
params: { category: entry.data.category, slug: entry.slug }, params: { category: entry.data.category, slug: entry.slug },
props: { entry }, props: { entry },
@ -22,5 +27,21 @@ export async function getStaticPaths() {
<Header /> <Header />
<Post post={entry} componentType="full" /> <Post post={entry} componentType="full" />
<EmojiReactionForm entryId={entry.id} /> <EmojiReactionForm entryId={entry.id} />
<section class="comments">
<h6 class="text-xl mb-3">Yorumlar</h6>
<div class="flex flex-col gap-6">
<div
hx-get=`${backendHost}/api/blog/comments?postId=${entry.id}`
hx-trigger="load"
hx-swap="innerHTML"
id="comments-container"
class="flex flex-col gap-6">
<p id="no-comments-text">Henüz yorum yok!</p>
</div>
<HorizontalLine />
<CommentForm entryId={entry.id} />
</div>
</section>
<Footer /> <Footer />
</Layout> </Layout>

35
src/pages/about.astro Normal file
View File

@ -0,0 +1,35 @@
---
import Header from "@/components/Header.astro";
import Footer from "@/components/Footer.astro";
import Layout from "@/layouts/Layout.astro";
---
<Layout title="log101">
<Header />
<p>
İsmini açıklayamayacağım uzak bir gezegende, elektronik bilgisayarlar
yalnızca eğlence amaçlı kullanılıyor. Programlama ise orada bir spor
sayılıyor, hatta bir olimpiyat sporu! Bunları, yıllar önce benimle iletişime
geçen Merhume isimli bir şahıstan öğrendim. Kendisini gezegenlerarası bir
gezgin olarak tanımlayan bu şahıs bana uzun uzun ziyaret maksadından,
geldiği yerden bahsettikten sonra elime eski püskü bir deri çanta tutuşturdu
ve esrarengiz, arabaya benzer aracıyla kaybolup gitti. Eve döndüğümde
çantanın içerisinde üzerlerine yayın tarihleri iliştirilmiş yüzlerce yazı
olduğunu gördüm. Bunlar çoğunlukla, programlamaya, bilgisayarlara dair kısa,
bir-iki sayfalık denemelerdi. Aralarında edebi, felsefi metinlere de
rastladım. Bir de "Babür'ün Serüvenleri" vardı, kalın, kara kapaklı bir
roman. Romanın sayfalarını karıştırırken kucağıma bir not kağıdı düştü.
Kağıdın üzerinde içe içe geçmiş birbirini kesen çemberler vardı, köşesinde
de bir şiir. Sebebini anlamasam da benden bu yazıları yayınlamamı
istediklerini anladım, işte bu genel ağ sayfası da böyle ortaya çıktı.
</p>
<p>
Tüm bu yazılar veya bu yaşadıklarım ne anlama geliyor, inanın bilmiyorum.
Üzerime düşen bu mütevazı vazifeyi yerine getirmekle yetindiğim ve bu
gizemin peşinde düşmediğim için beni mazur görün. Belki de Merhume'nin,
memleketinin, bu yazıların gizemi benden sonrakiler tarafından ortaya
çıkarılır.
</p>
<p><i>Saygı ve sevgilerimle, <br />Furkan Erdem</i></p>
<Footer />
</Layout>

View File

@ -1,36 +0,0 @@
---
import { getCollection } from "astro:content";
import { CATEGORIES } from "@/content/config";
import Header from "@/components/Header.astro";
import Footer from "@/components/Footer.astro";
import Layout from "@/layouts/Layout.astro";
import Post from "@/components/Post.astro";
export function getStaticPaths() {
return CATEGORIES.map((category) => {
return {
params: { category },
};
});
}
const { category } = Astro.params;
const allTeknikPosts = await getCollection(
"blog",
(post) => post.data.category === category
);
---
<Layout title="log101">
<Header />
<div class="posts">
{
allTeknikPosts
.sort((p1, p2) => p2.data.date.getTime() - p1.data.date.getTime())
.map((p) => <Post post={p} componentType="long" />)
}
</div>
<Footer />
</Layout>

View File

@ -18,6 +18,6 @@ const allTeknikPosts = await getCollection("blog");
.map((p) => <Post post={p} componentType="short" />) .map((p) => <Post post={p} componentType="short" />)
} }
</div> </div>
<a class="text-inherit" href="#">Tüm Yayınlar</a> <a class="text-inherit" href="/posts/1">Tüm Yayınlar</a>
<Footer /> <Footer />
</Layout> </Layout>

View File

@ -0,0 +1,74 @@
---
import type { Page } from "astro";
import { getCollection } from "astro:content";
import Header from "@/components/Header.astro";
import Footer from "@/components/Footer.astro";
import Layout from "@/layouts/Layout.astro";
import Post from "@/components/Post.astro";
export async function getStaticPaths({ paginate }: { paginate: any }) {
const blogEntries = await getCollection("blog");
return paginate(blogEntries, {
pageSize: 3,
});
}
interface Props {
page: Page;
}
const { page } = Astro.props;
const posts = page.data;
const pages = Array.from({ length: page.lastPage }, (_, i) => i + 1);
---
<Layout title="log101">
<Header />
<div class="posts">
{
posts.length > 0 ? (
posts
.sort((p1, p2) => p2.data.date.getTime() - p1.data.date.getTime())
.map((p) => <Post post={p} componentType="long" />)
) : (
<p>
Henüz bu kategoride bir yazı yayınlanmadı. Yazarımızın ilhama veya
teşviğe ihtiyacı olabilir!
</p>
)
}
</div>
{
page.lastPage != 1 && (
<>
<div id="pagination-container" class="flex gap-2">
<a href={page.url.prev} class="no-underline text-inherit">
<button class="cursor-pointer">geri git</button>
</a>
{pages.map((pageNumber) => {
switch (pageNumber) {
case page.currentPage:
return <a>{pageNumber}</a>;
default:
return (
<a
href={`${page.url.current.slice(0, -1)}${pageNumber}`}
class="text-inherit">
{pageNumber}
</a>
);
}
})}
<a href={page.url.next} class="no-underline text-inherit">
<button class="cursor-pointer">ileri git</button>
</a>
</div>
</>
)
}
<Footer />
</Layout>

View File

@ -1,3 +1,5 @@
// https://github.com/Tebs-Lab/conways-game-of-life
import { heavyWeightSpaceshipCell } from "./utils"; import { heavyWeightSpaceshipCell } from "./utils";
/* /*

File diff suppressed because one or more lines are too long