(FEAT): Worked on tags! They seem good, but need a final check.
This was much easier than the previous implementation, gotta love JS/TS (I hate this shit).
This commit is contained in:
parent
58691fd7a1
commit
d18710e1fc
@ -64,8 +64,8 @@ export default function InstructionElement({ instruction, index, allowDelete, on
|
||||
<DragIconSmall />
|
||||
</div>
|
||||
|
||||
<button
|
||||
tabIndex={-1}
|
||||
<button
|
||||
tabIndex={-1}
|
||||
disabled={!allowDelete}
|
||||
onClick={() => onDelete(instruction.id)}
|
||||
className="p-2 pr-0 cursor-pointer text-gray-500 hover:text-red-500 disabled:text-gray-200 disabled:cursor-not-allowed duration-300"
|
||||
|
||||
@ -18,7 +18,7 @@ export default function InstructionForm({ instructions, setInstructions }: Instr
|
||||
};
|
||||
|
||||
const handleDelete = (id: string) => {
|
||||
setInstructions(prev =>
|
||||
setInstructions(prev =>
|
||||
prev.filter(instr => instr.id !== id)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useState, type ChangeEvent, type FormEvent } from "react";
|
||||
import Banner from "../components/Banner";
|
||||
import { isRecipeMeal } from "../types/recipe";
|
||||
import InstructionForm from "../components/forms/InstructionForm";
|
||||
@ -104,16 +104,7 @@ export default function Create() {
|
||||
|
||||
|
||||
// HANDLERS
|
||||
// TODO: Only needed if we use the form element
|
||||
const keyDownHandler = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const changeHandler = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||||
const changeHandler = (e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||||
const { name, value } = e.target;
|
||||
setInputs(prev => ({
|
||||
...prev,
|
||||
@ -125,15 +116,48 @@ export default function Create() {
|
||||
}));
|
||||
};
|
||||
|
||||
const tagCreationHandler = (e: FormEvent<HTMLFormElement>) => {
|
||||
e.preventDefault();
|
||||
|
||||
// why would anyone try this lol
|
||||
if (inputs.tagInput.trim() === "") return;
|
||||
|
||||
// Tag already exists, clear input and exit
|
||||
if (inputs.tags.includes(inputs.tagInput.toLowerCase())) {
|
||||
setInputs(prev => ({
|
||||
...prev,
|
||||
tagInput: "",
|
||||
}));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
setInputs(prev => ({
|
||||
...prev,
|
||||
tags: [...prev.tags, inputs.tagInput.toLowerCase()],
|
||||
tagInput: "",
|
||||
}));
|
||||
}
|
||||
|
||||
const tagDeletionHandler = (tag: string) => {
|
||||
if (!tag) return;
|
||||
|
||||
setInputs(prev => ({
|
||||
...prev,
|
||||
tags: prev.tags.filter(t => t !== tag)
|
||||
}));
|
||||
}
|
||||
|
||||
const addInstructionHandler = () => {
|
||||
setInstructions([...instructions, { id: crypto.randomUUID(), content: "" }]);
|
||||
}
|
||||
|
||||
|
||||
// EFFECTS
|
||||
useEffect(() => {
|
||||
// Execute validation every time inputs change
|
||||
validate();
|
||||
// console.log("@inputs", inputs);
|
||||
console.log("@inputs", inputs);
|
||||
}, [inputs, instructions]);
|
||||
|
||||
// useEffect(() => {
|
||||
@ -219,7 +243,7 @@ export default function Create() {
|
||||
</div>
|
||||
|
||||
{/* TODO: Tags Input */}
|
||||
<div className="my-4 flex flex-col gap-x-2">
|
||||
<form onSubmit={tagCreationHandler} className="my-4 flex flex-col gap-x-2">
|
||||
<div className="flex flex-col flex-grow">
|
||||
<label htmlFor="tags" className="text-sm">
|
||||
Recipe Tags
|
||||
@ -228,18 +252,30 @@ 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
|
||||
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"
|
||||
type="text"
|
||||
value={inputs.tagInput}
|
||||
onChange={changeHandler}
|
||||
name="tagInput"
|
||||
maxLength={32}
|
||||
enterKeyHint="done"
|
||||
type="text"
|
||||
id="tag"
|
||||
name="tag"
|
||||
placeholder="e.g., Healthy"
|
||||
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"
|
||||
/>
|
||||
<input type="hidden" name="tags" id="tags" value="" />
|
||||
</div>
|
||||
<ul id="tag-list" className="my-2 flex gap-1 flex-wrap"></ul>
|
||||
</div>
|
||||
<ul id="tag-list" className="my-2 flex gap-1 flex-wrap">
|
||||
{inputs.tags.map(tag =>
|
||||
<li
|
||||
className="flex text-xs items-center bg-blue-100 w-fit px-2 py-1 rounded-full gap-x-1 select-none cursor-pointer hover:bg-blue-200 duration-300"
|
||||
key={tag}
|
||||
>
|
||||
<button tabIndex={-1} type="button" onClick={() => tagDeletionHandler(tag)}>
|
||||
× {tag}
|
||||
</button>
|
||||
</li>
|
||||
)}
|
||||
</ul>
|
||||
</form>
|
||||
|
||||
{/* Time Input */}
|
||||
<div className="my-4 flex gap-x-2">
|
||||
@ -423,7 +459,6 @@ export default function Create() {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* TODO: Instructions Inputs */}
|
||||
<div className="flex flex-col my-4">
|
||||
<label htmlFor="instructions" className="text-sm">
|
||||
Instructions
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user