DEV Community

Levi Ackerman
Levi Ackerman

Posted on

Bookings Frontend

I redid my file structure and moved my axiosinstance into a folder in components called services. Then made api.jsx

import AxiosInstance from "./AxiosInstance";  // ✅ Fix import

// Fetch user's bookings
export const fetchBookings = async () => {
  try {
    const response = await AxiosInstance.get("/bookings/");  // ✅ Use AxiosInstance
    return response.data;
  } catch (error) {
    console.error("❌ Error fetching bookings:", error.response?.data || error.message);
    throw error;
  }
};

// Create a new booking
export const createBooking = async (bookingData) => {
  try {
    const response = await AxiosInstance.post("/bookings/", bookingData);  // ✅ Use AxiosInstance
    return response.data;
  } catch (error) {
    console.error("❌ Error creating booking:", error.response?.data || error.message);
    throw error;
  }
};

// Delete a booking
export const deleteBooking = async (bookingId) => {
  try {
    await AxiosInstance.delete(`/bookings/${bookingId}/`);  // ✅ Use AxiosInstance
  } catch (error) {
    console.error("❌ Error deleting booking:", error.response?.data || error.message);
    throw error;
  }
};

Enter fullscreen mode Exit fullscreen mode

We now make bookings components in components folder

Booking form

import React, { useState } from "react";
import { createBooking } from "./services/api";

const BookingForm = ({ onBookingCreated }) => {
  const [bookingType, setBookingType] = useState("booking");
  const [bookingDate, setBookingDate] = useState("");

  const handleSubmit = async (e) => {
    e.preventDefault();

    // Ensure the date is in the future
    const today = new Date().toISOString().split("T")[0]; // Get today's date in YYYY-MM-DD format
    if (bookingDate <= today) {
      alert("Please select a future date.");
      return;
    }

    try {
      const newBooking = await createBooking({
        booking_type: bookingType,
        booking_date: bookingDate,
      });

      alert("Booking created successfully!");
      onBookingCreated(newBooking); // Update the UI with the new booking
    } catch (error) {
      alert("Failed to create booking. Please try again.");
    }
  };

  return (
    <div className="max-w-md mx-auto bg-white p-6 rounded-lg shadow-md">
      <h2 className="text-xl font-semibold mb-4">Schedule a Booking</h2>
      <form onSubmit={handleSubmit}>
        <div className="mb-4">
          <label className="block font-medium">Booking Type:</label>
          <select
            className="w-full p-2 border rounded"
            value={bookingType}
            onChange={(e) => setBookingType(e.target.value)}
          >
            <option value="booking">Consultation</option>
            <option value="installation">Installation</option>
          </select>
        </div>

        <div className="mb-4">
          <label className="block font-medium">Select Date:</label>
          <input
            type="date"
            className="w-full p-2 border rounded"
            value={bookingDate}
            onChange={(e) => setBookingDate(e.target.value)}
          />
        </div>

        <button
          type="submit"
          className="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600"
        >
          Schedule
        </button>
      </form>
    </div>
  );
};

export default BookingForm;

Enter fullscreen mode Exit fullscreen mode

Then booking list

import React, { useEffect, useState } from "react";
import { fetchBookings, deleteBooking } from "./services/api";

const BookingList = () => {
  const [bookings, setBookings] = useState([]); // ✅ Ensure an array as the initial state
  const [loading, setLoading] = useState(true); // Track loading state

  useEffect(() => {
    loadBookings();
  }, []);

  const loadBookings = async () => {
    try {
      setLoading(true);
      const data = await fetchBookings();

      if (Array.isArray(data)) {
        setBookings(data); // ✅ Ensure only an array is set
      } else {
        console.error("Unexpected response format:", data);
        setBookings([]); // Set an empty array to prevent errors
      }
    } catch (error) {
      console.error("Error loading bookings:", error);
      setBookings([]); // Prevent crash if error occurs
    } finally {
      setLoading(false);
    }
  };

  const handleDelete = async (bookingId) => {
    if (window.confirm("Are you sure you want to cancel this booking?")) {
      try {
        await deleteBooking(bookingId);
        setBookings(bookings.filter((booking) => booking.id !== bookingId));
        alert("Booking canceled.");
      } catch (error) {
        alert("Failed to cancel booking.");
      }
    }
  };

  return (
    <div className="max-w-md mx-auto bg-white p-6 rounded-lg shadow-md">
      <h2 className="text-xl font-semibold mb-4">My Bookings</h2>

      {loading ? (
        <p>Loading...</p> // Show loading state
      ) : bookings.length === 0 ? (
        <p>No bookings found.</p>
      ) : (
        <ul>
          {bookings.map((booking) => (
            <li key={booking.booking_id} className="border-b p-2 flex justify-between items-center">
              <div>
                <p className="font-medium">{booking.booking_type.toUpperCase()}</p>
                <p className="text-sm text-gray-500">{booking.booking_date}</p>
              </div>
              <button
                onClick={() => handleDelete(booking.booking_id)}
                className="text-red-500 hover:text-red-700"
              >
                Cancel
              </button>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
};

export default BookingList;

Enter fullscreen mode Exit fullscreen mode

then BookingsPage

import React, { useState } from "react";
import BookingForm from "../components/BookingForm";
import BookingList from "../components/BookingList";

const BookingsPage = () => {
  const [refresh, setRefresh] = useState(false);

  return (
    <div className="container mx-auto p-4">
      <h1 className="text-2xl font-bold text-center mb-6">Manage Your Bookings</h1>
      <BookingForm onBookingCreated={() => setRefresh(!refresh)} />
      <BookingList key={refresh} />
    </div>
  );
};

export default BookingsPage;

Enter fullscreen mode Exit fullscreen mode

Finally add bookings route to app.jsx

import BookingsPage from './components/BookingsPage'

                <Route path="/bookings" element={<BookingsPage/>}/>

Enter fullscreen mode Exit fullscreen mode

dun

Top comments (0)