Skip to content

Commit 25aee36

Browse files
authored
Merge pull request #52 from sliitsesc/feat/all-articles-page
Feat/all articles page
2 parents 6c8281e + a5c4e06 commit 25aee36

File tree

8 files changed

+132
-14
lines changed

8 files changed

+132
-14
lines changed

next.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import type { NextConfig } from "next";
22

33
const nextConfig: NextConfig = {
44
/* config options here */
5+
images: {
6+
domains: ["images.unsplash.com"],
7+
},
58
};
69

710
export default nextConfig;

package-lock.json

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import ArticleCard from "@/app/components/Articles/ArticleCard";
2+
import { API_ENDPOINTS } from "@/config/endpoints";
3+
import { getData } from "@/lib/helpers/dataFetchHelper";
4+
import { ApiResponse, SubcategoryType } from "@/types/CommonTypes";
5+
6+
export default async function Page({
7+
params,
8+
}: {
9+
params: { subcategory: string };
10+
}) {
11+
const response: ApiResponse<SubcategoryType> = await getData(
12+
`${API_ENDPOINTS.SUBCATEGORIES}?filters[slug][$eq]=${params.subcategory}&populate=articles`
13+
);
14+
15+
const [{ name, subtitle, articles }] = response.data;
16+
17+
// Map and transform articles to match the expected props
18+
19+
const transformedArticles = articles.map((article: any) => ({
20+
id: article.id,
21+
title: article.title,
22+
description: article.description,
23+
content: article.content || "No content available", // Matches the expected `content` field
24+
imageUrl: article.image?.url || "/placeholder.png", // Matches the expected `imageUrl` field
25+
}));
26+
27+
return (
28+
<>
29+
<section className="flex flex-col items-center justify-center h-[400px] bg-gradient-to-r from-blue-100 to-white text-center px-4">
30+
<h1 className="text-4xl font-bold text-gray-800 mb-4">{name}</h1>
31+
<p className="text-lg text-gray-600 max-w-2xl">{subtitle}</p>
32+
</section>
33+
34+
<ArticleCard name={name} subtitle={subtitle} articles={transformedArticles} />
35+
</>
36+
);
37+
}

src/app/[category]/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ export default async function Page({
1212
const response: ApiResponse<Category> = await getData(
1313
`${API_ENDPOINTS.CATEGORIES}?populate=subcategories&filters[slug][$eq]=${categorySlug}`
1414
);
15+
console.log("API response" , response)
1516

1617
const [{ name, subtitle, subcategories, slug }] = response.data; // select first object in array, and destructure properties
1718

19+
1820
return (
1921
<>
2022
<section className="flex flex-col items-center justify-center h-[400px] bg-gradient-to-r from-blue-100 to-white text-center px-4">
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import Image from "next/image";
2+
3+
interface ArticleCardProps {
4+
name: string;
5+
subtitle: string;
6+
articles: Array<{
7+
description: string;
8+
id: number;
9+
title: string;
10+
content: string;
11+
imageUrl: string;
12+
}>;
13+
}
14+
15+
export default function ArticleCard({ name, subtitle, articles }: ArticleCardProps) {
16+
return (
17+
<section className="p-6">
18+
{/* <h1 className="text-3xl font-bold text-center text-black mb-4">{name}</h1>
19+
<p className="text-center text-gray-600 mb-8">{subtitle}</p> */}
20+
21+
{/* Responsive grid layout */}
22+
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
23+
{articles.map((article) => (
24+
<div
25+
key={article.id}
26+
className="bg-gradient-to-r from-[#eaf5ff98] to-[#f4f9ff86] p-6 rounded-xl"
27+
>
28+
<Image
29+
className="w-full h-[150px] object-cover object-center rounded-lg"
30+
src={article.imageUrl || "/placeholder.png"} // Fallback image if none provided
31+
alt={article.title}
32+
width={1000}
33+
height={1000}
34+
/>
35+
<h2 className="font-semibold text-2xl text-black mt-4">{article.title}</h2>
36+
<p className="text-black m-1">{article.description.slice(0, 100)}...</p>
37+
<button className="bg-transparent text-[#2F7CC4] border-2 border-[#2F7CC4] w-full h-10 rounded-[12px] text-[16px] font-medium hover:bg-[#276ca3] hover:text-white transition flex items-center justify-center">
38+
Explore more
39+
</button>
40+
</div>
41+
))}
42+
</div>
43+
</section>
44+
);
45+
}

src/app/layout.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@ import "./globals.css";
33
import Navbar from "./components/Navbar/Navbar";
44
import "@fontsource/dm-sans";
55
import { API_ENDPOINTS } from "@/config/endpoints";
6-
import { API_URL } from "@/config";
76
import { DM_Sans } from "next/font/google";
87
import Footer from "./components/Footer";
8+
import { ApiResponseSingle, NavbarType } from "@/types/CommonTypes";
9+
import { getData } from "@/lib/helpers/dataFetchHelper";
910

1011
const dmSans = DM_Sans({
1112
subsets: ["latin"],
@@ -23,13 +24,14 @@ export default async function RootLayout({
2324
}: {
2425
children: React.ReactNode;
2526
}) {
26-
const data = await fetch(`${API_URL}${API_ENDPOINTS.NAVBAR}`);
27-
const navbarData = await data.json();
27+
const navbarResponse: ApiResponseSingle<NavbarType> = await getData(
28+
`${API_ENDPOINTS.NAVBAR}`
29+
);
2830

2931
return (
3032
<html lang="en" className={dmSans.variable}>
3133
<body className="antialiased font-sans">
32-
<Navbar data={navbarData?.data} />
34+
<Navbar data={navbarResponse?.data} />
3335
<main>{children}</main>
3436
<Footer />
3537
</body>

src/config/endpoints.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
export const API_ENDPOINTS = {
22
NAVBAR: "/navbar?populate=link&populate=navbarButton",
33
CATEGORIES: "/categories",
4+
SUBCATEGORIES: "/subcategories",
45
};

src/types/CommonTypes.ts

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1+
// strapi image type
12
export interface ImageType {
2-
url: string;
3-
alt: string;
4-
width?: number;
5-
height?: number;
3+
id: string;
4+
documentId: string;
5+
name: string;
6+
alternativeText: string;
7+
caption: string;
8+
width: number;
9+
height: number;
610
}
711

8-
export interface NavbarDataType {
9-
link: NavbarLinkType[];
10-
navbarButton: ButtonType;
12+
export interface NavbarType {
13+
link: LinkType[];
14+
navbarButton: ButtonType[];
1115
}
1216

13-
export interface NavbarLinkType {
17+
export interface LinkType {
18+
id: string;
1419
linkText: string;
15-
linkUrl?: string | null;
20+
linkUrl: string;
1621
}
1722

1823
export interface ButtonType {
@@ -25,6 +30,10 @@ export interface ApiResponse<T> {
2530
data: T[];
2631
}
2732

33+
export interface ApiResponseSingle<T> {
34+
data: T;
35+
}
36+
2837
export interface Category {
2938
id: string;
3039
documentId: string;
@@ -34,6 +43,26 @@ export interface Category {
3443
subcategories: Subcategory[];
3544
}
3645

46+
export interface SubcategoryType {
47+
id: string;
48+
documentId: string;
49+
name: string;
50+
subtitle: string;
51+
slug: string;
52+
articles: Article[];
53+
}
54+
55+
export interface Article {
56+
id: string;
57+
documentId: string;
58+
title: string;
59+
slug: string;
60+
description: string;
61+
category: string;
62+
subcategory: string;
63+
thumbnailImage: ImageType;
64+
}
65+
3766
export interface Subcategory {
3867
id: string;
3968
name: string;

0 commit comments

Comments
 (0)