project setup

This commit is contained in:
Al Murad Uzzaman
2024-05-14 15:34:22 +06:00
parent d34a3f5489
commit ac6fa96c9c
86 changed files with 1966 additions and 293 deletions
+16 -6
View File
@@ -1,5 +1,18 @@
---
import Base from "@/layouts/Base.astro";
import config from "@/config/config.json";
import { getLangFromUrl, useTranslations } from "@/lib/utils/i18nUtils";
export function getStaticPaths() {
const {supported} = config.language;
const paths = supported.map((lang) => ({ params: { lang: lang || undefined } }));
return paths;
}
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang as any);
const {defaultLang} = config.language;
const href = lang && lang !== defaultLang ? `/${lang}/` : "/";
---
<Base title="Page Not Found">
@@ -12,14 +25,11 @@ import Base from "@/layouts/Base.astro";
>
404
</span>
<h1 class="h2 mb-4">Page not found</h1>
<h1 class="h2 mb-4">{t("page_not_found")}</h1>
<div class="content">
<p>
The page you are looking for might have been removed, had its name
changed, or is temporarily unavailable.
</p>
<p>{t("page_not_found_content")}</p>
</div>
<a href="/" class="btn btn-primary mt-8">Back to home</a>
<a href={href} class="btn btn-primary mt-8">{t("back_to_home")}</a>
</div>
</div>
</div>
@@ -1,21 +1,29 @@
---
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import PageHeader from "@/partials/PageHeader.astro";
import type { ContentEntryMap } from "astro:content";
// get static paths for all pages
export async function getStaticPaths() {
const COLLECTION_FOLDER = "pages";
const { supported } = config.language;
const pages = await getSinglePage(COLLECTION_FOLDER);
const paths = await Promise.all(
supported.map(async (lang) => {
const pages = await getSinglePage("pages", lang as keyof ContentEntryMap);
const paths = pages.map((page) => ({
params: {
regular: page.slug,
},
props: { page },
}));
return paths;
return pages.map((page) => ({
params: {
lang: lang || undefined,
regular: page.slug.split("/").pop(),
},
props: {
page,
},
}));
})
);
return paths.flat();
}
const { page } = Astro.props;
@@ -2,11 +2,22 @@
import ImageMod from "@/components/ImageMod.astro";
import Base from "@/layouts/Base.astro";
import { markdownify } from "@/lib/utils/textConverter";
import { getEntry } from "astro:content";
import type { ContentEntryMap } from "astro:content";
import { getCollection } from "astro:content";
import config from "@/config/config.json";
import { getListPage } from "@/lib/contentParser.astro";
const about = await getEntry("about", "-index");
const { Content } = await about.render();
const { title, description, meta_title, image } = about.data;
export function getStaticPaths() {
const {supported} = config.language;
const paths = supported.map((lang) => ({ params: { lang: lang || undefined } }));
return paths;
}
const { lang } = Astro.params;
const about = await getListPage("about", lang as keyof ContentEntryMap);
const { Content } = await about[0].render();
const { title, description, meta_title, image } = about[0].data;
---
<Base
@@ -2,33 +2,46 @@
import BlogCard from "@/components/BlogCard.astro";
import ImageMod from "@/components/ImageMod.astro";
import Social from "@/components/Social.astro";
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import { slugify } from "@/lib/utils/textConverter";
import type { ContentEntryMap } from "astro:content";
import { getCollection } from "astro:content";
// get all static paths for authors
export async function getStaticPaths() {
const { supported } = config.language;
const COLLECTION_FOLDER = "authors";
const authors = await getSinglePage(COLLECTION_FOLDER);
const paths = authors.map((author) => ({
params: {
single: author.slug,
},
props: { author },
}));
return paths;
const paths = await Promise.all(
supported.map(async (lang) => {
const authors = await getSinglePage(COLLECTION_FOLDER, lang as keyof ContentEntryMap);
return authors.map((author) => ({
params: {
lang: lang || undefined,
single: author.slug.split("/").pop(),
},
props: {
author,
lang
},
}));
})
);
return paths.flat();
}
const { author } = Astro.props;
const { author, lang } = Astro.props;
const { title, social, meta_title, description, image } = author.data;
const { Content } = await author.render();
// get all posts by author
const BLOG_FOLDER = "blog";
const posts = await getSinglePage(BLOG_FOLDER);
const posts = await getSinglePage(BLOG_FOLDER, lang as keyof ContentEntryMap);
const postFilterByAuthor = posts.filter(
(post) => slugify(post.data.author) === slugify(title),
(post) => slugify(post.data.author) === slugify(title)
);
---
+45
View File
@@ -0,0 +1,45 @@
---
import AuthorCard from "@/components/AuthorCard.astro";
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getListPage, getSinglePage } from "@/lib/contentParser.astro";
import PageHeader from "@/partials/PageHeader.astro";
import { type ContentEntryMap } from "astro:content";
const COLLECTION_FOLDER = "authors";
export function getStaticPaths() {
const { supported } = config.language;
const paths = supported.map((lang) => ({
params: { lang: lang || undefined },
}));
return paths;
}
const { lang } = Astro.params;
const authorIndex = await getListPage(
COLLECTION_FOLDER,
lang as keyof ContentEntryMap
);
const authors = await getSinglePage(
COLLECTION_FOLDER,
lang as keyof ContentEntryMap
);
---
<Base title={authorIndex[0].data.title}>
<PageHeader title={authorIndex[0].data.title} />
<section class="section-sm pb-0">
<div class="container">
<div class="row justify-center">
{
authors.map((author) => (
<div class="mb-14 md:col-6 lg:col-4">
<AuthorCard data={author} />
</div>
))
}
</div>
</div>
</section>
</Base>
+41
View File
@@ -0,0 +1,41 @@
---
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import PostSingle from "@/layouts/PostSingle.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import type { ContentEntryMap } from "astro:content";
import { getCollection } from "astro:content";
export async function getStaticPaths() {
const { supported } = config.language;
const BLOG_FOLDER = "blog";
const paths = await Promise.all(
supported.map(async (lang) => {
const posts = await getSinglePage(BLOG_FOLDER, lang as keyof ContentEntryMap);
return posts.map((post) => ({
params: {
lang: lang || undefined,
single: post.slug.split("/").pop(),
},
props: {
post,
},
}));
})
);
return paths.flat();
}
const { post } = Astro.props;
const { title, meta_title, description, image } = post.data;
---
<Base
title={title}
meta_title={meta_title}
description={description}
image={image}
>
<PostSingle post={post} />
</Base>
@@ -3,32 +3,43 @@ import BlogCard from "@/components/BlogCard.astro";
import Pagination from "@/components/Pagination.astro";
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import { getListPage, getSinglePage } from "@/lib/contentParser.astro";
import { getAllTaxonomy, getTaxonomy } from "@/lib/taxonomyParser.astro";
import { sortByDate } from "@/lib/utils/sortFunctions";
import PageHeader from "@/partials/PageHeader.astro";
import PostSidebar from "@/partials/PostSidebar.astro";
import { getEntry } from "astro:content";
import type { ContentEntryMap } from "astro:content";
export function getStaticPaths() {
const { supported } = config.language;
const paths = supported.map((lang) => ({
params: { lang: lang || undefined },
}));
return paths;
}
const { lang } = Astro.params;
const BLOG_FOLDER = "blog";
// const postIndex = await getListPage(BLOG_FOLDER, lang as keyof ContentEntryMap);
const postIndex: any
= await getListPage(BLOG_FOLDER, lang as keyof ContentEntryMap);
const langCollection: keyof ContentEntryMap = lang as keyof ContentEntryMap;
const posts = await getSinglePage(BLOG_FOLDER, lang as keyof ContentEntryMap);
const postIndex = await getEntry(BLOG_FOLDER, "-index");
const posts = await getSinglePage(BLOG_FOLDER);
const allCategories = await getAllTaxonomy(BLOG_FOLDER, "categories");
const categories = await getTaxonomy(BLOG_FOLDER, "categories");
const tags = await getTaxonomy(BLOG_FOLDER, "tags");
const allCategories = await getAllTaxonomy(langCollection, "categories");
const categories = await getTaxonomy(langCollection, "categories");
const tags = await getTaxonomy(langCollection, "tags");
const sortedPosts = sortByDate(posts);
const totalPages: number = Math.ceil(posts.length / config.settings.pagination);
const currentPosts = sortedPosts.slice(0, config.settings.pagination);
---
<Base
title={postIndex.data.title}
meta_title={postIndex.data.meta_title}
image={postIndex.data.image}
description={postIndex.data.description}
title={postIndex[0].data.title}
meta_title={postIndex[0].data.meta_title}
image={postIndex[0].data.image}
description={postIndex[0].data.description}
>
<PageHeader title={postIndex.data.title} />
<PageHeader title={postIndex[0].data.title} />
<section class="section">
<div class="container">
<div class="row gx-5">
@@ -3,21 +3,32 @@ import BlogCard from "@/components/BlogCard.astro";
import Pagination from "@/components/Pagination.astro";
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import { getAllTaxonomy, getTaxonomy } from "@/lib/taxonomyParser.astro";
import { sortByDate } from "@/lib/utils/sortFunctions";
import PageHeader from "@/partials/PageHeader.astro";
import PostSidebar from "@/partials/PostSidebar.astro";
import { getEntry } from "astro:content";
import type { ContentEntryMap } from "astro:content";
import { getCollection } from "astro:content";
const BLOG_FOLDER = "blog";
const { slug } = Astro.params;
const postIndex = await getEntry(BLOG_FOLDER, "-index");
const posts = await getSinglePage(BLOG_FOLDER);
const allCategories = await getAllTaxonomy(BLOG_FOLDER, "categories");
const categories = await getTaxonomy(BLOG_FOLDER, "categories");
const tags = await getTaxonomy(BLOG_FOLDER, "tags");
const { slug, lang } = Astro.params;
const postIndex = await getCollection(
lang as keyof ContentEntryMap,
({ id }) => {
return id.startsWith(BLOG_FOLDER);
}
);
const posts = await getCollection(lang as keyof ContentEntryMap, ({ id }) => {
return id.startsWith(BLOG_FOLDER) && !id.endsWith("-index.md");
});
const langCollection: keyof ContentEntryMap = lang as keyof ContentEntryMap;
const allCategories = await getAllTaxonomy(langCollection, "categories");
const categories = await getTaxonomy(langCollection, "categories");
const tags = await getTaxonomy(langCollection, "tags");
const sortedPosts = sortByDate(posts);
const totalPages = Math.ceil(posts.length / config.settings.pagination);
const currentPage = slug && !isNaN(Number(slug)) ? Number(slug) : 1;
@@ -26,29 +37,46 @@ const indexOfFirstPost = indexOfLastPost - config.settings.pagination;
const currentPosts = sortedPosts.slice(indexOfFirstPost, indexOfLastPost);
export async function getStaticPaths() {
const { supported } = config.language;
const BLOG_FOLDER = "blog";
const posts = await getSinglePage(BLOG_FOLDER);
const totalPages = Math.ceil(posts.length / config.settings.pagination);
const paths = [];
for (let i = 1; i < totalPages; i++) {
paths.push({
params: {
slug: (i + 1).toString(),
},
});
}
return paths;
const paths = await Promise.all(
supported.map(async (lang) => {
const posts = await getCollection(
lang as keyof ContentEntryMap,
({ id }) => {
return id.startsWith(BLOG_FOLDER) && !id.endsWith("-index.md");
}
);
const totalPages = Math.ceil(posts.length / config.settings.pagination);
const langString = lang.toString();
const langPaths = [];
for (let i = 1; i < totalPages; i++) {
langPaths.push({
params: {
lang: langString,
slug: (i + 1).toString(),
},
});
}
return langPaths;
})
);
return paths.flat();
}
---
<Base
title={postIndex.data.title}
meta_title={postIndex.data.meta_title}
image={postIndex.data.image}
description={postIndex.data.description}
title={postIndex[0].data.title}
meta_title={postIndex[0].data.meta_title}
image={postIndex[0].data.image}
description={postIndex[0].data.description}
>
<PageHeader title={postIndex.data.title} />
<PageHeader title={postIndex[0].data.title} />
<section class="section">
<div class="container">
<div class="row gx-5">
@@ -1,5 +1,6 @@
---
import BlogCard from "@/components/BlogCard.astro";
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import { getTaxonomy } from "@/lib/taxonomyParser.astro";
@@ -7,23 +8,33 @@ import { sortByDate } from "@/lib/utils/sortFunctions";
import taxonomyFilter from "@/lib/utils/taxonomyFilter";
import PageHeader from "@/partials/PageHeader.astro";
// get static paths for all categories
// get all static paths for categories
export async function getStaticPaths() {
const BLOG_FOLDER = "blog";
const categories = await getTaxonomy(BLOG_FOLDER, "categories");
const { supported } = config.language;
return categories.map((category) => {
return {
params: { category },
};
});
const paths = await Promise.all(
supported.map(async (lang) => {
const categories = await getTaxonomy(lang, "categories");
return categories.map((category) => ({
params: {
lang: lang || undefined,
category: category,
},
props: {
category,
},
}));
})
);
return paths.flat();
}
const { category } = Astro.params;
const { category, lang } = Astro.params;
// get posts by category
const BLOG_FOLDER = "blog";
const posts = await getSinglePage(BLOG_FOLDER);
const posts = await getSinglePage(BLOG_FOLDER, lang as any);
const filterByCategories = taxonomyFilter(posts, "categories", category!);
const sortedPosts = sortByDate(filterByCategories);
---
@@ -3,11 +3,19 @@ import Base from "@/layouts/Base.astro";
import { getAllTaxonomy, getTaxonomy } from "@/lib/taxonomyParser.astro";
import { humanize } from "@/lib/utils/textConverter";
import PageHeader from "@/partials/PageHeader.astro";
import config from "@/config/config.json";
import type { ContentEntryMap } from "astro:content";
const BLOG_FOLDER = "blog";
export function getStaticPaths() {
const {supported } = config.language;
const paths = supported.map((lang) => ({ params: { lang: lang || undefined } }));
return paths;
}
const categories = await getTaxonomy(BLOG_FOLDER, "categories");
const allCategories = await getAllTaxonomy(BLOG_FOLDER, "categories");
const { lang } = Astro.params;
const langCollection: keyof ContentEntryMap = lang as keyof ContentEntryMap;
const categories = await getTaxonomy(langCollection, "categories");
const allCategories = await getAllTaxonomy(langCollection, "categories");
---
<Base title={"Categories"}>
@@ -21,7 +29,7 @@ const allCategories = await getAllTaxonomy(BLOG_FOLDER, "categories");
return (
<li class="m-3 inline-block">
<a
href={`/categories/${category}`}
href={`/${lang === "en" ? "categories" + "/" : lang}/categories/${category}`}
class="block rounded bg-theme-light px-4 py-2 text-xl text-dark dark:bg-darkmode-theme-light dark:text-darkmode-dark"
>
{humanize(category)}{" "}
@@ -1,12 +1,24 @@
---
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getListPage } from "@/lib/contentParser.astro";
import { useTranslations } from "@/lib/utils/i18nUtils";
import PageHeader from "@/partials/PageHeader.astro";
import { getEntry } from "astro:content";
import { type ContentEntryMap } from "astro:content";
export function getStaticPaths() {
const {supported} = config.language;
const paths = supported.map((lang) => ({ params: { lang: lang || undefined } }));
return paths;
}
const { lang } = Astro.params;
const contact = await getListPage("contact", lang as keyof ContentEntryMap);
const contact = await getEntry("contact", "-index");
const { contact_form_action }: { contact_form_action: string } = config.params;
const { title, description, meta_title, image } = contact.data;
const { title, description, meta_title, image } = contact[0].data;
const t = useTranslations(lang as any);
---
<Base
@@ -23,7 +35,8 @@ const { title, description, meta_title, image } = contact.data;
<form action={contact_form_action} method="POST">
<div class="mb-6">
<label for="name" class="form-label">
Full Name <span class="text-red-500">*</span>
{t("full_name")}
<span class="text-red-500">*</span>
</label>
<input
id="name"
@@ -35,7 +48,7 @@ const { title, description, meta_title, image } = contact.data;
</div>
<div class="mb-6">
<label for="email" class="form-label">
Working Mail <span class="text-red-500">*</span>
{t("working_mail")} <span class="text-red-500">*</span>
</label>
<input
id="email"
@@ -47,16 +60,16 @@ const { title, description, meta_title, image } = contact.data;
</div>
<div class="mb-6">
<label for="message" class="form-label">
Anything else? <span class="text-red-500">*</span>
{t("anything_else")} <span class="text-red-500">*</span>
</label>
<textarea
id="message"
name="message"
class="form-input"
placeholder="Message goes here..."
placeholder={t("contact_message_placeholder")}
rows="8"></textarea>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="submit" class="btn btn-primary">{t("submit")}</button>
</form>
</div>
</div>
@@ -1,12 +1,16 @@
---
import ImageMod from "@/components/ImageMod.astro";
import config from "@/config/config.json";
import Base from "@/layouts/Base.astro";
import { getListPage } from "@/lib/contentParser.astro";
import { markdownify } from "@/lib/utils/textConverter";
import CallToAction from "@/partials/CallToAction.astro";
import Testimonial from "@/partials/Testimonial.astro";
import type { Button, Feature } from "@/types";
import { getEntry } from "astro:content";
import type { ContentEntryMap } from "astro:content";
import { getCollection } from "astro:content";
import { FaCheck } from "react-icons/fa";
const { defaultLang } = config.language;
interface Homepage {
banner: {
@@ -18,10 +22,35 @@ interface Homepage {
features: Feature[];
}
const homepage = await getEntry("homepage", "-index");
const testimonial = await getEntry("sections", "testimonial");
const call_to_action = await getEntry("sections", "call-to-action");
const { banner, features }: Homepage = homepage.data;
export function getStaticPaths() {
const { supported } = config.language;
const paths = supported.map((lang) => ({
params: { lang: lang || undefined },
}));
return paths;
}
const { lang } = Astro.params;
const homepage = await getListPage("homepage", lang as keyof ContentEntryMap);
// const testimonial = await getEntry("sections", "testimonial");
// const call_to_action = await getEntry("sections", "call-to-action");
const { banner, features }: Homepage = homepage[0].data;
const testimonial = await getCollection(
(lang as keyof ContentEntryMap) || defaultLang,
({ id }) => {
return id.startsWith("sections/testimonial") && !id.endsWith("-index.md");
}
);
const call_to_action = await getCollection(
(lang as keyof ContentEntryMap) || defaultLang,
({ id }) => {
return (
id.startsWith("sections/call-to-action") && !id.endsWith("-index.md")
);
}
);
---
<Base>
@@ -109,6 +138,6 @@ const { banner, features }: Homepage = homepage.data;
}
<!-- /Features -->
<Testimonial testimonial={testimonial} />
<CallToAction call_to_action={call_to_action} />
<Testimonial testimonial={testimonial[0]} />
<CallToAction call_to_action={call_to_action[0]} />
</Base>
-29
View File
@@ -1,29 +0,0 @@
---
import AuthorCard from "@/components/AuthorCard.astro";
import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import PageHeader from "@/partials/PageHeader.astro";
import { getEntry } from "astro:content";
const COLLECTION_FOLDER = "authors";
const authorIndex = await getEntry(COLLECTION_FOLDER, "-index");
const authors = await getSinglePage(COLLECTION_FOLDER);
---
<Base title={authorIndex.data.title}>
<PageHeader title={authorIndex.data.title} />
<section class="section-sm pb-0">
<div class="container">
<div class="row justify-center">
{
authors.map((author) => (
<div class="mb-14 md:col-6 lg:col-4">
<AuthorCard data={author} />
</div>
))
}
</div>
</div>
</section>
</Base>
-30
View File
@@ -1,30 +0,0 @@
---
import Base from "@/layouts/Base.astro";
import PostSingle from "@/layouts/PostSingle.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
export async function getStaticPaths() {
const BLOG_FOLDER = "blog";
const posts = await getSinglePage(BLOG_FOLDER);
const paths = posts.map((post) => ({
params: {
single: post.slug,
},
props: { post },
}));
return paths;
}
const { post } = Astro.props;
const { title, meta_title, description, image } = post.data;
---
<Base
title={title}
meta_title={meta_title}
description={description}
image={image}
>
<PostSingle post={post} />
</Base>
-45
View File
@@ -1,45 +0,0 @@
---
import BlogCard from "@/components/BlogCard.astro";
import Base from "@/layouts/Base.astro";
import { getSinglePage } from "@/lib/contentParser.astro";
import { getTaxonomy } from "@/lib/taxonomyParser.astro";
import { sortByDate } from "@/lib/utils/sortFunctions";
import taxonomyFilter from "@/lib/utils/taxonomyFilter";
import PageHeader from "@/partials/PageHeader.astro";
export async function getStaticPaths() {
const BLOG_FOLDER = "blog";
const tags = await getTaxonomy(BLOG_FOLDER, "tags");
return tags.map((tag) => {
return {
params: { tag },
};
});
}
const { tag } = Astro.params;
// get posts by tag
const BLOG_FOLDER = "blog";
const posts = await getSinglePage(BLOG_FOLDER);
const filterByTags = taxonomyFilter(posts, "tags", tag!);
const sortedPosts = sortByDate(filterByTags);
---
<Base title={tag}>
<PageHeader title={tag} />
<div class="section-sm pb-0">
<div class="container">
<div class="row">
{
sortedPosts.map((post) => (
<div class="mb-14 md:col-6 lg:col-4">
<BlogCard data={post} />
</div>
))
}
</div>
</div>
</div>
</Base>
-39
View File
@@ -1,39 +0,0 @@
---
import Base from "@/layouts/Base.astro";
import { getAllTaxonomy, getTaxonomy } from "@/lib/taxonomyParser.astro";
import { humanize } from "@/lib/utils/textConverter";
import PageHeader from "@/partials/PageHeader.astro";
const BLOG_FOLDER = "blog";
const tags = await getTaxonomy(BLOG_FOLDER, "tags");
const allTags = await getAllTaxonomy(BLOG_FOLDER, "tags");
---
<Base title={"Tags"}>
<PageHeader title={"Tags"} />
<section class="section">
<div class="container text-center">
<ul>
{
tags.map((tag: any) => {
const count = allTags.filter((c) => c === tag).length;
return (
<li class="m-3 inline-block">
<a
href={`/tags/${tag}`}
class="block rounded bg-theme-light px-4 py-2 text-xl text-dark dark:bg-darkmode-theme-light dark:text-darkmode-dark"
>
{humanize(tag)}{" "}
<span class="ml-2 rounded bg-body px-2 dark:bg-darkmode-body">
{count}
</span>
</a>
</li>
);
})
}
</ul>
</div>
</section>
</Base>