Signed-off-by: Avior <florian.bouillon@delta-wings.net>
This commit is contained in:
2019-12-16 23:59:00 +01:00
parent f19f4f43a6
commit 70f05363e2
33 changed files with 8242 additions and 0 deletions

32
components/Button.tsx Normal file
View File

@ -0,0 +1,32 @@
import { Component } from "react";
import { type } from "os";
import '../styl/styl.styl'
export enum ButtonType {
NORMAL = "",
OUTLINE = "outline",
GHOST = "ghost"
}
interface Props {
text: string
type?: ButtonType
// src: string
// alt?: string
// layout?: string
}
export default class DWButton extends Component<Props, {}> {
constructor(props: Props) {
super(props)
}
render() {
return (
<button className={this.props.type}>{this.props.text}</button>
)
}
}

89
components/Element.tsx Normal file
View File

@ -0,0 +1,89 @@
import React from 'react'
import Link from 'next/link'
import { ChevronRight } from 'react-feather'
interface Props {
title: string
date: Date
image?: string
link: string
}
const months = [
"le 13eme mois",
'Janvier',
'Février',
'Mars',
'Avril',
'Mai',
'Juin',
'Juillet',
'Août',
'Septembre',
'Octobre',
'Novembre',
'Décembre'
]
export default class Element extends React.Component<Props, {}> {
constructor(props: Props) {
super(props)
}
render() {
return (
<div>
<Link href={this.props.link}>
{this.props.image ? (
<a><img src={this.props.image}/></a>
) : (
<div></div>
)}
</Link>
<i>Le {this.props.date.getDate()} {months[this.props.date.getMonth()]} {this.props.date.getFullYear()}</i>
<span>
<Link href={this.props.link}>
<a>{this.props.title}</a>
</Link>
<Link href={this.props.link}>
<a><ChevronRight size={48}/></a>
</Link>
</span>
<style jsx>{`
div {
padding: 5% 5%;
max-width: 40%;
min-width: 400px;
}
img {
width: 100%;
border-radius: 10px;
height: 250px;
object-fit: cover;
}
span {
display: flex;
justify-content: space-between;
align-items: center;
}
a, i {
margin: 10px 0;
display: block;
}
i {
font-style: italic;
font-size: 14px;
}
a {
font-weight: bold;
font-size: 24px;
color: black;
text-decoration: none;
}
`}</style>
</div>
)
}
}

158
components/Filters.tsx Normal file
View File

@ -0,0 +1,158 @@
import React from 'react'
import Link from 'next/link'
import Category from './interfaces/Category'
import '../styl/styl.styl'
import { ChevronRight } from 'react-feather'
import Router from 'next/router'
interface Props {
categories?: Category[]
onQuery?: (query: string) => void
onHeight?: (height: number) => void
}
interface States {
follow?: boolean
height?: number
}
export default class Filters extends React.Component<Props, States> {
private aside = undefined
private input = undefined
constructor(props: Props) {
super(props)
}
setRef = element => {
this.aside = element
}
setInput = element => {
this.input = element
}
onScroll = () => {
this.setState({
follow: window.pageYOffset > 217
})
}
onKeyDown = (ev: React.KeyboardEvent<HTMLInputElement>) => {
setTimeout(() => {
this.submit()
}, 1);
}
onClick = () => {
if (this.input.value !== "") {
this.submit()
return
}
this.input.focus()
}
submit = () => {
if (this.props.onQuery) this.props.onQuery(this.input.value)
}
componentDidMount() {
this.onScroll()
this.setState({
height: this.aside.clientHeight
})
if (this.props.onHeight) this.props.onHeight(this.aside.clientHeight)
window.addEventListener('scroll', this.onScroll)
}
componentWillUnmount() {
window.removeEventListener('scroll', this.onScroll)
}
render() {
return (
<aside ref={this.setRef} className={this.state && this.state.follow ? "follow" : ""}>
<div>Trier</div>
<div className="input icon-right">
<select>
<option value="plus récant au moins récent"></option>
</select>
</div>
<div>Filtrer</div>
<div className="input icon-right">
<input placeholder="ex: dzeio.com" type="text" ref={this.setInput} onKeyDownCapture={this.onKeyDown} />
<i>
<ChevronRight onClick={this.onClick} />
</i>
</div>
<p>Languages :</p>
{this.props.categories.map(cat => (
<Link key={cat.slug} href={cat.slug}>
<a>{cat.name}</a>
</Link>
))}
<style jsx>{`
aside {
padding: 5% 3% 0;
}
@media (min-width: 820px) and (min-height: ${this.state && this.state.height ? this.state.height+100 : 600}px) {
aside {
position: absolute;
min-width: calc(400px - 6%);
right: 0;
}
aside.follow {
position: fixed;
top: 70px;
}
}
.input {
display: flex;
justify-content: center;
margin: 20px 0;
}
div:not(.input) {
display: block;
padding: 20px;
margin: 10px 0;
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;
}
a {
padding: 7px 12px;
background: #4285F4;
color: white;
text-transform: uppercase;
border-radius: 10px;
font-size: 20px;
text-decoration: none;
display: inline-block;
transition: background 200ms
}
a:hover {
background: #45CAFC;
}
`}</style>
</aside>
)
}
}

32
components/Header.tsx Normal file
View File

@ -0,0 +1,32 @@
import React from 'react'
interface Props {
}
export default class Header extends React.Component<Props, {}> {
constructor(props: Props) {
super(props)
}
render() {
return (
<div>
<img src="/clouds.svg" alt=""/>
<style jsx>{`
div {
position: relative;
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
height: 207px;
}
img {
position: absolute;
bottom: 0;
min-width: 100%;
height: 50px
}
`}</style>
</div>
)
}
}

46
components/Menu.tsx Normal file
View File

@ -0,0 +1,46 @@
import React from 'react'
import Link from 'next/link'
interface Props {
}
export default class Menu extends React.Component<Props, {}> {
constructor(props: Props) {
super(props)
}
render() {
return (
<ul>
<li>
<Link href="/">
<a>Home</a>
</Link>
</li>
<style jsx>{`
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
background: white;
width: calc(100% - 10px);
padding: 5px;
}
a {
color: black;
display: block;
text-decoration: none;
padding: 10px;
border-radius: 10px;
transition: background 200ms
}
a:hover {
background: #45CAFC20
}
`}</style>
</ul>
)
}
}

125
components/Navbar.tsx Normal file
View File

@ -0,0 +1,125 @@
import React from 'react'
import { Menu } from 'react-feather'
import { timingSafeEqual } from 'crypto'
interface Props {
height?: number
}
interface States {
scrolled: boolean
}
export default class Navbar extends React.Component<Props, States> {
private height = 80
private menuRef = undefined
constructor(props: Props) {
super(props)
if (this.props.height) {
this.height = this.props.height
}
}
setRef = element => {
this.menuRef = element
}
onScroll = () => {
this.setState({
scrolled: window.pageYOffset > 207
})
}
componentDidMount() {
window.addEventListener('scroll', this.onScroll)
}
componentWillUnmount() {
window.removeEventListener('scroll', this.onScroll)
}
onClick = () => {
this.menuRef.classList.toggle("shown")
}
render() {
const height = this.props.height || 80
// if (!this.state.scrolled)
// console.log(this.state.scrolled)
return (
<nav className={this.state && this.state.scrolled ? "scrolled" : ""}>
<style jsx global>{`
body {
margin-top: ${height}px;
overflow-x: hidden;
}
`}</style>
<hr />
<div className="head">
<img src="/logo.svg" alt=""/>
<span onClick={this.onClick} data-menu={this.refs.menu}>
<Menu size={30} />
</span>
</div>
<div ref={this.setRef} className="menu">
{this.props.children}
</div>
<style jsx>{`
nav {
position: fixed;
width: 100%;
top: 0;
z-index: 1000;
transition: box-shadow 200ms
}
nav.scrolled {
box-shadow: 0 0 10px 5px #00000040
}
img {
height: 80%;
}
hr {
height: 10px;
margin: 0;
border: none;
background: linear-gradient(90deg, #45CAFC 0%, #4285F4 92.19%);
}
.menu {
display: none
}
.menu.shown {
display: block
}
.head {
display: flex;
height: ${height-10}px;
background: white;
padding-left: ${height-10}px;
justify-content: center;
align-items: center;
}
img {
flex-grow: 1;
}
span {
width: ${height-10}px;
height: ${height-10}px;
display: flex;
justify-content: center;
align-items: center;
}
`}</style>
</nav>
)
}
}

56
components/Post.ts Normal file
View File

@ -0,0 +1,56 @@
import matter from 'gray-matter'
interface PostInterface {
slug: string
title: string
content: any
}
interface PostHeader {
title: string
}
export default class Post implements PostInterface {
public slug: string
public title: string
public content: string
public isStarted = false
constructor(slug: string) {
this.slug = slug
}
public async fetch() {
console.log(this.slug)
const content = await import(`../posts/${this.slug}.md`)
const md = matter(content.default)
this.title = md.data.title
this.content = md.content
}
public fetchSync() {
console.log(this.slug)
const content = require(`../posts/${this.slug}.md`)
const md = matter(content.default)
this.title = md.data.title
this.content = md.content
}
public static async fetchAll(): Promise<Post[]> {
const files: string[] = ((require as any).context('../posts', true, /\.md$/)).keys()
const posts: Post[] = []
for (const file of files) {
posts.push(
new Post(
file.replace(/^.*[\\\/]/, '')
.split('.')
.slice(0, -1)
.join('.')
)
)
}
return posts
}
}

15
components/default.tsx Normal file
View File

@ -0,0 +1,15 @@
import React from 'react'
interface Props {
}
export default class Name extends React.Component<Props, {}> {
constructor(props: Props) {
super(props)
}
render() {
return (
<span></span>
)
}
}

View File

@ -0,0 +1,4 @@
export default interface Category {
name: string
slug: string
}