mirror of
https://github.com/ArthurDanjou/website-old.git
synced 2026-01-14 12:14:42 +01:00
Working hardly
This commit is contained in:
@@ -6,6 +6,7 @@ import arch from './settings/Arch'
|
|||||||
import plugins from './settings/Plugins'
|
import plugins from './settings/Plugins'
|
||||||
import css from './settings/Style'
|
import css from './settings/Style'
|
||||||
import configs from './settings/RuntimeConfig'
|
import configs from './settings/RuntimeConfig'
|
||||||
|
import {NuxtConfig} from "@nuxt/types";
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
head,
|
head,
|
||||||
@@ -16,6 +17,6 @@ const config = {
|
|||||||
css,
|
css,
|
||||||
buildModules,
|
buildModules,
|
||||||
...configs,
|
...configs,
|
||||||
}
|
} as NuxtConfig
|
||||||
|
|
||||||
export default config
|
export default config
|
||||||
|
|||||||
23
package.json
23
package.json
@@ -10,8 +10,9 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@nuxt/content": "^1.14.0",
|
"@nuxt/content": "^1.14.0",
|
||||||
"@nuxtjs/axios": "^5.13.6",
|
"@nuxtjs/axios": "^5.13.6",
|
||||||
"@nuxtjs/composition-api": "0.23.4",
|
"@nuxtjs/composition-api": "0.26.0",
|
||||||
"@nuxtjs/dotenv": "^1.4.1",
|
"@nuxtjs/dotenv": "^1.4.1",
|
||||||
|
"@nuxtjs/i18n": "^7.0.2",
|
||||||
"@nuxtjs/proxy": "^2.1.0",
|
"@nuxtjs/proxy": "^2.1.0",
|
||||||
"@nuxtjs/redirect-module": "^0.3.1",
|
"@nuxtjs/redirect-module": "^0.3.1",
|
||||||
"@nuxtjs/robots": "^2.5.0",
|
"@nuxtjs/robots": "^2.5.0",
|
||||||
@@ -19,20 +20,18 @@
|
|||||||
"@nuxtjs/sitemap": "^2.4.0",
|
"@nuxtjs/sitemap": "^2.4.0",
|
||||||
"@nuxtjs/universal-storage": "^0.5.9",
|
"@nuxtjs/universal-storage": "^0.5.9",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
"core-js": "^3.14.0",
|
"core-js": "^3.16.1",
|
||||||
"nuxt": "^2.15.7",
|
"nuxt": "^2.15.8",
|
||||||
"nuxt-i18n": "^6.27.1",
|
"prism-themes": "^1.8.0",
|
||||||
"prism-themes": "^1.7.0",
|
"sass": "^1.37.5",
|
||||||
"sass": "^1.35.1",
|
"windicss": "^3.1.7"
|
||||||
"vuex": "^3.6.2",
|
|
||||||
"windicss": "^3.1.3"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nuxt/types": "^2.15.7",
|
"@nuxt/types": "^2.15.8",
|
||||||
"@nuxt/typescript-build": "^2.1.0",
|
"@nuxt/typescript-build": "^2.1.0",
|
||||||
"@nuxtjs/color-mode": "^2.0.10",
|
"@nuxtjs/color-mode": "^2.1.1",
|
||||||
"markdown-it-prism": "^2.1.6",
|
"markdown-it-prism": "^2.1.8",
|
||||||
"nuxt-windicss": "^1.1.1",
|
"nuxt-windicss": "^1.2.3",
|
||||||
"sass-loader": "10.1.1"
|
"sass-loader": "10.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ const sentry = {
|
|||||||
|
|
||||||
export default [
|
export default [
|
||||||
['@nuxtjs/axios', axios],
|
['@nuxtjs/axios', axios],
|
||||||
['nuxt-i18n', i18n],
|
['@nuxtjs/i18n', i18n],
|
||||||
['@nuxt/content', content],
|
['@nuxt/content', content],
|
||||||
['@nuxtjs/universal-storage', storage],
|
['@nuxtjs/universal-storage', storage],
|
||||||
['@nuxtjs/robots', robots],
|
['@nuxtjs/robots', robots],
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ export default defineComponent({
|
|||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
$sentry.captureEvent(error)
|
$sentry.captureEvent(error)
|
||||||
});
|
});
|
||||||
})
|
}, 'infos')
|
||||||
|
|
||||||
return {
|
return {
|
||||||
info
|
info
|
||||||
|
|||||||
@@ -37,6 +37,6 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
export default {
|
export default {
|
||||||
name: "AdPreview"
|
name: "AdHome"
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,28 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
v-if="announce"
|
v-if="announce"
|
||||||
class="h-12 flex justify-center items-center"
|
class="p-4 duration-300 flex justify-center items-center text-center"
|
||||||
:class="[getBackgroundColor, getHoverColor]"
|
:class="[getHoverColor, getBackgroundColor]"
|
||||||
>
|
>
|
||||||
{{ announce.translation.code }}
|
{{ $t(announce.message.code) }}
|
||||||
<img
|
<img
|
||||||
v-if="announce.file"
|
v-if="announce.file"
|
||||||
:src="`https://athena.arthurdanjou.fr/files/${announce.file}`"
|
:src="`https://athena.arthurdanjou.fr/files/${announce.file}`"
|
||||||
alt="Announce Cover File"
|
alt="Announce Cover File"
|
||||||
>
|
>
|
||||||
</div>
|
</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>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {computed, ref, useAsync, useContext} from "@nuxtjs/composition-api";
|
import {computed, ref, useAsync, useContext} from "@nuxtjs/composition-api";
|
||||||
import {Translation} from "~/types/types";
|
import {Announce} from "~/types/types";
|
||||||
|
|
||||||
interface Announce {
|
|
||||||
color: string,
|
|
||||||
hover_color: string,
|
|
||||||
translation: Translation
|
|
||||||
file: null
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Announcement",
|
name: "Announcement",
|
||||||
@@ -52,9 +48,9 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const getHoverColor = computed(() => {
|
const getHoverColor = computed(() => {
|
||||||
switch (announce.value!.color) {
|
switch (announce.value!.hover_color) {
|
||||||
case 'gray': {
|
case 'gray': {
|
||||||
return 'hover:bg-gray-600'
|
return 'hover:bg-gray-800 dark:hover:bg-gray-300'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -62,7 +58,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
announce,
|
announce,
|
||||||
getBackgroundColor,
|
getBackgroundColor,
|
||||||
getHoverColor
|
getHoverColor,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ export default defineComponent({
|
|||||||
const {$axios, $sentry} = useContext()
|
const {$axios, $sentry} = useContext()
|
||||||
const form = ref<Form>({} as Form)
|
const form = ref<Form>({} as Form)
|
||||||
const handleForm = async () => {
|
const handleForm = async () => {
|
||||||
const response = await $axios.post('form',
|
const response = await $axios.post('/api/form',
|
||||||
{
|
{
|
||||||
email: form.value.email,
|
email: form.value.email,
|
||||||
name: form.value.name,
|
name: form.value.name,
|
||||||
|
|||||||
@@ -1,70 +1,150 @@
|
|||||||
<template>
|
<template>
|
||||||
<footer class="footer w-full border-t-2 border-solid border-gray-200 px-4 xl:px-32 dark:border-gray-800 mb-26 md:mb-0">
|
<footer class="footer w-full mt-20">
|
||||||
<div class="flex flex-col-reverse md:flex-row justify-between pt-4 items-center">
|
<div class="p-8 pb-0">
|
||||||
<div class="inline flex space-x-4">
|
<div class="lg:flex justify-evenly">
|
||||||
<a class="link font-semibold" href="https://twitch.com/ArthurDanjou" target="_blank" rel="noopener noreferrer">
|
<div class="lg:w-1/3">
|
||||||
<TwitchIcon /> <span>Twitch</span>,
|
<div class="flex">
|
||||||
</a>
|
<Logo />
|
||||||
<a class="link font-semibold" href="https://github.com/ArthurDanjou" target="_blank" rel="noopener noreferrer">
|
|
||||||
<GithubIcon /> <span>Github</span>,
|
|
||||||
</a>
|
|
||||||
<a class="link font-semibold" href="https://twitter.com/ArthurDanj" target="_blank" rel="noopener noreferrer">
|
|
||||||
<TwitterIcon /> <span>Twitter</span>,
|
|
||||||
</a>
|
|
||||||
<a class="link font-semibold" href="mailto:contact@arthurdanjou.fr" target="_blank" rel="noopener noreferrer">
|
|
||||||
<MailIcon /> <span>Mail</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="flex space-x-4 mb-4 md:mb-0">
|
<div class="my-8">
|
||||||
<nuxt-link class="link font-semibold" to="/env">
|
<p class="text-justify">
|
||||||
<span>{{ $t('header.env') }}</span>,
|
{{ $t('footer.description') }}
|
||||||
</nuxt-link>
|
</p>
|
||||||
<nuxt-link class="link font-semibold" to="/guestbook">
|
<div class="mt-4">
|
||||||
<span>{{ $t('header.guestbook') }}</span>,
|
<nuxt-link to="/contact" class="text-red-400 border-b-2 border-gray-200 dark:border-gray-700 hover:border-red-400 duration-300">
|
||||||
</nuxt-link>
|
{{ $t(hiring_message) }}
|
||||||
<nuxt-link class="link font-semibold" to="/contact">
|
|
||||||
<span>{{ $t('header.contact') }}</span>,
|
|
||||||
</nuxt-link>
|
|
||||||
<nuxt-link class="link font-semibold" to="/newsletter">
|
|
||||||
<span>{{ $t('header.newsletter') }}</span>
|
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center my-4">
|
<div class="social-links flex space-x-4 mb-8">
|
||||||
<p>
|
<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/RQhjE5UkxD" rel="noopener noreferrer">
|
||||||
|
<DiscordIcon />
|
||||||
|
</a>
|
||||||
|
<a target="_blank" href="mailto:contact@arthurdanjou.fr" rel="noopener noreferrer">
|
||||||
|
<MailIcon />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<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 mb-8 space-y-2 lg:space-y-4 font-medium">
|
||||||
|
<div class="link">
|
||||||
|
<nuxt-link to="/">
|
||||||
|
{{ $t('header.home') }}
|
||||||
|
</nuxt-link>
|
||||||
|
</div>
|
||||||
|
<div class="link">
|
||||||
|
<nuxt-link to="/about">
|
||||||
|
{{ $t('header.about') }}
|
||||||
|
</nuxt-link>
|
||||||
|
</div>
|
||||||
|
<div class="link">
|
||||||
|
<nuxt-link to="/blog">
|
||||||
|
{{ $t('header.blog') }}
|
||||||
|
</nuxt-link>
|
||||||
|
</div>
|
||||||
|
<div class="link">
|
||||||
|
<nuxt-link to="/projects">
|
||||||
|
{{ $t('header.projects') }}
|
||||||
|
</nuxt-link>
|
||||||
|
</div>
|
||||||
|
<div class="link">
|
||||||
|
<nuxt-link to="/services">
|
||||||
|
{{ $t('header.services') }}
|
||||||
|
</nuxt-link>
|
||||||
|
</div>
|
||||||
|
<div class="link">
|
||||||
|
<nuxt-link to="/env">
|
||||||
|
{{ $t('header.env') }}
|
||||||
|
</nuxt-link>
|
||||||
|
</div>
|
||||||
|
<div class="link">
|
||||||
|
<nuxt-link to="/guestbook">
|
||||||
|
{{ $t('header.guestbook') }}
|
||||||
|
</nuxt-link>
|
||||||
|
</div>
|
||||||
|
<div class="link">
|
||||||
|
<nuxt-link to="/newsletter">
|
||||||
|
{{ $t('header.newsletter') }}
|
||||||
|
</nuxt-link>
|
||||||
|
</div>
|
||||||
|
<div class="link">
|
||||||
|
<nuxt-link to="/contact">
|
||||||
|
{{ $t('header.contact') }}
|
||||||
|
</nuxt-link>
|
||||||
|
</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') }}
|
{{ $t('footer.credits') }}
|
||||||
<a class="link 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 />
|
<NuxtIcon />
|
||||||
<span>NuxtJS</span>
|
<span>NuxtJS</span>
|
||||||
</a>
|
</a>
|
||||||
{{ $t('footer.credits_separator_and') }}
|
{{ $t('footer.credits_separator') }}
|
||||||
<a class="link font-semibold" target="_blank" href="https://adonisjs.com" rel="noopener noreferrer">
|
<a class="social font-semibold" target="_blank" href="https://adonisjs.com" rel="noopener noreferrer">
|
||||||
<AdonisIcon />
|
<AdonisIcon />
|
||||||
<span>AdonisJS</span>
|
<span>AdonisJS</span>
|
||||||
</a>
|
</a>
|
||||||
{{ $t('footer.credits_separator') }} <span>Arthur DANJOU</span>
|
</div>
|
||||||
</p>
|
<p class="mt-4 lg:mt-0">{{ $t('footer.copyrights', { date: getDate }) }}</p>
|
||||||
<p>{{ $t('footer.copyrights', { date: getDate }) }}</p>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<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({
|
export default defineComponent({
|
||||||
name: "Footer",
|
name: "Footer",
|
||||||
setup() {
|
setup() {
|
||||||
const {$colorMode} = useContext()
|
const {$colorMode, $axios, $sentry, app} = useContext()
|
||||||
const isDarkMode = computed(() => {
|
const isDarkMode = computed(() => {
|
||||||
return $colorMode.preference === 'dark'
|
return $colorMode.preference === 'dark'
|
||||||
})
|
})
|
||||||
|
|
||||||
const getDate = ref(new Date().getFullYear())
|
const getDate = ref(new Date().getFullYear())
|
||||||
|
|
||||||
|
const hiring_message = ref("")
|
||||||
|
useAsync(async () => {
|
||||||
|
const request = await $axios.get('/api/informations', {
|
||||||
|
headers: {
|
||||||
|
'Authorization': `Bearer ${process.env.API_TOKEN}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (request.status === 200) {
|
||||||
|
hiring_message.value = request.data.informations.translation.code
|
||||||
|
} else {
|
||||||
|
app.error({statusCode: 500})
|
||||||
|
$sentry.captureEvent(request.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const store = useStore<State>()
|
||||||
|
const route = computed(() => store.state.route)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
getDate,
|
getDate,
|
||||||
isDarkMode
|
isDarkMode,
|
||||||
|
hiring_message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -72,7 +152,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.footer {
|
.footer {
|
||||||
.link {
|
.social {
|
||||||
span {
|
span {
|
||||||
@apply border-b-2 border-gray-200 dark:border-gray-700 duration-300;
|
@apply border-b-2 border-gray-200 dark:border-gray-700 duration-300;
|
||||||
}
|
}
|
||||||
@@ -80,5 +160,14 @@ export default defineComponent({
|
|||||||
@apply border-indigo-600
|
@apply border-indigo-600
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.link {
|
||||||
|
a {
|
||||||
|
@apply border-b-2 border-transparent duration-300;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
@apply border-indigo-600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ export default defineComponent({
|
|||||||
|
|
||||||
const alreadySent = ref(false)
|
const alreadySent = ref(false)
|
||||||
const hasAlreadySignMessage = async (id: number) => {
|
const hasAlreadySignMessage = async (id: number) => {
|
||||||
const response = await $axios.get(`/guestbook/${id}`, {
|
const response = await $axios.get(`/api/guestbook/${id}`, {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${process.env.API_TOKEN}`
|
'Authorization': `Bearer ${process.env.API_TOKEN}`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export default defineComponent({
|
|||||||
const month = realMonth.toString().length == 2 ? realMonth.toString() : `0${realMonth.toString()}`
|
const month = realMonth.toString().length == 2 ? realMonth.toString() : `0${realMonth.toString()}`
|
||||||
const minutes = date.getMinutes().toString().length == 2 ? date.getMinutes() : `0${date.getMinutes()}`
|
const minutes = date.getMinutes().toString().length == 2 ? date.getMinutes() : `0${date.getMinutes()}`
|
||||||
const hours = date.getHours().toString().length == 2 ? date.getHours() : `0${date.getHours()}`
|
const hours = date.getHours().toString().length == 2 ? date.getHours() : `0${date.getHours()}`
|
||||||
return `${date.getDate()} ${i18n.t(`month.${month}`)} ${date.getFullYear()} at ${hours}:${minutes}`
|
return `${date.getDate()} ${i18n.t(`month.${month}`)} ${date.getFullYear()} ${i18n.t('guestbook.at')} ${hours}:${minutes}`
|
||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,22 +1,20 @@
|
|||||||
<template>
|
<template>
|
||||||
<header class="hidden md:block dark:bg-black dark:text-white sticky z-50 top-0 left-0 bg-white w-full duration-400"
|
<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'">
|
: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">
|
<div class="header-container z-index-50 flex justify-between items-center h-full px-5 xl:px-32">
|
||||||
<nuxt-link to="/">
|
<Logo />
|
||||||
<img src="~/assets/images/logo-header.png" alt="Logo Circle" class="h-10 left cursor-pointer duration-500"/>
|
|
||||||
</nuxt-link>
|
|
||||||
<nav class="right flex flex-col md:flex-row items-center hidden md:inline-block">
|
<nav class="right flex flex-col md:flex-row items-center hidden md:inline-block">
|
||||||
<div class="flex text-lg">
|
<div class="flex text-lg">
|
||||||
<nuxt-link class="nav-link" to="/about">
|
<nuxt-link class="nav-link" to="/about" :class="{ 'link-active': isWindow('about') }">
|
||||||
{{ $t('header.about') }}
|
{{ $t('header.about') }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<nuxt-link class="nav-link" to="/blog">
|
<nuxt-link class="nav-link" to="/blog" :class="{ 'link-active': isWindow('blog') }">
|
||||||
{{ $t('header.blog') }}
|
{{ $t('header.blog') }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<nuxt-link class="nav-link" to="/projects">
|
<nuxt-link class="nav-link" to="/projects" :class="{ 'link-active': isWindow('projects') }">
|
||||||
{{ $t('header.projects') }}
|
{{ $t('header.projects') }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<nuxt-link class="nav-link" to="/contact">
|
<nuxt-link class="nav-link" to="/contact" :class="{ 'link-active': isWindow('contact') }">
|
||||||
{{ $t('header.contact') }}
|
{{ $t('header.contact') }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</div>
|
</div>
|
||||||
@@ -44,14 +42,17 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {
|
import {
|
||||||
|
computed,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
onMounted,
|
onMounted,
|
||||||
onUnmounted,
|
onUnmounted,
|
||||||
ref,
|
ref,
|
||||||
useAsync,
|
useAsync,
|
||||||
useContext,
|
useContext,
|
||||||
useRouter
|
useRouter,
|
||||||
|
useStore
|
||||||
} from "@nuxtjs/composition-api";
|
} from "@nuxtjs/composition-api";
|
||||||
|
import {State} from "~/types/types";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "Header",
|
name: "Header",
|
||||||
@@ -83,11 +84,20 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
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 {
|
return {
|
||||||
scrollPosition,
|
scrollPosition,
|
||||||
changeColorMode,
|
changeColorMode,
|
||||||
updateScroll,
|
updateScroll,
|
||||||
changeLanguage,
|
changeLanguage,
|
||||||
|
isWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -95,10 +105,14 @@ export default defineComponent({
|
|||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.nav-link {
|
.nav-link {
|
||||||
@apply font-medium cursor-pointer duration-300 mx-4 border-b-2 border-transparent hover:(border-indigo-600);
|
@apply font-medium cursor-pointer duration-500 mx-4 border-b-2 border-transparent hover:(border-indigo-600);
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar-bottom-items li {
|
.navbar-bottom-items li {
|
||||||
transition: all .2s ease-in-out;
|
transition: all .2s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link-active {
|
||||||
|
@apply text-indigo-600
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
18
src/components/Logo.vue
Normal file
18
src/components/Logo.vue
Normal 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>
|
||||||
@@ -1,41 +1,31 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="w-full z-100 fixed bottom-0 left-0 md:hidden duration-500"
|
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="{'opened': isOpened}"
|
:class="{'-translate-y-8 translate-x-9/12 sm:translate-x-1/2 xl:translate-x-0': opened}"
|
||||||
>
|
>
|
||||||
<ul
|
<nav class="flex justify-evenly py-4 bg-gray-200 dark:bg-gray-700 rounded-3xl dark:text-white text-sm overflow-hidden">
|
||||||
class="bg-gray-200 dark:bg-gray-800 m-4 rounded-3xl dark:text-white text-sm flex items-center justify-around h-20 navbar-bottom-items"
|
<nuxt-link to="/" class="relative font-medium">
|
||||||
>
|
|
||||||
<nuxt-link to="/" class="w-1/5">
|
|
||||||
<li class="h-full w-full font-medium flex flex-col items-center justify-center">
|
|
||||||
<HomeIcon :active="isWindow('')"/>
|
<HomeIcon :active="isWindow('')"/>
|
||||||
{{ debug }}
|
|
||||||
</li>
|
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<nuxt-link to="/about" class="w-1/5">
|
<nuxt-link to="/about" class="relative font-medium">
|
||||||
<li class="font-medium flex flex-col items-center justify-center">
|
|
||||||
<UserIcon :active="isWindow('/about')"/>
|
<UserIcon :active="isWindow('/about')"/>
|
||||||
</li>
|
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<nuxt-link to="/blog" class="w-1/5">
|
<nuxt-link to="/blog" class="relative font-medium">
|
||||||
<li class="font-medium flex flex-col items-center justify-center">
|
|
||||||
<BookIcon :active="isWindow('/blog')"/>
|
<BookIcon :active="isWindow('/blog')"/>
|
||||||
</li>
|
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<nuxt-link to="/projects" class="w-1/5">
|
<nuxt-link to="/projects" class="relative font-medium">
|
||||||
<li class="font-medium flex flex-col items-center justify-center">
|
|
||||||
<LightbulbIcon :active="isWindow('/projects')"/>
|
<LightbulbIcon :active="isWindow('/projects')"/>
|
||||||
</li>
|
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
<li @click='toggleMenu' class="w-1/5 flex flex-col items-center justify-center cursor-pointer">
|
<button @click.prevent='toggleMenu' class="font-medium cursor-pointer">
|
||||||
<MenuIcon :type="getMenuIconType"/>
|
<CrossIcon v-if="opened" />
|
||||||
</li>
|
<MenuIcon v-else :type="getMenuIconType"/>
|
||||||
</ul>
|
</button>
|
||||||
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {computed, defineComponent, useRouter, useStore} from "@nuxtjs/composition-api";
|
import {computed, defineComponent, ref, useRouter, useStore, watch} from "@nuxtjs/composition-api";
|
||||||
import {State} from "~/types/types";
|
import {State} from "~/types/types";
|
||||||
|
|
||||||
const PAGE_TYPE = {
|
const PAGE_TYPE = {
|
||||||
@@ -44,44 +34,43 @@ const PAGE_TYPE = {
|
|||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "MobileNavbar",
|
name: "MobileNavbar",
|
||||||
setup() {
|
setup () {
|
||||||
const $router = useRouter()
|
|
||||||
const debug = computed(() => $router.currentRoute.path)
|
|
||||||
|
|
||||||
const isWindow = (loc: string) => {
|
|
||||||
if (loc === '') return $router.currentRoute.path === "/"
|
|
||||||
else return $router.currentRoute.path.includes(loc)
|
|
||||||
}
|
|
||||||
|
|
||||||
const getMenuIconType = computed(() => PAGE_TYPE[$router.currentRoute.path.split('/')[1]] || 0)
|
|
||||||
|
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const toggleMenu = () => {
|
const route = computed(() => store.state.route)
|
||||||
window.scrollTo({
|
const isWindow = (loc: string) => {
|
||||||
top: 0,
|
if (loc === '') return route.value === "/"
|
||||||
})
|
else return route.value.includes(loc)
|
||||||
store.commit('TOGGLE_OPENED', !store.state.opened)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getMenuIconType = computed(() => PAGE_TYPE[route.value.split('/')[1]] || 0)
|
||||||
|
|
||||||
|
const toggleMenu = () => {
|
||||||
|
store.commit('TOGGLE_OPENED', !store.state.opened)
|
||||||
|
if (store.state.opened) {
|
||||||
|
setTimeout(() => document.getElementById('nav')!.classList.add('z-50'), 300)
|
||||||
|
} else {
|
||||||
|
document.getElementById('nav')!.classList.remove('z-50')
|
||||||
|
setTimeout(() => {
|
||||||
|
document.getElementById('slider')!.style.maxHeight = 'none'
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const $router = useRouter()
|
||||||
$router.afterEach(() => {
|
$router.afterEach(() => {
|
||||||
store.commit('TOGGLE_OPENED', false)
|
store.commit('TOGGLE_OPENED', false)
|
||||||
|
document.getElementById('nav')!.classList.remove('z-50')
|
||||||
|
setTimeout(() => {
|
||||||
|
document.getElementById('slider')!.style.maxHeight = 'none'
|
||||||
|
}, 100)
|
||||||
})
|
})
|
||||||
|
|
||||||
const isOpened = computed(() => store.state.opened)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isWindow,
|
isWindow,
|
||||||
toggleMenu,
|
toggleMenu,
|
||||||
isOpened,
|
opened: computed(() => store.state.opened),
|
||||||
getMenuIconType,
|
getMenuIconType
|
||||||
debug
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.opened {
|
|
||||||
@apply transform translate-x-9/12 scale-90 -translate-y-10 duration-500;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<nuxt-link :to="`/blog/${slug}`" rel="noreferrer noopener">
|
<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="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"
|
<div class="h-2/5 post rounded-t-lg"
|
||||||
:style="{ backgroundImage: `url(${getCover})` }">
|
:style="{ backgroundImage: `url(${getCover})` }">
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<a :href="url" target="_blank" rel="noopener noreferrer">
|
<a :href="url" target="_blank">
|
||||||
<div class="rounded-lg dark:shadow-white 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="rounded-lg dark:shadow-white 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"
|
<div class="h-1/2 w-full h-2/5 project rounded-t-lg"
|
||||||
:style="{ backgroundImage: `url(${getCover})` }">
|
:style="{ backgroundImage: `url(${getCover})` }">
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="my-8 lg:flex w-full lg:space-x-8 flex flex-wrap justify-center">
|
<div class="my-8 lg:flex w-full lg:space-x-8 flex flex-wrap justify-center">
|
||||||
<div v-for="project in projects">
|
<div v-for="project in projects" class="mb-4">
|
||||||
<Project
|
<Project
|
||||||
:title="project.title"
|
:title="project.title"
|
||||||
:cover="project.cover"
|
:cover="project.cover"
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="md:hidden w-full min-w-screen">
|
<div class="relative w-full min-w-screen xl:overflow-auto">
|
||||||
<div class="bg-gray-100 dark:bg-gray-900 min-h-screen duration-500 absolute top-0 left-0 right-0 py-4 pr-20 pl-4 flex items-center">
|
<div
|
||||||
<nav class="w-auto">
|
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="mb-8">
|
||||||
<div class="flex justify-between mb-4">
|
<div class="flex justify-between mb-4">
|
||||||
<div @click="closeMenu" class="flex justify-center items-center cursor-pointer cross text-sm">
|
<div @click="closeMenu" class="flex justify-center items-center cursor-pointer cross text-sm">
|
||||||
@@ -26,10 +31,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<nuxt-link class="profile ml-4 flex items-center" to="/">
|
<Logo />
|
||||||
<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>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="w-auto flex">
|
<div class="w-auto flex">
|
||||||
<div class="flex flex-col ml-4 mb-8 space-y-1.5 font-bold text-lg">
|
<div class="flex flex-col ml-4 mb-8 space-y-1.5 font-bold text-lg">
|
||||||
@@ -38,7 +40,7 @@
|
|||||||
{{ $t('header.home') }}
|
{{ $t('header.home') }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-link" :class="{ 'link-active': isWindow('') }">
|
<div class="nav-link" :class="{ 'link-active': isWindow('about') }">
|
||||||
<nuxt-link to="/about">
|
<nuxt-link to="/about">
|
||||||
{{ $t('header.about') }}
|
{{ $t('header.about') }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
@@ -68,6 +70,11 @@
|
|||||||
{{ $t('header.guestbook') }}
|
{{ $t('header.guestbook') }}
|
||||||
</nuxt-link>
|
</nuxt-link>
|
||||||
</div>
|
</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') }">
|
<div class="nav-link" :class="{ 'link-active': isWindow('contact') }">
|
||||||
<nuxt-link to="/contact">
|
<nuxt-link to="/contact">
|
||||||
{{ $t('header.contact') }}
|
{{ $t('header.contact') }}
|
||||||
@@ -75,7 +82,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="social-links flex justify-between space-x-1">
|
<div class="social-links flex justify-between space-x-0.5">
|
||||||
<a target="_blank" href="https://twitter.com/ArthurDanj" rel="noopener noreferrer">
|
<a target="_blank" href="https://twitter.com/ArthurDanj" rel="noopener noreferrer">
|
||||||
<TwitterIcon />
|
<TwitterIcon />
|
||||||
</a>
|
</a>
|
||||||
@@ -101,7 +108,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {defineComponent, useAsync, useContext, useRouter, useStore} from "@nuxtjs/composition-api";
|
import {
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
useAsync,
|
||||||
|
useContext,
|
||||||
|
useRouter,
|
||||||
|
useStore
|
||||||
|
} from "@nuxtjs/composition-api";
|
||||||
import {State} from "~/types/types";
|
import {State} from "~/types/types";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -121,21 +135,27 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const isWindow = (loc: string) => {
|
|
||||||
if (loc === '') return $router.currentRoute.path === "/"
|
|
||||||
else return $router.currentRoute.path.includes(loc)
|
|
||||||
}
|
|
||||||
|
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
const closeMenu = () => {
|
const closeMenu = () => {
|
||||||
store.commit('TOGGLE_OPENED', false)
|
store.commit('TOGGLE_OPENED', false)
|
||||||
|
document.getElementById('nav')!.classList.remove('z-50')
|
||||||
|
setTimeout(() => {
|
||||||
|
document.getElementById('slider')!.style.maxHeight = 'none'
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
|
||||||
|
const route = computed(() => store.state.route)
|
||||||
|
const isWindow = (loc: string) => {
|
||||||
|
if (loc === '') return route.value === "/"
|
||||||
|
else return route.value.includes(loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isWindow,
|
|
||||||
changeColorMode,
|
changeColorMode,
|
||||||
changeLanguage,
|
changeLanguage,
|
||||||
closeMenu
|
closeMenu,
|
||||||
|
opened: computed(() => store.state.opened),
|
||||||
|
isWindow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -146,11 +166,7 @@ export default defineComponent({
|
|||||||
@apply transform scale-140;
|
@apply transform scale-140;
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile:hover img {
|
.nav-link a {
|
||||||
@apply transform rotate-360;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-link a, .link-active a {
|
|
||||||
@apply duration-300 border-b-2 border-transparent;
|
@apply duration-300 border-b-2 border-transparent;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@@ -158,9 +174,13 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.link-active a {
|
||||||
|
@apply text-indigo-600;
|
||||||
|
}
|
||||||
|
|
||||||
.social-links a {
|
.social-links a {
|
||||||
svg {
|
svg {
|
||||||
@apply h-8 w-8 duration-300
|
@apply h-6 w-6 duration-300
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover svg {
|
&:hover svg {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
<g fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<path d="M3 12h18"/>
|
<path d="M3 12h18"/>
|
||||||
<path d="M3 6h18"/>
|
<path d="M3 6h18"/>
|
||||||
<path d="M3 18h18/"/>
|
<path d="M3 18h18"/>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
<svg v-else-if="type === 1" class="inline" width="2.5em" height="2.5em" viewBox="0 0 48 48" focusable="false">
|
<svg v-else-if="type === 1" class="inline" width="2.5em" height="2.5em" viewBox="0 0 48 48" focusable="false">
|
||||||
|
|||||||
@@ -7,6 +7,14 @@
|
|||||||
"begin_date": "04-2015",
|
"begin_date": "04-2015",
|
||||||
"end_date": "Today"
|
"end_date": "Today"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"slug": "bac",
|
||||||
|
"title": "formations.bac.title",
|
||||||
|
"description": "formations.bac.description",
|
||||||
|
"location": "France",
|
||||||
|
"begin_date": "09-2020",
|
||||||
|
"end_date": "07-2021 "
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"slug": "dnb",
|
"slug": "dnb",
|
||||||
"title": "formations.dnb.title",
|
"title": "formations.dnb.title",
|
||||||
@@ -14,13 +22,5 @@
|
|||||||
"location": "France",
|
"location": "France",
|
||||||
"begin_date": "09-2017",
|
"begin_date": "09-2017",
|
||||||
"end_date": "09-2018"
|
"end_date": "09-2018"
|
||||||
},
|
|
||||||
{
|
|
||||||
"slug": "bac",
|
|
||||||
"title": "formations.bac.title",
|
|
||||||
"description": "formations.bac.description",
|
|
||||||
"location": "France",
|
|
||||||
"begin_date": "09-2020",
|
|
||||||
"end_date": "Today"
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"slug": "ares",
|
"slug": "ares",
|
||||||
"title": "ares",
|
"title": "Ares",
|
||||||
"description": "works.ares",
|
"description": "works.ares",
|
||||||
"url": "https://arthurdanjou.fr",
|
"url": "https://arthurdanjou.fr",
|
||||||
"cover": "ares.png",
|
"cover": "ares.png",
|
||||||
|
|||||||
@@ -1,34 +1,46 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="relative">
|
||||||
<SideMenu />
|
<SideMenu />
|
||||||
|
<div class="relative w-full overflow-hidden">
|
||||||
<div
|
<div
|
||||||
class="z-50 relative top-0 left-0 w-full duration-500 h-1/2"
|
id="slider"
|
||||||
:class="{'opened': opened}"
|
class="relative xl:static shadow-2xl overflow-hidden transform transition-all duration-500"
|
||||||
:style="`max-height: ${height}px`"
|
:class="{'rounded-lg xl:rounded-none scale-90 md:scale-70 lg:scale-60 xl:scale-100 translate-x-9/12 sm:translate-x-4/12 lg:translate-x-3/12 xl:translate-x-0': opened}"
|
||||||
|
:style="opened ? `max-height: ${height}px` : 'max-height: none'"
|
||||||
|
:tabindex="opened ? -1 : 0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
@click.prevent="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}"
|
||||||
>
|
>
|
||||||
<div @click="closeMenu" class="z-50 bg-white dark:bg-black overflow-hidden overflow-x-hidden w-full min-w-screen" :class="{'cursor-pointer': opened}">
|
|
||||||
<Announcement />
|
<Announcement />
|
||||||
<Header />
|
<Header />
|
||||||
<Nuxt class="z-10 pt-16 lg:pt-24 content"/>
|
<Nuxt class="z-10 pt-16 lg:pt-24 content"/>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<MobileNavbar />
|
<MobileNavbar />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {computed, onMounted, ref, useStore} from "@nuxtjs/composition-api";
|
import {computed, onMounted, ref, useRouter, useStore} from "@nuxtjs/composition-api";
|
||||||
import {State} from "~/types/types";
|
import {State} from "~/types/types";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
setup() {
|
setup() {
|
||||||
const store = useStore<State>()
|
const store = useStore<State>()
|
||||||
|
const $router = useRouter()
|
||||||
|
|
||||||
const opened = computed(() => store.state.opened)
|
$router.afterEach(() => {
|
||||||
|
store.commit('SET_ROUTE', $router.currentRoute.path)
|
||||||
|
})
|
||||||
|
|
||||||
const closeMenu = () => {
|
const closeMenu = () => {
|
||||||
store.commit('TOGGLE_OPENED', false)
|
store.commit('TOGGLE_OPENED', false)
|
||||||
|
document.getElementById('nav')!.classList.remove('z-50')
|
||||||
}
|
}
|
||||||
|
|
||||||
const height = ref(0)
|
const height = ref(0)
|
||||||
@@ -37,16 +49,10 @@ export default {
|
|||||||
})
|
})
|
||||||
|
|
||||||
return {
|
return {
|
||||||
opened,
|
opened: computed(() => store.state.opened),
|
||||||
closeMenu,
|
closeMenu,
|
||||||
height
|
height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.opened {
|
|
||||||
@apply rounded-lg overflow-hidden overflow-x-hidden transform scale-90 translate-x-9/12 transition-all duration-500;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
export default {
|
import axios from "axios";
|
||||||
|
|
||||||
|
const translations = {
|
||||||
header: {
|
header: {
|
||||||
home: 'Home',
|
home: 'Home',
|
||||||
about: 'About',
|
about: 'About',
|
||||||
@@ -204,7 +206,8 @@ export default {
|
|||||||
placeholder: 'Your message...',
|
placeholder: 'Your message...',
|
||||||
sign: 'Sign',
|
sign: 'Sign',
|
||||||
error: 'Error while sending your message ❌',
|
error: 'Error while sending your message ❌',
|
||||||
success: 'Thank you for your message 😉'
|
success: 'Thank you for your message 😉',
|
||||||
|
at: 'at'
|
||||||
},
|
},
|
||||||
|
|
||||||
newsletter: {
|
newsletter: {
|
||||||
@@ -287,5 +290,24 @@ export default {
|
|||||||
ares: 'Ares is my personal website creating a single point of contact',
|
ares: 'Ares is my personal website creating a single point of contact',
|
||||||
erisium: 'Erisium is a french minecraft mini-game server.',
|
erisium: 'Erisium is a french minecraft mini-game server.',
|
||||||
linkyjs: 'LinkyJS is my custom and Open-Source url shortener'
|
linkyjs: 'LinkyJS is my custom and Open-Source url shortener'
|
||||||
|
},
|
||||||
|
|
||||||
|
loading: 'Loading...'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function () {
|
||||||
|
let informations = {}
|
||||||
|
const response = await axios.get('https://athena.arthurdanjou.fr/translations', {
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${process.env.API_TOKEN}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
response.data.translations.map(({ code, english }: any) => {
|
||||||
|
informations = { ...informations, [code]: english }
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
...informations,
|
||||||
|
...translations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
export default {
|
import axios from "axios";
|
||||||
|
import {Translation} from "~/types/types";
|
||||||
|
|
||||||
|
const translations = {
|
||||||
header: {
|
header: {
|
||||||
home: 'Accueil',
|
home: 'Accueil',
|
||||||
about: 'A Propos',
|
about: 'A Propos',
|
||||||
@@ -15,6 +18,10 @@ export default {
|
|||||||
close: 'Fermer le menu'
|
close: 'Fermer le menu'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
services: {
|
||||||
|
description: 'Je fourni tout ce dont vous avez besoin pour créer votre site internet parfait'
|
||||||
|
},
|
||||||
|
|
||||||
part: {
|
part: {
|
||||||
about: 'A propos',
|
about: 'A propos',
|
||||||
contact: 'Me contacter',
|
contact: 'Me contacter',
|
||||||
@@ -22,14 +29,16 @@ export default {
|
|||||||
blog: 'Mon blog',
|
blog: 'Mon blog',
|
||||||
env: 'Mon environnement',
|
env: 'Mon environnement',
|
||||||
guestbook: "Mon livre d'or",
|
guestbook: "Mon livre d'or",
|
||||||
newsletter: 'Ma newsletter'
|
newsletter: 'Ma newsletter',
|
||||||
|
services: 'Mes services'
|
||||||
},
|
},
|
||||||
|
|
||||||
footer: {
|
footer: {
|
||||||
credits: 'Développé et conçu avec ❤️ en utilisant',
|
description: 'Développeur Web et Logiciel, mais également étudiant en Mathématiques et en Physique. Je développe des sites internet',
|
||||||
credits_separator: 'par',
|
links: 'Liens rapides',
|
||||||
credits_separator_and: 'et',
|
credits: 'Développé avec',
|
||||||
copyrights: '© Copyright {date} - Tous droits réservés'
|
credits_separator: 'et',
|
||||||
|
copyrights: '© {date} Arthur Danjou - Tous droits réservés'
|
||||||
},
|
},
|
||||||
|
|
||||||
error: {
|
error: {
|
||||||
@@ -208,7 +217,8 @@ export default {
|
|||||||
placeholder: 'Votre message...',
|
placeholder: 'Votre message...',
|
||||||
sign: 'Signer',
|
sign: 'Signer',
|
||||||
error: "Erreur lors de l'envoi de votre message ❌",
|
error: "Erreur lors de l'envoi de votre message ❌",
|
||||||
success: 'Merci pour votre message 😉'
|
success: 'Merci pour votre message 😉',
|
||||||
|
at: 'à'
|
||||||
},
|
},
|
||||||
|
|
||||||
newsletter: {
|
newsletter: {
|
||||||
@@ -291,5 +301,24 @@ export default {
|
|||||||
ares: 'Ares est mon site personnel créant un point de contact unique.',
|
ares: 'Ares est mon site personnel créant un point de contact unique.',
|
||||||
erisium: 'Erisium est un serveur minecraft francophone de mini-jeux.',
|
erisium: 'Erisium est un serveur minecraft francophone de mini-jeux.',
|
||||||
linkyjs: "LinkyJS est mon raccourcisseur d'url personnalisé et Open-Source."
|
linkyjs: "LinkyJS est mon raccourcisseur d'url personnalisé et Open-Source."
|
||||||
|
},
|
||||||
|
|
||||||
|
loading: 'Chargement...'
|
||||||
|
}
|
||||||
|
|
||||||
|
export default async function () {
|
||||||
|
let informations = {}
|
||||||
|
const response = await axios.get('https://athena.arthurdanjou.fr/translations', {
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${process.env.API_TOKEN}`
|
||||||
|
}
|
||||||
|
})
|
||||||
|
response.data.translations.map(({ code, french }: any) => {
|
||||||
|
informations = { ...informations, [code]: french }
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
...informations,
|
||||||
|
...translations
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,19 +9,6 @@
|
|||||||
{{ $t('contact.why.description') }}
|
{{ $t('contact.why.description') }}
|
||||||
</h3>
|
</h3>
|
||||||
</section>
|
</section>
|
||||||
<section class="w-full lg:w-3/4 mb-10 mt-4 text-justify">
|
|
||||||
<h1 class="font-bold text-gray-700 text-xl md:text-3xl my-4 dark:text-gray-400">
|
|
||||||
{{ $t('contact.available.title') }}
|
|
||||||
</h1>
|
|
||||||
<h3 class="text-lg md:text-xl">
|
|
||||||
{{ $t('contact.available.description') }}
|
|
||||||
</h3>
|
|
||||||
<div class="text-lg md:text-xl my-4 text-indigo-600">
|
|
||||||
{{ $t('contact.available.start') }}
|
|
||||||
<span v-if="info && info.hiring.status && info.hiring.color" class="py-1 px-2 font-bold rounded-full m-0.5" :class="getColor">{{ $t('hiring.status.' + info.hiring.status) }}</span>
|
|
||||||
{{ $t('contact.available.end') }}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
<ContactForm class="w-full"/>
|
<ContactForm class="w-full"/>
|
||||||
</main>
|
</main>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<main v-if="projects" class="work flex flex-col items-center px-4 xl:px-32">
|
<main v-if="projects" class="flex flex-col items-center px-4 xl:px-32">
|
||||||
<PageTitle title="part.projects" />
|
<PageTitle title="part.projects" />
|
||||||
<h1 v-if="projects.length === 0" class="text-xl font-bold text-center my-8 w-full">{{ $t('projects.no_project') }}</h1>
|
<h1 v-if="projects.length === 0" class="text-xl font-bold text-center my-8 w-full">{{ $t('projects.no_project') }}</h1>
|
||||||
<div v-else class="flex flex-col justify-around items-center py-10 w-full">
|
<div v-else class="flex flex-col justify-around items-center py-10 w-full">
|
||||||
|
|||||||
18
src/pages/services.vue
Normal file
18
src/pages/services.vue
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<main class="flex flex-col items-center px-4 xl:px-32">
|
||||||
|
<PageTitle title="part.services" />
|
||||||
|
<p class="text-justify text-gray-700 dark:text-gray-400 text-xl my-8">{{ $t('services.description') }}</p>
|
||||||
|
</main>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import {defineComponent} from "@nuxtjs/composition-api";
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: "services"
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
2
src/plugins/main.ts
Executable file → Normal file
2
src/plugins/main.ts
Executable file → Normal file
@@ -1 +1 @@
|
|||||||
import 'windi.css'
|
import 'virtual:windi.css'
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
import {GetterTree, MutationTree} from "vuex";
|
import {GetterTree, MutationTree} from "vuex";
|
||||||
|
|
||||||
export const state = () => ({
|
export const state = () => ({
|
||||||
opened: false
|
opened: false,
|
||||||
|
route: '/'
|
||||||
})
|
})
|
||||||
|
|
||||||
export type RootState = ReturnType<typeof state>
|
export type RootState = ReturnType<typeof state>
|
||||||
|
|
||||||
export const getters: GetterTree<RootState, RootState> = {
|
export const getters: GetterTree<RootState, RootState> = {
|
||||||
opened: state => state.opened,
|
opened: state => state.opened,
|
||||||
|
route: state => state.route
|
||||||
}
|
}
|
||||||
|
|
||||||
export const mutations: MutationTree<RootState> = {
|
export const mutations: MutationTree<RootState> = {
|
||||||
TOGGLE_OPENED: (state, opened: boolean) => (state.opened = opened),
|
TOGGLE_OPENED: (state, opened: boolean) => (state.opened = opened),
|
||||||
|
SET_ROUTE: (state, route: string) => (state.route = route)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,9 @@
|
|||||||
"@nuxtjs/axios",
|
"@nuxtjs/axios",
|
||||||
"@nuxtjs/sentry",
|
"@nuxtjs/sentry",
|
||||||
"@nuxtjs/composition-api",
|
"@nuxtjs/composition-api",
|
||||||
"nuxt-i18n"
|
"@nuxtjs/i18n",
|
||||||
|
"@nuxtjs/color-mode",
|
||||||
|
"@nuxtjs/universal-storage"
|
||||||
] /* Type declaration files to be included in compilation. */,
|
] /* Type declaration files to be included in compilation. */,
|
||||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
|
||||||
|
|||||||
36
types/index.d.ts
vendored
36
types/index.d.ts
vendored
@@ -1,36 +0,0 @@
|
|||||||
import { NuxtAxiosInstance } from '@nuxtjs/axios'
|
|
||||||
import VueI18n, {IVueI18n} from "vue-i18n";
|
|
||||||
import {ColorModeInstance} from "@nuxtjs/color-mode/types/color-mode";
|
|
||||||
import {NuxtApp} from "@nuxt/types/app";
|
|
||||||
import {NuxtStorage} from "@nuxtjs/universal-storage";
|
|
||||||
import {NuxtOptionsRouter} from "@nuxt/types/config/router";
|
|
||||||
|
|
||||||
declare module 'vue/types/vue' {
|
|
||||||
|
|
||||||
interface Vue {
|
|
||||||
$axios: NuxtAxiosInstance,
|
|
||||||
i18n: VueI18n & IVueI18n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
declare module '@nuxt/types' {
|
|
||||||
|
|
||||||
interface NuxtAppOptions {
|
|
||||||
$axios: NuxtAxiosInstance,
|
|
||||||
i18n: VueI18n & IVueI18n
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Context {
|
|
||||||
$axios: NuxtAxiosInstance,
|
|
||||||
i18n: VueI18n & IVueI18n
|
|
||||||
$colorMode: ColorModeInstance,
|
|
||||||
app: NuxtApp,
|
|
||||||
$storage: NuxtStorage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module 'vuex/types/index' {
|
|
||||||
interface Store<S> {
|
|
||||||
$axios: NuxtAxiosInstance,
|
|
||||||
i18n: VueI18n & IVueI18n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -76,7 +76,15 @@ interface Translation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
opened: boolean
|
opened: boolean,
|
||||||
|
route: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export { Form, InfoData, Skill, Experience, Formation, Post, Tag, Project, GuestbookForm, NewsletterForm, Translation, State }
|
interface Announce {
|
||||||
|
color: string,
|
||||||
|
hover_color: string,
|
||||||
|
translation: Translation
|
||||||
|
file: null
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Form, InfoData, Skill, Experience, Formation, Post, Tag, Project, GuestbookForm, NewsletterForm, Translation, State, Announce }
|
||||||
|
|||||||
Reference in New Issue
Block a user