keanacobarde / INDIVIDUAL-ASSIGNMENT-Team-Roster

0 stars 0 forks source link

COMPONENT PLANNING #5

Closed keanacobarde closed 1 year ago

keanacobarde commented 1 year ago

User Story

While this is not imperative to the user directly, it in-directly supports the user experience. The user should be able to complete all needed CRUD functionality with the components planned here.

Acceptance Criteria

The following functionality is expected of this application: CREATE - Creating members to be added to a roster. This will require a FORM component. READ - Users should be able to read team members and their details. This will require a CARD component that renders all the details of a team member. It will also require the creation of a component responsible for displaying all of the cards. A PAGE. UPDATE - Users should be able to update an individual member's card. The form should be PRE-POPULATED with information (handled w/ useEffect()). This functionality is handled within the MemberForm.js component referenced in CREATE. DELETE - This segment of functionality is dictated not by a component but by specific API calls and routing.

Dependecies

4 will need to be completed as well as the creation of the needed API calls in order to supply the functionality of the components.

Dev Notes

EXAMPLES FROM SIMPLY BOOKS

CREATE - AUTHORFORM.JS COMPONENT

import PropTypes from 'prop-types';
import Form from 'react-bootstrap/Form';
import { Button } from 'react-bootstrap';
import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import { createAuthor, updateAuthor } from '../../api/authorData';
import { useAuth } from '../../utils/context/authContext';

// Setting Initial state for useState()
const initialState = {
  email: '',
  favorite: false,
  first_name: '',
  last_name: '',
};

export default function AuthorForm({ obj }) {
  const [formInput, setFormInput] = useState(initialState);
  const router = useRouter();
  const { user } = useAuth();

  useEffect(() => {
    if (obj.firebaseKey) setFormInput(obj);
  }, [obj]);

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

  const handleSubmit = (e) => {
    e.preventDefault();
    if (obj.firebaseKey) {
      updateAuthor(formInput).then(() => router.push(`/author/${obj.firebaseKey}`));
    } else {
      const payload = { ...formInput, uid: user.uid };
      createAuthor(payload).then(({ name }) => {
        const patchPayload = { firebaseKey: name };
        updateAuthor(patchPayload).then(() => {
          router.push('/');
        });
      });
    }
  };

  return (
    <Form onSubmit={handleSubmit}>
      <h2 className="text-white mt-5">{obj.firebaseKey ? 'Update' : 'Create'} Author</h2>

      <Form.Group className="mb-3 text-white mt-5" controlId="authorFirstName">
        <Form.Label>First Name</Form.Label>
        <Form.Control
          type="text"
          placeholder="First Name"
          name="first_name"
          value={formInput.first_name}
          onChange={handleChange}
          required
        />
      </Form.Group>

      <Form.Group className="mb-3 text-white mt-5" controlId="authorLastName">
        <Form.Label>Last Name</Form.Label>
        <Form.Control type="text" placeholder="Last Name" name="last_name" value={formInput.last_name} onChange={handleChange} required />
      </Form.Group>
      <Form.Group className="mb-3 text-white mt-5" controlId="authorEmail">
        <Form.Label>Email</Form.Label>
        <Form.Control type="email" placeholder="Email" name="email" value={formInput.email} onChange={handleChange} required />
      </Form.Group>
      <Form.Group className="mb-3 text-white mt-5" controlId="authorFavorite">
        <Form.Check
          type="checkbox"
          label="Favorite?"
          name="favorite"
          checked={formInput.favorite}
          onChange={(e) => {
            setFormInput((prevState) => ({
              ...prevState,
              favorite: e.target.checked,
            }));
          }}
        />
      </Form.Group>
      <Button variant="primary" type="submit"> {obj.firebaseKey ? 'Update' : 'Create'} Author
      </Button>
    </Form>
  );
}

AuthorForm.propTypes = {
  obj: PropTypes.shape({
    email: PropTypes.string,
    favorite: PropTypes.bool,
    firebaseKey: PropTypes.string,
    first_name: PropTypes.string,
    last_name: PropTypes.string,
  }),
};

AuthorForm.defaultProps = {
  obj: initialState,
};

READ - AUTHOR CARD + PAGE COMPONENT

import React from 'react';
import PropTypes from 'prop-types';
import Link from 'next/link';
import Button from 'react-bootstrap/Button';
import Card from 'react-bootstrap/Card';
import { deleteAuthorBooks } from '../api/mergedData';

export default function AuthorCard({ authorObj, onUpdate }) {
  const deleteThisAuthor = () => {
    if (window.confirm(`Delete ${authorObj.first_name} ${authorObj.last_name}?`)) {
      deleteAuthorBooks(authorObj.firebaseKey).then(() => onUpdate());
    }
  }; // DELETE FUNCTIONALITY REFERENCED IN 'ACCEPTANCE CRITERIA > DELETE'

  return (
    <Card style={{ width: '18rem', margin: '10px' }}>
      <Card.Body>
        <Card.Title>{authorObj.first_name} {authorObj.last_name}</Card.Title>
        <p> {authorObj.email} </p>
        <Link href={`/author/${authorObj.firebaseKey}`} passHref>
          <Button variant="primary" className="m-2">VIEW</Button>
        </Link>
        {/* DYNAMIC LINK TO EDIT THE BOOK DETAILS  */}
        <Link href={`/author/edit/${authorObj.firebaseKey}`} passHref>
          <Button variant="info">EDIT</Button>
        </Link>
        <Button variant="danger" onClick={deleteThisAuthor} className="m-2">
          DELETE
        </Button>
        {authorObj.favorite ? <Button variant="success"> FAVORITE </Button> : ''}
      </Card.Body>
    </Card>
  );
}

AuthorCard.propTypes = {
  authorObj: PropTypes.shape({
    email: PropTypes.string,
    favorite: PropTypes.bool,
    firebaseKey: PropTypes.string,
    first_name: PropTypes.string,
    last_name: PropTypes.string,
  }).isRequired,
  onUpdate: PropTypes.func.isRequired,
};

AUTHOR PAGE

/* eslint-disable react-hooks/exhaustive-deps */
import React, { useEffect, useState } from 'react';
import Link from 'next/link';
import { Button } from 'react-bootstrap';
import { useAuth } from '../utils/context/authContext';
import { getAuthors } from '../api/authorData';
import AuthorCard from '../components/AuthorCard';

export default function Authors() {
  // Create useState for authors
  const [authors, setAuthors] = useState([]);

  // Obtain user.uid
  const { user } = useAuth();

  // Get all authors w/ user.uid w/ API call
  const getAllAuthors = () => {
    getAuthors(user.uid).then(setAuthors);
  };

  // Create useEffect so that operation is done whenever page is rednered.
  useEffect(() => {
    getAllAuthors();
  }, []);

  return (
    <div className="text-center my-4">
      <Link href="/author/new" passHref>
        <Button> Add an Author </Button>
      </Link>
      {authors.map((author) => <AuthorCard key={author.firebaseKey} authorObj={author} onUpdate={getAllAuthors} />)}
    </div>
  );
}

EDIT - [FIREBASEKEY].JS

import { React, useEffect, useState } from 'react';
import { useRouter } from 'next/router';
import AuthorForm from '../../../components/forms/AuthorForm';
import { getSingleAuthor } from '../../../api/authorData';

export default function EditAuthor() {
  const [editItem, setEditItem] = useState([]);
  const router = useRouter();
  const { firebaseKey } = router.query;
  console.warn(editItem);

  useEffect(() => {
    getSingleAuthor(firebaseKey).then(setEditItem);
  }, [firebaseKey]);

  return (
    <AuthorForm obj={editItem} />
  );
}