This commit is contained in:
Dominik Klarkowski
2026-06-18 11:02:31 +02:00
parent d00a5a42ac
commit 047e580da0
32 changed files with 735 additions and 189 deletions

View File

@@ -2,22 +2,30 @@ import { CheckCircle2, XCircle } from "lucide-react";
import { SyncButton } from "@/components/sync-button";
import { formatDate } from "@/lib/format";
import { getLastSyncAt } from "@/lib/models/running";
import { getGarminCredentials, getSavedOauth1Token } from "@/lib/models/garmin-auth";
import { getCurrentUserId } from "@/lib/session";
import { GarminCredentialsForm } from "./garmin-credentials-form";
export const dynamic = "force-dynamic";
function ConfigRow({ label, configured }: { label: string; configured: boolean }) {
function StatusRow({ label, ok, okLabel = "Skonfigurowano", failLabel = "Brak konfiguracji" }: {
label: string;
ok: boolean;
okLabel?: string;
failLabel?: string;
}) {
return (
<div className="flex items-center justify-between rounded-lg border border-muted/40 bg-surface p-4">
<span className="text-fg">{label}</span>
{configured ? (
{ok ? (
<span className="flex items-center gap-1.5 text-sm text-fg/70">
<CheckCircle2 size={16} className="text-accent" />
Skonfigurowano
{okLabel}
</span>
) : (
<span className="flex items-center gap-1.5 text-sm text-fg/50">
<XCircle size={16} />
Brak w .env.local
{failLabel}
</span>
)}
</div>
@@ -25,31 +33,52 @@ function ConfigRow({ label, configured }: { label: string; configured: boolean }
}
export default async function SettingsPage() {
const lastSyncAt = await getLastSyncAt();
const mongoConfigured = Boolean(process.env.MONGODB_URI);
const garminConfigured = Boolean(process.env.GARMIN_EMAIL && process.env.GARMIN_PASSWORD);
const claudeConfigured = Boolean(process.env.ANTHROPIC_API_KEY);
const userId = await getCurrentUserId();
const [lastSyncAt, garminCreds, garminToken] = await Promise.all([
getLastSyncAt(userId),
getGarminCredentials(userId),
getSavedOauth1Token(userId),
]);
return (
<div className="flex flex-col gap-6">
<div>
<h1 className="text-2xl font-bold text-fg">Ustawienia</h1>
<p className="mt-1 text-sm text-fg/60">Status konfiguracji i synchronizacja Garmin.</p>
<p className="mt-1 text-sm text-fg/60">Konfiguracja konta i synchronizacja Garmin.</p>
</div>
<section className="flex flex-col gap-3">
<h2 className="text-lg font-semibold text-fg">Konfiguracja</h2>
<ConfigRow label="MongoDB" configured={mongoConfigured} />
<ConfigRow label="Garmin Connect" configured={garminConfigured} />
<ConfigRow label="Claude API" configured={claudeConfigured} />
<h2 className="text-lg font-semibold text-fg">Status</h2>
<StatusRow label="MongoDB" ok={Boolean(process.env.MONGODB_URI)} />
<StatusRow
label="Garmin Connect — token sesji"
ok={Boolean(garminToken)}
okLabel="Aktywny (synchronizacja działa)"
failLabel="Brak tokenu — wymagane logowanie"
/>
<StatusRow
label="Garmin Connect — dane logowania"
ok={Boolean(garminCreds)}
okLabel={`Zapisano (${garminCreds?.email})`}
failLabel="Brak — potrzebne gdy token wygaśnie"
/>
<StatusRow label="Claude API" ok={Boolean(process.env.ANTHROPIC_API_KEY)} />
</section>
<section className="flex flex-col gap-3">
<h2 className="text-lg font-semibold text-fg">Konto Garmin Connect</h2>
<div className="rounded-lg border border-muted/40 bg-surface p-4">
<GarminCredentialsForm savedEmail={garminCreds?.email ?? null} />
</div>
</section>
<section className="flex flex-col gap-3">
<h2 className="text-lg font-semibold text-fg">Synchronizacja z Garmin</h2>
<div className="flex items-center justify-between rounded-lg border border-muted/40 bg-surface p-4">
<span className="text-sm text-fg/70">
{lastSyncAt ? `Ostatnia synchronizacja: ${formatDate(lastSyncAt)}` : "Jeszcze nie zsynchronizowano"}
{lastSyncAt
? `Ostatnia synchronizacja: ${formatDate(lastSyncAt)}`
: "Jeszcze nie zsynchronizowano"}
</span>
<SyncButton />
</div>