diff --git a/prisma/migrations/20241029084744_/migration.sql b/prisma/migrations/20241029084744_/migration.sql new file mode 100644 index 0000000..fb66fdc --- /dev/null +++ b/prisma/migrations/20241029084744_/migration.sql @@ -0,0 +1,13 @@ +-- CreateTable +CREATE TABLE "Notes" ( + "id" TEXT NOT NULL, + "content" TEXT NOT NULL, + "userId" TEXT NOT NULL, + "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" TIMESTAMP(3) NOT NULL, + + CONSTRAINT "Notes_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "Notes" ADD CONSTRAINT "Notes_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/prisma/migrations/20241029092746_tags/migration.sql b/prisma/migrations/20241029092746_tags/migration.sql new file mode 100644 index 0000000..9184c67 --- /dev/null +++ b/prisma/migrations/20241029092746_tags/migration.sql @@ -0,0 +1,2 @@ +-- AlterTable +ALTER TABLE "Diary" ADD COLUMN "tags" TEXT[] DEFAULT ARRAY[]::TEXT[]; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index b62d214..dd6b4a1 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -37,10 +37,12 @@ model Diary { content String user User @relation(fields: [userId], references: [id]) userId String + tags String[] @default([]) // Ensure tags are stored as an array of strings createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } + model Notes { id String @id @default(uuid()) content String diff --git a/src/app/api/diary/[...id]/route.js b/src/app/api/diary/[...id]/route.js index a1f37e8..4a671bd 100644 --- a/src/app/api/diary/[...id]/route.js +++ b/src/app/api/diary/[...id]/route.js @@ -35,12 +35,13 @@ export async function PATCH(req, { params }) { } const { id } = params; const body = await req.json(); - const { title, content } = body; + const { title, content, tags } = body; // Include tags here try { const user = await prisma.user.findUnique({ where: { clerkId: userId, - }, select: { + }, + select: { id: true } }); @@ -51,7 +52,8 @@ export async function PATCH(req, { params }) { }, data: { title, - content + content, + tags: tags || [] // Update tags as well }, }); return Response.json({ message: "diary updated successfully" }); @@ -59,4 +61,4 @@ export async function PATCH(req, { params }) { console.log(err); return Response.json({ error: "Error updating diary" }); } -} \ No newline at end of file +} diff --git a/src/app/api/diary/route.js b/src/app/api/diary/route.js index b9c44bc..62969c5 100644 --- a/src/app/api/diary/route.js +++ b/src/app/api/diary/route.js @@ -8,19 +8,26 @@ export async function GET(req) { } let user = await prisma.user.findUnique({ where: { clerkId: userId }, - }) + }); let diaries = await prisma.diary.findMany({ where: { userId: user.id, }, + select: { // Optionally, select only the fields you want + id: true, + title: true, + content: true, + tags: true, // Ensure tags are selected + userId: true, + }, }); return Response.json({ diaries }); } + export async function POST(req) { const { userId } = getAuth(req); - const body = await req.json(); if (!userId) { @@ -28,28 +35,29 @@ export async function POST(req) { } try { - let clerkUser = await clerkClient.users.getUser(userId) + let clerkUser = await clerkClient.users.getUser(userId); clerkUser = { id: userId, name: clerkUser.firstName + " " + clerkUser.lastName, email: clerkUser.primaryEmailAddress.emailAddress, - } + }; let user = await prisma.user.findUnique({ where: { clerkId: clerkUser.id }, - }) + }); if (!user) { user = await prisma.user.create({ data: { clerkId: clerkUser.id, - name: clerkUser.name || '', // Use fullName if available - email: clerkUser.email || '', // Use emailAddress if available + name: clerkUser.name || '', + email: clerkUser.email || '', }, - }) + }); } const diary = await prisma.diary.create({ data: { title: body.title, content: body.content, + tags: body.tags || [], // Add this line to save tags userId: user.id, }, }); diff --git a/src/app/diary/page.jsx b/src/app/diary/page.jsx index ae97fd9..553bd99 100644 --- a/src/app/diary/page.jsx +++ b/src/app/diary/page.jsx @@ -9,7 +9,7 @@ import { useEffect, useState } from "react"; const initialFormState = { title: "", content: "", - tags: [], // Add tags to the initial state + tags: [], }; export default function Diary() { @@ -19,6 +19,8 @@ export default function Diary() { const [form, setForm] = useState(initialFormState); const [showModal, setShowModal] = useState(false); const [currentDiary, setCurrentDiary] = useState(null); + const [searchQuery, setSearchQuery] = useState(""); + const [uniqueTags, setUniqueTags] = useState([]); const handleEdit = (diary) => { setCurrentDiary(diary); @@ -37,14 +39,14 @@ export default function Diary() { body: JSON.stringify({ title: currentDiary.title, content: currentDiary.content, - tags: currentDiary.tags, // Include tags + tags: currentDiary.tags, }), }); - const data = await res.json(); + await res.json(); + fetchDiaries(); } catch (err) { - console.log("error while sending the diary details", err); + console.log("Error updating diary:", err); } finally { - setCount((prev) => !prev); setForm(initialFormState); } }; @@ -60,18 +62,15 @@ export default function Diary() { headers: { "Content-Type": "application/json", }, - body: JSON.stringify({ - title: data.title, - content: data.content, - tags: data.tags, // Include tags - }), + body: JSON.stringify(data), }); - res = await res.json(); + await res.json(); + fetchDiaries(); } catch (err) { - console.log("error while sending the diary details", err); + console.log("Error sending diary:", err); } finally { setLoading(false); - setCount((prev) => !prev); + setForm(initialFormState); } }; @@ -83,17 +82,15 @@ export default function Diary() { const handleDelete = async (id) => { try { - let res = await fetch(`/api/diary/${id}`, { + await fetch(`/api/diary/${id}`, { method: "DELETE", headers: { "Content-Type": "application/json", }, }); - res = await res.json(); + fetchDiaries(); } catch (err) { - console.log("error while sending the diary details", err); - } finally { - setCount((prev) => !prev); + console.log("Error deleting diary:", err); } }; @@ -107,14 +104,23 @@ export default function Diary() { }); res = await res.json(); setDiaries(res.diaries); + setUniqueTags([...new Set(res.diaries.flatMap((diary) => diary.tags))]); // Populate unique tags } catch (err) { - console.log("error while sending the diary details", err); + console.log("Error fetching diaries:", err); } }; + const filteredDiaries = diaries.filter( + (diary) => + diary.title.toLowerCase().includes(searchQuery.toLowerCase()) || + diary.content.toLowerCase().includes(searchQuery.toLowerCase()) || + diary.tags.some((tag) => + tag.toLowerCase().includes(searchQuery.toLowerCase()) + ) + ); + return (
- {/* Add Diary Card */} @@ -153,51 +159,68 @@ export default function Diary() { setForm({ ...form, tags: e.target.value.split(",").map((tag) => tag.trim()), }) - } // Split and trim tags + } className="bg-input text-foreground placeholder-muted-foreground border border-border rounded-md p-2 focus:ring focus:ring-primary" />
- {loading ? ( - - ) : ( - - )} + - {/* List of Diaries */} - {diaries.map((diary, index) => ( + setSearchQuery(e.target.value)} + className="mb-4 bg-input text-foreground placeholder-muted-foreground border border-border rounded-md p-2 focus:ring focus:ring-primary" + /> + +
+ {uniqueTags.map((tag) => ( + + ))} +
+ + {filteredDiaries.map((diary, index) => ( - - + {diary.title} - -

{diary.content}

-

- Tags: {diary.tags.join(", ")} -

{" "} - {/* Display tags */} +

{diary.content}

+
+ {diary.tags.map((tag, index) => ( + + {tag} + + ))} +
- -
+ diff --git a/src/components/Footer.js b/src/components/Footer.js index dc87b59..e513068 100644 --- a/src/components/Footer.js +++ b/src/components/Footer.js @@ -1,33 +1,39 @@ -'use client' -import Link from 'next/link'; -import { Github, Link as FaLink } from 'lucide-react'; +"use client"; +import Link from "next/link"; +import { Github, Link as FaLink } from "lucide-react"; const Footer = () => { return ( - -