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: notes | category connect to backend #553

Merged
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
61 changes: 32 additions & 29 deletions src/components/Dashboard/Notetaker/Category/CategorySidebar.jsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import React, { useEffect, useState } from "react";
import { MdCreateNewFolder, MdOutlineCancel } from "react-icons/md";
import { LuFolderCog } from "react-icons/lu";
import { useDispatch, useSelector } from "react-redux";
import { toast } from "react-toastify";
import { TbEditCircle } from "react-icons/tb";
import { AiTwotoneDelete } from "react-icons/ai";
Expand All @@ -16,55 +15,49 @@ import {
import CategoryList from "./CategoryList";
import LoadingSpinner from "../../../Other/MixComponents/Spinner/LoadingSpinner";
import ModifyCategory from "./ModifyCategory";
import { createCategory, editCategory, removeCategory } from "../../../../features/notes/category/categorySlice";
import { updateCategory, deleteCategory, createCategory } from "../../../../features/notes/category/categorySlice";
import { useDispatch } from "react-redux";

const CategorySidebar = ({ pickedCategory, onPick, onUnpickNote, pickedNote }) => {
const CategorySidebar = ({
pickedCategory,
onPick,
onUnpickNote,
requiredCategories,
setCopyCategoryOptionMode,
categories,
isCategoryLoading,
setPickedCategory,
}) => {
const dispatch = useDispatch();
const { categories } = useSelector((state) => state.categories);
const [nonRequiredCategories, setNonRequiredCategories] = useState([]);
const [requiredCategories, setRequiredCategories] = useState([]);
const [modalOpenMode, setModalOpenMode] = useState("");
const [categoryOptionMode, setCategoryOptionMode] = useState(false);
const isCategoryLoading = false;

useEffect(() => {
const findNonRequiredCategories = categories.filter((item) => !item.required);
if (!findNonRequiredCategories.length && categoryOptionMode) handleCloseOptionsMode();
setNonRequiredCategories(() => {
return findNonRequiredCategories;
});
setRequiredCategories(categories.filter((item) => item.required));
if (!categories.length && categoryOptionMode) handleCloseOptionsMode();
}, [categories]);

useEffect(() => {
if (Object.keys(pickedNote).length !== 0) setCategoryOptionMode(false);
}, [pickedNote]);

setCopyCategoryOptionMode(categoryOptionMode);
}, [categoryOptionMode]);
const handleCreateCategory = () => {
setModalOpenMode("Create");
onUnpickNote();
};
const handleEditCategory = () => {
if (Object.keys(pickedCategory).length === 0) {
toast.error("Need to pick a category to edit it");
return;
}
setModalOpenMode("Edit");
};

const handleCloseModal = () => {
setModalOpenMode("");
};
const handleSave = (categoryName) => {
if (modalOpenMode === "Create") {
dispatch(createCategory(categoryName));
dispatch(createCategory({ name: categoryName }));
} else {
dispatch(editCategory({ ...pickedCategory, name: categoryName }));
dispatch(updateCategory({ id: pickedCategory._id, categoryData: { name: categoryName } }));
onPick({});
}
handleCloseModal();
};
const handleOpenOptionsMode = () => {
if (nonRequiredCategories.length === 0) {
if (categories.length === 0) {
toast.error(
`Options Mode Is Only For Unique Categories Modification.
First Add At Least One Unique Category And Click Again`,
Expand All @@ -73,19 +66,29 @@ const CategorySidebar = ({ pickedCategory, onPick, onUnpickNote, pickedNote }) =
}
setCategoryOptionMode(true);
onUnpickNote();
onPick(nonRequiredCategories[0]);
onPick(categories[0]);
};
const handleCloseOptionsMode = () => {
setCategoryOptionMode(false);
handleCloseModal();
onPick(requiredCategories[0]);
};
const handleEditCategory = () => {
if (Object.keys(pickedCategory).length === 0) {
toast.error("Need to pick a category to edit it");
return;
}
setModalOpenMode("Edit");
};

const handleDeleteCategory = () => {
if (Object.keys(pickedCategory).length === 0) {
toast.error("Need to pick a category to delete it");
return;
}
dispatch(removeCategory(pickedCategory._id));
dispatch(deleteCategory(pickedCategory._id)).then(() => {
setPickedCategory({});
});
};
return (
<CategoriesSidebarContainer>
Expand Down Expand Up @@ -143,7 +146,7 @@ const CategorySidebar = ({ pickedCategory, onPick, onUnpickNote, pickedNote }) =
</CategoryList>
)}
<CategoryList onPick={onPick} pickedCategory={pickedCategory}>
{nonRequiredCategories}
{categories}
</CategoryList>
</>
)}
Expand Down
10 changes: 10 additions & 0 deletions src/components/Dashboard/Notetaker/NoteApp.css
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,13 @@
opacity: 0.7;
cursor: pointer;
}
.slide-in {
transform: translateX(0);
transition: 0.5s;
z-index: 0;
}
.slide-out {
transform: translateX(-100vw);
transition: 2s;
z-index: -100;
}
139 changes: 52 additions & 87 deletions src/components/Dashboard/Notetaker/NoteApp.jsx
Original file line number Diff line number Diff line change
@@ -1,97 +1,78 @@
import React, { useEffect, useState } from "react";
import { MdNoteAdd } from "react-icons/md";
import { useDispatch, useSelector } from "react-redux";

import {
NotesContainer,
NotesSidebarContainer,
NotesSidebarHeader,
NotesSidebarHeaderTitle,
SearchContainer,
} from "./NoteElements";
import SearchInputBox from "../../Common/SearchInputBox";
import { NotesContainer } from "./NoteElements";
import "./NoteApp.css";
import NoteList from "./NoteList";
import NoteDescription from "./NoteDescription";
import { getNotes, noteReset, pinNote } from "../../../features/notes/notesSlice";
import LoadingSpinner from "../../Other/MixComponents/Spinner/LoadingSpinner";
import { CategorySidebar } from "./Category";
import NoteSidebar from "./NoteSidebar";
import { toast } from "react-toastify";
import { categoryReset, getCategories } from "../../../features/notes/category/categorySlice";

const requiredCategories = [
{
name: "Pinned Notes",
type: "pinned",
},
{
name: "Other Notes",
type: "other",
},
];

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

useEffect(() => {
if (isCategoryError) {
toast.error(categoryMessage);
console.log(categoryMessage);
}
dispatch(getCategories());
return () => dispatch(categoryReset());
}, [dispatch, isCategoryError, categoryMessage]);

useEffect(() => {
if (categoryOptionMode || isCategoryLoading) return;
if (isNoteError) {
console.log(noteMessage);
}
dispatch(getNotes()).then(({ payload }) => {
if (payload.length > 0) {
let pickedNote = payload.find((note) => note.pinned);
if (pickedNote) {
setPickedCategory(() => {
return categories.find((category) => category.name === "Pinned Notes");
});
setPickedCategory(requiredCategories[0]);
setPickedNote(
pickedNote.title.includes("UntitledNote") ? { ...pickedNote, title: "" } : pickedNote,
);
} else {
pickedNote = payload.find((note) => !note.pinned);
setPickedCategory(() => {
return categories.find((category) => category.name === "Other Notes");
});
setPickedCategory(requiredCategories[1]);
setPickedNote(
pickedNote.title.includes("UntitledNote") ? { ...pickedNote, title: "" } : pickedNote,
);
}
} else {
setPickedCategory(() => {
return categories.find((category) => category.name === "Pinned Notes");
});
setPickedCategory(requiredCategories[0]);
}
});
return () => dispatch(noteReset());
}, [dispatch, isNoteError, noteMessage]);

useEffect(() => {
const newFilteredNotes = notes?.filter((note) => {
const searchedNote =
note?.title?.toLowerCase().includes(searchTerm?.toLowerCase()) ||
note?.content?.toLowerCase().includes(searchTerm?.toLowerCase());
if (!searchedNote) return false;
if (Object.keys(pickedCategory).length === 0) return false;
if (pickedCategory.name === "Other Notes") {
return !note.pinned;
}
if (pickedCategory.name === "Pinned Notes") {
return note.pinned;
}
return note.category.toLowerCase() === pickedCategory.name.toLowerCase();
});
setFilteredNotes(newFilteredNotes);
setPickedNote({});
}, [searchTerm, notes, pickedCategory]);
}, [dispatch, isNoteError, noteMessage, categoryOptionMode, isCategoryLoading]);

const handleSearchTermChange = (e) => {
setSearchTerm(e.target.value);
};
const handlePickNote = (noteId) => {
const pickedNote = notes.find((note) => note._id === noteId);
const handleCloseMDEditorMode = () => {
setNeedToAdd(false);
setPickedNote(
pickedNote === -1
? {}
: pickedNote.title.includes("UntitledNote")
? { ...pickedNote, title: "" }
: pickedNote,
);
setPickedNote({});
};

const handlePinNote = (noteId) => {
const pinnedNote = notes.find((note) => note._id === noteId);
const noteData = {
Expand All @@ -100,54 +81,38 @@ const NoteApp = () => {
};
dispatch(pinNote({ id: noteId, noteData }));
};
const handleOpenAddNewNoteMode = () => {
setNeedToAdd(true);
setPickedNote({});
};
const handleCloseMDEditorMode = () => {
setNeedToAdd(false);
setPickedNote({});
};

return (
<NotesContainer>
<CategorySidebar
pickedCategory={pickedCategory}
onPick={setPickedCategory}
onUnpickNote={handleCloseMDEditorMode}
requiredCategories={requiredCategories}
setCopyCategoryOptionMode={setCategoryOptionMode}
categories={categories}
isCategoryLoading={isCategoryLoading}
setPickedCategory={setPickedCategory}
/>
<NoteSidebar
categoryOptionMode={categoryOptionMode}
pickedCategory={pickedCategory}
pickedNote={pickedNote}
onPickNote={setPickedNote}
onNeedToAddNote={setNeedToAdd}
onPinNote={handlePinNote}
notes={notes}
isNoteLoading={isNoteLoading}
isCategoryLoading={isCategoryLoading}
/>
<NotesSidebarContainer>
<NotesSidebarHeader>
<NotesSidebarHeaderTitle>
{(pickedCategory && pickedCategory.name) || "Please, Pick Category"}
</NotesSidebarHeaderTitle>
</NotesSidebarHeader>
<SearchContainer>
<SearchInputBox placeholder="Search Note" value={searchTerm} onChange={handleSearchTermChange} />
<MdNoteAdd
className="icon icon-add"
style={{ marginLeft: "5px", marginRight: "5px" }}
size="20px"
title="New Note"
onClick={handleOpenAddNewNoteMode}
/>
</SearchContainer>

{isNoteLoading ? (
<LoadingSpinner />
) : (
<NoteList onPin={handlePinNote} onPick={handlePickNote} pickedNoteId={pickedNote._id}>
{filteredNotes}
</NoteList>
)}
</NotesSidebarContainer>
<NoteDescription
onPin={handlePinNote}
needToAdd={needToAdd}
onCloseAddMode={handleCloseMDEditorMode}
onChangePickedNote={setPickedNote}
pickedCategory={pickedCategory}
requiredCategories={requiredCategories}
>
{pickedNote}
</NoteDescription>
Expand Down
Loading