Hi, I made the following data structure mocking how the the admin user will add options for a new item
type OptionValues={ val:string,price:number}
type Option = {
optionName: string;
optionValues: OptionValues[];
};
example if the admin is adding meal and want to add options of size, sides and sauce there would be an array holding multiple entries like the following
{
optionName:"Size",
optionValues:[
{
val: "Small",
price: 0
},
{
val: "medium",
price: 5
},
{
val: "Large",
price: 10
}
]
},
{
optionName:"Side",
optionValues:[
{
val: "rice",
price: 0
},
{
val: "bread",
price: 5
},
{
val: "potatos",
price: 10
}
]},
{
optionName:"sauce",
optionValues:[
{
val: "bbq",
price: 0
},
{
val: "mild",
price: 5
},
{
val: "spicy mayo",
price: 10
}
]}
this will go into my ItemContainer component that renders a single item with the options and this is how I call it where items here is the raw data passes as a prop called options
<ItemContainer catName={"Fish"} itemImage={food} itemPrice={90} options={items}/>
inside ItemContainer I have defined a useState as instructed in the Docs but I made it an array to hold multiple selections.
const [useSelected, setSelected] = useState<string[]>([]);
Now, I understand that in theory I need to map through options first then inside that map I need to map again but for the sake of simplicity I hard coded the end result with magic numbers to demonstrate what I want to achieve so I skipped mapping through options and just wrote the three entries like that but mapped through each one
<IonRadioGroup value={useSelected[0]} onIonChange={(e: any)=>{setSelected([e.detail.value,useSelected[1],useSelected[2]])}}>
{useItemView[1].state && <div className="choices">
<IonListHeader>
<IonLabel>{props.options[0].optionName}</IonLabel>
</IonListHeader>
{
props.options[0].optionValues.map((optionValue) => {
return (
<IonItem>
<IonLabel>{optionValue.val} + {optionValue.price}kwd</IonLabel>
<IonRadio slot="start" value={optionValue.val} />
</IonItem>
); } )
}
</div>}
</IonRadioGroup>
<IonRadioGroup value={useSelected[1]} onIonChange={(e: any)=>{setSelected([useSelected[0],e.detail.value,useSelected[2]])}}>
{useItemView[1].state && <div className="choices">
<IonListHeader>
<IonLabel>{props.options[1].optionName}</IonLabel>
</IonListHeader>
{
props.options[1].optionValues.map((optionValue) => {
return (
<IonItem>
<IonLabel>{optionValue.val} + {optionValue.price}kwd</IonLabel>
<IonRadio slot="start" value={optionValue.val} />
</IonItem>
); } )
}
</div>}
</IonRadioGroup>
<IonRadioGroup value={useSelected[2]} onIonChange={(e: any)=>{setSelected([useSelected[0],useSelected[1],e.detail.value])}}>
{useItemView[1].state && <div className="choices">
<IonListHeader>
<IonLabel>{props.options[2].optionName}</IonLabel>
</IonListHeader>
{
props.options[2].optionValues.map((optionValue) => {
return (
<IonItem>
<IonLabel>{optionValue.val} + {optionValue.price}kwd</IonLabel>
<IonRadio slot="start" value={optionValue.val} />
</IonItem>
); } )
}
</div>}
</IonRadioGroup>
This works now I can select a Size, Side and a Sauce for my meal!
I have three questions
a) How to get rid of those magic numbers and map through options to achieve as many results and handle as many entries.
b) What if I want the user to choose one size but must choose two three sides and any number of sauces?
c) As I am new to this technology pleas let me know if I am on right track for best practice here, am I approaching a solution to this problem the right way here?
Note: I also need a way to pass the optionVal.price to the onIonChange function to set the additional charge of the option. I noticed that the only can pass to it what I put into value of
<IonRadio slot="start" value={optionValue.val} />
and I can’t call my setSelectedPrice(optionValue.price)function inside the return for some reason!
thank you