incr/resources/js/components/Counter/SetCountForm.tsx

96 lines
3.8 KiB
TypeScript
Raw Normal View History

import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import InputError from '@/components/InputError';
import { csrfToken } from '@/lib/utils';
import { LoaderCircle } from 'lucide-react';
import { FormEventHandler, useState } from 'react';
interface SetCountFormProps {
currentCount: number;
onClose: () => void;
onSuccess: (count: number) => void;
}
export default function SetCountForm({ currentCount, onClose, onSuccess }: SetCountFormProps) {
const [value, setValue] = useState(String(currentCount));
const [processing, setProcessing] = useState(false);
const [error, setError] = useState<string | undefined>();
const submit: FormEventHandler = async (e) => {
e.preventDefault();
setProcessing(true);
setError(undefined);
try {
const response = await fetch('/count', {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'X-CSRF-TOKEN': csrfToken(),
Accept: 'application/json',
},
body: JSON.stringify({ count: Number(value) }),
});
if (!response.ok) {
setError('Enter a whole number of zero or more.');
return;
}
const { count } = await response.json();
onSuccess(count);
onClose();
} catch {
setError('Something went wrong. Please try again.');
} finally {
setProcessing(false);
}
};
return (
<div className="bg-black p-8">
<div className="w-full border-4 border-red-500 p-6 bg-black glow-red">
<form onSubmit={submit} className="space-y-4">
<Label
htmlFor="count"
className="text-red-400 font-mono text-xs uppercase tracking-wider"
>
&gt; Set Value
</Label>
<Input
id="count"
type="number"
min="0"
step="1"
autoFocus
value={value}
onChange={(e) => setValue(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} />
<div className="flex gap-3 pt-2">
<Button
type="submit"
disabled={processing || value === ''}
className="flex-1 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" />}
[EXECUTE]
</Button>
<Button
type="button"
variant="outline"
onClick={onClose}
className="flex-1 bg-black border-red-500 text-red-400 hover:bg-red-950 hover:text-red-300 font-mono text-sm font-bold rounded-none border-2 uppercase tracking-wider transition-all glow-red"
>
[ABORT]
</Button>
</div>
</form>
</div>
</div>
);
}