About the Code Style and Organization

The LaraBooking was made with Laravel 5.5 and VueJS for FrontEnd. The system is not SPA, but a hybrid application that uses the power of Server Side Rendering and the power of JavaScript and Ajax in some features like Calendar, Booking Appointments, etc.

We have adopted some code conventions and patterns to keep the code quality. Let's see it below:

1. The Repositories and Services

To keep the code organization and reduce the code duplication through the system, we used Repository and Service Classes that abstract the system logic. For example, to get all the appointments among two dates on the AppointmentController, simply call this method that is in the Repositories\AppointmentsRepository.php:

$this->appointmentsRepository->getAppointmentsByPeriod($start, $end);

By default this method filters the appointments by the user type, for example, A provider can get only appointments that he provides.

And, to get all the available times in a date, by service and provider, you can use the methods inside Services\ServiceAvailableTimes.php:

$times = (new ServiceAvailableTimes($date, $service, $provider))->getAvailableTimes();

2. JavaScript Settings Object

To pass some settings to the JavaScript, we used the view file: resources/views/js/config.blade.php. Currently, all the settings inside this file are URLs that will be used on AJAX requests:

    var LaraBooking = {
        // Appointments
        appointmentsUrl: "{{ route('home.appointments.index') }}",
        addAppointmentUrl: "{{ route('home.appointments.store') }}",
        addClientAppointmentUrl: "{{ route('ajax.appointments.storeClientAppointment') }}",
        updateAppointmentUrl: "{{ route('home.appointments.update', ':id') }}",
        removeAppointmentUrl: "{{ route('home.appointments.destroy', ':id') }}",

        // Clients
        clientsUrl: "{{ route('home.clients.index') }}",

        // Providers
        providersUrl: "{{ route('home.providers.index') }}",

        // Services
        servicesUrl: "{{ route('ajax.services.index') }}",
        serviceAvailableTimesUrl: "{{ route('ajax.services.times', ':id') }}",

As you can see, when the route has attributes, we pass it to the route string using the :attribute notation.

updateAppointmentUrl: "{{ route('home.appointments.update', ':id') }}"

It will be replaced after in the JavaScript by the correct attribute value and can be used on AJAX. Eg:

var url = LaraBooking.updateAppointmentUrl.replace(':id', id);

3. AJAX Requests

We use the Axios Library to make AJAX Requests, but we wrote a Wrapper that simplifies using Axios, and automatically shows Toasts when the request has errors. You can see the Wrapper inside resources/assets/js/wrappers/axiosWrapper.js to see how it works. Basically, the AxiosWrapper constructor can receive a Toast and a Loader Screen instances that can be used internally (but it is optional).

The most important method in the AxiosWrapper is request. This method makes an AJAX request, show and hide the Loader if it exists and catch the errors.

Other methods like get, post, put and delete are simple wrappers to the request method.

Here you can see a code (from the BookAddAppointmentsComponent.vue) using the AxiosWrapper to make an AJAX Request:

getAvailableTimes(date) {
    let url = LaraBooking.serviceAvailableTimesUrl;
    url = url.replace(':id', this.appointment.service_id);
    url = url + '?date=' + date + '&provider=' + this.appointment.provider_id;

    AxiosWrapper.get(url, (data) => {
        this.availableTimes = data.times;