Learn by Directing AI
All materials

BookingForm.jsx

jsxBookingForm.jsx
import { useState, useEffect } from 'react';
import { useParams, useNavigate, Link } from 'react-router-dom';
import { fetchTrek, createBooking } from '../api';

export default function BookingForm() {
  const { trekId } = useParams();
  const navigate = useNavigate();
  const [trek, setTrek] = useState(null);
  const [form, setForm] = useState({
    customer_name: '',
    customer_email: '',
    group_size: 1,
    booking_date: ''
  });
  const [submitting, setSubmitting] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetchTrek(trekId).then(setTrek).catch(err => setError(err.message));
  }, [trekId]);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setSubmitting(true);
    setError(null);
    try {
      await createBooking({ ...form, trek_id: parseInt(trekId) });
      navigate('/bookings');
    } catch (err) {
      setError(err.message);
    } finally {
      setSubmitting(false);
    }
  };

  if (!trek) return <p className="text-stone-500">Loading...</p>;

  return (
    <div className="max-w-lg">
      <Link to={`/treks/${trekId}`} className="text-sm text-amber-700 hover:text-amber-800">&larr; Back to trek</Link>
      <h1 className="text-2xl font-bold text-stone-800 mt-4">Book: {trek.name}</h1>
      <p className="text-stone-500 mt-1">{trek.duration_days} days &middot; NPR {trek.price_npr?.toLocaleString()}</p>

      {error && <p className="mt-4 text-red-600 text-sm">{error}</p>}

      <form onSubmit={handleSubmit} className="mt-6 space-y-4">
        <div>
          <label className="block text-sm font-medium text-stone-700">Name</label>
          <input
            type="text"
            required
            value={form.customer_name}
            onChange={e => setForm({ ...form, customer_name: e.target.value })}
            className="mt-1 w-full border border-stone-300 rounded px-3 py-2 text-sm"
          />
        </div>
        <div>
          <label className="block text-sm font-medium text-stone-700">Email</label>
          <input
            type="email"
            required
            value={form.customer_email}
            onChange={e => setForm({ ...form, customer_email: e.target.value })}
            className="mt-1 w-full border border-stone-300 rounded px-3 py-2 text-sm"
          />
        </div>
        <div>
          <label className="block text-sm font-medium text-stone-700">
            Group size (max {trek.max_group_size})
          </label>
          <input
            type="number"
            min="1"
            max={trek.max_group_size}
            required
            value={form.group_size}
            onChange={e => setForm({ ...form, group_size: parseInt(e.target.value) })}
            className="mt-1 w-full border border-stone-300 rounded px-3 py-2 text-sm"
          />
        </div>
        <div>
          <label className="block text-sm font-medium text-stone-700">Preferred date</label>
          <input
            type="date"
            required
            value={form.booking_date}
            onChange={e => setForm({ ...form, booking_date: e.target.value })}
            className="mt-1 w-full border border-stone-300 rounded px-3 py-2 text-sm"
          />
        </div>
        <button
          type="submit"
          disabled={submitting}
          className="w-full bg-amber-600 text-white py-2 rounded hover:bg-amber-700 transition-colors disabled:opacity-50"
        >
          {submitting ? 'Booking...' : 'Confirm Booking'}
        </button>
      </form>
    </div>
  );
}