diff --git a/package.json b/package.json index 8b5870a..74466d2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atridotdad", "type": "module", - "version": "4.0.0", + "version": "4.1.0", "scripts": { "dev": "astro dev", "build": "astro build", diff --git a/src/components/ProjectsIsland.astro b/src/components/ProjectsIsland.astro deleted file mode 100644 index faa1b71..0000000 --- a/src/components/ProjectsIsland.astro +++ /dev/null @@ -1,144 +0,0 @@ ---- -import { Icon } from "astro-icon/components"; -import { config } from "../config"; -import { fetchGiteaInfoFromUrl, formatRelativeTime } from "../utils/gitea"; -import type { Project } from "../types"; - -Astro.response.headers.set( - "Cache-Control", - "public, max-age=300, s-maxage=300, stale-while-revalidate=60", -); - -function isGiteaDomain(url: string): boolean { - if (!config.siteConfig.giteaDomains) return true; - try { - const urlObj = new URL(url); - return config.siteConfig.giteaDomains.some( - (domain) => urlObj.origin === new URL(domain).origin, - ); - } catch { - return false; - } -} - -const projectsWithGiteaInfo = await Promise.all( - config.projects.map(async (project) => { - if ( - project.gitLink && - !project.giteaInfo && - isGiteaDomain(project.gitLink) - ) { - const giteaInfo = await fetchGiteaInfoFromUrl(project.gitLink); - if (giteaInfo) { - return { ...project, giteaInfo } as Project; - } - } - return project; - }), -); - -const sortedProjects = projectsWithGiteaInfo.sort((a, b) => { - const aTime = a.giteaInfo?.updatedAt - ? new Date(a.giteaInfo.updatedAt).getTime() - : 0; - const bTime = b.giteaInfo?.updatedAt - ? new Date(b.giteaInfo.updatedAt).getTime() - : 0; - return bTime - aTime; -}); ---- - - - -{ - sortedProjects.length === 0 && ( -

- No projects available yet. Check back soon! -

- ) -} diff --git a/src/components/ProjectsLoader.astro b/src/components/ProjectsLoader.astro deleted file mode 100644 index fd8844c..0000000 --- a/src/components/ProjectsLoader.astro +++ /dev/null @@ -1,7 +0,0 @@ ---- - ---- - -
- -
diff --git a/src/config.ts b/src/config.ts index e963ef2..3b8cc6e 100644 --- a/src/config.ts +++ b/src/config.ts @@ -206,6 +206,7 @@ export const config: Config = { id: "atrodotdad", name: "Personal Site", description: "My personal website built with Astro.", + webLink: "https://atri.dad", gitLink: "https://git.atri.dad/atridad/atridotdad", }, ], diff --git a/src/pages/projects.astro b/src/pages/projects.astro index c21cb0e..fab24fe 100644 --- a/src/pages/projects.astro +++ b/src/pages/projects.astro @@ -1,21 +1,189 @@ --- import Layout from "../layouts/Layout.astro"; -import ProjectsIsland from "../components/ProjectsIsland.astro"; -import ProjectsLoader from "../components/ProjectsLoader.astro"; +import { Icon } from "astro-icon/components"; +import { config } from "../config"; +import { fetchGiteaInfoFromUrl, formatRelativeTime } from "../utils/gitea"; +import type { Project } from "../types"; export const prerender = false; + +Astro.response.headers.set( + "Cache-Control", + "public, max-age=300, s-maxage=300, stale-while-revalidate=60", +); + +function isGiteaDomain(url: string): boolean { + if (!config.siteConfig.giteaDomains) return true; + try { + const urlObj = new URL(url); + return config.siteConfig.giteaDomains.some( + (domain) => urlObj.origin === new URL(domain).origin, + ); + } catch { + return false; + } +} + +const projectsWithGiteaInfo = await Promise.all( + config.projects.map(async (project) => { + if ( + project.gitLink && + !project.giteaInfo && + isGiteaDomain(project.gitLink) + ) { + const giteaInfo = await fetchGiteaInfoFromUrl(project.gitLink); + if (giteaInfo) { + return { ...project, giteaInfo } as Project; + } + } + return project; + }), +); + +const sortedProjects = projectsWithGiteaInfo.sort((a, b) => { + const aTime = a.giteaInfo?.updatedAt + ? new Date(a.giteaInfo.updatedAt).getTime() + : 0; + const bTime = b.giteaInfo?.updatedAt + ? new Date(b.giteaInfo.updatedAt).getTime() + : 0; + return bTime - aTime; +}); --- -
+

Projects

- - - +
    + { + sortedProjects.map((project) => ( +
  • + {/* Project icon/avatar */} +
    + {project.giteaInfo?.avatarUrl ? ( + {`${project.name} + ) : ( +
    + +
    + )} +
    + + {/* Main content */} +
    +
    +

    + {project.name} +

    + {project.giteaInfo?.updatedAt && ( + + {formatRelativeTime( + project.giteaInfo.updatedAt, + )} + + )} +
    + +

    + {project.description} +

    + + {/* Languages & Topics */} +
    + {project.giteaInfo?.languages + ?.slice(0, 3) + .map((lang: string) => ( + + {lang} + + ))} + {project.giteaInfo?.topics + ?.slice(0, 4) + .map((topic: string) => ( + + {topic} + + ))} +
    +
    + + {/* Action buttons */} +
    + {project.webLink && ( + + + + )} + {project.gitLink && ( + + + + )} + {project.iosLink && ( + + + + )} + {project.androidLink && ( + + + + )} +
    +
  • + )) + } +
+ { + sortedProjects.length === 0 && ( +

+ No projects available yet. Check back soon! +

+ ) + }
diff --git a/src/utils/gitea.ts b/src/utils/gitea.ts index 9b0c1ca..b3d679e 100644 --- a/src/utils/gitea.ts +++ b/src/utils/gitea.ts @@ -4,6 +4,7 @@ export interface GiteaRepoInfo { size: number; defaultBranch: string; topics: string[]; + avatarUrl?: string; } export interface GiteaConfig { @@ -74,6 +75,7 @@ export async function fetchGiteaRepoInfo( size: data.size || 0, defaultBranch: data.default_branch || "main", topics: Array.isArray(data.topics) ? data.topics : [], + avatarUrl: data.avatar_url, }; } catch (error) { return null;