diff --git a/src/app/(frontend)/blogs/[slug]/page.tsx b/src/app/(frontend)/blogs/[slug]/page.tsx
index 5c5912b..2a72433 100644
--- a/src/app/(frontend)/blogs/[slug]/page.tsx
+++ b/src/app/(frontend)/blogs/[slug]/page.tsx
@@ -3,13 +3,7 @@ import Header from '@/components/common/Header'
import Footer from '@/components/common/Footer'
import { notFound } from 'next/navigation'
import { getBlogBySlug } from '@/lib/payload/blogs'
-import Template1 from '@/components/blogs/templates/Template1'
-import Template2 from '@/components/blogs/templates/Template2'
-
-const templates = {
- template1: Template1,
- template2: Template2,
-} as const
+import { BLOG_TEMPLATES } from '@/lib/blog-templates'
export default async function BlogPage({
params,
@@ -20,7 +14,7 @@ export default async function BlogPage({
const blog = await getBlogBySlug(slug)
if (!blog) return notFound()
- const Template = templates[blog.template]
+ const Template = BLOG_TEMPLATES[blog.template]
return (
<>
diff --git a/src/assets/groupedLeaves.svg b/src/assets/groupedLeaves.svg
new file mode 100644
index 0000000..0fb3bc2
--- /dev/null
+++ b/src/assets/groupedLeaves.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/src/collections/Blogs.ts b/src/collections/Blogs.ts
index cf5cd08..aea7fce 100644
--- a/src/collections/Blogs.ts
+++ b/src/collections/Blogs.ts
@@ -33,9 +33,7 @@ export const Blogs: CollectionConfig = {
beforeValidate: [
async ({ data = {}, originalDoc, req, operation }) => {
const baseSource =
- data.slug ||
- data.title ||
- (operation === 'update' ? originalDoc?.title : '')
+ data.slug || data.title || (operation === 'update' ? originalDoc?.title : '')
const base = slugify((baseSource || '').toString(), {
lower: true,
@@ -103,6 +101,8 @@ export const Blogs: CollectionConfig = {
options: [
{ label: 'Template 1', value: 'template1' },
{ label: 'Template 2', value: 'template2' },
+ { label: 'Template 3', value: 'template3' },
+ { label: 'Template 4', value: 'template4' },
],
admin: {
description: 'Select which layout template to use when rendering this blog.',
diff --git a/src/components/blogs/templates/Template3.tsx b/src/components/blogs/templates/Template3.tsx
new file mode 100644
index 0000000..8e8dda0
--- /dev/null
+++ b/src/components/blogs/templates/Template3.tsx
@@ -0,0 +1,132 @@
+import React from 'react'
+import Image from 'next/image'
+import gL from '@/assets/groupedLeaves.svg'
+import authorImage from '@/assets/people_placeholder.png'
+import type { BlogType } from '@/types/blog'
+
+interface Template3Props {
+ blog: BlogType
+}
+
+export default function Template3({ blog }: Template3Props) {
+ return (
+
+ {/* Navigation section */}
+
+
+
+ BLOGS {'>'}{' '}
+ {/* TODO: Remove placeholder fields once the field is added to Payload blog collection */}
+ {
+ // blog.category ||
+ 'Behind the Scenes'} :{' '}
+ {blog.title}
+
+
+
+
+ {/* Hero block */}
+
+
+
+
+
+ {/* TODO: Remove placeholder fields once the field is added to Payload blog collection */}
+ {
+ // blog.category ||
+ 'Behind the Scenes'}
+
+
+ {blog.title}
+
+
{blog.description}
+
+ Written By:
+ {blog.authorName}
+
+
+
+
+
+ {/* Content + Sidebar Image */}
+
+
+
+ child.type === 'paragraph'
+ ? `
${(child.children ?? [])
+ .map((c: any) => c.text || '')
+ .join('')}
`
+ : '',
+ )
+ .join('') || 'Content coming soon...',
+ }}
+ />
+
+
+
+
+
+
+
+ {/* TODO: Remove placeholder fields once the field is added to Payload blog collection */}
+ {
+ // blog.quote ||
+ `"Insert an inspirational quote here!"`}
+
+ {/* TODO: Remove placeholder fields once the field is added to Payload blog collection */}
+
{
+ // blog.quoteAuthor ||
+ '- Author'}
+
+
+
+
+
+ {/* About the Author */}
+
+
+
+
+
+
About the Author
+
+ {/* TODO: Remove placeholder fields once the field is added to Payload blog collection */}
+ {
+ // blog.authorBio ||
+ 'This is a short bio about the author. They share stories, insights, and moments that inspire others.'}
+
+
+
+
+
+ {/* Bottom Decoration */}
+
+
+
+
+
+ )
+}
diff --git a/src/components/blogs/templates/Template4.tsx b/src/components/blogs/templates/Template4.tsx
new file mode 100644
index 0000000..704c9c3
--- /dev/null
+++ b/src/components/blogs/templates/Template4.tsx
@@ -0,0 +1,187 @@
+import React from 'react'
+import Image from 'next/image'
+import bigGreenKoru from '@/assets/bigGreenKoru.png'
+import leaf from '@/assets/leaf.svg'
+import type { BlogType } from '@/types/blog'
+
+interface Template3Props {
+ blog: BlogType
+}
+
+export default function Template4({ blog }: Template3Props) {
+ // Split content into different sections
+ const getContentSections = () => {
+ const paragraphs =
+ blog.content?.root?.children
+ ?.filter((child: any) => child.type === 'paragraph')
+ ?.map((child: any) => (child.children ?? []).map((c: any) => c.text || '').join('')) || []
+
+ const totalParagraphs = paragraphs.length
+ const sectionSize = Math.ceil(totalParagraphs / 3)
+
+ return {
+ section1: paragraphs.slice(0, sectionSize),
+ section2: paragraphs.slice(sectionSize, sectionSize * 2),
+ section3: paragraphs.slice(sectionSize * 2),
+ }
+ }
+
+ const contentSections = getContentSections()
+
+ const renderContent = (paragraphs: string[]) => {
+ if (paragraphs.length === 0) return 'Content coming soon...'
+ return paragraphs.map((text, index) => `${text}
`).join('')
+ }
+
+ return (
+
+ {/* Breadcrumb Navigation */}
+
+
+
+ BLOGS {'>'} Stories :{' '}
+ {blog.title}
+
+
+
+ Written By:
+ {blog.authorName}
+
+
+
+
+ {/* Hero Section */}
+
+ Stories
+
+
+ {blog.title}
+
+
+ {/* Large decorative koru background */}
+
+
+
+
+ {blog.description && (
+
+ {blog.description}
+
+ )}
+
+ {/* Main Content Section */}
+
+
+ {/* First Row - Image Left, Text Right */}
+
+
+
+
+
+ {/* Decorative leaves */}
+
+
+
+
+
+
+
+
+
+
+
+ {/* Second Row - Text Left, Image Right */}
+
+
+
+
+
+
+
+ {/* Blue koru decoration */}
+
+
+
+
+
+
+ {/* Quote Section */}
+
+ {/* TODO: Remove the placeholder quote once the field is added to Payload blog collection */}
+
+ "it doloribus ut rerum culpa est eligendi veniam Aut quia en assumenda eum pa
+ nostrum vel"
+
+
+
+
+ {/* Third Row - Image Left, Text Right */}
+
+
+
+
+
+ {/* Decorative leaves */}
+
+
+
+
+
+
+
+
+
+
+
+ {/* Bottom decorative leaves */}
+
+
+
+
+
+ )
+}
diff --git a/src/lib/blog-templates.ts b/src/lib/blog-templates.ts
new file mode 100644
index 0000000..be9bf3e
--- /dev/null
+++ b/src/lib/blog-templates.ts
@@ -0,0 +1,16 @@
+import Template1 from '@/components/blogs/templates/Template1'
+import Template2 from '@/components/blogs/templates/Template2'
+import Template3 from '@/components/blogs/templates/Template3'
+import Template4 from "@/components/blogs/templates/Template4";
+
+// All valid template keys
+export const TEMPLATE_KEYS = ['template1', 'template2', 'template3', 'template4'] as const
+export type TemplateKey = typeof TEMPLATE_KEYS[number]
+
+// Map of key -> actual React component
+export const BLOG_TEMPLATES: Record> = {
+ template1: Template1,
+ template2: Template2,
+ template3: Template3,
+ template4: Template4,
+}
diff --git a/src/lib/mapBlog.ts b/src/lib/mapBlog.ts
index bdf12e7..e611325 100644
--- a/src/lib/mapBlog.ts
+++ b/src/lib/mapBlog.ts
@@ -1,6 +1,7 @@
import type { Blog } from '@/payload-types'
import placeholderImage from '@/assets/landscape_placeholder.png'
-import { TEMPLATE_KEYS, type TemplateKey, type BlogType } from '@/types/blog'
+import { type BlogType } from '@/types/blog'
+import { TEMPLATE_KEYS, type TemplateKey } from "@/lib/blog-templates";
export function mapPayloadBlog(b: Blog): BlogType {
const template: TemplateKey = TEMPLATE_KEYS.includes(b.template as TemplateKey)
diff --git a/src/lib/payload/blogs.ts b/src/lib/payload/blogs.ts
index e8e3564..38410fd 100644
--- a/src/lib/payload/blogs.ts
+++ b/src/lib/payload/blogs.ts
@@ -2,16 +2,7 @@ import { fetchJSON } from './client';
import type { Blog } from '@/payload-types';
import {mapPayloadBlog} from "@/lib/mapBlog";
import {BlogType} from "@/types/blog";
-
-type Paginated = {
- docs: T[];
- totalDocs: number;
- limit: number;
- page: number;
- totalPages: number;
- hasNextPage: boolean;
- hasPrevPage: boolean;
-};
+import type {Paginated} from "@/types/pagination";
export async function getBlogs(opts: { page?: number; limit?: number } = {}) {
diff --git a/src/lib/payload/events.ts b/src/lib/payload/events.ts
index d5fbd5d..dc20fd8 100644
--- a/src/lib/payload/events.ts
+++ b/src/lib/payload/events.ts
@@ -2,16 +2,8 @@ import { mapPayloadEvent } from '@/lib/mapEvent'
import { EventType } from '@/types/event'
import type { Event } from '@/payload-types'
import {fetchJSON} from "@/lib/payload/client";
+import type {Paginated} from "@/types/pagination";
-type Paginated = {
- docs: T[];
- totalDocs: number;
- limit: number;
- page: number;
- totalPages: number;
- hasNextPage: boolean;
- hasPrevPage: boolean;
-};
/**
* Fetch upcoming events (future-dated).
diff --git a/src/lib/payload/members.ts b/src/lib/payload/members.ts
index a6f9b1f..8684da1 100644
--- a/src/lib/payload/members.ts
+++ b/src/lib/payload/members.ts
@@ -1,20 +1,9 @@
-import { fetchJSON } from './client'
-import type { Member } from '@/payload-types'
+import {fetchJSON} from './client'
+import type {Member} from '@/payload-types'
+import type {Paginated} from "@/types/pagination";
-type PaginatedResponse = {
- docs: Member[]
- totalDocs: number
- limit: number
- totalPages: number
- page: number
- pagingCounter: number
- hasPrevPage: boolean
- hasNextPage: boolean
- prevPage: number | null
- nextPage: number | null
-}
export async function getMembers() {
- const data = await fetchJSON('/api/members?depth=2&sort=createdAt&limit=100')
+ const data = await fetchJSON>('/api/members?depth=2&sort=createdAt&limit=100')
return data.docs
}
diff --git a/src/payload-types.ts b/src/payload-types.ts
index c388b82..60da439 100644
--- a/src/payload-types.ts
+++ b/src/payload-types.ts
@@ -201,7 +201,7 @@ export interface Blog {
/**
* Select which layout template to use when rendering this blog.
*/
- template: 'template1' | 'template2';
+ template: 'template1' | 'template2' | 'template3' | 'template4';
published?: boolean | null;
updatedAt: string;
createdAt: string;
diff --git a/src/types/blog.ts b/src/types/blog.ts
index 5b46a95..ce94394 100644
--- a/src/types/blog.ts
+++ b/src/types/blog.ts
@@ -1,7 +1,5 @@
import { StaticImageData } from 'next/image'
-
-export const TEMPLATE_KEYS = ['template1', 'template2'] as const
-export type TemplateKey = typeof TEMPLATE_KEYS[number]
+import type {TemplateKey} from '@/lib/blog-templates'
export type BlogType = {
id: string
diff --git a/src/types/pagination.ts b/src/types/pagination.ts
new file mode 100644
index 0000000..b52e311
--- /dev/null
+++ b/src/types/pagination.ts
@@ -0,0 +1,12 @@
+export type Paginated = {
+ docs: T[]
+ totalDocs: number
+ limit: number
+ totalPages: number
+ page: number
+ hasNextPage?: boolean
+ hasPrevPage?: boolean
+ pagingCounter?: number
+ prevPage?: number | null
+ nextPage?: number | null
+}