keanacobarde / INDIVIDUAL-ASSIGNMENT-Team-Roster

0 stars 0 forks source link

CREATE/UPDATE #9

Closed keanacobarde closed 11 months ago

keanacobarde commented 11 months ago

User Story

I, as the user, should be able to navigate to the 'New' item within the navbar and be met with a place to add a team member. This should be a form that can be submitted.

Acceptance Criteria

AS PULLED FROM THE INSTRUCTIONS

[CREATE Members]
As an authenticated user, when I create a member, the member object should include my uid.
As an authenticated user, I should be able to click the NEW link in the navbar that displays a form to add a new member.
As an authenticated user, when I fill out the form and submit a new member should be created in firebase and should now show in my Team view.

SINCE UPDATE IS INCLUDED WITHIN THE FORM FUNCTIONALITY

[UPDATE Members]
As an authenticated user, I should be able to see an edit button on each member card.
As an authenticated user, when I click the edit button I should see a form with the member information pre-populated in the form.
As an authenticated user, I should be able to edit the information in the form and hit the submit button.
As an authenticated user, when I submit the edit form firebase should be updated (PATCH request) and the Team view should update

The form should take into account the information highlighted in the ERD: image

Dependecies

5 - a solid understanding of the components that are needed for the completion of this issue is needed, as well as the dependencies of that issue.

https://github.com/keanacobarde/INDIVIDUAL-ASSIGNMENT-Team-Roster/issues/6 - This is an important implementation. These functions are dependent on correctly POSTING to the database.

Dev Notes

EXAMPLE FROM SIMPLY BOOKS

BOOKS > NEW.JS

import React from 'react';
import BookForm from '../../components/forms/BookForm';

// TODO: create a reusable form to add/edit book and render in this view

export default function AddBook() {
  return <BookForm />;
}

BOOKFORM.JS

import React, { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import PropTypes from 'prop-types';
import FloatingLabel from 'react-bootstrap/FloatingLabel';
import Form from 'react-bootstrap/Form';
import { Button } from 'react-bootstrap';
import { useAuth } from '../../utils/context/authContext';
import { getAuthors } from '../../api/authorData';
import { createBook, updateBook } from '../../api/bookData';

const initialState = {
  description: '',
  image: '',
  price: '',
  sale: false,
  title: '',
};

function BookForm({ obj }) {
  const [formInput, setFormInput] = useState(initialState);
  const [authors, setAuthors] = useState([]);
  const router = useRouter();
  const { user } = useAuth();

  useEffect(() => {
    getAuthors(user.uid).then(setAuthors);

    if (obj.firebaseKey) setFormInput(obj);
  }, [obj, user]);

  const handleChange = (e) => {
    const { name, value } = e.target;
    setFormInput((prevState) => ({
      ...prevState,
      [name]: value,
    }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    if (obj.firebaseKey) {
      updateBook(formInput).then(() => router.push(`/book/${obj.firebaseKey}`));
    } else {
      const payload = { ...formInput, uid: user.uid };
      createBook(payload).then(({ name }) => {
        const patchPayload = { firebaseKey: name };
        updateBook(patchPayload).then(() => {
          router.push('/');
        });
      });
    }
  };
  return (
    <Form onSubmit={handleSubmit}>
      <h2 className="text-white mt-5">{obj.firebaseKey ? 'Update' : 'Create'} Book</h2>

      {/* TITLE INPUT  */}
      <FloatingLabel controlId="floatingInput1" label="Book Title" className="mb-3">
        <Form.Control
          type="text"
          placeholder="Enter a title"
          name="title"
          value={formInput.title}
          onChange={handleChange}
          required
        />
      </FloatingLabel>

      {/* IMAGE INPUT  */}
      <FloatingLabel controlId="floatingInput2" label="Book Image" className="mb-3">
        <Form.Control
          type="url"
          placeholder="Enter an image url"
          name="image"
          value={formInput.image}
          onChange={handleChange}
          required
        />
      </FloatingLabel>

      {/* PRICE INPUT  */}
      <FloatingLabel controlId="floatingInput3" label="Book Price" className="mb-3">
        <Form.Control
          type="text"
          placeholder="Enter price"
          name="price"
          value={formInput.price}
          onChange={handleChange}
          required
        />
      </FloatingLabel>

      {/* AUTHOR SELECT  */}
      <FloatingLabel controlId="floatingSelect" label="Author">
        <Form.Select
          aria-label="Author"
          name="author_id"
          onChange={handleChange}
          className="mb-3"
          value={obj.author_id} // FIXME: modify code to remove error
          required
        >
          <option value="">Select an Author</option>
          {
            authors.map((author) => (
              <option
                key={author.firebaseKey}
                value={author.firebaseKey}
              >
                {author.first_name} {author.last_name}
              </option>
            ))
          }
        </Form.Select>
      </FloatingLabel>

      {/* DESCRIPTION TEXTAREA  */}
      <FloatingLabel controlId="floatingTextarea" label="Description" className="mb-3">
        <Form.Control
          as="textarea"
          placeholder="Description"
          style={{ height: '100px' }}
          name="description"
          value={formInput.description}
          onChange={handleChange}
          required
        />
      </FloatingLabel>

      {/* A WAY TO HANDLE UPDATES FOR TOGGLES, RADIOS, ETC  */}
      <Form.Check
        className="text-white mb-3"
        type="switch"
        id="sale"
        name="sale"
        label="On Sale?"
        checked={formInput.sale}
        onChange={(e) => {
          setFormInput((prevState) => ({
            ...prevState,
            sale: e.target.checked,
          }));
        }}
      />

      {/* SUBMIT BUTTON  */}
      <Button type="submit">{obj.firebaseKey ? 'Update' : 'Create'} Book</Button>
    </Form>
  );
}

BookForm.propTypes = {
  obj: PropTypes.shape({
    description: PropTypes.string,
    image: PropTypes.string,
    price: PropTypes.string,
    sale: PropTypes.bool,
    title: PropTypes.string,
    author_id: PropTypes.string,
    firebaseKey: PropTypes.string,
  }),
};

BookForm.defaultProps = {
  obj: initialState,
};

export default BookForm;

'EDIT' - SEEN WITHIN BOOKS > EDIT > [FIREBASEKEY].JS, DEPENDENT ON FORM COMPONENT FOR COMPLETION

import { React, useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import { getSingleBook } from '../../../api/bookData';
import BookForm from '../../../components/forms/BookForm';

export default function EditBook() {
  const [editItem, setEditItem] = useState({});
  const router = useRouter();
  // TODO: grab the firebasekey
  const { firebaseKey } = router.query;

  // TODO: make a call to the API to get the book data
  useEffect(() => {
    getSingleBook(firebaseKey).then(setEditItem);
  }, [firebaseKey]);

  // TODO: pass object to form
  return (<BookForm obj={editItem} />);
}