# project-name

project-description

## Requirement

### Software

- Node 8+ (Recommanded Node 12)
- Npm 6+
- Widows 10 / Mac 10.14

### Knowledge

- [Js Es 2020](https://tc39.es/ecma262/)
- [React](https://reactjs.org/)
- [Next](https://nextjs.org/)
- [Sass](https://sass-lang.com/)

## Installation

`npm i`

## Commands

- `npm run dev` : Run the server in development mode
- `npm run build` : Build the server for the production
- `npm start` : Start the production server, be sure to have build before

## Project folders

- `/src` Dynamic files (js, scss, html) compiled with webpack
- `/src/config/*` Configurations file
- `/public` Static files like images & fonts
- `/public/locales/{locale}/` Folders where json and static images will be localized
- `/server` Server tools
- `/.next` Build & cache folder

## Configuration

Configurations files are located in `/src/config/*` :

- `config.js` : JS Configation for client & server.

Client side :
```js
import getConfig from 'config'
const config = getConfig()
```

Server side :
```js
const config = require('./src/config')()
```

Javascript configuration can be override with the `/.env` file or with `environements variables`.
Priority order is : 

1) config.js
2) environements variables
3) .env

- `config.scss` : Sass configuration

```css
@import "~config/styles.scss";
```

Only use mixins & variables in `config.scss`.

## Sass & CSS modules

- Sass : [https://sass-lang.com/](https://sass-lang.com/)
- CSS modules : [https://github.com/css-modules/css-modules](https://github.com/css-modules/css-modules)

## Basic Auth

You can add a `BasicAuth` for your staging. Just add a `AUTH_LOGIN` and `AUTH_PASSWORD` in `.env`.

```apache
# Authentification
AUTH_LOGIN = login
AUTH_PASSWORD = password
```

> BasicAuth don't work in `export` mode. Add a `.htpasswd` if you are host by an apache server.

## DAN's Pakages

### Router

#### Setup localized routes

Setup your supported locales in the `/.env` file.
```apache
# Supported locales (default in first)
LOCALES = en, fr
```

#### Routes

Add your routes in `/src/routes.js` with :

- `addI18nRoute(path, file, name)` Add a new route for all locales.

```js
/*
Add a new route named "home" for the page "/src/pages/index.js".
Supported URLs are :
- /my-page
- /:locale/my-page
*/
addI18nRoute('/my-page', 'index', 'home')
```

- `addRoute(path, file, name)` Add a new route without localisation.

```js
/*
Add a new route named "home" for the page "/src/pages/index.js".
Supported URLs are :
- /my-page
*/
addRoute('/my-page', 'index', 'home')
```

#### Link & pushRoute

|Method / Component|Description|
|-|-|
|`<Link route="routeName" params={params} options={}>...</Link>`|React component for bind a link|
|`pushRoute(routeName, [params], [option])`|Javascript function for push a new route in the router|

Use `<Link>` For add a link in react with `dan/router` :

```js
import { Link } from 'dan/router'

export default () => (
    <Link route="home" params={{ foo: 'bar' }}>
        <a>Back to home<a>
    </Link>
)
```

You can override localized routes with the parameter `locale`. Be sure to have setup i18n context in your page (see in the section `i18n`).

```js
<Link route="home" params={{ locale: 'fr' }}>
    <a>Page d'accueil</a>
</Link>
```

It's also possible to call `pushRoute(route, params, options)` for javascript link.

```js
import { pushRoute } from 'dan/router'

export default () => (
    <span onClick={() => pushRoute('home', { foo: 'bar' })}>
        Back to home
    </span>
)
```

### i18n

With the i18n package you can have :

- localized URL
- localized pages

`i18n` is a React context in `/src/dan/i18n.js`. You can import it with :
```js
import { I18nContext } from 'dan/i18n'
```

#### API

|Method / Component|Description|
|-|-|
|`i18n.locale`|Get the current locale|
|`i18n.localize(key, [params], [options])`|Get a localized text|
|`<Localize {...params} {...options}>key</Localize>`|React component for localize a text|

#### Setup Provider

For add the provider in a page, call `pageWithI18n(MyPage)`, it will also inject `i18n` in React properties.

```jsx
import { pageWithI18n } from 'dan/i18n'

function HomePage({ i18n }) {
    return (
        <div>
            Current locale : {i18n.locale}
        </div>
    )
}
export default pageWithI18n(HomePage)
```

#### Consumer

You can now use the context in a component of this page with `withI18n(MyComponent)` or `useI18n()`.

```jsx
import { withI18n } from 'dan/i18n'

function MyComponent({ i18n }) {
    return (
        <div>
            Current locale : {i18n.locale}
        </div>
    )
}
export default withI18n(MyComponent)
```

Or you can also get the i18n context with `useI18n()`

```jsx
import { useI18n } from 'dan/i18n'

export default () => {
    const i18n = useI18n()
    return (
        <div>
            Current locale : {i18n.locale}
        </div>
    )
}
```

#### Localized JSON

You can use static localized texts with JSON files. They are located in `/public/locales/{locale}/*.json`

```json
{
    "hello": "Hello {name} !"
}
```

By dedault `main.json` is loaded. For add more JSON in a page :

```js
export default pageWithI18n(MyPage, [
    'main', // /public/locales/{locale}/main.js
    'items' // /public/locales/{locale}/items.json
])
```

Get localized text with :

- `localize(key, params, options)`
- `<Localize {...params} {...options}>key</Localize>`

```js
import { localize, Localize } from 'dan/i18n'

export default () => (
    <div>
        {localize('hello', { name: 'dan' })}
        <Localize name="dan">hello</Localize>
    </div>
)
```

### Is

`is` is the pakage for get information about the current user. It works with useragent.

`is` is a React context in `/src/dan/is.js`. You can import it with :

```js
import { IsContext } from 'dan/is'
```

#### API

|Property|Description|
|-|-|
|`is.ie`|Internet explorer 11|
|`is.edge`|Edge|
|`is.firefox`|Firefox|
|`is.chrome`|Chrome|
|`is.safari`|Safari|
|`is.ios`|iOs|
|`is.android`|Android|
|`is.tablet`|Tablet|
|`is.mobile`|Mobile|
|`is.desktop`|Desktop|
|`is.images`|Supported images|

#### Setup Provider

For add the provider in a page, call `pageWithIs(MyPage)`, it will also inject `is` in React properties.

```jsx
import { pageWithIs } from 'dan/is'

function HomePage({ is }) {
    return (
        <div>
            Is mobile : {is.mobile}
        </div>
    )
}
export default pageWithIs(HomePage)
```

#### Consumer

You can now use the context in a component of this page with `withIs(MyComponent)` or `useIs()`.

```jsx
import { withIs } from 'dan/is'

function MyComponent({ is }) {
    return (
        <div>
            Is mobile : {is.mobile}
        </div>
    )
}
export default withIs(MyComponent)
```

Or you can also get the `is` context with `useIs()`

```jsx
import { useIs } from 'dan/is'

export default () => {
    const is = useIs()
    return (
        <div>
            Is mobile : {is.mobile}
        </div>
    )
}
```

### Assets

```js
import { newQueue } from 'dan/assets'

const q = newQueue()
q.add('data/test01.txt', { id: 'text' })
q.add('data/test02.png', { id: 'image' })
q.add('data/test02.json', { id: 'json' })
q.onComplete.once((assets) => {
    console.log('Queue completed:', assets) 
    console.log('Text:', q.get('text'))
})
```

#### Cache

```js
import { newQueue, getFromCache } from 'dan/assets'

const q = newQueue({
    cache: true // All the queue will be cached
})
q.add('data/test01.txt', {
    id: 'text',
    cache: true // Only this asset wil be cached
})

q.onComplete.once(() => {
    console.log(getFromCache('text'))
})
```

#### Assynchronous Start

```js
import { newQueue } from 'dan/assets'

const q = newQueue({
    autoStart: false
})
q.add('data/test01.mp4')
q.add('data/test02.mp4')
q.add('data/test03.mp4')

// Wait 1s before starting the queue
setTimeout(() => {
    q.start()
}, 1000)
```

#### Stop & resume

```js
q.add('data/test01.mp4').catch(() => {
    q.stop() // Stop
    setTimeout(() => {
        q.start() // Resume
    }, 1000)
})
```

#### Number of simultaneous download in parallel

```js
const q = newQueue({
    simultaneous: 4 // 4 simultaneous max
})
```

#### Priority

```js
const q = newQueue({
    simultaneous: 2
})
q.add('data/test01.text')
q.add('data/test02.text', { priority: 1 })
q.add('data/test03.text', { priority: 2 })
q.add('data/test04.text')

// Download order will be: test02, test03, test01, test04
```

### Request animation frame

```js
import { addRaf } from 'dan/raf'

addRaf((dt) => {
    console.log(`delta time: ${dt}ms`)
})
