From ec1f2c7b8ffbc74885519423f6850b1ed1819e74 Mon Sep 17 00:00:00 2001 From: Zsolt Tasnadi Date: Mon, 23 Mar 2026 16:34:10 +0100 Subject: [PATCH] catalog permalink --- apps/frontend/src/pages/catalog.astro | 242 +++---------------- apps/frontend/src/pages/catalog/[name].astro | 228 +++++++++++++++++ apps/frontend/src/pages/index.astro | 4 +- 3 files changed, 266 insertions(+), 208 deletions(-) create mode 100644 apps/frontend/src/pages/catalog/[name].astro diff --git a/apps/frontend/src/pages/catalog.astro b/apps/frontend/src/pages/catalog.astro index 0101a58..e3af328 100644 --- a/apps/frontend/src/pages/catalog.astro +++ b/apps/frontend/src/pages/catalog.astro @@ -27,144 +27,44 @@ const softwares = json.softwares;
- {softwares.map(({ software, releases, latestRelease }) => { - const stableReleases = releases.filter((r: any) => !r.version.startsWith('dev-')); - const devReleases = releases.filter((r: any) => r.version.startsWith('dev-')); + {softwares.map(({ software, releases }) => { + const latestStable = releases + .filter((r: any) => !r.version.startsWith('dev-')) + .sort((a: any, b: any) => new Date(b.UpdatedAt).getTime() - new Date(a.UpdatedAt).getTime())[0]; + return ( -
+
-
-

{software.title}

- - {software.status} - -
-

{software.desc}

-
-
Author: {software.author}
-
Platform: {software.platform}
-
- - {latestRelease && ( -
- {latestRelease.htmlFolderPath ? ( - ▶ Play - ) : ( - ▶ Play - )} - {latestRelease.cartridgePath ? ( - Download - ) : ( - Download - )} - {latestRelease.sourcePath ? ( - Source - ) : ( - Source - )} - {latestRelease.docsFolderPath ? ( - Docs - ) : ( - Docs - )} -
- )} - -
- - Releases ({releases.length}) - - -
- {/* Desktop Table View */} -
- - - - - - - - - - - {stableReleases.map((release: any) => ( - - - - - - - ))} - {devReleases.length > 0 && ( - - - - )} - {devReleases.map((release: any) => ( - - - - - - - ))} - -
VersionCreatedUpdatedActions
{release.version}{formatDateTime(release.CreatedAt)}{formatDateTime(release.UpdatedAt)} - {release.htmlFolderPath ? (▶ Play) : (▶ Play)} - {release.cartridgePath ? (Download) : (Download)} - {release.sourcePath ? (Source) : (Source)} - {release.docsFolderPath ? (Docs) : (Docs)} -
Development Releases
{release.version}{formatDateTime(release.CreatedAt)}{formatDateTime(release.UpdatedAt)} - {release.htmlFolderPath ? (▶ Play) : (▶ Play)} - {release.cartridgePath ? (Download) : (Download)} - {release.sourcePath ? (Source) : (Source)} - {release.docsFolderPath ? (Docs) : (Docs)} -
+
+
+
+ +

{software.title}

+
+ + {software.status} + +
+

{software.desc}

+
+ Author: {software.author} + + Platform: {software.platform} +
- {/* Mobile Stacked View */} -
- {stableReleases.map((release: any) => ( -
-
- {release.version} - Created: {formatDateTime(release.CreatedAt)} - Updated: {formatDateTime(release.UpdatedAt)} -
-
- {release.htmlFolderPath ? (▶ Play) : (▶ Play)} - {release.cartridgePath ? (Download) : (Download)} - {release.sourcePath ? (Source) : (Source)} - {release.docsFolderPath ? (Docs) : (Docs)} -
-
- ))} - {devReleases.length > 0 && ( -
Development Releases
+
+ {latestStable?.htmlFolderPath && ( + ▶ Play )} - {devReleases.map((release: any) => ( -
-
- {release.version} - Created: {formatDateTime(release.CreatedAt)} - Updated: {formatDateTime(release.UpdatedAt)} -
-
- {release.htmlFolderPath ? (▶ Play) : (▶ Play)} - {release.cartridgePath ? (Download) : (Download)} - {release.sourcePath ? (Source) : (Source)} - {release.docsFolderPath ? (Docs) : (Docs)} -
-
- ))} + + ℹ More Info +
-
+
-
- ) - })} + )})}
@@ -216,89 +116,19 @@ const softwares = json.softwares; @apply p-6; } .software-title { - @apply text-2xl font-semibold mb-2; + @apply text-2xl font-bold mb-0; } .software-desc { - @apply text-gray-600 mb-4; + @apply text-gray-600 mb-3; } .software-meta { - @apply text-sm text-gray-500 mb-4; - } - .latest-release-actions { - @apply flex flex-row flex-wrap gap-1 mb-4 sm:absolute sm:top-4 sm:right-4 sm:flex-col sm:mb-0 z-10; + @apply text-sm text-gray-500; } /* Small Action Buttons */ .btn-base-sm { - @apply inline-block font-bold py-1 px-2 rounded-lg text-sm transition-colors; + @apply inline-flex items-center justify-center font-bold py-2.5 px-5 rounded-xl text-sm transition-all active:scale-95; } - .btn-play-sm { @apply btn-base-sm bg-purple-600 hover:bg-purple-700 text-white; } - .btn-download-sm { @apply btn-base-sm bg-blue-600 hover:bg-blue-700 text-white; } - .btn-source-sm { @apply btn-base-sm bg-green-600 hover:bg-green-700 text-white; } - .btn-docs-sm { @apply btn-base-sm bg-yellow-600 hover:bg-yellow-700 text-white; } - .btn-disabled-sm { @apply btn-base-sm bg-gray-200 text-gray-400 cursor-not-allowed; } - - .releases-summary { - @apply cursor-pointer font-semibold text-purple-600 hover:text-purple-800; - } - - /* Desktop Table Styles */ - .desktop-releases { - @apply hidden sm:block overflow-x-auto; - } - .releases-table { - @apply min-w-full divide-y divide-gray-200; - } - .releases-thead { - @apply bg-gray-50; - } - .releases-th { - @apply px-3 py-2 text-left text-xs font-medium text-gray-500 uppercase tracking-wider; - } - .releases-tbody { - @apply bg-white divide-y divide-gray-200; - } - .releases-td { - @apply px-3 py-2 whitespace-nowrap text-sm; - } - - /* Action Links */ - .action-link-base { - @apply hover:underline mr-2 last:mr-0; - } - .action-link-purple { @apply action-link-base text-purple-600 hover:text-purple-900; } - .action-link-blue { @apply action-link-base text-blue-600 hover:text-blue-900; } - .action-link-green { @apply action-link-base text-green-600 hover:text-green-900; } - .action-link-yellow { @apply action-link-base text-yellow-600 hover:text-yellow-900; } - .action-link-disabled { @apply text-gray-400 cursor-not-allowed mr-2 last:mr-0; } - - /* Mobile Release Styles */ - .mobile-releases { - @apply sm:hidden space-y-4; - } - .release-mobile-card { - @apply border border-gray-100 rounded-lg p-4 bg-gray-50 shadow-sm; - } - .release-mobile-header { - @apply flex flex-col mb-3 border-b border-gray-200 pb-2; - } - .release-mobile-version { - @apply font-bold text-gray-900 text-lg break-words; - } - .release-mobile-date { - @apply text-xs text-gray-500 mt-1; - } - .release-mobile-grid { - @apply grid grid-cols-2 gap-2; - } - - /* Mobile Buttons */ - .mobile-btn-base { - @apply flex items-center justify-center py-2 px-3 rounded text-sm font-bold shadow-sm; - } - .mobile-btn-play { @apply mobile-btn-base bg-purple-600 text-white; } - .mobile-btn-download { @apply mobile-btn-base bg-blue-600 text-white; } - .mobile-btn-source { @apply mobile-btn-base bg-green-600 text-white; } - .mobile-btn-docs { @apply mobile-btn-base bg-yellow-600 text-white; } - .mobile-btn-disabled { @apply mobile-btn-base bg-gray-200 text-gray-400 cursor-not-allowed; } + .btn-play-sm { @apply btn-base-sm bg-purple-600 hover:bg-purple-700 text-white shadow-lg shadow-purple-600/20; } + .btn-info-sm { @apply btn-base-sm bg-gray-100 hover:bg-gray-200 text-gray-700; } \ No newline at end of file diff --git a/apps/frontend/src/pages/catalog/[name].astro b/apps/frontend/src/pages/catalog/[name].astro new file mode 100644 index 0000000..a4bd3b0 --- /dev/null +++ b/apps/frontend/src/pages/catalog/[name].astro @@ -0,0 +1,228 @@ +--- +import Layout from '../../layouts/Layout.astro'; +import { formatDateTime } from '../../utils/dateFormat'; + +export async function getStaticPaths() { + const BASE = "https://games.teletype.hu"; + const API = BASE + "/api/software"; + const res = await fetch(API); + const json = await res.json(); + const softwares = json.softwares; + + return softwares.map((item: any) => ({ + params: { name: item.software.name }, + props: { project: item }, + })); +} + +const { project } = Astro.props; +const { software, releases } = project; +const BASE = "https://games.teletype.hu"; + +const stableReleases = releases + .filter((r: any) => !r.version.startsWith('dev-')) + .sort((a: any, b: any) => new Date(b.UpdatedAt).getTime() - new Date(a.UpdatedAt).getTime()); +const devReleases = releases + .filter((r: any) => r.version.startsWith('dev-')) + .sort((a: any, b: any) => new Date(b.UpdatedAt).getTime() - new Date(a.UpdatedAt).getTime()); + +const latestStable = stableReleases[0]; +--- + + +
+
+
+ + +
+
+
+ + {software.status} + + {software.platform} +
+

{software.title}

+

{software.desc}

+
+
+
+
+ +
+
+ + +
+
+

+ Project Info +

+
+
+
Author
+
{software.author}
+
+
+
Platform
+
{software.platform}
+
+ {software.license && ( +
+
License
+
{software.license}
+
+ )} + {software.site && ( +
+
Source Code
+
+ + Visit Repository ↗ + +
+
+ )} +
+
+
+ + +
+ + + {latestStable && ( +
+
+
+
+ Latest Stable +
+

{latestStable.version}

+

Released: {formatDateTime(latestStable.UpdatedAt)}

+
+ +
+ {latestStable.htmlFolderPath && ( + + ▶ Play Now + + )} + {latestStable.cartridgePath && ( + + 💾 Download + + )} + {latestStable.sourcePath && ( + + 📄 Source + + )} + {latestStable.docsFolderPath && ( + + 📖 Docs + + )} +
+
+
+ )} + + +
+
+

All Releases

+
+ +
+ {/* Desktop Table */} + + + {/* Mobile View */} +
+ {releases.map((release: any) => ( +
+
+
+
{release.version}
+
{formatDateTime(release.UpdatedAt)}
+
+ {release.version.startsWith('dev-') && ( + Dev + )} +
+
+ {release.htmlFolderPath && Play} + {release.cartridgePath && Download} + {release.sourcePath && Source} + {release.docsFolderPath && Docs} +
+
+ ))} +
+
+
+
+
+
+
+
+ + diff --git a/apps/frontend/src/pages/index.astro b/apps/frontend/src/pages/index.astro index ff44738..f008109 100644 --- a/apps/frontend/src/pages/index.astro +++ b/apps/frontend/src/pages/index.astro @@ -156,8 +156,8 @@ const YOUTUBE_CHANNEL_ID = import.meta.env.YOUTUBE_CHANNEL_ID; ▶ Play in Browser )} - - View in Catalog + + View Project Details