Skip to content

Commit

Permalink
Add basic comments api + db + basic form pg
Browse files Browse the repository at this point in the history
  • Loading branch information
Draikth committed Jul 22, 2024
1 parent aeb02cb commit cc92929
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 3 deletions.
58 changes: 58 additions & 0 deletions app/api/comments/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { cookies } from 'next/headers';
import { NextRequest, NextResponse } from 'next/server';
import { createComment } from '../../../database/comments';
import { commentSchema } from '../../../migrations/00003-createTableComments';

export type CommentsResponseBodyPost =
| {
comment: { commentText: string };
}
| {
error: string;
};

export async function POST(
request: NextRequest,
): Promise<NextResponse<CommentsResponseBodyPost>> {
// Task: Create a note for the current logged in user

// 1. Get the note data from the request
const body = await request.json();

// 2. Validate notes data with zod
const result = commentSchema.safeParse(body);

if (!result.success) {
return NextResponse.json(
{ error: 'Request does not contain note object' },
{
status: 400,
},
);
}

// 3. Get the token from the cookie
const sessionTokenCookie = cookies().get('sessionToken');

// 4. Create the comment
const newComment =
sessionTokenCookie &&
(await createComment(sessionTokenCookie.value, result.data.commentText));

// 5. If the note creation fails, return an error
if (!newComment) {
return NextResponse.json(
{ error: 'Note not created or access denied creating note' },
{
status: 400,
},
);
}

// 6. Return the text content of the note
return NextResponse.json({
comment: {
commentText: newComment.commentText,
},
});
}
3 changes: 3 additions & 0 deletions app/comments/CommentsForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function CommentsForm() {
return <h1>User Comments</h1>;
}
24 changes: 24 additions & 0 deletions app/comments/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
import { getComments } from '../../database/comments';
import { getUser } from '../../database/users';
import CommentsForm from './CommentsForm';

export default async function CommentsPage() {
// Task: Restrict access to the notes page and only display notes belonging to the current logged in user
// 1. Check if the sessionToken cookie exists
const sessionCookie = cookies().get('sessionToken');

// 2. Query user with the sessionToken
const user = sessionCookie && (await getUser(sessionCookie.value));

// 3. If the user does not exist, redirect to the login with the returnTo query parameter
if (!user) redirect(`/login?returnTo=/${user}`);

// 4. Display the notes for the current logged in user

const comments = await getComments(sessionCookie.value);
console.log(comments);

return <CommentsForm />;
}
1 change: 1 addition & 0 deletions app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default async function RootLayout({ children }: Props) {
{user.username}
</Link>
<Link href="/post">Post Events</Link>
<Link href="/comments"> Comments </Link>
<LogoutButton />
</>
) : (
Expand Down
2 changes: 1 addition & 1 deletion app/post/PostEventForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@
// const [description, setDescription] = useState('');
// const [image, setImage] = useState('');
// const [organizerUrl, setOrganizerUrl] = useState('');
// const [ageRestriction, setAgeRestriction] = useState('');
// const [ageRestriction, setAgeRestriction] = useState(false);
// }
10 changes: 8 additions & 2 deletions app/profile/[username]/DeleteProfileForm.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
'use client';

import { useRouter } from 'next/navigation';
import React from 'react';

type DeleteProfileFormProps = {
sessionToken: string;
};

export default function DeleteProfileForm({ sessionToken }: DeleteProfileFormProps) {
export default function DeleteProfileForm({
sessionToken,
}: DeleteProfileFormProps) {
const router = useRouter();

const handleDelete = async (event: React.FormEvent) => {
event.preventDefault();

Expand All @@ -19,7 +24,8 @@ export default function DeleteProfileForm({ sessionToken }: DeleteProfileFormPro
});

if (response.ok) {
window.location.href = '/login'; // Redirect to login page after deletion
router.push('/login'); // Redirect to login page after deletion
router.refresh();
} else {
console.error('Failed to delete user');
}
Expand Down
65 changes: 65 additions & 0 deletions database/comments.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { cache } from 'react';
import { sql } from './connect';

export type Comment = {
id: number;
eventId: number;
commentText: string;
userId: number;
};

export const getComments = cache(async (sessionToken: string) => {
const comments = await sql<Comment[]>`
SELECT
comments.*
FROM
comments
INNER JOIN sessions ON (
sessions.token = ${sessionToken}
AND sessions.user_id = comments.user_id
AND expiry_timestamp > now()
)
`;
return comments;
});

export const getComment = cache(
async (sessionToken: string, commentId: number) => {
const [comment] = await sql<Comment[]>`
SELECT
comments.*
FROM
comments
INNER JOIN sessions ON (
sessions.token = ${sessionToken}
AND sessions.user_id = comments.user_id
AND expiry_timestamp > now()
)
WHERE
comments.id = ${commentId}
`;
return comment;
},
);

export const createComment = cache(
async (sessionToken: string, textContent: string) => {
const [note] = await sql<Comment[]>`
INSERT INTO
comments (user_id, comment_text) (
SELECT
user_id,
${textContent}
FROM
sessions
WHERE
token = ${sessionToken}
AND sessions.expiry_timestamp > now()
)
RETURNING
comments.*
`;

return note;
},
);
5 changes: 5 additions & 0 deletions migrations/00003-createTableComments.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { Sql } from 'postgres';
import { z } from 'zod';

export const commentSchema = z.object({
commentText: z.string().min(1),
});

export async function up(sql: Sql) {
await sql`
Expand Down

0 comments on commit cc92929

Please sign in to comment.