mirror of
https://github.com/anotherhadi/blog.git
synced 2026-05-20 13:32:33 +02:00
Update projects structure
Signed-off-by: Hadi <112569860+anotherhadi@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
---
|
||||
import type { GiteaRepoWithMirrors } from "../lib/gitea";
|
||||
import { getBannerUrl } from "../lib/gitea";
|
||||
import { ExternalLink, ChevronDown } from "@lucide/astro";
|
||||
|
||||
interface Props {
|
||||
repo: GiteaRepoWithMirrors;
|
||||
}
|
||||
|
||||
const { repo } = Astro.props;
|
||||
const bannerUrl = getBannerUrl(repo);
|
||||
|
||||
const platforms = [
|
||||
...(repo.mirrors.github ? [{ label: "GitHub", url: repo.mirrors.github }] : []),
|
||||
...(repo.mirrors.gitlab ? [{ label: "GitLab", url: repo.mirrors.gitlab }] : []),
|
||||
{ label: "Gitea", url: repo.html_url },
|
||||
];
|
||||
|
||||
const hasMultiplePlatforms = platforms.length > 1;
|
||||
---
|
||||
|
||||
<article
|
||||
class="card bg-base-100 shadow-xl border border-base-200 rounded-lg hover:shadow-2xl transition-shadow"
|
||||
>
|
||||
<figure class="aspect-video bg-base-200 overflow-hidden">
|
||||
<img
|
||||
src={bannerUrl}
|
||||
alt={repo.name}
|
||||
class="w-full h-full object-cover"
|
||||
onerror="this.parentElement.style.display='none'"
|
||||
/>
|
||||
</figure>
|
||||
|
||||
<div class="card-body">
|
||||
<h2 class="card-title hover:text-primary transition-colors">
|
||||
<a href={repo.html_url} target="_blank" rel="noopener noreferrer">
|
||||
{repo.name}
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
{repo.description && (
|
||||
<p class="text-base-content/80">{repo.description}</p>
|
||||
)}
|
||||
|
||||
<div class="flex flex-wrap gap-2 mt-2">
|
||||
{repo.topics.map((topic) => (
|
||||
<span class="badge badge-sm rounded-sm badge-soft badge-accent">
|
||||
{topic}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div class="card-actions justify-end mt-4 gap-2">
|
||||
{repo.website && (
|
||||
|
||||
<a
|
||||
href={repo.website}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="btn btn-soft btn-sm gap-1"
|
||||
>
|
||||
<ExternalLink class="size-4" />
|
||||
Website
|
||||
</a>
|
||||
)}
|
||||
|
||||
{hasMultiplePlatforms ? (
|
||||
<div class="dropdown dropdown-end">
|
||||
<div tabindex="0" role="button" class="btn btn-primary btn-sm gap-1">
|
||||
<ExternalLink class="size-4" />
|
||||
View Source
|
||||
<ChevronDown class="size-3" />
|
||||
</div>
|
||||
<ul
|
||||
tabindex="0"
|
||||
class="dropdown-content menu bg-base-100 rounded-xl z-10 w-36 p-1.5 shadow border border-base-200 text-sm"
|
||||
>
|
||||
{platforms.map(({ label, url }) => (
|
||||
<li>
|
||||
<a href={url} target="_blank" rel="noopener noreferrer">
|
||||
{label}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
<a
|
||||
href={repo.html_url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="btn btn-primary btn-sm gap-1"
|
||||
>
|
||||
<ExternalLink class="size-4" />
|
||||
View on Gitea
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
@@ -10,6 +10,8 @@ interface Props {
|
||||
location?: string;
|
||||
socialLinks?: {
|
||||
github?: string;
|
||||
gitlab?: string;
|
||||
gitea?: string;
|
||||
linkedin?: string;
|
||||
twitter?: string;
|
||||
bluesky?: string;
|
||||
@@ -68,6 +70,44 @@ const { name, title, description, avatar, location, socialLinks, gpgKey } =
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
{socialLinks.gitlab && (
|
||||
<div class="tooltip" data-tip="Gitlab">
|
||||
<a
|
||||
href={socialLinks.gitlab}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="btn btn-circle btn-ghost"
|
||||
aria-label="Gitlab"
|
||||
>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
fill="currentColor"
|
||||
role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m23.6004 9.5927-.0337-.0862L20.3.9814a.851.851 0 0 0-.3362-.405.8748.8748 0 0 0-.9997.0539.8748.8748 0 0 0-.29.4399l-2.2055 6.748H7.5375l-2.2057-6.748a.8573.8573 0 0 0-.29-.4412.8748.8748 0 0 0-.9997-.0537.8585.8585 0 0 0-.3362.4049L.4332 9.5015l-.0325.0862a6.0657 6.0657 0 0 0 2.0119 7.0105l.0113.0087.03.0213 4.976 3.7264 2.462 1.8633 1.4995 1.1321a1.0085 1.0085 0 0 0 1.2197 0l1.4995-1.1321 2.4619-1.8633 5.006-3.7489.0125-.01a6.0682 6.0682 0 0 0 2.0094-7.003z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
{socialLinks.gitea && (
|
||||
<div class="tooltip" data-tip="Gitea">
|
||||
<a
|
||||
href={socialLinks.gitea}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="btn btn-circle btn-ghost"
|
||||
aria-label="Gitea"
|
||||
>
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
fill="currentColor"
|
||||
role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.209 4.603c-.247 0-.525.02-.84.088-.333.07-1.28.283-2.054 1.027C-.403 7.25.035 9.685.089 10.052c.065.446.263 1.687 1.21 2.768 1.749 2.141 5.513 2.092 5.513 2.092s.462 1.103 1.168 2.119c.955 1.263 1.936 2.248 2.89 2.367 2.406 0 7.212-.004 7.212-.004s.458.004 1.08-.394c.535-.324 1.013-.893 1.013-.893s.492-.527 1.18-1.73c.21-.37.385-.729.538-1.068 0 0 2.107-4.471 2.107-8.823-.042-1.318-.367-1.55-.443-1.627-.156-.156-.366-.153-.366-.153s-4.475.252-6.792.306c-.508.011-1.012.023-1.512.027v4.474l-.634-.301c0-1.39-.004-4.17-.004-4.17-1.107.016-3.405-.084-3.405-.084s-5.399-.27-5.987-.324c-.187-.011-.401-.032-.648-.032zm.354 1.832h.111s.271 2.269.6 3.597C5.549 11.147 6.22 13 6.22 13s-.996-.119-1.641-.348c-.99-.324-1.409-.714-1.409-.714s-.73-.511-1.096-1.52C1.444 8.73 2.021 7.7 2.021 7.7s.32-.859 1.47-1.145c.395-.106.863-.12 1.072-.12zm8.33 2.554c.26.003.509.127.509.127l.868.422-.529 1.075a.686.686 0 0 0-.614.359.685.685 0 0 0 .072.756l-.939 1.924a.69.69 0 0 0-.66.527.687.687 0 0 0 .347.763.686.686 0 0 0 .867-.206.688.688 0 0 0-.069-.882l.916-1.874a.667.667 0 0 0 .237-.02.657.657 0 0 0 .271-.137 8.826 8.826 0 0 1 1.016.512.761.761 0 0 1 .286.282c.073.21-.073.569-.073.569-.087.29-.702 1.55-.702 1.55a.692.692 0 0 0-.676.477.681.681 0 1 0 1.157-.252c.073-.141.141-.282.214-.431.19-.397.515-1.16.515-1.16.035-.066.218-.394.103-.814-.095-.435-.48-.638-.48-.638-.467-.301-1.116-.58-1.116-.58s0-.156-.042-.27a.688.688 0 0 0-.148-.241l.516-1.062 2.89 1.401s.48.218.583.619c.073.282-.019.534-.069.657-.24.587-2.1 4.317-2.1 4.317s-.232.554-.748.588a1.065 1.065 0 0 1-.393-.045l-.202-.08-4.31-2.1s-.417-.218-.49-.596c-.083-.31.104-.691.104-.691l2.073-4.272s.183-.37.466-.497a.855.855 0 0 1 .35-.077z"/>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
{socialLinks.linkedin && (
|
||||
<div class="tooltip" data-tip="Linkedin">
|
||||
<a
|
||||
@@ -212,7 +252,7 @@ const { name, title, description, avatar, location, socialLinks, gpgKey } =
|
||||
</div>
|
||||
)}
|
||||
{socialLinks.kofi && (
|
||||
<div class="tooltip" data-tip="Ko-fi">
|
||||
<div class="tooltip" data-tip="Ko-fi - Support me">
|
||||
<a
|
||||
href={socialLinks.kofi}
|
||||
class="btn btn-circle btn-ghost"
|
||||
@@ -282,13 +322,17 @@ const { name, title, description, avatar, location, socialLinks, gpgKey } =
|
||||
|
||||
<div class="mt-12 flex gap-5">
|
||||
<a href="/blog" class="btn btn-ghost gap-2">
|
||||
Blog
|
||||
Blog Posts
|
||||
<ArrowRight class="size-4" />
|
||||
</a>
|
||||
<a href="/projects" class="btn btn-ghost gap-2">
|
||||
Projects
|
||||
<ArrowRight class="size-4" />
|
||||
</a>
|
||||
<a href="/#contact" class="btn btn-ghost gap-2">
|
||||
Contact Me
|
||||
<ArrowRight class="size-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
---
|
||||
import { Image } from "astro:assets";
|
||||
import TagBadge from "./TagBadge.astro";
|
||||
import { ExternalLink, Eye } from "@lucide/astro";
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
|
||||
interface Props {
|
||||
project: CollectionEntry<"projects">;
|
||||
}
|
||||
|
||||
const { project } = Astro.props;
|
||||
---
|
||||
|
||||
<article
|
||||
class="card bg-base-100 shadow-xl border border-base-200 rounded-lg hover:shadow-2xl transition-shadow"
|
||||
>
|
||||
<figure class="aspect-video">
|
||||
<Image
|
||||
src={project.data.image}
|
||||
alt={project.data.title}
|
||||
class="w-full h-full object-cover"
|
||||
width={600}
|
||||
height={400}
|
||||
/>
|
||||
</figure>
|
||||
<div class="card-body">
|
||||
<h2 class="card-title hover:text-primary transition-colors">
|
||||
<a href={`/projects/${project.id}`}>{project.data.title}</a>
|
||||
</h2>
|
||||
<p class="text-base-content/80">{project.data.description}</p>
|
||||
{
|
||||
project.data.tags && project.data.tags.length > 0 && (
|
||||
<div class="flex flex-wrap gap-2 mt-2">
|
||||
{project.data.tags.map((tag) => (
|
||||
<TagBadge tag={tag} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<div class="card-actions justify-end mt-4 gap-2">
|
||||
{
|
||||
project.data.demoLink && (
|
||||
<a
|
||||
href={project.data.demoLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="btn btn-sm btn-ghost gap-1"
|
||||
>
|
||||
<ExternalLink class="size-4" />
|
||||
Demo
|
||||
</a>
|
||||
)
|
||||
}
|
||||
{
|
||||
project.data.url && (
|
||||
<a
|
||||
href={project.data.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="btn btn-sm btn-ghost gap-1"
|
||||
>
|
||||
<ExternalLink class="size-4" />
|
||||
Website
|
||||
</a>
|
||||
)
|
||||
}
|
||||
{
|
||||
project.data.sourceLink && (
|
||||
<a
|
||||
href={project.data.sourceLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="btn btn-sm btn-ghost gap-1"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 32 32"
|
||||
fill="currentColor"
|
||||
>
|
||||
<path d="M16,2.345c7.735,0,14,6.265,14,14-.002,6.015-3.839,11.359-9.537,13.282-.7,.14-.963-.298-.963-.665,0-.473,.018-1.978,.018-3.85,0-1.312-.437-2.152-.945-2.59,3.115-.35,6.388-1.54,6.388-6.912,0-1.54-.543-2.783-1.435-3.762,.14-.35,.63-1.785-.14-3.71,0,0-1.173-.385-3.85,1.435-1.12-.315-2.31-.472-3.5-.472s-2.38,.157-3.5,.472c-2.677-1.802-3.85-1.435-3.85-1.435-.77,1.925-.28,3.36-.14,3.71-.892,.98-1.435,2.24-1.435,3.762,0,5.355,3.255,6.563,6.37,6.913-.403,.35-.77,.963-.893,1.872-.805,.368-2.818,.963-4.077-1.155-.263-.42-1.05-1.452-2.152-1.435-1.173,.018-.472,.665,.017,.927,.595,.332,1.277,1.575,1.435,1.978,.28,.787,1.19,2.293,4.707,1.645,0,1.173,.018,2.275,.018,2.607,0,.368-.263,.787-.963,.665-5.719-1.904-9.576-7.255-9.573-13.283,0-7.735,6.265-14,14-14Z" />
|
||||
</svg>
|
||||
Source
|
||||
</a>
|
||||
)
|
||||
}
|
||||
<div class="tooltip" data-tip="View project details">
|
||||
<a href={`/projects/${project.id}`} class="btn btn-sm btn-primary">
|
||||
<Eye class="size-4" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
@@ -1,9 +1,10 @@
|
||||
---
|
||||
import { getCollection } from "astro:content";
|
||||
import ProjectCard from "./ProjectCard.astro";
|
||||
import GiteaProjectCard from "./GiteaProjectCard.astro";
|
||||
import { ArrowRight } from "@lucide/astro";
|
||||
import { fetchGiteaRepos } from "../lib/gitea";
|
||||
|
||||
const projectEntries = await getCollection("projects");
|
||||
const repos = await fetchGiteaRepos();
|
||||
const latestRepos = repos.slice(0, 3); // 3 plus récents sur la homepage
|
||||
---
|
||||
|
||||
<section id="projects" class="py-20 px-4">
|
||||
@@ -12,21 +13,16 @@ const projectEntries = await getCollection("projects");
|
||||
<h2 class="text-4xl font-bold mb-4">Check out my latest work</h2>
|
||||
<p class="text-lg text-base-content/70">
|
||||
I enjoy the challenge of reimagining existing programs & scripts in my
|
||||
own unique way. By creating these projects from scratch, I can ensure
|
||||
complete control over every aspect of their design and functionality.
|
||||
own unique way.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{projectEntries.map((project) => <ProjectCard project={project} />)}
|
||||
{latestRepos.map((repo) => <GiteaProjectCard repo={repo} />)}
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-12">
|
||||
<a
|
||||
href="https://github.com/anotherhadi"
|
||||
target="_blank"
|
||||
class="btn btn-ghost gap-2"
|
||||
>
|
||||
<a href="/projects" class="btn btn-ghost gap-2">
|
||||
View All Projects
|
||||
<ArrowRight class="size-4" />
|
||||
</a>
|
||||
|
||||
Reference in New Issue
Block a user