add more strapi shit
All checks were successful
Deployment / Deploy website (push) Successful in 2m57s
Deployment / Deploy strapi (push) Successful in 2m54s

This commit is contained in:
Benjamin Palko 2025-05-12 18:12:24 -04:00
parent 18bde0daca
commit 6fa049504b
24 changed files with 595 additions and 62 deletions

View file

@ -1,4 +1,5 @@
import { env } from '$env/dynamic/private';
import { logger } from '$lib/server/logger';
import { Strapi } from '$lib/server/strapi';
import type { Handle, HandleServerError } from '@sveltejs/kit';
import { randomUUID } from 'crypto';
@ -6,7 +7,7 @@ import { randomUUID } from 'crypto';
export const handleError: HandleServerError = async ({ error, event, message, status }) => {
const errorId = randomUUID();
console.error(error, { errorId, event, message, status });
logger.error({ error, errorId, event, message, status }, 'Blyat');
return {
message: 'An Internal Error Occurred',

View file

@ -15,6 +15,22 @@ export class Strapi {
});
}
async SiteBackground() {
const background = this.client.single('site-background');
return await background.find({
populate: ['Background']
});
}
async About() {
const about = this.client.single('about');
return await about.find({
populate: ['Titles', 'Photo', 'Activities']
});
}
async Blogs() {
const blogs = this.client.collection('blogs');
@ -30,4 +46,18 @@ export class Strapi {
populate: ['Header', 'Topics']
});
}
async Experiences() {
const experiences = this.client.collection('experiences');
return await experiences.find({
populate: ['Logo']
});
}
async Education() {
const education = this.client.collection('educations');
return await education.find({});
}
}

View file

@ -0,0 +1,44 @@
import { logger } from '$lib/server/logger';
import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
interface Data {
about: {
name: string;
bio: string;
titles: string[];
photo: {
url: string;
};
activities: { title: string; description: string }[];
};
}
export const load: PageServerLoad = async ({ locals }): Promise<Data | undefined> => {
const { strapi } = locals;
try {
const { data: about } = await strapi.About();
return {
about: {
name: about.Name,
bio: about.Bio,
titles: about.Titles.map((title: { value: string }) => title.value),
photo: {
url: about.Photo.url
},
activities: about.Activities.map((item: { Title: string; Description: string }) => {
return { title: item.Title, description: item.Description };
})
}
} satisfies Data;
} catch (err) {
if (err instanceof Error) {
logger.error('Uh-oh!', err);
if (err instanceof Error) {
error(500, err);
}
}
}
};

View file

@ -1,69 +1,37 @@
<script lang="ts">
import Hero from '$lib/components/Hero.svelte';
import { Braces, Gamepad2, HeartHandshake, MonitorCog } from 'lucide-svelte';
import { Braces } from 'lucide-svelte';
import type { PageProps } from './$types';
const description =
'Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae pellentesque sem placerat. In id cursus mi pretium tellus duis convallis. Tempus leo eu aenean sed diam urna tempor. Pulvinar vivamus fringilla lacus nec metus bibendum egestas. Iaculis massa nisl malesuada lacinia integer nunc posuere. Ut hendrerit semper vel class aptent taciti sociosqu. Ad litora torquent per conubia nostra inceptos himenaeos.';
let { data }: PageProps = $props();
let about = $derived(data.about!);
type ActivityItem = Exclude<typeof about.activities, undefined>[number];
</script>
{#snippet Activity(item: ActivityItem)}
<div class="flex flex-col gap-4 lg:flex-row">
<Braces size={48} class="text-primary" />
<div class="flex flex-col">
<h3 class="text-xl">{item.title}</h3>
<p class="max-w-2xl">
{item.description}
</p>
</div>
</div>
{/snippet}
<div class="flex flex-col items-center px-6 md:px-12">
<div class="lg:py-48">
<Hero
photo="/waterfall-cropped.jpg"
titles={[
'Software Engineer',
'Game Developer',
'Linux Enjoyer',
'Cyclist',
'Goalie for Hire ⚽'
]}
name="Benjamin Palko"
{description}
/>
<Hero photo={about.photo.url} titles={about.titles} name={about.name} description={about.bio} />
</div>
<div class="grid grid-cols-1 gap-8 md:grid-cols-2">
<div class="col-span-full">
<h2 class="border-primary w-fit border-b text-2xl font-light">What I Do</h2>
</div>
<div class="flex flex-col gap-4 lg:flex-row">
<Braces size={48} class="text-primary" />
<div class="flex flex-col">
<h3 class="text-xl">Web Development</h3>
<p class="max-w-2xl">
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae
pellentesque sem placerat. In id cursus mi pretium tellus duis convallis.
</p>
</div>
</div>
<div class="flex flex-col gap-4 lg:flex-row">
<Gamepad2 size={48} class="text-primary" />
<div class="flex flex-col">
<h3 class="text-xl">Video Game Development</h3>
<p class="max-w-2xl">
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae
pellentesque sem placerat. In id cursus mi pretium tellus duis convallis.
</p>
</div>
</div>
<div class="flex flex-col gap-4 lg:flex-row">
<MonitorCog size={48} class="text-primary" />
<div class="flex flex-col">
<h3 class="text-xl">Linux Ricing</h3>
<p class="max-w-2xl">
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae
pellentesque sem placerat. In id cursus mi pretium tellus duis convallis.
</p>
</div>
</div>
<div class="flex flex-col gap-4 lg:flex-row">
<HeartHandshake size={48} class="text-primary" />
<div class="flex flex-col">
<h3 class="text-xl">Open-Source Development</h3>
<p class="max-w-2xl">
Lorem ipsum dolor sit amet consectetur adipiscing elit. Quisque faucibus ex sapien vitae
pellentesque sem placerat. In id cursus mi pretium tellus duis convallis.
</p>
</div>
</div>
{#each about.activities as activity (activity.title)}
{@render Activity(activity)}
{/each}
</div>
</div>

View file

@ -1,3 +1,4 @@
import { logger } from '$lib/server/logger';
import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
@ -25,7 +26,9 @@ export const load: PageServerLoad = async ({ locals }) => {
meta
};
} catch (err) {
console.log('Uh-oh!');
error(500, err.message);
logger.error('Uh-oh!', err);
if (err instanceof Error) {
error(500, err);
}
}
};

View file

@ -2,6 +2,7 @@ import { env } from '$env/dynamic/private';
import { fail } from '@sveltejs/kit';
import { createTransport } from 'nodemailer';
import type { Actions } from './$types';
import { logger } from '$lib/server/logger';
export const actions = {
default: async ({ request }) => {
@ -74,7 +75,7 @@ export const actions = {
}
};
} catch (error) {
console.error(error);
logger.error(error);
}
}
} satisfies Actions;

View file

@ -0,0 +1,43 @@
import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
import { logger } from '$lib/server/logger';
export const load: PageServerLoad = async ({ locals }) => {
const { strapi } = locals;
try {
const { data: experiences, meta: experiencesMeta } = await strapi.Experiences();
const { data: education, meta: educationMeta } = await strapi.Education();
return {
experiences: experiences.map((item) => {
return {
title: item.Title,
company: item.Company,
description: item.Description,
startDate: item.StartDate,
endDate: item.EndDate,
logo: item.Logo
};
}),
education: education.map((item) => {
return {
institute: item.Institute,
field: item.Field,
description: item.Description,
startDate: item.StartDate,
endDate: item.EndDate
};
}),
meta: {
experiences: experiencesMeta,
education: educationMeta
}
};
} catch (err) {
logger.error('Uh-oh!', err);
if (err instanceof Error) {
error(500, err);
}
}
};

View file

@ -1,5 +1,98 @@
<script>
import Wip from '$lib/components/WIP.svelte';
<script lang="ts">
import dayjs from 'dayjs';
import type { PageProps } from './$types';
let { data }: PageProps = $props();
type ExperienceItem = Exclude<typeof experiences, undefined>[number];
type EducationItem = Exclude<typeof education, undefined>[number];
let experiences = $derived(
data.experiences?.sort((a, b) => {
if (dayjs(a.endDate).isBefore(b.startDate)) {
return 1;
}
return -1;
})
);
let education = $derived(
data.education?.sort((a, b) => {
if (dayjs(a.endDate).isBefore(b.startDate)) {
return 1;
}
return -1;
})
);
</script>
<Wip />
{#snippet ExperienceEntry(item: ExperienceItem)}
<div class="bg-base-100 rounded">
<div class="flex items-center gap-2">
<div class="badge badge-outline badge-primary">
{dayjs(item.startDate).format('MMM YYYY')} - {item.endDate
? dayjs(item.endDate).format('MMM YYYY')
: 'Current'}
</div>
<p class="font-light text-gray-400">{item.company}</p>
</div>
<div class="flex flex-col gap-2 p-4">
<h3 class="text-lg font-semibold">{item.title}</h3>
<p>{item.description}</p>
</div>
</div>
{/snippet}
{#snippet EducationEntry(item: EducationItem)}
<div class="bg-base-100 rounded">
<div class="flex items-center gap-2">
<div class="badge badge-outline badge-primary">
{dayjs(item.startDate).format('MMM YYYY')} - {item.endDate
? dayjs(item.endDate).format('MMM YYYY')
: 'Current'}
</div>
<p class="font-light text-gray-400">{item.institute}</p>
</div>
<div class="flex flex-col gap-2 p-4">
<h3 class="text-lg font-semibold">{item.field}</h3>
<p>{item.description}</p>
</div>
</div>
{/snippet}
<div class="grid w-fit gap-4 px-6 py-6 sm:px-8 sm:py-4 lg:grid-cols-2">
<!-- Experience -->
<div class="col-span-full">
<div class="flex flex-col gap-1">
<h2 class="text-2xl font-light">Experience</h2>
<div class="bg-base-100 h-0.5 w-48 rounded-full">
<div class="bg-primary h-0.5 w-1/3 rounded-full"></div>
</div>
</div>
</div>
{#if !experiences}
Looks like I have no experience :(
{:else}
{#each experiences as item (item.company)}
{@render ExperienceEntry(item)}
{/each}
{/if}
<!-- Education -->
<div class="col-span-full">
<div class="flex flex-col gap-1">
<h2 class="text-2xl font-light">Education</h2>
<div class="bg-base-100 h-0.5 w-48 rounded-full">
<div class="bg-primary h-0.5 w-1/3 rounded-full"></div>
</div>
</div>
</div>
{#if !education}
Looks like I have no education :(
{:else}
{#each education as item (item.field)}
{@render EducationEntry(item)}
{/each}
{/if}
</div>