Implement Stats and activity card on main page

This commit is contained in:
2024-02-23 21:39:42 +01:00
parent 79b7cdf7c9
commit e3e202ad05
7 changed files with 305 additions and 0 deletions

View File

@@ -0,0 +1,76 @@
<script lang="ts" setup>
const { data: activity } = await $fetch('/api/activity')
const codingActivity = computed(() => activity.activities.filter(activity => activity.name === 'Visual Studio Code')[0])
function formatDate(date) {
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' },
}
</script>
<template>
<UCard class="mx-8 md:mx-0 f-auto flex flex-col justify-between" :ui="CardUi">
<div v-if="activity && activity.activities" class="flex items-center gap-x-4">
<p
class="uppercase tracking-widest text-sm"
:style="{ writingMode: 'vertical-rl', textOrientation: 'sideways-right' }"
>
Activity
</p>
<div v-if="codingActivity">
<div class="flex gap-4 items-center">
<UIcon
class="h-10 w-10"
name="i-skill-icons-vscode-light"
/>
<div>
<div class="flex items-center gap-2">
<h1>{{ codingActivity.name }}</h1>
<UTooltip text="I'm online">
<div class="h-3 w-3 inline-flex rounded-full bg-green-500 cursor-pointer" />
</UTooltip>
</div>
<h3>{{ 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-between">
<p v-if="codingActivity" class="text-subtitle text-xs">
Started the {{ formatDate(codingActivity.timestamps.start) }}
</p>
<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://github.com/Phineas/lanyard"
target="_blank"
label="Lanyard"
/>
<UIcon name="i-jam-thunder" class="text-subtitle" />
</div>
</div>
</template>
</UCard>
</template>
<style>
</style>

View File

@@ -0,0 +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/',
},
]
</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>
</template>

View File

@@ -0,0 +1,93 @@
<script lang="ts" setup>
import { Circle, FunctionPlot, Graph, Label, Line, Point, Vector } from '@ksassnowski/vueclid'
const angle = ref(45)
const time = ref(0)
useIntervalFn(() => {
angle.value = angle.value === 1 ? 0 : angle.value + 0.01
time.value += 0.1
}, 10)
</script>
<template>
<section class="flex flex-col md:flex-row items-center justify-center gap-5 overflow-hidden py-4 sm:gap-8 mb-16">
<div>
<Graph :domain-x="[-3, 3]" :domain-y="[-3, 3]">
<FunctionPlot
:function="(x) => Math.cos(x)"
:line-width="2"
animated
color="hotpink"
/>
<Label text="cos(x)" color="hotpink" :position="[2, -0.5]" size="small" />
<FunctionPlot
:function="(x) => Math.sin(x)"
:line-width="2"
animated
color="#33aabb"
/>
<Label text="sin(x)" color="#33aabb" :position="[2, 1]" size="small" />
<FunctionPlot
:function="(x) => Math.exp(x)"
:line-width="2"
animated
/>
<Label text="exp(x)" :position="[0.7, 2]" size="small" />
<FunctionPlot
:function="(x) => Math.log(x)"
:domain="[0.001, 4]"
:line-width="2"
animated
color="limegreen"
/>
<Label text="ln(x)" color="limegreen" :position="[0.2, -2]" size="small" />
<FunctionPlot
:function="(x) => -x"
:domain="[-3, 0]"
:line-width="2"
animated
color="orange"
/>
<FunctionPlot
:function="(x) => x"
:domain="[0, 3]"
:line-width="2"
animated
color="orange"
/>
<Label text="|x|" color="orange" :position="[-2, 2]" size="small" />
</Graph>
</div>
<div>
<Graph
:domain-x="[-2, 2]"
:domain-y="[-2, 2]"
>
<Circle :radius="1" color="#aaa" />
<Vector :to="[Math.cos(angle), Math.sin(angle)]" />
<Line
:from="[Math.cos(angle), 0]"
:to="[Math.cos(angle), Math.sin(angle)]"
:line-width="1.5"
color="hotpink"
dashed
/>
<Line
:from="[0, Math.sin(angle)]"
:to="[Math.cos(angle), Math.sin(angle)]"
:line-width="1.5"
color="#33aabb"
dashed
/>
<Point :position="[Math.cos(angle), Math.sin(angle)]" label="M" />
<Point :position="[Math.cos(angle), 0]" color="hotpink" label="cos(x)" />
<Point
:position="[0, Math.sin(angle)]"
color="#33aabb"
label="sin(x)"
label-position="top"
/>
</Graph>
</div>
</section>
</template>

View File

@@ -0,0 +1,70 @@
<script lang="ts" setup>
const stats = await $fetch('/api/stats')
const CardUi = {
footer: { padding: 'px-4 py-2' },
body: { base: 'h-full' },
}
</script>
<template>
<UCard class="mx-8 md:mx-0 flex flex-col justify-between" :ui="CardUi">
<div class="flex items-center gap-x-4 h-full">
<p
class="uppercase tracking-widest text-sm"
:style="{ writingMode: 'vertical-rl', textOrientation: 'sideways-right' }"
>
STATS
</p>
<div v-if="stats">
<div class="flex gap-4 items-center">
<div>
<div class="flex items-center gap-1">
<h3>Total hours:</h3>
<p>{{ usePrecision(stats.coding.data.grand_total.total_seconds_including_other_language / 3600, 0) }} hours</p>
</div>
<div class="flex items-start gap-3">
<h3>Best Editors:</h3>
<p>
{{ stats.editors.data.slice(0, 2).map(editor => `${editor.name} (${editor.percent}%)`).join(', ') }}
</p>
</div>
<div class="flex items-center gap-1">
<h3>Best OS:</h3>
<p>{{ stats.os.data[0].name }} with {{ stats.os.data[0].percent }}%</p>
</div>
<div class="flex items-start gap-3 flex-wrap">
<h3>Top languages:</h3>
<p>{{ 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">
<p v-if="stats" class="text-subtitle text-xs">
Started {{ useTimeAgo(new Date(stats.coding.data.range.start)).value }}, the {{ useDateFormat(new Date(stats.coding.data.range.start), 'Do MMMM YYYY').value }}
</p>
<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 name="i-jam-thunder" class="text-subtitle" />
</div>
</div>
</template>
</UCard>
</template>
<style>
</style>

BIN
src/public/purple.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -0,0 +1,4 @@
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig(event)
return await $fetch(`https://api.lanyard.rest/v1/users/${config.discordUserId}`)
})

View File

@@ -0,0 +1,13 @@
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig(event)
const coding = await $fetch(`https://wakatime.com/share/${config.wakatimeUserId}/${config.wakatimeCodig}.json`)
const editors = await $fetch(`https://wakatime.com/share/${config.wakatimeUserId}/${config.wakatimeEditors}.json`)
const os = await $fetch(`https://wakatime.com/share/${config.wakatimeUserId}/${config.wakatimeOs}.json`)
const languages = await $fetch(`https://wakatime.com/share/${config.wakatimeUserId}/${config.wakatimeLanguages}.json`)
return {
coding,
editors,
os,
languages,
}
})