From 0f6df76667f64ee8da309a69938e484c1a62c2dc Mon Sep 17 00:00:00 2001 From: Alex Tselegidis Date: Sun, 16 Oct 2022 21:54:26 +0300 Subject: [PATCH] Allow the users to define their own status and assign them to appointments (#244). --- application/controllers/Booking.php | 7 + application/controllers/Calendar.php | 4 + .../language/arabic/translations_lang.php | 3 + .../language/bulgarian/translations_lang.php | 3 + .../language/catalan/translations_lang.php | 3 + .../language/chinese/translations_lang.php | 3 + .../language/czech/translations_lang.php | 3 + .../language/danish/translations_lang.php | 3 + .../language/dutch/translations_lang.php | 3 + .../language/english/translations_lang.php | 3 + .../language/estonian/translations_lang.php | 3 + .../language/finnish/translations_lang.php | 3 + .../language/french/translations_lang.php | 3 + .../language/german/translations_lang.php | 3 + .../language/greek/translations_lang.php | 3 + .../language/hebrew/translations_lang.php | 3 + .../language/hindi/translations_lang.php | 3 + .../language/hungarian/translations_lang.php | 3 + .../language/italian/translations_lang.php | 3 + .../language/japanese/translations_lang.php | 3 + .../luxembourgish/translations_lang.php | 3 + .../language/marathi/translations_lang.php | 3 + .../language/persian/translations_lang.php | 3 + .../language/polish/translations_lang.php | 3 + .../portuguese-br/translations_lang.php | 3 + .../language/portuguese/translations_lang.php | 3 + .../language/romanian/translations_lang.php | 3 + .../language/russian/translations_lang.php | 3 + .../language/serbian/translations_lang.php | 3 + .../language/slovak/translations_lang.php | 3 + .../language/spanish/translations_lang.php | 3 + .../language/swedish/translations_lang.php | 3 + .../language/turkish/translations_lang.php | 3 + ...add_appointment_status_options_setting.php | 47 +++++++ ...dd_status_column_to_appointments_table.php | 45 +++++++ application/models/Appointments_model.php | 1 + .../components/appointment_status_options.php | 22 +++ .../views/components/appointments_modal.php | 23 +++- application/views/pages/business_settings.php | 12 ++ application/views/pages/calendar.php | 1 + application/views/pages/services.php | 1 - assets/css/layouts/backend_layout.scss | 4 + .../components/appointment_status_options.js | 126 ++++++++++++++++++ assets/js/components/appointments_modal.js | 4 + assets/js/pages/business_settings.js | 15 +++ assets/js/utils/calendar_default_view.js | 13 ++ assets/js/utils/calendar_table_view.js | 28 +++- openapi.yml | 12 ++ 48 files changed, 452 insertions(+), 6 deletions(-) create mode 100644 application/migrations/043_add_appointment_status_options_setting.php create mode 100644 application/migrations/044_add_status_column_to_appointments_table.php create mode 100644 application/views/components/appointment_status_options.php create mode 100644 assets/js/components/appointment_status_options.js diff --git a/application/controllers/Booking.php b/application/controllers/Booking.php index 13800fd8..33775d14 100755 --- a/application/controllers/Booking.php +++ b/application/controllers/Booking.php @@ -536,12 +536,19 @@ class Booking extends EA_Controller { $appointment['id_users_customer'] = $customer_id; $appointment['is_unavailability'] = FALSE; + $appointment['color'] = $service['color']; + + $appointment_status_options_json = setting('appointment_status_options', '[]'); + $appointment_status_options = json_decode($appointment_status_options_json, TRUE) ?? []; + $appointment['status'] = $appointment_status_options[0] ?? NULL; $this->appointments_model->only($appointment, [ 'start_datetime', 'end_datetime', 'location', 'notes', + 'color', + 'status', 'is_unavailability', 'id_users_provider', 'id_users_customer', diff --git a/application/controllers/Calendar.php b/application/controllers/Calendar.php index a4cd0654..6ba4efb1 100644 --- a/application/controllers/Calendar.php +++ b/application/controllers/Calendar.php @@ -117,6 +117,8 @@ class Calendar extends EA_Controller { $calendar_view = request('view', $user['settings']['calendar_view']); + $appointment_status_options = setting('appointment_status_options'); + script_vars([ 'user_id' => $user_id, 'role_slug' => $role_slug, @@ -146,6 +148,7 @@ class Calendar extends EA_Controller { 'available_providers' => $available_providers, 'available_services' => $available_services, 'secretary_providers' => $secretary_providers, + 'appointment_status_options' => json_decode($appointment_status_options, TRUE) ?? [], 'require_first_name' => setting('require_first_name'), 'require_last_name' => setting('require_last_name'), 'require_email' => setting('require_email'), @@ -248,6 +251,7 @@ class Calendar extends EA_Controller { 'location', 'notes', 'color', + 'status', 'is_unavailability', 'id_users_provider', 'id_users_customer', diff --git a/application/language/arabic/translations_lang.php b/application/language/arabic/translations_lang.php index 012ccbb6..16d7be76 100755 --- a/application/language/arabic/translations_lang.php +++ b/application/language/arabic/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/bulgarian/translations_lang.php b/application/language/bulgarian/translations_lang.php index 852cf25f..32a1ea50 100755 --- a/application/language/bulgarian/translations_lang.php +++ b/application/language/bulgarian/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/catalan/translations_lang.php b/application/language/catalan/translations_lang.php index 70bb1cbd..7395db3a 100644 --- a/application/language/catalan/translations_lang.php +++ b/application/language/catalan/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/chinese/translations_lang.php b/application/language/chinese/translations_lang.php index 497d2a27..6372391e 100755 --- a/application/language/chinese/translations_lang.php +++ b/application/language/chinese/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/czech/translations_lang.php b/application/language/czech/translations_lang.php index ca7e77e9..3731882a 100644 --- a/application/language/czech/translations_lang.php +++ b/application/language/czech/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/danish/translations_lang.php b/application/language/danish/translations_lang.php index 9812f97d..555af33e 100755 --- a/application/language/danish/translations_lang.php +++ b/application/language/danish/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/dutch/translations_lang.php b/application/language/dutch/translations_lang.php index 156d2e15..c3ae57d3 100755 --- a/application/language/dutch/translations_lang.php +++ b/application/language/dutch/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/english/translations_lang.php b/application/language/english/translations_lang.php index f8caea6d..64d70431 100755 --- a/application/language/english/translations_lang.php +++ b/application/language/english/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/estonian/translations_lang.php b/application/language/estonian/translations_lang.php index 27f3ea64..e18bf7ea 100644 --- a/application/language/estonian/translations_lang.php +++ b/application/language/estonian/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/finnish/translations_lang.php b/application/language/finnish/translations_lang.php index 95ed81bf..5d65e570 100755 --- a/application/language/finnish/translations_lang.php +++ b/application/language/finnish/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/french/translations_lang.php b/application/language/french/translations_lang.php index 815059c4..d484364f 100755 --- a/application/language/french/translations_lang.php +++ b/application/language/french/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/german/translations_lang.php b/application/language/german/translations_lang.php index 2e0d5dde..029a97a1 100755 --- a/application/language/german/translations_lang.php +++ b/application/language/german/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/greek/translations_lang.php b/application/language/greek/translations_lang.php index 60fc0a97..388ec8a1 100755 --- a/application/language/greek/translations_lang.php +++ b/application/language/greek/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/hebrew/translations_lang.php b/application/language/hebrew/translations_lang.php index 5ee023bc..da91bd44 100644 --- a/application/language/hebrew/translations_lang.php +++ b/application/language/hebrew/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/hindi/translations_lang.php b/application/language/hindi/translations_lang.php index c4dbd00a..3c0c789c 100755 --- a/application/language/hindi/translations_lang.php +++ b/application/language/hindi/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/hungarian/translations_lang.php b/application/language/hungarian/translations_lang.php index e7fbceee..523442fb 100755 --- a/application/language/hungarian/translations_lang.php +++ b/application/language/hungarian/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/italian/translations_lang.php b/application/language/italian/translations_lang.php index 39d10fdd..ea6de8bf 100755 --- a/application/language/italian/translations_lang.php +++ b/application/language/italian/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/japanese/translations_lang.php b/application/language/japanese/translations_lang.php index cca792b5..771a900e 100755 --- a/application/language/japanese/translations_lang.php +++ b/application/language/japanese/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/luxembourgish/translations_lang.php b/application/language/luxembourgish/translations_lang.php index 73b70b90..1e20ef4b 100755 --- a/application/language/luxembourgish/translations_lang.php +++ b/application/language/luxembourgish/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/marathi/translations_lang.php b/application/language/marathi/translations_lang.php index 1815df5f..65b37e27 100644 --- a/application/language/marathi/translations_lang.php +++ b/application/language/marathi/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/persian/translations_lang.php b/application/language/persian/translations_lang.php index 1b6ae74b..55ff01f7 100644 --- a/application/language/persian/translations_lang.php +++ b/application/language/persian/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/polish/translations_lang.php b/application/language/polish/translations_lang.php index 3fcbe467..e9067da0 100755 --- a/application/language/polish/translations_lang.php +++ b/application/language/polish/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/portuguese-br/translations_lang.php b/application/language/portuguese-br/translations_lang.php index 92662835..e09e2f79 100755 --- a/application/language/portuguese-br/translations_lang.php +++ b/application/language/portuguese-br/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/portuguese/translations_lang.php b/application/language/portuguese/translations_lang.php index 9d3dd1a0..bc514e53 100755 --- a/application/language/portuguese/translations_lang.php +++ b/application/language/portuguese/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/romanian/translations_lang.php b/application/language/romanian/translations_lang.php index df14a035..4ae8d56c 100755 --- a/application/language/romanian/translations_lang.php +++ b/application/language/romanian/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/russian/translations_lang.php b/application/language/russian/translations_lang.php index 869a103a..f1c0e404 100755 --- a/application/language/russian/translations_lang.php +++ b/application/language/russian/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/serbian/translations_lang.php b/application/language/serbian/translations_lang.php index 3b960b82..4f11b7ea 100644 --- a/application/language/serbian/translations_lang.php +++ b/application/language/serbian/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/slovak/translations_lang.php b/application/language/slovak/translations_lang.php index a0b25585..68342cf6 100755 --- a/application/language/slovak/translations_lang.php +++ b/application/language/slovak/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/spanish/translations_lang.php b/application/language/spanish/translations_lang.php index 71a0dc43..a47e7568 100755 --- a/application/language/spanish/translations_lang.php +++ b/application/language/spanish/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/swedish/translations_lang.php b/application/language/swedish/translations_lang.php index cb97806e..903b72ae 100644 --- a/application/language/swedish/translations_lang.php +++ b/application/language/swedish/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/language/turkish/translations_lang.php b/application/language/turkish/translations_lang.php index c90e76c4..5a1b852c 100755 --- a/application/language/turkish/translations_lang.php +++ b/application/language/turkish/translations_lang.php @@ -405,4 +405,7 @@ $lang['future_booking_limit_hint'] = 'Set the future limit in days customers can $lang['api_token'] = 'API Token'; $lang['allow_rescheduling_cancellation_before'] = 'Allow Rescheduling/Cancellation Before'; $lang['at_least_one_field'] = 'At least one field must be displayed in the booking page.'; +$lang['status'] = 'Status'; +$lang['appointment_status_options'] = 'Appointment Status Options'; +$lang['appointment_status_options_info'] = 'Define a list of available appointment status options that can be used in the the calendar page (the first one will automatically become the default value).'; // End diff --git a/application/migrations/043_add_appointment_status_options_setting.php b/application/migrations/043_add_appointment_status_options_setting.php new file mode 100644 index 00000000..efb50c10 --- /dev/null +++ b/application/migrations/043_add_appointment_status_options_setting.php @@ -0,0 +1,47 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +/** + * @property CI_DB_query_builder $db + * @property CI_DB_forge $dbforge + */ +class Migration_Add_appointment_status_options_setting extends CI_Migration { + /** + * Upgrade method. + * + * @throws Exception + */ + public function up() + { + if ( ! $this->db->get_where('settings', ['name' => 'appointment_status_options'])->num_rows()) + { + $this->db->insert('settings', [ + 'name' => 'appointment_status_options', + 'value' => '["Booked", "Confirmed", "Rescheduled", "Cancelled", "Draft"]' + ]); + } + } + + /** + * Downgrade method. + * + * @throws Exception + */ + public function down() + { + if ($this->db->get_where('settings', ['name' => 'appointment_status_options'])->num_rows()) + { + $this->db->delete('settings', ['name' => 'status_options']); + } + } +} diff --git a/application/migrations/044_add_status_column_to_appointments_table.php b/application/migrations/044_add_status_column_to_appointments_table.php new file mode 100644 index 00000000..5d8c5986 --- /dev/null +++ b/application/migrations/044_add_status_column_to_appointments_table.php @@ -0,0 +1,45 @@ + + * @copyright Copyright (c) 2013 - 2020, Alex Tselegidis + * @license http://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link http://easyappointments.org + * @since v1.4.0 + * ---------------------------------------------------------------------------- */ + +class Migration_Add_status_column_to_appointments_table extends EA_Migration { + /** + * Upgrade method. + */ + public function up() + { + if ( ! $this->db->field_exists('status', 'appointments')) + { + $fields = [ + 'status' => [ + 'type' => 'VARCHAR', + 'constraint' => '512', + 'default' => '', + 'after' => 'color' + ] + ]; + + $this->dbforge->add_column('appointments', $fields); + } + } + + /** + * Downgrade method. + */ + public function down() + { + if ( ! $this->db->field_exists('status', 'appointments')) + { + $this->dbforge->drop_column('appointments', 'status'); + } + } +} diff --git a/application/models/Appointments_model.php b/application/models/Appointments_model.php index 97115bea..329a149b 100644 --- a/application/models/Appointments_model.php +++ b/application/models/Appointments_model.php @@ -38,6 +38,7 @@ class Appointments_model extends EA_Model { 'end' => 'end_datetime', 'location' => 'location', 'color' => 'color', + 'status' => 'status', 'notes' => 'notes', 'hash' => 'hash', 'providerId' => 'id_users_provider', diff --git a/application/views/components/appointment_status_options.php b/application/views/components/appointment_status_options.php new file mode 100644 index 00000000..9a3957f6 --- /dev/null +++ b/application/views/components/appointment_status_options.php @@ -0,0 +1,22 @@ + + +
> + + + +
+ + + + + + diff --git a/application/views/components/appointments_modal.php b/application/views/components/appointments_modal.php index a32e8424..eb86c166 100644 --- a/application/views/components/appointments_modal.php +++ b/application/views/components/appointments_modal.php @@ -1,8 +1,9 @@
- - + +
@@ -153,7 +162,8 @@ -
+
: @@ -168,6 +178,11 @@
+ +
+ + +
diff --git a/application/views/pages/business_settings.php b/application/views/pages/business_settings.php index 1d788479..36b861da 100755 --- a/application/views/pages/business_settings.php +++ b/application/views/pages/business_settings.php @@ -104,6 +104,18 @@ + +
+
+ +
+
+ +

+ +

+ + 'id="appointment-status-options"']) ?> diff --git a/application/views/pages/calendar.php b/application/views/pages/calendar.php index 881f3e5b..99deddcf 100755 --- a/application/views/pages/calendar.php +++ b/application/views/pages/calendar.php @@ -92,6 +92,7 @@ 'appointments_modal', [ 'available_services' => vars('available_services'), + 'appointment_status_options' => vars('appointment_status_options'), 'timezones' => vars('timezones'), 'require_first_name' => vars('require_first_name'), 'require_last_name' => vars('require_last_name'), diff --git a/application/views/pages/services.php b/application/views/pages/services.php index 2161d344..b56851cd 100755 --- a/application/views/pages/services.php +++ b/application/views/pages/services.php @@ -126,7 +126,6 @@
diff --git a/assets/css/layouts/backend_layout.scss b/assets/css/layouts/backend_layout.scss index deb28970..f8f3c83a 100644 --- a/assets/css/layouts/backend_layout.scss +++ b/assets/css/layouts/backend_layout.scss @@ -908,3 +908,7 @@ body .form-horizontal .controls { #company-color { min-height: 41px; } + +.status-list-item { + max-width: 400px; +} diff --git a/assets/js/components/appointment_status_options.js b/assets/js/components/appointment_status_options.js new file mode 100644 index 00000000..f343deba --- /dev/null +++ b/assets/js/components/appointment_status_options.js @@ -0,0 +1,126 @@ +/* ---------------------------------------------------------------------------- + * Easy!Appointments - Online Appointment Scheduler + * + * @package EasyAppointments + * @author A.Tselegidis + * @copyright Copyright (c) Alex Tselegidis + * @license https://opensource.org/licenses/GPL-3.0 - GPLv3 + * @link https://easyappointments.org + * @since v1.5.0 + * ---------------------------------------------------------------------------- */ + +/** + * Appointment status options component. + * + * This module implements the appointment status options. + */ +App.Components.AppointmentStatusOptions = (function () { + /** + * Render an appointment status option. + * + * @param {String} [appointmentStatusOption] + * + * @return {jQuery} Returns a jQuery selector with the list group item markup. + */ + function renderListGroupItem(appointmentStatusOption = '') { + return $(` +
  • + + + +
  • + `); + } + + /** + * Event: Delete Appointment Status Option "Click" + * + * @param {jQuery.Event} event + */ + function onDeleteAppointmentStatusOptionClick(event) { + $(event.currentTarget).closest('li').remove(); + } + + /** + * Event: Add Appointment Status Option "Click" + * + * @param {jQuery.Event} event + */ + function onAddAppointmentStatusOptionClick(event) { + const $target = $(event.currentTarget); + + const $listGroup = $target.closest('.appointment-status-options').find('.list-group'); + + if (!$listGroup.length) { + return; + } + + renderListGroupItem() + .appendTo($listGroup); + } + + /** + * Get target options. + * + * @param {jQuery} $target Container element ".status-list" selector. + * + * @return {String[]} + */ + function getOptions($target) { + const $listGroup = $target.find('.list-group'); + + const appointmentStatusOptions = []; + + $listGroup.find('li').each((index, listGroupItemEl) => { + const $listGroupItem = $(listGroupItemEl); + const appointmentStatusOption = $listGroupItem.find('input:text').val(); + appointmentStatusOptions.push(appointmentStatusOption); + }); + + return appointmentStatusOptions; + } + + /** + * Set target options. + * + * @param {jQuery} $target Container element ".status-list" selector. + * @param {String[]} appointmentStatusOptions Appointment status options. + */ + function setOptions($target, appointmentStatusOptions) { + if (!$target.length || !appointmentStatusOptions || !appointmentStatusOptions.length) { + return; + } + + const $listGroup = $target.find('.list-group'); + + if (!$listGroup.length) { + return; + } + + $listGroup.empty(); + + appointmentStatusOptions.forEach((appointmentStatusOption) => { + renderListGroupItem(appointmentStatusOption).appendTo($listGroup); + }); + } + + /** + * Initialize the module. + */ + function initialize() { + $(document).on('click', '.delete-appointment-status-option', onDeleteAppointmentStatusOptionClick); + $(document).on('click', '.add-appointment-status-option', onAddAppointmentStatusOptionClick); + } + + document.addEventListener('DOMContentLoaded', initialize); + + return { + getOptions, + setOptions, + initialize + }; +})(); diff --git a/assets/js/components/appointments_modal.js b/assets/js/components/appointments_modal.js index c264e92d..97d6b499 100755 --- a/assets/js/components/appointments_modal.js +++ b/assets/js/components/appointments_modal.js @@ -36,6 +36,7 @@ App.Components.AppointmentsModal = (function () { const $saveAppointment = $('#save-appointment'); const $appointmentId = $('#appointment-id'); const $appointmentLocation = $('#appointment-location'); + const $appointmentStatus = $('#appointment-status'); const $appointmentColor = $('#appointment-color'); const $appointmentNotes = $('#appointment-notes'); const $reloadAppointments = $('#reload-appointments'); @@ -89,6 +90,7 @@ App.Components.AppointmentsModal = (function () { end_datetime: endDatetime, location: $appointmentLocation.val(), color: App.Components.ColorSelection.getColor($appointmentColor), + status: $appointmentStatus.val(), notes: $appointmentNotes.val(), is_unavailability: Number(false) }; @@ -411,6 +413,8 @@ App.Components.AppointmentsModal = (function () { $appointmentsModal.find('input, textarea').val(''); $appointmentsModal.find('.modal-message').fadeOut(); + $appointmentStatus.find('option:first').prop('checked', true); + $language.val('english'); $timezone.val('UTC'); diff --git a/assets/js/pages/business_settings.js b/assets/js/pages/business_settings.js index 413d0059..6a4f8c61 100644 --- a/assets/js/pages/business_settings.js +++ b/assets/js/pages/business_settings.js @@ -17,6 +17,7 @@ App.Pages.BusinessSettings = (function () { const $saveSettings = $('#save-settings'); const $applyGlobalWorkingPlan = $('#apply-global-working-plan'); + const $appointmentStatusOptions = $('#appointment-status-options') let workingPlanManager = null; /** @@ -77,6 +78,13 @@ App.Pages.BusinessSettings = (function () { value: JSON.stringify(workingPlan) }); + const appointmentStatusOptions = App.Components.AppointmentStatusOptions.getOptions($appointmentStatusOptions); + + businessSettings.push({ + name: 'appointment_status_options', + value: JSON.stringify(appointmentStatusOptions) + }); + return businessSettings; } @@ -136,17 +144,24 @@ App.Pages.BusinessSettings = (function () { deserialize(businessSettings); let companyWorkingPlan = {}; + let appointmentStatusOptions = []; vars('business_settings').forEach((businessSetting) => { if (businessSetting.name === 'company_working_plan') { companyWorkingPlan = JSON.parse(businessSetting.value); } + + if (businessSetting.name === 'appointment_status_options') { + appointmentStatusOptions = JSON.parse(businessSetting.value); + } }); workingPlanManager = new App.Utils.WorkingPlan(); workingPlanManager.setup(companyWorkingPlan); workingPlanManager.timepickers(false); workingPlanManager.addEventListeners(); + + App.Components.AppointmentStatusOptions.setOptions($appointmentStatusOptions, appointmentStatusOptions); $saveSettings.on('click', onSaveSettingsClick); diff --git a/assets/js/utils/calendar_default_view.js b/assets/js/utils/calendar_default_view.js index 1089458c..5b816442 100755 --- a/assets/js/utils/calendar_default_view.js +++ b/assets/js/utils/calendar_default_view.js @@ -153,6 +153,7 @@ App.Utils.CalendarDefaultView = (function () { $appointmentsModal.find('#language').val(customer.language); $appointmentsModal.find('#timezone').val(customer.timezone); $appointmentsModal.find('#appointment-location').val(appointment.location); + $appointmentsModal.find('#appointment-status').val(appointment.status); $appointmentsModal.find('#appointment-notes').val(appointment.notes); $appointmentsModal.find('#customer-notes').val(customer.notes); @@ -411,6 +412,7 @@ App.Utils.CalendarDefaultView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('notes') }), $('', { @@ -605,6 +607,15 @@ App.Utils.CalendarDefaultView = (function () { }), $('
    '), + $('', { + 'class': 'd-inline-block me-2', + 'text': lang('status') + }), + $('', { + 'text': info.event.extendedProps.data.status || '-', + }), + $('
    '), + $('', { 'class': 'd-inline-block me-2', 'text': lang('service') @@ -664,6 +675,7 @@ App.Utils.CalendarDefaultView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('notes') }), $('', { @@ -1687,6 +1699,7 @@ App.Utils.CalendarDefaultView = (function () { $appointmentsModal.find('#language').val(customer.language); $appointmentsModal.find('#timezone').val(customer.timezone); $appointmentsModal.find('#appointment-location').val(appointment.location); + $appointmentsModal.find('#appointment-status').val(appointment.status); $appointmentsModal.find('#appointment-notes').val(appointment.notes); $appointmentsModal.find('#customer-notes').val(customer.notes); diff --git a/assets/js/utils/calendar_table_view.js b/assets/js/utils/calendar_table_view.js index 87d1e25e..f798c8c5 100755 --- a/assets/js/utils/calendar_table_view.js +++ b/assets/js/utils/calendar_table_view.js @@ -229,6 +229,7 @@ App.Utils.CalendarTableView = (function () { $appointmentsModal.find('#language').val(customer.language); $appointmentsModal.find('#timezone').val(customer.timezone); $appointmentsModal.find('#appointment-location').val(appointment.location); + $appointmentsModal.find('#appointment-status').val(appointment.status); $appointmentsModal.find('#appointment-notes').val(appointment.notes); $appointmentsModal.find('#customer-notes').val(customer.notes); @@ -436,7 +437,7 @@ App.Utils.CalendarTableView = (function () { firstDay: firstWeekdayNumber, onSelect: (dateText, instance) => { const startDate = new Date(instance.currentYear, instance.currentMonth, instance.currentDay); - const endDate = moment(startDate).add(parseInt($selectFilterItem.val()) - 1, 'days').toDate(); + const endDate = moment(startDate).add(parseInt($selectFilterItem.val()) - 1, 'days').toDate(); createView(startDate, endDate); } }); @@ -1147,6 +1148,7 @@ App.Utils.CalendarTableView = (function () { $html = $('
    ', { 'html': [ $('', { + 'class': 'd-inline-block me-2', 'text': lang('start') }), $('', { @@ -1160,6 +1162,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('end') }), $('', { @@ -1173,6 +1176,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('notes') }), $('', { @@ -1232,6 +1236,7 @@ App.Utils.CalendarTableView = (function () { $html = $('
    ', { 'html': [ $('', { + 'class': 'd-inline-block me-2', 'text': lang('provider') }), $('', { @@ -1244,6 +1249,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('start') }), $('', { @@ -1259,6 +1265,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('end') }), $('', { @@ -1274,6 +1281,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('timezone') }), $('', { @@ -1330,6 +1338,7 @@ App.Utils.CalendarTableView = (function () { $html = $('
    ', { 'html': [ $('', { + 'class': 'd-inline-block me-2', 'text': lang('start') }), $('', { @@ -1343,6 +1352,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('end') }), $('', { @@ -1356,6 +1366,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('timezone') }), $('', { @@ -1364,6 +1375,16 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', + 'text': lang('status') + }), + $('', { + 'text': info.event.extendedProps.data.status || '-' + }), + $('
    '), + + $('', { + 'class': 'd-inline-block me-2', 'text': lang('service') }), $('', { @@ -1372,6 +1393,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('provider') }), App.Utils.CalendarEventPopover.renderMapIcon(info.event.extendedProps.data.provider), @@ -1384,6 +1406,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('customer') }), App.Utils.CalendarEventPopover.renderMapIcon(info.event.extendedProps.data.customer), @@ -1396,6 +1419,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('email') }), App.Utils.CalendarEventPopover.renderMailIcon(info.event.extendedProps.data.customer.email), @@ -1405,6 +1429,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('phone') }), App.Utils.CalendarEventPopover.renderPhoneIcon(info.event.extendedProps.data.customer.phone_number), @@ -1414,6 +1439,7 @@ App.Utils.CalendarTableView = (function () { $('
    '), $('', { + 'class': 'd-inline-block me-2', 'text': lang('notes') }), $('', { diff --git a/openapi.yml b/openapi.yml index ab11dbe4..34a2a320 100644 --- a/openapi.yml +++ b/openapi.yml @@ -1737,6 +1737,10 @@ components: type: string location: type: string + color: + type: string + status: + type: string notes: type: string customerId: @@ -1754,6 +1758,8 @@ components: end: '2021-01-01 18:00:00' hash: apTWVbSvBJXR location: Test Street 1A, 12345 Some State, Some Place + color: '#123456' + status: Booked notes: This is a test appointment. customerId: 5 providerId: 2 @@ -1768,6 +1774,10 @@ components: type: string location: type: string + color: + type: string + status: + type: string notes: type: string customerId: @@ -1780,6 +1790,8 @@ components: start: '2021-01-01 17:00:00' end: '2021-01-01 18:00:00' location: Test Street 1A, 12345 Some State, Some Place + color: '#123456' + status: Booked notes: This is a test appointment. customerId: 5 providerId: 2