parent
140b61e1d7
commit
7f8e5dd903
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Replace this with your own classes
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* .container {
|
||||||
|
* }
|
||||||
|
*/
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import BlogPagination from './blog-pagination';
|
||||||
|
|
||||||
|
describe('BlogPagination', () => {
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const { baseElement } = render(<BlogPagination />);
|
||||||
|
expect(baseElement).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,74 @@
|
|||||||
|
import styles from './blog-pagination.module.scss';
|
||||||
|
import {useRouter} from "next/router";
|
||||||
|
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
export interface BlogPaginationProps {
|
||||||
|
paginator: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BlogPagination({paginator}: BlogPaginationProps) {
|
||||||
|
const router = useRouter();
|
||||||
|
const {total, pageCount, page} = paginator.pagination;
|
||||||
|
const isOnlyOne = pageCount > 0 && pageCount === 1;
|
||||||
|
const isEmpty = total === 0;
|
||||||
|
const isFirst = page === 1;
|
||||||
|
const isLast = page === pageCount;
|
||||||
|
const goPrevious = async () => {
|
||||||
|
await router.push(`${window.location.origin}${window.location.pathname}?page=${page - 1}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const goNext = async () => {
|
||||||
|
await router.push(`${window.location.origin}${window.location.pathname}?page=${page + 1}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles['container']}>
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
{isOnlyOne && !isEmpty && (
|
||||||
|
<span className="text-sm text-gray-700 dark:text-gray-400">{total} article(s)</span>)}
|
||||||
|
{!isOnlyOne && !isEmpty && (<span className="text-sm text-gray-700 dark:text-gray-400">
|
||||||
|
Articles <span className="font-semibold text-gray-900 dark:text-white">{page}</span> à <span
|
||||||
|
className="font-semibold text-gray-900 dark:text-white">{pageCount}</span> sur un total de <span
|
||||||
|
className="font-semibold text-gray-900 dark:text-white">{total}</span>
|
||||||
|
</span>)}
|
||||||
|
<div className="inline-flex mt-2 xs:mt-0">
|
||||||
|
<button
|
||||||
|
disabled={isOnlyOne || isFirst || isEmpty}
|
||||||
|
onClick={goPrevious}
|
||||||
|
className="
|
||||||
|
inline-flex items-center px-4 py-2 mr-2 text-sm font-medium rounded
|
||||||
|
text-white bg-gray-800
|
||||||
|
hover:bg-gray-900
|
||||||
|
disabled:bg-gray-500 disabled:hover:bg-gray-500
|
||||||
|
dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">
|
||||||
|
<svg aria-hidden="true" className="w-5 h-5 mr-2" fill="currentColor" viewBox="0 0 20 20"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fillRule="evenodd"
|
||||||
|
d="M7.707 14.707a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 1.414L5.414 9H17a1 1 0 110 2H5.414l2.293 2.293a1 1 0 010 1.414z"
|
||||||
|
clipRule="evenodd"></path>
|
||||||
|
</svg>
|
||||||
|
Prev
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
disabled={isOnlyOne || isLast || isEmpty}
|
||||||
|
onClick={goNext}
|
||||||
|
className="inline-flex items-center px-4 py-2 ml-2 text-sm font-medium rounded
|
||||||
|
text-white bg-gray-800
|
||||||
|
hover:bg-gray-900
|
||||||
|
disabled:bg-gray-500 disabled:hover:bg-gray-500
|
||||||
|
dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">
|
||||||
|
Next
|
||||||
|
<svg aria-hidden="true" className="w-5 h-5 ml-2" fill="currentColor" viewBox="0 0 20 20"
|
||||||
|
xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fillRule="evenodd"
|
||||||
|
d="M12.293 5.293a1 1 0 011.414 0l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414-1.414L14.586 11H3a1 1 0 110-2h11.586l-2.293-2.293a1 1 0 010-1.414z"
|
||||||
|
clipRule="evenodd"></path>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BlogPagination;
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Replace this with your own classes
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* .container {
|
||||||
|
* }
|
||||||
|
*/
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import BlogSearch from './blog-search';
|
||||||
|
|
||||||
|
describe('BlogSearch', () => {
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const { baseElement } = render(<BlogSearch />);
|
||||||
|
expect(baseElement).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
import styles from './blog-search.module.scss';
|
||||||
|
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
export interface BlogSearchProps {
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BlogSearch(props: BlogSearchProps) {
|
||||||
|
return (
|
||||||
|
<div className={styles['container'] + " bg-white rounded-lg mx-2 lg:mx-0 mt-5 lg:mt-0 p-5 mb-5 shadow-sm"}>
|
||||||
|
<form>
|
||||||
|
<label htmlFor="default-search"
|
||||||
|
className="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Search</label>
|
||||||
|
<div className="relative">
|
||||||
|
<div className="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
|
||||||
|
<svg aria-hidden="true" className="w-5 h-5 text-gray-500 dark:text-gray-400" fill="none"
|
||||||
|
stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"
|
||||||
|
d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<input type="search" id="default-search"
|
||||||
|
className="block w-full p-4 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||||
|
placeholder="Rechercher un article ..." required />
|
||||||
|
<button type="submit"
|
||||||
|
className="text-white absolute right-2.5 bottom-2.5 bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Search
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default BlogSearch;
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Replace this with your own classes
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* .container {
|
||||||
|
* }
|
||||||
|
*/
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import CardBlogDetails from './card-blog-details';
|
||||||
|
|
||||||
|
describe('CardBlogDetails', () => {
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const { baseElement } = render(<CardBlogDetails />);
|
||||||
|
expect(baseElement).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,111 @@
|
|||||||
|
import delve from 'dlv';
|
||||||
|
import NextImage from "next/image";
|
||||||
|
import {
|
||||||
|
FacebookIcon,
|
||||||
|
FacebookMessengerIcon,
|
||||||
|
FacebookMessengerShareButton,
|
||||||
|
FacebookShareButton,
|
||||||
|
LinkedinIcon,
|
||||||
|
LinkedinShareButton,
|
||||||
|
TwitterIcon,
|
||||||
|
TwitterShareButton,
|
||||||
|
WhatsappIcon,
|
||||||
|
WhatsappShareButton
|
||||||
|
} from "react-share";
|
||||||
|
|
||||||
|
import {environment} from "../../environments/environment";
|
||||||
|
|
||||||
|
import styles from './card-blog-details.module.scss';
|
||||||
|
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
export interface CardBlogDetailsProps {
|
||||||
|
item: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CardBlogDetails({item}: CardBlogDetailsProps) {
|
||||||
|
const {alternativeText, width, height} = item.image.data.attributes;
|
||||||
|
const {slug} = item.category.data.attributes;
|
||||||
|
const {title} = item;
|
||||||
|
const shareUrl = `${environment.appUrl}/blog/${slug}/${item.slug}`;
|
||||||
|
console.log(shareUrl);
|
||||||
|
return (
|
||||||
|
<div className={styles['container'] + " bg-white rounded-l p-8 overflow-hidden shadow-sm"}>
|
||||||
|
<header className="md:flex flex-col">
|
||||||
|
<h2 className="text-3xl mb-5 text-bold">
|
||||||
|
{delve(item, 'title', 'N/A')}
|
||||||
|
</h2>
|
||||||
|
<section className="flex items-center justify-between">
|
||||||
|
<div className="flex">
|
||||||
|
<a href="#" className="flex items-center">
|
||||||
|
<img
|
||||||
|
src="https://images.unsplash.com/photo-1492562080023-ab3db95bfbce?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=731&q=80"
|
||||||
|
alt="avatar" className="mr-4 w-10 h-10 object-cover rounded-full hidden sm:block"/>
|
||||||
|
<h3 className="text-gray-700 text-normal font-bold hover:underline text-slate-400">Par Alex John</h3>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col">
|
||||||
|
<a href={'/blog/' + delve(item, 'category.data.attributes.slug', '')}
|
||||||
|
className="px-2 py-1 text-sm bg-gray-600 text-gray-100 font-bold rounded hover:bg-gray-500">
|
||||||
|
{delve(item, 'category.data.attributes.name', 'N/A')}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</header>
|
||||||
|
<hr className="border-gray-100 my-5 sm:mx-auto dark:border-gray-700 container mx-auto"/>
|
||||||
|
<main>
|
||||||
|
<section>
|
||||||
|
<div className="whitespace-pre-wrap text-lg font-bold text-slate-500"
|
||||||
|
dangerouslySetInnerHTML={{__html: delve(item, 'description', 'N/A')}}/>
|
||||||
|
<NextImage
|
||||||
|
layout="responsive"
|
||||||
|
width={width}
|
||||||
|
height={height}
|
||||||
|
objectFit="contain"
|
||||||
|
className="rounded-lg my-5"
|
||||||
|
src={environment.strapiUrl + delve(item, 'image.data.attributes.url', '')}
|
||||||
|
alt={delve(item, 'title', 'N/A')}/>
|
||||||
|
</section>
|
||||||
|
<section className="whitespace-pre-wrap text-lg text-slate-400"
|
||||||
|
dangerouslySetInnerHTML={{__html: delve(item, 'content', 'N/A')}}/>
|
||||||
|
<hr className="border-gray-100 my-5 sm:mx-auto dark:border-gray-700 container mx-auto"/>
|
||||||
|
<section className="flex justify-between">
|
||||||
|
<div>
|
||||||
|
<h4 className="font-bold text-lg text-gray-400 mb-2">Partager cet article</h4>
|
||||||
|
<div className="grid grid-cols-5 gap-2">
|
||||||
|
<FacebookShareButton url={shareUrl}>
|
||||||
|
<FacebookIcon size={32} round/>
|
||||||
|
</FacebookShareButton>
|
||||||
|
<FacebookMessengerShareButton
|
||||||
|
url={shareUrl}
|
||||||
|
appId="521270401588372"
|
||||||
|
className="Demo__some-network__share-button"
|
||||||
|
>
|
||||||
|
<FacebookMessengerIcon size={32} round/>
|
||||||
|
</FacebookMessengerShareButton>
|
||||||
|
<TwitterShareButton
|
||||||
|
url={shareUrl}
|
||||||
|
title={title}
|
||||||
|
className="Demo__some-network__share-button"
|
||||||
|
>
|
||||||
|
<TwitterIcon size={32} round/>
|
||||||
|
</TwitterShareButton>
|
||||||
|
<WhatsappShareButton
|
||||||
|
url={shareUrl}
|
||||||
|
title={title}
|
||||||
|
separator=":: "
|
||||||
|
className="Demo__some-network__share-button"
|
||||||
|
>
|
||||||
|
<WhatsappIcon size={32} round/>
|
||||||
|
</WhatsappShareButton>
|
||||||
|
<LinkedinShareButton url={shareUrl} className="Demo__some-network__share-button">
|
||||||
|
<LinkedinIcon size={32} round/>
|
||||||
|
</LinkedinShareButton>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CardBlogDetails;
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Replace this with your own classes
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* .container {
|
||||||
|
* }
|
||||||
|
*/
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import CardBlog from './card-blog';
|
||||||
|
|
||||||
|
describe('CardBlog', () => {
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const { baseElement } = render(<CardBlog />);
|
||||||
|
expect(baseElement).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,57 @@
|
|||||||
|
import delve from 'dlv';
|
||||||
|
import { format } from 'date-fns';
|
||||||
|
import {environment} from '../../environments/environment';
|
||||||
|
|
||||||
|
import styles from './card-blog.module.scss';
|
||||||
|
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
export interface CardBlogProps {
|
||||||
|
item: object;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CardBlog({item}: CardBlogProps) {
|
||||||
|
return (
|
||||||
|
<div className={styles['container'] + " bg-white rounded-l overflow-hidden shadow-sm"}>
|
||||||
|
<div className="md:flex">
|
||||||
|
<div className="md:shrink-0">
|
||||||
|
<img className="h-48 w-full object-cover md:h-full md:w-48"
|
||||||
|
src={environment.strapiUrl + delve(item, 'attributes.image.data.attributes.formats.medium.url', '')}
|
||||||
|
alt="Modern building architecture"/>
|
||||||
|
</div>
|
||||||
|
<div className="p-8 w-full">
|
||||||
|
<div className="flex justify-between items-center">
|
||||||
|
<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', '')}
|
||||||
|
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')}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div className="mt-2">
|
||||||
|
<a
|
||||||
|
href={'/blog/' + delve(item, 'attributes.category.data.attributes.slug', '') + '/' + delve(item, 'attributes.slug', '')}
|
||||||
|
className="text-xl text-gray-700 font-bold hover:underline">
|
||||||
|
{delve(item, 'attributes.title', 'N/A')}
|
||||||
|
</a>
|
||||||
|
<p className="mt-2 font-light text-sm text-gray-600">{delve(item, 'attributes.description', 'N/A')}</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-between items-center mt-4">
|
||||||
|
<a href="#" 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&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=731&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>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CardBlog;
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Replace this with your own classes
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* .container {
|
||||||
|
* }
|
||||||
|
*/
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import Categories from './categories';
|
||||||
|
|
||||||
|
describe('Categories', () => {
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const { baseElement } = render(<Categories />);
|
||||||
|
expect(baseElement).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
import delve from 'dlv';
|
||||||
|
|
||||||
|
import {environment} from "../../environments/environment";
|
||||||
|
|
||||||
|
import styles from './categories.module.scss';
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
export interface CategoriesProps {
|
||||||
|
items: object[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// <!-- pb-0 sm:pt-4 -->
|
||||||
|
|
||||||
|
export function Categories({items = []}: CategoriesProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={styles['container'] + " bg-white rounded-lg mx-2 lg:mx-0 mt-5 lg:mt-0 p-5 mb-5 shadow-sm"}>
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<h5 className="text-xl font-bold leading-none text-gray-900 dark:text-white">Catégories</h5>
|
||||||
|
</div>
|
||||||
|
<div className="flow-root">
|
||||||
|
<ul role="list" className="divide-y divide-gray-200 dark:divide-gray-700">
|
||||||
|
{items.map((item: any, index: number) => (<li key={'categories-' + item.slug + index} className="py-3 sm:py-4">
|
||||||
|
<div className="flex items-center space-x-4">
|
||||||
|
<div className="flex-shrink-0">
|
||||||
|
<img className="w-8 h-8 rounded-full"
|
||||||
|
src={environment.strapiUrl + delve(item, 'attributes.image.data.attributes.formats.thumbnail.url', '')}
|
||||||
|
alt="Neil image"/>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<h4><Link href={"/blog/" + item.attributes.slug}>{delve(item, 'attributes.name', 'N/A')}</Link></h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>))
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Categories;
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
/*
|
||||||
|
* Replace this with your own classes
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* .container {
|
||||||
|
* }
|
||||||
|
*/
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { render } from '@testing-library/react';
|
||||||
|
|
||||||
|
import LastArticles from './last-articles';
|
||||||
|
|
||||||
|
describe('LastArticles', () => {
|
||||||
|
it('should render successfully', () => {
|
||||||
|
const { baseElement } = render(<LastArticles />);
|
||||||
|
expect(baseElement).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
import delve from 'dlv';
|
||||||
|
|
||||||
|
import styles from './last-articles.module.scss';
|
||||||
|
import {environment} from "../../environments/environment";
|
||||||
|
import {format} from "date-fns";
|
||||||
|
|
||||||
|
/* eslint-disable-next-line */
|
||||||
|
export interface LastArticlesProps {
|
||||||
|
items: object[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function LastArticles({items = []}: LastArticlesProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={styles['container'] + " bg-white rounded-lg mx-2 lg:mx-0 mt-5 lg:mt-0 p-5 mb-5 shadow-sm"}>
|
||||||
|
<div className="flex items-center justify-between mb-4">
|
||||||
|
<h5 className="text-xl font-bold leading-none text-gray-900 dark:text-white">Derniers articles publiés</h5>
|
||||||
|
</div>
|
||||||
|
<div className="flow-root">
|
||||||
|
<ul role="list" className="divide-y divide-gray-200 dark:divide-gray-700">
|
||||||
|
{items.map((item: object, index: number) => (<li key={'last-articles-' + index} className="py-3 sm:py-4">
|
||||||
|
<div className="flex items-center space-x-4">
|
||||||
|
<div className="flex-shrink-0">
|
||||||
|
<img className="w-[85px] h-[75px] rounded-lg"
|
||||||
|
src={environment.strapiUrl + delve(item, 'attributes.image.data.attributes.formats.medium.url', '')}
|
||||||
|
alt="Neil image"/>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 min-w-0">
|
||||||
|
<p className="text-xl font-medium text-gray-900 dark:text-white">
|
||||||
|
{delve(item, 'attributes.title', 'N/A')}
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-gray-500 dark:text-gray-400">
|
||||||
|
{delve(item, 'attributes.category.data.attributes.name', 'N/A')} - {format(new Date(delve(item, 'attributes.publishedAt', 'Jun 1, 2020')), 'dd/MM/yyyy')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</li>))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LastArticles;
|
||||||
@ -1,5 +1,6 @@
|
|||||||
export const environment = {
|
export const environment = {
|
||||||
strapiUrl: 'http://127.0.0.1:1337/',
|
appUrl: 'http://localhost:4200',
|
||||||
|
strapiUrl: 'http://127.0.0.1:1337',
|
||||||
strapiApiUrl: 'http://127.0.0.1:1337/api',
|
strapiApiUrl: 'http://127.0.0.1:1337/api',
|
||||||
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP"
|
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
export const environment = {
|
export const environment = {
|
||||||
strapiUrl: 'https://admin.mecp.nasercloud.fr/',
|
appUrl: 'http://localhost:4200',
|
||||||
|
strapiUrl: 'https://admin.mecp.nasercloud.fr',
|
||||||
strapiApiUrl: 'https://admin.mecp.nasercloud.fr/api',
|
strapiApiUrl: 'https://admin.mecp.nasercloud.fr/api',
|
||||||
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP"
|
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
export const environment = {
|
export const environment = {
|
||||||
strapiUrl: 'https://admin.mecp.nasercloud.fr/',
|
appUrl: 'http://localhost:4200',
|
||||||
|
strapiUrl: 'https://admin.mecp.nasercloud.fr',
|
||||||
strapiApiUrl: 'https://admin.mecp.nasercloud.fr/api',
|
strapiApiUrl: 'https://admin.mecp.nasercloud.fr/api',
|
||||||
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP"
|
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
export const environment = {
|
export const environment = {
|
||||||
strapiUrl: 'http://127.0.0.1:1337/',
|
appUrl: 'http://localhost:4200',
|
||||||
|
strapiUrl: 'http://127.0.0.1:1337',
|
||||||
strapiApiUrl: 'http://127.0.0.1:1337/api',
|
strapiApiUrl: 'http://127.0.0.1:1337/api',
|
||||||
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP"
|
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,57 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import delve from 'dlv';
|
||||||
|
|
||||||
|
import {environment} from "../../../environments/environment";
|
||||||
|
import SeoConfig from "../../../components/seo-config/seo-config";
|
||||||
|
import Layout from "../../../components/layout/layout";
|
||||||
|
import styles from "../../index.module.scss";
|
||||||
|
import BlogSearch from "../../../components/blog-search/blog-search";
|
||||||
|
import Categories from "../../../components/categories/categories";
|
||||||
|
import LastArticles from "../../../components/last-articles/last-articles";
|
||||||
|
import CardBlogDetails from "../../../components/card-blog-details/card-blog-details";
|
||||||
|
|
||||||
|
export async function getServerSideProps(context) {
|
||||||
|
console.log(context);
|
||||||
|
const categories = await axios.get(`${environment.strapiApiUrl}/categories?populate=deep`);
|
||||||
|
const lastPublished = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&_sort=date:DESC`);
|
||||||
|
const post = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&filters[slug]=${context.params.post_slug}`);
|
||||||
|
|
||||||
|
if (!delve(post, "data.data.0.attributes", null)) {
|
||||||
|
return {
|
||||||
|
notFound: true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
categories: delve(categories, 'data.data', []),
|
||||||
|
lastPublished: delve(lastPublished, 'data.data', []),
|
||||||
|
post: delve(post, "data.data.0.attributes", null),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PostBlog({menuHeader, menuFooter, seo, categories, post, lastPublished}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SeoConfig {...seo}/>
|
||||||
|
<Layout menuHeader={menuHeader} menuFooter={menuFooter} headerTransparent={true}>
|
||||||
|
<main className={styles['blog-container'] + " w-full lg:my-10"}>
|
||||||
|
<section className="container max-w-screen-xl mx-auto relative flex flex-col lg:flex-row">
|
||||||
|
<section className="grow lg:basis-4/6 mx-2 lg:mx-0 lg:pr-5">
|
||||||
|
<CardBlogDetails item={post}/>
|
||||||
|
</section>
|
||||||
|
<aside className="grow lg:basis-2/6">
|
||||||
|
<BlogSearch/>
|
||||||
|
<Categories items={categories}/>
|
||||||
|
<LastArticles items={lastPublished}/>
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</Layout>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PostBlog;
|
||||||
@ -0,0 +1,77 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import delve from "dlv";
|
||||||
|
|
||||||
|
import {environment} from "../../../environments/environment";
|
||||||
|
import SeoConfig from "../../../components/seo-config/seo-config";
|
||||||
|
import Layout from "../../../components/layout/layout";
|
||||||
|
import BlogSearch from "../../../components/blog-search/blog-search";
|
||||||
|
import Categories from "../../../components/categories/categories";
|
||||||
|
import LastArticles from "../../../components/last-articles/last-articles";
|
||||||
|
|
||||||
|
import styles from "../index.module.scss";
|
||||||
|
import CardBlog from "../../../components/card-blog/card-blog";
|
||||||
|
import BlogPagination from "../../../components/blog-pagination/blog-pagination";
|
||||||
|
|
||||||
|
export async function getServerSideProps(context) {
|
||||||
|
const {query} = context;
|
||||||
|
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 lastPublished = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&_sort=date:DESC`);
|
||||||
|
let postsUrl = `${environment.strapiApiUrl}/articles?populate=deep&_sort=date:DESC&filters[category][slug][$contains]=${context.params.category_slug}`;
|
||||||
|
if (query && query.page) {
|
||||||
|
postsUrl += `$pagination[page]=${query.page}`;
|
||||||
|
}
|
||||||
|
const posts = await axios.get(postsUrl);
|
||||||
|
|
||||||
|
if (!delve(category, "data.data.0.attributes", null)) {
|
||||||
|
return {
|
||||||
|
notFound: true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
categories: delve(categories, 'data.data', []),
|
||||||
|
category: delve(category, "data.data.0.attributes", null),
|
||||||
|
lastPublished: delve(lastPublished, 'data.data', []),
|
||||||
|
posts: delve(posts, 'data.data', []),
|
||||||
|
paginator: delve(posts, 'data.meta', []),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function CategoryBlog({menuHeader, menuFooter, seo, categories, category, posts, lastPublished, paginator}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SeoConfig {...seo}/>
|
||||||
|
<Layout menuHeader={menuHeader} menuFooter={menuFooter} headerTransparent={true}>
|
||||||
|
<main className={styles['blog-container'] + " w-full lg:my-10"}>
|
||||||
|
<section className="container max-w-screen-xl mx-auto relative flex">
|
||||||
|
<section className="grow lg:basis-4/6 mx-2 lg:mx-0 lg:pr-5">
|
||||||
|
<h3 className="text-2xl font-bold mb-5">{category.name}</h3>
|
||||||
|
{posts.length === 0 && (
|
||||||
|
<p>Aucun article n'a été posté dans cette catégorie pour l'instant</p>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
{posts.length > 0 && posts.map((post, index: number) => (
|
||||||
|
<CardBlog key={'card-blog-' + post.id + index} item={post}/>))
|
||||||
|
}
|
||||||
|
|
||||||
|
{posts.length > 0 && (<footer className="mt-10">
|
||||||
|
<BlogPagination paginator={paginator}/>
|
||||||
|
</footer>)}
|
||||||
|
</section>
|
||||||
|
<aside className="grow lg:basis-2/6">
|
||||||
|
<BlogSearch/>
|
||||||
|
<Categories items={categories}/>
|
||||||
|
<LastArticles items={lastPublished}/>
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</Layout>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default CategoryBlog;
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* Replace this with your own classes
|
||||||
|
*
|
||||||
|
* e.g.
|
||||||
|
* .container {
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
.blog-container {
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import delve from "dlv";
|
||||||
|
|
||||||
|
import SeoConfig from "../../components/seo-config/seo-config";
|
||||||
|
import Layout from "../../components/layout/layout";
|
||||||
|
import Categories from "../../components/categories/categories";
|
||||||
|
|
||||||
|
import styles from "./index.module.scss";
|
||||||
|
import BlogSearch from "../../components/blog-search/blog-search";
|
||||||
|
import {environment} from "../../environments/environment";
|
||||||
|
import CardBlog from "../../components/card-blog/card-blog";
|
||||||
|
|
||||||
|
export async function getServerSideProps(context) {
|
||||||
|
const categories = await axios.get(`${environment.strapiApiUrl}/categories?populate=deep`)
|
||||||
|
const posts = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&_sort=date:DESC`)
|
||||||
|
return {
|
||||||
|
props: {
|
||||||
|
categories: delve(categories, 'data.data', []),
|
||||||
|
lastPublished: delve(posts, 'data.data', []),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Blog({menuHeader, menuFooter, seo, categories, lastPublished}) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SeoConfig {...seo}/>
|
||||||
|
<Layout menuHeader={menuHeader} menuFooter={menuFooter} headerTransparent={true}>
|
||||||
|
<main className={styles['blog-container'] + " w-full lg:my-10"}>
|
||||||
|
<section className="container mx-auto relative flex">
|
||||||
|
<section className="grow lg:basis-4/6 mx-2 lg:mx-0 lg:pr-5">
|
||||||
|
{lastPublished.map((post, index: number) => (
|
||||||
|
<CardBlog key={'card-blog-' + post.id + index} item={post}/>))
|
||||||
|
}
|
||||||
|
</section>
|
||||||
|
<aside className="grow lg:basis-2/6">
|
||||||
|
<BlogSearch/>
|
||||||
|
<Categories items={categories}/>
|
||||||
|
</aside>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
</Layout>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Blog;
|
||||||
File diff suppressed because it is too large
Load Diff
Loading…
Reference in new issue