feat: add blog section into home page

feature/homepage
Näser 3 years ago
parent 5315b6a5ac
commit 8c28b6e25a

@ -3,6 +3,7 @@ import { format } from 'date-fns';
import {environment} from '../../environments/environment'; import {environment} from '../../environments/environment';
import styles from './card-blog.module.scss'; import styles from './card-blog.module.scss';
import {getCategoryUrl, getPostUrl} from "../../libs/utils";
/* eslint-disable-next-line */ /* eslint-disable-next-line */
export interface CardBlogProps { export interface CardBlogProps {
@ -22,21 +23,21 @@ export function CardBlog({item}: CardBlogProps) {
<div className="flex justify-between items-center"> <div className="flex justify-between items-center">
<span <span
className="font-light text-gray-600 text-sm">{format(new Date(delve(item, 'attributes.publishedAt', 'Jun 1, 2020')),'dd/MM/yyyy')}</span> className="font-light text-gray-600 text-sm">{format(new Date(delve(item, 'attributes.publishedAt', 'Jun 1, 2020')),'dd/MM/yyyy')}</span>
<a href={'/blog/' + delve(item, 'attributes.category.data.attributes.slug', '')} <a href={getCategoryUrl(item)}
className="px-2 py-1 text-sm bg-gray-600 text-gray-100 font-bold rounded hover:bg-gray-500"> className="px-2 py-1 text-sm bg-gray-600 text-gray-100 font-bold rounded hover:bg-gray-500">
{delve(item, 'attributes.category.data.attributes.name', 'N/A')} {delve(item, 'attributes.category.data.attributes.name', 'N/A')}
</a> </a>
</div> </div>
<div className="mt-2"> <div className="mt-2">
<a <a
href={'/blog/' + delve(item, 'attributes.category.data.attributes.slug', '') + '/' + delve(item, 'attributes.slug', '')} href={getPostUrl(item)}
className="text-xl text-gray-700 font-bold hover:underline"> className="text-xl text-gray-700 font-bold hover:underline">
{delve(item, 'attributes.title', 'N/A')} {delve(item, 'attributes.title', 'N/A')}
</a> </a>
<p className="mt-2 font-light text-sm text-gray-600">{delve(item, 'attributes.description', 'N/A')}</p> <p className="mt-2 font-light text-sm text-gray-600">{delve(item, 'attributes.description', 'N/A')}</p>
</div> </div>
<div className="flex justify-between items-center mt-4"> <div className="flex justify-between items-center mt-4">
<a href="#" className="text-blue-500 text-sm hover:underline">Lire l'article</a> <a href={getPostUrl(item)} className="text-blue-500 text-sm hover:underline">Lire l'article</a>
<div> <div>
<a href="#" className="flex items-center"> <a href="#" className="flex items-center">
<img <img

@ -19,7 +19,7 @@ export function Footer({items = []}) {
<div className="sm:flex sm:items-center sm:justify-between"> <div className="sm:flex sm:items-center sm:justify-between">
<a href="/" className="flex items-center mb-4 sm:mb-0"> <a href="/" className="flex items-center mb-4 sm:mb-0">
<img src="https://flowbite.com/docs/images/logo.svg" className="h-8 mr-3" alt="Flowbite Logo"/> <img src="https://flowbite.com/docs/images/logo.svg" className="h-8 mr-3" alt="Flowbite Logo"/>
<span className="self-center text-2xl font-semibold whitespace-nowrap dark:text-white">Flowbite</span> <span className="self-center text-2xl font-semibold whitespace-nowrap dark:text-white">MeCP</span>
</a> </a>
<ul className="flex flex-wrap items-center mb-6 text-sm text-gray-500 sm:mb-0 dark:text-gray-400"> <ul className="flex flex-wrap items-center mb-6 text-sm text-gray-500 sm:mb-0 dark:text-gray-400">
{items.map((item, index: number) => generateItem(item, index))} {items.map((item, index: number) => generateItem(item, index))}

@ -181,7 +181,7 @@ export function Header({items = []}) {
<div className="container max-w-screen-xl flex flex-wrap items-center justify-between mx-auto"> <div className="container max-w-screen-xl flex flex-wrap items-center justify-between mx-auto">
<a href="/" className="flex items-center"> <a href="/" className="flex items-center">
<img src="https://flowbite.com/docs/images/logo.svg" className="h-6 mr-3 sm:h-9" alt="Flowbite Logo"/> <img src="https://flowbite.com/docs/images/logo.svg" className="h-6 mr-3 sm:h-9" alt="Flowbite Logo"/>
<span className="self-center text-xl font-semibold whitespace-nowrap dark:text-white">Flowbite</span> <span className="self-center text-xl font-semibold whitespace-nowrap dark:text-white">MeCP</span>
</a> </a>
<div className="flex items-center"> <div className="flex items-center">
<button <button

@ -1,14 +1,75 @@
import styles from './home-section-blog.module.scss';
/* eslint-disable-next-line */ /* eslint-disable-next-line */
export interface HomeSectionBlogProps {} import NextImage from "next/image";
import delve from 'dlv';
import {getCategoryUrl, getPostUrl, getStrapiImage, getStrapiImageSize} from "../../libs/utils";
import CardBlog from "../card-blog/card-blog";
import {format} from "date-fns";
export interface HomeSectionBlogProps {
posts: object[];
}
export function HomeSectionBlog(props: HomeSectionBlogProps) { export function HomeSectionBlog({posts}: HomeSectionBlogProps) {
const firstArticle = posts.length > 0 ? posts.slice(0, 1) : [];
const otherArticles = posts.length > 0 ? posts.slice(1, posts.length) : [];
console.log(firstArticle, otherArticles);
const [width, height] = getStrapiImageSize(firstArticle[0]);
return ( return (
<> <>
<section className="container max-w-6xl relative mx-auto relative flex row mb-10 h-auto"> <section className="container max-w-6xl relative mx-auto relative flex flex-col md:flex-row mb-10 h-auto">
<div className="md:w-6/12">a</div> <div className="w-12/12 md:w-6/12 px-4 mb-4 md:mb-0 md:px-0 md:pr-2">
<div className="md:w-6/12">b</div> <div className="block border rounded-lg shadow-sm h-full my-2 mx-2 sm:my-0 sm:mx-0 relative
bg-white border-gray-200
hover:bg-gray-100
dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">
<div className="flex justify-between items-center absolute left-5 top-5">
<span
className="font-bold shadow text-white text-sm">{format(new Date(delve(firstArticle[0], 'attributes.publishedAt', 'Jun 1, 2020')),'dd/MM/yyyy')}</span>
</div>
<div className="flex justify-between items-center absolute right-5 top-5">
<a href={getCategoryUrl(firstArticle[0])}
className="px-2 py-1 text-sm bg-gray-600 text-gray-100 font-bold rounded hover:bg-gray-500">
{delve(firstArticle[0], 'attributes.category.data.attributes.name', 'N/A')}
</a>
</div>
<NextImage
layout="responsive"
width={width}
height={height}
objectFit="contain"
className="rounded-t"
src={getStrapiImage(firstArticle[0])}
alt={delve(firstArticle, '0.title', 'N/A')} />
<main className="p-5">
<div className="mt-2">
<a
href={'/blog/' + delve(firstArticle[0], 'attributes.category.data.attributes.slug', '') + '/' + delve(firstArticle[0], 'attributes.slug', '')}
className="text-xl text-gray-700 font-bold hover:underline">
{delve(firstArticle[0], 'attributes.title', 'N/A')}
</a>
<p className="mt-2 font-light text-sm text-gray-600">{delve(firstArticle[0], 'attributes.description', 'N/A')}</p>
</div>
<div className="flex justify-between items-center mt-4">
<a href={getPostUrl(firstArticle[0])} className="text-blue-500 text-sm hover:underline">Lire l'article</a>
<div>
<a href="#" className="flex items-center">
<img
src="https://images.unsplash.com/photo-1492562080023-ab3db95bfbce?ixlib=rb-1.2.1&amp;ixid=eyJhcHBfaWQiOjEyMDd9&amp;auto=format&amp;fit=crop&amp;w=731&amp;q=80"
alt="avatar" className="mx-4 w-10 h-10 object-cover rounded-full hidden sm:block"/>
<h3 className="text-gray-700 text-normal font-bold hover:underline">Alex John</h3>
</a>
</div>
</div>
</main>
</div>
</div>
<div className="w-12/12 md:w-6/12 px-4 md:px-0 md:pl-2">
{otherArticles.map((item: object, index: number) => (<CardBlog key={"home-card-blog-" + index} item={item} />))}
</div>
</section> </section>
</> </>
); );

@ -15,17 +15,17 @@ export function HomeSectionCardsHeader(props: HomeSectionCardsHeaderProps) {
<> <>
<main className="container relative max-w-screen-xl mx-auto relative flex flex-col mb-10"> <main className="container relative max-w-screen-xl mx-auto relative flex flex-col mb-10">
<section className="relative max-w-6xl w-full mx-auto lg:h-[200px] sm:grid sm:grid-cols-3 sm:gap-4 sm:-top-10 sm:px-4 xl:px-0"> <section className="relative max-w-6xl w-full mx-auto lg:h-[200px] sm:grid sm:grid-cols-3 sm:gap-4 sm:-top-10 sm:px-4 xl:px-0">
<div className="block p-6 border rounded-lg shadow h-full my-2 mx-2 sm:my-0 sm:mx-0 <div className="block p-6 border rounded-lg shadow-sm h-full my-2 mx-2 sm:my-0 sm:mx-0
bg-white border-gray-200 bg-white border-gray-200
hover:bg-gray-100 hover:bg-gray-100
dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">a dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">a
</div> </div>
<div className="block p-6 border rounded-lg shadow h-full my-2 mx-2 sm:my-0 sm:mx-0 <div className="block p-6 border rounded-lg shadow-sm h-full my-2 mx-2 sm:my-0 sm:mx-0
bg-white border-gray-200 bg-white border-gray-200
hover:bg-gray-100 hover:bg-gray-100
dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">b dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">b
</div> </div>
<div className="blocks p-6 border rounded-lg shadow h-full my-2 mx-2 sm:my-0 sm:mx-0 <div className="blocks p-6 border rounded-lg shadow-sm h-full my-2 mx-2 sm:my-0 sm:mx-0
bg-white border-gray-200 bg-white border-gray-200
hover:bg-gray-100 hover:bg-gray-100
dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">c dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">c

@ -7,9 +7,10 @@ import HomeSectionBlog from "../home-section-blog/home-section-blog";
/* eslint-disable-next-line */ /* eslint-disable-next-line */
export interface HomeProps { export interface HomeProps {
posts: object[];
} }
export function HomeContent(props: HomeProps) { export function HomeContent({posts}: HomeProps) {
return ( return (
<div className={styles['container']}> <div className={styles['container']}>
<header className="w-full hidden sm:block min-h-[40vh] md:min-h-[50vh] lg:min-h-[75vh] bg-gray-500 bg-cover bg-no-repeat" style={{backgroundImage: 'url(/images/home.jpeg)'}}></header> <header className="w-full hidden sm:block min-h-[40vh] md:min-h-[50vh] lg:min-h-[75vh] bg-gray-500 bg-cover bg-no-repeat" style={{backgroundImage: 'url(/images/home.jpeg)'}}></header>
@ -17,7 +18,7 @@ export function HomeContent(props: HomeProps) {
<HomeSectionGrid /> <HomeSectionGrid />
<HomeSectionVideo /> <HomeSectionVideo />
<HomeSectionComments /> <HomeSectionComments />
<HomeSectionBlog /> <HomeSectionBlog posts={posts} />
</div> </div>
); );
} }

@ -1,7 +1,7 @@
export const environment = { export const environment = {
appUrl: 'http://localhost:4200', appUrl: 'http://localhost:4200',
strapiUrl: 'http://127.0.0.1:1337', strapiUrl: 'http://localhost:1337',
strapiApiUrl: 'http://127.0.0.1:1337/api', strapiApiUrl: 'http://localhost:1337/api',
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP", nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP",
meiliApiKey: "0e9a9d027b9e6b2d98c9670e5030a8d1aa72cab911fd768d4ad02636ae673690", meiliApiKey: "0e9a9d027b9e6b2d98c9670e5030a8d1aa72cab911fd768d4ad02636ae673690",
meiliMasterKey: "f2e963e883cbacf6d4f63e792dc276491b8a866fb837f3fda37b8b78889a6851" meiliMasterKey: "f2e963e883cbacf6d4f63e792dc276491b8a866fb837f3fda37b8b78889a6851"

@ -1,7 +1,7 @@
export const environment = { export const environment = {
appUrl: 'http://localhost:4200', appUrl: 'http://localhost:4200',
strapiUrl: 'http://127.0.0.1:1337', strapiUrl: 'http://localhost:1337',
strapiApiUrl: 'http://127.0.0.1:1337/api', strapiApiUrl: 'http://localhost:1337/api',
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP", nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP",
meiliApiKey: "0e9a9d027b9e6b2d98c9670e5030a8d1aa72cab911fd768d4ad02636ae673690", meiliApiKey: "0e9a9d027b9e6b2d98c9670e5030a8d1aa72cab911fd768d4ad02636ae673690",
meiliMasterKey: "f2e963e883cbacf6d4f63e792dc276491b8a866fb837f3fda37b8b78889a6851" meiliMasterKey: "f2e963e883cbacf6d4f63e792dc276491b8a866fb837f3fda37b8b78889a6851"

@ -0,0 +1,43 @@
import delve from 'dlv';
import {environment} from "../environments/environment";
export type ImageFormatType = "default" | "thumbnail" | "medium" | "small";
export const getCategoryUrl = (item): string => {
return '/blog/' + delve(item, 'attributes.category.data.attributes.slug', '');
}
export const getPostUrl = (item): string => {
return '/blog/' + getCategoryUrl(item) + '/' + delve(item, 'attributes.slug', '');
}
export const getStrapiImage = (item, format: ImageFormatType = 'default') => {
const image = delve(item, 'attributes.image.data.attributes', {});
switch (format) {
case "default":
return environment.strapiUrl + delve(image, "url", "/images/default.png");
case "medium":
return environment.strapiUrl + delve(image, "formats.medium.url", "/images/default.png");
case "small":
return environment.strapiUrl + delve(image, "formats.small.url", "/images/default.png");
case "thumbnail":
return environment.strapiUrl + delve(image, "formats.thumbnail.url", "/images/default.png");
default:
return environment.strapiUrl + delve(image, "url", "/images/default.png");
}
}
export const getStrapiImageSize = (item, format: ImageFormatType = 'default'): [number, number] => {
const image = delve(item, 'attributes.image.data.attributes', {});
switch (format) {
case "default":
return [delve(image, "width", 100), delve(image, "height", 100)];
case "medium":
return [delve(image, "formats.medium.width", 100), delve(image, "formats.medium.height", 100)];
case "small":
return [delve(image, "formats.small.width", 100), delve(image, "formats.small.height", 100)];
case "thumbnail":
return [delve(image, "formats.thumbnail.width", 100), delve(image, "formats.thumbnail.height", 100)];
default:
return [delve(image, "width", 100), delve(image, "height", 100)];
}
}

@ -12,7 +12,7 @@ import CardBlogDetails from "../../../components/card-blog-details/card-blog-det
export async function getServerSideProps(context) { export async function getServerSideProps(context) {
const categories = await axios.get(`${environment.strapiApiUrl}/categories?populate=deep`); const categories = await axios.get(`${environment.strapiApiUrl}/categories?populate=deep`);
const lastPublished = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&_sort=date:DESC`); const lastPublished = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&sort=publishedAt:DESC`);
const post = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&filters[slug]=${context.params.post_slug}`); const post = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&filters[slug]=${context.params.post_slug}`);
if (!delve(post, "data.data.0.attributes", null)) { if (!delve(post, "data.data.0.attributes", null)) {

@ -16,8 +16,8 @@ export async function getServerSideProps(context) {
const {query} = context; const {query} = context;
const categories = await axios.get(`${environment.strapiApiUrl}/categories?populate=deep`); const categories = await axios.get(`${environment.strapiApiUrl}/categories?populate=deep`);
const category = await axios.get(`${environment.strapiApiUrl}/categories?populate=deep&filters[slug]=${context.params.category_slug}`); const category = await axios.get(`${environment.strapiApiUrl}/categories?populate=deep&filters[slug]=${context.params.category_slug}`);
const lastPublished = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&_sort=date:DESC`); const lastPublished = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&_sort=date:DESC&sort=publishedAt:DESC`);
let postsUrl = `${environment.strapiApiUrl}/articles?populate=deep&_sort=date:DESC&filters[category][slug][$contains]=${context.params.category_slug}`; let postsUrl = `${environment.strapiApiUrl}/articles?populate=deep&sort=publishedAt:DESC&filters[category][slug][$contains]=${context.params.category_slug}`;
if (query && query.page) { if (query && query.page) {
postsUrl += `$pagination[page]=${query.page}`; postsUrl += `$pagination[page]=${query.page}`;
} }

@ -1,17 +1,32 @@
import axios from "axios";
import delve from "dlv";
import {environment} from "../../environments/environment";
import SeoConfig from "../../components/seo-config/seo-config"; import SeoConfig from "../../components/seo-config/seo-config";
import Layout from "../../components/layout/layout"; import Layout from "../../components/layout/layout";
import HomeContent from "../../components/home/home"; import HomeContent from "../../components/home/home";
import styles from "../blog/index.module.scss"; import styles from "../blog/index.module.scss";
export function Home({menuHeader, menuFooter, seo}) { export async function getServerSideProps(context) {
const postsUrl = `${environment.strapiApiUrl}/articles?populate=deep&sort=publishedAt:DESC&pagination[limit]=3`;
const posts = await axios.get(postsUrl);
return {
props: {
posts: delve(posts, 'data.data', []),
}
}
}
export function Home({menuHeader, menuFooter, seo, posts}) {
return ( return (
<> <>
<SeoConfig {...seo} /> <SeoConfig {...seo} />
<Layout menuHeader={menuHeader} <Layout menuHeader={menuHeader}
menuFooter={menuFooter}> menuFooter={menuFooter}>
<main className={styles['blog-container'] + " w-full"}> <main className={styles['blog-container'] + " w-full"}>
<HomeContent /> <HomeContent posts={posts} />
</main> </main>
</Layout> </Layout>
</> </>

Loading…
Cancel
Save