feat: room photo gallery, featured photo, and comments moderation
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
import { requireRole } from '@/lib/auth';
|
||||
|
||||
export async function DELETE(request: NextRequest, { params }: { params: { id: string } }) {
|
||||
try {
|
||||
await requireRole('admin');
|
||||
const commentId = parseInt(params.id, 10);
|
||||
await db.query('UPDATE room_comments SET deleted_by_admin = TRUE WHERE id = $1', [commentId]);
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (err: any) {
|
||||
return NextResponse.json(
|
||||
{ error: err.message || 'Failed to delete comment' },
|
||||
{ status: err.message === 'Unauthorized' ? 401 : 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { db } from '@/lib/db';
|
||||
export async function GET() {
|
||||
try {
|
||||
await requireRole('admin');
|
||||
const { rows } = await db.query('SELECT id, username, role, created_at FROM users ORDER BY created_at DESC');
|
||||
const { rows } = await db.query('SELECT id, username, role, comments_disabled, first_name, last_name, created_at FROM users ORDER BY created_at DESC');
|
||||
return NextResponse.json({ data: rows });
|
||||
} catch (err: any) {
|
||||
return NextResponse.json({ error: err.message || 'Failed to fetch users' }, { status: err.message === 'Unauthorized' ? 401 : 500 });
|
||||
@@ -32,3 +32,39 @@ export async function POST(request: NextRequest) {
|
||||
return NextResponse.json({ error: err.message || 'Failed to create user' }, { status: err.message === 'Unauthorized' ? 401 : 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(request: NextRequest) {
|
||||
try {
|
||||
await requireRole('admin');
|
||||
const body = await request.json();
|
||||
const { id, first_name, last_name, comments_disabled } = body;
|
||||
|
||||
const { rows } = await db.query(
|
||||
'UPDATE users SET first_name = $1, last_name = $2, comments_disabled = $3 WHERE id = $4 RETURNING id, username, role, first_name, last_name, comments_disabled, created_at',
|
||||
[first_name || null, last_name || null, comments_disabled === true, id]
|
||||
);
|
||||
|
||||
if (rows.length === 0) {
|
||||
return NextResponse.json({ error: 'User not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ data: rows[0] });
|
||||
} catch (err: any) {
|
||||
return NextResponse.json({ error: err.message || 'Failed to update user' }, { status: err.message === 'Unauthorized' ? 401 : 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(request: NextRequest) {
|
||||
try {
|
||||
await requireRole('admin');
|
||||
const { searchParams } = new URL(request.url);
|
||||
const id = searchParams.get('id');
|
||||
if (!id) {
|
||||
return NextResponse.json({ error: 'User ID required' }, { status: 400 });
|
||||
}
|
||||
await db.query('DELETE FROM users WHERE id = $1', [id]);
|
||||
return NextResponse.json({ ok: true });
|
||||
} catch (err: any) {
|
||||
return NextResponse.json({ error: err.message || 'Failed to delete user' }, { status: err.message === 'Unauthorized' ? 401 : 500 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
import { getSession } from '@/lib/auth';
|
||||
|
||||
export async function GET() {
|
||||
@@ -6,5 +7,18 @@ export async function GET() {
|
||||
if (!session) {
|
||||
return NextResponse.json({ authenticated: false }, { status: 401 });
|
||||
}
|
||||
return NextResponse.json({ authenticated: true, role: session.role, username: session.username });
|
||||
const { rows } = await db.query(
|
||||
'SELECT id, username, role, first_name, last_name, comments_disabled FROM users WHERE id = $1',
|
||||
[session.id]
|
||||
);
|
||||
const user = rows[0] || {};
|
||||
return NextResponse.json({
|
||||
authenticated: true,
|
||||
role: session.role,
|
||||
username: session.username,
|
||||
id: session.id,
|
||||
first_name: user.first_name || null,
|
||||
last_name: user.last_name || null,
|
||||
comments_disabled: user.comments_disabled === true,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
import { requireAuth, canComment } from '@/lib/auth';
|
||||
|
||||
export async function GET(request: NextRequest, { params }: { params: { id: string } }) {
|
||||
try {
|
||||
const roomId = parseInt(params.id, 10);
|
||||
const { searchParams } = new URL(request.url);
|
||||
const photoUrl = searchParams.get('photo_url') || null;
|
||||
|
||||
const { rows } = await db.query(
|
||||
`SELECT id, room_id, photo_url, user_id, first_name, last_initial, text, created_at, deleted_by_admin
|
||||
FROM room_comments
|
||||
WHERE room_id = $1 AND ($2::varchar IS NULL OR photo_url = $2) AND deleted_by_admin = FALSE
|
||||
ORDER BY created_at DESC`,
|
||||
[roomId, photoUrl]
|
||||
);
|
||||
|
||||
return NextResponse.json({ data: rows });
|
||||
} catch (err: any) {
|
||||
return NextResponse.json({ error: err.message || 'Failed to fetch comments' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest, { params }: { params: { id: string } }) {
|
||||
try {
|
||||
const session = await requireAuth();
|
||||
const allowed = await canComment(session.id);
|
||||
if (!allowed) {
|
||||
return NextResponse.json({ error: 'Comments are disabled for your account' }, { status: 403 });
|
||||
}
|
||||
|
||||
const roomId = parseInt(params.id, 10);
|
||||
const body = await request.json();
|
||||
const { photo_url, text } = body;
|
||||
|
||||
if (!text || !text.trim()) {
|
||||
return NextResponse.json({ error: 'Comment text is required' }, { status: 400 });
|
||||
}
|
||||
|
||||
const { rows } = await db.query(
|
||||
`SELECT first_name, last_name FROM users WHERE id = $1`,
|
||||
[session.id]
|
||||
);
|
||||
const user = rows[0] || {};
|
||||
const firstName = user.first_name || session.username || 'Guest';
|
||||
const lastInitial = user.last_name ? user.last_name.charAt(0).toUpperCase() : null;
|
||||
|
||||
const { rows: inserted } = await db.query(
|
||||
`INSERT INTO room_comments (room_id, photo_url, user_id, first_name, last_initial, text)
|
||||
VALUES ($1, $2, $3, $4, $5, $6) RETURNING *`,
|
||||
[roomId, photo_url || null, session.id, firstName, lastInitial, text.trim()]
|
||||
);
|
||||
|
||||
return NextResponse.json({ data: inserted[0] });
|
||||
} catch (err: any) {
|
||||
return NextResponse.json(
|
||||
{ error: err.message || 'Failed to post comment' },
|
||||
{ status: err.message === 'Unauthorized' ? 401 : 500 }
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,12 @@ export async function PUT(request: NextRequest, { params }: { params: { id: stri
|
||||
await requireRole('admin');
|
||||
const id = parseInt(params.id, 10);
|
||||
const body = await request.json();
|
||||
const { name, description, price, photos, active, sort_order } = body;
|
||||
const { name, description, price, photos, active, sort_order, featured_photo } = body;
|
||||
|
||||
const { rows } = await db.query(
|
||||
`UPDATE rooms SET name = $1, description = $2, price = $3, photos = $4, active = $5, sort_order = $6, updated_at = NOW()
|
||||
WHERE id = $7 RETURNING *`,
|
||||
[name, description, price, photos || [], active, sort_order || 0, id]
|
||||
`UPDATE rooms SET name = $1, description = $2, price = $3, photos = $4, active = $5, sort_order = $6, featured_photo = $7, updated_at = NOW()
|
||||
WHERE id = $8 RETURNING *`,
|
||||
[name, description, price, photos || [], active, sort_order || 0, featured_photo || null, id]
|
||||
);
|
||||
|
||||
if (rows.length === 0) {
|
||||
|
||||
@@ -16,17 +16,17 @@ export async function POST(request: NextRequest) {
|
||||
try {
|
||||
await requireRole('admin');
|
||||
const body = await request.json();
|
||||
const { name, description, price, photos, sort_order } = body;
|
||||
const { name, description, price, photos, sort_order, featured_photo } = body;
|
||||
|
||||
if (!name || !description || price === undefined) {
|
||||
return NextResponse.json({ error: 'Missing required fields' }, { status: 400 });
|
||||
}
|
||||
|
||||
const { rows } = await db.query(
|
||||
`INSERT INTO rooms (name, description, price, photos, sort_order)
|
||||
VALUES ($1, $2, $3, $4, $5)
|
||||
`INSERT INTO rooms (name, description, price, photos, sort_order, featured_photo)
|
||||
VALUES ($1, $2, $3, $4, $5, $6)
|
||||
RETURNING *`,
|
||||
[name, description, price, photos || [], sort_order || 0]
|
||||
[name, description, price, photos || [], sort_order || 0, featured_photo || null]
|
||||
);
|
||||
|
||||
return NextResponse.json({ data: rows[0] });
|
||||
|
||||
Reference in New Issue
Block a user