ui changes and cs prices
All checks were successful
Test and deploy staging / staging (push) Successful in 11m52s
All checks were successful
Test and deploy staging / staging (push) Successful in 11m52s
This commit is contained in:
@@ -2,24 +2,46 @@
|
||||
import { resolve } from '$app/paths';
|
||||
import portrait from '$lib/assets/stan.jpg?url';
|
||||
import ProgressBar from '$lib/components/ProgressBar.svelte';
|
||||
import ProjectIcon from '$lib/components/ProjectIcon.svelte';
|
||||
import * as Card from '$lib/components/ui/card/index.js';
|
||||
import { projects } from '$lib/projects';
|
||||
import ArrowRight from 'lucide-svelte/icons/arrow-right';
|
||||
import ExternalLink from 'lucide-svelte/icons/external-link';
|
||||
import Mail from 'lucide-svelte/icons/mail';
|
||||
import BriefcaseBusiness from 'lucide-svelte/icons/briefcase-business';
|
||||
import GraduationCap from 'lucide-svelte/icons/graduation-cap';
|
||||
import type { PageProps } from './$types';
|
||||
|
||||
let { data }: PageProps = $props();
|
||||
const experienceImages = import.meta.glob<string>(
|
||||
'/src/lib/assets/experience/*.{webp,png,jpg,jpeg,avif,svg}',
|
||||
{ eager: true, query: '?url', import: 'default' }
|
||||
);
|
||||
|
||||
function experienceImage(filename: string) {
|
||||
return (
|
||||
['webp', 'png', 'jpg', 'jpeg', 'avif', 'svg']
|
||||
.map((extension) => experienceImages[`/src/lib/assets/experience/${filename}.${extension}`])
|
||||
.find(Boolean) ??
|
||||
(filename === 'cargill'
|
||||
? experienceImages[
|
||||
'/src/lib/assets/experience/Cargill-Logo-R-Black-and-Leaf-Green-RGB.webp'
|
||||
]
|
||||
: undefined)
|
||||
);
|
||||
}
|
||||
|
||||
const experience = [
|
||||
{ when: '2026–now', role: 'associate software engineer', place: 'Cargill' },
|
||||
{ when: '2026–now', role: 'associate software engineer', place: 'Cargill', icon: 'cargill' },
|
||||
{
|
||||
when: '2021–2026',
|
||||
role: 'BSc computer science · software engineering',
|
||||
place: 'The Hague University of Applied Sciences'
|
||||
place: 'The Hague University of Applied Sciences',
|
||||
icon: 'the-hague-university'
|
||||
},
|
||||
{ when: '2026', role: 'software engineering intern', place: '3webapps' },
|
||||
{ when: '2023', role: 'software engineering intern', place: 'h5mag' },
|
||||
{ when: '2021–2023', role: 'junior IT specialist', place: 'Finance Plus' }
|
||||
{ when: '2026', role: 'software engineering intern', place: '3webapps', icon: '3webapps' },
|
||||
{ when: '2023', role: 'software engineering intern', place: 'h5mag', icon: 'h5mag' },
|
||||
{ when: '2021–2023', role: 'junior IT specialist', place: 'Finance Plus', icon: 'finance-plus' }
|
||||
] as const;
|
||||
</script>
|
||||
|
||||
@@ -82,41 +104,61 @@
|
||||
>projects <ArrowRight size={20} aria-hidden="true" /></a
|
||||
>
|
||||
</h2>
|
||||
<ul>
|
||||
<ul class="grid gap-3 sm:grid-cols-2">
|
||||
{#each projects as project (project.name)}
|
||||
<li class="border-b border-[var(--site-border)] text-lg">
|
||||
{#if project.external}
|
||||
<a
|
||||
href={project.href}
|
||||
rel="external"
|
||||
class="flex items-center justify-between gap-4 py-4 hover:text-[var(--site-muted)]"
|
||||
>
|
||||
<span class="min-w-0">
|
||||
<span class="block">{project.name}</span>
|
||||
<span class="mt-1 block text-base text-[var(--site-muted)]">{project.subtitle}</span
|
||||
<li>
|
||||
<Card.Root class="h-full py-0 transition-colors hover:bg-muted/50"
|
||||
><Card.Content class="p-0">
|
||||
{#if project.external}
|
||||
<a
|
||||
href={project.href}
|
||||
rel="external"
|
||||
class="flex min-h-28 items-start justify-between gap-4 p-5"
|
||||
>
|
||||
</span><ExternalLink
|
||||
size={18}
|
||||
aria-hidden="true"
|
||||
class="shrink-0 text-[var(--site-muted)]"
|
||||
/>
|
||||
</a>
|
||||
{:else}
|
||||
<a
|
||||
href={resolve(project.href)}
|
||||
class="flex items-center justify-between gap-4 py-4 hover:text-[var(--site-muted)]"
|
||||
>
|
||||
<span class="min-w-0">
|
||||
<span class="block">{project.name}</span>
|
||||
<span class="mt-1 block text-base text-[var(--site-muted)]">{project.subtitle}</span
|
||||
<span class="flex min-w-0 items-start gap-3">
|
||||
<span
|
||||
class="mt-0.5 flex size-10 shrink-0 items-center justify-center rounded-md border border-border bg-[var(--site-surface)] text-[var(--site-muted)]"
|
||||
>
|
||||
<ProjectIcon name={project.name} class="size-5" />
|
||||
</span>
|
||||
<span class="min-w-0">
|
||||
<span class="block font-medium">{project.name}</span>
|
||||
<span class="mt-1 block text-base text-[var(--site-muted)]"
|
||||
>{project.subtitle}</span
|
||||
>
|
||||
</span>
|
||||
</span><ExternalLink
|
||||
size={18}
|
||||
aria-hidden="true"
|
||||
class="shrink-0 text-[var(--site-muted)]"
|
||||
/>
|
||||
</a>
|
||||
{:else}
|
||||
<a
|
||||
href={resolve(project.href)}
|
||||
class="flex min-h-28 items-start justify-between gap-4 p-5"
|
||||
>
|
||||
</span><ArrowRight
|
||||
size={18}
|
||||
aria-hidden="true"
|
||||
class="shrink-0 text-[var(--site-muted)]"
|
||||
/>
|
||||
</a>
|
||||
{/if}
|
||||
<span class="flex min-w-0 items-start gap-3">
|
||||
<span
|
||||
class="mt-0.5 flex size-10 shrink-0 items-center justify-center rounded-md border border-border bg-[var(--site-surface)] text-[var(--site-muted)]"
|
||||
>
|
||||
<ProjectIcon name={project.name} class="size-5" />
|
||||
</span>
|
||||
<span class="min-w-0">
|
||||
<span class="block font-medium">{project.name}</span>
|
||||
<span class="mt-1 block text-base text-[var(--site-muted)]"
|
||||
>{project.subtitle}</span
|
||||
>
|
||||
</span>
|
||||
</span><ArrowRight
|
||||
size={18}
|
||||
aria-hidden="true"
|
||||
class="shrink-0 text-[var(--site-muted)]"
|
||||
/>
|
||||
</a>
|
||||
{/if}
|
||||
</Card.Content></Card.Root
|
||||
>
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
@@ -135,37 +177,41 @@
|
||||
<li class="border-b border-[var(--site-border)] text-lg">
|
||||
<a
|
||||
href={resolve('/lists/[slug]', { slug: list.slug })}
|
||||
class="block py-4 hover:text-[var(--site-muted)]"
|
||||
class={list.isProgress
|
||||
? 'grid grid-cols-[minmax(0,1fr)_8rem_auto] items-center gap-3 py-4 hover:text-[var(--site-muted)]'
|
||||
: 'flex items-center justify-between gap-3 py-4 hover:text-[var(--site-muted)]'}
|
||||
>
|
||||
<span class="flex flex-wrap items-center justify-between gap-x-6 gap-y-1">
|
||||
<span class="flex items-center gap-3">
|
||||
{#if list.pictureUrl}<img
|
||||
src={list.pictureUrl}
|
||||
alt=""
|
||||
loading="lazy"
|
||||
width="40"
|
||||
height="40"
|
||||
class="h-10 w-10 rounded bg-[var(--site-surface)] object-cover"
|
||||
/>{/if}
|
||||
<span>{list.name}</span>
|
||||
</span>
|
||||
<span class="inline-flex items-center gap-1 text-base text-[var(--site-muted)]">
|
||||
{#if list.isProgress && data.user}
|
||||
{list.total ? Math.round((list.checked / list.total) * 100) : 0}% · {list.checked}/{list.total}
|
||||
{:else}
|
||||
{list.total} {list.total === 1 ? 'item' : 'items'}
|
||||
{/if}
|
||||
<ArrowRight size={16} aria-hidden="true" />
|
||||
</span>
|
||||
<span class="flex min-w-0 items-center gap-3">
|
||||
{#if list.pictureUrl}<img
|
||||
src={list.pictureUrl}
|
||||
alt=""
|
||||
loading="lazy"
|
||||
width="40"
|
||||
height="40"
|
||||
class="h-10 w-10 rounded bg-[var(--site-surface)] object-cover"
|
||||
/>{/if}
|
||||
<span class="truncate">{list.name}</span>
|
||||
</span>
|
||||
{#if list.isProgress}<span class="mt-3 block"
|
||||
{#if list.isProgress}
|
||||
<span class="block w-32"
|
||||
><ProgressBar
|
||||
value={list.checked}
|
||||
max={list.total}
|
||||
label={`Progress on ${list.name}`}
|
||||
small
|
||||
/></span
|
||||
>{/if}
|
||||
>
|
||||
{/if}
|
||||
<span
|
||||
class="inline-flex min-w-16 items-center justify-end gap-1 whitespace-nowrap text-base text-[var(--site-muted)]"
|
||||
>
|
||||
{#if list.isProgress && data.user}
|
||||
{list.total ? Math.round((list.checked / list.total) * 100) : 0}%
|
||||
{:else}
|
||||
{list.total}
|
||||
{/if}
|
||||
<ArrowRight size={16} aria-hidden="true" />
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
{/each}
|
||||
@@ -176,14 +222,35 @@
|
||||
<h2 id="experience-heading" class="mb-4 text-2xl font-semibold tracking-tight">experience</h2>
|
||||
<ol>
|
||||
{#each experience as item (item.when + item.place)}
|
||||
{@const image = experienceImage(item.icon)}
|
||||
<li
|
||||
class="grid gap-1 border-t border-[var(--site-border)] py-4 sm:grid-cols-[minmax(0,1fr)_130px] sm:gap-6"
|
||||
class="grid grid-cols-[3rem_minmax(0,1fr)] gap-x-4 gap-y-1 border-t border-[var(--site-border)] py-4 sm:grid-cols-[3rem_minmax(0,1fr)_130px]"
|
||||
>
|
||||
<span
|
||||
class="row-span-2 flex size-12 items-center justify-center overflow-hidden rounded-md border border-border bg-[var(--site-surface)] text-muted-foreground sm:row-span-1"
|
||||
>
|
||||
{#if image}
|
||||
<img
|
||||
src={image}
|
||||
alt=""
|
||||
width="48"
|
||||
height="48"
|
||||
loading="lazy"
|
||||
class="size-full object-cover"
|
||||
/>
|
||||
{:else if item.icon === 'the-hague-university'}
|
||||
<GraduationCap class="size-5" aria-hidden="true" />
|
||||
{:else}
|
||||
<BriefcaseBusiness class="size-5" aria-hidden="true" />
|
||||
{/if}
|
||||
</span>
|
||||
<div class="min-w-0">
|
||||
<h3 class="font-medium">{item.role}</h3>
|
||||
<p class="mt-1 text-base text-[var(--site-muted)]">{item.place}</p>
|
||||
</div>
|
||||
<span class="text-base text-[var(--site-muted)] sm:text-right">{item.when}</span>
|
||||
<span class="col-start-2 text-base text-[var(--site-muted)] sm:col-start-3 sm:text-right"
|
||||
>{item.when}</span
|
||||
>
|
||||
</li>
|
||||
{/each}
|
||||
</ol>
|
||||
|
||||
Reference in New Issue
Block a user