mirror of
https://github.com/ArthurDanjou/website.git
synced 2026-01-14 12:14:42 +01:00
Working
This commit is contained in:
@@ -14,6 +14,9 @@ export default defineAppConfig({
|
||||
},
|
||||
dropdown: {
|
||||
background: 'bg-white dark:bg-zinc-800',
|
||||
item: {
|
||||
base: 'duration-300 group flex items-center gap-2 w-full',
|
||||
},
|
||||
},
|
||||
button: {
|
||||
base: 'duration-300 focus:outline-none focus-visible:outline-0 disabled:cursor-not-allowed disabled:opacity-75 flex-shrink-0',
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
@layer components {
|
||||
.w-container {
|
||||
@apply mx-auto max-w-7xl lg:px-24 sm:px-4;
|
||||
@apply mx-auto max-w-7xl lg:px-24 md:px-12 sm:px-4;
|
||||
}
|
||||
|
||||
.text-subtitle {
|
||||
|
||||
@@ -1,130 +0,0 @@
|
||||
<script setup lang="ts">
|
||||
const isOpen = ref(false)
|
||||
const commandPaletteRef = ref()
|
||||
|
||||
const router = useRouter()
|
||||
const color = useColorMode()
|
||||
|
||||
const quickLinks = [
|
||||
{ id: 'twitter', label: 'Twitter', icon: 'i-ph-twitter-logo-bold' },
|
||||
{ id: 'github', label: 'GitHub', icon: 'i-ph-github-logo-bold' },
|
||||
]
|
||||
|
||||
const navigations = [
|
||||
{ id: 'home', label: 'Home', icon: 'i-ph-house-bold', to: '/', shortcuts: ['H'] },
|
||||
{ id: 'about', label: 'About', icon: 'i-ph-user-bold', to: '/about', shortcuts: ['A'] },
|
||||
{ id: 'blog', label: 'Blog', icon: 'i-ph-book-bold', to: '/blog', shortcuts: ['B'] },
|
||||
{ id: 'work', label: 'Work', icon: 'i-ph-wrench-bold', to: '/work', shortcuts: ['W'] },
|
||||
]
|
||||
|
||||
const toast = useToast()
|
||||
|
||||
const isDark = computed(() => color.preference === 'dark')
|
||||
const controls = [
|
||||
{
|
||||
id: 'color',
|
||||
label: 'Toggle Color Mode',
|
||||
icon: isDark ? 'i-ph-moon-bold' : 'i-ph-sun-bold',
|
||||
click: () => {
|
||||
color.preference = color.value === 'dark' ? 'light' : 'dark'
|
||||
toast.add({
|
||||
color: 'primary',
|
||||
title: 'Color mode switched!',
|
||||
icon: isDark.value ? 'i-ph-moon-bold' : 'i-ph-sun-bold',
|
||||
})
|
||||
},
|
||||
shortcuts: ['C'],
|
||||
},
|
||||
]
|
||||
|
||||
const groups = [{
|
||||
key: 'navigation',
|
||||
label: 'Navigation',
|
||||
inactive: 'Navigation',
|
||||
commands: navigations,
|
||||
}, {
|
||||
key: 'quickLinks',
|
||||
label: 'Quick Links',
|
||||
inactive: 'Quick Links',
|
||||
commands: quickLinks,
|
||||
}, {
|
||||
key: 'controls',
|
||||
label: 'Controls',
|
||||
inactive: 'Controls',
|
||||
commands: controls,
|
||||
}]
|
||||
|
||||
const { usingInput } = useShortcuts()
|
||||
const canToggleModal = computed(() => isOpen.value || !usingInput.value)
|
||||
|
||||
defineShortcuts({
|
||||
meta_k: {
|
||||
usingInput: true,
|
||||
whenever: [canToggleModal],
|
||||
handler: () => {
|
||||
isOpen.value = !isOpen.value
|
||||
},
|
||||
},
|
||||
escape: {
|
||||
usingInput: true,
|
||||
whenever: [isOpen],
|
||||
handler: () => { isOpen.value = false },
|
||||
},
|
||||
})
|
||||
|
||||
function onSelect(option: any) {
|
||||
if (option.click) {
|
||||
option.click()
|
||||
isOpen.value = false
|
||||
}
|
||||
|
||||
else if (option.to) { router.push(option.to) }
|
||||
|
||||
else if (option.href) { window.open(option.href, '_blank') }
|
||||
}
|
||||
|
||||
onKeyStroke(true, (event: KeyboardEvent) => {
|
||||
if (!isOpen.value && !usingInput.value) {
|
||||
switch (event.key) {
|
||||
case 'A':
|
||||
case 'a':
|
||||
router.push('/about')
|
||||
break
|
||||
case 'H':
|
||||
case 'h':
|
||||
router.push('/')
|
||||
break
|
||||
case 'W':
|
||||
case 'w':
|
||||
router.push('/work')
|
||||
break
|
||||
case 'B':
|
||||
case 'b':
|
||||
router.push('/blog')
|
||||
break
|
||||
case 'C':
|
||||
case 'c':
|
||||
color.preference = color.value === 'dark' ? 'light' : 'dark'
|
||||
toast.add({
|
||||
color: 'primary',
|
||||
title: 'Color mode switched!',
|
||||
icon: isDark.value ? 'i-ph-moon-bold' : 'i-ph-sun-bold',
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<UModal v-model="isOpen">
|
||||
<UCommandPalette
|
||||
ref="commandPaletteRef"
|
||||
:groups="groups"
|
||||
icon=""
|
||||
:autoselect="false"
|
||||
placeholder="Search for apps and commands"
|
||||
@update:model-value="onSelect"
|
||||
/>
|
||||
</UModal>
|
||||
</template>
|
||||
@@ -22,27 +22,27 @@ const items = [
|
||||
<template>
|
||||
<nav class="hidden md:block pointer-events-auto 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 to="/" size="sm" variant="ghost" color="white">
|
||||
<UButton to="/" size="sm" variant="ghost" color="white" :class="{ 'router-link-exact-active': route.path === '/' }">
|
||||
Home
|
||||
</UButton>
|
||||
<UButton to="/about" size="sm" variant="ghost" color="white">
|
||||
<UButton to="/about" size="sm" variant="ghost" color="white" :class="{ 'router-link-exact-active': route.path.includes('/about') }">
|
||||
About
|
||||
</UButton>
|
||||
<UButton to="/writing" size="sm" variant="ghost" color="white" :class="{ 'router-link-exact-active': route.path.includes('/writing') }">
|
||||
Articles
|
||||
</UButton>
|
||||
<UButton to="/work" size="sm" variant="ghost" color="white">
|
||||
<UButton to="/work" size="sm" variant="ghost" color="white" :class="{ 'router-link-exact-active': route.path.includes('/work') }">
|
||||
Projects
|
||||
</UButton>
|
||||
<UButton to="/uses" size="sm" variant="ghost" color="white">
|
||||
<UButton to="/uses" size="sm" variant="ghost" color="white" :class="{ 'router-link-exact-active': route.path.includes('/uses') }">
|
||||
Uses
|
||||
</UButton>
|
||||
<UDropdown mode="hover" :items="items" :popper="{ placement: 'bottom' }">
|
||||
<UButton size="sm" variant="ghost" color="white">
|
||||
<UButton size="sm" variant="ghost" color="white" class="duration-300">
|
||||
Other
|
||||
</UButton>
|
||||
</UDropdown>
|
||||
<UButton to="/contact" size="sm" variant="ghost" color="white">
|
||||
<UButton to="/contact" size="sm" variant="ghost" color="white" :class="{ 'router-link-exact-active': route.path.includes('/contact') }">
|
||||
Contact
|
||||
</UButton>
|
||||
</div>
|
||||
|
||||
@@ -1,78 +1,78 @@
|
||||
::uses-section{title="Computers"}
|
||||
::grid-section{title="Computers"}
|
||||
|
||||
:::uses-slot{title="MacBook Pro 13'"}
|
||||
:::grid-slot{title="MacBook Pro 13'"}
|
||||
I use this for code
|
||||
:::
|
||||
|
||||
:::uses-slot{title="Specs..."}
|
||||
:::grid-slot{title="Specs..."}
|
||||
I use this for valorant
|
||||
:::
|
||||
|
||||
::
|
||||
|
||||
::uses-section{title="Peripherals"}
|
||||
::grid-section{title="Peripherals"}
|
||||
|
||||
:::uses-slot{title="MacBook Pro 13'"}
|
||||
:::grid-slot{title="MacBook Pro 13'"}
|
||||
I use this for code
|
||||
:::
|
||||
|
||||
:::uses-slot{title="My gaming computer"}
|
||||
:::grid-slot{title="My gaming computer"}
|
||||
Windows 11, Intel Core i5-10400F, 16Go DDR4, RTX 2060
|
||||
:::
|
||||
|
||||
:::uses-slot{title="Phone, Sound & Other"}
|
||||
:::grid-slot{title="Phone, Sound & Other"}
|
||||
Iphone 14 Pro, Ipad Air, AirPods Pro, Beats Studio 3
|
||||
:::
|
||||
|
||||
::
|
||||
|
||||
::uses-section{title="Editors"}
|
||||
::grid-section{title="Editors"}
|
||||
|
||||
:::uses-slot{title="Visual Studio Code"}
|
||||
:::grid-slot{title="Visual Studio Code"}
|
||||
I use this for code
|
||||
:::
|
||||
|
||||
:::uses-slot{title="JetBrains Mono"}
|
||||
:::grid-slot{title="JetBrains Mono"}
|
||||
I use this for valorant
|
||||
:::
|
||||
|
||||
::
|
||||
|
||||
::uses-section{title="Software and Applications"}
|
||||
::grid-section{title="Software and Applications"}
|
||||
|
||||
:::uses-slot{title="Warp"}
|
||||
:::grid-slot{title="Warp"}
|
||||
I use this for code
|
||||
:::
|
||||
|
||||
:::uses-slot{title="Apple Apps"}
|
||||
:::grid-slot{title="Apple Apps"}
|
||||
Music, mail, reminders, calendar
|
||||
:::
|
||||
|
||||
:::uses-slot{title="Notion"}
|
||||
:::grid-slot{title="Notion"}
|
||||
I use this for valorant
|
||||
:::
|
||||
|
||||
:::uses-slot{title="Google Chrome & Arc"}
|
||||
:::grid-slot{title="Google Chrome & Arc"}
|
||||
I use this for valorant
|
||||
:::
|
||||
|
||||
:::uses-slot{title="Discord"}
|
||||
:::grid-slot{title="Discord"}
|
||||
I use this for valorant
|
||||
:::
|
||||
|
||||
:::uses-slot{title="RayCast"}
|
||||
:::grid-slot{title="RayCast"}
|
||||
I use this for valorant
|
||||
:::
|
||||
|
||||
::
|
||||
|
||||
::uses-section{title="Favorite Stack"}
|
||||
::grid-section{title="Favorite Stack"}
|
||||
|
||||
:::uses-slot{title="FrontEnd"}
|
||||
:::grid-slot{title="FrontEnd"}
|
||||
TS, Vue 3 with Nuxt 3, TailwindCss, Nuxt UI
|
||||
:::
|
||||
|
||||
:::uses-slot{title="BackEnd"}
|
||||
:::grid-slot{title="BackEnd"}
|
||||
Prisma, AdonisJs, Supabase, TRPC.io
|
||||
:::
|
||||
|
||||
|
||||
48
src/error.vue
Normal file
48
src/error.vue
Normal file
@@ -0,0 +1,48 @@
|
||||
<script setup lang="ts">
|
||||
const error = useError()
|
||||
const appConfig = useAppConfig()
|
||||
const getColor = computed(() => appConfig.ui.primary)
|
||||
|
||||
definePageMeta({
|
||||
layout: 'default',
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NuxtLoadingIndicator :color="getColor" />
|
||||
<section class="fixed inset-0 flex justify-center sm:px-8">
|
||||
<div class="flex w-full max-w-7xl">
|
||||
<div class="w-full bg-white ring-1 ring-zinc-100 dark:bg-zinc-900 dark:ring-zinc-300/20" />
|
||||
</div>
|
||||
</section>
|
||||
<div class="relative z-50">
|
||||
<Header />
|
||||
<UContainer class="my-32 w-container flex flex-col items-center gap-8">
|
||||
<div class="flex flex-col items-center gap-4">
|
||||
<h1 class="font-medium text-[8rem] md:text-[16rem] leading-none bg-error bg-clip-text tracking-wider font-error" :class="`text-${getColor}-500`">
|
||||
{{ error.statusCode }}
|
||||
</h1>
|
||||
<p class="text-lg md:text-2xl text-subtitle text-center">
|
||||
Sorry, {{ error.statusCode === 404
|
||||
? "the page you are looking for doesn't exist or as been moved."
|
||||
: "you have encountered a problem."
|
||||
}}
|
||||
<br>
|
||||
Let's find a better place for you to go.
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<UButton to="/" size="md" variant="soft" color="primary">
|
||||
Go back to the main page
|
||||
</UButton>
|
||||
</div>
|
||||
</UContainer>
|
||||
<Footer />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.bg-error {
|
||||
@apply text-transparent bg-clip-text bg-origin-content bg-gradient-to-b from-gray-100 to-gray-300 dark:from-zinc-600 to-55% dark:to-zinc-800;
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,10 @@
|
||||
<script setup lang="ts">
|
||||
const appConfig = useAppConfig()
|
||||
const getColor = computed(() => appConfig.ui.primary)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<CommandPalette />
|
||||
<NuxtLoadingIndicator />
|
||||
<NuxtLoadingIndicator :color="getColor" />
|
||||
<section class="fixed inset-0 flex justify-center sm:px-8">
|
||||
<div class="flex w-full max-w-7xl">
|
||||
<div class="w-full bg-white ring-1 ring-zinc-100 dark:bg-zinc-900 dark:ring-zinc-300/20" />
|
||||
@@ -13,6 +17,4 @@
|
||||
</UContainer>
|
||||
<Footer />
|
||||
</div>
|
||||
|
||||
<UNotifications />
|
||||
</template>
|
||||
|
||||
@@ -3,7 +3,36 @@
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
ABOUT
|
||||
</div>
|
||||
<section>
|
||||
<div class="w-container lg:my-32 mt-16">
|
||||
<div class="max-w-2xl space-y-8 mb-16">
|
||||
<h1 class="text-4xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100 sm:text-5xl !leading-tight">
|
||||
I'm Arthur, I live and study in France where I learn new things.
|
||||
</h1>
|
||||
<p class="leading-relaxed text-subtitle">
|
||||
As a software engineer with a passion for AI and the cloud, I have a deep understanding of emerging technologies that are transforming the way businesses and organizations operate. I am at the heart of an ever-changing and rapidly growing field. My background in mathematics also gives me an edge in understanding the mathematical concepts and theories behind these technologies as well as how to design them.
|
||||
</p>
|
||||
<p class="leading-relaxed text-subtitle">
|
||||
I enjoy sharing my knowledge and learning new theorems and technologies. I am a curious person and eager to continue learning and growing throughout your life. My passion and commitment to these subjects are admirable qualities and will help me succeed in my career and education.
|
||||
</p>
|
||||
</div>
|
||||
<GridSection title="Interests">
|
||||
<GridSlot title="Development">
|
||||
Development is the passion that appeared the earliest in my life. I started developing on Minecraft and then I migrated to the broad field of the web.
|
||||
</GridSlot>
|
||||
<GridSlot title="Mathematics">
|
||||
During my studies, I loved mathematics very quickly. That's why today I continue my studies in this fabulous field.
|
||||
</GridSlot>
|
||||
<GridSlot title="Artificial Intelligence">
|
||||
We hear more and more about artificial intelligence with the evolution of our society. So I quickly got interested by doing my own research and I quickly discovered that this field is closely related to mathematics, hence my interest.
|
||||
</GridSlot>
|
||||
<GridSlot title="Cloud and infrastructure">
|
||||
When you're doing development and deploying projects online, you discover and are forced to touch the cloud, infrastructure, and network. It's a totally different field than the others but just as interesting.
|
||||
</GridSlot>
|
||||
<GridSlot title="Fitness">
|
||||
In addition to my studies and programming, I go to the gym every day to relax and stay in shape. Sport allows me to recharge my batteries and move on to other things.
|
||||
</GridSlot>
|
||||
</GridSection>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
@@ -1,18 +1,23 @@
|
||||
<script lang="ts" setup>
|
||||
import type { Post } from '../../../types'
|
||||
import type { Post } from '~~/types'
|
||||
|
||||
const route = useRoute()
|
||||
const { data: postContent } = await useAsyncData<Post>(`writing:${route.params.slug}`, async () => await queryContent<Post>(`/writing/${route.params.slug}`).findOne())
|
||||
|
||||
const { post, view, like, likes, views } = await usePost(route.params.slug.toString())
|
||||
if (!postContent.value) {
|
||||
throw createError({
|
||||
statusMessage: 'The post you are looking for was not found.',
|
||||
statusCode: 404,
|
||||
})
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
view()
|
||||
})
|
||||
const { post, view, like, likes, views } = await usePost(route.params.slug.toString())
|
||||
view()
|
||||
|
||||
useHead({
|
||||
title: `${postContent.value?.title} — Arthur Danjou's shelf`,
|
||||
})
|
||||
|
||||
function top() {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
@@ -25,8 +30,6 @@ const { copy, copied } = useClipboard({
|
||||
source: `https://arthurdanjou.fr/writing/${route.params.slug}`,
|
||||
copiedDuring: 4000,
|
||||
})
|
||||
|
||||
const router = useRouter()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -41,7 +44,7 @@ const router = useRouter()
|
||||
size="lg"
|
||||
:ui="{ rounded: 'rounded-full' }"
|
||||
class="lg:absolute left-0 mb-8"
|
||||
@click.prevent="router.back()"
|
||||
@click.prevent="useRouter().back()"
|
||||
/>
|
||||
<article>
|
||||
<header class="flex flex-col space-y-6">
|
||||
@@ -54,7 +57,7 @@ const router = useRouter()
|
||||
<span>•</span>
|
||||
<div>{{ postContent.readingMins }} min</div>
|
||||
<span>•</span>
|
||||
<div>{{ views }} views</div>
|
||||
<div>{{ views }} {{ views > 1 ? 'views' : 'view' }}</div>
|
||||
</div>
|
||||
</time>
|
||||
<h1 class="text-4xl font-bold tracking-tight text-zinc-800 dark:text-zinc-100 sm:text-5xl">
|
||||
@@ -67,18 +70,25 @@ const router = useRouter()
|
||||
<div class="w-full rounded-md my-8">
|
||||
{{ postContent.cover }}
|
||||
</div>
|
||||
<ContentRenderer
|
||||
class="mt-12 prose leading-6 prose-table:w-full md:prose-table:w-3/4 lg:prose-table:w-2/5 max-w-none
|
||||
<ClientOnly>
|
||||
<ContentRenderer
|
||||
class="mt-12 prose leading-6 prose-table:w-full md:prose-table:w-3/4 lg:prose-table:w-2/5 max-w-none
|
||||
dark:prose dark:prose-invert dark:leading-6 dark:max-w-none dark:prose-table:w-full dark:md:prose-table:w-3/4 dark:lg:prose-table:w-2/5"
|
||||
:value="postContent || undefined"
|
||||
/>
|
||||
:value="postContent"
|
||||
/>
|
||||
<template #fallback>
|
||||
<p class="my-16 text-subtitle">
|
||||
The content of the page is loading...
|
||||
</p>
|
||||
</template>
|
||||
</ClientOnly>
|
||||
<footer class="my-8 space-y-8">
|
||||
<p class="text-subtitle">
|
||||
Thanks for reading this post! If you liked it, please consider sharing it with your friends. <strong>Don't forget to leave a like!</strong>
|
||||
</p>
|
||||
<div class="flex gap-4 flex-wrap">
|
||||
<UButton
|
||||
:label="`${likes} likes`"
|
||||
:label="`${likes} ${likes > 1 ? 'likes' : 'like'}`"
|
||||
icon="i-ph-heart-bold"
|
||||
size="lg"
|
||||
variant="soft"
|
||||
|
||||
@@ -26,7 +26,7 @@ const { data: posts } = await usePosts()
|
||||
<div class="mt-16 md:mt-20">
|
||||
<div class="md:border-l md:border-zinc-100 md:pl-6 md:dark:border-zinc-700/40">
|
||||
<div class="flex max-w-3xl flex-col space-y-16">
|
||||
<article v-for="post in posts" :key="post.slug" class="md:grid md:grid-cols-4 md:items-baseline">
|
||||
<article v-for="post in posts" :key="post.slug" class="group md:grid md:grid-cols-4 md:items-baseline">
|
||||
<div class="md:col-span-3 group relative flex flex-col items-start">
|
||||
<h2 class="text-base font-semibold tracking-tight text-zinc-800 dark:text-zinc-100">
|
||||
<div class="absolute -inset-y-6 -inset-x-4 z-0 scale-95 bg-zinc-50 opacity-0 transition group-hover:scale-100 group-hover:opacity-100 dark:bg-zinc-800/50 sm:-inset-x-6 sm:rounded-2xl" />
|
||||
@@ -48,7 +48,7 @@ const { data: posts } = await usePosts()
|
||||
</p>
|
||||
<div class="relative z-10 mt-4 flex items-center gap-2 justify-center text-sm font-medium" :class="getColor()">
|
||||
<p>Read article</p>
|
||||
<UIcon name="i-ph-arrow-circle-right-bold" />
|
||||
<UIcon name="i-ph-arrow-circle-right-bold" class="duration-300 group-hover:ml-2"/>
|
||||
</div>
|
||||
</div>
|
||||
<time class="mt-1 md:block relative z-10 order-first mb-3 hidden text-sm text-zinc-400 dark:text-zinc-500">
|
||||
|
||||
Reference in New Issue
Block a user