mirror of
https://github.com/ArthurDanjou/website.git
synced 2026-01-14 12:14:42 +01:00
@@ -3,20 +3,32 @@ const { data: announce } = await useFetch('/api/announcement')
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
function getColor() {
|
||||
return `bg-${appConfig.ui.primary}-500`
|
||||
return `bg-${appConfig.ui.primary}-500`
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="announce" class="w-container flex justify-center mt-8">
|
||||
<div class="relative">
|
||||
<h1 class="px-4 py-2 bg-white dark:bg-zinc-900 rounded-md border border-zinc-100 dark:border-zinc-300/10" v-html="announce.content" />
|
||||
<span class="absolute -top-0.5 -right-0.5 flex h-2 w-2">
|
||||
<span class="animate-ping absolute inline-flex h-full w-full rounded-full opacity-75" :class="getColor()" />
|
||||
<span class="relative inline-flex rounded-full h-2 w-2" :class="getColor()" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="announce"
|
||||
class="w-container flex justify-center mt-8"
|
||||
>
|
||||
<div class="relative">
|
||||
<h1
|
||||
class="px-4 py-2 bg-white dark:bg-zinc-900 rounded-md border border-zinc-100 dark:border-zinc-300/10"
|
||||
v-html="announce.content"
|
||||
/>
|
||||
<span class="absolute -top-0.5 -right-0.5 flex h-2 w-2">
|
||||
<span
|
||||
class="animate-ping absolute inline-flex h-full w-full rounded-full opacity-75"
|
||||
:class="getColor()"
|
||||
/>
|
||||
<span
|
||||
class="relative inline-flex rounded-full h-2 w-2"
|
||||
:class="getColor()"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -4,15 +4,15 @@ const points = useState(() => Array.from({ length: 25 }).fill(0).map(() => [Math
|
||||
const poly = computed(() => points.value.map(([x, y]) => `${x * 100}% ${y * 100}%`).join(', '))
|
||||
|
||||
function jumpVal(val: number) {
|
||||
return Math.random() > 0.5 ? val + (Math.random() - 0.5) / 2 : Math.random()
|
||||
return Math.random() > 0.5 ? val + (Math.random() - 0.5) / 2 : Math.random()
|
||||
}
|
||||
|
||||
let timeout: NodeJS.Timeout
|
||||
function jumpPoints() {
|
||||
for (let i = 0; i < points.value.length; i++)
|
||||
points.value[i] = [jumpVal(points.value[i][0]), jumpVal(points.value[i][1])]
|
||||
for (let i = 0; i < points.value.length; i++)
|
||||
points.value[i] = [jumpVal(points.value[i][0]), jumpVal(points.value[i][1])]
|
||||
|
||||
timeout = setTimeout(jumpPoints, Math.random() * 1000)
|
||||
timeout = setTimeout(jumpPoints, Math.random() * 1000)
|
||||
}
|
||||
|
||||
onMounted(() => jumpPoints())
|
||||
@@ -20,17 +20,17 @@ onUnmounted(() => clearTimeout(timeout))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ClientOnly>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="bg sm:mx-8 absolute inset-0 z-20 transform-gpu blur-3xl overflow-hidden"
|
||||
>
|
||||
<div
|
||||
class="aspect-[2] h-2/3 w-full bg-gradient-to-r from-[rgb(var(--color-primary-DEFAULT))] to-white/10 lg:opacity-30 xs:opacity-50"
|
||||
:style="{ 'clip-path': `polygon(${poly})` }"
|
||||
/>
|
||||
</div>
|
||||
</ClientOnly>
|
||||
<ClientOnly>
|
||||
<div
|
||||
aria-hidden="true"
|
||||
class="bg sm:mx-8 absolute inset-0 z-20 transform-gpu blur-3xl overflow-hidden"
|
||||
>
|
||||
<div
|
||||
class="aspect-[2] h-2/3 w-full bg-gradient-to-r from-[rgb(var(--color-primary-DEFAULT))] to-white/10 lg:opacity-30 xs:opacity-50"
|
||||
:style="{ 'clip-path': `polygon(${poly})` }"
|
||||
/>
|
||||
</div>
|
||||
</ClientOnly>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -3,37 +3,37 @@ const year = computed(() => new Date().getFullYear())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<footer class="w-full flex justify-center">
|
||||
<div class="w-full px-4 sm:px-6 lg:px-8 sm:mx-8 max-w-9xl py-4 flex justify-between bg-white dark:bg-zinc-900 border-t border-zinc-100 dark:border-zinc-300/10">
|
||||
<div class="w-full duration-300 text-center flex flex-col md:flex-row md:justify-between items-center gap-y-2">
|
||||
<p class="text-subtitle text-sm">
|
||||
© {{ year }} ArtDanjProduction
|
||||
</p>
|
||||
<div class="flex items-center">
|
||||
<p class="text-subtitle">
|
||||
Designed & Built by
|
||||
</p>
|
||||
<UButton
|
||||
color="primary"
|
||||
label="Arthur Danjou"
|
||||
target="_blank"
|
||||
to="https://twitter.com/arthurdanj"
|
||||
variant="link"
|
||||
/>
|
||||
</div>
|
||||
<p class="text-subtitle flex items-center">
|
||||
Made with
|
||||
<UButton
|
||||
color="green"
|
||||
icon="i-vscode-icons-file-type-nuxt"
|
||||
label="Nuxt 3"
|
||||
target="_blank"
|
||||
to="https://nuxt.com/"
|
||||
trailing
|
||||
variant="link"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
<footer class="w-full flex justify-center">
|
||||
<div class="w-full px-4 sm:px-6 lg:px-8 sm:mx-8 max-w-9xl py-4 flex justify-between bg-white dark:bg-zinc-900 border-t border-zinc-100 dark:border-zinc-300/10">
|
||||
<div class="w-full duration-300 text-center flex flex-col md:flex-row md:justify-between items-center gap-y-2">
|
||||
<p class="text-subtitle text-sm">
|
||||
© {{ year }} ArtDanjProduction
|
||||
</p>
|
||||
<div class="flex items-center">
|
||||
<p class="text-subtitle">
|
||||
Designed & Built by
|
||||
</p>
|
||||
<UButton
|
||||
color="primary"
|
||||
label="Arthur Danjou"
|
||||
target="_blank"
|
||||
to="https://twitter.com/arthurdanj"
|
||||
variant="link"
|
||||
/>
|
||||
</div>
|
||||
<p class="text-subtitle flex items-center">
|
||||
Made with
|
||||
<UButton
|
||||
color="green"
|
||||
icon="i-vscode-icons-file-type-nuxt"
|
||||
label="Nuxt 3"
|
||||
target="_blank"
|
||||
to="https://nuxt.com/"
|
||||
trailing
|
||||
variant="link"
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: 'Uses Section title',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: 'Uses Section title',
|
||||
},
|
||||
})
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
@@ -12,22 +12,22 @@ const getColor = computed(() => `text-${appConfig.ui.primary}-500`)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<section class="md:border-l md:border-zinc-100 md:pl-6 md:dark:border-zinc-700/40 mb-24 px-4">
|
||||
<div class="grid max-w-3xl grid-cols-1 items-baseline gap-y-8 md:grid-cols-4">
|
||||
<h2
|
||||
:class="getColor"
|
||||
class="relative text-sm font-semibold pl-3.5"
|
||||
>
|
||||
<span class="md:hidden absolute inset-y-0 left-0 flex items-center">
|
||||
<span class="h-4 w-0.5 rounded-full bg-zinc-200 dark:bg-zinc-500" />
|
||||
</span>
|
||||
{{ title }}
|
||||
</h2>
|
||||
<div class="md:col-span-3">
|
||||
<ul class="space-y-8">
|
||||
<slot />
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section class="md:border-l md:border-zinc-100 md:pl-6 md:dark:border-zinc-700/40 mb-24 px-4">
|
||||
<div class="grid max-w-3xl grid-cols-1 items-baseline gap-y-8 md:grid-cols-4">
|
||||
<h2
|
||||
:class="getColor"
|
||||
class="relative text-sm font-semibold pl-3.5"
|
||||
>
|
||||
<span class="md:hidden absolute inset-y-0 left-0 flex items-center">
|
||||
<span class="h-4 w-0.5 rounded-full bg-zinc-200 dark:bg-zinc-500" />
|
||||
</span>
|
||||
{{ title }}
|
||||
</h2>
|
||||
<div class="md:col-span-3">
|
||||
<ul class="space-y-8">
|
||||
<slot />
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
default: 'Uses Slot title',
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: 'Uses Slot title',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<li class="group relative flex flex-col items-start">
|
||||
<h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<p class="relative z-10 mt-2 text-sm text-zinc-600 dark:text-zinc-400">
|
||||
<slot />
|
||||
</p>
|
||||
</li>
|
||||
<li class="group relative flex flex-col items-start">
|
||||
<h3 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">
|
||||
{{ title }}
|
||||
</h3>
|
||||
<p class="relative z-10 mt-2 text-sm text-zinc-600 dark:text-zinc-400">
|
||||
<slot />
|
||||
</p>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
href: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
target: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
required: false,
|
||||
},
|
||||
href: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
target: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
required: false,
|
||||
},
|
||||
})
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NuxtLink
|
||||
:href="href"
|
||||
:target="target"
|
||||
class="border-b border-zinc-200 dark:border-zinc-700/70 duration-300"
|
||||
:class="`hover:border-${appConfig.ui.primary}-500 dark:hover:border-${appConfig.ui.primary}-500`"
|
||||
>
|
||||
<slot />
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
:href="href"
|
||||
:target="target"
|
||||
class="border-b border-zinc-200 dark:border-zinc-700/70 duration-300"
|
||||
:class="`hover:border-${appConfig.ui.primary}-500 dark:hover:border-${appConfig.ui.primary}-500`"
|
||||
>
|
||||
<slot />
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, useRuntimeConfig } from '#imports'
|
||||
import {computed, useRuntimeConfig} from '#imports'
|
||||
|
||||
const props = defineProps<{ id?: string }>()
|
||||
|
||||
@@ -8,14 +8,14 @@ const generate = computed(() => props.id && headings?.anchorLinks?.h2)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<h2 :id="id">
|
||||
<a
|
||||
v-if="id && generate"
|
||||
:href="`#${id}`"
|
||||
class="pl-6 border-l border-zinc-200 dark:border-zinc-700/70 duration-300"
|
||||
>
|
||||
<slot />
|
||||
</a>
|
||||
<slot v-else />
|
||||
</h2>
|
||||
<h2 :id="id">
|
||||
<a
|
||||
v-if="id && generate"
|
||||
:href="`#${id}`"
|
||||
class="pl-6 border-l border-zinc-200 dark:border-zinc-700/70 duration-300"
|
||||
>
|
||||
<slot />
|
||||
</a>
|
||||
<slot v-else />
|
||||
</h2>
|
||||
</template>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
<template>
|
||||
<header class="z-30 sticky top-0 left-0 flex justify-center w-full">
|
||||
<div class="w-full px-4 sm:px-6 lg:px-8 sm:mx-8 max-w-9xl py-4 grid grid-cols-2 lg:grid-cols-3 bg-white dark:bg-zinc-900 border-b border-zinc-100 dark:border-zinc-300/10">
|
||||
<Logo />
|
||||
<div class="hidden grow lg:flex justify-center">
|
||||
<NavBar />
|
||||
</div>
|
||||
<div class="flex justify-end gap-2 items-center">
|
||||
<ThemePicker />
|
||||
<MobileNavBar />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<header class="z-30 sticky top-0 left-0 flex justify-center w-full">
|
||||
<div class="w-full px-4 sm:px-6 lg:px-8 sm:mx-8 max-w-9xl py-4 grid grid-cols-2 lg:grid-cols-3 bg-white dark:bg-zinc-900 border-b border-zinc-100 dark:border-zinc-300/10">
|
||||
<Logo />
|
||||
<div class="hidden grow lg:flex justify-center">
|
||||
<NavBar />
|
||||
</div>
|
||||
<div class="flex justify-end gap-2 items-center">
|
||||
<ThemePicker />
|
||||
<MobileNavBar />
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
@@ -3,26 +3,26 @@ const appConfig = useAppConfig()
|
||||
const getTextColor = computed(() => `text-${appConfig.ui.primary}-500`)
|
||||
|
||||
function getGroupColor() {
|
||||
return `group-hover:text-${appConfig.ui.primary}-500`
|
||||
return `group-hover:text-${appConfig.ui.primary}-500`
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NuxtLink
|
||||
class="flex gap-1 items-center rounded-xl group text-xl !bg-transparent !dark:bg-transparent"
|
||||
to="/"
|
||||
>
|
||||
<span
|
||||
:class="getTextColor"
|
||||
class="font-black group-hover:text-black dark:group-hover:text-white duration-300"
|
||||
>Arthur</span>
|
||||
<span
|
||||
:class="getGroupColor()"
|
||||
class="font-bold text-gray-300 dark:text-neutral-600 duration-300"
|
||||
>/</span>
|
||||
<span
|
||||
:class="getTextColor"
|
||||
class="font-black group-hover:text-black dark:group-hover:text-white duration-300"
|
||||
>Danjou</span>
|
||||
</NuxtLink>
|
||||
<NuxtLink
|
||||
class="flex gap-1 items-center rounded-xl group text-xl !bg-transparent !dark:bg-transparent"
|
||||
to="/"
|
||||
>
|
||||
<span
|
||||
:class="getTextColor"
|
||||
class="font-black group-hover:text-black dark:group-hover:text-white duration-300"
|
||||
>Arthur</span>
|
||||
<span
|
||||
:class="getGroupColor()"
|
||||
class="font-bold text-gray-300 dark:text-neutral-600 duration-300"
|
||||
>/</span>
|
||||
<span
|
||||
:class="getTextColor"
|
||||
class="font-black group-hover:text-black dark:group-hover:text-white duration-300"
|
||||
>Danjou</span>
|
||||
</NuxtLink>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
import { navs } from '~~/types'
|
||||
import {navs} from '~~/types'
|
||||
|
||||
const isOpenSidebar = ref(false)
|
||||
const isOpenModal = ref(false)
|
||||
@@ -9,171 +9,171 @@ router.afterEach(() => isOpenSidebar.value = false)
|
||||
|
||||
const route = useRoute()
|
||||
function isRoute(path: string) {
|
||||
return route.path === path
|
||||
return route.path === path
|
||||
}
|
||||
|
||||
function openModal() {
|
||||
isOpenSidebar.value = false
|
||||
isOpenModal.value = true
|
||||
isOpenSidebar.value = false
|
||||
isOpenModal.value = true
|
||||
}
|
||||
|
||||
const { copy, copied } = useClipboard({ source: 'arthurdanjou@outlook.fr', copiedDuring: 3000 })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="lg:hidden">
|
||||
<div class="p-1 rounded-md bg-black/5 text-sm font-medium text-zinc-700 dark:bg-zinc-800/90 dark:text-zinc-300">
|
||||
<UButton
|
||||
variant="ghost"
|
||||
color="primary"
|
||||
size="sm"
|
||||
icon="i-ph-list-bold"
|
||||
@click="isOpenSidebar = true"
|
||||
/>
|
||||
</div>
|
||||
<div class="lg:hidden">
|
||||
<div class="p-1 rounded-md bg-black/5 text-sm font-medium text-zinc-700 dark:bg-zinc-800/90 dark:text-zinc-300">
|
||||
<UButton
|
||||
variant="ghost"
|
||||
color="primary"
|
||||
size="sm"
|
||||
icon="i-ph-list-bold"
|
||||
@click="isOpenSidebar = true"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<USlideover v-model="isOpenSidebar">
|
||||
<UCard
|
||||
:ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }"
|
||||
class="flex flex-col flex-1"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<Logo />
|
||||
<UButton
|
||||
size="md"
|
||||
icon="i-ic-round-close"
|
||||
:ui="{ rounded: 'rounded-full' }"
|
||||
@click.prevent="isOpenSidebar = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<USlideover v-model="isOpenSidebar">
|
||||
<UCard
|
||||
:ui="{ body: { base: 'flex-1' }, ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }"
|
||||
class="flex flex-col flex-1"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex justify-between items-center">
|
||||
<Logo />
|
||||
<UButton
|
||||
size="md"
|
||||
icon="i-ic-round-close"
|
||||
:ui="{ rounded: 'rounded-full' }"
|
||||
@click.prevent="isOpenSidebar = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="flex flex-col space-y-2">
|
||||
<div
|
||||
v-for="nav in navs"
|
||||
:key="nav.label"
|
||||
class="w-full"
|
||||
>
|
||||
<UButton
|
||||
v-if="nav.to"
|
||||
size="sm"
|
||||
class="w-full"
|
||||
:variant="isRoute(nav.to) ? 'solid' : 'ghost'"
|
||||
color="primary"
|
||||
:to="nav.to"
|
||||
:icon="nav.icon"
|
||||
:label="nav.label"
|
||||
/>
|
||||
<UButton
|
||||
v-else
|
||||
class="w-full"
|
||||
size="sm"
|
||||
color="primary"
|
||||
variant="ghost"
|
||||
:icon="nav.icon"
|
||||
:label="nav.label"
|
||||
@click.prevent="openModal()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col space-y-2">
|
||||
<div
|
||||
v-for="nav in navs"
|
||||
:key="nav.label"
|
||||
class="w-full"
|
||||
>
|
||||
<UButton
|
||||
v-if="nav.to"
|
||||
size="sm"
|
||||
class="w-full"
|
||||
:variant="isRoute(nav.to) ? 'solid' : 'ghost'"
|
||||
color="primary"
|
||||
:to="nav.to"
|
||||
:icon="nav.icon"
|
||||
:label="nav.label"
|
||||
/>
|
||||
<UButton
|
||||
v-else
|
||||
class="w-full"
|
||||
size="sm"
|
||||
color="primary"
|
||||
variant="ghost"
|
||||
:icon="nav.icon"
|
||||
:label="nav.label"
|
||||
@click.prevent="openModal()"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
Footer
|
||||
</template>
|
||||
</UCard>
|
||||
</USlideover>
|
||||
<UModal v-model="isOpenModal">
|
||||
<UCard class="p-4">
|
||||
<div>
|
||||
<div class="mb-8 flex justify-between items-center">
|
||||
<h1 class="text-xl font-bold">
|
||||
Contact me
|
||||
</h1>
|
||||
<UButton
|
||||
icon="i-akar-icons-cross"
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
@click.prevent="isOpenModal = false"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col space-y-6">
|
||||
<div class="flex flex-col md:flex-row justify-between md:items-center space-y-2">
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-sm">
|
||||
Email
|
||||
</h3>
|
||||
<p class="text-xs text-subtitle">
|
||||
arthurdanjou@outlook.fr
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<UButtonGroup
|
||||
orientation="horizontal"
|
||||
size="sm"
|
||||
>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-mdi-note-edit-outline"
|
||||
label="Compose"
|
||||
to="mailto:arthurdanjou@outlook.fr"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
v-if="copied"
|
||||
color="green"
|
||||
icon="i-mdi-content-copy"
|
||||
label="Copied"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
v-else
|
||||
color="gray"
|
||||
icon="i-mdi-content-copy"
|
||||
label="Copy"
|
||||
variant="solid"
|
||||
@click.prevent="copy()"
|
||||
/>
|
||||
</UButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
<UDivider label="OR" />
|
||||
<div class="flex flex-col md:flex-row justify-between md:items-center space-y-2">
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-sm">
|
||||
Get in touch
|
||||
</h3>
|
||||
<p class="text-xs text-subtitle">
|
||||
I'm most active on Twitter
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<UButtonGroup
|
||||
orientation="horizontal"
|
||||
size="sm"
|
||||
>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-ph-github-logo-bold"
|
||||
label="Github"
|
||||
target="_blank"
|
||||
to="https://github.com/ArthurDanjou"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-ph-twitter-logo-bold"
|
||||
label="Twitter"
|
||||
target="_blank"
|
||||
to="https://twitter.com/ArthurDanj"
|
||||
variant="solid"
|
||||
/>
|
||||
</UButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</UCard>
|
||||
</UModal>
|
||||
</div>
|
||||
<template #footer>
|
||||
Footer
|
||||
</template>
|
||||
</UCard>
|
||||
</USlideover>
|
||||
<UModal v-model="isOpenModal">
|
||||
<UCard class="p-4">
|
||||
<div>
|
||||
<div class="mb-8 flex justify-between items-center">
|
||||
<h1 class="text-xl font-bold">
|
||||
Contact me
|
||||
</h1>
|
||||
<UButton
|
||||
icon="i-akar-icons-cross"
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
@click.prevent="isOpenModal = false"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col space-y-6">
|
||||
<div class="flex flex-col md:flex-row justify-between md:items-center space-y-2">
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-sm">
|
||||
Email
|
||||
</h3>
|
||||
<p class="text-xs text-subtitle">
|
||||
arthurdanjou@outlook.fr
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<UButtonGroup
|
||||
orientation="horizontal"
|
||||
size="sm"
|
||||
>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-mdi-note-edit-outline"
|
||||
label="Compose"
|
||||
to="mailto:arthurdanjou@outlook.fr"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
v-if="copied"
|
||||
color="green"
|
||||
icon="i-mdi-content-copy"
|
||||
label="Copied"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
v-else
|
||||
color="gray"
|
||||
icon="i-mdi-content-copy"
|
||||
label="Copy"
|
||||
variant="solid"
|
||||
@click.prevent="copy()"
|
||||
/>
|
||||
</UButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
<UDivider label="OR" />
|
||||
<div class="flex flex-col md:flex-row justify-between md:items-center space-y-2">
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-sm">
|
||||
Get in touch
|
||||
</h3>
|
||||
<p class="text-xs text-subtitle">
|
||||
I'm most active on Twitter
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<UButtonGroup
|
||||
orientation="horizontal"
|
||||
size="sm"
|
||||
>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-ph-github-logo-bold"
|
||||
label="Github"
|
||||
target="_blank"
|
||||
to="https://github.com/ArthurDanjou"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-ph-twitter-logo-bold"
|
||||
label="Twitter"
|
||||
target="_blank"
|
||||
to="https://twitter.com/ArthurDanj"
|
||||
variant="solid"
|
||||
/>
|
||||
</UButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</UCard>
|
||||
</UModal>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { otherTab } from '~~/types'
|
||||
import {otherTab} from '~~/types'
|
||||
|
||||
const route = useRoute()
|
||||
const isOpenModal = ref(false)
|
||||
@@ -8,163 +8,163 @@ const { copy, copied } = useClipboard({ source: 'arthurdanjou@outlook.fr', copie
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<nav class="hidden lg:block z-50">
|
||||
<div class="flex items-center h-10 rounded-md p-1 gap-1 relative bg-black/5 text-sm font-medium text-zinc-700 dark:bg-zinc-800/90 dark:text-zinc-300">
|
||||
<UButton
|
||||
:class="{ 'link-active': route.path === '/' }"
|
||||
color="white"
|
||||
size="sm"
|
||||
to="/"
|
||||
variant="ghost"
|
||||
>
|
||||
Home
|
||||
</UButton>
|
||||
<UButton
|
||||
:class="{ 'link-active': route.path.includes('/about') }"
|
||||
color="white"
|
||||
size="sm"
|
||||
to="/about"
|
||||
variant="ghost"
|
||||
>
|
||||
About
|
||||
</UButton>
|
||||
<!-- <UButton to="/writing" size="sm" variant="ghost" color="white" :class="{ 'link-active': route.path.includes('/writing') }">
|
||||
<nav class="hidden lg:block z-50">
|
||||
<div class="flex items-center h-10 rounded-md p-1 gap-1 relative bg-black/5 text-sm font-medium text-zinc-700 dark:bg-zinc-800/90 dark:text-zinc-300">
|
||||
<UButton
|
||||
:class="{ 'link-active': route.path === '/' }"
|
||||
color="white"
|
||||
size="sm"
|
||||
to="/"
|
||||
variant="ghost"
|
||||
>
|
||||
Home
|
||||
</UButton>
|
||||
<UButton
|
||||
:class="{ 'link-active': route.path.includes('/about') }"
|
||||
color="white"
|
||||
size="sm"
|
||||
to="/about"
|
||||
variant="ghost"
|
||||
>
|
||||
About
|
||||
</UButton>
|
||||
<!-- <UButton to="/writing" size="sm" variant="ghost" color="white" :class="{ 'link-active': route.path.includes('/writing') }">
|
||||
Articles
|
||||
</UButton> -->
|
||||
<UButton
|
||||
:class="{ 'link-active': route.path.includes('/work') }"
|
||||
color="white"
|
||||
size="sm"
|
||||
to="/work"
|
||||
variant="ghost"
|
||||
>
|
||||
Projects
|
||||
</UButton>
|
||||
<UButton
|
||||
:class="{ 'link-active': route.path.includes('/uses') }"
|
||||
color="white"
|
||||
size="sm"
|
||||
to="/uses"
|
||||
variant="ghost"
|
||||
>
|
||||
Uses
|
||||
</UButton>
|
||||
<UDropdown
|
||||
:items="otherTab"
|
||||
:popper="{ placement: 'bottom' }"
|
||||
mode="hover"
|
||||
>
|
||||
<UButton
|
||||
class="duration-300"
|
||||
color="white"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
>
|
||||
Other
|
||||
</UButton>
|
||||
</UDropdown>
|
||||
<UButton
|
||||
color="white"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
@click="isOpenModal = true"
|
||||
>
|
||||
Contact
|
||||
</UButton>
|
||||
</div>
|
||||
<UModal v-model="isOpenModal">
|
||||
<UCard class="p-4">
|
||||
<div>
|
||||
<div class="mb-8 flex justify-between items-center">
|
||||
<h1 class="text-xl font-bold">
|
||||
Contact me
|
||||
</h1>
|
||||
<UButton
|
||||
icon="i-akar-icons-cross"
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
@click.prevent="isOpenModal = false"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col space-y-6">
|
||||
<div class="flex flex-col md:flex-row justify-between md:items-center space-y-2">
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-sm">
|
||||
Email
|
||||
</h3>
|
||||
<p class="text-xs text-subtitle">
|
||||
arthurdanjou@outlook.fr
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<UButtonGroup
|
||||
orientation="horizontal"
|
||||
size="sm"
|
||||
>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-mdi-note-edit-outline"
|
||||
label="Compose"
|
||||
to="mailto:arthurdanjou@outlook.fr"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
v-if="copied"
|
||||
color="green"
|
||||
icon="i-mdi-content-copy"
|
||||
label="Copied"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
v-else
|
||||
color="gray"
|
||||
icon="i-mdi-content-copy"
|
||||
label="Copy"
|
||||
variant="solid"
|
||||
@click.prevent="copy()"
|
||||
/>
|
||||
</UButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
<UDivider label="OR" />
|
||||
<div class="flex flex-col md:flex-row justify-between md:items-center space-y-2">
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-sm">
|
||||
Get in touch
|
||||
</h3>
|
||||
<p class="text-xs text-subtitle">
|
||||
I'm most active on Twitter
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<UButtonGroup
|
||||
orientation="horizontal"
|
||||
size="sm"
|
||||
>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-ph-github-logo-bold"
|
||||
label="Github"
|
||||
target="_blank"
|
||||
to="https://github.com/ArthurDanjou"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-ph-twitter-logo-bold"
|
||||
label="Twitter"
|
||||
target="_blank"
|
||||
to="https://twitter.com/ArthurDanj"
|
||||
variant="solid"
|
||||
/>
|
||||
</UButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</UCard>
|
||||
</UModal>
|
||||
</nav>
|
||||
<UButton
|
||||
:class="{ 'link-active': route.path.includes('/work') }"
|
||||
color="white"
|
||||
size="sm"
|
||||
to="/work"
|
||||
variant="ghost"
|
||||
>
|
||||
Projects
|
||||
</UButton>
|
||||
<UButton
|
||||
:class="{ 'link-active': route.path.includes('/uses') }"
|
||||
color="white"
|
||||
size="sm"
|
||||
to="/uses"
|
||||
variant="ghost"
|
||||
>
|
||||
Uses
|
||||
</UButton>
|
||||
<UDropdown
|
||||
:items="otherTab"
|
||||
:popper="{ placement: 'bottom' }"
|
||||
mode="hover"
|
||||
>
|
||||
<UButton
|
||||
class="duration-300"
|
||||
color="white"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
>
|
||||
Other
|
||||
</UButton>
|
||||
</UDropdown>
|
||||
<UButton
|
||||
color="white"
|
||||
size="sm"
|
||||
variant="ghost"
|
||||
@click="isOpenModal = true"
|
||||
>
|
||||
Contact
|
||||
</UButton>
|
||||
</div>
|
||||
<UModal v-model="isOpenModal">
|
||||
<UCard class="p-4">
|
||||
<div>
|
||||
<div class="mb-8 flex justify-between items-center">
|
||||
<h1 class="text-xl font-bold">
|
||||
Contact me
|
||||
</h1>
|
||||
<UButton
|
||||
icon="i-akar-icons-cross"
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
@click.prevent="isOpenModal = false"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex flex-col space-y-6">
|
||||
<div class="flex flex-col md:flex-row justify-between md:items-center space-y-2">
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-sm">
|
||||
Email
|
||||
</h3>
|
||||
<p class="text-xs text-subtitle">
|
||||
arthurdanjou@outlook.fr
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<UButtonGroup
|
||||
orientation="horizontal"
|
||||
size="sm"
|
||||
>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-mdi-note-edit-outline"
|
||||
label="Compose"
|
||||
to="mailto:arthurdanjou@outlook.fr"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
v-if="copied"
|
||||
color="green"
|
||||
icon="i-mdi-content-copy"
|
||||
label="Copied"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
v-else
|
||||
color="gray"
|
||||
icon="i-mdi-content-copy"
|
||||
label="Copy"
|
||||
variant="solid"
|
||||
@click.prevent="copy()"
|
||||
/>
|
||||
</UButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
<UDivider label="OR" />
|
||||
<div class="flex flex-col md:flex-row justify-between md:items-center space-y-2">
|
||||
<div class="flex flex-col">
|
||||
<h3 class="text-sm">
|
||||
Get in touch
|
||||
</h3>
|
||||
<p class="text-xs text-subtitle">
|
||||
I'm most active on Twitter
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<UButtonGroup
|
||||
orientation="horizontal"
|
||||
size="sm"
|
||||
>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-ph-github-logo-bold"
|
||||
label="Github"
|
||||
target="_blank"
|
||||
to="https://github.com/ArthurDanjou"
|
||||
variant="solid"
|
||||
/>
|
||||
<UButton
|
||||
color="gray"
|
||||
icon="i-ph-twitter-logo-bold"
|
||||
label="Twitter"
|
||||
target="_blank"
|
||||
to="https://twitter.com/ArthurDanj"
|
||||
variant="solid"
|
||||
/>
|
||||
</UButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</UCard>
|
||||
</UModal>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import {useColorStore} from '~/store/color'
|
||||
import {ColorsTheme} from '~~/types'
|
||||
import { useColorStore } from '~/store/color'
|
||||
import { ColorsTheme } from '~~/types'
|
||||
|
||||
const colors = Object.values(ColorsTheme)
|
||||
|
||||
@@ -9,80 +9,80 @@ const { getColor, setColor } = useColorStore()
|
||||
const colorMode = useColorMode()
|
||||
const isDark = ref(colorMode.value === 'dark')
|
||||
watch(isDark, () => {
|
||||
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
|
||||
colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UPopover
|
||||
mode="hover"
|
||||
:ui="{
|
||||
background: 'bg-white dark:bg-stone-900',
|
||||
ring: 'ring-1 ring-gray-200 dark:ring-stone-800',
|
||||
container: 'z-30',
|
||||
}"
|
||||
>
|
||||
<template #default="{ open }">
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
square
|
||||
size="lg"
|
||||
:class="[open && 'bg-gray-50 dark:bg-gray-800']"
|
||||
aria-label="Color picker"
|
||||
>
|
||||
<UIcon
|
||||
class="w-5 h-5 text-primary-500 dark:text-primary-400"
|
||||
name="i-ph-paint-brush-bold"
|
||||
/>
|
||||
</UButton>
|
||||
</template>
|
||||
<UPopover
|
||||
mode="hover"
|
||||
:ui="{
|
||||
background: 'bg-white dark:bg-stone-900',
|
||||
ring: 'ring-1 ring-gray-200 dark:ring-stone-800',
|
||||
container: 'z-30',
|
||||
}"
|
||||
>
|
||||
<template #default="{ open }">
|
||||
<UButton
|
||||
color="gray"
|
||||
variant="ghost"
|
||||
square
|
||||
size="lg"
|
||||
:class="[open && 'bg-gray-50 dark:bg-gray-800']"
|
||||
aria-label="Color picker"
|
||||
>
|
||||
<UIcon
|
||||
class="w-5 h-5 text-primary-500 dark:text-primary-400"
|
||||
name="i-ph-paint-brush-bold"
|
||||
/>
|
||||
</UButton>
|
||||
</template>
|
||||
|
||||
<template #panel>
|
||||
<div class="p-2">
|
||||
<div class="grid grid-cols-5 gap-px">
|
||||
<UTooltip
|
||||
v-for="color in colors"
|
||||
:key="color"
|
||||
:open-delay="500"
|
||||
:text="color"
|
||||
class="capitalize"
|
||||
>
|
||||
<UButton
|
||||
color="gray"
|
||||
square
|
||||
:ui="{
|
||||
color: {
|
||||
white: {
|
||||
solid: 'ring-0 bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800',
|
||||
ghost: 'hover:bg-gray-50 dark:hover:bg-gray-800/50',
|
||||
},
|
||||
},
|
||||
}"
|
||||
:variant="color === getColor ? 'solid' : 'ghost'"
|
||||
@click.stop.prevent="setColor(color)"
|
||||
>
|
||||
<span
|
||||
:class="`bg-${color}-500/80 border-${color}-500`"
|
||||
class="flex items-center justify-center w-3 h-3 rounded-full border text-white"
|
||||
>
|
||||
<UIcon
|
||||
v-if="color === getColor"
|
||||
name="i-ic-round-check"
|
||||
/>
|
||||
</span>
|
||||
</UButton>
|
||||
</UTooltip>
|
||||
</div>
|
||||
<UDivider class="my-2" />
|
||||
<div>
|
||||
<UToggle
|
||||
v-model="isDark"
|
||||
on-icon="i-heroicons-moon-20-solid"
|
||||
off-icon="i-heroicons-sun-20-solid"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UPopover>
|
||||
<template #panel>
|
||||
<div class="p-2">
|
||||
<div class="grid grid-cols-5 gap-px">
|
||||
<UTooltip
|
||||
v-for="color in colors"
|
||||
:key="color"
|
||||
:open-delay="500"
|
||||
:text="color"
|
||||
class="capitalize"
|
||||
>
|
||||
<UButton
|
||||
color="gray"
|
||||
square
|
||||
:ui="{
|
||||
color: {
|
||||
white: {
|
||||
solid: 'ring-0 bg-gray-100 dark:bg-gray-800 hover:bg-gray-100 dark:hover:bg-gray-800',
|
||||
ghost: 'hover:bg-gray-50 dark:hover:bg-gray-800/50',
|
||||
},
|
||||
},
|
||||
}"
|
||||
:variant="color === getColor ? 'solid' : 'ghost'"
|
||||
@click.stop.prevent="setColor(color)"
|
||||
>
|
||||
<span
|
||||
:class="`bg-${color}-500/80 border-${color}-500`"
|
||||
class="flex items-center justify-center w-3 h-3 rounded-full border text-white"
|
||||
>
|
||||
<UIcon
|
||||
v-if="color === getColor"
|
||||
name="i-ic-round-check"
|
||||
/>
|
||||
</span>
|
||||
</UButton>
|
||||
</UTooltip>
|
||||
</div>
|
||||
<UDivider class="my-2" />
|
||||
<div>
|
||||
<UToggle
|
||||
v-model="isDark"
|
||||
on-icon="i-heroicons-moon-20-solid"
|
||||
off-icon="i-heroicons-sun-20-solid"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UPopover>
|
||||
</template>
|
||||
|
||||
@@ -5,100 +5,100 @@ const { data: activity, refresh } = await useAsyncData<Activity>('activity', ()
|
||||
const codingActivity = computed(() => activity.value!.data.activities.filter(activity => IDEs.some(ide => ide.name === activity.name))[0])
|
||||
|
||||
function formatDate(date: number) {
|
||||
return `${useDateFormat(date, 'DD MMM YYYY').value} at ${useDateFormat(date, 'HH:mm:ss').value}`
|
||||
return `${useDateFormat(date, 'DD MMM YYYY').value} at ${useDateFormat(date, 'HH:mm:ss').value}`
|
||||
}
|
||||
|
||||
const CardUi = {
|
||||
footer: { padding: 'px-4 py-2' },
|
||||
body: { base: 'h-full flex items-center' },
|
||||
footer: { padding: 'px-4 py-2' },
|
||||
body: { base: 'h-full flex items-center' },
|
||||
}
|
||||
|
||||
useIntervalFn(async () => await refresh(), 5000)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UCard
|
||||
:ui="CardUi"
|
||||
class="flex flex-col justify-between"
|
||||
>
|
||||
<div
|
||||
v-if="activity && activity.data.activities"
|
||||
class="flex items-center gap-x-4"
|
||||
>
|
||||
<p
|
||||
class="uppercase tracking-widest text-sm"
|
||||
:style="{ writingMode: 'vertical-rl', textOrientation: 'sideways' }"
|
||||
>
|
||||
Activity
|
||||
</p>
|
||||
<div v-if="codingActivity">
|
||||
<div class="flex gap-4 items-center">
|
||||
<UIcon
|
||||
class="h-10 w-10"
|
||||
:name="IDEs.find(ide => ide.name === codingActivity.name)!.icon"
|
||||
/>
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h1>{{ codingActivity.name }}</h1>
|
||||
<UTooltip :text="codingActivity.details === 'Idling' ? 'I\'m sleeping 😴' : 'I\'m online 👋'">
|
||||
<div
|
||||
:class="codingActivity.details === 'Idling' ? 'bg-amber-500' : 'bg-green-500'"
|
||||
class="h-3 w-3 inline-flex rounded-full cursor-pointer"
|
||||
/>
|
||||
</UTooltip>
|
||||
</div>
|
||||
<h3 v-if="codingActivity.details === 'Idling'">
|
||||
I'm Idling on my computer
|
||||
</h3>
|
||||
<h3 v-else>
|
||||
{{ codingActivity.details }} - {{ codingActivity.state }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="text-subtitle"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<h1>I'm currently offline</h1>
|
||||
<UTooltip text="I'm offline 🫥">
|
||||
<div class="h-3 w-3 inline-flex rounded-full bg-red-500" />
|
||||
</UTooltip>
|
||||
</div>
|
||||
<h3>Come back later to see what I'm doing</h3>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex items-center justify-end w-full">
|
||||
<ClientOnly>
|
||||
<p
|
||||
v-if="codingActivity"
|
||||
class="text-subtitle text-xs w-1/2"
|
||||
>
|
||||
Started {{ useTimeAgo(codingActivity.timestamps.start).value }}, the {{ formatDate(codingActivity.timestamps.start) }}
|
||||
</p>
|
||||
</ClientOnly>
|
||||
<div class="flex items-center space-x-1 w-1/2 justify-end">
|
||||
<p class="text-subtitle text-xs">
|
||||
powered by
|
||||
</p>
|
||||
<UButton
|
||||
size="xs"
|
||||
:padded="false"
|
||||
variant="link"
|
||||
to="https://github.com/Phineas/lanyard"
|
||||
target="_blank"
|
||||
label="Lanyard"
|
||||
/>
|
||||
<UIcon
|
||||
class="text-subtitle"
|
||||
name="i-jam-thunder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UCard>
|
||||
<UCard
|
||||
:ui="CardUi"
|
||||
class="flex flex-col justify-between"
|
||||
>
|
||||
<div
|
||||
v-if="activity && activity.data.activities"
|
||||
class="flex items-center gap-x-4"
|
||||
>
|
||||
<p
|
||||
class="uppercase tracking-widest text-sm"
|
||||
:style="{ writingMode: 'vertical-rl', textOrientation: 'sideways' }"
|
||||
>
|
||||
Activity
|
||||
</p>
|
||||
<div v-if="codingActivity">
|
||||
<div class="flex gap-4 items-center">
|
||||
<UIcon
|
||||
class="h-10 w-10"
|
||||
:name="IDEs.find(ide => ide.name === codingActivity.name)!.icon"
|
||||
/>
|
||||
<div>
|
||||
<div class="flex items-center gap-2">
|
||||
<h1>{{ codingActivity.name }}</h1>
|
||||
<UTooltip :text="codingActivity.details === 'Idling' ? 'I\'m sleeping 😴' : 'I\'m online 👋'">
|
||||
<div
|
||||
:class="codingActivity.details === 'Idling' ? 'bg-amber-500' : 'bg-green-500'"
|
||||
class="h-3 w-3 inline-flex rounded-full cursor-pointer"
|
||||
/>
|
||||
</UTooltip>
|
||||
</div>
|
||||
<h3 v-if="codingActivity.details === 'Idling'">
|
||||
I'm Idling on my computer
|
||||
</h3>
|
||||
<h3 v-else>
|
||||
{{ codingActivity.details }} - {{ codingActivity.state }}
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="text-subtitle"
|
||||
>
|
||||
<div class="flex items-center gap-2">
|
||||
<h1>I'm currently offline</h1>
|
||||
<UTooltip text="I'm offline 🫥">
|
||||
<div class="h-3 w-3 inline-flex rounded-full bg-red-500" />
|
||||
</UTooltip>
|
||||
</div>
|
||||
<h3>Come back later to see what I'm doing</h3>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex items-center justify-end w-full">
|
||||
<ClientOnly>
|
||||
<p
|
||||
v-if="codingActivity"
|
||||
class="text-subtitle text-xs w-1/2"
|
||||
>
|
||||
Started {{ useTimeAgo(codingActivity.timestamps.start).value }}, the {{ formatDate(codingActivity.timestamps.start) }}
|
||||
</p>
|
||||
</ClientOnly>
|
||||
<div class="flex items-center space-x-1 w-1/2 justify-end">
|
||||
<p class="text-subtitle text-xs">
|
||||
powered by
|
||||
</p>
|
||||
<UButton
|
||||
size="xs"
|
||||
:padded="false"
|
||||
variant="link"
|
||||
to="https://github.com/Phineas/lanyard"
|
||||
target="_blank"
|
||||
label="Lanyard"
|
||||
/>
|
||||
<UIcon
|
||||
class="text-subtitle"
|
||||
name="i-jam-thunder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UCard>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
<script setup>
|
||||
const socials = [
|
||||
{
|
||||
name: 'mail',
|
||||
icon: 'i-material-symbols-alternate-email',
|
||||
link: 'mailto:arthurdanjou@outlook.fr',
|
||||
},
|
||||
{
|
||||
name: 'twitter',
|
||||
icon: 'i-ph-twitter-logo-bold',
|
||||
link: 'https://twitter.com/ArthurDanj',
|
||||
},
|
||||
{
|
||||
name: 'github',
|
||||
icon: 'i-ph-github-logo-bold',
|
||||
link: 'https://github.com/ArthurDanjou',
|
||||
},
|
||||
{
|
||||
name: 'linkedin',
|
||||
icon: 'i-ph-linkedin-logo-bold',
|
||||
link: 'https://www.linkedin.com/in/arthurdanjou/',
|
||||
},
|
||||
{
|
||||
name: 'mail',
|
||||
icon: 'i-material-symbols-alternate-email',
|
||||
link: 'mailto:arthurdanjou@outlook.fr',
|
||||
},
|
||||
{
|
||||
name: 'twitter',
|
||||
icon: 'i-ph-twitter-logo-bold',
|
||||
link: 'https://twitter.com/ArthurDanj',
|
||||
},
|
||||
{
|
||||
name: 'github',
|
||||
icon: 'i-ph-github-logo-bold',
|
||||
link: 'https://github.com/ArthurDanjou',
|
||||
},
|
||||
{
|
||||
name: 'linkedin',
|
||||
icon: 'i-ph-linkedin-logo-bold',
|
||||
link: 'https://www.linkedin.com/in/arthurdanjou/',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="w-container mt-32 mb-24">
|
||||
<div class="flex items-center flex-col space-y-4">
|
||||
<h1 class="text-center lg:text-6xl sm:text-5xl text-4xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100 !leading-tight md:w-2/3">
|
||||
Software engineer, mathematics lover and AI enthusiast
|
||||
</h1>
|
||||
<p class="leading-relaxed text-subtitle text-center md:w-2/3 p-2">
|
||||
I'm Arthur, a software engineer passionate about artificial intelligence and the cloud but also a mathematics student living in France. I am currently studying mathematics at the Faculty of Sciences of Paris-Saclay.
|
||||
</p>
|
||||
<div class="flex gap-4">
|
||||
<UButton
|
||||
v-for="social in socials"
|
||||
:key="social.name"
|
||||
:icon="social.icon"
|
||||
size="md"
|
||||
:to="social.link"
|
||||
variant="ghost"
|
||||
target="_blank"
|
||||
:ui="{ rounded: 'rounded-full' }"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-container mt-32 mb-24">
|
||||
<div class="flex items-center flex-col space-y-4">
|
||||
<h1 class="text-center lg:text-6xl sm:text-5xl text-4xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100 !leading-tight md:w-2/3">
|
||||
Software engineer, mathematics lover and AI enthusiast
|
||||
</h1>
|
||||
<p class="leading-relaxed text-subtitle text-center md:w-2/3 p-2">
|
||||
I'm Arthur, a software engineer passionate about artificial intelligence and the cloud but also a mathematics student living in France. I am currently studying mathematics at the Faculty of Sciences of Paris-Saclay.
|
||||
</p>
|
||||
<div class="flex gap-4">
|
||||
<UButton
|
||||
v-for="social in socials"
|
||||
:key="social.name"
|
||||
:icon="social.icon"
|
||||
size="md"
|
||||
:to="social.link"
|
||||
variant="ghost"
|
||||
target="_blank"
|
||||
:ui="{ rounded: 'rounded-full' }"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -4,84 +4,84 @@ import type {Stats} from '~~/types'
|
||||
const stats = await $fetch<Stats>('/api/stats')
|
||||
|
||||
const CardUi = {
|
||||
footer: { padding: 'px-4 py-2' },
|
||||
body: { base: 'h-full' },
|
||||
footer: { padding: 'px-4 py-2' },
|
||||
body: { base: 'h-full' },
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UCard
|
||||
:ui="CardUi"
|
||||
class="flex flex-col justify-between"
|
||||
>
|
||||
<div class="flex items-center gap-x-4 h-full">
|
||||
<p
|
||||
class="uppercase tracking-widest text-sm"
|
||||
:style="{ writingMode: 'vertical-rl', textOrientation: 'sideways' }"
|
||||
>
|
||||
STATS
|
||||
</p>
|
||||
<div v-if="stats">
|
||||
<div class="flex gap-4 items-center">
|
||||
<div class="text-md">
|
||||
<div class="flex items-center gap-x-1">
|
||||
<h3>Total hours:</h3>
|
||||
<p class="text-subtitle">
|
||||
{{ usePrecision(stats.coding.data.grand_total.total_seconds_including_other_language / 3600, 0) }} hours
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-start gap-x-1 flex-wrap">
|
||||
<h3>Best Editors:</h3>
|
||||
<p class="text-subtitle">
|
||||
{{ stats.editors.data.slice(0, 2).map(editor => `${editor.name} (${editor.percent}%)`).join(', ') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-x-1">
|
||||
<h3>Best OS:</h3>
|
||||
<p class="text-subtitle">
|
||||
{{ stats.os.data[0].name }} with {{ stats.os.data[0].percent }}%
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-start gap-x-1 flex-wrap">
|
||||
<h3>Top languages:</h3>
|
||||
<p class="text-subtitle">
|
||||
{{ stats.languages.data.slice(0, 2).map(language => `${language.name} (${language.percent}%)`).join(', ') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex items-center justify-between">
|
||||
<ClientOnly>
|
||||
<p
|
||||
v-if="stats"
|
||||
class="text-subtitle text-xs w-1/2"
|
||||
>
|
||||
Started {{ useTimeAgo(new Date(stats.coding.data.range.start)).value }}, the {{ useDateFormat(new Date(stats.coding.data.range.start), 'Do MMMM YYYY').value }}
|
||||
</p>
|
||||
</ClientOnly>
|
||||
<div class="flex items-center justify-end space-x-1">
|
||||
<p class="text-subtitle text-xs">
|
||||
powered by
|
||||
</p>
|
||||
<UButton
|
||||
size="xs"
|
||||
:padded="false"
|
||||
variant="link"
|
||||
to="https://wakatime.com/"
|
||||
target="_blank"
|
||||
label="Wakatime"
|
||||
/>
|
||||
<UIcon
|
||||
class="text-subtitle"
|
||||
name="i-jam-thunder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UCard>
|
||||
<UCard
|
||||
:ui="CardUi"
|
||||
class="flex flex-col justify-between"
|
||||
>
|
||||
<div class="flex items-center gap-x-4 h-full">
|
||||
<p
|
||||
class="uppercase tracking-widest text-sm"
|
||||
:style="{ writingMode: 'vertical-rl', textOrientation: 'sideways' }"
|
||||
>
|
||||
STATS
|
||||
</p>
|
||||
<div v-if="stats">
|
||||
<div class="flex gap-4 items-center">
|
||||
<div class="text-md">
|
||||
<div class="flex items-center gap-x-1">
|
||||
<h3>Total hours:</h3>
|
||||
<p class="text-subtitle">
|
||||
{{ usePrecision(stats.coding.data.grand_total.total_seconds_including_other_language / 3600, 0) }} hours
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-start gap-x-1 flex-wrap">
|
||||
<h3>Best Editors:</h3>
|
||||
<p class="text-subtitle">
|
||||
{{ stats.editors.data.slice(0, 2).map(editor => `${editor.name} (${editor.percent}%)`).join(', ') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-center gap-x-1">
|
||||
<h3>Best OS:</h3>
|
||||
<p class="text-subtitle">
|
||||
{{ stats.os.data[0].name }} with {{ stats.os.data[0].percent }}%
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex items-start gap-x-1 flex-wrap">
|
||||
<h3>Top languages:</h3>
|
||||
<p class="text-subtitle">
|
||||
{{ stats.languages.data.slice(0, 2).map(language => `${language.name} (${language.percent}%)`).join(', ') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="flex items-center justify-between">
|
||||
<ClientOnly>
|
||||
<p
|
||||
v-if="stats"
|
||||
class="text-subtitle text-xs w-1/2"
|
||||
>
|
||||
Started {{ useTimeAgo(new Date(stats.coding.data.range.start)).value }}, the {{ useDateFormat(new Date(stats.coding.data.range.start), 'Do MMMM YYYY').value }}
|
||||
</p>
|
||||
</ClientOnly>
|
||||
<div class="flex items-center justify-end space-x-1">
|
||||
<p class="text-subtitle text-xs">
|
||||
powered by
|
||||
</p>
|
||||
<UButton
|
||||
size="xs"
|
||||
:padded="false"
|
||||
variant="link"
|
||||
to="https://wakatime.com/"
|
||||
target="_blank"
|
||||
label="Wakatime"
|
||||
/>
|
||||
<UIcon
|
||||
class="text-subtitle"
|
||||
name="i-jam-thunder"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</UCard>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
<script setup lang="ts">
|
||||
defineProps({
|
||||
startDate: String,
|
||||
endDate: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
startDate: String,
|
||||
endDate: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
function formatTodayDate(date: string) {
|
||||
const split = date.split(' ')
|
||||
return date === 'Today' ? 'Today' : `${split[0]} ${split[1]}`
|
||||
const split = date.split(' ')
|
||||
return date === 'Today' ? 'Today' : `${split[0]} ${split[1]}`
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UBadge
|
||||
v-if="startDate !== endDate"
|
||||
size="xs"
|
||||
variant="soft"
|
||||
>
|
||||
{{ formatTodayDate(startDate!.toString()) }} — {{ formatTodayDate(endDate) }}
|
||||
</UBadge>
|
||||
<UBadge
|
||||
v-else
|
||||
size="xs"
|
||||
variant="soft"
|
||||
>
|
||||
{{ formatTodayDate(endDate) }}
|
||||
</UBadge>
|
||||
<UBadge
|
||||
v-if="startDate !== endDate"
|
||||
size="xs"
|
||||
variant="soft"
|
||||
>
|
||||
{{ formatTodayDate(startDate!.toString()) }} — {{ formatTodayDate(endDate) }}
|
||||
</UBadge>
|
||||
<UBadge
|
||||
v-else
|
||||
size="xs"
|
||||
variant="soft"
|
||||
>
|
||||
{{ formatTodayDate(endDate) }}
|
||||
</UBadge>
|
||||
</template>
|
||||
|
||||
@@ -2,28 +2,28 @@
|
||||
import type {Education} from '~~/types'
|
||||
|
||||
defineProps({
|
||||
education: Object as PropType<Education>,
|
||||
education: Object as PropType<Education>,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="education"
|
||||
class="group relative flex flex-col items-start"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<DateTag
|
||||
:end-date="education.endDate"
|
||||
:start-date="education.startDate"
|
||||
/>
|
||||
</div>
|
||||
<h1 class="my-1 text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">
|
||||
{{ education.title }}
|
||||
</h1>
|
||||
</div>
|
||||
<p class="text-justify leading-5 text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{{ education.location }} — {{ education.description }}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
v-if="education"
|
||||
class="group relative flex flex-col items-start"
|
||||
>
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<DateTag
|
||||
:end-date="education.endDate"
|
||||
:start-date="education.startDate"
|
||||
/>
|
||||
</div>
|
||||
<h1 class="my-1 text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">
|
||||
{{ education.title }}
|
||||
</h1>
|
||||
</div>
|
||||
<p class="text-justify leading-5 text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{{ education.location }} — {{ education.description }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -2,56 +2,56 @@
|
||||
import type {WorkExperience} from '~~/types'
|
||||
|
||||
defineProps({
|
||||
experience: Object as PropType<WorkExperience>,
|
||||
experience: Object as PropType<WorkExperience>,
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
v-if="experience"
|
||||
class="group relative flex flex-col items-start"
|
||||
>
|
||||
<div>
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<DateTag
|
||||
:end-date="experience.endDate"
|
||||
:start-date="experience.startDate"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center my-1">
|
||||
<UButton
|
||||
v-if="experience.companyLink"
|
||||
:to="experience.companyLink"
|
||||
variant="link"
|
||||
:padded="false"
|
||||
color="white"
|
||||
size="xl"
|
||||
target="_blank"
|
||||
:label="experience.company"
|
||||
class="mr-3 text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100"
|
||||
>
|
||||
<template #leading>
|
||||
<UIcon
|
||||
color="gray"
|
||||
name="i-akar-icons-link-chain"
|
||||
/>
|
||||
</template>
|
||||
</UButton>
|
||||
<h1
|
||||
v-else
|
||||
class="mr-3 my-1 text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100"
|
||||
>
|
||||
{{ experience.company }}
|
||||
</h1>
|
||||
<div class="text-subtitle text-xs">
|
||||
{{ experience.location }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-justify leading-5 text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{{ experience.title }} — {{ experience.description }}
|
||||
</p>
|
||||
</div>
|
||||
<div
|
||||
v-if="experience"
|
||||
class="group relative flex flex-col items-start"
|
||||
>
|
||||
<div>
|
||||
<div class="flex flex-col">
|
||||
<div>
|
||||
<DateTag
|
||||
:end-date="experience.endDate"
|
||||
:start-date="experience.startDate"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex items-center my-1">
|
||||
<UButton
|
||||
v-if="experience.companyLink"
|
||||
:to="experience.companyLink"
|
||||
variant="link"
|
||||
:padded="false"
|
||||
color="white"
|
||||
size="xl"
|
||||
target="_blank"
|
||||
:label="experience.company"
|
||||
class="mr-3 text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100"
|
||||
>
|
||||
<template #leading>
|
||||
<UIcon
|
||||
color="gray"
|
||||
name="i-akar-icons-link-chain"
|
||||
/>
|
||||
</template>
|
||||
</UButton>
|
||||
<h1
|
||||
v-else
|
||||
class="mr-3 my-1 text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100"
|
||||
>
|
||||
{{ experience.company }}
|
||||
</h1>
|
||||
<div class="text-subtitle text-xs">
|
||||
{{ experience.location }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="text-justify leading-5 text-sm text-zinc-600 dark:text-zinc-400">
|
||||
{{ experience.title }} — {{ experience.description }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import type {Skill} from '~~/types'
|
||||
|
||||
defineProps({
|
||||
skill: Object as PropType<Skill>,
|
||||
skill: Object as PropType<Skill>,
|
||||
})
|
||||
|
||||
const { $colorMode } = useNuxtApp()
|
||||
@@ -10,24 +10,24 @@ const isLight = computed(() => $colorMode.value === 'light')
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<li
|
||||
v-if="skill"
|
||||
class="flex items-center gap-2 rounded-md px-2 py-3 duration-300 md:hover:bg-gray-100 md:dark:hover:bg-neutral-800"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<UIcon
|
||||
v-if="isLight"
|
||||
:name="skill.icon.light ? skill.icon.light : skill.icon"
|
||||
dynamic
|
||||
size="20"
|
||||
/>
|
||||
<UIcon
|
||||
v-else
|
||||
:name="skill.icon.dark ? skill.icon.dark : skill.icon"
|
||||
dynamic
|
||||
size="20"
|
||||
/>
|
||||
</div>
|
||||
<span class="text-sm text-subtitle">{{ skill.name }}</span>
|
||||
</li>
|
||||
<li
|
||||
v-if="skill"
|
||||
class="flex items-center gap-2 rounded-md px-2 py-3 duration-300 md:hover:bg-gray-100 md:dark:hover:bg-neutral-800"
|
||||
>
|
||||
<div class="flex items-center">
|
||||
<UIcon
|
||||
v-if="isLight"
|
||||
:name="skill.icon.light ? skill.icon.light : skill.icon"
|
||||
dynamic
|
||||
size="20"
|
||||
/>
|
||||
<UIcon
|
||||
v-else
|
||||
:name="skill.icon.dark ? skill.icon.dark : skill.icon"
|
||||
dynamic
|
||||
size="20"
|
||||
/>
|
||||
</div>
|
||||
<span class="text-sm text-subtitle">{{ skill.name }}</span>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user