feat: Added AppFooter component displaying app version, build date, com…

- "frontend/src/components/AppFooter.tsx"
- "frontend/vite.config.ts"
- "frontend/src/App.tsx"
- "frontend/src/App.css"
- "frontend/src/vite-env.d.ts"

GSD-Task: S06/T01
This commit is contained in:
jlightner 2026-03-30 12:00:58 +00:00
parent 96d7bc6e75
commit ec9e307538
6 changed files with 123 additions and 1 deletions

View file

@ -159,6 +159,12 @@ body {
/* ── App shell ────────────────────────────────────────────────────────────── */
.app {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.app-header {
display: flex;
align-items: center;
@ -191,11 +197,41 @@ body {
}
.app-main {
flex: 1;
max-width: 72rem;
margin: 1.5rem auto;
padding: 0 1.5rem;
}
/* ── App footer ───────────────────────────────────────────────────────────── */
.app-footer {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 1rem 1.5rem;
font-size: 0.6875rem;
color: var(--color-text-muted);
border-top: 1px solid var(--color-border);
}
.app-footer__sep {
opacity: 0.4;
}
.app-footer__commit,
.app-footer__repo {
color: var(--color-text-muted);
text-decoration: none;
transition: color 0.15s;
}
a.app-footer__commit:hover,
a.app-footer__repo:hover {
color: var(--color-accent);
}
/* ── Queue header ─────────────────────────────────────────────────────────── */
.queue-header {

View file

@ -10,6 +10,7 @@ import MomentDetail from "./pages/MomentDetail";
import AdminReports from "./pages/AdminReports";
import AdminPipeline from "./pages/AdminPipeline";
import AdminDropdown from "./components/AdminDropdown";
import AppFooter from "./components/AppFooter";
export default function App() {
return (
@ -50,6 +51,8 @@ export default function App() {
<Route path="*" element={<Navigate to="/" replace />} />
</Routes>
</main>
<AppFooter />
</div>
);
}

View file

@ -0,0 +1,47 @@
const REPO_URL = "https://github.com/xpltdco/chrysopedia";
export default function AppFooter() {
const commitUrl =
__GIT_COMMIT__ !== "dev"
? `${REPO_URL}/commit/${__GIT_COMMIT__}`
: undefined;
return (
<footer className="app-footer">
<span className="app-footer__version">
v{__APP_VERSION__}
</span>
<span className="app-footer__sep">·</span>
<span className="app-footer__date">
Built {__BUILD_DATE__.slice(0, 10)}
</span>
{commitUrl ? (
<>
<span className="app-footer__sep">·</span>
<a
href={commitUrl}
className="app-footer__commit"
target="_blank"
rel="noopener noreferrer"
>
{__GIT_COMMIT__}
</a>
</>
) : (
<>
<span className="app-footer__sep">·</span>
<span className="app-footer__commit">{__GIT_COMMIT__}</span>
</>
)}
<span className="app-footer__sep">·</span>
<a
href={REPO_URL}
className="app-footer__repo"
target="_blank"
rel="noopener noreferrer"
>
GitHub
</a>
</footer>
);
}

View file

@ -1 +1,5 @@
/// <reference types="vite/client" />
declare const __APP_VERSION__: string;
declare const __BUILD_DATE__: string;
declare const __GIT_COMMIT__: string;

View file

@ -1 +1 @@
{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/client.ts","./src/api/public-client.ts","./src/components/AdminDropdown.tsx","./src/components/ModeToggle.tsx","./src/components/ReportIssueModal.tsx","./src/components/StatusBadge.tsx","./src/pages/AdminPipeline.tsx","./src/pages/AdminReports.tsx","./src/pages/CreatorDetail.tsx","./src/pages/CreatorsBrowse.tsx","./src/pages/Home.tsx","./src/pages/MomentDetail.tsx","./src/pages/ReviewQueue.tsx","./src/pages/SearchResults.tsx","./src/pages/TechniquePage.tsx","./src/pages/TopicsBrowse.tsx"],"version":"5.6.3"}
{"root":["./src/App.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/api/client.ts","./src/api/public-client.ts","./src/components/AdminDropdown.tsx","./src/components/AppFooter.tsx","./src/components/ModeToggle.tsx","./src/components/ReportIssueModal.tsx","./src/components/StatusBadge.tsx","./src/pages/AdminPipeline.tsx","./src/pages/AdminReports.tsx","./src/pages/CreatorDetail.tsx","./src/pages/CreatorsBrowse.tsx","./src/pages/Home.tsx","./src/pages/MomentDetail.tsx","./src/pages/ReviewQueue.tsx","./src/pages/SearchResults.tsx","./src/pages/TechniquePage.tsx","./src/pages/TopicsBrowse.tsx"],"version":"5.6.3"}

View file

@ -1,8 +1,40 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { execSync } from "child_process";
import { readFileSync } from "fs";
import { resolve } from "path";
function getGitCommit(): string {
// In Docker builds, VITE_GIT_COMMIT is set via ENV from the build ARG
if (process.env.VITE_GIT_COMMIT) {
return process.env.VITE_GIT_COMMIT;
}
// Local dev: try git
try {
return execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
} catch {
return "dev";
}
}
function getAppVersion(): string {
try {
const pkg = JSON.parse(
readFileSync(resolve(__dirname, "package.json"), "utf-8"),
);
return pkg.version ?? "0.0.0";
} catch {
return "0.0.0";
}
}
export default defineConfig({
plugins: [react()],
define: {
__APP_VERSION__: JSON.stringify(getAppVersion()),
__BUILD_DATE__: JSON.stringify(new Date().toISOString()),
__GIT_COMMIT__: JSON.stringify(getGitCommit()),
},
server: {
proxy: {
"/api": {