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>
);
}
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()