2026-08-15 14:32:03 +02:00
|
|
|
import { Button } from '@/components/ui/button';
|
|
|
|
|
import { Input } from '@/components/ui/input';
|
|
|
|
|
import { Label } from '@/components/ui/label';
|
|
|
|
|
import InputError from '@/components/InputError';
|
|
|
|
|
import { todayISO } from '@/lib/utils';
|
|
|
|
|
import { LoaderCircle } from 'lucide-react';
|
|
|
|
|
import { FormEventHandler, useState } from 'react';
|
2026-05-01 23:31:01 +02:00
|
|
|
|
2025-08-01 00:56:26 +02:00
|
|
|
interface OnboardingFlowProps {
|
|
|
|
|
onComplete?: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
2026-08-15 14:32:03 +02:00
|
|
|
function csrfToken(): string {
|
|
|
|
|
return (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement)?.content ?? '';
|
|
|
|
|
}
|
2025-08-01 00:56:26 +02:00
|
|
|
|
2026-08-15 14:32:03 +02:00
|
|
|
export default function OnboardingFlow({ onComplete }: OnboardingFlowProps) {
|
|
|
|
|
const [startingValue, setStartingValue] = useState('0');
|
|
|
|
|
const [processing, setProcessing] = useState(false);
|
|
|
|
|
const [error, setError] = useState<string | undefined>();
|
2026-05-01 22:02:13 +02:00
|
|
|
|
2026-08-15 14:32:03 +02:00
|
|
|
const submit: FormEventHandler = async (e) => {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
setProcessing(true);
|
|
|
|
|
setError(undefined);
|
2026-05-01 22:02:13 +02:00
|
|
|
|
2026-08-15 14:32:03 +02:00
|
|
|
const headers = {
|
|
|
|
|
'Content-Type': 'application/json',
|
|
|
|
|
'X-CSRF-TOKEN': csrfToken(),
|
|
|
|
|
Accept: 'application/json',
|
|
|
|
|
};
|
2026-05-01 22:02:13 +02:00
|
|
|
|
2026-08-15 14:32:03 +02:00
|
|
|
try {
|
|
|
|
|
const trackerResponse = await fetch(route('tracker.store'), {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers,
|
|
|
|
|
body: JSON.stringify({}),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!trackerResponse.ok && trackerResponse.status !== 409) {
|
|
|
|
|
setError('Could not create the counter. Please try again.');
|
|
|
|
|
return;
|
2025-08-01 00:56:26 +02:00
|
|
|
}
|
2026-05-01 23:31:01 +02:00
|
|
|
|
2026-08-15 14:32:03 +02:00
|
|
|
const quantity = Number(startingValue);
|
2026-05-01 23:31:01 +02:00
|
|
|
|
2026-08-15 14:32:03 +02:00
|
|
|
if (quantity > 0) {
|
|
|
|
|
const entryResponse = await fetch(route('entries.store'), {
|
|
|
|
|
method: 'POST',
|
|
|
|
|
headers,
|
|
|
|
|
body: JSON.stringify({ date: todayISO(), quantity }),
|
|
|
|
|
});
|
2026-05-02 18:17:42 +02:00
|
|
|
|
2026-08-15 14:32:03 +02:00
|
|
|
if (!entryResponse.ok) {
|
|
|
|
|
setError('Could not save the starting value. Please try again.');
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-05-01 23:31:01 +02:00
|
|
|
|
2026-08-15 14:32:03 +02:00
|
|
|
onComplete?.();
|
|
|
|
|
} catch {
|
|
|
|
|
setError('Something went wrong. Please try again.');
|
|
|
|
|
} finally {
|
|
|
|
|
setProcessing(false);
|
2025-08-01 00:56:26 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="min-h-screen bg-black flex items-center justify-center p-4">
|
2026-08-15 14:32:03 +02:00
|
|
|
<div className="w-full max-w-md">
|
2025-08-01 00:56:26 +02:00
|
|
|
<div className="border-2 border-red-500 bg-black shadow-[0_0_20px_rgba(239,68,68,0.3)] p-8">
|
2026-08-15 14:32:03 +02:00
|
|
|
<form onSubmit={submit} className="space-y-4">
|
|
|
|
|
<Label
|
|
|
|
|
htmlFor="starting-value"
|
|
|
|
|
className="text-red-400 font-mono text-xs uppercase tracking-wider"
|
|
|
|
|
>
|
|
|
|
|
> Starting Value
|
|
|
|
|
</Label>
|
|
|
|
|
<Input
|
|
|
|
|
id="starting-value"
|
|
|
|
|
type="number"
|
|
|
|
|
min="0"
|
|
|
|
|
step="1"
|
|
|
|
|
autoFocus
|
|
|
|
|
value={startingValue}
|
|
|
|
|
onChange={(e) => setStartingValue(e.target.value)}
|
|
|
|
|
className="bg-black border-red-500 text-red-400 focus:border-red-300 font-mono text-sm rounded-none border-2 focus:ring-0 focus:outline-none placeholder:text-red-400/40 transition-all glow-red"
|
|
|
|
|
/>
|
|
|
|
|
<InputError message={error} />
|
|
|
|
|
|
|
|
|
|
<Button
|
|
|
|
|
type="submit"
|
|
|
|
|
disabled={processing || startingValue === ''}
|
|
|
|
|
className="w-full bg-red-500 hover:bg-red-500 text-black font-mono text-sm font-bold border-red-500 rounded-none border-2 uppercase tracking-wider transition-all glow-red"
|
|
|
|
|
>
|
|
|
|
|
{processing && <LoaderCircle className="mr-2 h-4 w-4 animate-spin" />}
|
|
|
|
|
[INITIALIZE]
|
|
|
|
|
</Button>
|
|
|
|
|
</form>
|
2025-08-01 00:56:26 +02:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2026-05-01 23:31:01 +02:00
|
|
|
}
|