Mission Page: Button sets Editable Inputs

Let's now set up to edit the Mission title and description. We're going to expand the editable content to include inputs representing the title and description.

But first, we setup new state variables title and description from useState hooks. We initialize with the mission variables. We setup change functions to setTitle / setDescriptions from inputs.

In the editing content, we're rendering a lot more now. In the MissionTitleRow, we're rendering an input for the title, and two new buttons (Update / Cancel). Update is going to simply call a new function saveMission that just sets editing to false. Cancel will also set editing to false, but will revert to the original variables (note, saving doesn't persist, so canceling will revert to the original mission). We'll modify the saveMission more in the next module.

To edit the description, we use a new TextArea component imported from the Input.js file.

Menu
Lesson 25/26
import { useState, useMemo } from "react";
import styled from "styled-components";
import { useParams } from "react-router-dom";
import { missions } from "./Missions";
import Button from "../Components/Button";
import Input from "../Components/Input";
import { TextArea } from "../Components/Input";

const MissionTitleRow = styled.div`
  display: grid;
  grid-template-columns: 1fr 200px;
`;

const MissionTitle = styled.h2`
  font-size: 32px; 
`;

const DescriptionContainer = styled.div``;

const EditDescriptionContainer = styled.div``;

const DescriptionParagraph = styled.p`
  font-size: 22px;
  font-weight: normal;
  line-height: 21px;
`;

const MissionActions = styled.div`
  display: grid;
  grid-auto-flow: column;
  justify-self: right;
  gap: 4px;
`;

function findMissionById(id) {
  return () => missions.find((mission) => mission.id == id);
}

function Mission() {
  const { id } = useParams();
  const mission = useMemo(findMissionById(id), []);
  const [editing, setEditing] = useState(false);
  const [title, setTitle] = useState(mission?.title);
  const [description, setDescription] = useState(mission?.description);

  if (!mission) {
    return <div> No mission found </div>;
  }

  const onChangeTitle = ({ target: { value } }) => setTitle(value);
  const onChangeDescription = ({ target: { value } }) => setDescription(value);

  function saveMission() {
    setEditing(false);
  }

  function revert() {
    setEditing(false);
    setTitle(mission?.title);
    setDescription(mission?.description);
  }

  return editing ? (
    <>
      <MissionTitleRow>
        <Input
          placeholder="Mission Title"
          autoFocus
          value={title}
          onChange={onChangeTitle}
        />
        <div>
          <Button onClick={saveMission}> Update </Button>
          <Button variant="outline" onClick={revert}>
            {" "}
            Cancel{" "}
          </Button>
        </div>
      </MissionTitleRow>
      <EditDescriptionContainer>
        <TextArea
          placeholder="Description"
          size="small"
          value={description}
          onChange={onChangeDescription}
        />
      </EditDescriptionContainer>
    </>
  ) : (
    <div>
      <MissionTitleRow>
        <MissionTitle> {title} </MissionTitle>
        <MissionActions>
          <Button variant="outline" onClick={() => setEditing(true)}>
            Edit
          </Button>
          <Button variant="outline">Delete</Button>
        </MissionActions>
      </MissionTitleRow>
      <DescriptionContainer>
        <DescriptionParagraph>{description}</DescriptionParagraph>
      </DescriptionContainer>
    </div>
  );
}

export default Mission;