feat(portal): /track/[token] 비회원 의뢰 추적 페이지

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 05:13:58 +09:00
parent b4f57c85ec
commit f5cfb8bd6f
2 changed files with 465 additions and 0 deletions

View File

@@ -0,0 +1,31 @@
import { NextResponse } from 'next/server';
import { createAdminClient } from '@/lib/supabase/admin';
export const runtime = 'nodejs';
// 비회원 의뢰 추적 API — 향후 클라이언트 측 폴링/갱신용.
// PII(이메일·전화·메시지 본문)는 select에서 제외한다.
// DB 예외(마이그레이션 미적용 42703 포함)는 모두 404로 폴백한다.
export async function GET(_req: Request, { params }: { params: Promise<{ token: string }> }) {
const { token } = await params;
if (!token || token.length > 64) return NextResponse.json({ error: 'not found' }, { status: 404 });
const admin = createAdminClient();
const { data: request, error } = await admin
.from('contact_requests')
.select('id, name, service, status, project_type, budget, timeline, created_at, updated_at')
.eq('public_token', token)
.maybeSingle();
if (error || !request) return NextResponse.json({ error: 'not found' }, { status: 404 });
const { data: quote } = await admin
.from('quotes')
.select('public_token, title, status, valid_until')
.eq('contact_request_id', request.id)
.in('status', ['sent', 'accepted', 'rejected'])
.order('created_at', { ascending: false })
.limit(1)
.maybeSingle();
return NextResponse.json({ request, quote: quote ?? null });
}