init
This commit is contained in:
37
app/strength/import/actions.ts
Normal file
37
app/strength/import/actions.ts
Normal 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");
|
||||
}
|
||||
32
app/strength/import/import-form.tsx
Normal file
32
app/strength/import/import-form.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
17
app/strength/import/page.tsx
Normal file
17
app/strength/import/page.tsx
Normal 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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user