(FIX): Added error display list.
This looks nice and is a bit more functional! I really need to break the form up into components...
This commit is contained in:
parent
728b7eb28c
commit
58691fd7a1
34
web/src/components/forms/ValidationErrorList.tsx
Normal file
34
web/src/components/forms/ValidationErrorList.tsx
Normal file
@ -0,0 +1,34 @@
|
||||
import type { CreateRecipeFormToggles } from "../../pages/Create";
|
||||
|
||||
interface ValidationErrorListProps {
|
||||
validation: CreateRecipeFormToggles;
|
||||
}
|
||||
|
||||
const MESSAGES: Record<keyof CreateRecipeFormToggles, string> = {
|
||||
title: "Invalid title provided.",
|
||||
description: "Invalid description provided.",
|
||||
prepTime: "Invalid preparation time provided.",
|
||||
cookTime: "Invalid cook time provided.",
|
||||
servingSize: "Invalid serving size provided.",
|
||||
category: "Invalid category selected.",
|
||||
difficulty: "Invalid difficulty selected.",
|
||||
ingredients: "Invalid ingredients provided.",
|
||||
instructions: "Invalid instructions provided.",
|
||||
}
|
||||
|
||||
export default function ValidationErrorList({ validation }: ValidationErrorListProps) {
|
||||
return (
|
||||
<div className="my-2">
|
||||
{Object.entries(validation)
|
||||
.filter(([, isValid]) => !isValid)
|
||||
.map(([name]) => {
|
||||
const key = name as keyof CreateRecipeFormToggles;
|
||||
return (
|
||||
<p key={name} className="text-sm text-red-500">
|
||||
{MESSAGES[key]}
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
|
||||
import Banner from "../components/Banner";
|
||||
import { isRecipeMeal } from "../types/recipe";
|
||||
import InstructionForm from "../components/forms/InstructionForm";
|
||||
import ValidationErrorList from "../components/forms/ValidationErrorList";
|
||||
|
||||
interface CreateRecipeForm {
|
||||
title: string;
|
||||
@ -18,7 +19,7 @@ interface CreateRecipeForm {
|
||||
image: File | null;
|
||||
};
|
||||
|
||||
interface CreateRecipeFormToggles {
|
||||
export interface CreateRecipeFormToggles {
|
||||
title: boolean;
|
||||
description: boolean;
|
||||
prepTime: boolean;
|
||||
@ -175,7 +176,6 @@ export default function Create() {
|
||||
Please provide a unique title for your recipe. This is the most important part!
|
||||
</p>
|
||||
<input
|
||||
onKeyDown={keyDownHandler}
|
||||
className={`${!validation.title ? "border-red-500" : ""} ${INPUT_CLASSES}`}
|
||||
type="text"
|
||||
name="title"
|
||||
@ -228,7 +228,6 @@ export default function Create() {
|
||||
Please provide a list of tags. <span className="italic">e.g., easy, dairy-free, gluten-free, high protein.</span>
|
||||
</p>
|
||||
<input
|
||||
onKeyDown={keyDownHandler}
|
||||
className="border border-gray-300 px-4 py-2 rounded-lg focus:outline-none focus:ring-blue-500 focus:ring-2 duration-200 ease-in-out transition-all shadow-sm"
|
||||
maxLength={32}
|
||||
enterKeyHint="done"
|
||||
@ -253,7 +252,6 @@ export default function Create() {
|
||||
Please provide the estimated prep time (minutes).
|
||||
</p>
|
||||
<input
|
||||
onKeyDown={keyDownHandler}
|
||||
className={`${!validation.prepTime ? "border-red-500" : ""} ${INPUT_CLASSES}`}
|
||||
type="number"
|
||||
name="prepTime"
|
||||
@ -277,7 +275,6 @@ export default function Create() {
|
||||
Please provide the estimated cook time (minutes).
|
||||
</p>
|
||||
<input
|
||||
onKeyDown={keyDownHandler}
|
||||
className={`${!validation.cookTime ? "border-red-500" : ""} ${INPUT_CLASSES}`}
|
||||
type="number"
|
||||
name="cookTime"
|
||||
@ -301,7 +298,6 @@ export default function Create() {
|
||||
Please provide the estimated serving size.
|
||||
</p>
|
||||
<input
|
||||
onKeyDown={keyDownHandler}
|
||||
className={`${!validation.servingSize ? "border-red-500" : ""} ${INPUT_CLASSES}`}
|
||||
type="number"
|
||||
name="servingSize"
|
||||
@ -387,7 +383,6 @@ export default function Create() {
|
||||
<li className="w-full flex gap-x-2 py-2">
|
||||
<div className="flex-grow">
|
||||
<input
|
||||
onKeyDown={keyDownHandler}
|
||||
className="peer w-full border border-gray-300 px-4 py-2 rounded-lg focus:outline-none
|
||||
focus:ring-blue-500 focus:ring-2 duration-200 ease-in-out transition-all shadow-sm
|
||||
invalid:border-red-500"
|
||||
@ -404,7 +399,6 @@ export default function Create() {
|
||||
</div>
|
||||
<div className="w-1/3">
|
||||
<input
|
||||
onKeyDown={keyDownHandler}
|
||||
className="peer w-full border border-gray-300 px-4 py-2 rounded-lg focus:outline-none
|
||||
focus:ring-blue-500 focus:ring-2 duration-200 ease-in-out transition-all shadow-sm
|
||||
invalid:border-red-500"
|
||||
@ -466,7 +460,10 @@ export default function Create() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button disabled={!isFormValid} className={`${isFormValid ? "bg-gradient-to-r from-blue-200 to-purple-200 cursor-pointer" : "bg-gray-200 text-gray-500 cursor-not-allowed"} w-full mt-8 py-2 rounded-lg text-lg shadow-md`}>
|
||||
{/* Display the reason for the invalidation */}
|
||||
<ValidationErrorList validation={validation} />
|
||||
|
||||
<button disabled={!isFormValid} className={`${isFormValid ? "bg-gradient-to-r from-blue-200 to-purple-200 cursor-pointer" : "bg-gray-200 text-gray-500 cursor-not-allowed"} w-full py-2 rounded-lg text-lg shadow-md`}>
|
||||
Create Recipe
|
||||
</button>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user