frontend: Preloader & 404 Error page

This commit is contained in:
Divlo 2020-03-21 23:03:30 +01:00
parent 3debd85a70
commit fd7fc44fe7
12 changed files with 98 additions and 38 deletions

View File

@ -1,6 +1,6 @@
import Link from 'next/link'; import Link from 'next/link';
import { useState, forwardRef } from 'react'; import { useState, forwardRef } from 'react';
import Loader from '../Loader/Loader'; import Loader from '../Loader';
import './FunctionCard.css'; import './FunctionCard.css';
const FunctionCard = forwardRef((props, ref) => { const FunctionCard = forwardRef((props, ref) => {

View File

@ -1,33 +1,36 @@
import Head from 'next/head'; import Head from 'next/head';
const HeadTag = (props) => ( const HeadTag = ({ title, image, description }) => (
<Head> <Head>
<title>{props.title}</title> <title>{title}</title>
<link rel="icon" type="image/png" href={props.image} /> <link rel="icon" type="image/png" href={image} />
{/* Meta Tag */} {/* Meta Tag */}
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="description" content={props.description} /> <meta name="description" content={description} />
<link rel="canonical" href="function.divlo.fr"/> <link rel="canonical" href="function.divlo.fr"/>
<meta name="Language" content="fr" /> <meta name="Language" content="fr" />
<meta name="theme-color" content="#ffd800" /> <meta name="theme-color" content="#ffd800" />
{/* Open Graph Metadata */} {/* Open Graph Metadata */}
<meta property="og:title" content={props.title} /> <meta property="og:title" content={title} />
<meta property="og:type" content="website" /> <meta property="og:type" content="website" />
<meta property="og:url" content="https://function.divlo.fr/" /> <meta property="og:url" content="https://function.divlo.fr/" />
<meta property="og:image" content={props.image} /> <meta property="og:image" content={image} />
<meta property="og:description" content={props.description} /> <meta property="og:description" content={description} />
<meta property="og:locale" content="fr_FR" /> <meta property="og:locale" content="fr_FR" />
<meta property="og:site_name" content="FunctionProject" /> <meta property="og:site_name" content="FunctionProject" />
{/* Twitter card Metadata */} {/* Twitter card Metadata */}
<meta name="twitter:card" content="summary" /> <meta name="twitter:card" content="summary" />
<meta name="twitter:description" content={props.description} /> <meta name="twitter:description" content={description} />
<meta name="twitter:title" content={props.title} /> <meta name="twitter:title" content={title} />
<meta name="twitter:site" content="@Divlo_FR" /> <meta name="twitter:site" content="@Divlo_FR" />
<meta name="twitter:image:src" content={props.image} /> <meta name="twitter:image:src" content={image} />
<meta name="twitter:creator" content="@Divlo_FR" /> <meta name="twitter:creator" content="@Divlo_FR" />
{/* Preloader script */}
<script src="/js/preloader.js"></script>
</Head> </Head>
); );

View File

@ -0,0 +1,15 @@
const Loader = ({ width, height, speed }) => (
<svg width={width} height={height} viewBox="0 0 100 100">
<g transform="translate(50 50) rotate(0) scale(1 1) translate(-50 -50)">
<image style={{transformOrigin: "50% 50%", animation: `${speed} linear 0s infinite normal forwards running Loader__spin`}} x="0" y="0" width="100" height="100" href="/images/FunctionProject_icon.png"></image>
</g>
</svg>
);
Loader.defaultProps = {
width: "100px",
height: "100px",
speed: ".9s"
}
export default Loader;

View File

@ -1,13 +0,0 @@
.Loader {
transform-origin: 50% 50%; animation: .9s linear 0s infinite normal forwards running Loader__spin;
}
@keyframes Loader__spin {
0% {
animation-timing-function: cubic-bezier(0.5856,0.0703,0.4143,0.9297);
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -1,11 +0,0 @@
import './Loader.css';
const Loader = ({ width, height }) => (
<svg width={width} height={height} viewBox="0 0 100 100">
<g transform="translate(50 50) rotate(0) scale(1 1) translate(-50 -50)">
<image className="Loader" x="0" y="0" width="100" height="100" href="/images/FunctionProject_icon.png"></image>
</g>
</svg>
);
export default Loader;

29
frontend/pages/404.js Normal file
View File

@ -0,0 +1,29 @@
import { Fragment } from 'react';
import Link from 'next/link';
import HeadTag from '../components/HeadTag';
import '../public/css/pages/404.css';
const Error404 = () => (
<Fragment>
<HeadTag
title="Erreur 404"
description="Cette page n'existe pas!"
image="/images/error404.png"
/>
<div className="Error404__container">
<h1>Erreur <span className="important">404</span></h1>
<p className="text-center">
Cette page n'existe pas! <Link href={"/"}><a>Revenir à la page d'accueil ?</a></Link>
</p>
</div>
<style>
{`
#__next {
padding-top: 0;
}
`}
</style>
</Fragment>
);
export default Error404;

View File

@ -1,4 +1,5 @@
import Document, { Html, Head, Main, NextScript } from "next/document"; import Document, { Html, Head, Main, NextScript } from "next/document";
import Loader from '../components/Loader';
class MyDocument extends Document { class MyDocument extends Document {
static async getInitialProps(ctx) { static async getInitialProps(ctx) {
@ -11,7 +12,12 @@ class MyDocument extends Document {
<Html lang="fr"> <Html lang="fr">
<Head /> <Head />
<body> <body>
<Main /> <div id="preloader">
<Loader />
</div>
<div className="isLoading">
<Main />
</div>
<NextScript /> <NextScript />
</body> </body>
</Html> </Html>

View File

@ -1,7 +1,7 @@
import { Fragment, useState, useEffect, useRef, useCallback } from 'react'; import { Fragment, useState, useEffect, useRef, useCallback } from 'react';
import HeadTag from '../components/HeadTag'; import HeadTag from '../components/HeadTag';
import FunctionCard from '../components/FunctionCard/FunctionCard'; import FunctionCard from '../components/FunctionCard/FunctionCard';
import Loader from '../components/Loader/Loader'; import Loader from '../components/Loader';
import '../public/css/pages/functions.css'; import '../public/css/pages/functions.css';
import { API_URL } from '../config/config'; import { API_URL } from '../config/config';
import api from '../config/api'; import api from '../config/api';
@ -91,7 +91,7 @@ const Functions = () => {
return <FunctionCard key={f.id} slug={f.slug} image={API_URL + f.image} title={f.title} description={f.description} category={f.categorie} publicationDate={new Date(f.createdAt).toLocaleDateString('fr-FR')} />; return <FunctionCard key={f.id} slug={f.slug} image={API_URL + f.image} title={f.title} description={f.description} category={f.categorie} publicationDate={new Date(f.createdAt).toLocaleDateString('fr-FR')} />;
})} })}
</div> </div>
{isLoadingFunctions && <Loader width="100px" height="100px" />} {isLoadingFunctions && <Loader />}
</div> </div>
</Fragment> </Fragment>
); );

View File

@ -45,6 +45,26 @@ a:hover {
align-items: center; align-items: center;
} }
/* LOADING */
.isLoading {
display: none;
}
#preloader {
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
@keyframes Loader__spin {
0% {
animation-timing-function: cubic-bezier(0.5856, 0.0703, 0.4143, 0.9297);
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
/* UTILITIES */ /* UTILITIES */
.text-center { .text-center {
text-align: center; text-align: center;

View File

@ -0,0 +1,7 @@
.Error404__container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-width: 100%;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

View File

@ -0,0 +1,4 @@
window.addEventListener('load', () => {
document.querySelector('.isLoading').classList.remove('isLoading');
document.getElementById('preloader').remove();
});