Signed-off-by: Avior <florian.bouillon@delta-wings.net>
This commit is contained in:
2020-01-04 17:35:30 +01:00
parent e5fb01eea8
commit a0f1799114
51 changed files with 879 additions and 261 deletions

128
pages/[category]/[slug].tsx Normal file
View File

@ -0,0 +1,128 @@
import { NextPageContext } from "next"
import{ Component } from 'react'
import Post from "../../components/Post"
import ReactMarkdown from 'react-markdown'
import Error from "../_error"
import Link from "next/link"
interface Props {
post: Post
}
interface States {
imgHeight: number
}
export default class PostPage extends Component<Props, States> {
public render() {
return (
<main>
{this.props.post === undefined ? (
<Error statusCode={404} />
) : (
<div>
<img src={this.props.post.header.image} alt={this.props.post.header.imageAlt} />
<ReactMarkdown source={this.props.post.content}/>
<h2>Détails</h2>
<p>Tags:</p>
<ul>
{this.props.post.header.tags.map((el) => (
<li>
<Link href="/tag/[tag]" as={'/tag/'+el.toLowerCase()}>
<a className="button">{el}</a>
</Link>
</li>
))}
</ul>
{this.props.post.header.url ? (
<a className="button outline large" href={this.props.post.header.url}>Visiter le site :D</a>
) : undefined}
</div>
)}
<style jsx global>{`
main h1 {
font-size: 50px;
text-align: center;
}
main h2 {
font-size: 40px;
text-align: center;
text-shadow: 4px 4px 0px rgba(66, 133, 244, 0.5);
}
main h2::selection {
text-shadow: 4px 4px 0px rgba(255, 255, 255, 0.5);
}
main p {
text-align: justify;
}
.header {
height: 250px;
}
@media (min-width: 820px) {
.header {
height: 0
}
}
`}</style>
<style jsx>{`
main div {
margin-top: -150px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
padding: 0 10%;
}
main a.button.outline {
align-self: center;
}
@media (min-width: 820px) {
main div {
margin-top: 0
}
main img {
max-width: 750px;
}
}
main img {
z-index: 999;
max-width: 100%;
border-radius: 10px;
max-height: 300px;
box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.4);
}
/*
li {
border-radius: 10px;
background: #4285F4;
color: white;
margin: 10px;
display: inline-block;
transition: background 200ms;
}
li:hover {
background: #45CAFC;
}
li a {
padding: 15px 20px;
color: white;
display: inline-block;
text-decoration: none;
}*/
li {
display: inline-block;
}
`}</style>
</main>
)
}
public static async getInitialProps(context: NextPageContext) {
const { slug } = context.query
if (typeof slug === "object" || slug === "[slug]") return {post: undefined}
const post = new Post(slug)
await post.fetch()
return {post}
}
}

View File

@ -26,7 +26,7 @@ const PortfolioIndex: NextPage<Props> = (props: Props) => {
<ul>
{props.files.map(post => (
<li key={post.slug}>
<Link href="/portfolio/[slug]" as={`/portfolio/${post.slug}`}>
<Link href="/[category]/[slug]" as={`/${post.slug}`}>
<a>{post.title}</a>
</Link>
</li>
@ -41,7 +41,7 @@ PortfolioIndex.getInitialProps = async (context: NextPageContext) => {
for (const post of await Post.fetchAll()) {
if (!post.isStarted) await post.fetch()
arr.push({
slug: post.slug,
slug: post.slug.replace(".md", ""),
title: post.title
})
}
@ -49,10 +49,3 @@ PortfolioIndex.getInitialProps = async (context: NextPageContext) => {
}
export default PortfolioIndex
function l(args: any) {
console.log(arguments)
}
async function test() {
}

View File

@ -1,23 +1,17 @@
import React from 'react'
import App from 'next/app'
import '../styl/styl.styl'
import Layout from '../components/Layout'
class MyApp extends App {
// Only uncomment this method if you have blocking data requirements for
// every single page in your application. This disables the ability to
// perform automatic static optimization, causing every page in your app to
// be server-side rendered.
//
// static async getInitialProps(appContext) {
// // calls page's `getInitialProps` and fills `appProps.pageProps`
// const appProps = await App.getInitialProps(appContext);
//
// return { ...appProps }
// }
render() {
const { Component, pageProps } = this.props
return <Component {...pageProps} />
}
render() {
const { Component, pageProps } = this.props
return(
<Layout>
<Component {...pageProps} />
</Layout>
)
}
}
export default MyApp

View File

@ -5,22 +5,24 @@
import Document, { Html, Head, Main, NextScript } from 'next/document'
class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
return { ...initialProps }
}
render() {
return (
<Html>
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
render() {
return (
<Html>
<Head>
<link rel="manifest" href="/manifest.json" />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument

58
pages/_error.tsx Normal file
View File

@ -0,0 +1,58 @@
import React, { Component } from 'react'
import { NextPageContext } from 'next'
import Head from 'next/head'
import Layout from '../components/Layout'
interface Props {
statusCode: number
}
const codesTexts = {
404: "Page non trouvé !",
500: "Le serveur n'a pas pu répondre a ta demande :O"
}
export default class Error extends Component<Props, {}> {
public render = () => {
const statusCode = this.props.statusCode
return (
<main>
<Head>
<title>Pouet :D</title>
</Head>
<div className="errorContainer">
<h1>{statusCode ? statusCode : "404"}</h1>
<h2>{statusCode ? codesTexts[statusCode] : codesTexts[404]}</h2>
</div>
<style jsx>{`
.errorContainer {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
height: 100%
}
.separator {
border: 1px solid black
}
h1 {
font-size: 250px;
margin: 10px;
color: transparent;
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
background-clip: text;
-webkit-background-clip: text;
}
`}</style>
</main>
)
}
getInitialProps = ({ res, err }: NextPageContext) => {
const statusCode = res ? res.statusCode : err ? err.statusCode : 404
return { statusCode }
}
}

View File

@ -1,124 +1,119 @@
import { NextPage } from 'next'
import Head from 'next/head'
import Link from 'next/link'
import '../styl/styl.styl'
import Element from '../components/Element'
import Navbar from '../components/Navbar'
import Header from '../components/Header'
import Menu from '../components/Menu'
import Filters from '../components/Filters'
import Category from '../components/interfaces/Category'
import { Component } from 'react'
import Post, { PostHeader } from '../components/Post'
interface Props {
userAgent?: string
}
interface el {
link: string,
title: string,
img: string,
date: Date
}
interface el extends PostHeader {}
interface States {
elements: el[]
loaded: boolean
asideHeight: number
categories: string[]
}
// export const config = {amp: 'hybrid'}
const categories: Category[] = [
{
name: "test",
slug: "pouet"
}
]
const elements: el[] = [
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Dzeio.io, Services en ligne pour vous simplifier la vie !", img:"/sea.jpg", date: new Date()},
{link:"/studiomoto", title:"Loram ipsum dolor sit amet", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"j'aime les licornes et leurs jolie corne", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Pokémon ! attrapez les tous !", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"abcde", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"def", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"abc", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()},
{link:"/studiomoto", title:"Studiomoto, Site de référencement d'événement moto en France", img:"/uploads/stm.png", date: new Date()}
]
let elements: PostHeader[] = []
export default class Page extends Component<Props, States> {
onQuery = (query: string) => {
console.log(`query: ${query}`)
onQuery = async (query: string, recent: boolean = true) => {
// console.log(`query: ${query}`)
const t= elements.filter(el => {
return el.title.toLowerCase().includes(query.toLowerCase())
})
if (recent) {
t.sort((a, b) => {
return (a.date < b.date) ? 1 : -1
})
} else {
t.sort((a, b) => {
return (a.date > b.date) ? 1 : -1
})
}
this.setState({
elements: t
})
}
onHeight = (height: number) => {
onHeight = async (height: number) => {
this.setState({
asideHeight: height
})
}
componentDidMount() {
async componentDidMount() {
const posts = await Post.fetchAll()
const header: Array<PostHeader> = []
let cats: Array<string> = []
posts.forEach(el => {
el.fetchSync()
header.push(el.header)
cats.push(...el.header.tags)
})
header.sort((a, b) => {
return (a.date < b.date) ? 1 : -1
})
cats.sort((a, b) => (a < b) ? -1 : 1)
elements = header
this.setState({
elements
elements: header,
loaded: true,
categories: cats.filter((item, pos) => {return cats.indexOf(item) === pos})
})
}
render() {
return (
<div>
<Head>
<link rel="manifest" href="/manifest.json" />
</Head>
<Navbar>
<Menu />
</Navbar>
<Header />
<main>
<span>
{this.state && this.state.elements.map((el, index) => (
<Element key={index} link={el.link} title={el.title} image={el.img} date={el.date} />
))}
</span>
<Filters categories={categories} onQuery={this.onQuery} onHeight={this.onHeight}/>
</main>
<main>
<span>
{this.state && this.state.elements && this.state.elements.length !== 0 ? this.state.elements.map((el, index) => (
<Element key={index} link={"/"+el.category.toLowerCase() + "/" + el.id} title={el.title} image={el.image} alt={el.imageAlt} date={el.date || new Date} />
)) : this.state && this.state.loaded ? (
<div>La recherche n'a rien donnée <span className="emoji">😢</span></div>
) : (
<div>Chargement en cours... <span className="emoji">😃</span></div>
)}
</span>
<Filters categories={this.state && this.state.categories || []} onQuery={this.onQuery} onHeight={this.onHeight}/>
<style jsx>{`
span {
span:not(.emoji) {
display: flex;
flex-wrap: wrap;
justify-content: center;
flex-grow: 1;
}
main {
display: flex;
flex-direction: column-reverse;
}
div {
font-size: 36px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
main span {
flex-grow: 1;
}
@media (min-width: 820px) and (min-height: ${this.state && this.state.asideHeight ? this.state.asideHeight+100 : 600}px) {
main span {
@media (min-width: 820px) and (min-height: ${this.state && this.state.asideHeight ? this.state.asideHeight+100 : 600}px) {
span {
max-width: calc(100% - 400px);
}
main {
flex-direction: row;
}
}
`}</style>
</div>
</main>
)
}
}

View File

@ -1,28 +0,0 @@
import { NextPage, NextPageContext } from "next"
import React from 'react'
import Post from "../../components/Post"
import ReactMarkdown from 'react-markdown'
interface Props {
post: Post
}
const PostPage: NextPage<Props> = (props: Props) => {
// React.
return (
<main>
<ReactMarkdown source={props.post.content}/>
</main>
)
}
PostPage.getInitialProps = async (context: NextPageContext) => {
const { slug } = context.query
if (typeof slug === "object") throw new Error("Slug is not correct")
const post = new Post(slug)
await post.fetch()
return {post}
}
export default PostPage

85
pages/tag/[tag].tsx Normal file
View File

@ -0,0 +1,85 @@
import { NextPage, NextPageContext } from "next"
import Link from 'next/link'
import Post from "../../components/Post"
import Element from '../../components/Element'
import Error from "../_error"
// import posts from '../../posts/pages.json'
// import firstline from 'firstline'
// import 'fs'
interface Props {
files: Post[],
tag: string
}
const PortfolioIndex: NextPage<Props> = (props: Props) => {
const el: JSX.Element[] = []
for (const post of props.files) {
el.push(
)
}
if (props.files.length === 0) {
return (
<Error statusCode={404} />
)
}
return (
<div>
<h2>Tag: {props && props.tag}</h2>
<div>
{props.files.map((post, index) => (
<Element key={index} link={"/"+post.header.category.toLowerCase() + "/" + post.header.id} title={post.header.title} image={post.header.image} date={post.header.date || new Date} />
))}
</div>
<style jsx>{`
span:not(.emoji) {
display: flex;
flex-wrap: wrap;
justify-content: center;
flex-grow: 1;
}
div div {
display: flex;
flex-direction: row;
}
div {
display: flex;
flex-direction: column;
}
h2 {
display: inline-block;
padding: 20px;
margin: auto;
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
color: white;
font-size: 24px;
text-transform: uppercase;
font-weight: 500;
text-align: center;
border-radius: 10px;
}
`}</style>
</div>
)
}
PortfolioIndex.getInitialProps = async (context: NextPageContext) => {
const { tag } = context.query
if (typeof tag === "object" || tag === "[tag]") return {files: [], tag: ""}
const arr: Post[] = []
for (const post of await Post.fetchAll()) {
if (!post.isStarted) await post.fetch()
let tags = []
for (const tg of post.header.tags) {
tags.push(tg.toLowerCase())
}
if (!tags.includes(tag)) continue
arr.push(post)
}
return {files: arr, tag: tag} as Props
}
export default PortfolioIndex