59 lines
2.3 KiB
TypeScript
59 lines
2.3 KiB
TypeScript
|
|
"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>
|
||
|
|
);
|
||
|
|
}
|