rtrips-online/src/app/trips/new/page.tsx

95 lines
3.1 KiB
TypeScript

'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
import Link from 'next/link';
import { AppSwitcher } from '@/components/AppSwitcher';
import { NLInput } from '@/components/NLInput';
import { ParsedTripPreview } from '@/components/ParsedTripPreview';
import { ParsedTrip } from '@/lib/types';
export default function NewTrip() {
const router = useRouter();
const [parsed, setParsed] = useState<ParsedTrip | null>(null);
const [rawInput, setRawInput] = useState('');
const [creating, setCreating] = useState(false);
const [error, setError] = useState<string | null>(null);
const handleParsed = (data: ParsedTrip, raw: string) => {
setParsed(data);
setRawInput(raw);
};
const handleConfirm = async (finalParsed: ParsedTrip) => {
setCreating(true);
setError(null);
try {
const res = await fetch('/api/trips', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ parsed: finalParsed, rawInput }),
});
if (!res.ok) {
const data = await res.json();
throw new Error(data.error || 'Failed to create trip');
}
const trip = await res.json();
router.push(`/trips/${trip.id}`);
} catch (err) {
setError(err instanceof Error ? err.message : 'Something went wrong');
setCreating(false);
}
};
return (
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900 text-white">
{/* Nav */}
<nav className="border-b border-slate-700/50 backdrop-blur-sm">
<div className="max-w-6xl mx-auto px-6 py-4 flex items-center justify-between">
<div className="flex items-center gap-3">
<AppSwitcher current="trips" />
<Link href="/" className="flex items-center gap-2">
<div className="w-8 h-8 bg-gradient-to-br from-teal-400 to-cyan-500 rounded-lg flex items-center justify-center font-bold text-slate-900 text-sm">
rT
</div>
<span className="font-semibold text-lg">rTrips</span>
</Link>
</div>
<Link href="/trips" className="text-sm text-slate-300 hover:text-white transition-colors">
My Trips
</Link>
</div>
</nav>
{/* Content */}
<div className="max-w-2xl mx-auto px-6 py-12">
<h1 className="text-3xl font-bold mb-2">Plan a New Trip</h1>
<p className="text-slate-400 mb-8">
Describe your trip in natural language and we&apos;ll structure it for you.
</p>
{error && (
<div className="mb-6 p-3 bg-red-900/30 border border-red-700/50 rounded-lg text-red-300 text-sm">
{error}
</div>
)}
{!parsed ? (
<NLInput onParsed={handleParsed} />
) : (
<ParsedTripPreview
parsed={parsed}
rawInput={rawInput}
onConfirm={handleConfirm}
onBack={() => setParsed(null)}
loading={creating}
/>
)}
</div>
</div>
);
}