Skip to content

Commit

Permalink
feat: notes | Connect Notes to Backend (#534)
Browse files Browse the repository at this point in the history
* [Feat] Connect Notes To Backend

why: so the notes will be stored in db
how: change the redux slice file, add fetching data with axios

* [Feat] Connect Notes To Backend

why: so the notes will be stored in db
how: change the redux slice file, add fetching data with axios
  • Loading branch information
ArkadiK94 authored Dec 9, 2023
1 parent ee79fdc commit 6142d7f
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 61 deletions.
31 changes: 23 additions & 8 deletions src/components/Dashboard/Notetaker/NoteApp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,27 @@ import "./NoteApp.css";
import NoteList from "./NoteList";
import NoteDescription from "./NoteDescription";
import { useDispatch, useSelector } from "react-redux";
import { notePin } from "../../../features/notes/notesSlice";
import { getNotes, noteReset, pinNote } from "../../../features/notes/notesSlice";
import LoadingSpinner from "../../Other/MixComponents/Spinner/LoadingSpinner";

const NoteApp = () => {
const dispatch = useDispatch();
const { notes } = useSelector(({ notes }) => notes);
const { notes, isNoteLoading, isNoteError, noteMessage } = useSelector((state) => state.notes);
const [searchTerm, setSearchTerm] = useState("");
const [filteredNotes, setFilteredNotes] = useState([]);
const [pickedNote, setPickedNote] = useState({});
const [needToAdd, setNeedToAdd] = useState(false);

useEffect(() => {
const newFilteredNotes = notes.filter((note) => {
if (isNoteError) {
console.log(noteMessage);
}
dispatch(getNotes());
return () => dispatch(noteReset());
}, [dispatch, isNoteError, noteMessage]);

useEffect(() => {
const newFilteredNotes = notes?.filter((note) => {
return (
note?.title?.toLowerCase().includes(searchTerm?.toLowerCase()) ||
note?.description?.toLowerCase().includes(searchTerm?.toLowerCase())
Expand All @@ -37,11 +46,13 @@ const NoteApp = () => {
setSearchTerm(e.target.value);
};
const handlePickNote = (noteId) => {
const pickedNote = notes.find((note) => note.id === noteId);
const pickedNote = notes.find((note) => note._id === noteId);
setPickedNote(pickedNote !== -1 ? pickedNote : {});
};
const handlePinNote = (noteId) => {
dispatch(notePin(noteId));
const pinnedNote = notes.find((note) => note._id === noteId);
const noteData = { ...pinnedNote, pinned: !pinnedNote.pinned };
dispatch(pinNote({ id: noteId, noteData }));
};
const handleOpenAddNewNoteMode = () => {
setNeedToAdd(true);
Expand All @@ -66,9 +77,13 @@ const NoteApp = () => {
onChange={handleSearchTermChange}
/>
</SearchContainer>
<NoteList onPin={handlePinNote} onPick={handlePickNote}>
{filteredNotes}
</NoteList>
{isNoteLoading ? (
<LoadingSpinner />
) : (
<NoteList onPin={handlePinNote} onPick={handlePickNote}>
{filteredNotes}
</NoteList>
)}
</NotesSidebarContainer>
<NoteDescription
onPin={handlePinNote}
Expand Down
23 changes: 12 additions & 11 deletions src/components/Dashboard/Notetaker/NoteDescription.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { RiMore2Fill } from "react-icons/ri";
import MarkdownEditor from "../../Common/MarkdownEditor";
import InputEditor from "../../Common/InputEditor";
import { useDispatch } from "react-redux";
import { noteAdd, noteEdit, noteRemove } from "../../../features/notes/notesSlice";
import { createNote, updateNote, deleteNote } from "../../../features/notes/notesSlice";

const NoteDescription = ({ children, onPin, needToAdd, onCloseAddMode, onChangePickedNote }) => {
const dispatch = useDispatch();
Expand All @@ -26,7 +26,7 @@ const NoteDescription = ({ children, onPin, needToAdd, onCloseAddMode, onChangeP
}, [children]);

const handleDeleteNote = () => {
dispatch(noteRemove(children.id));
dispatch(deleteNote(children._id));
setShowNote({});
};
const handleClose = () => {
Expand All @@ -36,34 +36,35 @@ const NoteDescription = ({ children, onPin, needToAdd, onCloseAddMode, onChangeP
};
const handleCopyNoteData = (label, content) => {
setShowNote((prevCopyNote) => {
if (label === "description") label = "content";
return {
...prevCopyNote,
[label]: content,
};
});
};
const handleSaveNote = (newNote) => {
if (!newNote.title && !newNote.description) {
dispatch(noteRemove(newNote.id));
if (!newNote.title && !newNote.content) {
dispatch(deleteNote(newNote._id));
onChangePickedNote({});
handleClose();
return;
}
if (needToEdit) {
dispatch(noteEdit({ ...newNote, id: children.id }));
dispatch(updateNote({ id: children._id, noteData: newNote }));
} else if (needToAdd) {
dispatch(noteAdd(newNote));
dispatch(createNote(newNote));
}
onChangePickedNote(newNote);
handleClose();
};
return (
<NotesDescriptionContainer>
<NotesDescriptionHeader>
{!needToAdd && !needToEdit && (showNote.title || showNote.description) && (
{!needToAdd && !needToEdit && (showNote.title || showNote.content) && (
<NotesDescriptionIconsContainer icons={3}>
<BiSolidEdit className="icon" size="24px" title="Edit" onClick={setNeedToEdit} />
<NotePinning isPinned={showNote.pinned} onPin={onPin} noteId={showNote.id} />
<NotePinning isPinned={showNote.pinned} onPin={onPin} noteId={showNote._id} />
<MdDeleteForever
className="icon icon-delete"
size="24px"
Expand Down Expand Up @@ -96,20 +97,20 @@ const NoteDescription = ({ children, onPin, needToAdd, onCloseAddMode, onChangeP
/>
) : (
<DescriptionDisplayTitle>
{showNote.title || (showNote.id ? `UntitledNote #${showNote.id.substr(0, 5)}` : "")}
{showNote.title || (showNote._id ? `UntitledNote #${showNote._id.substr(0, 5)}` : "")}
</DescriptionDisplayTitle>
)}
</DescriptionTitle>
<DescriptionContent>
{needToAdd || needToEdit ? (
<MarkdownEditor
content={needToEdit && showNote.description ? showNote.description : ""}
content={needToEdit && showNote.content ? showNote.content : ""}
label="description"
onCopyChanges={handleCopyNoteData}
/>
) : (
<MarkdownEditor
content={showNote.description || (showNote.id ? `undescribedNote` : "")}
content={showNote.content || (showNote._id ? `undescribedNote` : "")}
previewModeOnly
/>
)}
Expand Down
12 changes: 6 additions & 6 deletions src/components/Dashboard/Notetaker/NoteItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,23 @@ const shortText = (text, letters) => {
return textCleanFromTags?.length > letters ? `${textCleanFromTags.slice(0, letters)}...` : textCleanFromTags;
};

const NoteItem = ({ id, title, description, pinned, onPick, onPin }) => {
const NoteItem = ({ _id, title, content, pinned, onPick, onPin }) => {
const [shortTitle, setShortTitle] = useState("");
const [shortDescr, setShortDescr] = useState("");

useEffect(() => {
setShortTitle(() => (title ? shortText(title, 30) : `UntitledNote #${id.substr(0, 5)}`));
setShortDescr(() => (description ? shortText(description, 60) : "undescribedNote"));
}, [title, description]);
setShortTitle(() => (title ? shortText(title, 30) : `UntitledNote #${_id.substr(0, 5)}`));
setShortDescr(() => (content ? shortText(content, 60) : "undescribedNote"));
}, [title, content]);

return (
<NoteItemElementContainer>
<NoteItemElement isPinned={pinned} onClick={() => onPick(id)}>
<NoteItemElement isPinned={pinned} onClick={() => onPick(_id)}>
<NoteItemShortTitle>{shortTitle}</NoteItemShortTitle>
<NoteItemShortDescription>{shortDescr}</NoteItemShortDescription>
</NoteItemElement>
<NoteItemPinningContainer isPinned={pinned}>
<NotePinning isPinned={pinned} onPin={onPin} noteId={id} />
<NotePinning isPinned={pinned} onPin={onPin} noteId={_id} />
</NoteItemPinningContainer>
</NoteItemElementContainer>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dashboard/Notetaker/NoteList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ const NoteList = ({ children, onPick, onPin }) => {
<NotesListContainer>
{!children.length && <NotesListNoFound>There Are No Notes</NotesListNoFound>}
{children.map((note) => (
<NoteItem key={note.id} {...note} onPick={onPick} onPin={onPin} />
<NoteItem key={note._id} {...note} onPick={onPick} onPin={onPin} />
))}
</NotesListContainer>
);
Expand Down
66 changes: 65 additions & 1 deletion src/features/notes/notesService.js
Original file line number Diff line number Diff line change
@@ -1 +1,65 @@
// we will add here the services after finising with the back-end
import axios from "axios";
import { getApiUrl } from "../apiUrl";

const API_URL = getApiUrl("api/notes/");

// Create new note
const createNote = async (noteData, token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
};

const response = await axios.post(API_URL, noteData, config);

return response.data;
};

// Update note
const updateNote = async (id, noteData, token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
};

const response = await axios.put(API_URL + id, noteData, config);

return response.data;
};

// Get user notes
const getNotes = async (token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
};

const response = await axios.get(API_URL, config);

return response.data;
};

// Delete user note
const deleteNote = async (noteId, token) => {
const config = {
headers: {
Authorization: `Bearer ${token}`,
},
};

const response = await axios.delete(API_URL + noteId, config);

return response.data;
};

const notesService = {
createNote,
updateNote,
getNotes,
deleteNote,
};

export default notesService;
Loading

0 comments on commit 6142d7f

Please sign in to comment.