95 lines
2.9 KiB
TypeScript
95 lines
2.9 KiB
TypeScript
|
|
import React, { useState } from "react";
|
||
|
|
import { useRouter } from "next/navigation";
|
||
|
|
import { createDish } from "@/utils/api/dishApi";
|
||
|
|
import PageTitle from "@/components/ui/PageTitle";
|
||
|
|
import Alert from "@/components/ui/Alert";
|
||
|
|
import SolidButton from "@/components/ui/Buttons/SolidButton";
|
||
|
|
import OutlineLinkButton from "@/components/ui/Buttons/OutlineLinkButton";
|
||
|
|
import { ChevronLeftIcon } from "@heroicons/react/16/solid";
|
||
|
|
import Hr from "@/components/ui/Hr"
|
||
|
|
|
||
|
|
const CreateDishForm = () => {
|
||
|
|
const router = useRouter()
|
||
|
|
const [name, setName] = useState<string>("");
|
||
|
|
const [error, setError] = useState<string>("");
|
||
|
|
const [loading, setLoading] = useState(false);
|
||
|
|
|
||
|
|
const validateForm = () => {
|
||
|
|
if (!name.trim()) {
|
||
|
|
setError("Dish name cannot be empty.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return true;
|
||
|
|
};
|
||
|
|
|
||
|
|
const submitForm = async (e: React.FormEvent<HTMLFormElement>) => {
|
||
|
|
e.preventDefault()
|
||
|
|
|
||
|
|
// Validate client-side input
|
||
|
|
if (!validateForm()) return;
|
||
|
|
|
||
|
|
setError("");
|
||
|
|
setLoading(true);
|
||
|
|
|
||
|
|
try {
|
||
|
|
const result = await createDish(name);
|
||
|
|
if (result) {
|
||
|
|
router.push('/dishes')
|
||
|
|
}
|
||
|
|
} catch (error: unknown) {
|
||
|
|
setError(error instanceof Error ? error.message : "An unexpected error occurred.");
|
||
|
|
} finally {
|
||
|
|
setLoading(false);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div className="px-5">
|
||
|
|
<div className="flex mb-3">
|
||
|
|
<PageTitle>Create Dish</PageTitle>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<form className="space-y-4" onSubmit={ submitForm }>
|
||
|
|
{ error && (
|
||
|
|
<Alert type="error">{ error }</Alert>
|
||
|
|
) }
|
||
|
|
|
||
|
|
<div>
|
||
|
|
<label htmlFor="name" className="block text-sm font-medium">Dish Name</label>
|
||
|
|
<input
|
||
|
|
type="text"
|
||
|
|
id="name"
|
||
|
|
name="name"
|
||
|
|
value={ name }
|
||
|
|
onChange={ (e) => setName(e.target.value) } // Update the name state on change
|
||
|
|
className="w-full p-2 mb-4 border rounded bg-gray-600 border-secondary text-secondary focus:bg-gray-900"
|
||
|
|
placeholder="Enter dish name"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<SolidButton
|
||
|
|
type="submit"
|
||
|
|
disabled={ loading }
|
||
|
|
className={ loading ? "bg-gray-400" : '' }
|
||
|
|
>
|
||
|
|
{ loading ? "Saving..." : "Save Changes" }
|
||
|
|
</SolidButton>
|
||
|
|
</form>
|
||
|
|
|
||
|
|
<Hr />
|
||
|
|
|
||
|
|
<OutlineLinkButton
|
||
|
|
href="/dishes"
|
||
|
|
className="mt-4 pl-0 mr-0"
|
||
|
|
icon={ <ChevronLeftIcon/> }
|
||
|
|
>
|
||
|
|
Back to dishes
|
||
|
|
</OutlineLinkButton>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
|
||
|
|
|
||
|
|
};
|
||
|
|
|
||
|
|
export default CreateDishForm;
|