const [isAgent, setAgent] = useState(true);
{isSupervisor.map((value, index) => {
return <div className="text-gray-700 rounded-lg" key={index}>
{isAgent ? <div className="flex flex-row">
<div className=" flex-none text-center">
<div>Halo</div>
</div>
<div className="flex-grow text-gray-700 px-2 py-1 my-auto">
<button onClick={() => setAgent(true)} className="bg-custom-14 ">Edit</button>
</div>
</div>
</div>
</div> : <div>
<div className="flex flex-col my-2 mx-8">
<div className=" flex-none text-center">
<div>Halo</div>
</div>
<div className="flex justify-end">
<button onClick={() => setAgent(false)} className="bg-custom-14">Discard</button>
</div>
</div> </div>
problem:
when i click a condition button, all button follow the condition, is there any solution to make a separate condition in every button ? thanks
I write this answer assuming that in this list of sections with buttons you only need to change one section on clicking 'edit'.
Since isAgent and setAgent affect all sections at once, your state should have a map of states for each sections, isAgent should be a function to retrieve balue from this state by a section key, and setAgent should accept the section key.
So, your react state may look ike this:
class State {
editingAgents = {};
isAgent = (index) => editingAgents[index];
setAgents = (index, isAgent) => editingAgents[index] = isAgent;
}
and modified component code may be like this (notice how isAgent and setAgent are used now)
const [isAgent, setAgent] = useState(true);
{isSupervisor.map((value, index) => {
return <div className="text-gray-700 hover:bg-custom-8 rounded-lg" key={index}>
{isAgent(index) ? <div className="flex flex-row">
<div className=" flex-none text-center mx-2 my-1">
<img src={Ane} className=" w-54px lg:w-50px object-contain"></img>
</div>
<div className="flex-grow text-gray-700 px-2 py-1 my-auto">
<button onClick={() => setAgent(index, true)} className="bg-custom-14 ">Edit</button>
</div>
</div>
</div>
</div> : <form onSubmit={handleSubmit(updateAgent)}>
<div className="flex flex-col my-2 mx-8">
<div className="m-2 lg:mt-4 hidden">
<div className="inline-block w-3/12 text-base lg:text-sm font-semibold">Id</div>
</div>
<div className="flex justify-end">
<button onClick={() => setAgent(index, false)} className="bg-custom-14">Discard</button>
</div>
</div> </form>
Related
I've a map that creates edit and delete buttons.
The delete button needs to be confirmed.
So I created a modal.
console.log(additive._id) at the first delete button gives me the correct ._id
the confirm button inside the modal gives me always the last ._id of the array i map through, so it'll always delete the last item.
How can i get the correct ._id?
{additives.sort(byId).map((additive) => (
<div key={additive._id}>
<div>
<div </div>
<div>{additive.additive[0]?.label}</div>
</div>
<div className='flex justify-between items-center'>
<button
onClick={() =>
editAdditive(
additive._id,
additive.additive[0]?.value,
additive.additive[0]?.label
)
}>
Edit
</button>
<button
onClick={() => {
setShowModal(!showModal);
console.log(additive._id);
}}
>
Delete
</button>
{showModal && (
<>
<div
className='backdrop'
onClick={(e) => {
if (e.target.className === 'backdrop') {
setShowModal(false);
}
}}
>
<div className='relative w-auto my-6 mx-auto max-w-3xl'>
<div className=' rounded-lg shadow-2xl relative flex flex-col w-full bg-white outline-none focus:outline-none'>
<div className='flex items-start justify-between p-5 border-b border-solid border-slate-200 rounded-t bg-gray-600'>
<h3 className='text-3xl font-semibold text-red-500'>
Delete Additive
</h3>
</div>
<div className='relative p-6 flex-auto bg-gray-600'>
<p className='my-4 text-white text-lg leading-relaxed'>
Are you sure?
</p>
</div>
<div className='flex items-center justify-end p-6 border-t border-solid border-slate-200 rounded-b bg-gray-600'>
<button
className='text-red-500 background-transparent font-bold uppercase px-6 py-2 text-sm outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150'
type='button'
onClick={() => setShowModal(!showModal)}
>
Cancel
</button>
<button
className='bg-red-500 text-white active:bg-red-600 font-bold uppercase text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150'
type='button'
onClick={() => {
deleteAdditive(additive._id);
setShowModal(!showModal);
console.log(additive._id);
}}
>
Confirm
</button>
</div>
</div>
</div>
</div>
</>
)}
</div>
</div>
))}
store the additive id in a state and use it in the modal
const [additiveId, setAdditiveId] = useState()
<button
onClick={() => {
setShowModal(!showModal);
setAdditiveId(additive._id)
console.log(additive._id);
}}
>
Delete
</button>
<button
className='bg-red-500 text-white active:bg-red-600 font-bold uppercase text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150'
type='button'
onClick={() => {
deleteAdditive(additiveId);
setShowModal(!showModal);
console.log(additiveId);
}}
>
Confirm
</button>
I would like to do some changes to the Ui by sliding the slider with Carousel tailwind and NextJS, yet I have no idea to do so?!
this is an example of my code
...
const slider = sliderData.map((item, index) => {
return (
<>
<div
className={`carousel-item ${
index == 0 && "active"
} relative float-left w-full`}
>
<Link href={item.link + `?storeId=${state.id}`}>
<button className="block w-full">
<img src={item.image} className="block w-full" alt="..." />
</button>
</Link>
<div className="carousel-caption hidden md:block absolute text-center">
<h5 className="text-xl">{item.title}</h5>
<p>{item.description}</p>
</div>
</div>
</>
);
});
const sliderButton = sliderData.map((item, index) => {
return (
<>
<button
type="button"
data-bs-target="#carouselExampleCaptions"
data-bs-slide-to={`${index}`}
className="active"
aria-current="true"
aria-label={item.title}
></button>
</>
);
});
...
return (
<>
<div className="flex flex-col">
<div
id="carouselExampleCaptions"
className="carousel slide relative w-screen"
data-bs-ride="carousel"
>
<div className="carousel-indicators absolute right-0 bottom-0 left-0 flex justify-center p-0 mb-4">
{sliderButton}
</div>
<div className="carousel-inner relative w-full overflow-hidden">
{slider}
</div>
<button
className="carousel-control-prev absolute top-0 bottom-0 flex items-center justify-center p-0 text-center border-0 hover:outline-none hover:no-underline focus:outline-none focus:no-underline left-0"
type="button"
data-bs-target="#carouselExampleCaptions"
data-bs-slide="prev"
>
<span
className="carousel-control-prev-icon inline-block bg-no-repeat"
aria-hidden="true"
></span>
<span className="visually-hidden">Previous</span>
</button>
<button
className="carousel-control-next absolute top-0 bottom-0 flex items-center justify-center p-0 text-center border-0 hover:outline-none hover:no-underline focus:outline-none focus:no-underline right-0"
type="button"
data-bs-target="#carouselExampleCaptions"
data-bs-slide="next"
>
<span
className="carousel-control-next-icon inline-block bg-no-repeat"
aria-hidden="true"
></span>
<span className="visually-hidden">Next</span>
</button>
</div>
<div>
<CatalogView
store={state.loadedStore}
categories={state.loadedCategories}
products={state.loadedProducts}
selectedCategory={state.selectedCategory}
/>
</div>
</div>
</>
);
the changes I'm trying to do is to change the selectedCategory on slide, which are stored in the state object and the state hook to change them, yet how to let's say if the user tap on next or slide the slider to call setState.
In the code below, when I click on the burger menu, the design changes from burger to an X and the menu opens successfully. However, when I click on a link within the menu, the menu does close BUT the X menu does NOT change its design back to a burger.In other words, the menu closes but the css of the icon does not change back. Does anyone know what I am doing wrong?
const handleClick = (event: any) => {
if (!menuOpen) {
event.currentTarget.classList.add("open");
setMenu(true);
} else {
event.currentTarget.classList.remove("open");
setMenu(false);
}
};
<div className="mt-4 container page-container">
<div className="row">
<div className="d-grid gap-2 pb-3 col-4 mx-auto ">
<div className="menu-btn" onClick={handleClick}>
<div className="menu-btn_burger"></div>
</div>
</div>
</div>
{menuOpen && (
<div className="row">
<div className="d-grid gap-2 pt-3 col-6 mx-auto ">
<Link to="/add" onClick={handleClick} className="btn btn-primary btn-sm ">
Add Task
</Link>
<Link to="/" onClick={handleClick} className="btn btn-primary btn-sm">
All Reminders <span className="badge badge-light text-dark">{tasks.length > 0 && tasks.length}</span>
</Link>
</div>
</div>}
The problem is from the event target
In the first case, the target is the div with class menu-button but in the second case, it is referring to the link element.
How to solve it?
Use Refs
const menuRef = useRef(null);
const handleClick = (event: any) => {
if (!menuOpen) {
menuRef.current.classList.add("open");
setMenu(true);
} else {
menuRef.current.classList.remove("open");
setMenu(false);
}
};
<div className="mt-4 container page-container">
<div className="row">
<div className="d-grid gap-2 pb-3 col-4 mx-auto ">
<div ref={menuRef} className="menu-btn" onClick={handleClick}>
<div className="menu-btn_burger"></div>
</div>
</div>
</div>
{menuOpen && (
<div className="row">
<div className="d-grid gap-2 pt-3 col-6 mx-auto ">
<Link to="/add" onClick={handleClick} className="btn btn-primary btn-sm ">
Add Task
</Link>
<Link to="/" onClick={handleClick} className="btn btn-primary btn-sm">
All Reminders <span className="badge badge-light text-dark">{tasks.length > 0 && tasks.length}</span>
</Link>
</div>
</div>}
see more in the official docs
React Ref
I am using react and globalContext to add items to a cart page and this adds the product to the array stored in localStorage and looks like this.
basket,…]
0: {id: "9", title: "Apple Watch SE 40mm (GPS) - Space Grey Aluminium Case with Midnight Sport Band",…}
id: "9"
price: 249.99
quantity: 1
src: "/static/media/se.0ca02982636517aed223.png"
title: "Apple Watch SE 40mm (GPS) - Space Grey Aluminium Case with Midnight Sport Band"
The key is basket and i am able to map the data in the basket page but how would I calculate the total of the items within that array?
import { GlobalContext } from '../context/GlobalState'
export const Basket = () => {
const { basket } = useContext(GlobalContext)
return (
<div className="h-screen bg-zinc-100 p-4">
<div className="py-5">
<div className="max-w-md mx-auto bg-white shadow-lg rounded-lg md:max-w-7xl">
<div className="md:flex">
<div className="w-full p-4">
<div className="md:grid md:grid-cols-3 gap-2 ">
<div className="col-span-2 p2 md:p-5">
<h1 className="text-xl font-bold ">Shopping Basket</h1>
<div className="flex justify-between flex-col items-center mt-6 pt-6 gap-12">
{basket.length > 0 ? (
<>
{basket.map(item => (
<>
<div className='flex flex-col w-full justify-between md:gap-44 items-start'>
<div className="flex items-center">
<img src={item.src} className="rounded w-20 " />
<div className="flex flex-col ml-3 gap-1 ">
<span className="md:text-lg text-sm font-bold w-full md:t-width ">{item.title}</span>
<span className="text-xl font-bold">£ {item.price}</span>
</div>
</div>
</div>
</>
))}
</>
) : (
<div>No Items</div>
)}
</div>
<div className="flex justify-between items-center mt-6 pt-6 border-t">
<div className="flex items-center"> <i className="fa fa-arrow-left text-sm pr-2">
</i> <span className="text-md font-medium text-amz hover:text-orange-500 cursor-pointer "> <FontAwesomeIcon icon={faChevronLeft}></FontAwesomeIcon> Continue Shopping</span>
</div>
<div className="flex justify-center items-end">
<span className="text-sm font-medium text-gray-400 mr-1">Total:</span>
<span className="text-lg font-bold text-gray-800 ">Total}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
You'd simply loop over the array from the localstorage and calculate the total.
let cartArray = localStorage.getItem("basket");
/* since cartArray returns a stringified array you need to parse it */
cartArray = JSON.parse(cartArray);
/* you now have an array of objects. You'd now want to use the reduce function on the object */
const total = cartArray.reduce((prev, cur) => (cur.price * cur.quantity) + prev, 0);
total would be your cart total
I want to include my - button in my gray bar. As you can see in the picture, my blue button exceeds the gray bar
export default function App() {
...
return (
<div className="text-md font-bold">
Invitee {i + 1}
<span className="float-right ">
{!!i && (
<Button className="rounded-md float-right mt-4" primary onClick={() => removeInvitee(Id)}>
-
</Button>
)}
</span>
...
)
You can use the flexbox properties to make the design you want. I had created the very similar example below , please add your functions here and replace class with className.
<script src="https://cdn.tailwindcss.com"></script>
<div class="container mx-auto py-4">
<div class="bg-gray-200 text-md flex items-center justify-between rounded-r-md">
<div class=" font-bold text-gray-500 ml-4" >Invitee 2</div>
<div class="">
<Button primary class="rounded-md bg-black text-white py-2 px-4" onclick="removeInvitee(pId)">
-
</Button>
</div>
</div>
</div>