Merge branch 'feature/homepage' into develop

develop
Näser 3 years ago
commit b9f109b7fb

@ -1,10 +1,20 @@
import { render } from '@testing-library/react'; import {render} from '@testing-library/react';
import BlogPagination from './blog-pagination'; import BlogPagination from './blog-pagination';
jest.mock("next/router", () => ({
useRouter() {
return {
route: "/",
pathname: "",
query: "",
asPath: "",
};
},
}));
describe('BlogPagination', () => { describe('BlogPagination', () => {
it('should render successfully', () => { it('should render successfully', () => {
const { baseElement } = render(<BlogPagination />); const {baseElement} = render(<BlogPagination paginator={{pagination: {}}} />);
expect(baseElement).toBeTruthy(); expect(baseElement).toBeTruthy();
}); });
}); });

@ -6,7 +6,7 @@ export interface BlogPaginationProps {
paginator: any; paginator: any;
} }
export function BlogPagination({paginator}: BlogPaginationProps) { export function BlogPagination({paginator = {pagination: {}}}: BlogPaginationProps) {
const router = useRouter(); const router = useRouter();
const {total, pageCount, page} = paginator.pagination; const {total, pageCount, page} = paginator.pagination;
const isOnlyOne = pageCount > 0 && pageCount === 1; const isOnlyOne = pageCount > 0 && pageCount === 1;
@ -41,7 +41,10 @@ export function BlogPagination({paginator}: BlogPaginationProps) {
hover:bg-gray-900 hover:bg-gray-900
disabled:bg-gray-500 disabled:hover:bg-gray-500 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"> 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" <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"> xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" <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" 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"
@ -58,7 +61,10 @@ export function BlogPagination({paginator}: BlogPaginationProps) {
disabled:bg-gray-500 disabled:hover:bg-gray-500 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"> dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">
Next Next
<svg aria-hidden="true" className="w-5 h-5 ml-2" fill="currentColor" viewBox="0 0 20 20" <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"> xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" <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" 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"

@ -1,10 +1,31 @@
import { render } from '@testing-library/react'; import {render} from '@testing-library/react';
import configureStore from "redux-mock-store";
import BlogSearch from './blog-search'; import BlogSearch from './blog-search';
import {Provider} from "react-redux";
jest.mock("next/router", () => ({
useRouter() {
return {
route: "/",
pathname: "",
query: "",
asPath: "",
};
},
}));
describe('BlogSearch', () => { describe('BlogSearch', () => {
const initialState = {results: []};
const mockStore = configureStore();
let store;
it('should render successfully', () => { it('should render successfully', () => {
const { baseElement } = render(<BlogSearch />); store = mockStore(initialState);
const {baseElement} = render(
<Provider store={store}>
<BlogSearch />
</Provider>);
expect(baseElement).toBeTruthy(); expect(baseElement).toBeTruthy();
}); });
}); });

@ -24,8 +24,8 @@ export function BlogSearch(props: BlogSearchProps) {
if (subject === null) { if (subject === null) {
const sub = new BehaviorSubject(''); const sub = new BehaviorSubject('');
const client = new MeiliSearch({ const client = new MeiliSearch({
host: 'http://127.0.0.1:7700', host: environment.meiliUrl,
apiKey: environment.meiliMasterKey apiKey: environment.meiliApiKey
}) })
setSubject(sub); setSubject(sub);
setClient(client); setClient(client);
@ -55,7 +55,9 @@ export function BlogSearch(props: BlogSearchProps) {
const onSearchChange = (e) => subject.next(e.target.value); const onSearchChange = (e) => subject.next(e.target.value);
return ( 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={styles['container'] + " rounded-lg mx-2 lg:mx-0 mt-5 lg:mt-0 p-5 mb-5 shadow-sm" +
" bg-white" +
" dark:bg-gray-800"}>
<form> <form>
<label htmlFor="default-search" <label htmlFor="default-search"
className="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Search</label> className="mb-2 text-sm font-medium text-gray-900 sr-only dark:text-white">Search</label>

@ -1,10 +1,10 @@
import { render } from '@testing-library/react'; import {render} from '@testing-library/react';
import CardBlogDetails from './card-blog-details'; import CardBlogDetails from './card-blog-details';
describe('CardBlogDetails', () => { describe('CardBlogDetails', () => {
it('should render successfully', () => { it('should render successfully', () => {
const { baseElement } = render(<CardBlogDetails />); const {baseElement} = render(<CardBlogDetails item={{}} />);
expect(baseElement).toBeTruthy(); expect(baseElement).toBeTruthy();
}); });
}); });

@ -13,80 +13,87 @@ import {
WhatsappShareButton WhatsappShareButton
} from "react-share"; } from "react-share";
import {environment} from "../../environments/environment";
import styles from './card-blog-details.module.scss'; import styles from './card-blog-details.module.scss';
import {getCategoryUrl, getPostUrl, getStrapiImage} from "../../libs/utils";
/* eslint-disable-next-line */ /* eslint-disable-next-line */
export interface CardBlogDetailsProps { export interface CardBlogDetailsProps {
item: any; item: any;
} }
export function CardBlogDetails({item}: CardBlogDetailsProps) { export function CardBlogDetails({item = {}}: CardBlogDetailsProps) {
const {alternativeText, width, height} = item.image.data.attributes; const {width = 0, height = 0} = delve(item, 'image.data.attributes', {});
const {slug} = item.category.data.attributes;
const {title} = item; const {title} = item;
const shareUrl = `${environment.appUrl}/blog/${slug}/${item.slug}`; const shareUrl = getPostUrl(item);
return ( return (
<div className={styles['container'] + " bg-white rounded-l p-8 overflow-hidden shadow-sm"}> <div className={styles['container'] + " rounded-l p-8 overflow-hidden shadow-sm" +
" bg-white" +
" dark:bg-gray-800"}>
<header className="md:flex flex-col"> <header className="md:flex flex-col">
<h2 className="text-3xl mb-5 text-bold"> <h2 className="text-3xl mb-5 text-bold">
{delve(item, 'title', 'N/A')} {delve(item, 'title', 'N/A')}
</h2> </h2>
<section className="flex items-center justify-between"> <section className="flex items-center justify-between">
<div className="flex"> <div className="flex">
<a href="#" className="flex items-center"> <a href="#"
className="flex items-center">
<img <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" 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="mr-4 w-10 h-10 object-cover rounded-full hidden sm:block"/> 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> <h3 className="text-gray-700 text-normal font-bold hover:underline text-slate-400">Par Alex John</h3>
</a> </a>
</div> </div>
<div className="flex flex-col"> <div className="flex flex-col">
<a href={'/blog/' + delve(item, '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, 'category.data.attributes.name', 'N/A')} {delve(item, 'category.data.attributes.name', 'N/A')}
</a> </a>
</div> </div>
</section> </section>
</header> </header>
<hr className="border-gray-100 my-5 sm:mx-auto dark:border-gray-700 container mx-auto"/> <hr className="border-gray-100 my-5 sm:mx-auto dark:border-gray-700 container mx-auto" />
<main> <main>
<section> <section>
<div className="whitespace-pre-wrap text-lg font-bold text-slate-500" <div className="whitespace-pre-wrap text-lg font-bold text-slate-500
dangerouslySetInnerHTML={{__html: delve(item, 'description', 'N/A')}}/> text-gray-600
dark:text-gray-300"
dangerouslySetInnerHTML={{__html: delve(item, 'description', 'N/A')}} />
<NextImage <NextImage
layout="responsive" layout="responsive"
width={width} width={width}
height={height} height={height}
objectFit="contain" objectFit="contain"
className="rounded-lg my-5" className="rounded-lg my-5"
src={environment.strapiUrl + delve(item, 'image.data.attributes.url', '')} src={getStrapiImage(item, "default")}
alt={delve(item, 'title', 'N/A')}/> alt={delve(item, 'title', 'N/A')} />
</section> </section>
<section className="whitespace-pre-wrap text-lg text-slate-400" <section className="whitespace-pre-wrap text-lg text-slate-400"
dangerouslySetInnerHTML={{__html: delve(item, 'content', 'N/A')}}/> dangerouslySetInnerHTML={{__html: delve(item, 'content', 'N/A')}} />
<hr className="border-gray-100 my-5 sm:mx-auto dark:border-gray-700 container mx-auto"/> <hr className="border-gray-100 my-5 sm:mx-auto dark:border-gray-700 container mx-auto" />
<section className="flex justify-between"> <section className="flex justify-between">
<div> <div>
<h4 className="font-bold text-lg text-gray-400 mb-2">Partager cet article</h4> <h4 className="font-bold text-lg text-gray-400 mb-2">Partager cet article</h4>
<div className="grid grid-cols-5 gap-2"> <div className="grid grid-cols-5 gap-2">
<FacebookShareButton url={shareUrl}> <FacebookShareButton url={shareUrl}>
<FacebookIcon size={32} round/> <FacebookIcon size={32}
round />
</FacebookShareButton> </FacebookShareButton>
<FacebookMessengerShareButton <FacebookMessengerShareButton
url={shareUrl} url={shareUrl}
appId="521270401588372" appId="521270401588372"
className="Demo__some-network__share-button" className="Demo__some-network__share-button"
> >
<FacebookMessengerIcon size={32} round/> <FacebookMessengerIcon size={32}
round />
</FacebookMessengerShareButton> </FacebookMessengerShareButton>
<TwitterShareButton <TwitterShareButton
url={shareUrl} url={shareUrl}
title={title} title={title}
className="Demo__some-network__share-button" className="Demo__some-network__share-button"
> >
<TwitterIcon size={32} round/> <TwitterIcon size={32}
round />
</TwitterShareButton> </TwitterShareButton>
<WhatsappShareButton <WhatsappShareButton
url={shareUrl} url={shareUrl}
@ -94,10 +101,13 @@ export function CardBlogDetails({item}: CardBlogDetailsProps) {
separator=":: " separator=":: "
className="Demo__some-network__share-button" className="Demo__some-network__share-button"
> >
<WhatsappIcon size={32} round/> <WhatsappIcon size={32}
round />
</WhatsappShareButton> </WhatsappShareButton>
<LinkedinShareButton url={shareUrl} className="Demo__some-network__share-button"> <LinkedinShareButton url={shareUrl}
<LinkedinIcon size={32} round/> className="Demo__some-network__share-button">
<LinkedinIcon size={32}
round />
</LinkedinShareButton> </LinkedinShareButton>
</div> </div>
</div> </div>

@ -5,3 +5,6 @@
* .container { * .container {
* } * }
*/ */
.card-blog-container {
margin-bottom: 10px;
}

@ -1,8 +1,8 @@
import delve from 'dlv'; import delve from 'dlv';
import { format } from 'date-fns'; import {format} from 'date-fns';
import {environment} from '../../environments/environment';
import styles from './card-blog.module.scss'; import styles from './card-blog.module.scss';
import {getCategoryUrl, getPostUrl, getStrapiImage} from "../../libs/utils";
/* eslint-disable-next-line */ /* eslint-disable-next-line */
export interface CardBlogProps { export interface CardBlogProps {
@ -11,38 +11,53 @@ export interface CardBlogProps {
export function CardBlog({item}: CardBlogProps) { export function CardBlog({item}: CardBlogProps) {
return ( return (
<div className={styles['container'] + " bg-white rounded-l overflow-hidden shadow-sm"}> <div className={styles['card-blog-container'] + " rounded-l overflow-hidden shadow-sm" +
" bg-white" +
" dark:bg-gray-800"}>
<div className="md:flex"> <div className="md:flex">
<div className="md:shrink-0"> <div className="md:shrink-0">
<img className="h-48 w-full object-cover md:h-full md:w-48" <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', '')} src={getStrapiImage(item, 'medium')}
alt="Modern building architecture"/> alt="Modern building architecture" />
</div> </div>
<div className="p-8 w-full"> <div className="p-8 w-full">
<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-sm
<a href={'/blog/' + delve(item, 'attributes.category.data.attributes.slug', '')} text-gray-600
className="px-2 py-1 text-sm bg-gray-600 text-gray-100 font-bold rounded hover:bg-gray-500"> dark:text-gray-300">{format(new Date(delve(item, 'attributes.publishedAt', 'Jun 1, 2020')), 'dd/MM/yyyy')}</span>
<a href={getCategoryUrl(item)}
className="px-2 py-1 text-sm font-bold rounded
bg-gray-600 text-gray-100
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 font-bold hover:underline
text-gray-700
dark:text-gray-200">
{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
dark:text-gray-300">{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
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" 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"/> alt="avatar"
<h3 className="text-gray-700 text-normal font-bold hover:underline">Alex John</h3> className="mx-4 w-10 h-10 object-cover rounded-full hidden sm:block" />
<h3 className="text-normal font-bold hover:underline
text-gray-700
dark:text-gray-300">Alex John</h3>
</a> </a>
</div> </div>
</div> </div>

@ -15,7 +15,9 @@ export interface CategoriesProps {
export function Categories({items = []}: CategoriesProps) { export function Categories({items = []}: CategoriesProps) {
return ( return (
<div <div
className={styles['container'] + " bg-white rounded-lg mx-2 lg:mx-0 mt-5 lg:mt-0 p-5 mb-5 shadow-sm"}> className={styles['container'] + " rounded-lg mx-2 lg:mx-0 mt-5 lg:mt-0 p-5 mb-5 shadow-sm" +
" bg-white" +
" dark:bg-gray-800"}>
<div className="flex items-center justify-between mb-4"> <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> <h5 className="text-xl font-bold leading-none text-gray-900 dark:text-white">Catégories</h5>
</div> </div>

@ -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))}

@ -172,16 +172,16 @@ export function Header({items = []}) {
return ( return (
<nav <nav
className="bg-white fixed border-gray-200 rounded dark:bg-gray-800 w-full z-10 border-b-2 border-b-gray-50 dark:border-b-gray-700"> className="bg-white fixed border-gray-200 dark:bg-gray-800 w-full z-10 border-b-gray-50 dark:border-b-gray-700">
<div className="flex mx-auto"> <div className="flex mx-auto">
<main className="w-full"> <main className="w-full">
<section <section
className="bg-white dark:bg-gray-900 w-full md:w-auto p-2 md:p-4" className="bg-white dark:bg-gray-800 w-full md:w-auto p-2 md:p-4"
id="navbar-default"> id="navbar-default">
<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
@ -207,7 +207,7 @@ export function Header({items = []}) {
</div> </div>
</div> </div>
</section> </section>
<hr className="border-gray-100 sm:mx-auto dark:border-gray-700 container mx-auto"/> <hr className="border-gray-100 dark:border-gray-700 container max-w-screen-xl mx-auto"/>
<section className="hidden w-full md:block md:w-auto" id="navbar-dropdown"> <section className="hidden w-full md:block md:w-auto" id="navbar-dropdown">
<div className="container max-w-screen-xl mx-auto"> <div className="container max-w-screen-xl mx-auto">
<ul className="flex flex-col md:p-4 font-medium md:flex-row md:space-x-8 md:mt-0"> <ul className="flex flex-col md:p-4 font-medium md:flex-row md:space-x-8 md:mt-0">

@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import HomeSectionBlog from './home-section-blog';
describe('HomeSectionBlog', () => {
it('should render successfully', () => {
const { baseElement } = render(<HomeSectionBlog />);
expect(baseElement).toBeTruthy();
});
});

@ -0,0 +1,86 @@
/* eslint-disable-next-line */
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({posts = []}: HomeSectionBlogProps) {
const firstArticle = posts.length > 0 ? posts.slice(0, 1) : [];
const otherArticles = posts.length > 0 ? posts.slice(1, posts.length) : [];
const [width, height] = getStrapiImageSize(firstArticle[0]);
return (
<>
<section className="container max-w-6xl relative mx-auto relative flex flex-col md:flex-row mb-10 h-auto">
<div className="w-12/12 md:w-6/12 px-4 mb-4 md:mb-0 md:px-0 md:pr-2">
<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
dark:bg-gray-800 dark:border-gray-800 dark:hover:bg-gray-800">
<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={getPostUrl(firstArticle[0])}
className="text-xl font-bold hover:underline
text-gray-700
dark:text-gray-200">
{delve(firstArticle[0], 'attributes.title', 'N/A')}
</a>
<p className="mt-2 font-light text-sm
text-gray-600
dark:text-gray-300">{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-normal font-bold hover:underline
text-gray-700
dark:text-gray-300">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>
</>
);
}
export default HomeSectionBlog;

@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import HomeSectionCardsHeader from './home-section-cards-header';
describe('HomeSectionCardsHeader', () => {
it('should render successfully', () => {
const { baseElement } = render(<HomeSectionCardsHeader />);
expect(baseElement).toBeTruthy();
});
});

@ -0,0 +1,82 @@
import styles from './home-section-cards-header.module.scss';
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {
faChalkboardUser,
faGraduationCap, faGuitar,
faLinesLeaning, faScrewdriverWrench,
faTabletScreenButton
} from "@fortawesome/free-solid-svg-icons";
/* eslint-disable-next-line */
export interface HomeSectionCardsHeaderProps {}
export function HomeSectionCardsHeader(props: HomeSectionCardsHeaderProps) {
return (
<>
<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">
<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
hover:bg-gray-100
dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">a
</div>
<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
hover:bg-gray-100
dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">b
</div>
<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
hover:bg-gray-100
dark:bg-gray-800 dark:border-gray-700 dark:hover:bg-gray-700">c
</div>
</section>
<section className="relative w-full">
<h2 className="font-bold w-full text-center my-5 text-2xl mx-auto text-teal-800">MeCP fournit tout les outils nécessaire pour un apprentissage de qualité</h2>
<div className="grid grid-cols-3 gap-2 md:gap-4 max-w-4xl mx-auto px-2 md:px-0">
<div className="text-center flex flex-col transition scale-75
text-gray-400
hover:scale-100 hover:text-lime-600">
<span className="text-5xl my-2 md:mx-10 md:my-5"><FontAwesomeIcon icon={faTabletScreenButton} /></span>
<span className="text-lg">Des formats adaptés</span>
</div>
<div className="text-center flex flex-col transition scale-75
text-gray-400
hover:scale-100 hover:text-violet-600">
<span className="text-5xl my-2 md:mx-10 md:my-5"><FontAwesomeIcon icon={faGraduationCap} /></span>
<span className="text-lg">Une organisation pédagogique</span>
</div>
<div className="text-center flex flex-col transition scale-75
text-gray-400
hover:scale-100 hover:text-yellow-600">
<span className="text-5xl my-2 md:mx-10 md:my-5"><FontAwesomeIcon icon={faChalkboardUser} /></span>
<span className="text-lg ">Un espace dédié à l'apprentissage</span>
</div>
<div className="text-center flex flex-col transition scale-75
text-gray-400
hover:scale-100 hover:text-orange-600">
<span className="text-5xl my-2 md:mx-10 md:my-5"><FontAwesomeIcon icon={faLinesLeaning} /></span>
<span className="text-lg">Des contenus adaptés et motivants</span>
</div>
<div className="text-center flex flex-col transition scale-75
text-gray-400
hover:scale-100 hover:text-teal-600">
<span className="text-5xl my-2 md:mx-10 md:my-5"><FontAwesomeIcon icon={faGuitar} /></span>
<span className="text-lg">Une méthode révolutionnaire</span>
</div>
<div className="text-center flex flex-col transition scale-75
text-gray-400
hover:scale-100 hover:text-pink-600">
<span className="text-5xl my-2 md:mx-10 md:my-5"><FontAwesomeIcon icon={faScrewdriverWrench} /></span>
<span className="text-lg">Des outils interactifs</span>
</div>
</div>
</section>
</main>
</>
);
}
export default HomeSectionCardsHeader;

@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import HomeSectionComments from './home-section-comments';
describe('HomeSectionComments', () => {
it('should render successfully', () => {
const { baseElement } = render(<HomeSectionComments />);
expect(baseElement).toBeTruthy();
});
});

@ -0,0 +1,186 @@
/* eslint-disable-next-line */
export interface HomeSectionCommentsProps {
}
export function HomeSectionComments(props: HomeSectionCommentsProps) {
return (
<>
<section className="w-full py-10 my-10
bg-white
dark:bg-gray-800">
<div className="container max-w-6xl relative mx-auto relative flex-col mb-10 h-auto">
<h3 className="w-full mb-10 text-xl text-center font-extrabold tracking-tight leading-none md:text-2xl xl:text-3xl dark:text-white">
Ce que nos étudiants en pense
</h3>
<div className="w-full grid md:grid-cols-3 md:px-4 xl:px-0 gap-5">
<div className="rounded-lg p-7 mx-5 md:mx-0
bg-gray-100
dark:bg-gray-700">
<header>
<div className="flex items-center">
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>First star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Second star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Third star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Fourth star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-gray-300 dark:text-gray-500"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Fifth star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
</div>
</header>
<section className="pt-3">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec sodales nisi. Donec pretium varius purus quis porttitor. In et tempus massa, accumsan egestas orci. Aenean eros purus, consequat eget.</p>
</section>
<hr className="my-5" />
<footer 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="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>
</footer>
</div>
<div className="rounded-lg p-7 mx-5 md:mx-0
bg-gray-100
dark:bg-gray-700">
<header>
<div className="flex items-center">
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>First star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Second star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Third star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Fourth star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-gray-300 dark:text-gray-500"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Fifth star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
</div>
</header>
<section className="pt-3">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec sodales nisi. Donec pretium varius purus quis porttitor. In et tempus massa, accumsan egestas orci. Aenean eros purus, consequat eget.</p>
</section>
<hr className="my-5" />
<footer 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="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>
</footer>
</div>
<div className="rounded-lg p-7 mx-5 md:mx-0
bg-gray-100
dark:bg-gray-700">
<header>
<div className="flex items-center">
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>First star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Second star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Third star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-yellow-400"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Fourth star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
<svg aria-hidden="true"
className="w-5 h-5 text-gray-300 dark:text-gray-500"
fill="currentColor"
viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"><title>Fifth star</title>
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"></path>
</svg>
</div>
</header>
<section className="pt-3">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer nec sodales nisi. Donec pretium varius purus quis porttitor. In et tempus massa, accumsan egestas orci. Aenean eros purus, consequat eget.</p>
</section>
<hr className="my-5" />
<footer 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="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>
</footer>
</div>
</div>
</div>
</section>
</>
);
}
export default HomeSectionComments;

@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import HomeSectionGrid from './home-section-grid';
describe('HomeSectionGrid', () => {
it('should render successfully', () => {
const { baseElement } = render(<HomeSectionGrid />);
expect(baseElement).toBeTruthy();
});
});

@ -0,0 +1,36 @@
/* eslint-disable-next-line */
export interface HomeSectionGridProps {
}
export function HomeSectionGrid(props: HomeSectionGridProps) {
return (
<>
<section className="w-full p-5 sm:p-10 lg:pt-0 lg:py-10 lg:my-10
bg-white
dark:bg-gray-800">
<div className="container max-w-6xl relative mx-auto relative flex row lg:mb-10 h-auto">
<div className="place-self-center lg:col-span-7 md:px-5 md:px-0 md:pr-10">
<h3 className="lg:max-w-2xl mb-4 lg:my-10 text-xl font-extrabold tracking-tight leading-none md:text-2xl xl:text-3xl
dark:text-white">
Méthode révolutionnaire pour apprendre à jouer
</h3>
<p className="lg:max-w-2xl mb-6 font-light text-gray-500 lg:mb-8 md:text-lg
dark:text-gray-400">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed feugiat nulla lorem, at consectetur ligula pulvinar nec. Fusce dictum aliquet tellus id aliquam. Praesent feugiat tincidunt ante. Aliquam non lectus est. Suspendisse porta, dolor vel aliquet pharetra, ipsum diam laoreet ante, a feugiat nisi justo eu est.
</p>
<p className="lg:max-w-2xl font-light text-gray-500 lg:mb-8 md:text-lg
dark:text-gray-400">
Suspendisse in eros nisl. Vivamus eu convallis massa. Phasellus sit amet felis ut velit semper sagittis eget vitae arcu. Nunc leo est, vulputate sed libero non, efficitur lobortis odio. Proin fermentum massa non metus bibendum imperdiet.
</p>
</div>
<div className="hidden relative md:mt-10 lg:col-span-5 lg:flex grow justify-around">
<div className="md:w-2/5 relative bg-gray-200 rounded-lg h-[350px]"></div>
<div className="md:w-2/5 relative bg-gray-200 rounded-lg h-[350px] top-10"></div>
</div>
</div>
</section>
</>
);
}
export default HomeSectionGrid;

@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import HomeSectionVideo from './home-section-video';
describe('HomeSectionVideo', () => {
it('should render successfully', () => {
const { baseElement } = render(<HomeSectionVideo />);
expect(baseElement).toBeTruthy();
});
});

@ -0,0 +1,27 @@
import styles from './home-section-video.module.scss';
/* eslint-disable-next-line */
export interface HomeSectionVideoProps {}
export function HomeSectionVideo(props: HomeSectionVideoProps) {
return (
<>
<section className="container relative max-w-screen-xl mx-auto relative flex flex-col justify-center mb-10">
<h2 className="font-bold w-full text-center mt-5 text-2xl mx-auto text-blue-800">
Démonstration en vidéo
</h2>
<p className="text-lg text-gray-500 mb-10 text-center">Rien ne vaut une démonstration pour convaincre !</p>
<iframe src="https://embed.api.video/vod/vi2JpEFEClejM7A4hhn6i7fU"
width="90%"
frameBorder="0"
scrolling="no"
className="mx-auto"
allowFullScreen={true}></iframe>
</section>
</>
);
}
export default HomeSectionVideo;

@ -0,0 +1,7 @@
/*
* Replace this with your own classes
*
* e.g.
* .container {
* }
*/

@ -0,0 +1,10 @@
import { render } from '@testing-library/react';
import Home from './home';
describe('Home', () => {
it('should render successfully', () => {
const { baseElement } = render(<Home />);
expect(baseElement).toBeTruthy();
});
});

@ -0,0 +1,26 @@
import styles from './home.module.scss';
import HomeSectionGrid from "../home-section-grid/home-section-grid";
import HomeSectionCardsHeader from "../home-section-cards-header/home-section-cards-header";
import HomeSectionVideo from "../home-section-video/home-section-video";
import HomeSectionComments from "../home-section-comments/home-section-comments";
import HomeSectionBlog from "../home-section-blog/home-section-blog";
/* eslint-disable-next-line */
export interface HomeProps {
posts: object[];
}
export function HomeContent({posts}: HomeProps) {
return (
<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>
<HomeSectionCardsHeader />
<HomeSectionGrid />
<HomeSectionVideo />
<HomeSectionComments />
<HomeSectionBlog posts={posts} />
</div>
);
}
export default HomeContent;

@ -12,7 +12,9 @@ export interface LastArticlesProps {
export function LastArticles({items = []}: LastArticlesProps) { export function LastArticles({items = []}: LastArticlesProps) {
return ( return (
<div <div
className={styles['container'] + " bg-white rounded-lg mx-2 lg:mx-0 mt-5 lg:mt-0 p-5 mb-5 shadow-sm"}> className={styles['container'] + "rounded-lg mx-2 lg:mx-0 mt-5 lg:mt-0 p-5 mb-5 shadow-sm" +
" bg-white" +
" dark:bg-gray-800"}>
<div className="flex items-center justify-between mb-4"> <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> <h5 className="text-xl font-bold leading-none text-gray-900 dark:text-white">Derniers articles publiés</h5>
</div> </div>

@ -11,7 +11,7 @@
.app-content { .app-content {
position: relative; position: relative;
padding-top: 75.5px; padding-top: 58px;
min-height: calc(100vh - 189px); min-height: calc(100vh - 189px);
} }
} }
@ -64,7 +64,7 @@
@media (min-width: 1024px) { @media (min-width: 1024px) {
.app-container:not(.without-footer) { .app-container:not(.without-footer) {
.app-content { .app-content {
padding-top: 135px; padding-top: 131px;
min-height: calc(100vh - 181px); min-height: calc(100vh - 181px);
} }
} }

@ -53,6 +53,7 @@ export const SeoConfig = ({metaDescription = null, lang = null, meta = [], metaT
return ( return (
<Head> <Head>
<title>{title}</title> <title>{title}</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" <meta name="description"
content={description}/> content={description}/>
<meta property="og:title" <meta property="og:title"

@ -1,8 +1,8 @@
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", meiliUrl: "http://127.0.0.1:7700",
meiliMasterKey: "f2e963e883cbacf6d4f63e792dc276491b8a866fb837f3fda37b8b78889a6851" meiliApiKey: "f2e963e883cbacf6d4f63e792dc276491b8a866fb837f3fda37b8b78889a6851",
} }

@ -3,6 +3,6 @@ export const environment = {
strapiUrl: 'https://admin.mecp.nasercloud.fr', strapiUrl: 'https://admin.mecp.nasercloud.fr',
strapiApiUrl: 'https://admin.mecp.nasercloud.fr/api', strapiApiUrl: 'https://admin.mecp.nasercloud.fr/api',
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP", nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP",
meiliUrl: "https://ms-b6dafcb0b382-1943.fra.meilisearch.io",
meiliApiKey: "0e9a9d027b9e6b2d98c9670e5030a8d1aa72cab911fd768d4ad02636ae673690", meiliApiKey: "0e9a9d027b9e6b2d98c9670e5030a8d1aa72cab911fd768d4ad02636ae673690",
meiliMasterKey: "f2e963e883cbacf6d4f63e792dc276491b8a866fb837f3fda37b8b78889a6851"
} }

@ -3,6 +3,6 @@ export const environment = {
strapiUrl: 'https://admin.mecp.nasercloud.fr', strapiUrl: 'https://admin.mecp.nasercloud.fr',
strapiApiUrl: 'https://admin.mecp.nasercloud.fr/api', strapiApiUrl: 'https://admin.mecp.nasercloud.fr/api',
nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP", nextAuthSecret: "yBNW1wrb9CgOvEfbX6EQCvCDqiMkRBZP",
meiliApiKey: "0e9a9d027b9e6b2d98c9670e5030a8d1aa72cab911fd768d4ad02636ae673690", meiliUrl: "https://ms-b6dafcb0b382-1943.fra.meilisearch.io",
meiliMasterKey: "f2e963e883cbacf6d4f63e792dc276491b8a866fb837f3fda37b8b78889a6851" meiliApiKey: "dda9e4a354839db9ae18c3722ae75422515c06525b3a841010928b5256f54e72",
} }

@ -1,8 +1,8 @@
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", meiliUrl: "http://127.0.0.1:7700",
meiliMasterKey: "f2e963e883cbacf6d4f63e792dc276491b8a866fb837f3fda37b8b78889a6851" meiliApiKey: "dda9e4a354839db9ae18c3722ae75422515c06525b3a841010928b5256f54e72",
} }

@ -0,0 +1,47 @@
import delve from 'dlv';
import {environment} from "../environments/environment";
export type ImageFormatType = "default" | "thumbnail" | "medium" | "small";
export const getCategoryUrl = (item): string => {
const categorySlug = !delve(item, 'attributes', null) ? delve(item, 'category.data.attributes.slug', '') : delve(item, 'attributes.category.data.attributes.slug', '');
return '/blog/' + categorySlug;
}
export const getPostUrl = (item): string => {
const categorySlug = !delve(item, 'attributes', null) ? delve(item, 'category.data.attributes.slug', '') : delve(item, 'attributes.category.data.attributes.slug', '');
const postSlug = !delve(item, 'attributes', null) ? delve(item, 'slug', '') : delve(item, 'attributes.slug', '');
return '/blog/' + categorySlug + '/' + postSlug;
}
export const getStrapiImage = (item, format: ImageFormatType = 'default') => {
const image = !delve(item, 'attributes', null) ? delve(item, 'image.data.attributes', {}) : delve(item, 'attributes.image.data.attributes', {});
console.log(item, image);
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)];
}
}

@ -2,9 +2,21 @@ import App, {AppProps} from 'next/app';
import {SessionProvider} from "next-auth/react"; import {SessionProvider} from "next-auth/react";
import {config, library} from "@fortawesome/fontawesome-svg-core"; import {config, library} from "@fortawesome/fontawesome-svg-core";
import '@fortawesome/fontawesome-svg-core/styles.css'; import '@fortawesome/fontawesome-svg-core/styles.css';
import {faBagShopping, faRightToBracket, faUserPlus} from "@fortawesome/free-solid-svg-icons"; import {
faBagShopping,
faChalkboardUser,
faGraduationCap,
faGuitar,
faLinesLeaning,
faRightToBracket,
faScrewdriverWrench,
faTabletScreenButton,
faUserPlus
} from "@fortawesome/free-solid-svg-icons";
import axios from "axios"; import axios from "axios";
import delve from 'dlv'; import delve from 'dlv';
import {ThemeProvider} from "next-themes";
import {wrapper} from "../store/store"; import {wrapper} from "../store/store";
import {environment} from "../environments/environment"; import {environment} from "../environments/environment";
@ -15,6 +27,12 @@ config.autoAddCss = false;
library.add(faRightToBracket); library.add(faRightToBracket);
library.add(faUserPlus); library.add(faUserPlus);
library.add(faBagShopping); library.add(faBagShopping);
library.add(faTabletScreenButton);
library.add(faGraduationCap);
library.add(faChalkboardUser);
library.add(faLinesLeaning);
library.add(faGuitar);
library.add(faScrewdriverWrench);
interface CustomAppProps extends AppProps { interface CustomAppProps extends AppProps {
menuHeader: object[], menuHeader: object[],
@ -37,7 +55,10 @@ const CustomApp = ({Component, pageProps: {session, ...pageProps}, menuFooter, m
pageProps = {...pageProps, menuFooter, menuHeader, seo}; pageProps = {...pageProps, menuFooter, menuHeader, seo};
return ( return (
<SessionProvider session={session}> <SessionProvider session={session}>
<ThemeProvider enableSystem={true}
attribute="class">
<Component {...pageProps} /> <Component {...pageProps} />
</ThemeProvider>
</SessionProvider> </SessionProvider>
); );
} }

@ -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}`;
} }

@ -9,19 +9,28 @@ import styles from "./index.module.scss";
import BlogSearch from "../../components/blog-search/blog-search"; import BlogSearch from "../../components/blog-search/blog-search";
import {environment} from "../../environments/environment"; import {environment} from "../../environments/environment";
import CardBlog from "../../components/card-blog/card-blog"; import CardBlog from "../../components/card-blog/card-blog";
import BlogPagination from "../../components/blog-pagination/blog-pagination";
export async function getServerSideProps(context) { export async function getServerSideProps(context) {
const categories = await axios.get(`${environment.strapiApiUrl}/categories?populate=deep`) const {query} = context;
const posts = await axios.get(`${environment.strapiApiUrl}/articles?populate=deep&_sort=date:DESC`)
let postsUrl = `${environment.strapiApiUrl}/articles?populate=deep&sort=publishedAt:DESC`;
if (query && query.page) {
postsUrl += `$pagination[page]=${query.page}`;
}
const categories = await axios.get(`${environment.strapiApiUrl}/categories?populate=deep`);
const posts = await axios.get(postsUrl);
return { return {
props: { props: {
categories: delve(categories, 'data.data', []), categories: delve(categories, 'data.data', []),
lastPublished: delve(posts, 'data.data', []), lastPublished: delve(posts, 'data.data', []),
paginator: delve(posts, 'data.meta', []),
} }
} }
} }
export function Blog({menuHeader, menuFooter, seo, categories, lastPublished}) { export function Blog({menuHeader, menuFooter, seo, categories, lastPublished, paginator}) {
return ( return (
<> <>
<SeoConfig {...seo}/> <SeoConfig {...seo}/>
@ -32,6 +41,10 @@ export function Blog({menuHeader, menuFooter, seo, categories, lastPublished}) {
{lastPublished.map((post, index: number) => ( {lastPublished.map((post, index: number) => (
<CardBlog key={'card-blog-' + post.id + index} item={post}/>)) <CardBlog key={'card-blog-' + post.id + index} item={post}/>))
} }
{lastPublished.length > 0 && (<footer className="mt-10">
<BlogPagination paginator={paginator}/>
</footer>)}
</section> </section>
<aside className="grow lg:basis-2/6"> <aside className="grow lg:basis-2/6">
<BlogSearch/> <BlogSearch/>

@ -1,16 +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 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} menuFooter={menuFooter}> <Layout menuHeader={menuHeader}
<main className={styles['blog-container'] + " w-full lg:my-10"}> menuFooter={menuFooter}>
<section className="container max-w-screen-xl mx-auto relative flex"> <main className={styles['blog-container'] + " w-full"}>
<p>Page d&apos;accueil</p> <HomeContent posts={posts} />
</section>
</main> </main>
</Layout> </Layout>
</> </>

@ -1,13 +1,33 @@
import SeoConfig from "../components/seo-config/seo-config"; 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 Layout from "../components/layout/layout";
import HomeContent from "../components/home/home";
import styles from "./blog/index.module.scss";
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 Index({menuHeader, menuFooter, page, seo}) { export function Index({menuHeader, menuFooter, posts, seo}) {
return ( return (
<> <>
<SeoConfig {...seo}/> <SeoConfig {...seo} />
<Layout menuHeader={menuHeader} menuFooter={menuFooter}> <Layout menuHeader={menuHeader}
<p>Page d&apos;accueil</p> menuFooter={menuFooter}>
<main className={styles['blog-container'] + " w-full"}>
<HomeContent posts={posts} />
</main>
</Layout> </Layout>
</> </>
); );

Binary file not shown.

After

Width:  |  Height:  |  Size: 254 KiB

20
package-lock.json generated

@ -9748,6 +9748,12 @@
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
"integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="
}, },
"lodash.isplainobject": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
"integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
"dev": true
},
"lodash.memoize": { "lodash.memoize": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
@ -10124,6 +10130,11 @@
"resolved": "https://registry.npmjs.org/next-redux-wrapper/-/next-redux-wrapper-8.1.0.tgz", "resolved": "https://registry.npmjs.org/next-redux-wrapper/-/next-redux-wrapper-8.1.0.tgz",
"integrity": "sha512-2hIau0hcI6uQszOtrvAFqgc0NkZegKYhBB7ZAKiG3jk7zfuQb4E7OV9jfxViqqojh3SEHdnFfPkN9KErttUKuw==" "integrity": "sha512-2hIau0hcI6uQszOtrvAFqgc0NkZegKYhBB7ZAKiG3jk7zfuQb4E7OV9jfxViqqojh3SEHdnFfPkN9KErttUKuw=="
}, },
"next-themes": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/next-themes/-/next-themes-0.2.1.tgz",
"integrity": "sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A=="
},
"node-abort-controller": { "node-abort-controller": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz",
@ -11435,6 +11446,15 @@
"@babel/runtime": "^7.9.2" "@babel/runtime": "^7.9.2"
} }
}, },
"redux-mock-store": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/redux-mock-store/-/redux-mock-store-1.5.4.tgz",
"integrity": "sha512-xmcA0O/tjCLXhh9Fuiq6pMrJCwFRaouA8436zcikdIpYWWCjU76CRk+i2bHx8EeiSiMGnB85/lZdU3wIJVXHTA==",
"dev": true,
"requires": {
"lodash.isplainobject": "^4.0.6"
}
},
"redux-thunk": { "redux-thunk": {
"version": "2.4.2", "version": "2.4.2",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",

@ -27,6 +27,7 @@
"next": "13.1.1", "next": "13.1.1",
"next-auth": "4.18.8", "next-auth": "4.18.8",
"next-redux-wrapper": "^8.1.0", "next-redux-wrapper": "^8.1.0",
"next-themes": "^0.2.1",
"react": "18.2.0", "react": "18.2.0",
"react-dom": "18.2.0", "react-dom": "18.2.0",
"react-helmet": "6.0.0", "react-helmet": "6.0.0",
@ -70,6 +71,7 @@
"postcss": "8.4.19", "postcss": "8.4.19",
"prettier": "2.6.2", "prettier": "2.6.2",
"react-test-renderer": "18.2.0", "react-test-renderer": "18.2.0",
"redux-mock-store": "^1.5.4",
"sass": "1.55.0", "sass": "1.55.0",
"ts-jest": "28.0.5", "ts-jest": "28.0.5",
"ts-node": "10.9.1", "ts-node": "10.9.1",

Loading…
Cancel
Save