This commit is contained in:
Dominik Klarkowski
2026-06-16 09:43:48 +02:00
parent f0e87d8d11
commit 36407f534b
52 changed files with 3211 additions and 100 deletions

View File

@@ -0,0 +1,37 @@
"use server";
import { redirect } from "next/navigation";
import { revalidatePath } from "next/cache";
import { parseStrongShareText } from "@/lib/strong/parser";
import { upsertStrengthWorkout } from "@/lib/models/strength";
export type ImportStrongWorkoutState = { error: string } | null;
export async function importStrongWorkout(
_prevState: ImportStrongWorkoutState,
formData: FormData
): Promise<ImportStrongWorkoutState> {
const text = formData.get("text");
if (typeof text !== "string" || text.trim().length === 0) {
return { error: "Wklej tekst wygenerowany przez funkcję 'Share workout' w Strong." };
}
let workouts;
try {
workouts = parseStrongShareText(text);
} catch (error) {
return { error: error instanceof Error ? error.message : "Nie udało się przetworzyć tekstu." };
}
if (workouts.length === 0) {
return { error: "Nie znaleziono żadnego treningu w podanym tekście." };
}
for (const workout of workouts) {
await upsertStrengthWorkout(workout);
}
revalidatePath("/strength");
revalidatePath("/");
redirect("/strength");
}

View File

@@ -0,0 +1,32 @@
"use client";
import { useActionState } from "react";
import { importStrongWorkout } from "./actions";
export function ImportForm() {
const [state, formAction, pending] = useActionState(importStrongWorkout, null);
return (
<form action={formAction} className="flex flex-col gap-4">
{state?.error ? (
<div className="rounded-md border border-accent/40 bg-accent/10 px-4 py-3 text-sm text-fg">
{state.error}
</div>
) : null}
<textarea
name="text"
rows={16}
required
placeholder={"Trening A\nWednesday, 10 June 2026 at 06:40\n\nDeadlift (Barbell)\nSet 1: 80 kg × 8\n..."}
className="w-full rounded-md border border-muted/40 bg-surface p-3 font-mono text-sm text-fg placeholder:text-fg/30 focus:border-accent focus:outline-none"
/>
<button
type="submit"
disabled={pending}
className="self-start rounded-md bg-accent px-4 py-2 text-sm font-semibold text-fg transition-opacity hover:opacity-90 disabled:opacity-50"
>
{pending ? "Importowanie..." : "Importuj"}
</button>
</form>
);
}

View File

@@ -0,0 +1,17 @@
import { ImportForm } from "./import-form";
export default function StrengthImportPage() {
return (
<div className="flex flex-col gap-6">
<div>
<h1 className="text-2xl font-bold text-fg">Importuj trening</h1>
<p className="mt-1 text-sm text-fg/60">
W aplikacji Strong otwórz zakończony trening, wybierz Share workout
i wklej poniżej skopiowany tekst. Można wkleić kilka treningów na raz.
</p>
</div>
<ImportForm />
</div>
);
}