Bewertung

This commit is contained in:
2026-08-16 09:25:32 +00:00
parent 48ba6ae282
commit 9f5f4911f2
4 changed files with 1078 additions and 519 deletions

View File

@@ -0,0 +1,27 @@
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
export const dynamic = 'force-dynamic';
// POST: Bewertung speichern oder aktualisieren
export async function POST(req: NextRequest, { params }: { params: { id: string } }) {
try {
const { member_id, grade, comment } = await req.json();
if (!member_id || !grade) {
return NextResponse.json({ error: 'Mitreisender und Note erforderlich' }, { status: 400 });
}
const res = await query(
`INSERT INTO hotel_ratings (hotel_id, member_id, grade, comment, updated_at)
VALUES ($1, $2, $3, $4, NOW())
ON CONFLICT (hotel_id, member_id)
DO UPDATE SET grade = EXCLUDED.grade, comment = EXCLUDED.comment, updated_at = NOW()
RETURNING *`,
[params.id, member_id, grade, comment ? comment.trim() : null]
);
return NextResponse.json({ success: true, rating: res.rows[0] });
} catch (e: any) {
return NextResponse.json({ success: false, error: e.message }, { status: 500 });
}
}

View File

@@ -15,7 +15,9 @@ export async function GET() {
ph.nights AS latest_nights, ph.nights AS latest_nights,
ph.persons AS latest_persons, ph.persons AS latest_persons,
bp.best_price, bp.best_price,
bp.best_price_per_night hr.avg_grade,
hr.total_votes,
hr.ratings_json
FROM hotels h FROM hotels h
LEFT JOIN trips t ON h.trip_id = t.id LEFT JOIN trips t ON h.trip_id = t.id
LEFT JOIN LATERAL ( LEFT JOIN LATERAL (
@@ -26,13 +28,31 @@ export async function GET() {
LIMIT 1 LIMIT 1
) ph ON true ) ph ON true
LEFT JOIN LATERAL ( LEFT JOIN LATERAL (
SELECT SELECT MIN(price_numeric)::float AS best_price
MIN(price_numeric)::float AS best_price,
MIN(price_per_night)::float AS best_price_per_night
FROM hotel_price_history FROM hotel_price_history
WHERE hotel_id::text = h.id::text AND price_numeric > 0 WHERE hotel_id::text = h.id::text AND price_numeric > 0
) bp ON true ) bp ON true
ORDER BY h.checkin_date ASC NULLS LAST, h.id ASC LEFT JOIN LATERAL (
SELECT
ROUND(AVG(hr_sub.grade), 1)::float AS avg_grade,
COUNT(hr_sub.id)::int AS total_votes,
COALESCE(
json_agg(
json_build_object(
'member_id', hr_sub.member_id,
'name', tm.name,
'color', tm.color,
'grade', hr_sub.grade,
'comment', hr_sub.comment
)
ORDER BY hr_sub.updated_at DESC
),
'[]'
) AS ratings_json
FROM hotel_ratings hr_sub
JOIN trip_members tm ON hr_sub.member_id = tm.id
WHERE hr_sub.hotel_id = h.id
) hr ON true
`); `);
return NextResponse.json({ success: true, hotels: res.rows }); return NextResponse.json({ success: true, hotels: res.rows });
} catch (error: any) { } catch (error: any) {

View File

@@ -0,0 +1,55 @@
import { NextRequest, NextResponse } from 'next/server';
import { query } from '@/lib/db';
export const dynamic = 'force-dynamic';
// GET: Alle Mitreisenden eines Trips laden
export async function GET(req: NextRequest, { params }: { params: { id: string } }) {
try {
const res = await query(
`SELECT * FROM trip_members WHERE trip_id = $1 ORDER BY created_at ASC`,
[params.id]
);
return NextResponse.json({ success: true, members: res.rows });
} catch (e: any) {
return NextResponse.json({ success: false, error: e.message }, { status: 500 });
}
}
// POST: Neuen Mitreisenden hinzufügen
export async function POST(req: NextRequest, { params }: { params: { id: string } }) {
try {
const { name, color } = await req.json();
if (!name) {
return NextResponse.json({ error: 'Name ist erforderlich' }, { status: 400 });
}
const defaultColors = ['#2563eb', '#db2777', '#059669', '#d97706', '#7c3aed', '#0891b2'];
const randomColor = color || defaultColors[Math.floor(Math.random() * defaultColors.length)];
const res = await query(
`INSERT INTO trip_members (trip_id, name, color)
VALUES ($1, $2, $3)
RETURNING *`,
[params.id, name.trim(), randomColor]
);
return NextResponse.json({ success: true, member: res.rows[0] });
} catch (e: any) {
return NextResponse.json({ success: false, error: e.message }, { status: 500 });
}
}
// DELETE: Mitreisenden entfernen
export async function DELETE(req: NextRequest) {
try {
const { searchParams } = new URL(req.url);
const memberId = searchParams.get('memberId');
if (!memberId) return NextResponse.json({ error: 'memberId fehlt' }, { status: 400 });
await query(`DELETE FROM trip_members WHERE id = $1`, [memberId]);
return NextResponse.json({ success: true });
} catch (e: any) {
return NextResponse.json({ success: false, error: e.message }, { status: 500 });
}
}

File diff suppressed because it is too large Load Diff