- {releases.map((release) => (
+ {stableReleases.map((release: any) => (
| {release.version} |
-
- {new Date(release.CreatedAt).toLocaleDateString('en-US')}
- |
+ {new Date(release.CreatedAt).toLocaleDateString('en-US')} |
+ {new Date(release.UpdatedAt).toLocaleDateString('en-US')} |
- {release.htmlFolderPath ? (
- ▶ Play
- ) : (
- ▶ Play
- )}
- {release.cartridgePath ? (
- Download
- ) : (
- Download
- )}
- {release.sourcePath ? (
- Source
- ) : (
- Source
- )}
- {release.docsFolderPath ? (
- Docs
- ) : (
- Docs
- )}
+ {release.htmlFolderPath ? (▶ Play) : (▶ Play)}
+ {release.cartridgePath ? (Download) : (Download)}
+ {release.sourcePath ? (Source) : (Source)}
+ {release.docsFolderPath ? (Docs) : (Docs)}
+ |
+
+ ))}
+ {devReleases.length > 0 && (
+
+ | Development Releases |
+
+ )}
+ {devReleases.map((release: any) => (
+
+ | {release.version} |
+ {new Date(release.CreatedAt).toLocaleDateString('en-US')} |
+ {new Date(release.UpdatedAt).toLocaleDateString('en-US')} |
+
+ {release.htmlFolderPath ? (▶ Play) : (▶ Play)}
+ {release.cartridgePath ? (Download) : (Download)}
+ {release.sourcePath ? (Source) : (Source)}
+ {release.docsFolderPath ? (Docs) : (Docs)}
|
))}
@@ -119,33 +124,36 @@ const softwares = json.softwares;
{/* Mobile Stacked View */}
- {releases.map((release) => (
+ {stableReleases.map((release: any) => (
- {release.htmlFolderPath ? (
-
▶ Play
- ) : (
-
▶ Play
- )}
- {release.cartridgePath ? (
-
Download
- ) : (
-
Download
- )}
- {release.sourcePath ? (
-
Source
- ) : (
-
Source
- )}
- {release.docsFolderPath ? (
-
Docs
- ) : (
-
Docs
- )}
+ {release.htmlFolderPath ? (
▶ Play) : (
▶ Play)}
+ {release.cartridgePath ? (
Download) : (
Download)}
+ {release.sourcePath ? (
Source) : (
Source)}
+ {release.docsFolderPath ? (
Docs) : (
Docs)}
+
+
+ ))}
+ {devReleases.length > 0 && (
+
Development Releases
+ )}
+ {devReleases.map((release: any) => (
+
+
+
+ {release.htmlFolderPath ? (
▶ Play) : (
▶ Play)}
+ {release.cartridgePath ? (
Download) : (
Download)}
+ {release.sourcePath ? (
Source) : (
Source)}
+ {release.docsFolderPath ? (
Docs) : (
Docs)}
))}
@@ -154,7 +162,8 @@ const softwares = json.softwares;
- ))}
+ )
+ })}
@@ -203,7 +212,7 @@ const softwares = json.softwares;
@apply bg-white shadow-lg relative rounded-xl overflow-hidden hover:shadow-2xl transition-shadow duration-300;
}
.software-card-content {
- @apply p-6 pr-28 sm:pr-6;
+ @apply p-6;
}
.software-title {
@apply text-2xl font-semibold mb-2;
@@ -215,7 +224,7 @@ const softwares = json.softwares;
@apply text-sm text-gray-500 mb-4;
}
.latest-release-actions {
- @apply absolute top-4 right-4 flex flex-col sm:flex-row gap-1 z-10;
+ @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;
}
/* Small Action Buttons */
diff --git a/apps/frontend/src/pages/index.astro b/apps/frontend/src/pages/index.astro
index 7b4ff2e..040efae 100644
--- a/apps/frontend/src/pages/index.astro
+++ b/apps/frontend/src/pages/index.astro
@@ -68,11 +68,18 @@ try {
const BASE = "https://games.teletype.hu";
const API_HIGHLIGHTED = BASE + "/api/software/highlighted";
let highlightedSoftware = null;
+let highlightedStableRelease = null;
try {
const res = await fetch(API_HIGHLIGHTED);
if (res.ok) {
highlightedSoftware = await res.json();
+ if (highlightedSoftware?.releases) {
+ const stableReleases = highlightedSoftware.releases
+ .filter((r: any) => !r.version.startsWith('dev-'))
+ .sort((a: any, b: any) => new Date(b.UpdatedAt).getTime() - new Date(a.UpdatedAt).getTime());
+ highlightedStableRelease = stableReleases[0] ?? null;
+ }
}
} catch (e) {
console.error('Failed to fetch highlighted software:', e);
@@ -141,13 +148,16 @@ const YOUTUBE_CHANNEL_ID = import.meta.env.YOUTUBE_CHANNEL_ID;
Featured Game
{highlightedSoftware.software.status}
+ {highlightedStableRelease && (
+ {highlightedStableRelease.version}
+ )}
{highlightedSoftware.software.title}
{highlightedSoftware.software.desc}
- {highlightedSoftware.webPlayableRelease && (
-
+ {highlightedStableRelease?.htmlFolderPath && (
+
▶ Play in Browser
)}
@@ -331,6 +341,9 @@ const YOUTUBE_CHANNEL_ID = import.meta.env.YOUTUBE_CHANNEL_ID;
.status-demo { @apply bg-blue-500/20 text-blue-300 border border-blue-500/30; }
.status-development { @apply bg-yellow-500/20 text-yellow-300 border border-yellow-500/30; }
.status-archived { @apply bg-gray-500/20 text-gray-300 border border-gray-500/30; }
+ .featured-version-badge {
+ @apply px-2 py-0.5 rounded text-[10px] font-bold bg-white/10 text-white/70 border border-white/20;
+ }
/* Countdown Card */