feat: room amenities with editable SVG icons
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
export async function GET() {
|
||||
try {
|
||||
const { rows } = await db.query(
|
||||
'SELECT id, name, icon_svg, sort_order FROM room_amenities ORDER BY sort_order, name'
|
||||
);
|
||||
return NextResponse.json({ data: rows });
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch amenities:', error);
|
||||
return NextResponse.json({ error: 'Failed to fetch amenities' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const { name, icon_svg, sort_order } = await request.json();
|
||||
|
||||
if (!name || !icon_svg) {
|
||||
return NextResponse.json({ error: 'Name and icon_svg are required' }, { status: 400 });
|
||||
}
|
||||
|
||||
const { rows } = await db.query(
|
||||
'INSERT INTO room_amenities (name, icon_svg, sort_order) VALUES ($1, $2, $3) RETURNING id, name, icon_svg, sort_order',
|
||||
[name, icon_svg, sort_order || 0]
|
||||
);
|
||||
|
||||
return NextResponse.json({ data: rows[0] });
|
||||
} catch (error: any) {
|
||||
console.error('Failed to create amenity:', error);
|
||||
if (error.code === '23505') {
|
||||
return NextResponse.json({ error: 'Amenity with this name already exists' }, { status: 409 });
|
||||
}
|
||||
return NextResponse.json({ error: 'Failed to create amenity' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function PUT(request: NextRequest) {
|
||||
try {
|
||||
const { id, name, icon_svg, sort_order } = await request.json();
|
||||
|
||||
if (!id) {
|
||||
return NextResponse.json({ error: 'ID is required' }, { status: 400 });
|
||||
}
|
||||
|
||||
const { rows } = await db.query(
|
||||
'UPDATE room_amenities SET name = $1, icon_svg = $2, sort_order = $3 WHERE id = $4 RETURNING id, name, icon_svg, sort_order',
|
||||
[name, icon_svg, sort_order || 0, id]
|
||||
);
|
||||
|
||||
if (rows.length === 0) {
|
||||
return NextResponse.json({ error: 'Amenity not found' }, { status: 404 });
|
||||
}
|
||||
|
||||
return NextResponse.json({ data: rows[0] });
|
||||
} catch (error: any) {
|
||||
console.error('Failed to update amenity:', error);
|
||||
if (error.code === '23505') {
|
||||
return NextResponse.json({ error: 'Amenity with this name already exists' }, { status: 409 });
|
||||
}
|
||||
return NextResponse.json({ error: 'Failed to update amenity' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
export async function DELETE(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const id = searchParams.get('id');
|
||||
|
||||
if (!id) {
|
||||
return NextResponse.json({ error: 'ID is required' }, { status: 400 });
|
||||
}
|
||||
|
||||
await db.query('DELETE FROM room_amenities WHERE id = $1', [id]);
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Failed to delete amenity:', error);
|
||||
return NextResponse.json({ error: 'Failed to delete amenity' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import { db } from '@/lib/db';
|
||||
|
||||
export const dynamic = 'force-dynamic';
|
||||
|
||||
// GET room's amenities
|
||||
export async function GET(request: NextRequest) {
|
||||
const { searchParams } = new URL(request.url);
|
||||
const roomId = searchParams.get('room_id');
|
||||
|
||||
try {
|
||||
if (roomId) {
|
||||
const { rows } = await db.query(
|
||||
`SELECT a.id, a.name, a.icon_svg, a.sort_order
|
||||
FROM room_amenities a
|
||||
JOIN room_amenity_links r ON a.id = r.amenity_id
|
||||
WHERE r.room_id = $1
|
||||
ORDER BY a.sort_order, a.name`,
|
||||
[roomId]
|
||||
);
|
||||
return NextResponse.json({ data: rows });
|
||||
}
|
||||
|
||||
const { rows } = await db.query(
|
||||
'SELECT id, name, icon_svg, sort_order FROM room_amenities ORDER BY sort_order, name'
|
||||
);
|
||||
return NextResponse.json({ data: rows });
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch amenities:', error);
|
||||
return NextResponse.json({ error: 'Failed to fetch amenities' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
// Link amenities to a room (replaces all links)
|
||||
export async function POST(request: NextRequest) {
|
||||
try {
|
||||
const { room_id, amenity_ids } = await request.json();
|
||||
|
||||
if (!room_id || !Array.isArray(amenity_ids)) {
|
||||
return NextResponse.json({ error: 'room_id and amenity_ids array are required' }, { status: 400 });
|
||||
}
|
||||
|
||||
// Delete existing links
|
||||
await db.query('DELETE FROM room_amenity_links WHERE room_id = $1', [room_id]);
|
||||
|
||||
// Insert new links
|
||||
if (amenity_ids.length > 0) {
|
||||
const values = amenity_ids.map((_, i) => `($1, $${i + 2})`).join(', ');
|
||||
await db.query(
|
||||
`INSERT INTO room_amenity_links (room_id, amenity_id) VALUES ${values}`,
|
||||
[room_id, ...amenity_ids]
|
||||
);
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true });
|
||||
} catch (error) {
|
||||
console.error('Failed to link amenities:', error);
|
||||
return NextResponse.json({ error: 'Failed to link amenities' }, { status: 500 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user