diff --git a/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php b/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php
new file mode 100644
index 00000000..12c6d57f
--- /dev/null
+++ b/database/migrations/2023_12_11_193200_add_new_column_2_to_job_results_table.php
@@ -0,0 +1,34 @@
+string('request_signature')->after('job_id')->nullable();
+ $table->string('result_signature')->after('request_signature')->nullable();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('job_results', function (Blueprint $table) {
+ $table->dropColumn('request_signature');
+ $table->dropColumn('result_signature');
+ });
+ }
+}
diff --git a/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue
new file mode 100644
index 00000000..03244ff4
--- /dev/null
+++ b/resources/assets/vue/components/bookings/sections/AdminPaymentsBillingSectionComponent.vue
@@ -0,0 +1,136 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/resources/assets/vue/general/mixins/aws/requestV2.js b/resources/assets/vue/general/mixins/aws/requestV2.js
new file mode 100644
index 00000000..12b27542
--- /dev/null
+++ b/resources/assets/vue/general/mixins/aws/requestV2.js
@@ -0,0 +1,49 @@
+export default {
+ methods: {
+ poll(url, method, section, successNotification = true, errorNotification = true){
+ if(!this.validate()){ return; }
+ if (section) {
+ this.$store.dispatch('toggleLoading', {name: section, status: true})
+ }
+ this.$store.dispatch('crudRequestV2', {
+ endpoint: url,
+ method: method,
+ parameters: this.parameters
+ }).then(response => {
+ let statusCode = response.status,
+ success = response.ok;
+
+ response.json().then(response => {
+
+ if(!success){
+ this.openModal();
+ errorNotification ? this.$store.dispatch('createNotification', {title: response.title, message: response.message, type: 'error'}): null;
+ this.errorHandler(response, statusCode); return;
+ }
+
+ successNotification ? this.$store.dispatch('createNotification', {title: response.title, message: response.message, type: 'success'}): null;
+ this.successHandler(response)
+
+
+ });
+ }).catch((error) => {
+ this.$store.dispatch('createNotification', {title: 'Unexpected Error', message: 'An unexpected error has occurred. Try again!', type: 'error'});
+ }).then(() => {
+ if (section) {
+ this.$store.dispatch('toggleLoading', {name: section, status: false})
+ }
+ })
+
+ },
+ validate() {
+ if(this.$v){
+ this.$v.$touch();
+ return !this.$v.$invalid;
+ }
+ return true;
+ },
+ successHandler(response){},
+ errorHandler(response){}
+ }
+
+}
diff --git a/resources/assets/vue/general/mixins/tabHandler.js b/resources/assets/vue/general/mixins/tabHandler.js
new file mode 100644
index 00000000..81790ed0
--- /dev/null
+++ b/resources/assets/vue/general/mixins/tabHandler.js
@@ -0,0 +1,24 @@
+export default {
+ data() {
+ return {
+ activeTab: null,
+ displayedTabs: [],
+ };
+ },
+ methods: {
+ setActiveTab(event) {
+ const tabName = event.currentTarget.getAttribute('tab-name');
+ // console.log(`Tab "${tabName}" clicked`);
+ this.activeTab = tabName;
+ if (!this.displayedTabs.includes(tabName)) {
+ this.displayedTabs.push(tabName);
+ }
+ },
+ isActiveTab(tabName) {
+ return this.activeTab === tabName;
+ },
+ showTabContent(tabName) {
+ return this.displayedTabs.includes(tabName);
+ },
+ },
+}
diff --git a/resources/assets/vue/vuex/modules/crudRequestV2.js b/resources/assets/vue/vuex/modules/crudRequestV2.js
new file mode 100644
index 00000000..2445190e
--- /dev/null
+++ b/resources/assets/vue/vuex/modules/crudRequestV2.js
@@ -0,0 +1,47 @@
+export default {
+ actions: {
+ crudRequestV2({getters, dispatch}, {endpoint, method, parameters}){
+ const queryDomain = endpoint.split('?')[0];
+ let encodedParams = endpoint.split('?')[1];
+ let decodedParams = fullyDecodeURI(encodedParams);
+ const queryParams = encodeURIComponent(decodedParams);
+ encodedParams = queryParams.toString();
+ let filteredEncodedParams = encodedParams.replace(/%3D/g,'=');
+ filteredEncodedParams = filteredEncodedParams.replace(/%26/g,'&');
+ let combinedAbsoluteUrl = queryDomain;
+ if(filteredEncodedParams !== undefined && filteredEncodedParams !== 'undefined'){
+ combinedAbsoluteUrl = queryDomain + '?' + filteredEncodedParams;
+ }
+
+ // return fetch(endpoint, {
+ return fetch(combinedAbsoluteUrl, {
+ method: method,
+ responseType: 'json',
+ body: parameters ? JSON.stringify(parameters):null,
+ headers: {
+ 'content-type': 'application/json',
+ 'Authorization': 'Bearer '+getters.getAccessToken
+ }
+ }).then(response => {
+ if(response.status === 401 && window.location.href !== route('login') && window.location.href.indexOf(route('last_mile_delivery.login')) <= -1){
+ dispatch('userAuthentication', {access_token: '', redirect_url: [7, 8].includes(getters.getCompanyModuleType) ? route('last_mile_delivery.login') : route('login')});
+ }
+
+ return response;
+
+ })
+ }
+ }
+}
+
+function isEncoded(uri) {
+ uri = uri || '';
+ return uri !== decodeURIComponent(uri);
+}
+
+function fullyDecodeURI(uri){
+ while (isEncoded(uri)){
+ uri = decodeURIComponent(uri);
+ }
+ return uri;
+}
diff --git a/resources/assets/vue/vuex/store.js b/resources/assets/vue/vuex/store.js
index 2c3d911b..ff10c673 100644
--- a/resources/assets/vue/vuex/store.js
+++ b/resources/assets/vue/vuex/store.js
@@ -4,6 +4,7 @@ import toggleSection from './modules/toggleSection'
import toggleLoading from './modules/toggleLoading'
import createNotification from './modules/createNotification'
import crudRequest from './modules/crudRequest'
+import crudRequestV2 from './modules/crudRequestV2'
import authentication from './modules/authentication'
import loadRequestQueue from './modules/loadRequestQueue'
@@ -16,6 +17,7 @@ export default new Vuex.Store({
loadRequestQueue,
createNotification,
crudRequest,
+ crudRequestV2,
authentication
}
-})
\ No newline at end of file
+})
diff --git a/resources/views/pages/billings.blade.php b/resources/views/pages/billings.blade.php
index 4bc012d5..da84f8b9 100644
--- a/resources/views/pages/billings.blade.php
+++ b/resources/views/pages/billings.blade.php
@@ -3,129 +3,7 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-@endsection
\ No newline at end of file
+@endsection