import React, { useCallback, useEffect, useState } from 'react';
import { Link } from 'react-router-dom';
import { ArrowLeft, ArrowUpCircle, CheckCircle2, Info, Loader2, Sparkles, AlertCircle } from 'lucide-react';
import { api } from '@/api';
import { useAuth } from '@/hooks/useAuth';
import { APP_VERSION } from '@/lib/version';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card';
function UpdateBadge({ status, loading }) {
if (loading) {
return (
Checking…
);
}
if (!status) return null;
if (status.has_update) {
return (
v{status.latest_version} available
);
}
if (status.up_to_date) {
return (
Up to date
);
}
// up_to_date is null — check failed
return (
Could not check
);
}
export default function AboutPage() {
const { user } = useAuth();
const [about, setAbout] = useState(null);
const [loading, setLoading] = useState(true);
const [updateStatus, setUpdateStatus] = useState(null);
const [updateLoading, setUpdateLoading] = useState(true);
const load = useCallback(async () => {
setLoading(true);
try {
setAbout(await api.about());
} finally {
setLoading(false);
}
}, []);
useEffect(() => { load(); }, [load]);
useEffect(() => {
setUpdateLoading(true);
api.updateStatus()
.then(setUpdateStatus)
.catch(() => setUpdateStatus(null))
.finally(() => setUpdateLoading(false));
}, []);
// Use Vite-injected APP_VERSION as the immediate source of truth.
// api.about() version is shown once loaded as a cross-check; they should always match.
const displayVersion = about?.version ?? APP_VERSION;
return (
{about?.name || 'BillTracker'}
{about?.description || ''}
{/* Version card — shows immediately via APP_VERSION, update status alongside */}
Version
v{displayVersion}
Backend
{about?.stack?.backend || 'Node.js / Express'}
Storage
{about?.stack?.database || 'SQLite'}
Produced with AI assistance
BillTracker is self-hosted software for personal bill planning and history. This product was produced with the assistance of AI.
{user == null && (
)}
{/* Easter egg — barely visible, reveals on hover for curious explorers */}
);
}