diff --git a/next/src/app/about/styles.module.scss b/next/src/app/about/styles.module.scss index 9ab44bc..79e557b 100644 --- a/next/src/app/about/styles.module.scss +++ b/next/src/app/about/styles.module.scss @@ -20,6 +20,6 @@ } .mainContent { - margin-top: 3rem; + margin-top: 2rem; } } diff --git a/next/src/app/blog/[slug]/(blog-header)/BlogHeader.tsx b/next/src/app/blog/[slug]/(blog-header)/BlogHeader.tsx index c7823ab..4a0ea1a 100644 --- a/next/src/app/blog/[slug]/(blog-header)/BlogHeader.tsx +++ b/next/src/app/blog/[slug]/(blog-header)/BlogHeader.tsx @@ -2,6 +2,7 @@ import React, { FunctionComponent } from 'react'; import gStyles from '@/styles/global.module.scss'; import styles from './styles.module.scss'; import { Post } from '@/components/blog-post-item/types'; +import Categories from '@/components/categories/Categories'; interface Props { post: Post; @@ -13,13 +14,7 @@ const BlogHeader: FunctionComponent = ({ post }) => { return (

{post.attributes.title}

- {Boolean(categories?.length) && categories && ( - - )} +
); }; diff --git a/next/src/app/blog/[slug]/(blog-header)/styles.module.scss b/next/src/app/blog/[slug]/(blog-header)/styles.module.scss index dfda350..3c8aab5 100644 --- a/next/src/app/blog/[slug]/(blog-header)/styles.module.scss +++ b/next/src/app/blog/[slug]/(blog-header)/styles.module.scss @@ -1,7 +1,3 @@ .heading { text-transform: initial; -} - -.categories { - margin-bottom: 2rem; } \ No newline at end of file diff --git a/next/src/app/blog/page.tsx b/next/src/app/blog/page.tsx index e04a310..bb103b5 100644 --- a/next/src/app/blog/page.tsx +++ b/next/src/app/blog/page.tsx @@ -4,20 +4,23 @@ import styles from './styles.module.scss'; import BlogPostItem from '@/components/blog-post-item/BlogPostItem'; import React from 'react'; import { db } from '@/scripts/fetch'; +import Categories from '@/components/categories/Categories'; -const Page: NextPage = async () => { - const posts = await db.getPosts(); +interface Props { + searchParams: { + category?: string; + }; +} + +const Page: NextPage = async ({ searchParams: { category } }) => { + const posts = category ? await db.getPostsByCategory(category) : await db.getPosts(); const categories = await db.getCategories(); return (

Blog

-
    - {categories.data.map((category) => ( -
  • #{category.attributes.name}
  • - ))} -
+
{posts.data.map((post) => )}
diff --git a/next/src/app/blog/styles.module.scss b/next/src/app/blog/styles.module.scss index 9bf494e..6223f4c 100644 --- a/next/src/app/blog/styles.module.scss +++ b/next/src/app/blog/styles.module.scss @@ -1,6 +1,5 @@ @import '@/styles/vars'; .blogs { - margin-top: 3rem; gap: 3rem; } \ No newline at end of file diff --git a/next/src/components/blog-post-item/types.ts b/next/src/components/blog-post-item/types.ts index 3261287..fb42a5a 100644 --- a/next/src/components/blog-post-item/types.ts +++ b/next/src/components/blog-post-item/types.ts @@ -1,14 +1,4 @@ -interface Category { - id: number; - attributes: { - name: string; - color: string; - background: string; - createdAt: string, - updatedAt: string, - publishedAt: string, - }; -} +import { Category } from '@/components/categories/types'; export interface Post { id: number, @@ -35,16 +25,4 @@ export interface PostsFetchResponse { total: number } } -} - -export interface CategoriesFetchResponse { - data: Category[], - meta: { - pagination: { - page: number, - pageSize: number, - pageCount: number, - total: number - } - } } \ No newline at end of file diff --git a/next/src/components/categories/Categories.tsx b/next/src/components/categories/Categories.tsx new file mode 100644 index 0000000..23810a8 --- /dev/null +++ b/next/src/components/categories/Categories.tsx @@ -0,0 +1,27 @@ +import React, { FunctionComponent } from 'react'; +import styles from './styles.module.scss'; +import { Category } from '@/components/categories/types'; +import CategoryLink from './category-link/CategoryLink'; + +interface Props { + categories: Category[] | undefined; + activeCategory?: Category['attributes']['name']; +} + +const Categories: FunctionComponent = ({ categories, activeCategory }) => { + if (!categories || !categories.length) { + return null; + } + + return ( +
    + {categories.map((category) => ( +
  • + +
  • + ))} +
+ ); +}; + +export default Categories; \ No newline at end of file diff --git a/next/src/components/categories/category-link/CategoryLink.tsx b/next/src/components/categories/category-link/CategoryLink.tsx new file mode 100644 index 0000000..18d09bd --- /dev/null +++ b/next/src/components/categories/category-link/CategoryLink.tsx @@ -0,0 +1,22 @@ +import Link from 'next/link'; +import React, { FunctionComponent } from 'react'; +import styles from './styles.module.scss'; +import { Category } from '@/components/categories/types'; + +interface Props { + name: string; + activeCategory?: Category['attributes']['name']; +} + +const CategoryLink: FunctionComponent = ({ activeCategory, name }) => { + const isActiveCategory = name === activeCategory; + + const setActiveCategory = isActiveCategory ? styles.active : ''; + const setHref = isActiveCategory ? '/blog' : `/blog?category=${name}`; + + return ( + #{name} + ); +}; + +export default CategoryLink; \ No newline at end of file diff --git a/next/src/components/categories/category-link/styles.module.scss b/next/src/components/categories/category-link/styles.module.scss new file mode 100644 index 0000000..8329331 --- /dev/null +++ b/next/src/components/categories/category-link/styles.module.scss @@ -0,0 +1,9 @@ +@import '@/styles/vars'; + +.link { + color: darken($color-text, 40%); + + &.active { + color: $color-accent; + } +} \ No newline at end of file diff --git a/next/src/components/categories/styles.module.scss b/next/src/components/categories/styles.module.scss new file mode 100644 index 0000000..e150921 --- /dev/null +++ b/next/src/components/categories/styles.module.scss @@ -0,0 +1,8 @@ +@import '@/styles/vars'; + +.categories { + margin-bottom: 3rem; + justify-content: flex-start; + display: flex; + gap: .5rem; +} \ No newline at end of file diff --git a/next/src/components/categories/types.ts b/next/src/components/categories/types.ts new file mode 100644 index 0000000..ea2616f --- /dev/null +++ b/next/src/components/categories/types.ts @@ -0,0 +1,22 @@ +export interface Category { + id: number; + attributes: { + name: string; + color: string; + background: string; + createdAt: string, + updatedAt: string, + publishedAt: string, + }; +} +export interface CategoriesFetchResponse { + data: Category[], + meta: { + pagination: { + page: number, + pageSize: number, + pageCount: number, + total: number + } + } +} \ No newline at end of file diff --git a/next/src/scripts/fetch.ts b/next/src/scripts/fetch.ts index 823c32b..72113e1 100644 --- a/next/src/scripts/fetch.ts +++ b/next/src/scripts/fetch.ts @@ -1,5 +1,6 @@ -import type { CategoriesFetchResponse, PostsFetchResponse } from '@/components/blog-post-item/types'; import qs from 'qs'; +import type { PostsFetchResponse } from '@/components/blog-post-item/types'; +import { CategoriesFetchResponse } from '@/components/categories/types'; export const fetchWrapper = async (url: string | URL) => { try { @@ -35,6 +36,25 @@ export const db = { const queryString = qs.stringify(queryParams); return await fetchWrapper(`/posts?${queryString}`); }, + getPostsByCategory: async (category: string) => { + const queryParams = { + sort: ['publishedAt:desc'], + filters: { + categories: { + name: { + $eq: category + } + } + }, + pagination: { + pageSize: 10, + page: 1 + } + }; + + const queryString = qs.stringify(queryParams); + return await fetchWrapper(`/posts?${queryString}`); + }, getPostBySlug: async (slug: string) => { const queryParams = { filters: { diff --git a/next/src/styles/global.module.scss b/next/src/styles/global.module.scss index 94b1f13..396fbbd 100644 --- a/next/src/styles/global.module.scss +++ b/next/src/styles/global.module.scss @@ -57,14 +57,4 @@ .tagsMini { @extend .tags; font-size: clamp(1rem, 1.1vw, 1.4rem); -} - -.categories { - justify-content: flex-start; - display: flex; - gap: .5rem; - - li { - color: darken($color-text, 40%); - } } \ No newline at end of file