Merge branch 'dev'

# Conflicts:
#	package.json
#	yarn.lock
This commit is contained in:
2021-08-24 13:09:15 +02:00
123 changed files with 2607 additions and 12096 deletions

View File

@@ -1 +1,2 @@
node_modules
build

0
.editorconfig Executable file → Normal file
View File

2
.npmrc
View File

@@ -1,2 +0,0 @@
shamefully-hoist=true
ignore-workspace-root-check=true

View File

@@ -1,18 +1,15 @@
FROM node:15.8.0-alpine3.10
FROM node:16-alpine3.11
RUN mkdir -p /usr/src/artsite
WORKDIR /usr/src/artsite
RUN mkdir -p /usr/src/ares
COPY . /usr/src/artsite
WORKDIR /usr/src/ares
RUN yarn install
COPY . /usr/src/ares
RUN yarn install --production
RUN yarn build
RUN cp .env build
EXPOSE 3333
COPY . .
CMD ["yarn", "start"]

View File

@@ -1,4 +1,4 @@
# ArtSite 🌍
# Arès 🌍
This is my personnal website.
Hosted version : [arthurdanjou.fr](https://arthurdanjou.fr)
@@ -13,7 +13,7 @@ Hosted version : [arthurdanjou.fr](https://arthurdanjou.fr)
- Automatic working state
- Wonderfull Mobile-Header
- Multi-Language site
- Connected to ArtApi (my personal api)
- Connected to [Athena](https://github.com/arthurdanjou/athena) (my personal api)
## Tech used ⚙
@@ -30,4 +30,4 @@ Hosted version : [arthurdanjou.fr](https://arthurdanjou.fr)
## License 📑
Copyright © 2020 - [@ArthurDanj](https://arthurdanjou.fr) \
This project is [MIT](https://github.com/ArthurDanjou/artsite/blob/master/License) Licensed.
This project is [MIT](https://github.com/ArthurDanjou/ares/blob/master/License) Licensed.

View File

@@ -6,6 +6,7 @@ import arch from './settings/Arch'
import plugins from './settings/Plugins'
import css from './settings/Style'
import configs from './settings/RuntimeConfig'
import {NuxtConfig} from "@nuxt/types";
const config = {
head,
@@ -16,6 +17,6 @@ const config = {
css,
buildModules,
...configs,
}
} as NuxtConfig
export default config

View File

@@ -1,5 +1,5 @@
{
"name": "artsite",
"name": "ares",
"version": "1.0.0",
"private": true,
"scripts": {
@@ -10,26 +10,27 @@
"dependencies": {
"@nuxt/content": "^1.14.0",
"@nuxtjs/axios": "^5.13.6",
"@nuxtjs/composition-api": "0.23.4",
"@nuxtjs/composition-api": "^0.27.0",
"@nuxtjs/dotenv": "^1.4.1",
"@nuxtjs/i18n": "^7.0.2",
"@nuxtjs/proxy": "^2.1.0",
"@nuxtjs/redirect-module": "^0.3.1",
"@nuxtjs/robots": "^2.5.0",
"@nuxtjs/sentry": "^5.1.0",
"@nuxtjs/sentry": "^5.1.2",
"@nuxtjs/sitemap": "^2.4.0",
"@nuxtjs/universal-storage": "^0.5.9",
"core-js": "^3.14.0",
"nuxt": "^2.15.7",
"nuxt-i18n": "^6.27.1",
"prism-themes": "^1.7.0",
"sass": "^1.35.2",
"windicss": "^3.1.3"
"axios": "^0.21.1",
"core-js": "^3.16.2",
"nuxt": "^2.15.8",
"prism-themes": "^1.8.0",
"sass": "^1.38.0"
},
"devDependencies": {
"@nuxt/types": "^2.15.7",
"@nuxt/types": "^2.15.8",
"@nuxt/typescript-build": "^2.1.0",
"@nuxtjs/color-mode": "^2.0.10",
"markdown-it-prism": "^2.1.6",
"nuxt-windicss": "1.0.3",
"@nuxtjs/color-mode": "^2.1.1",
"markdown-it-prism": "^2.1.8",
"nuxt-windicss": "^1.2.3",
"sass-loader": "10.1.1"
}
}

View File

@@ -34,4 +34,15 @@ const buildDir = 'build'
const ssr = true
export default { srcDir, dir, build, pageTransition, target, server, buildDir, components, ssr }
const proxy = {
'/api': {
target: 'https://athena.arthurdanjou.fr',
pathRewrite: { "^/api": "" }
}
}
const router = {
middleware: 'maintenance'
}
export default { router, srcDir, dir, build, pageTransition, target, server, buildDir, components, ssr, proxy }

View File

@@ -1,6 +1,15 @@
// Build Configuration: https://go.nuxtjs.dev/config-build
export default {
babel: {
plugins: [['@babel/plugin-proposal-private-methods', { loose: true }]],
plugins: [
['@babel/plugin-proposal-private-methods', { loose: true }]
],
},
postcss: {
preset: {
features: {
"focus-within-pseudo-class": false
}
}
}
}

View File

@@ -2,7 +2,7 @@
import {NuxtOptionsHead} from "@nuxt/types/config/head";
const params = {
title: 'artsite',
title: 'arthurdanjou.fr - Web & Software Developer',
color: '#00a0ff',
image: '/images/memojies/Hey.png',
url: 'https://arthurdanjou.fr',

View File

@@ -1,8 +1,9 @@
import {NuxtOptionsModule} from "@nuxt/types/config/module";
const axios = {
proxy: true,
credentials: true,
baseURL: 'https://api.arthurdanjou.fr'
proxyHeaders: true
}
const i18n = {
@@ -31,7 +32,6 @@ const i18n = {
}
const content = {
apiPrefix: 'api',
nestedProperties: ['skills.slug'],
markdown: {
prism: {
@@ -49,7 +49,7 @@ const content = {
const storage = {
cookie: {
prefix: 'artsite/',
prefix: 'arthurdanjou.fr/',
options: {
path: '/'
}
@@ -71,9 +71,7 @@ const robots = {
}
const redirect = [
{ from: '/source', to: 'https://github.com/arthurdanjou/artsite' },
{ from: '/twitter', to: 'https://twitter.com/arthurdanj' },
{ from: '/github', to: 'https://github.com/arthurdanjou/' },
{ from: '/source', to: 'https://github.com/arthurdanjou/ares' },
{ from: '/shelf', to: '/blog' },
{ from: '/posts', to: '/blog' },
{ from: '/resume', to: '/cv' }
@@ -84,15 +82,12 @@ const env = {
}
const sentry = {
dsn: process.env.SENTRY_DSN,
config: {
}
dsn: process.env.SENTRY_DSN
}
export default [
['@nuxtjs/axios', axios],
['nuxt-i18n', i18n],
['@nuxtjs/i18n', i18n],
['@nuxt/content', content],
['@nuxtjs/universal-storage', storage],
['@nuxtjs/robots', robots],

View File

@@ -2,8 +2,5 @@
export default [
{
src: '~/plugins/i18n.ts'
},
{
src: '~/plugins/main.ts',
}
]

View File

@@ -1,5 +1,4 @@
const publicRuntimeConfig = {
}
const privateRuntimeConfig = {

View File

@@ -1,4 +1,5 @@
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@500&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@900&display=swap');
.icon {
transform: translate(3px, -3px);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 340 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 457 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

49
src/components/About.vue Normal file
View File

@@ -0,0 +1,49 @@
<template>
<section v-if="age" class="w-full flex items-center justify-center my-12">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="mb-12 md:mb-0 w-full md:w-1/2 flex justify-center">
<img src="@/assets/images/memojies/Hat.png" alt="It's me !" class="xl:w-1/2" />
</div>
<div class="md:w-1/2 text-justify">
<h2 class="text-4xl font-bold text-center md:text-justify">
{{ $t('home.about.title') }}
</h2>
<p class="text-xl my-6 text-gray-700 dark:text-gray-400">
{{ $t('home.about.description', {age: age}) }}
</p>
<div class="flex justify-center md:justify-start">
<Button content="home.about.about" link="about" />
</div>
</div>
</div>
</section>
</template>
<script lang="ts">
import {defineComponent, useAsync, useContext} from "@nuxtjs/composition-api";
export default defineComponent({
name: "About",
setup() {
const {$axios, $sentry, app} = useContext()
const age = useAsync(async () => {
const response = await $axios.get('/api/informations', {
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`
}
})
if (response.status === 200) {
return response.data.informations.age
} else {
$sentry.captureEvent(response.data)
app.error({statusCode: 500})
}
}, 'infos')
return {
age
}
}
})
</script>

View File

@@ -1,43 +0,0 @@
<template>
<section v-if="info && info.age" class="w-full flex items-center justify-center my-12">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="mb-12 md:mb-0 w-full md:w-1/2 flex justify-center">
<img src="~/assets/images/memojies/Hat.png" alt="It's me !" class="xl:w-1/2" />
</div>
<div class="md:w-1/2 text-justify">
<h2 class="text-4xl font-bold text-center md:text-justify">
{{ $t('home.about.title') }}
</h2>
<p class="text-xl my-6 text-gray-700 dark:text-gray-400">
{{ $t('home.about.description', {age: info.age}) }}
</p>
<div class="flex justify-center md:justify-start">
<Button content="home.about.about" link="about"/>
</div>
</div>
</div>
</section>
</template>
<script lang="ts">
import {defineComponent, useAsync, useContext} from "@nuxtjs/composition-api";
import {InfoData} from "~/types/types";
export default defineComponent({
name: "AboutHome",
setup() {
const {$content, $sentry} = useContext()
const info = useAsync(() => {
return $content('infos')
.fetch<InfoData>()
.catch((error) => {
$sentry.captureEvent(error)
});
})
return {
info
}
}
})
</script>

View File

@@ -37,6 +37,6 @@
<script lang="ts">
export default {
name: "AdPreview"
name: "AdHome"
}
</script>

View File

@@ -0,0 +1,64 @@
<template>
<div
v-if="announce"
class="p-4 duration-300 flex justify-center items-center text-center"
:class="[getHoverColor, getBackgroundColor]"
>
{{ $t(announce.message.code) }}
<img
v-if="announce.file"
:src="`https://athena.arthurdanjou.fr/files/${announce.file}`"
alt="Announce Cover File"
>
</div>
<div v-else class="p-4 duration-300 flex justify-center items-center text-center bg-black dark:bg-white text-white dark:text-black">
{{ $t('loading') }}
</div>
</template>
<script lang="ts">
import {computed, defineComponent, useAsync, useContext} from "@nuxtjs/composition-api";
export default defineComponent({
name: "Announce",
setup() {
const {$axios, $sentry, app} = useContext()
const announce = useAsync(async () => {
const response = await $axios.get('/api/announce', {
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`
}
})
if (response.status === 200) {
return response.data.announce
} else {
$sentry.captureEvent(response.data)
app.error({statusCode: 500})
}
}, 'announce')
const getBackgroundColor = computed(() => {
switch (announce.value.color) {
case 'black': {
return 'bg-black text-white dark:(bg-white text-black)'
}
}
})
const getHoverColor = computed(() => {
switch (announce.value.hover_color) {
case 'gray': {
return 'hover:bg-gray-800 dark:hover:bg-gray-300'
}
}
})
return {
announce,
getBackgroundColor,
getHoverColor,
}
}
})
</script>

View File

@@ -1,5 +1,5 @@
<template>
<section class="my-16 md:my-32 w-full flex items-center justify-center">
<section class="my-16 w-full flex items-center justify-center">
<div class="text-center flex flex-col items-center">
<h1 class="text-6xl font-bold text-gray-700 dark:text-gray-400">
{{ $t('home.banner.hello') }} <span class="text-black dark:text-white">Arthur Danjou</span> 👋,
@@ -8,26 +8,66 @@
<strong>{{ $t('home.banner.role') }}</strong>. <br />
{{ $t('home.banner.student.main') }} <strong>{{ $t('home.banner.student.strong') }}</strong>.
</h2>
<p class="mt-4 text-lg text-gray-800 mb-10 dark:text-gray-300">{{ $t('home.banner.contact.follow') }}
<a href="https://twitter.com/arthurdanj" target="_blank" rel="noreferrer noopener" class="link">Twitter</a>,
<a href="https://twitch.tv/arthurdanjou" target="_blank" rel="noreferrer noopener" class="link">Twitch</a>
{{ $t('home.banner.contact.and') }}
<a href="https://github.com/arthurdanjou" target="_blank" rel="noreferrer noopener" class="link">Github</a>
{{ $t('home.banner.contact.spacer') }}
<nuxt-link to="contact" class="link">{{ $t('home.banner.contact.contact') }}</nuxt-link> {{ $t('home.banner.contact.me') }}
</p>
<div class="select-none mt-4 text-5xl text-gray-800 mb-10 dark:text-gray-300">
<span id="develop" class="color blue">{{ $t('home.banner.color.develop') }}</span>
<span id="publish" class="color">{{ $t('home.banner.color.publish') }}</span>
<span id="improve" class="color">{{ $t('home.banner.color.improve') }}</span>
</div>
</div>
</section>
</template>
<script lang="ts">
export default {
name: "Banner"
import {defineComponent, onMounted, onUnmounted} from "@nuxtjs/composition-api";
interface Color {
name: string,
color: string
}
const COLORS: Color[] = [
{ name: 'develop', color: 'blue' },
{ name: 'publish', color: 'red' },
{ name: 'improve', color: 'green' }
]
export default defineComponent({
name: "Banner",
setup() {
let task
onMounted(() => {
let CURRENT = 0
task = setInterval(() => {
const color = COLORS[CURRENT]
const new_color = COLORS[CURRENT === COLORS.length -1 ? 0 : CURRENT + 1]
document.getElementById(new_color.name)!.classList.toggle(new_color.color)
setTimeout(() => document.getElementById(color.name)!.classList.toggle(color.color), 0)
CURRENT === COLORS.length - 1 ? CURRENT = 0 : CURRENT++
}, 2000)
})
onUnmounted(() => clearInterval(task))
}
})
</script>
<style scoped lang="scss">
.link {
@apply font-medium cursor-pointer border-b-2 border-gray-200 text-indigo-600 hover:border-indigo-600 duration-200 dark:(font-white border-gray-700) hover:dark:border-indigo-600
}
.color {
@apply duration-500 text-white dark:text-black font-color;
&.red {
@apply select-text bg-clip-text text-transparent bg-gradient-to-r from-red-600 to-rose-300
}
&.blue {
@apply select-text bg-clip-text text-transparent bg-gradient-to-r from-blue-600 to-cyan-400
}
&.green {
@apply select-text bg-clip-text text-transparent bg-gradient-to-r from-emerald-600 to-lime-500
}
}
</style>

View File

@@ -1,9 +1,9 @@
<template>
<section class="w-full flex items-center justify-center flex-col">
<h2 class="text-center mb-10 font-bold text-gray-700 text-2xl md:text-3xl my-4 dark:text-gray-400">
<section class="w-full flex justify-center flex-col">
<h2 class="mb-10 font-bold text-gray-700 text-2xl md:text-3xl my-4 dark:text-gray-400">
{{ $t('contact.form.title.main') }} <br class="lg:hidden"/><a class="email text-black dark:text-white" href="mailto:me@arthurdanjou.fr" target="_blank">{{ $t('contact.form.title.email') }}</a> 📬
</h2>
<form class="w-full lg:w-1/2">
<form class="w-full">
<div class="w-full lg:flex justify-center mb-8 lg:mb-12">
<div class="form-div lg:w-1/2 mb-8 lg:mb-0 lg:mr-4">
<input
@@ -11,7 +11,6 @@
v-model="form.name"
required
type="text"
placeholder=" "
class="first-input w-full"
/>
<label for="name" class="form-label">{{ $t('contact.form.name') }}</label>
@@ -22,7 +21,6 @@
v-model="form.email"
required
type="email"
placeholder=" "
class="second-input w-full"
/>
<label for="email" class="form-label">{{ $t('contact.form.email') }}</label>
@@ -34,7 +32,6 @@
v-model="form.subject"
required
type="text"
placeholder=" "
class="form-input w-full"
/>
<label for="subject" class="form-label">{{ $t('contact.form.subject') }}</label>
@@ -44,7 +41,6 @@
id="content"
v-model="form.content"
required
placeholder=" "
class="form-input w-full"
minlength="30"
rows="4"
@@ -52,14 +48,19 @@
<label for="content" class="form-label">{{ $t('contact.form.content') }}</label>
</div>
</form>
<div v-if="error" class="mt-4 px-3 py-1 rounded-full bg-red-300 font-bold text-black">
<div v-if="error" class="mt-2 py-1 text-red-400 text-sm">
{{ $t('contact.form.error') }}
</div>
<div v-if="success" class="mt-4 px-3 py-1 rounded-full bg-green-300 font-bold text-black">
<div v-if="success" class="mt-2 py-1 text-green-400 text-sm">
{{ $t('contact.form.success') }}
</div>
<div class="my-12">
<button :disabled="!isSendable" :class="{'disabled': !isSendable}" @click.prevent="handleForm" class="font-bold px-6 py-3 border-2 rounded-full border-indigo-600 text-indigo-600 hover:(bg-indigo-600 text-white) hover:dark:text-black duration-300 cursor-pointer">
<div class="my-12 flex justify-center">
<button
:disabled="!isSendable"
:class="{'disabled': !isSendable}"
@click.prevent="handleForm"
class="font-bold px-8 py-4 border-2 rounded-xl border-indigo-600 text-indigo-600 hover:(bg-indigo-600 text-white) hover:dark:text-black duration-300 cursor-pointer"
>
{{ $t('contact.form.submit') }}
</button>
</div>
@@ -79,7 +80,7 @@ export default defineComponent({
const {$axios, $sentry} = useContext()
const form = ref<Form>({} as Form)
const handleForm = async () => {
const response = await $axios.post('form',
const response = await $axios.post('/api/form',
{
email: form.value.email,
name: form.value.name,
@@ -155,7 +156,7 @@ textarea:focus-within ~ label, textarea:not(:placeholder-shown) ~ label {
}
.email {
@apply duration-300 border-b-2 border-gray-200 dark:border-gray-800 hover:(border-black dark:border-white)
@apply duration-300 border-b-3 border-gray-200 dark:border-gray-800 hover:border-indigo-600
}
.disabled {

View File

@@ -6,7 +6,7 @@
</h3>
<div v-if="experiences" v-for="experience in experiences">
<Experience
:title="experience.title"
:title="experience.title.code"
:company="experience.company"
:location="experience.location"
:begin="experience.begin_date"
@@ -17,21 +17,27 @@
<script lang="ts">
import {defineComponent, useAsync, useContext} from "@nuxtjs/composition-api";
import {Experience} from "~/types/types";
export default defineComponent({
name: "ExperiencesAbout",
setup() {
const {$content, $sentry} = useContext()
const {$axios, $sentry, app} = useContext()
const experiences = useAsync(() => {
return $content('experiences')
.sortBy('end_date', 'desc')
.fetch<Experience>()
.catch((error) => {
$sentry.captureEvent(error)
const experiences = useAsync(async () => {
const response = await $axios.get('/api/experiences', {
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`
}
})
if (response.status === 200) {
return response.data.experiences.sort((a, b) => {
return a.end_date === 'Today' ? -1 : a.end_date.split('-')[1] > b.end_date.split('-')[1] ? -1 : a.end_date.split('-')[0] > b.end_date.split('-')[0] ? 0 : 1
})
})
} else {
app.error({statusCode: 500})
$sentry.captureEvent(response.data)
}
}, 'experiences')
return {
experiences

View File

@@ -1,69 +1,153 @@
<template>
<footer class="footer w-full border-t-2 border-solid border-gray-200 dark:border-gray-800 mb-20 md:mb-0">
<div>
<div class="flex flex-col items-center py-4 text-center ">
<div class="mb-3">
<p class="inline">{{ $t('footer.find_me') }}
<br class="md:hidden"/>
<a class="font-semibold" href="https://twitch.com/ArthurDanjou" target="_blank" rel="noopener noreferrer">
<TwitchIcon />
<span class="link">Twitch</span>
</a>,
<a class="font-semibold" href="https://github.com/ArthurDanjou" target="_blank" rel="noopener noreferrer">
<GithubIcon />
<span class="link">Github</span>
</a> &
<a class="font-semibold" href="https://twitter.com/ArthurDanj" target="_blank" rel="noopener noreferrer">
<footer class="footer w-full mt-20">
<div class="p-8 pb-0">
<div class="lg:flex justify-evenly items-center">
<div class="lg:w-1/3">
<div class="flex">
<Logo />
</div>
<div class="my-8">
<p class="text-justify">
{{ $t('footer.description') }}
</p>
<div class="mt-4">
<nuxt-link to="/contact" class="text-red-400 border-b-2 border-gray-200 dark:border-gray-700 hover:border-red-400 duration-300">
{{ $t(hiring_message) }}
</nuxt-link>
</div>
</div>
<div class="social-links flex space-x-4 mb-8">
<a target="_blank" href="https://twitter.com/ArthurDanj" rel="noopener noreferrer">
<TwitterIcon />
<span class="link">Twitter</span>
</a>
<br class="md:hidden"/>
{{ $t('footer.separator') }}
<a class="font-semibold" href="mailto:contact@arthurdanjou.fr" target="_blank" rel="noopener noreferrer">
<a target="_blank" href="https://github.com/ArthurDanjou" rel="noopener noreferrer">
<GithubIcon />
</a>
<a target="_blank" href="https://www.polywork.com/arthurdanjou" rel="noopener noreferrer">
<PolyworkIcon />
</a>
<a target="_blank" href="https://www.twitch.tv/arthurdanjou" rel="noopener noreferrer">
<TwitchIcon />
</a>
<a target="_blank" href="https://discord.gg/ENG6cFQhPS" rel="noopener noreferrer">
<DiscordIcon />
</a>
<a target="_blank" href="mailto:contact@arthurdanjou.fr" rel="noopener noreferrer">
<MailIcon />
<span class="link">Mail</span>
</a>
</p>
<br class="md:hidden"/>
<span class="inline dark:text-gray-400 text-gray-600 text-xs">
{{ $t('footer.links_click') }}
</span>
</div>
</div>
<p>
<div class="lg:ml-32 lg:w-1/3">
<h1 class="font-bold mb-4 text-lg underline">
{{ $t('footer.links') }}
</h1>
<div class="flex flex-col lg:flex-row mb-8 font-medium">
<div class="space-y-2 lg:space-y-4 mr-16">
<div class="link">
<nuxt-link to="/" :class="{'link-active': isWindow('')}">
{{ $t('header.home') }}
</nuxt-link>
</div>
<div class="link">
<nuxt-link to="/about" :class="{'link-active': isWindow('about')}">
{{ $t('header.about') }}
</nuxt-link>
</div>
<div class="link">
<nuxt-link to="/blog" :class="{'link-active': isWindow('blog')}">
{{ $t('header.blog') }}
</nuxt-link>
</div>
<div class="link">
<nuxt-link to="/projects" :class="{'link-active': isWindow('projects')}">
{{ $t('header.projects') }}
</nuxt-link>
</div>
</div>
<div class="space-y-2 lg:space-y-4 ">
<div class="link">
<nuxt-link to="/services" :class="{'link-active': isWindow('services')}">
{{ $t('header.services') }}
</nuxt-link>
</div>
<div class="link">
<nuxt-link to="/env" :class="{'link-active': isWindow('env')}">
{{ $t('header.env') }}
</nuxt-link>
</div>
<div class="link">
<nuxt-link to="/newsletter" :class="{'link-active': isWindow('newsletter')}">
{{ $t('header.newsletter') }}
</nuxt-link>
</div>
<div class="link">
<nuxt-link to="/contact" :class="{'link-active': isWindow('contact')}">
{{ $t('header.contact') }}
</nuxt-link>
</div>
</div>
</div>
</div>
</div>
<div class="text-center border-t-2 border-gray-200 dark:border-gray-800 py-8 lg:flex lg:flex-row-reverse justify-between">
<div>
{{ $t('footer.credits') }}
<a class="font-semibold" target="_blank" href="https://nuxtjs.org" rel="noopener noreferrer">
<a class="social font-semibold" target="_blank" href="https://nuxtjs.org" rel="noopener noreferrer">
<NuxtIcon />
<span class="link">NuxtJS</span>
<span>NuxtJS</span>
</a>
{{ $t('footer.credits_separator_and') }}
<a class="font-semibold" target="_blank" href="https://adonisjs.com" rel="noopener noreferrer">
{{ $t('footer.credits_separator') }}
<a class="social font-semibold" target="_blank" href="https://adonisjs.com" rel="noopener noreferrer">
<AdonisIcon />
<span class="link">AdonisJS</span>
<span>AdonisJS</span>
</a>
{{ $t('footer.credits_separator') }} <span>Arthur DANJOU</span>
</p>
<p>{{ $t('footer.copyrights', { date: getDate }) }}</p>
</div>
<p class="mt-4 lg:mt-0">{{ $t('footer.copyrights', { date: getDate }) }}</p>
</div>
</div>
</footer>
</template>
<script lang="ts">
import {computed, defineComponent, ref, useContext} from "@nuxtjs/composition-api";
import {computed, defineComponent, ref, useAsync, useContext, useRouter, useStore} from "@nuxtjs/composition-api";
import {State} from "~/types/types";
export default defineComponent({
name: "Footer",
setup() {
const {$colorMode} = useContext()
const {$colorMode, $axios, $sentry, app} = useContext()
const isDarkMode = computed(() => {
return $colorMode.preference === 'dark'
})
const getDate = ref(new Date().getFullYear())
const hiring_message = useAsync(async () => {
const request = await $axios.get('/api/informations', {
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`
}
})
if (request.status === 200) {
return request.data.informations.translation.code
} else {
app.error({statusCode: 500})
$sentry.captureEvent(request.data)
}
}, 'hiring_message')
const store = useStore<State>()
const route = computed(() => store.state.route)
const isWindow = (loc: string) => {
if (loc === '') return route.value === "/"
else return route.value.includes(loc)
}
return {
getDate,
isDarkMode
isDarkMode,
hiring_message,
isWindow
}
}
})
@@ -71,8 +155,38 @@ export default defineComponent({
<style scoped lang="scss">
.footer {
.link {
@apply border-b-2 border-gray-200 hover:border-black dark:border-gray-700 dark:hover:border-white duration-300;
.social {
span {
@apply border-b-2 border-gray-200 dark:border-gray-700 duration-300;
}
&:hover span {
@apply border-indigo-600
}
}
.link-active a {
@apply text-indigo-600;
}
.social-links a {
svg {
@apply h-6 w-6 duration-300
}
&:hover svg {
@apply transform hover:scale-120
}
}
.link a {
@apply duration-500 border-b-2 border-transparent;
&.link-active {
@apply text-indigo-600;
}
&:hover {
@apply border-indigo-600
}
}
}
</style>

View File

@@ -6,8 +6,8 @@
</h3>
<div v-if="formations" v-for="formation in formations">
<Formation
:title="formation.title"
:description="formation.description"
:title="formation.title.code"
:description="formation.description.code"
:location="formation.location"
:begin="formation.begin_date"
:end="formation.end_date" />
@@ -17,21 +17,27 @@
<script lang="ts">
import {defineComponent, useAsync, useContext} from "@nuxtjs/composition-api";
import {Formation} from "~/types/types";
export default defineComponent({
name: "FormationsHome",
setup() {
const {$content, $sentry} = useContext()
const {$axios, $sentry, app} = useContext()
const formations = useAsync(() => {
return $content('formations')
.sortBy('end_date', 'desc')
.fetch<Formation>()
.catch((error) => {
$sentry.captureEvent(error)
const formations = useAsync(async () => {
const response = await $axios.get('/api/formations', {
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`
}
})
if (response.status === 200) {
return response.data.formations.sort((a, b) => {
return a.end_date === 'Today' ? -1 : a.end_date.split('-')[1] > b.end_date.split('-')[1] ? -1 : a.end_date.split('-')[0] > b.end_date.split('-')[0] ? 0 : 1
})
})
} else {
app.error({statusCode: 500})
$sentry.captureEvent(response.data)
}
}, 'formations')
return {
formations

View File

@@ -1,83 +1,37 @@
<template>
<header class="dark:bg-black dark:text-white fixed z-50 top-0 left-0 bg-white w-full duration-400" :class="scrollPosition > 50 ? ' shadow-md dark:shadow-white h-16 lg:h-20' : 'h-20 lg:h-24'">
<header class="hidden xl:block dark:bg-black dark:text-white z-50 sticky top-0 left-0 bg-white w-full duration-400"
:class="scrollPosition > 65 ? 'shadow-md dark:shadow-white h-16 lg:h-20' : 'h-20 lg:h-24'">
<div class="header-container z-index-50 flex justify-between items-center h-full px-5 xl:px-32">
<nuxt-link to="/">
<img src="~/assets/images/logo-header.png" alt="Logo Circle" class="h-10 left cursor-pointer duration-500" />
</nuxt-link>
<nav class="right">
<div class="flex flex-col md:flex-row items-center">
<ul class="flex text-lg">
<nuxt-link class="hidden md:inline-block" to="/about">
<li class="nav-link">
{{ $t('header.about') }}
</li>
</nuxt-link>
<nuxt-link class="hidden md:inline-block" to="/blog">
<li class="nav-link">
{{ $t('header.blog') }}
</li>
</nuxt-link>
<nuxt-link class="hidden md:inline-block" to="/env">
<li class="nav-link">
{{ $t('header.env') }}
</li>
</nuxt-link>
<nuxt-link class="hidden md:inline-block" to="/projects">
<li class="nav-link">
{{ $t('header.projects') }}
</li>
</nuxt-link>
<nuxt-link class="hidden md:inline-block" to="/contact">
<li class="nav-link">
{{ $t('header.contact') }}
</li>
</nuxt-link>
</ul>
<Logo />
<nav class="right flex flex-col md:flex-row items-center hidden md:inline-block">
<div class="flex text-lg">
<nuxt-link class="nav-link" to="/about" :class="{ 'link-active': isWindow('about') }">
{{ $t('header.about') }}
</nuxt-link>
<nuxt-link class="nav-link" to="/blog" :class="{ 'link-active': isWindow('blog') }">
{{ $t('header.blog') }}
</nuxt-link>
<nuxt-link class="nav-link" to="/projects" :class="{ 'link-active': isWindow('projects') }">
{{ $t('header.projects') }}
</nuxt-link>
<nuxt-link class="nav-link" to="/contact" :class="{ 'link-active': isWindow('contact') }">
{{ $t('header.contact') }}
</nuxt-link>
</div>
<ul class="dark:text-white dark:bg-black text-sm z-50 bg-white md:hidden fixed bottom-0 left-0 w-full flex items-center justify-around h-20 border-t border-gray-200 border-solid navbar-bottom-items">
<nuxt-link to="/" class="w-1/6 nav-link-mobile">
<li class="h-full w-full font-medium flex flex-col items-center justify-center">
<HomeIcon :active="true" />
</li>
</nuxt-link>
<nuxt-link to="/about" class="w-1/6 nav-link-mobile">
<li class="font-medium flex flex-col items-center justify-center">
<UserIcon :active="false" />
</li>
</nuxt-link>
<nuxt-link to="/blog" class="w-1/6 nav-link-mobile blog">
<li class="font-medium flex flex-col items-center justify-center">
<BookIcon />
</li>
</nuxt-link>
<nuxt-link to="/env" class="w-1/6 nav-link-mobile">
<li class="font-medium flex flex-col items-center justify-center">
<ComputerIcon />
</li>
</nuxt-link>
<nuxt-link to="/projects" class="w-1/6 nav-link-mobile">
<li class="font-medium flex flex-col items-center justify-center">
<LightbulbIcon />
</li>
</nuxt-link>
<nuxt-link to="/contact" class="w-1/6 nav-link-mobile">
<li class="font-medium flex flex-col items-center justify-center">
<ContactIcon />
</li>
</nuxt-link>
</ul>
</nav>
<div>
<ul class="flex items-center">
<li @click="changeLanguage()" class="mx-1 h-9 w-9 cursor-pointer flex items-center justify-center p-1.5 rounded-xl hover:bg-gray-300 duration-200 dark:hover:bg-dark-400">
<TranslateIcon />
<li @click="changeLanguage()"
class="mx-1 h-9 w-9 cursor-pointer flex items-center justify-center p-1.5 rounded-xl hover:bg-gray-300 duration-200 dark:hover:bg-dark-400">
<TranslateIcon :french="isFrench"/>
</li>
<li @click="changeColorMode()" class="mx-1 h-9 w-9 cursor-pointer flex items-center p-1.5 rounded-xl hover:bg-gray-300 dark:hover:bg-dark-400 duration-200">
<li @click="changeColorMode()"
class="mx-1 h-9 w-9 cursor-pointer flex items-center p-1.5 rounded-xl hover:bg-gray-300 dark:hover:bg-dark-400 duration-200">
<div v-if="this.$colorMode.preference === 'light'">
<MoonIcon />
<MoonIcon/>
</div>
<div v-else>
<SunIcon />
<SunIcon/>
</div>
</li>
</ul>
@@ -87,7 +41,18 @@
</template>
<script lang="ts">
import {defineComponent, onMounted, onUnmounted, ref, useAsync, useContext, useRouter} from "@nuxtjs/composition-api";
import {
computed,
defineComponent,
onMounted,
onUnmounted,
ref,
useAsync,
useContext,
useRouter,
useStore
} from "@nuxtjs/composition-api";
import {State} from "~/types/types";
export default defineComponent({
name: "Header",
@@ -110,7 +75,7 @@ export default defineComponent({
window.removeEventListener('scroll', updateScroll)
})
const {i18n} = useContext()
const {i18n, } = useContext()
const $router = useRouter()
const changeLanguage = () => useAsync(() => {
i18n.setLocale(i18n.locale === 'fr' ? 'en' : 'fr')
@@ -118,12 +83,23 @@ export default defineComponent({
window.location.reload()
}
})
const isFrench = computed(() => i18n.locale === 'fr')
const store = useStore<State>()
const route = computed(() => store.state.route)
const isWindow = (loc: string) => {
if (loc === '') return route.value === "/"
else return route.value.includes(loc)
}
return {
scrollPosition,
changeColorMode,
updateScroll,
changeLanguage
changeLanguage,
isWindow,
isFrench
}
}
})
@@ -131,18 +107,14 @@ export default defineComponent({
<style scoped lang="scss">
.nav-link {
@apply text-gray-500 dark:text-gray-400 hover:dark:text-white font-medium hover:text-black mx-4 cursor-pointer duration-300
}
.nav-link-mobile {
@apply text-gray-500 dark:text-gray-400 hover:dark:text-white hover:text-black duration-300
}
.nuxt-link-exact-active {
@apply text-black dark:text-white;
@apply font-medium cursor-pointer duration-500 mx-4 border-b-2 border-transparent hover:(border-indigo-600);
}
.navbar-bottom-items li {
transition: all .2s ease-in-out;
}
.link-active {
@apply text-indigo-600
}
</style>

View File

@@ -2,7 +2,7 @@
<section class="w-full mb-10">
<h3 class="font-bold text-2xl md:text-4xl">
{{ $t('about.title.languages') }}
<TranslateIcon />
<LanguageIcon />
</h3>
<div>
<table class="text-base text-xl text-gray-700 dark:text-gray-400">
@@ -21,6 +21,6 @@
<script>
export default {
name: "LanguagesAbout"
name: "LanguagesAbout",
}
</script>

18
src/components/Logo.vue Normal file
View File

@@ -0,0 +1,18 @@
<template>
<nuxt-link class="profile ml-4 flex items-center" to="/">
<img class="h-12 w-12 duration-500" src="@/assets/images/photo-rounded.png" alt="Photo of me" />
<h1 class="ml-4 font-bold text-lg">Arthur Danjou</h1>
</nuxt-link>
</template>
<script>
export default {
name: "Logo"
}
</script>
<style lang="scss">
.profile:hover img {
@apply transform rotate-360;
}
</style>

View File

@@ -0,0 +1,80 @@
<template>
<div
class="xl:hidden fixed z-50 top-auto bottom-0 w-full md:w-2/3 md:left-1/2 p-4 transition-all duration-500 transform md:-translate-x-1/2"
:class="{'-translate-y-8 translate-x-10/12 sm:translate-x-1/2 xl:translate-x-0': opened}"
>
<nav class="flex justify-evenly py-4 bg-gray-200 dark:bg-gray-700 rounded-3xl dark:text-white text-sm overflow-hidden">
<nuxt-link to="/" class="relative font-medium">
<HomeIcon :active="isWindow('')"/>
</nuxt-link>
<nuxt-link to="/about" class="relative font-medium">
<UserIcon :active="isWindow('/about')"/>
</nuxt-link>
<nuxt-link to="/blog" class="relative font-medium">
<BookIcon :active="isWindow('/blog')"/>
</nuxt-link>
<nuxt-link to="/projects" class="relative font-medium">
<LightbulbIcon :active="isWindow('/projects')"/>
</nuxt-link>
<button @click='toggleMenu' class="font-medium cursor-pointer">
<CrossIcon v-if="opened" />
<MenuIcon v-else :type="getMenuIconType"/>
</button>
</nav>
</div>
</template>
<script lang="ts">
import {computed, defineComponent, ref, useRouter, useStore, watch} from "@nuxtjs/composition-api";
import {State} from "~/types/types";
const PAGE_TYPE = {
projects: 1,
services: 2,
env: 3,
about: 4,
newsletter: 5
}
export default defineComponent({
name: "MobileNavbar",
setup () {
const store = useStore<State>()
const route = computed(() => store.state.route)
const isWindow = (loc: string) => {
if (loc === '') return route.value === "/"
else return route.value.includes(loc)
}
const getMenuIconType = computed(() => PAGE_TYPE[route.value.split('/')[1]] || 0)
const toggleMenu = () => {
store.commit('TOGGLE_OPENED', !store.state.opened)
if (store.state.opened) {
document.getElementById('slider')!.style.maxHeight = window.screen.height + 'px'
setTimeout(() => document.getElementById('nav')!.classList.add('z-50'), 300)
} else {
document.getElementById('nav')!.classList.remove('z-50')
setTimeout(() => {
document.getElementById('slider')!.style.maxHeight = 'none'
}, 500)
}
}
const $router = useRouter()
$router.afterEach(() => {
store.commit('TOGGLE_OPENED', false)
setTimeout(() => {
document.getElementById('slider')!.style.maxHeight = 'none'
}, 600)
})
return {
isWindow,
toggleMenu,
opened: computed(() => store.state.opened),
getMenuIconType
}
}
})
</script>

View File

@@ -1,5 +1,5 @@
<template>
<h1 class="mt-16 md:mt-32 font-bold text-3xl md:text-5xl mr-2 inline mb-4 border-b-3 border-solid border-indigo-600">
<h1 class="mt-16 font-bold text-3xl md:text-5xl mr-2 inline mb-4 border-b-3 border-solid border-indigo-600">
{{ this.$t(title) }}
</h1>
</template>

View File

@@ -1,8 +1,8 @@
<template>
<nuxt-link :to="`/blog/${slug}`" rel="noreferrer noopener">
<div class="rounded-lg shadow-xl h-116 w-full lg:w-100 text-left bg-gray-100 dark:bg-gray-800 transform hover:scale-103 duration-300 mb-8 lg:mb-0">
<nuxt-link :to="`/blog/${slug}`">
<div class="rounded-lg dark:shadow-white shadow-xl h-116 w-full lg:w-100 text-left bg-gray-100 dark:bg-gray-800 transform hover:scale-103 duration-300 mb-8 lg:mb-0">
<div class="h-2/5 post rounded-t-lg"
:style="{ backgroundImage: `url(${getCover})` }">
:style="{ backgroundImage: `url(https://athena.arthurdanjou.fr/files/${cover})` }">
</div>
<div class="h-3/5 p-4 flex flex-col justify-between">
<div>
@@ -11,8 +11,8 @@
<Tag :content="tag" :pill="true"/>
</div>
</div>
<h1 class="text-2xl font-bold">{{ title }}</h1>
<p class="text-base mt-3 text-gray-700 dark:text-gray-400 text-justify">{{ description }}</p>
<h1 class="text-2xl font-bold">{{ $t(title) }}</h1>
<p class="text-base mt-3 text-gray-700 dark:text-gray-400 text-justify">{{ $t(description) }}</p>
</div>
<div class="flex justify-between">
<h5 class="text-base text-gray-700 dark:text-gray-400">{{ formatDate }}</h5>
@@ -69,8 +69,6 @@ export default defineComponent({
}
},
setup(props: PostProps) {
const getCover = computed(() => require(`~/assets/images/posts/${props.cover}`))
const { i18n } = useContext()
const formatDate = computed(() => {
const [first, second, third]: any = props.date.split('-')
@@ -78,7 +76,6 @@ export default defineComponent({
})
return {
getCover,
formatDate
}
}

View File

@@ -12,9 +12,9 @@
<div class="my-8 lg:flex w-full lg:space-x-6">
<div v-for="post in posts">
<Post
:title="post.title"
:cover="post.cover"
:description="post.description"
:title="post.title.code"
:cover="post.cover.file_name"
:description="post.description.code"
:date="post.date"
:slug="post.slug"
:tags="post.tags"
@@ -36,17 +36,21 @@ import {Post} from "~/types/types";
export default defineComponent({
name: "PostsHome",
setup() {
const { $content, i18n, $sentry } = useContext()
const { $axios, app, $sentry } = useContext()
const posts = useAsync(() => {
return $content(`articles/${i18n.locale}`)
.sortBy('date', 'asc')
.limit(3)
.fetch<Post>()
.catch((error) => {
$sentry.captureEvent(error)
})
}, 'posts')
const posts = useAsync(async () => {
const response = await $axios.get('/api/posts', {
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`
}
})
if (response.status === 200) {
return response.data.posts
} else {
app.error({statusCode: 500})
$sentry.captureEvent(response.data)
}
}, 'posts_home')
return {
posts

View File

@@ -1,25 +1,20 @@
<template>
<section class="flex flex-col 2xl:flex-row justify-center items-center py-8">
<div class="lg:mr-12">
<img class="logo-img rounded-full my-5" src="~/assets/images/memojies/Hey.png" alt="It's me !" />
<section class="flex flex-col justify-center items-center py-8">
<div>
<img class="rounded-full my-5" src="~/assets/images/memojies/Hey.png" alt="A picture of myself" />
</div>
<div class="ml-2 text-lg leading-6 xl:w-2/3 text-justify dark:text-gray-400 text-gray-700">
<p>{{ $t('about.banner.hello') }} <span class="text-indigo-600 font-bold">Arthur DANJOU</span> 👋.</p> <br/>
<div class="text-lg leading-6 text-justify dark:text-gray-400 text-gray-700">
<div>{{ $t('about.banner.hello') }} <span class="text-indigo-600 font-bold">Arthur DANJOU</span> 👋.</div> <br/>
<p>{{ $t('about.banner.1')}}</p> <br/>
<p>{{ $t('about.banner.2') }}</p> <br/>
<p>{{ $t('about.banner.3') }}</p>
<p>{{ $t('about.banner.3') }}</p> <br />
<p>{{ $t('about.banner.4') }}</p>
</div>
</section>
</template>
<script>
export default {
name: "SkillsAbout"
name: "PresentationAbout"
}
</script>
<style scoped lang="scss">
.logo-img {
height: 25rem;
}
</style>

View File

@@ -1,14 +1,14 @@
<template>
<a :href="url" target="_blank" rel="noopener noreferrer">
<div class="rounded-lg shadow-xl h-92 w-full lg:w-84 text-left bg-gray-100 dark:bg-gray-800 transform hover:scale-103 duration-300 mb-8 lg:mb-0">
<div class="h-1/2 w-full h-2/5 project rounded-t-lg"
:style="{ backgroundImage: `url(${getCover})` }">
<a :href="url" target="_blank">
<div class="rounded-lg dark:shadow-white shadow-xl lg:h-92 w-full lg:w-84 text-left bg-gray-100 dark:bg-gray-800 transform hover:scale-103 duration-300 mb-8 lg:mb-0">
<div class="h-64 lg:h-1/2 w-full project rounded-t-lg"
:style="{ backgroundImage: `url(https://athena.arthurdanjou.fr/files/${cover})` }">
</div>
<div class="h-1/2 p-4 flex flex-col justify-between">
<div class="lg:h-1/2 py-8 px-4 lg:p-4 flex flex-col justify-between">
<div>
<div class="flex space-x-2 mb-2">
<div v-for="tag in tags">
<Tag :content="tag" :pill="false"/>
<Tag :content="tag.label.code" :pill="false"/>
</div>
</div>
<h1 class="text-2xl font-bold">{{ title }}</h1>
@@ -20,15 +20,7 @@
</template>
<script lang="ts">
import {computed, defineComponent} from "@nuxtjs/composition-api";
interface ProjectProp {
title: string,
cover: string,
tags: Array<String>,
description: string,
url: string,
}
import {defineComponent} from "@nuxtjs/composition-api";
export default defineComponent({
name: "Project",
@@ -39,7 +31,7 @@ export default defineComponent({
},
cover: {
type: String,
default: "artapi.png"
default: "athena.png"
},
description: {
type: String,
@@ -53,13 +45,6 @@ export default defineComponent({
type: String,
default: 'https://arthurdanjou.fr'
}
},
setup(props: ProjectProp) {
const getCover = computed(() => require(`@/assets/images/projects/${props.cover}`))
return {
getCover
}
}
})
</script>

View File

@@ -9,12 +9,12 @@
{{ $t('projects.description') }}
</p>
</div>
<div class="my-8 lg:flex w-full lg:space-x-8 flex flex-wrap justify-center">
<div v-for="project in projects">
<div class="my-8 w-full lg:space-x-8 lg:flex justify-center">
<div v-for="project in projects" class="mb-4">
<Project
:title="project.title"
:cover="project.cover"
:description="project.description"
:title="project.name"
:cover="project.cover.file_name"
:description="project.description.code"
:tags="project.tags"
:url="project.url"
/>
@@ -29,21 +29,25 @@
<script lang="ts">
import {defineComponent, useAsync, useContext} from "@nuxtjs/composition-api";
import {Project} from "~/types/types";
export default defineComponent({
name: "ProjectsHome",
setup() {
const { $content, $sentry } = useContext()
const { $axios, app, $sentry } = useContext()
const projects = useAsync(() => {
return $content(`projects`)
.limit(3)
.fetch<Project>()
.catch((error) => {
$sentry.captureEvent(error)
})
}, 'projects')
const projects = useAsync(async () => {
const response = await $axios.get('/api/projects', {
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`
}
})
if (response.status === 200) {
return response.data.projects.slice(0, 3)
} else {
$sentry.captureEvent(response.data)
app.error({statusCode: 500})
}
}, 'projects_home')
return {
projects

View File

@@ -0,0 +1,31 @@
<template>
<div class="relative lg:(w-1/2 m-8) mt-8">
<div class="absolute right-0 top-0 bg-indigo-600 text-white rounded-xl p-3">
<slot />
</div>
<div class="rounded-lg mt-8 md:mr-8 pt-4 md:p-8">
<h1 class="font-bold capitalize text-4xl mb-4">
{{ $t(title) }}
</h1>
<p class="text-gray-600 text-lg text-justify leading-5 ">
{{ $t(content) }}
</p>
</div>
</div>
</template>
<script>
export default {
name: "ServicePart",
props: {
title: {
type: String,
default: 'services.1.title'
},
content: {
type: String,
default: 'services.1.content'
}
}
}
</script>

188
src/components/SideMenu.vue Normal file
View File

@@ -0,0 +1,188 @@
<template>
<div class="relative w-full min-w-screen xl:overflow-auto">
<div
class="min-h-screen bg-gray-100 dark:bg-gray-900 xl:hidden pl-4 pr-20 py-4 transition-all duration-500 duration-500 absolute top-0 left-0 right-0 flex items-center"
>
<nav
id="nav"
class="w-auto"
>
<div class="mb-8">
<div class="flex justify-between mb-4">
<div @click="closeMenu" class="flex justify-center items-center cursor-pointer cross text-sm">
<CrossIcon class="duration-300" />
<div class="ml-4">{{ $t('sidebar.close') }}</div>
</div>
<div class="ml-6">
<ul class="flex items-center">
<li @click="changeLanguage()"
class="mx-1 h-9 w-9 cursor-pointer flex items-center justify-center p-1.5 rounded-xl hover:bg-gray-300 duration-200 dark:hover:bg-dark-400">
<TranslateIcon :french="isFrench" />
</li>
<li @click="changeColorMode()"
class="mx-1 h-9 w-9 cursor-pointer flex items-center p-1.5 rounded-xl hover:bg-gray-300 dark:hover:bg-dark-400 duration-200">
<div v-if="this.$colorMode.preference === 'light'">
<MoonIcon/>
</div>
<div v-else>
<SunIcon/>
</div>
</li>
</ul>
</div>
</div>
<Logo />
</div>
<div class="w-auto flex">
<div class="flex flex-col ml-4 mb-8 space-y-1.5 font-bold text-lg">
<div class="nav-link" :class="{ 'link-active': isWindow('') }">
<nuxt-link to="/">
{{ $t('header.home') }}
</nuxt-link>
</div>
<div class="nav-link" :class="{ 'link-active': isWindow('about') }">
<nuxt-link to="/about">
{{ $t('header.about') }}
</nuxt-link>
</div>
<div class="nav-link" :class="{ 'link-active': isWindow('blog') }">
<nuxt-link to="/blog">
{{ $t('header.blog') }}
</nuxt-link>
</div>
<div class="nav-link" :class="{ 'link-active': isWindow('projects') }">
<nuxt-link to="/projects">
{{ $t('header.projects') }}
</nuxt-link>
</div>
<div class="nav-link" :class="{ 'link-active': isWindow('services') }">
<nuxt-link to="/services">
{{ $t('header.services') }}
</nuxt-link>
</div>
<div class="nav-link" :class="{ 'link-active': isWindow('env') }">
<nuxt-link to="/env">
{{ $t('header.env') }}
</nuxt-link>
</div>
<div class="nav-link" :class="{ 'link-active': isWindow('newsletter') }">
<nuxt-link to="/newsletter">
{{ $t('header.newsletter') }}
</nuxt-link>
</div>
<div class="nav-link" :class="{ 'link-active': isWindow('contact') }">
<nuxt-link to="/contact">
{{ $t('header.contact') }}
</nuxt-link>
</div>
</div>
</div>
<div class="social-links flex justify-between space-x-0.5">
<a target="_blank" href="https://twitter.com/ArthurDanj" rel="noopener noreferrer">
<TwitterIcon />
</a>
<a target="_blank" href="https://github.com/ArthurDanjou" rel="noopener noreferrer">
<GithubIcon />
</a>
<a target="_blank" href="https://www.polywork.com/arthurdanjou" rel="noopener noreferrer">
<PolyworkIcon />
</a>
<a target="_blank" href="https://www.twitch.tv/arthurdanjou" rel="noopener noreferrer">
<TwitchIcon />
</a>
<a target="_blank" href="https://discord.gg/ENG6cFQhPS" rel="noopener noreferrer">
<DiscordIcon />
</a>
<a target="_blank" href="mailto:contact@arthurdanjou.fr" rel="noopener noreferrer">
<MailIcon />
</a>
</div>
</nav>
</div>
</div>
</template>
<script lang="ts">
import {
computed,
defineComponent,
useAsync,
useContext,
useRouter,
useStore
} from "@nuxtjs/composition-api";
import {State} from "~/types/types";
export default defineComponent({
name: "SideMenu",
setup() {
const {$colorMode} = useContext()
const changeColorMode = () => {
$colorMode.preference = $colorMode.value === 'light' ? 'dark' : 'light'
}
const {i18n} = useContext()
const $router = useRouter()
const changeLanguage = () => useAsync(() => {
i18n.setLocale(i18n.locale === 'fr' ? 'en' : 'fr')
if ($router.currentRoute.fullPath.includes('blog') || $router.currentRoute.fullPath === '/') {
window.location.reload()
}
})
const isFrench = computed(() => i18n.locale === 'fr')
const store = useStore<State>()
const closeMenu = () => {
store.commit('TOGGLE_OPENED', false)
document.getElementById('nav')!.classList.remove('z-50')
setTimeout(() => {
document.getElementById('slider')!.style.maxHeight = 'none'
}, 500)
}
const route = computed(() => store.state.route)
const isWindow = (loc: string) => {
if (loc === '') return route.value === "/"
else return route.value.includes(loc)
}
return {
changeColorMode,
changeLanguage,
closeMenu,
opened: computed(() => store.state.opened),
isWindow,
isFrench
}
}
})
</script>
<style scoped lang="scss">
.cross:hover svg {
@apply transform scale-140;
}
.nav-link a {
@apply duration-300 border-b-2 border-transparent;
&:hover {
@apply border-indigo-600;
}
}
.link-active a {
@apply text-indigo-600;
}
.social-links a {
svg {
@apply h-6 w-6 duration-300
}
&:hover svg {
@apply transform hover:scale-120
}
}
</style>

View File

@@ -2,9 +2,9 @@
<div class="mb-3 mr-2 p-1 md:p-2 h-32 w-32 border-gray-900 dark:border-dark-200 border-2 duration-300 rounded-3xl hover:bg-opacity-25" :class="getColor">
<div class="w-full h-full flex flex-col justify-center items-center">
<div>
<img class="rounded-sm" alt="Skill Img" :src="getCoverLink" />
<img class="rounded-sm" :alt="`Skill ${name} Image`" :src="`https://athena.arthurdanjou.fr/files/${cover}`" />
</div>
<h1 class="md:text-lg text-md font-bold text-center text-gray-700 dark:text-gray-400">{{ skill }}</h1>
<h1 class="md:text-lg text-md font-bold text-center text-gray-700 dark:text-gray-400">{{ name }}</h1>
</div>
</div>
</template>
@@ -13,7 +13,7 @@
import {computed, defineComponent} from '@nuxtjs/composition-api'
interface SkillProps {
skill: string,
name: string,
color: string,
cover: string
}
@@ -21,7 +21,7 @@ interface SkillProps {
export default defineComponent({
name: "Skill",
props: {
skill: {
name: {
type: String,
default: "Rien"
},
@@ -65,11 +65,9 @@ export default defineComponent({
return 'hover:bg-amber-400'
}
})
const getCoverLink = computed(() => require(`@/assets/images/skills/${props.cover}`))
return {
getColor,
getCoverLink
getColor
}
}
})

View File

@@ -7,9 +7,9 @@
<div class="flex flex-row w-full overflow-x-auto md:overflow-x-hidden lg:flex-wrap space-x-4 lg:space-x-0 lg:justify-center">
<div v-if="skills" v-for="skill in skills">
<Skill
:skill="skill.title"
:name="skill.name"
:color="skill.color"
:cover="skill.cover"
:cover="skill.file.file_name"
/>
</div>
</div>
@@ -18,20 +18,25 @@
<script lang="ts">
import {defineComponent, useAsync, useContext} from "@nuxtjs/composition-api";
import {Skill} from "~/types/types";
export default defineComponent({
name: "SkillsAbout",
setup() {
const {$content, $sentry} = useContext()
const {$axios, $sentry, app} = useContext()
const skills = useAsync(() => {
return $content('skills')
.fetch<Skill>()
.catch((error) => {
$sentry.captureEvent(error)
})
})
const skills = useAsync(async () => {
const response = await $axios.get('/api/skills', {
headers: {
'Authorization': `Bearer ${process.env.API_TOKEN}`
}
})
if (response.status === 200) {
return response.data.skills
} else {
app.error({statusCode: 500})
$sentry.captureEvent(response.data)
}
}, 'skills')
return {
skills

View File

@@ -1,5 +1,11 @@
<template>
<svg class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<svg v-if="active" class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<path
d="M21 4H7a2 2 0 1 0 0 4h14v13a1 1 0 0 1-1 1H7a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4h13a1 1 0 0 1 1 1v1zm-1 3H7a1 1 0 1 1 0-2h13v2z"
fill="currentColor"
/>
</svg>
<svg v-else class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<path
d="M21 4H7a2 2 0 1 0 0 4h14v13a1 1 0 0 1-1 1H7a4 4 0 0 1-4-4V6a4 4 0 0 1 4-4h13a1 1 0 0 1 1 1v1zM5 18a2 2 0 0 0 2 2h12V10H7a3.982 3.982 0 0 1-2-.535V18zM20 7H7a1 1 0 1 1 0-2h13v2z"
fill="currentColor"

View File

@@ -0,0 +1,17 @@
<template>
<svg class="inline" width="2rem" height="2rem" viewBox="0 0 24 24" focusable="false">
<path
d="M20 3H4c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h16c1.103 0 2-.897 2-2V5c0-1.103-.897-2-2-2zM4 19V7h16l.002 12H4z"
fill="currentColor"
/>
<path
d="M9.293 9.293L5.586 13l3.707 3.707l1.414-1.414L8.414 13l2.293-2.293zm5.414 0l-1.414 1.414L15.586 13l-2.293 2.293l1.414 1.414L18.414 13z"
fill="currentColor" />
</svg>
</template>
<script>
export default {
name: "CodeIcon"
}
</script>

View File

@@ -1,20 +0,0 @@
<template>
<svg class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<path
d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"
fill="currentColor"
/>
</svg>
</template>
<script lang="ts">
export default {
name: "ComputerIcon",
props: {
active: {
type: Boolean,
default: false
}
}
}
</script>

View File

@@ -1,8 +1,16 @@
<template>
<svg class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<svg v-if="active" class="inline" width="2.5em" height="2.5em" viewBox="0 0 20 20" focusable="false">
<path
d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-1 14H5c-.55 0-1-.45-1-1V8l6.94 4.34c.65.41 1.47.41 2.12 0L20 8v9c0 .55-.45 1-1 1zm-7-7L4 6h16l-8 5z"
fill="currentColor"
fill-rule="evenodd"
d="M7.172 11.334l2.83 1.935l2.728-1.882l6.115 6.033c-.161.052-.333.08-.512.08H1.667c-.22 0-.43-.043-.623-.12l6.128-6.046zM20 6.376v9.457c0 .247-.054.481-.15.692l-5.994-5.914L20 6.376zM0 6.429l6.042 4.132l-5.936 5.858A1.663 1.663 0 0 1 0 15.833V6.43zM18.333 2.5c.92 0 1.667.746 1.667 1.667v.586L9.998 11.648L0 4.81v-.643C0 3.247.746 2.5 1.667 2.5h16.666z"
/>
</svg>
<svg v-else class="inline" width="2.5em" height="2.5em" viewBox="0 0 20 20" focusable="false">
<path
fill="currentColor"
fill-rule="evenodd"
d="M18.333 2.5c.92 0 1.667.746 1.667 1.667v11.666c0 .92-.746 1.667-1.667 1.667H1.667C.747 17.5 0 16.754 0 15.833V4.167C0 3.247.746 2.5 1.667 2.5h16.666zM7.168 11.328l-4.91 4.852h15.325l-4.857-4.802L10 13.265l-2.832-1.937zM18.64 7.292l-4.796 3.316l4.796 4.736V7.292zm-17.279.061v7.836l4.686-4.631l-4.686-3.205zm16.956-3.532H1.698a.358.358 0 0 0-.25.086a.26.26 0 0 0-.085.222v1.62L10 11.656l8.644-5.965V4.199c.001-.134-.03-.231-.092-.292a.306.306 0 0 0-.234-.086z"
/>
</svg>
</template>

View File

@@ -0,0 +1,18 @@
<template>
<svg class="inline" width="1.5em" height="1.5em" viewBox="0 0 15 15" focusable="false">
<g fill="none">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M11.782 4.032a.575.575 0 1 0-.813-.814L7.5 6.687L4.032 3.218a.575.575 0 0 0-.814.814L6.687 7.5l-3.469 3.468a.575.575 0 0 0 .814.814L7.5 8.313l3.469 3.469a.575.575 0 0 0 .813-.814L8.313 7.5l3.469-3.468z"
fill="currentColor"
/>
</g>
</svg>
</template>
<script>
export default {
name: "CrossIcon"
}
</script>

View File

@@ -5,7 +5,8 @@
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round">
stroke-linejoin="round"
>
<path d="M6 17.6l-2-1.1V14"/>
<path d="M4 10V7.5l2-1.1"/>
<path d="M10 4.1L12 3l2 1.1"/>

View File

@@ -0,0 +1,13 @@
<template>
<svg class="inline" width="1.5em" height="1.5em" viewBox="0 0 24 24" focusable="false">
<path
d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515a.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0a12.64 12.64 0 0 0-.617-1.25a.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057a19.9 19.9 0 0 0 5.993 3.03a.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106a13.107 13.107 0 0 1-1.872-.892a.077.077 0 0 1-.008-.128a10.2 10.2 0 0 0 .372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127a12.299 12.299 0 0 1-1.873.892a.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028a19.839 19.839 0 0 0 6.002-3.03a.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.956-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.955-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.946 2.418-2.157 2.418z"
fill="currentColor" />
</svg>
</template>
<script>
export default {
name: "DiscordIcon"
}
</script>

View File

@@ -13,8 +13,8 @@
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round">
</path>
stroke-linejoin="round"
/>
</g>
</svg>
</template>

View File

@@ -0,0 +1,13 @@
<template>
<svg class="inline" width="2rem" height="2rem" viewBox="0 0 512 512" focusable="false">
<path
fill="currentColor"
d="M479.6 399.716l-81.084-81.084l-62.368-25.767A175.014 175.014 0 0 0 368 192c0-97.047-78.953-176-176-176S16 94.953 16 192s78.953 176 176 176a175.034 175.034 0 0 0 101.619-32.377l25.7 62.2l81.081 81.088a56 56 0 1 0 79.2-79.195zM48 192c0-79.4 64.6-144 144-144s144 64.6 144 144s-64.6 144-144 144S48 271.4 48 192zm408.971 264.284a24.028 24.028 0 0 1-33.942 0l-76.572-76.572l-23.894-57.835l57.837 23.894l76.573 76.572a24.028 24.028 0 0 1-.002 33.941z" />
</svg>
</template>
<script>
export default {
name: "GlassIcon"
}
</script>

View File

@@ -0,0 +1,14 @@
<template>
<svg class="inline" width="1.5em" height="1.5em" viewBox="0 0 24 24" focusable="false">
<path
d="M21.35 11.1h-9.17v2.73h6.51c-.33 3.81-3.5 5.44-6.5 5.44C8.36 19.27 5 16.25 5 12c0-4.1 3.2-7.27 7.2-7.27c3.09 0 4.9 1.97 4.9 1.97L19 4.72S16.56 2 12.1 2C6.42 2 2.03 6.8 2.03 12c0 5.05 4.13 10 10.22 10c5.35 0 9.25-3.67 9.25-9.09c0-1.15-.15-1.81-.15-1.81z"
fill="currentColor"
/>
</svg>
</template>
<script>
export default {
name: "GoogleIcon"
}
</script>

View File

@@ -1,8 +1,14 @@
<template>
<svg class="inline" width="1em" height="1em" viewBox="0 0 24 24" focusable="false">
<svg v-if="liked" class="icon inline" width="1em" height="1em" viewBox="0 0 256 256" focusable="false">
<path
d="M12.1 18.55l-.1.1l-.11-.1C7.14 14.24 4 11.39 4 8.5C4 6.5 5.5 5 7.5 5c1.54 0 3.04 1 3.57 2.36h1.86C13.46 6 14.96 5 16.5 5c2 0 3.5 1.5 3.5 3.5c0 2.89-3.14 5.74-7.9 10.05M16.5 3c-1.74 0-3.41.81-4.5 2.08C10.91 3.81 9.24 3 7.5 3C4.42 3 2 5.41 2 8.5c0 3.77 3.4 6.86 8.55 11.53L12 21.35l1.45-1.32C18.6 15.36 22 12.27 22 8.5C22 5.41 19.58 3 16.5 3z"
:class="liked ? 'fill-heart': 'fill-current'"
d="M220.346 136.508l-81.032 81.031a16.013 16.013 0 0 1-22.625 0L33.58 134.43a59.974 59.974 0 0 1 2.344-87.07c23.281-21.015 61.25-19.054 84.578 4.297l7.5 7.492l9.578-9.578a60.698 60.698 0 0 1 43.984-17.554a59.55 59.55 0 0 1 43.063 19.89c20.984 23.297 19.062 61.25-4.281 84.602z"
class="fill-heart"
/>
</svg>
<svg v-else class="icon inline" width="1em" height="1em" viewBox="0 0 256 256" focusable="false">
<path
d="M128 220.218a13.957 13.957 0 0 1-9.9-4.093l-83.112-83.113a58 58 0 0 1 2.257-84.166A56.049 56.049 0 0 1 78.826 34.79a62.72 62.72 0 0 1 40.266 18.28L128 61.975l10.988-10.988a58.003 58.003 0 0 1 84.166 2.257a56.05 56.05 0 0 1 14.058 41.581a62.725 62.725 0 0 1-18.28 40.267L137.9 216.125a13.96 13.96 0 0 1-9.899 4.093zm5.657-8.336zM74.985 46.734a44.094 44.094 0 0 0-29.71 11.03a46.003 46.003 0 0 0-1.802 66.763l83.112 83.113a2.005 2.005 0 0 0 2.83 0l81.032-81.033c18.168-18.168 19.868-47.476 3.79-65.332a46.003 46.003 0 0 0-66.764-1.802l-15.23 15.23a5.999 5.999 0 0 1-8.485 0l-13.15-13.15a50.6 50.6 0 0 0-35.623-14.82z"
fill="currentColor"
/>
</svg>
</template>
@@ -18,3 +24,9 @@ export default {
}
}
</script>
<style lang="scss">
.icon {
transform: translate(0);
}
</style>

View File

@@ -1,9 +1,14 @@
<template>
<svg class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<svg v-if="active" class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<path
d="M15 22.065v-5a3 3 0 0 0-6 0v5H4a2 2 0 0 1-2-2V9.197a2 2 0 0 1 .971-1.715l8-4.8a2 2 0 0 1 2.058 0l8 4.8A2 2 0 0 1 22 9.197v10.868a2 2 0 0 1-2 2h-5z"
fill="currentColor"
/>
</svg>
<svg v-else class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<path
d="M20 20V9.132l-8-4.8l-8 4.8V20h4v-2.75a4 4 0 1 1 8 0V20h4zm-6 2v-4.75a2 2 0 1 0-4 0V22H4a2 2 0 0 1-2-2V9.132a2 2 0 0 1 .971-1.715l8-4.8a2 2 0 0 1 2.058 0l8 4.8A2 2 0 0 1 22 9.132V20a2 2 0 0 1-2 2h-6z"
stroke="currentColor"
:class="{active: 'fill-black dark:fill-white'}"
fill="currentColor"
/>
</svg>
</template>

View File

@@ -0,0 +1,14 @@
<template>
<svg class="inline" width="1em" height="1em" viewBox="0 0 24 24" focusable="false">
<path
d="M12.87 15.07l-2.54-2.51l.03-.03A17.52 17.52 0 0 0 14.07 6H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35C8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5l3.11 3.11l.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"
fill="currentColor"
/>
</svg>
</template>
<script>
export default {
name: "LanguageIcon"
}
</script>

View File

@@ -1,9 +1,15 @@
<template>
<svg class="inline" width="1.5em" height="2.5em" viewBox="0 0 352 512" focusable="false">
<svg v-if="active" class="inline" width="2.5em" height="2.5em" viewBox="0 0 256 256" focusable="false">
<path
d="M176 80c-52.94 0-96 43.06-96 96c0 8.84 7.16 16 16 16s16-7.16 16-16c0-35.3 28.72-64 64-64c8.84 0 16-7.16 16-16s-7.16-16-16-16zM96.06 459.17c0 3.15.93 6.22 2.68 8.84l24.51 36.84c2.97 4.46 7.97 7.14 13.32 7.14h78.85c5.36 0 10.36-2.68 13.32-7.14l24.51-36.84c1.74-2.62 2.67-5.7 2.68-8.84l.05-43.18H96.02l.04 43.18zM176 0C73.72 0 0 82.97 0 176c0 44.37 16.45 84.85 43.56 115.78c16.64 18.99 42.74 58.8 52.42 92.16v.06h48v-.12c-.01-4.77-.72-9.51-2.15-14.07c-5.59-17.81-22.82-64.77-62.17-109.67c-20.54-23.43-31.52-53.15-31.61-84.14c-.2-73.64 59.67-128 127.95-128c70.58 0 128 57.42 128 128c0 30.97-11.24 60.85-31.65 84.14c-39.11 44.61-56.42 91.47-62.1 109.46a47.507 47.507 0 0 0-2.22 14.3v.1h48v-.05c9.68-33.37 35.78-73.18 52.42-92.16C335.55 260.85 352 220.37 352 176C352 78.8 273.2 0 176 0z"
d="M176 232a8 8 0 0 1-8 8H88a8 8 0 0 1 0-16h80a8 8 0 0 1 8 8zm40-128a87.544 87.544 0 0 1-33.642 69.208A16.235 16.235 0 0 0 176 185.977V192a16.018 16.018 0 0 1-16 16H96a16.018 16.018 0 0 1-16-16v-6.031a16.02 16.02 0 0 0-6.23-12.66a87.575 87.575 0 0 1-33.769-68.814c-.263-47.662 38.263-87.35 85.881-88.47A88.002 88.002 0 0 1 216 104zm-50.343 2.343a8.002 8.002 0 0 0-11.314 0L128 132.687l-26.343-26.344a8 8 0 0 0-11.314 11.314L120 147.314V184a8 8 0 0 0 16 0v-36.686l29.657-29.657a8 8 0 0 0 0-11.314z"
fill="currentColor"
/>
/>
</svg>
<svg v-else class="inline" width="2.5em" height="2.5em" viewBox="0 0 256 256" focusable="false">
<path
d="M176 232a8 8 0 0 1-8 8H88a8 8 0 0 1 0-16h80a8 8 0 0 1 8 8zm40-128a87.544 87.544 0 0 1-33.642 69.208A16.235 16.235 0 0 0 176 185.977V192a16.018 16.018 0 0 1-16 16H96a16.018 16.018 0 0 1-16-16v-6.031a16.02 16.02 0 0 0-6.23-12.66a87.575 87.575 0 0 1-33.769-68.814c-.263-47.662 38.263-87.35 85.881-88.47A88.002 88.002 0 0 1 216 104zm-16 0a72 72 0 0 0-73.741-71.98C87.303 32.939 55.786 65.41 56 104.408a71.657 71.657 0 0 0 27.637 56.307A31.922 31.922 0 0 1 96 185.968V192h24v-44.686l-29.657-29.657a8 8 0 0 1 11.314-11.314L128 132.687l26.343-26.344a8 8 0 1 1 11.314 11.314L136 147.314V192h24v-6.024a32.135 32.135 0 0 1 12.467-25.344A71.638 71.638 0 0 0 200 104z"
fill="currentColor"
/>
</svg>
</template>

View File

@@ -0,0 +1,63 @@
<template>
<div>
<svg v-if="type === 0" class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 12h18"/>
<path d="M3 6h18"/>
<path d="M3 18h18"/>
</g>
</svg>
<svg v-else-if="type === 1" class="inline" width="2.5em" height="2.5em" viewBox="0 0 48 48" focusable="false">
<g fill="none" stroke="currentColor" stroke-width="4" stroke-linecap="round" stroke-linejoin="round">
<path
clip-rule="evenodd"
d="M44 22c0-9.941-8.954-18-20-18S4 12.059 4 22h40z" />
<path d="M4 38h40v6H4z" />
<path d="M4 28l5.455 4l7.272-4L24 32l7.273-4l7.272 4L44 28" />
</g>
</svg>
<svg v-else-if="type === 2" class="inline" width="0.75em" height="2.5em" viewBox="0 0 3 16" focusable="false">
<path
fill-rule="evenodd"
d="M0 2.5a1.5 1.5 0 1 0 3 0a1.5 1.5 0 0 0-3 0zm0 5a1.5 1.5 0 1 0 3 0a1.5 1.5 0 0 0-3 0zM1.5 14a1.5 1.5 0 1 1 0-3a1.5 1.5 0 0 1 0 3z"
fill="currentColor" />
</svg>
<svg v-else-if="type === 3" class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<g fill="none">
<path
d="M7 6a3 3 0 0 0-3 3h16a3 3 0 0 0-3-3H7z"
fill="currentColor" />
<path
d="M7 18a3 3 0 0 1-3-3h16a3 3 0 0 1-3 3H7z"
fill="currentColor" />
<path
d="M3 11a1 1 0 1 0 0 2h18a1 1 0 1 0 0-2H3z"
fill="currentColor" />
</g>
</svg>
<svg v-else-if="type === 4" class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M7.05 11.293l4.243-4.243a2 2 0 0 1 2.828 0l2.829 2.83a2 2 0 0 1 0 2.828l-4.243 4.243a2 2 0 0 1-2.828 0L7.05 14.12a2 2 0 0 1 0-2.828z" />
<path d="M16.243 9.172l3.086-.772a1.5 1.5 0 0 0 .697-2.516L17.81 3.667a1.5 1.5 0 0 0-2.44.47L14.122 7.05" />
<path d="M9.172 16.243L8.4 19.329a1.5 1.5 0 0 1-2.516.697L3.667 17.81a1.5 1.5 0 0 1 .47-2.44l2.913-1.248" />
</g>
</svg>
<svg v-else-if="type === 5" class="inline" width="2.5em" height="2.5em" viewBox="0 0 20 20" focusable="false">
<path
d="M9.584 6.036c1.952 0 2.591-1.381 1.839-2.843c-.871-1.693 1.895-3.155.521-3.155c-1.301 0-3.736 1.418-4.19 3.183c-.339 1.324.296 2.815 1.83 2.815zm5.212 8.951l-.444-.383a1.355 1.355 0 0 0-1.735 0l-.442.382a3.326 3.326 0 0 1-2.174.801a3.325 3.325 0 0 1-2.173-.8l-.444-.384a1.353 1.353 0 0 0-1.734.001l-.444.383c-1.193 1.028-2.967 1.056-4.204.1V19a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1v-3.912c-1.237.954-3.011.929-4.206-.101zM10 7c-7.574 0-9 3.361-9 5v.469l1.164 1.003a1.355 1.355 0 0 0 1.735 0l.444-.383a3.353 3.353 0 0 1 4.345 0l.444.384c.484.417 1.245.42 1.735-.001l.442-.382a3.352 3.352 0 0 1 4.346-.001l.444.383c.487.421 1.25.417 1.735 0L19 12.469V12c0-1.639-1.426-5-9-5z"
fill="currentColor"/>
</svg>
</div>
</template>
<script>
export default {
name: "MenuIcon",
props: {
type: {
type: Number,
default: 0
}
}
}
</script>

View File

@@ -0,0 +1,14 @@
<template>
<svg class="inline" width="2rem" height="2rem" viewBox="0 0 32 32" focusable="false">
<path
d="M17 17h5.142a4 4 0 1 0 0-2H17V7h5.142a4 4 0 1 0 0-2H17a2.002 2.002 0 0 0-2 2v8H9.858a4 4 0 1 0 0 2H15v8a2.002 2.002 0 0 0 2 2h5.142a4 4 0 1 0 0-2H17zm9-3a2 2 0 1 1-2 2a2.002 2.002 0 0 1 2-2zm0-10a2 2 0 1 1-2 2a2.002 2.002 0 0 1 2-2zM6 18a2 2 0 1 1 2-2a2.002 2.002 0 0 1-2 2zm20 6a2 2 0 1 1-2 2a2.002 2.002 0 0 1 2-2z"
fill="currentColor"
/>
</svg>
</template>
<script>
export default {
name: "NetworkIcon"
}
</script>

View File

@@ -10,7 +10,8 @@
/>
<path
d="M25.233 25.7l.026-.052l.07-.139a1.278 1.278 0 0 0 .061-.7a2.11 2.11 0 0 0-.27-.724l-6.286-10.9l-.95-1.656h-.017l-.959 1.648l-6.277 10.9a2.18 2.18 0 0 0-.244.715a1.438 1.438 0 0 0 .148.942a1.563 1.563 0 0 0 1.482.7h11.708a1.79 1.79 0 0 0 1.508-.741zm-7.367-10.864L23.62 24.8H12.112z"
fill="#2f495e"/>
fill="#2f495e"
/>
</svg>
</template>

View File

@@ -0,0 +1,13 @@
<template>
<svg class="inline" width="1.5em" height="1.5em" viewBox="0 0 24 24" focusable="false">
<path
d="M19.125 0H4.875A4.865 4.865 0 0 0 0 4.875v14.25C0 21.825 2.175 24 4.875 24h6.6c2.7 0 4.875-2.175 4.875-4.875V16.65h2.775c2.7 0 4.875-2.175 4.875-4.875v-6.9C24 2.175 21.825 0 19.125 0zM16.5 1.275h2.625a3.6 3.6 0 0 1 3.6 3.6v2.7H16.5v-6.3zM15.075 9v6.45H8.85V9h6.225zM8.85 1.2h6.225v6.375H8.85V1.2zM1.275 4.8a3.6 3.6 0 0 1 3.6-3.6H7.5v6.375H1.275V4.8zM7.5 9v6.45H1.2V9h6.3zm0 13.725H4.8a3.6 3.6 0 0 1-3.6-3.6V16.8h6.3v5.925zm7.575-3.525a3.6 3.6 0 0 1-3.6 3.6H8.85v-5.925h6.225V19.2zm7.65-7.35a3.6 3.6 0 0 1-3.6 3.6H16.5V9h6.225v2.85z"
fill="currentColor" />
</svg>
</template>
<script>
export default {
name: "PolyworkIcon"
}
</script>

View File

@@ -1,5 +1,5 @@
<template>
<svg class="inline" width="1em" height="1 em" viewBox="0 0 24 24" focusable="false">
<svg class="inline" width="1em" height="1em" viewBox="0 0 24 24" focusable="false">
<g
fill="none"
stroke="currentColor"

View File

@@ -0,0 +1,18 @@
<template>
<svg class="inline" width="2 rem" height="2rem" viewBox="0 0 24 24" focusable="false">
<g fill="none">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12.26 21.997a10.276 10.276 0 0 1-.52 0a10.004 10.004 0 0 1-8.983-6.173a10.034 10.034 0 0 1 .017-7.69A10.015 10.015 0 0 1 4.908 4.95l.042-.042a10.015 10.015 0 0 1 3.167-2.126a10.034 10.034 0 0 1 7.753-.006a10.015 10.015 0 0 1 3.186 2.138l.03.03c.913.917 1.65 2.01 2.153 3.223a10.012 10.012 0 0 1 .76 3.985a10.004 10.004 0 0 1-6.226 9.112a10.013 10.013 0 0 1-3.512.733zm1.772-6.55l2.874 2.873a8.004 8.004 0 0 1-9.812 0l2.874-2.874a4.007 4.007 0 0 0 4.064 0zm-5.478-1.415L5.68 16.906a8.004 8.004 0 0 1 0-9.812l2.874 2.874a4.007 4.007 0 0 0 0 4.064zm1.528-1.463a2.01 2.01 0 0 1-.014-1.087a1.99 1.99 0 0 1 .518-.896a1.99 1.99 0 0 1 1.932-.518c.328.088.639.26.896.518a1.99 1.99 0 0 1 .518 1.932c-.088.328-.26.639-.518.896a1.99 1.99 0 0 1-1.932.518a1.991 1.991 0 0 1-.896-.518a1.99 1.99 0 0 1-.504-.845zm3.95-4.015a4.007 4.007 0 0 0-4.064 0L7.094 5.68a8.004 8.004 0 0 1 9.812 0l-2.874 2.874zm4.288 8.352a8.004 8.004 0 0 0 0-9.812l-2.874 2.874a4.007 4.007 0 0 1 0 4.064l2.874 2.874z"
fill="currentColor"
/>
</g>
</svg>
</template>
<script>
export default {
name: "SupportIcon"
}
</script>

View File

@@ -1,14 +1,40 @@
<template>
<svg class="inline" width="1em" height="1em" viewBox="0 0 24 24" focusable="false">
<svg v-if="french" class="inline" width="1.5em" height="1.5em" viewBox="0 0 36 36" focusable="false">
<path
d="M12.87 15.07l-2.54-2.51l.03-.03A17.52 17.52 0 0 0 14.07 6H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35C8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5l3.11 3.11l.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"
fill="currentColor"
/>
fill="#00247D"
d="M0 9.059V13h5.628zM4.664 31H13v-5.837zM23 25.164V31h8.335zM0 23v3.941L5.63 23zM31.337 5H23v5.837zM36 26.942V23h-5.631zM36 13V9.059L30.371 13zM13 5H4.664L13 10.837z" />
<path
fill="#CF1B2B"
d="M25.14 23l9.712 6.801a3.977 3.977 0 0 0 .99-1.749L28.627 23H25.14zM13 23h-2.141l-9.711 6.8c.521.53 1.189.909 1.938 1.085L13 23.943V23zm10-10h2.141l9.711-6.8a3.988 3.988 0 0 0-1.937-1.085L23 12.057V13zm-12.141 0L1.148 6.2a3.994 3.994 0 0 0-.991 1.749L7.372 13h3.487z" />
<path
fill="#EEE"
d="M36 21H21v10h2v-5.836L31.335 31H32a3.99 3.99 0 0 0 2.852-1.199L25.14 23h3.487l7.215 5.052c.093-.337.158-.686.158-1.052v-.058L30.369 23H36v-2zM0 21v2h5.63L0 26.941V27c0 1.091.439 2.078 1.148 2.8l9.711-6.8H13v.943l-9.914 6.941c.294.07.598.116.914.116h.664L13 25.163V31h2V21H0zM36 9a3.983 3.983 0 0 0-1.148-2.8L25.141 13H23v-.943l9.915-6.942A4.001 4.001 0 0 0 32 5h-.663L23 10.837V5h-2v10h15v-2h-5.629L36 9.059V9zM13 5v5.837L4.664 5H4a3.985 3.985 0 0 0-2.852 1.2l9.711 6.8H7.372L.157 7.949A3.968 3.968 0 0 0 0 9v.059L5.628 13H0v2h15V5h-2z" />
<path
fill="#CF1B2B"
d="M21 15V5h-6v10H0v6h15v10h6V21h15v-6z" />
</svg>
<svg v-else class="inline" width="1.5em" height="1.5em" viewBox="0 0 36 36" focusable="false">
<path
fill="#ED2939"
d="M36 27a4 4 0 0 1-4 4h-8V5h8a4 4 0 0 1 4 4v18z" />
<path
fill="#002495"
d="M4 5a4 4 0 0 0-4 4v18a4 4 0 0 0 4 4h8V5H4z" />
<path
fill="#EEE"
d="M12 5h12v26H12z" />
</svg>
</template>
<script>
export default {
name: "TranslateIcon"
name: "TranslateIcon",
props: {
french: {
type: Boolean,
default: true
}
}
}
</script>

View File

@@ -1,9 +1,14 @@
<template>
<svg class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<svg v-if="active" class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<path
d="M15.71 12.71a6 6 0 1 0-7.42 0a10 10 0 0 0-6.22 8.18a1 1 0 0 0 2 .22a8 8 0 0 1 15.9 0a1 1 0 0 0 1 .89h.11a1 1 0 0 0 .88-1.1a10 10 0 0 0-6.25-8.19zM12 12a4 4 0 1 1 4-4a4 4 0 0 1-4 4z"
stroke="currentColor"
:class="{active: 'fill-black dark:fill-white'}"
d="M20 22H4v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2zm-8-9a6 6 0 1 1 0-12a6 6 0 0 1 0 12z"
fill="currentColor"
/>
</svg>
<svg v-else class="inline" width="2.5em" height="2.5em" viewBox="0 0 24 24" focusable="false">
<path
d="M20 22h-2v-2a3 3 0 0 0-3-3H9a3 3 0 0 0-3 3v2H4v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2zm-8-9a6 6 0 1 1 0-12a6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8a4 4 0 0 0 0 8z"
fill="currentColor"
/>
</svg>
</template>

View File

@@ -1,11 +1,5 @@
---
slug: how-i-start
title: How did I start development?
description: How did I start development? What am I capable of mastering? What will my future be?
reading_time: 5
tags: ["tags.life"]
cover: post-2.png
date: 07-01-2021
---
## Presentation

View File

@@ -1,11 +1,5 @@
---
slug: new-version-new-website
title: Opening of the new version of my site!
description: After long months of development, here is version 2 of my site!
reading_time: 2
tags: ["tags.dev"]
cover: post-1.png
date: 13-12-2020
---
## Presentation

View File

@@ -1,34 +0,0 @@
[
{
"slug": "erisium",
"title": "experiences.erisium",
"company": "Erisium",
"location": "Remote",
"begin_date": "02-2019",
"end_date": "11-2020"
},
{
"slug": "freelance",
"title": "experiences.freelance",
"company": "ArtDanjProduction",
"location": "France",
"begin_date": "09-2015",
"end_date": "Today"
},
{
"slug": "idemia",
"title": "experiences.idemia",
"company": "Idemia, Courbevoie",
"location": "France",
"begin_date": "06-2019",
"end_date": "06-2019"
},
{
"slug": "la-salle-a-manger",
"title": "experiences.lsam",
"company": "La Salle à manger, Boulogne Billancourt",
"location": "France",
"begin_date": "04-2018",
"end_date": "04-2018"
}
]

View File

@@ -1,26 +0,0 @@
[
{
"slug": "freelance",
"title": "formations.freelance.title",
"description": "formations.freelance.description",
"location": "Remote",
"begin_date": "04-2015",
"end_date": "Today"
},
{
"slug": "dnb",
"title": "formations.dnb.title",
"description": "formations.dnb.description",
"location": "France",
"begin_date": "09-2017",
"end_date": "09-2018"
},
{
"slug": "bac",
"title": "formations.bac.title",
"description": "formations.bac.description",
"location": "France",
"begin_date": "09-2020",
"end_date": "Today"
}
]

View File

@@ -1,11 +1,5 @@
---
slug: how-i-start
title: Comment ai-je commencé le développement ?
description: Comment ai-je commencé le développement ? Que suis-je capable de maitriser ? Quel sera mon futur ?
reading_time: 5
tags: ["tags.life"]
cover: post-2.png
date: 07-01-2021
---
## Présentation

View File

@@ -1,11 +1,5 @@
---
slug: new-version-new-website
title: Ouverture de la nouvelle version de mon site !
description: Après de long mois de développement, voici la version 2 de mon site !
reading_time: 2
tags: ["tags.dev"]
cover: post-1.png
date: 13-12-2020
---
## Présentation

View File

@@ -1,7 +0,0 @@
{
"age": 18,
"hiring": {
"status": "available",
"color": "green"
}
}

View File

@@ -1,34 +0,0 @@
[
{
"slug": "erisium",
"title": "Erisium",
"description": "works.erisium",
"url": "https://erisium.com",
"cover": "erisium.png",
"tags": ["tags.mc"]
},
{
"slug": "artsite",
"title": "ArtSite",
"description": "works.artsite",
"url": "https://arthurdanjou.fr",
"cover": "artsite.png",
"tags": ["tags.web"]
},
{
"slug": "artapi",
"title": "ArtApi",
"description": "works.artapi",
"url": "https://api.arthurdanjou.fr",
"cover": "artapi.png",
"tags": ["tags.api"]
},
{
"slug": "linkyjs",
"title": "LinkyJs",
"description": "works.linkyjs",
"url": "https://github.com/linkyjs/",
"cover": "linkyjs.png",
"tags": ["tags.software", "tags.opensource"]
}
]

View File

@@ -1,122 +0,0 @@
[
{
"title": "Java",
"color": "blueGray",
"cover": "Java.png",
"slug": "java"
},
{
"title": "TypeScript",
"color": "cyan",
"cover": "TypeScript.png",
"slug": "typescript"
},
{
"title": "JavaScript",
"color": "yellow",
"cover": "JavaScript.png",
"slug": "javascript"
},
{
"title": "Go",
"color": "cyan",
"cover": "GoLang.png",
"slug": "golang"
},
{
"title": "NuxtJs",
"color": "emerald",
"cover": "NuxtJs.png",
"slug": "nuxtjs"
},
{
"title": "VueJs",
"color": "emerald",
"cover": "VueJs.png",
"slug": "vuejs"
},
{
"title": "AdonisJs",
"color": "purple",
"cover": "AdonisJs.png",
"slug": "adonisjs"
},
{
"title": "ViteJs",
"color": "amber",
"cover": "Vitejs.png",
"slug": "vitejs"
},
{
"title": "WindiCss",
"color": "lightBlue",
"cover": "Windicss.png",
"slug": "windicss"
},
{
"title": "Html",
"color": "orange",
"cover": "Html.png",
"slug": "html"
},
{
"title": "Css",
"color": "lightBlue",
"cover": "Css.png",
"slug": "css"
},
{
"title": "NodeJs",
"color": "lime",
"cover": "NodeJs.png",
"slug": "nodejs"
},
{
"title": "ElectronJs",
"color": "teal",
"cover": "ElectronJs.png",
"slug": "electronjs"
},
{
"title": "Git",
"color": "orange",
"cover": "Git.png",
"slug": "git"
},
{
"title": "MariaDB",
"color": "blue",
"cover": "MariaDB.png",
"slug": "mariadb"
},
{
"title": "RabbitMQ",
"color": "orange",
"cover": "RabbitMQ.png",
"slug": "rabbitmq"
},
{
"title": "Redis",
"color": "red",
"cover": "Redis.png",
"slug": "redis"
},
{
"title": "Sass",
"color": "rose",
"cover": "Sass.png",
"slug": "sass"
},
{
"title": "TailwindCss",
"color": "teal",
"cover": "TailwindCss.png",
"slug": "tailwindcss"
},
{
"title": "Docker",
"color": "cyan",
"cover": "Docker.png",
"slug": "docker"
}
]

View File

@@ -1,11 +0,0 @@
[
{
"slug": "tags.dev"
},
{
"slug": "tags.tech"
},
{
"slug": "tags.life"
}
]

View File

@@ -1,7 +1,54 @@
<template>
<div>
<Header />
<Nuxt class="z-10 pt-16 lg:pt-24 content"/>
<Footer />
<SideMenu />
<div class="w-full overflow-hidden xl:overflow-visible">
<div
id="slider"
class="xl:static shadow-2xl transition-all duration-500 overflow-hidden xl:overflow-visible"
:class="{'transform scale-90 md:scale-70 lg:scale-60 xl:scale-100 rounded-lg xl:rounded-none translate-x-10/12 sm:translate-x-4/12 lg:translate-x-3/12 xl:translate-x-0': opened}"
:tabindex="opened ? -1 : 0"
>
<div
@click="closeMenu"
class="min-h-screen relative z-50 bg-white dark:bg-black w-full min-w-screen pb-20 xl:pb-0 duration-300"
:class="{'cursor-pointer': opened}"
>
<Announcement />
<Header />
<Nuxt class="z-10 pt-16 content"/>
<Footer />
</div>
</div>
</div>
<MobileNavbar />
</div>
</template>
<script lang="ts">
import {computed, useRouter, useStore} from "@nuxtjs/composition-api";
import {State} from "~/types/types";
export default {
setup() {
const store = useStore<State>()
const $router = useRouter()
$router.afterEach(() => {
store.commit('SET_ROUTE', $router.currentRoute.path)
})
const closeMenu = () => {
store.commit('TOGGLE_OPENED', false)
document.getElementById('nav')!.classList.remove('z-50')
setTimeout(() => {
document.getElementById('slider')!.style.maxHeight = 'none'
}, 500)
}
return {
opened: computed(() => store.state.opened),
closeMenu,
}
}
}
</script>

Some files were not shown because too many files have changed in this diff Show More