95 lines
3.8 KiB
TypeScript
95 lines
3.8 KiB
TypeScript
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"
|
|
>
|
|
> 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>
|
|
);
|
|
}
|