116 lines
4.0 KiB
Plaintext

---
import { projects } from "../../lib/list";
import Section from "../../components/common/Section.astro";
import ProjectSnippet from "../../components/ProjectSnippet.astro";
import ProjectSnippetSkeleton from "../../components/ProjectSnippetSkeleton.astro";
import SearchBar from "../../components/common/SearchBar.astro";
import Layout from "../../layouts/Layout.astro";
import { GLOBAL } from "../../lib/variables";
---
<Layout>
<Fragment slot="head">
<title>{GLOBAL.projectTitle} • {GLOBAL.username}</title>
<meta
name="description"
content={GLOBAL.projectLongDescription}
/>
<meta property="og:title" content={`${GLOBAL.projectTitle} • ${GLOBAL.username}`} />
<meta
property="og:description"
content={GLOBAL.projectShortDescription}
/>
<meta property="og:image" content={`${GLOBAL.rootUrl}/${GLOBAL.profileImage}`} />
<meta property="og:url" content={`${GLOBAL.rootUrl}/projects`} />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content={`${GLOBAL.projectTitle} • ${GLOBAL.username}`} />
<meta
name="twitter:description"
content={GLOBAL.projectShortDescription}
/>
<meta name="twitter:image" content={`${GLOBAL.rootUrl}/${GLOBAL.profileImage}`} />
<meta http-equiv="content-language" content="en" />
<meta name="language" content="English" />
<link rel="canonical" href={`${GLOBAL.rootUrl}/projects`} />
</Fragment>
<!-- Search functionality is provided by SearchScript.astro -->
<Section class="py-4 my-8">
<div x-data="searchProjects" x-init="init()" x-cloak>
<!-- Search container - positioned at the top -->
<div class="mb-4 pt-0">
<div class="w-full">
<SearchBar
placeholder="Search projects..."
ariaLabel="Search projects"
/>
</div>
</div>
<div class="flex items-center gap-4 pt-8 pb-16">
<h1 class="font-display text-3xl sm:text-4xl leading-loose">{GLOBAL.projectsName}</h1>
</div>
<!-- No results message -->
<div
x-show="searchQuery !== '' && !hasResults"
x-transition
class="text-center py-8 my-4 border-2 border-dashed border-current zag-text rounded-lg"
>
<p class="text-xl font-semibold zag-text">No Projects Found</p>
</div>
<!-- Loading skeleton -->
<div
x-show="loading"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-200"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
>
{Array.from({ length: 3 }).map((_, i) => (
<ProjectSnippetSkeleton />
))}
</div>
<!-- Actual content -->
<ul
id="project-list"
x-show="!loading"
x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
>
{
projects.map((project) => {
const projectTags = project.tags ? project.tags.join(' ').toLowerCase() : '';
const githubUrl = project.githubUrl || '';
const liveUrl = project.liveUrl || '';
return (
<li class="project-item"
data-title={project.title.toLowerCase()}
data-description={project.description.toLowerCase()}
data-tags={projectTags}
data-github={githubUrl.toLowerCase()}
data-live={liveUrl.toLowerCase()}>
<ProjectSnippet
title={project.title}
description={project.description}
url={project.filename}
githubUrl={project.githubUrl}
liveUrl={project.liveUrl}
tags={project.tags ?? []}
/>
</li>
);
})
}
</ul>
</div>
</Section>
</Layout>