change order of technology component

This commit is contained in:
2026-04-19 11:25:16 +02:00
parent 06e0d022c2
commit 67e01e9a5e
4 changed files with 181 additions and 17 deletions

View File

@@ -1,15 +1,23 @@
import { createFileRoute } from '@tanstack/react-router'
import { computeDuration, formatDate, CONTACT_EMAIL } from '#/data/portfolio'
import type { TExperience, TEducation, TSkillGroup } from '#/types/strapi'
import {
experiences,
educations,
skillGroups,
computeDuration,
formatDate,
CONTACT_EMAIL,
} from '#/data/portfolio'
import type { Experience, Education, SkillGroup } from '#/data/portfolio'
fetchExperiences,
fetchEducations,
fetchSkillGroups,
} from '#/data/loaders/portfolio'
export const Route = createFileRoute('/')({ component: HomePage })
export const Route = createFileRoute('/')({
loader: async () => {
const [experiences, educations, skillGroups] = await Promise.all([
fetchExperiences(),
fetchEducations(),
fetchSkillGroups(),
])
return { experiences, educations, skillGroups }
},
component: HomePage,
})
// ── Shared UI primitives ──────────────────────────────────────────────────
@@ -69,11 +77,16 @@ function SectionHeading({
// ── Experience card ───────────────────────────────────────────────────────
const EMPLOYMENT_TYPE_LABEL: Record<TExperience['employmentType'], string> = {
'full-time': 'Full-time',
'part-time': 'Part-time',
}
function ExperienceCard({
exp,
index,
}: {
readonly exp: Experience
readonly exp: TExperience
readonly index: number
}) {
const duration = computeDuration(exp.startDate, exp.endDate ?? undefined)
@@ -101,7 +114,7 @@ function ExperienceCard({
</h3>
</div>
<span className="mt-0.5 flex-shrink-0 rounded-full border border-[var(--chip-line)] bg-[var(--chip-bg)] px-2.5 py-0.5 text-xs font-semibold text-[var(--sea-ink-soft)]">
{exp.type}
{EMPLOYMENT_TYPE_LABEL[exp.employmentType]}
</span>
</div>
@@ -143,7 +156,7 @@ function ExperienceCard({
// ── Education card ────────────────────────────────────────────────────────
function EducationCard({ edu }: { readonly edu: Education }) {
function EducationCard({ edu }: { readonly edu: TEducation }) {
return (
<div className="island-shell feature-card rise-in rounded-2xl p-6">
<p className="island-kicker mb-2">{edu.institution}</p>
@@ -154,7 +167,7 @@ function EducationCard({ edu }: { readonly edu: Education }) {
<span>
{edu.startYear} {edu.endYear}
</span>
{edu.grade !== null && (
{edu.grade != null && (
<>
<span className="h-1 w-1 rounded-full bg-[var(--lagoon)]" />
<span className="font-semibold text-[var(--lagoon-deep)]">
@@ -169,7 +182,7 @@ function EducationCard({ edu }: { readonly edu: Education }) {
// ── Skill group card ──────────────────────────────────────────────────────
function SkillGroupCard({ group }: { readonly group: SkillGroup }) {
function SkillGroupCard({ group }: { readonly group: TSkillGroup }) {
return (
<div className="island-shell feature-card rise-in rounded-2xl p-5">
<p className="island-kicker mb-3">{group.category}</p>
@@ -185,6 +198,7 @@ function SkillGroupCard({ group }: { readonly group: SkillGroup }) {
// ── Page ──────────────────────────────────────────────────────────────────
function HomePage() {
const { experiences, educations, skillGroups } = Route.useLoaderData()
return (
<main className="page-wrap px-4 pb-16 pt-10">
{/* ── Hero ──────────────────────────────────────────── */}
@@ -248,7 +262,7 @@ function HomePage() {
/>
<div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
{skillGroups.map((group) => (
<SkillGroupCard key={group.category} group={group} />
<SkillGroupCard key={group.id} group={group} />
))}
</div>
</section>