0

I am creating a movie website that displays Modals of movies when you click on the movie card. I'm able to handle the "onCancel" which turns setActivateModal to false and closes the Modal, but I also want to allow the "Schedule" button to do something. The intended behavior is to have the "Schedule" button generate a different form in which I can fill out to "schedule" a movie with basic form entries that are then sent to my database. I'm not struggling with the form, but I'm struggling with how to handle generating one with the "Schedule" button. I'm unsure if you are allowed to do "nested" Modals, but any way it can be handled is fine.

import React, { useEffect, useState } from 'react';
import {
  Layout,
  Input,
  Row,
  Col,
  Card,
  Tag,
  Spin,
  Modal,
  Typography,
  Button,
} from 'antd';
import 'antd/dist/antd.css';

const { Content } = Layout;
const { Search } = Input;
const { Meta } = Card;
const TextTitle = Typography.Title;

const SearchBox = ({ searchHandler }) => {
  return (
    <Row>
      <Col span={12} offset={6}>
        <Search
          placeholder="Search for movies to schedule!"
          enterButton="Search"
          size="large"
          onSearch={value => searchHandler(value)}
        />
      </Col>
    </Row>
  );
};

const MovieCard = ({
  Title,
  imdbID,
  Poster,
  ShowDetails,
  DetailRequest,
  ActivateModal,
}) => {
  const clickHandler = () => {
    ActivateModal(true);
    DetailRequest(true);

    fetch(`http://www.omdbapi.com/?i=${imdbID}&apikey=xxxxxxxx`)
      .then(resp => resp)
      .then(resp => resp.json())
      .then(response => {
        DetailRequest(false);
        ShowDetails(response);
      });
  };

  return (
    <Col style={{ margin: '50px' }} span={3}>
      <div>
        <Card
          style={{ width: 300 }}
          cover={
            <img
              alt={Title}
              src={
                Poster === 'N/A'
                  ? 'https://placehold.it/198x264&text=Image+Not+Found'
                  : Poster
              }
            />
          }
          onClick={() => clickHandler()}
        >
          <Meta title={Title} />
        </Card>
      </div>
    </Col>
  );
};

const MovieDetail = ({
  Title,
  Actors,
  Released,
  Rated,
  Runtime,
  Genre,
  Poster,
  Plot,
}) => {
  return (
    <Row>
      <Col span={11}>
        <img
          src={
            Poster === 'N/A'
              ? 'https://placehold.it/198x264&text=Image+Not+Found'
              : Poster
          }
          alt={Title}
        />
      </Col>
      <Col span={13}>
        <Row>
          <Col>
            <TextTitle>{Title}</TextTitle>
          </Col>
        </Row>
        <Row style={{ marginBottom: '.7em' }}>
          <Col>{Actors}</Col>
        </Row>
        <Row style={{ marginBottom: '.7em' }}>
          <Col>
            <Tag>{Released}</Tag>
            <Tag>{Rated}</Tag>
            <Tag>{Runtime}</Tag>
            <Tag>{Genre}</Tag>
          </Col>
        </Row>
        <Row>
          <Col>{Plot}</Col>
        </Row>
      </Col>
    </Row>
  );
};

const Loader = () => (
  <div>
    <Spin />
  </div>
);

function Movies() {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [query, setQuery] = useState('');
  const [activateModal, setActivateModal] = useState(false);
  const [details, setShowDetails] = useState(false);
  const [detailRequest, setDetailRequest] = useState(false);

  useEffect(() => {
    setError(null);
    setData(null);

    fetch(`http://www.omdbapi.com/?s=${query}&apikey=xxxxxxxx`)
      .then(resp => resp)
      .then(resp => resp.json())
      .then(response => {
        if (response.Response === 'False') {
          setError(response.Error);
        } else {
          setData(response.Search);
        }
      })
      .catch(({ message }) => {
        setError(message);
      });
  }, [query]);

  return (
    <div className="Movies">
      <Layout className="layout">
        <Content>
          <div style={{ background: '#4a576e', padding: 60, minHeight: 300 }}>
            <SearchBox searchHandler={setQuery} />
            <br />
            <Row justify="center">
              {data !== null &&
                data.length > 0 &&
                data.map((result, index) => (
                  <MovieCard
                    ShowDetails={setShowDetails}
                    DetailRequest={setDetailRequest}
                    ActivateModal={setActivateModal}
                    key={index}
                    {...result}
                  />
                ))}
            </Row>
          </div>
          <Modal
            title="Details"
            centered
            visible={activateModal}
            onCancel={() => setActivateModal(false)}
            /* onOk= {() => What do I put here? */
            width={800}
            footer={[
              <Button key="cancel" onClick={() => setActivateModal(false)}>
                Cancel
              </Button>,
              <Button
                key="schedule" /* onClick={() => setActivateForm(true)} */
              >
                Schedule
              </Button>,
            ]}
          >
            {detailRequest === false ? (
              <MovieDetail {...details} />
            ) : (
              <Loader />
            )}
          </Modal>
        </Content>
      </Layout>
    </div>
  );
}

export default Movies;
2
  • I have since figured out a solution to my own question, how do I proceed?
    – Ay123
    Commented Oct 20, 2020 at 0:40
  • you can put the solution as an answer so that others who run into this issue can benefit from it Commented Oct 20, 2020 at 0:48

1 Answer 1

0

Assuming all the routes are set up properly in your App.js, add the following changes:

Add this to your import list:

import { Link } from "react-router-dom";

In the Movies function, add the const [activeForm, setActiveForm] = useState(false); as shown below

function Movies() {

const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [query, setQuery] = useState('');
const [activateModal, setActivateModal] = useState(false);
const [details, setShowDetails] = useState(false);
const [detailRequest, setDetailRequest] = useState(false);
const [activateForm, setActivateForm] = useState(false);

In the return for your function, in the div tag right under the "Content" tag, add ActivateForm={setActivateForm} as shown below.

                <div style={{ background: '#4a576e', padding: 60, minHeight: 300 }}>
                    <SearchBox searchHandler={setQuery} />
                    <br />
                    <Row justify="center">
                        { data !== null && data.length > 0 && data.map((result, index) => (
                            <MovieCard 
                                ShowDetails={setShowDetails} 
                                DetailRequest={setDetailRequest}
                                ActivateModal={setActivateModal}
                                ActivateForm={setActivateForm}
                                key={index} 
                                {...result} 
                            />
                        ))}
                    </Row>
                </div>

Finally, in the Modal tag, append to the "onOk" as such, and also in your Modal footer, add the following for "onClick".

                    <Modal
                    title='Details'
                    centered
                    visible={activateModal}
                    onCancel={() => setActivateModal(false)}
                    onOk={() => setActivateForm(true)}
                    width={800}
                    footer={[
                        <Button key="cancel" onClick={() => setActivateModal(false)}>
                            Cancel
                        </Button>,
                        <Button key="schedule" onClick={() =>setActivateForm(true)}><Link to='/ScheduleForm'>Schedule</Link ></Button>
                      ]}
                    >
                    { detailRequest === false ?
                        (<MovieDetail {...details} />) :
                        (<Loader />) 
                    }
                </Modal>

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.