Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat] Connect Notes to Backend #534

Merged
merged 5 commits into from
Dec 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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