Hi There, working on my phase/4 Rails project, one of the challenges I faced building a booking system was to freeze the start and end dates and all the dates in between those dates once the bookings is confirmed.
I started with a DatePicker React component, storing the Start and End date as states using useState hook as follows:
const [dateRange, setDateRange] = useState([null, null]);
const [startDate, endDate] = dateRange;
selectsRange={true}
startDate={startDate}
endDate={endDate}
onChange={(update) => {
setDateRange(update);
changeDate(update);
}}
withPortal
placeholderText="click to select dates"
/>
Note: withPortal prop will add a styling to the Calendar to be viewed as a modal with the background blurred. I have attached a photo of what it looks like.
Then I made a fetch post request to my backend, after I created a
route'/booking' with a create action, including the room_id as follows:
class BookingsController < ApplicationController
rescue_from ActiveRecord::RecordInvalid, with: :render_record_invalid
def create
books = Room.find(params[:room_id]).bookings
dates_arr_range = books.pluck(:start_date, :end_date)
dates_arr_range.each do |range|
first = Date.parse(range[0])
last= Date.parse(range[1])
range_between = (first..last).to_a
requested_range = ((Date.parse(params[:start_date]))..(Date.parse(params[:end_date]))).to_a
requested_range.each do |date|
if range_between.include?(date)
return render json: {error: "These dates are already booked, Please try other dates"},status: :unprocessable_entity
end
end
end
booking = Booking.create!(booking_params)
render json: booking, status: :created
end
private
def booking_params
params.permit(:start_date, :end_date, :user_id, :room_id, :duration)
end
end
Let me explain my code step by step:
first, I made sure the room exists using the 'Strong params'
looking for the room with the id matching params[:room_id] and stored the room bookings in a variable called books.
Then, I used the pluck method to pluck the start and end date from each booking of the specific room which returns an array of arrays, each array in the array includes a start and end date.
Then, I iterated over every array in the array and got the range between the two dates using .to_a method and stored that range in a variable, but first, I converted the start and end date into dates that are readable rails Date.
tip: use .class to double check if the class = Date
Using strong params, I managed to again find the range between the requested dates from my fetch request, again I converted them into Dates and into an array as follows:
((Date.parse(params[:start_date]))..(Date.parse(params[:end_date]))).to_a
then I iterated over all the ranges of the array of arrays to make sure the dates have not been booked yet, if the dates were already booked, then it should throw an error.
Finally, I displayed the result on my front end whether the dates were already booked or were available.
I'm sure there are other much more simple ways to achieve the same results but that is what I came up with.
Thank you for reading :) .
Nancy.
Top comments (0)