I am trying to create a weekly dinner list in react using zustand as the state-management.
I have successfully added and display the item title into div's when added. But I am needing to add a selected icon to the div.
So the user would type in the title of the item and select a image as well to be displayed
Here's where I am storing my source of truth:
import create from 'zustand';
import {devtools, persist} from 'zustand/middleware'
const dinnerStore = (set) => ({
meals: [],
addMeal: (meal) => {
set((state) => ({
meals: [meal, ...state.meals],
}))
},
removeMeal: (mealId) => {
set((state) => ({
meals: state.meals.filter((m) => m.id !== mealId)
}))
},
toggleMealStatus: (mealId) => {
set((state) => ({
meals: state.meals.map((meal) => meal.id === mealId ? {...meal, completed: !meal.completed} : meal) //If the meal id we've selected is equal to the corresponding id in the array
}))
},
icons: [],
addIcon: (icon) => {
set((state) => ({
icons: [icon, ...state.icons]
}))
}
})
const useDinnerStore = create(
devtools(
persist(dinnerStore, {
name: "meals",
iconList: "icons"
})
)
)
export default useDinnerStore;
Here's the code for dealing with the form submissions:
import React, {useState} from 'react'
import useDinnerStore from '../app/dinnerStore';
import Icon from './Icon';
import $ from 'jquery';
const DinnerForm = () => {
const addMeal = useDinnerStore((state) => state.addMeal)
const addIcon = useDinnerStore((state) => state.addIcon)
const icons = ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
const [mealTitle, setMealTitle] = useState("")
console.log("Meal Form Rendererd");
const [iconName, setIconName] = useState("");
const [iconDisplay, setIconDisplay] = useState("")
const handleMealSubmit = () => {
if (!mealTitle) return alert("Please add a dinner"); //Essentially, if the title is blank on submit
addMeal({
id: Math.ceil(Math.random() * 1000000),
title: mealTitle
})
setMealTitle("")
}
const handleIconSubmit = () => {
addIcon({
id: Math.ceil(Math.random() * 10),
icon: iconName
})
let selectedIcon = $(this).attr("id");
console.log(selectedIcon)
setIconName("")
}
return (
<div className="form-container">
<input
value={mealTitle} //For consistency what connecting this with the title state
onChange={(e) => {
setMealTitle(e.target.value)
}}
className="form-input" />
<button
onClick={() => {
handleMealSubmit();
}}
className="form-submit-btn">
Add Dinner
</button>
<div className="icon-list">
{icons.map((icon, i) => {
return (
<React.Fragment key={i}>
<input type="image" src="#" name="icon" id={i} className="btn" onClick={() => {
handleIconSubmit();
}} />
</React.Fragment>
)
})}
</div>
</div>
)
}
export default DinnerForm;
And dealing with the display render
import React from 'react';
import useDinnerStore from '../app/dinnerStore';
function DinnerList() {
const {meals, removeMeal, toggleMealStatus, icons, addIcon} = useDinnerStore(
(state) => ({
meals: state.meals,
removeMeal: state.removeMeal,
toggleMealStatus: state.toggleMealStatus,
icons: state.icons,
addIcon: state.addIcon
})
)
return (
<div className="meal-item-container">
{meals.map((meal, i) => {
return (
<React.Fragment key={i}>
<div
className={'meal-item'}
style={{
backgroundColor: meal.completed ? "#FF0044" : "transparent"
}}>
<span className="meal-item-col-1"></span>
<input
checked={meal.completed}
type="checkbox"
onChange={(e) => {
toggleMealStatus(meal.id)
}}
/>
<span>{meal?.title} </span>
<button
onClick={() => {
removeMeal(meal.id)
}}
className="delete-btn">X</button>
[needing to add selected icon here]
</div>
</React.Fragment>
)
})}
</div>
)
}
export default DinnerList;