Skip to content

Commit

Permalink
Merge pull request #4 from arayavalencia96/feature/MEMO-4-add-editing…
Browse files Browse the repository at this point in the history
…-function

feature/memo-4-add-editing-function
  • Loading branch information
arayavalencia96 committed Sep 7, 2023
2 parents 1b0c85a + 481651b commit 10019dd
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 93 deletions.
2 changes: 1 addition & 1 deletion src/components/Content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const Content: React.FC = () => {
<div className="mx-5 mt-5 flex min-h-[75vh] flex-col md:flex-row">
<Sidebar />
<div className="hide mr-6 mt-8 inline-block min-h-[1em] w-[1px] self-stretch bg-gray-300 opacity-100 dark:opacity-25"></div>
{selectedTopicId !== null && action !== "delete" ? (
{selectedTopicId !== null && action === "select" ? (
<CreateNote />
) : (
<NotSelectedTopic />
Expand Down
38 changes: 38 additions & 0 deletions src/components/CreateNote.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,25 @@ import { api } from "~/utils/api";
import { NoteCard } from "./NoteCard";
import { NoteEditor } from "./NoteEditor";
import { useSelectedTopic } from "~/contexts/SelectedTopicContext";
import { useState } from "react";
import { type RouterOutputs } from "~/utils/api";
type Note = RouterOutputs["note"]["getAll"][0];
import { toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";

const InitialValues: Note = {
content: '',
createdAt: new Date(),
id: '',
title: '',
topicId: '',
updatedAt: new Date(),
};

export const CreateNote: React.FC = () => {
const { data: sessionData } = useSession();
const { selectedTopic, setSelectedTopic } = useSelectedTopic();
const [selectedValues, setSelectedValues] = useState<Note>(InitialValues);

api.topic.getAll.useQuery(undefined, {
enabled: sessionData?.user !== undefined,
Expand Down Expand Up @@ -46,6 +59,16 @@ export const CreateNote: React.FC = () => {
},
});

const updateNote = api.note.update.useMutation({
onSuccess: () => {
void refetchNotes();
toast.success('Nota actualizada correctamente');
},
onError: () => {
toast.error('Error al actualizar la nota');
},
});

return (
<div className="col-span-3 w-full md:w-3/4">
<div>
Expand All @@ -54,6 +77,9 @@ export const CreateNote: React.FC = () => {
<NoteCard
note={note}
onDelete={() => void deleteNote.mutate({ id: note.id })}
onClickEdit={(note) => {
setSelectedValues(note);
}}
/>
</div>
))}
Expand All @@ -65,7 +91,19 @@ export const CreateNote: React.FC = () => {
content,
topicId: selectedTopic?.id ?? "",
});
setSelectedValues(InitialValues);
}}
onEdit={({ id, topicId, title, content }) => {
void updateNote.mutate({
id,
topicId,
title,
content,
});
setSelectedValues(InitialValues);
}}
isEdit={selectedValues.id !== '' ?? true}
values={selectedValues}
/>
</div>
);
Expand Down
12 changes: 12 additions & 0 deletions src/components/NoteCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@ type Note = RouterOutputs["note"]["getAll"][0];
export const NoteCard = ({
note,
onDelete,
onClickEdit,
}: {
note: Note;
onDelete: () => void;
onClickEdit: (note: Note) => void;
}) => {
const [isExpanded, setIsExpanded] = useState<boolean>(true);
const handleEditClick = () => {
onClickEdit(note);
};

return (
<div className="card mt-5 border border-gray-200 bg-base-100 shadow-xl">
<div className="card-body m-0 p-3">
Expand All @@ -31,6 +37,12 @@ export const NoteCard = ({
<button className="btn-warnin btn btn-xs px-5" onClick={onDelete}>
Eliminar
</button>
<button
className="btn-warnin btn btn-xs px-5"
onClick={handleEditClick}
>
Editar
</button>
</div>
</div>
</div>
Expand Down
48 changes: 39 additions & 9 deletions src/components/NoteEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,36 @@
import { useState } from "react";
import { useEffect, useState } from "react";
import CodeMirror from "@uiw/react-codemirror";
import { markdown, markdownLanguage } from "@codemirror/lang-markdown";
import { languages } from "@codemirror/language-data";
import { type RouterOutputs } from "~/utils/api";
type Note = RouterOutputs["note"]["getAll"][0];

export const NoteEditor = ({
onSave,
onEdit,
values,
isEdit,
}: {
onSave: (note: { title: string; content: string }) => void;
onEdit: (note: {
id: string;
topicId: string;
title: string;
content: string;
}) => void;
values?: Note;
isEdit?: boolean;
}) => {
const [code, setcode] = useState<string>("");
const [code, setCode] = useState<string>("");
const [title, setTitle] = useState<string>("");

useEffect(() => {
if (values) {
setCode(values?.content || "");
setTitle(values?.title || "");
}
}, [values]);

return (
<div className="card mt-5 border border-gray-200 bg-base-100 shadow-xl">
<div className="card-body">
Expand All @@ -31,24 +52,33 @@ export const NoteEditor = ({
extensions={[
markdown({ base: markdownLanguage, codeLanguages: languages }),
]}
onChange={(value) => setcode(value)}
onChange={(value) => setCode(value)}
className="border border-gray-300"
/>
</div>
<div className="card-actions justify-end">
<button
onClick={() => {
onSave({
title,
content: code,
});
setcode("");
if (!isEdit) {
onSave({
title,
content: code,
});
} else {
onEdit({
id: values?.id || "",
topicId: values?.topicId || "",
title,
content: code,
});
}
setCode("");
setTitle("");
}}
disabled={title.trim().length === 0 || code.trim().length === 0}
className="btn btn-primary"
>
Guardar
{isEdit ? "Actualizar" : "Guardar"}
</button>
</div>
</div>
Expand Down
73 changes: 62 additions & 11 deletions src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useSession } from "next-auth/react";
import { useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { api } from "~/utils/api";
import { FaPlus } from "react-icons/fa";
import { FaPlus, FaRegEdit } from "react-icons/fa";
import { useSelectedTopic } from "~/contexts/SelectedTopicContext";
import { TopicsList } from "./TopicsList";
import { toast } from "react-toastify";
Expand All @@ -10,7 +10,18 @@ import "react-toastify/dist/ReactToastify.css";
export const Sidebar: React.FC = () => {
const { data: sessionData } = useSession();
const [inputValue, setInputValue] = useState("");
const { selectedTopic, setSelectedTopic } = useSelectedTopic();
const {
selectedTopic,
setSelectedTopic,
selectedTopicId,
setAction,
action,
} = useSelectedTopic();
const isEditing = selectedTopicId !== null && action === "edit";
const selectedTopicTitle = useMemo(
() => selectedTopic?.title,
[selectedTopic]
);

const { refetch: refetchTopics } = api.topic.getAll.useQuery(undefined, {
enabled: sessionData?.user !== undefined,
Expand All @@ -22,10 +33,10 @@ export const Sidebar: React.FC = () => {
const createTopic = api.topic.create.useMutation({
onSuccess: () => {
void refetchTopics();
toast.success('Tema Creado')
toast.success("Tema Creado");
},
onError: () => {
toast.error('No se pudo crear el tema');
toast.error("No se pudo crear el tema");
},
});

Expand All @@ -34,6 +45,31 @@ export const Sidebar: React.FC = () => {
setInputValue("");
};

const updateTopic = api.topic.update.useMutation({
onSuccess: () => {
setSelectedTopic(null);
setAction("");
void refetchTopics();
toast.success("Tema Actualizado");
},
onError: () => {
toast.error("No se pudo actualizar el tema");
},
});

const handleUpdateTopic = () => {
updateTopic.mutate({ id: selectedTopicId || "", title: inputValue });
setSelectedTopic(null);
setAction("");
setInputValue("");
};

useEffect(() => {
if (isEditing) {
setInputValue(selectedTopicTitle || "");
}
}, [isEditing, selectedTopicTitle]);

return (
<div className="md:1/4 mt-10 flex flex-col-reverse justify-center px-2 md:h-[35vh] md:flex-col">
<div className="divider md:hidden"></div>
Expand All @@ -47,12 +83,21 @@ export const Sidebar: React.FC = () => {
autoFocus
className="input-borderer border-1 input input-primary input-sm w-full border-solid"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onChange={(e) => {
setInputValue(e.target.value);
}}
onKeyDown={(e) => {
if (e.key === "Enter") {
createTopic.mutate({
title: e.currentTarget.value,
});
if (isEditing) {
updateTopic.mutate({
id: selectedTopicId,
title: e.currentTarget.value,
});
} else {
createTopic.mutate({
title: e.currentTarget.value,
});
}
setInputValue("");
}
}}
Expand All @@ -61,9 +106,15 @@ export const Sidebar: React.FC = () => {
className="btn-sm"
title="Agregar"
type="button"
onClick={handleCreateTopic}
onClick={(_) => {
if (isEditing) {
handleUpdateTopic();
} else {
handleCreateTopic();
}
}}
>
<FaPlus />
{isEditing ? <FaRegEdit /> : <FaPlus />}
</button>
</div>
</div>
Expand Down
Loading

0 comments on commit 10019dd

Please sign in to comment.