Search code examples
javascriptreactjsfiltercomponentsaddition

how to add data to a user's profile while not affecting other users' profile React


When a user is clicked, it goes to his/her profile page. Clicking the notes tag on the profile page, user can add notes to his/her profile. But now when any user adds notes, the notes also appear in other users' profile. How to make it so that the added notes only appear on the user's profile who adds the notes?

    import React, { useState, useEffect } from "react";
    import { Switch, Route } from "react-router-dom";
    import PatientsTable from "./components/PatientsTable";
    import EditPatient from "./components/EditPatient";
    
    function App() {
      const [patients, setPatients] = useState([]);
      const [notes, setNotes] = useState([]);
      const finalDraftNotes = notes.filter((note) => note.isFinal === true);
    
      const fetchPatients = async () => {
        const response = await fetch("http://localhost:3000/users");
        const results = await response.json();
        setPatients(results);
      };
    console.log(notes)
      useEffect(() => {
        fetchPatients();
      }, []);
    
      const handleAddNote = (note) => {
        setNotes((prev) => [note, ...prev]);
      };
    
      const deleteDraftClick = (draftId) => {
        setNotes((prev) => prev.filter((draft) => draft.id !== draftId));
      };
    
      const saveNotesClick = () => {
        setNotes((prev) =>
          prev.map((note) => {
            return {
              ...note,
              isFinal: true,
            };
          })
        );
      };
    
      return (
        <>
          <Switch>
            <Route exact path="/">
              <PatientsTable patients={patients} />
            </Route>
            <Route path="/patient/:id">
              <EditPatient
                patients={patients}
                notes={notes}
                handleAddNote={handleAddNote}
                deleteDraftClick={deleteDraftClick}
                saveNotesClick={saveNotesClick}
                finalDraftNotes={finalDraftNotes}
              />
            </Route>
          </Switch>
        </>
      );
    }
    
    export default App;
    import React from "react";
    import { Link } from "react-router-dom";
    import {
      makeStyles,
      Table,
      TableBody,
      TableCell,
      TableContainer,
      TableHead,
      TableRow,
      Paper,
    } from "@material-ui/core";
    
    const useStyles = makeStyles({
      tableContainer: {
        width: 700,
        margin: "20px auto",
      },
      tableHead: {
        backgroundColor: "rgb(25,118,210)",
      },
      tableRow: {
        textDecoration: "none",
      },
    });
    
    export default function PatientsTable({ patients, selectPatientClick }) {
      const styles = useStyles();
      return (
        <TableContainer className={styles.tableContainer} component={Paper}>
          <Table aria-label="simple table">
            <TableHead className={styles.tableHead}>
              <TableRow>
                <TableCell>First Name</TableCell>
                <TableCell align="right">Last name</TableCell>
                <TableCell align="right">DOB</TableCell>
                <TableCell align="right">Phone Number</TableCell>
                <TableCell align="right">Email</TableCell>
              </TableRow>
            </TableHead>
            <TableBody>
              {patients.map((patient) => (
                <TableRow
                  component={Link}
                  to={`/patient/${patient.id}`}
                  onClick={selectPatientClick}
                  key={patient.id}
                  className={styles.tableRow}
                >
                  <TableCell component="th" scope="row">
                    {patient.fName}
                  </TableCell>
                  <TableCell align="right">{patient.lName}</TableCell>
                  <TableCell align="right">{patient.dob}</TableCell>
                  <TableCell align="right">{patient.pNumber}</TableCell>
                  <TableCell align="right">{patient.email}</TableCell>
                </TableRow>
              ))}
            </TableBody>
          </Table>
        </TableContainer>
      );
    }
    import React, { useState } from "react";
    import { useParams } from "react-router-dom";
    import { formatAMPM, generateId } from "../helper";
    
    import { makeStyles, Button, TextField } from "@material-ui/core";
    import AccountBoxIcon from "@material-ui/icons/AccountBox";
    
    const useStyles = makeStyles({
      form: {
        display: "flex",
        flexDirection: "column",
      },
      textFiled: {
        width: 300,
      },
      btnsContainer: {
        width: 300,
        margin: "20px 0",
        display: "flex",
        justifyContent: "space-between",
      },
    });
    
    export default function AddNote({ addNote }) {
      const styles = useStyles();
      const { id } = useParams();
      const [note, setNote] = useState(null);
      console.log(id);
      const handleInputChange = ({ target }) => {
        setNote(target.value);
      };
    
      const handleSubmitClick = (e) => {
        e.preventDefault();
    
        const newNote = {
          userPic: <AccountBoxIcon color="primary" fontSize="large" />,
          user: "Test User",
          time: formatAMPM(new Date()),
          note: note,
          id: generateId(),
          isFinal: false,
        };
    
        if (note) {
          addNote(newNote);
        }
        setNote("");
      };
    
      const handleClearNoteClick = () => {
        setNote("");
      };
    
      return (
        <>
          <form className={styles.form} onSubmit={handleSubmitClick}>
            <TextField
              className={styles.textFiled}
              label="note"
              multiline
              variant="outlined"
              rowsMax={Infinity}
              onChange={handleInputChange}
              placeholder="add a note"
              value={note}
            />
            <div className={styles.btnsContainer}>
              <Button
                label="add note"
                variant="contained"
                color="primary"
                type="sbumit"
              >
                add note
              </Button>
              <Button
                onClick={handleClearNoteClick}
                variant="contained"
                color="secondary"
              >
                clear note
              </Button>
            </div>
          </form>
        </>
      );
    }
    import React from "react";
    import { makeStyles, Button } from "@material-ui/core";
    
    export default function Notes({ note, draftIdToDelete }) {
      const styles = useStyles();
    
      const deleteDraftClick = () => {
        draftIdToDelete(note.id);
      };
    
      return (
        <li className={styles.note}>
          <span>{note.userPic}</span>
          <div className={styles.noteDetails}>
            <span>{note.user}</span>
            <span className={styles.time}>{note.time}</span>
            <span>{note.note}</span>
          </div>
          {!note.isFinal ? (
            <Button
              size="small"
              variant="contained"
              color="secondary"
              type="delete"
              className={styles.deleteBtn}
              onClick={deleteDraftClick}
            >
              delete draft
            </Button>
          ) : null}
        </li>
      );
    }
    

    import React from "react";
    import AddNote from "./AddNote";
    import Notes from "./Notes";
    import {
      useParams,
      Link,
      Route,
      useRouteMatch,
      Switch,
    } from "react-router-dom";
    
    
    import {
      makeStyles,
      Button,
      Typography,
      Card,
      CardContent,
    } from "@material-ui/core";
    
    const useStyles = makeStyles({
      card: {
        width: "70%",
        margin: "auto",
        minHeight: 600,
        position: "relative",
      },
      edit: {
        backgroundColor: "rgb(63,81,181)",
        display: "flex",
        justifyContent: "space-between",
        padding: 16,
        color: "white",
      },
      btnsContainer: {
        margin: "20px 0",
      },
      saveBtn: {
        width: 140,
        position: "absolute",
        bottom: 10,
        right: 10,
      },
    });
    
    export default function EditPatient({
      notes,
      handleAddNote,
      deleteDraftClick,
      saveNotesClick,
      finalDraftNotes,
    }) {
      const styles = useStyles();
      const { id } = useParams();
      let match = useRouteMatch();
    
      return (
        <Card className={styles.card}>
          <CardContent>
            <div className={styles.edit}>
              <Typography variant="h5">Edit Patient</Typography>
              <Button color="white" component={Link} to="/">
                X
              </Button>
            </div>
            <div className={styles.btnsContainer}>
              <Button
                color="primary"
                component={Link}
                to={`${match.url}/details`}
              >
                Detials
              </Button>
              <Button
                color="primary"
                component={Link}
                to={`${match.url}/notes`}
              >
                Notes ({finalDraftNotes.length})
              </Button>
            </div>
            <Switch>
              <Route path={`${match.path}/notes`}>
                <div>
                  <AddNote addNote={handleAddNote} />
                  <ul>
                    {notes && notes.map((note) => (
                      <Notes
                        key={note.id}
                        note={note}
                        draftIdToDelete={deleteDraftClick}
                      />
                    ))}
                  </ul>
                </div>
              </Route>
              <Route path={`${match.path}/details`}>
                <p>{id}</p>
              </Route>
            </Switch>
          </CardContent>
          <Button
            component={Link}
            to="/"
            onClick={saveNotesClick}
            className={styles.saveBtn}
            variant="contained"
            color="primary"
          >
            save & close
          </Button>
        </Card>
      );
    }


Solution

  • You have a very complex code there but I've tried to understand your point of view...finally ohh Okey, so each patient must have hist own notes, you must first add patient id to each note object, doing this is by getting id params (you already did, and pass it down to AddNote component:

    export default function EditPatient({//...})
      //.....
    const { id } = useParams();
     //.....
    <AddNote addNote={handleAddNote} idPatient={id} />
    

    Now, move on to your AddNote component, we need to add the patient id to note object just like that:

    export default function AddNote({ addNote, idPatient }) {
    /...
    const newNote = {
              userPic: <AccountBoxIcon color="primary" fontSize="large" />,
              user: "Test User",
              time: formatAMPM(new Date()),
              note: note,
              id: generateId(),
              isFinal: false,
              idPatient: idPatient //<----add it here
            };
    

    Now, what left to do is to filter notes for each patient profile depending on the idPatient, back to EditPatient component:

    export default function EditPatient({
       //....
    const { id } = useParams();
    notes = notes.filter((note)=> note.idPatient === id)
    

    PS: you are making your code so complex and unreadable, when you are doing a good job, so my advice use state management tools like Context api or redux to make your code cleaner and easy to maintain instead of a top level useState()