Search code examples
reactjsreact-router-domredux-toolkit

How to render a different title on the modal by clicking on a specific item among many options?


I am building an app where I have different seats that the user can book, and the logic is that when you click on one seat, the modal shows up, and you click on confirm, then you will be redirected to another screen that shows that seat is incremented by one. What I need is that when I click on a single seat, it should display the name of that seat (for example, "you have selected seat 1"), and when I click confirm, it should only increment the number of that seat on another screen. The help I need is in figuring out how I can render a specific title on the modal and how I can fire different functions that increment the number of each item so I can avoid repeating the code in several components. Thank you in advance. Here is my code:

image screen 1

image screen 2

Seat.jsx:

import React, { useEffect, useState } from "react";
import "./zones.css";
import { RxCross2 } from "react-icons/rx";
import {
  addSeat_1,
  add_2,
  addSeat_3,
  addSeat_4,
  addSeat_5,
} from "../../../features/trolleys/trolleySlice";
import { useDispatch } from "react-redux";
import { Link } from "react-router-dom";

const Seats = () => {
  const [show, setShow] = useState(false);
  const [title, setTitle] = useState({
    data: [
      {
        value: "Seat 1",
        id: 1,
      },
      {
        value: "Seat 2",
        id: 2,
      },
      {
        value: "Seat 3",
        id: 3,
      },
      {
        value: "Seat 4",
        id: 4,
      },

      {
        value: "Seat 5",
        id: 5,
      },
    ],
  });

  const toggleTitle = () => {
    setTitle(title.data.map((item) => item.value === item.id && item.value));
  };

  const dispatch = useDispatch();

  useEffect(() => {
    document.title = "Zones";
  });

  return (
    <div className="seat__container">
      <div onClick={() => setShow(true)} className="seat seat__fresh">
        <img src="/assets/freshGoods.png" alt="fresh" />
        <p className="seat__text">Seat 1</p>
      </div>
      <div onClick={() => setShow(true)} className="seat seat__fruits">
        <img src="/assets/fruit_veg.png" alt="dry/good" />
        <p className="seat__text">Seat 2</p>
      </div>
      <div onClick={() => setShow(true)} className="seat seat__deli">
        <img src="/assets/deli.png" alt="dry/good" />
        <p className="seat__text">Seat 3</p>
      </div>
      <div onClick={() => setShow(true)} className="seat seat__frozen">
        <img src="/assets/frozen.png" alt="dry/good" />
        <p className="seat__frozen">Seat 4</p>
      </div>
      <div onClick={() => setShow(true)} className="seat seat__WindSpritz">
        <img src="/assets/wine_spritz.png" alt="electronic" />
        <p className="seat__text">Seat 5</p>
      </div>
      <div className="seat seat__undraw">
        <img
          className="undraw"
          src="/assets/undraw_gone_shopping_re_2lau 1.png"
          alt="undraw"
        />
      </div>
      {show && (
        <div className="modal">
          <div className="inner__modal">
            <RxCross2 onClick={() => setShow(false)} />
            <p className="selected__text">You have selected</p>

        <p onClick={toggleTitle} className="item__name">
           {/*a specific name for a seat about should be displayed here*/}
          
        </p>

        {title.data.map((item) =>(
  

       <Link
     onClick={() => {
     item.value==="seat 1"&&dispatch(addSeat_1())
     item.value==="seat 1"&&dispatch(addSeat_2())
    item.value==="seat 1"&&dispatch(addSeat_3())
    item.value==="seat 1"&&dispatch(addSeat_4())
     item.value==="seat 1"&&dispatch(addSeat_5())
   }}
  to="/room"
   className="confirm__btn"
   >
   Confirm
   </Link>
    ))}
        <button onClick={() => setShow(false)} className="cancel__btn">
          Cancel
        </button>
      </div>
    </div>
  )}
</div>

  );
};

export default Seats;

Room.jsx:

import "./room.css";
import { GiCancel } from "react-icons/gi";
import { useEffect } from "react";
import { useSelector } from "react-redux";

const Room = () => {
  const roomQty = useSelector((state) => state.room);

  useEffect(() => {
    document.title = "Room";
  });

  return (
    <div className="room__container">
      <div className="room__list">
        <div className="room__item__box room__item__box__fresh">
          <div className="left__items">
            <div className="image__box">
              <img src="/assets/seat1s.png" alt="img" />
            </div>
            <p className="room__text">Seat1</p>
          </div>
          <div className="right__items">
            <span className="item__count">{roomQty.seat1Qty}</span>

            <div className="button__items">
              <GiCancel className="cancel" />
              <button className="cancel">Cancel</button>
            </div>
          </div>
        </div>
        <div className="room__item__box room__item__box__fruit-veg">
          <div className="left__items">
            <div className="image__box">
              <img src="/assets/seat2.png" alt="img" />
            </div>
            <p className="room__text">Seat2</p>
          </div>
          <div className="right__items">
            <span className="item__count">{roomQty.seat2Qty}</span>
            <div className="button__items">
              <GiCancel className="cancel" />
              <button className="cancel">Cancel</button>
            </div>
          </div>
        </div>
        <div className="room__item__box">
          <div className="left__items">
            <div className="image__box">
              <img src="/assets/seat3.png" alt="img" />
            </div>
            <p className="room__text">Seat3</p>
          </div>
          <div className="right__items">
            <span className="item__count">{roomQty.seat3Qty}</span>
            <div className="button__items">
              <GiCancel className="cancel" />
              <button className="cancel">Cancel</button>
            </div>
          </div>
        </div>
        <div className="room__item__box room__item__box__frozen">
          <div className="left__items">
            <div className="image__box">
              <img src="/assets/seat4.png" alt="img" />
            </div>
            <p className="room__text">Seat4</p>
          </div>
          <div className="right__items">
            <span className="item__count">{roomQty.seat4Qty}</span>

            <div className="button__items">
              <GiCancel className="cancel" />
              <button className="cancel">Cancel</button>
            </div>
          </div>
        </div>
        <div className="room__item__box room__item__box__wineSpritz">
          <div className="left__items">
            <div className="image__box">
              <img src="/assets/seat5.png" alt="img" />
            </div>
            <p className="room__text">Seat5</p>
          </div>
          <div className="right__items">
            <span className="item__count">{roomQty.seat5Qty}</span>
            <div className="button__items">
              <GiCancel className="cancel" />
              <button className="cancel">Cancel</button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
};

export default Room;

Solution

  • There is nothing in the Seats that associates a specific "seat" element to any specific title pr action. I'd suggest refactoring the component a bit to take a seat configuration array that is mapped to the UI, and to use a single selected seat state is either null (to indicate no seat is selected) or is set to a specific seat object value.

    ...
    import {
      addSeat_1,
      addSeat_2,
      addSeat_3,
      addSeat_4,
      addSeat_5,
    } from "../../../features/trolleys/trolleySlice";
    ...
    
    const seats = [
      {
        action: addSeat_1,
        value: "Seat 1",
        id: 1,
        className: "seat__fresh",
        img: {
          src: "/assets/freshGoods.png",
          alt: "fresh",
        },
      },
      {
        action: addSeat_2,
        value: "Seat 2",
        id: 2,
        className: "seat__fruits",
        img: {
          src: "/assets/fruit_veg.png",
          alt: "dry/good",
        },
      },
      {
        action: addSeat_3,
        value: "Seat 3",
        id: 3,
        className: "seat__deli",
        img: {
          src: "/assets/deli.png",
          alt: "dry/good",
        },
      },
      {
        action: addSeat_4,
        value: "Seat 4",
        id: 4,
        className: "seat__frozen",
        img: {
          src: "/assets/frozen.png",
          alt: "dry/good",
        },
      },
      {
        action: addSeat_5,
        value: "Seat 5",
        id: 5,
        className: "seat__WindSpritz",
        img: {
          src: "/assets/wine_spritz.png",
          alt: "electronic",
        },
      },
    ];
    
    const Seats = () => {
      const dispatch = useDispatch();
    
      const [selectedSeat, setSelectedSeat] = useState(null);
    
      useEffect(() => {
        document.title = "Zones";
      }, []);
    
      return (
        <div className="seat__container">
          {seats.map((seat) => {
            const { className, id, img, value } = seat;
            return (
              <div
                key={id}
                onClick={() => setSelectedSeat(seat)}
                className={["seat", className].filter(Boolean).join(" ")}
              >
                <img {...img} />
                <p className="seat__text">{label}</p>
              </div>
            );
          })}
          <div className="seat seat__undraw">
            <img
              className="undraw"
              src="/assets/undraw_gone_shopping_re_2lau 1.png"
              alt="undraw"
            />
          </div>
          {selectedSeat && (
            <div className="modal">
              <div className="inner__modal">
                <RxCross2 onClick={() => setSelectedSeat(null)} />
                <p className="selected__text">
                  You have selected
                </p>
    
                <p className="item__name">
                 {seat.label}
                </p>
    
                <Link
                  onClick={() => dispatch(selectedSeat.action())}
                  to="/room"
                  className="confirm__btn"
                >
                  Confirm
                </Link>
                <button
                  onClick={() => setSelectedSeat(null)}
                  className="cancel__btn"
                >
                  Cancel
                </button>
              </div>
            </div>
          )}
        </div>
      );
    };