Files
knur-app/components/sync-button.tsx

59 lines
2.3 KiB
TypeScript
Raw Normal View History

2026-06-16 09:43:48 +02:00
"use client";
import { useActionState } from "react";
import { RefreshCw } from "lucide-react";
import { submitGarminMfaCode, syncGarminActivities, type SyncGarminState } from "@/app/running/actions";
export function SyncButton() {
const [state, formAction, pending] = useActionState(async () => syncGarminActivities(), null);
const [mfaState, mfaAction, mfaPending] = useActionState(
async (_prev: SyncGarminState, formData: FormData) => submitGarminMfaCode(String(formData.get("code") ?? "")),
null
);
const mfaRequired = (state && "mfaRequired" in state) || (mfaState && "mfaRequired" in mfaState);
const activeState = mfaState ?? state;
return (
<div className="flex flex-col items-end gap-2">
<form action={formAction}>
<button
type="submit"
disabled={pending}
className="flex items-center gap-1.5 rounded-md bg-accent px-3 py-2 text-sm font-semibold text-fg transition-opacity hover:opacity-90 disabled:opacity-50"
>
<RefreshCw size={16} className={pending ? "animate-spin" : ""} />
{pending ? "Synchronizowanie..." : "Synchronizuj z Garmin"}
</button>
</form>
{mfaRequired ? (
<form action={mfaAction} className="flex items-center gap-2">
<input
type="text"
name="code"
inputMode="numeric"
maxLength={6}
placeholder="Kod z e-maila"
required
className="w-32 rounded-md border border-muted/40 bg-bg px-2 py-1.5 text-sm text-fg"
/>
<button
type="submit"
disabled={mfaPending}
className="rounded-md bg-accent px-3 py-1.5 text-sm font-semibold text-fg transition-opacity hover:opacity-90 disabled:opacity-50"
>
{mfaPending ? "Weryfikacja..." : "Zatwierdź kod"}
</button>
</form>
) : null}
{mfaRequired ? (
<div className="text-sm text-fg/60">Garmin wysłał kod weryfikacyjny na e-mail. Wpisz go powyżej.</div>
) : null}
{activeState && "error" in activeState ? <div className="text-sm text-accent">{activeState.error}</div> : null}
{activeState && "success" in activeState ? <div className="text-sm text-fg/60">{activeState.success}</div> : null}
</div>
);
}