Skip to content
Open
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
12 changes: 12 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions server/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

141 changes: 129 additions & 12 deletions src/components/CreateNoteForm.jsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,143 @@
// TODO: Import useForm, zodResolver, axios, useNavigate, useState, and noteSchema


import { useState } from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import { noteSchema } from "../schema/notes";
import { Save } from "lucide-react";

const CreateNoteForm = () => {
// TODO: Setup isSubmitting state with useState
// TODO: create navigate variable and set to useNavigate()

const [isSubmitting, setIsSubmitting] = useState(false);
const navigate = useNavigate();

// TODO: Set up the form with useForm from react-hook-form and zodResolver from @hookform/resolvers/zod
const {
register,
handleSubmit,
formState: { errors },
reset,
} = useForm({
resolver: zodResolver(noteSchema),
});

const sendToTheServer = async (data) => {
// TODO: Send the data to the server
// TODO: Use axios to create a new note in the server using the endpoint http://localhost:3001/api/notes
setIsSubmitting(true);
try {
await axios.post("http://localhost:3001/api/notes", data);
reset();
navigate("/notes");
} catch (error) {
console.error("Error creating note:", error);
alert("Failed to create note. Please try again.");
} finally {
setIsSubmitting(false);
}
};

return (
<>
<h1>Create Note</h1>
{/* TODO: Setup the form with TailwindCSS, create a form with the following fields: title, content, and submit button */}
</>

<div className="max-w-xl mx-auto bg-white p-6 rounded-lg shadow">

<h1 className="text-2xl font-bold mb-6 text-gray-800">Create Note</h1>

<form onSubmit={handleSubmit(sendToTheServer)} className="space-y-6">

<div>

<label className="block text-sm font-medium text-gray-700 mb-1">

Title

</label>

<input

type="text"

placeholder="Note Title"

{...register("title")}

className="w-full border rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-yellow-400"
/>
{errors.title && (

<p className="text-red-500 text-sm mt-1">

{errors.title.message}

</p>

)}

</div>


<div>

<label className="block text-sm font-medium text-gray-700 mb-1">

Content

</label>

<textarea

rows={6}

placeholder="Write your note here..."

{...register("content")}

className="w-full border rounded-md px-3 py-2 focus:outline-none focus:ring-2 focus:ring-yellow-400"
/>
{errors.content && (

<p className="text-red-500 text-sm mt-1">

{errors.content.message}

</p>
)}

</div>


<button

type="submit"

disabled={isSubmitting}

className="w-full inline-flex justify-center items-center gap-2 px-4 py-3 bg-yellow-500 text-white rounded-md hover:bg-yellow-600 transition disabled:opacity-50"
>
<Save size={18} />

{isSubmitting ? "Saving..." : "Save Note"}

</button>

</form>

</div>

);
};

export default CreateNoteForm;


// TODO: Setup isSubmitting state with useState
// TODO: create navigate variable and set to useNavigate()


// TODO: Set up the form with useForm from react-hook-form and zodResolver from @hookform/resolvers/zod


// TODO: Send the data to the server
// TODO: Use axios to create a new note in the server using the endpoint http://localhost:3001/api/notes





2 changes: 1 addition & 1 deletion src/components/NoteCard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const NoteCard = ({ note, onDelete }) => {
{title}
</h3>
<button
onClick={() => onDelete(id)}
onClick={() => onDelete(note._id)}
aria-label="Delete note"
className="text-gray-500 hover:text-red-500 p-1 rounded-full hover:bg-red-50 transition-colors"
>
Expand Down
16 changes: 15 additions & 1 deletion src/schema/notes.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,22 @@
import { z } from "zod";

export const noteSchema = z.object({


title: z
.string()
.min(1, "title is required")
.max(50, "title must be at most 50 characters"),

content: z
.string()
.min(1, "Content is required")
.max(500, "title must be at most 500 characters"),

});


//TODO: create the title and content schema,
// Make sure the title is required and the content is required
// Make sure the title is max 50 characters and the content is max 500 characters

});