Your IP : 216.73.217.77


Current Path : /home/users/unlimited/www/whatsapp-crm/resources/js/Components/Tables/
Upload File :
Current File : /home/users/unlimited/www/whatsapp-crm/resources/js/Components/Tables/AddonTable.vue

<script setup>
    import { ref } from 'vue';
    import debounce from 'lodash/debounce';
    import { router, useForm } from '@inertiajs/vue3';
    import AlertModal from '@/Components/AlertModal.vue';
    import { useAlertModal } from '@/Composables/useAlertModal';
    import Modal from '@/Components/Modal.vue';
    import FormInput from '@/Components/FormInput.vue';
    import FormToggleSwitch from '@/Components/FormToggleSwitch.vue';
    import Table from '@/Components/Table.vue';
    import TableHeader from '@/Components/TableHeader.vue';
    import TableHeaderRow from '@/Components/TableHeaderRow.vue';
    import TableHeaderRowItem from '@/Components/TableHeaderRowItem.vue';
    import TableBody from '@/Components/TableBody.vue';
    import TableBodyRow from '@/Components/TableBodyRow.vue';
    import TableBodyRowItem from '@/Components/TableBodyRowItem.vue';
    import Dropdown from '@/Components/Dropdown.vue';
    import DropdownItemGroup from '@/Components/DropdownItemGroup.vue';
    import DropdownItem from '@/Components/DropdownItem.vue';
    import Pagination from '@/Components/Pagination.vue';
    import { trans } from 'laravel-vue-i18n';

    const props = defineProps({
        rows: {
            type: Object,
            required: true,
        },
        filters: {
            type: Object
        },
        config: {
            type: Array
        }
    });

    const { isOpenAlert, openAlert, confirmAlert } = useAlertModal();

    const isOpenModal = ref(false);
    const isOpenInstallModal = ref(false);
    const isLoading = ref(false);
    const currentURL = ref(window.location.origin);

    const emit = defineEmits(['edit', 'delete']);

    const form = useForm({'test': null});
    const form2 = useForm({
        settings: {}
    });
    const form3 = useForm({
        uuid: null,
        purchase_code: null,
        addon: null
    });

    function deleteItem(id) {
        emit('delete', id);
    }

    const deleteAction = (key) => {
        form.delete('/admin/faqs/' + key);
    }

    const isLastRow = (index) => {
      return index === props.rows.data.length - 1;
    }

    const params = ref({
        search: props.filters.search,
    });

    const isSearching = ref(false);

    const clearSearch = () => {
        params.value.search = null;
        runSearch();
    }

    const search = debounce(() => {
        isSearching.value = true;
        runSearch();
    }, 1000);

    const runSearch = () => {
        const url = window.location.pathname;

        router.visit(url, {
            method: 'get',
            data: params.value,
        })
    }

    const formUrl = ref(null);
    const modalLogo = ref(null);
    const modalTitle = ref(null);
    const modalDescription = ref(null);
    const installDescription = ref(null);
    const modalInputs = ref([]);

    const setupAddon = (item) => {
        modalLogo.value = item.logo;
        modalTitle.value = item.name;
        modalDescription.value = item.description;
        const inputFields = JSON.parse(item.metadata)?.input_fields || [];
        modalInputs.value = inputFields;

        form2.settings = {};
        let urlSegment = modalTitle.value.toLowerCase().replace(/ /g, '-');
        formUrl.value = '/admin/addons/setup/' + urlSegment;

        // Populate form2.settings with input fields
        inputFields.forEach(input => {
            form2.settings[input.name] = getValueByKey(input.name);
        });

        isOpenModal.value = true
    }

    const setupInstallModal = (item, type) => {
        modalLogo.value = item.logo;
        modalTitle.value = item.name;
        modalDescription.value = item.description;
        installDescription.value = type == 'extended' ? trans('Enter your extended license to install') : trans('Enter the addon license to install');

        form3.uuid = item.uuid
        form3.addon = item.name;
        isOpenInstallModal.value = true
    }

    const getValueByKey = (key) => {
        const found = props.config.find(item => item.key === key);
        return found ? found.value : '';
    };

    const submitForm = () => {
        form2.post(formUrl.value, {
            preserveScroll: true,
            onSuccess: () => {
                isOpenModal.value = false
            }
        });
    }

    const submitForm3 = () => {
        form3.post('/admin/addons/install', {
            preserveScroll: true,
            onSuccess: () => {
                isOpenInstallModal.value = false
            }
        });
    }
</script>
<template>
    <div class="md:bg-white flex items-center border border-primary md:border-none md:shadow-sm h-12 md:h-10 w-full md:w-80 rounded-[0.5rem] mb-6 text-xl md:text-sm">
        <span class="pl-3">
            <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m15 15l6 6m-11-4a7 7 0 1 1 0-14a7 7 0 0 1 0 14Z"/></svg>
        </span>
        <input @input="search" v-model="params.search" type="text" class="outline-none px-4 w-full" :placeholder="$t('Search')">
        <button v-if="isSearching === false && params.search" @click="clearSearch" type="button" class="pr-2">
            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10s10-4.5 10-10S17.5 2 12 2zm3.7 12.3c.4.4.4 1 0 1.4c-.4.4-1 .4-1.4 0L12 13.4l-2.3 2.3c-.4.4-1 .4-1.4 0c-.4-.4-.4-1 0-1.4l2.3-2.3l-2.3-2.3c-.4-.4-.4-1 0-1.4c.4-.4 1-.4 1.4 0l2.3 2.3l2.3-2.3c.4-.4 1-.4 1.4 0c.4.4.4 1 0 1.4L13.4 12l2.3 2.3z"/></svg>
        </button>
        <span v-if="isSearching" class="pr-2">
            <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><circle cx="12" cy="3.5" r="1.5" fill="currentColor" opacity="0"><animateTransform attributeName="transform" calcMode="discrete" dur="2.4s" repeatCount="indefinite" type="rotate" values="0 12 12;90 12 12;180 12 12;270 12 12"/><animate attributeName="opacity" dur="0.6s" keyTimes="0;0.5;1" repeatCount="indefinite" values="1;1;0"/></circle><circle cx="12" cy="3.5" r="1.5" fill="currentColor" opacity="0"><animateTransform attributeName="transform" begin="0.2s" calcMode="discrete" dur="2.4s" repeatCount="indefinite" type="rotate" values="30 12 12;120 12 12;210 12 12;300 12 12"/><animate attributeName="opacity" begin="0.2s" dur="0.6s" keyTimes="0;0.5;1" repeatCount="indefinite" values="1;1;0"/></circle><circle cx="12" cy="3.5" r="1.5" fill="currentColor" opacity="0"><animateTransform attributeName="transform" begin="0.4s" calcMode="discrete" dur="2.4s" repeatCount="indefinite" type="rotate" values="60 12 12;150 12 12;240 12 12;330 12 12"/><animate attributeName="opacity" begin="0.4s" dur="0.6s" keyTimes="0;0.5;1" repeatCount="indefinite" values="1;1;0"/></circle></svg>
        </span>
    </div>

    <div class="grid md:grid-cols-3 gap-x-5 gap-y-4">
        <div v-for="addon in rows.data" :key="addon.id" class="bg-white rounded-[0.5rem] shadow-md text-sm space-y-3">
            <div class="flex items-center gap-x-3 pb-2 bg-slate-50 px-4 pt-4 rounded-tr-[0.5rem] rounded-tl-[0.5rem]">
                <div>
                    <img class="h-8 w-8" :src="'/images/' + addon.logo" alt="Whatsapp Logo">
                </div>
                <div class="text-[16px]">{{ $t(addon.name) }}</div>
            </div>
            <div class="text-slate-500 border-b px-4 text-xs pt-2 pb-4">{{ addon.description }}</div>
            <div class="flex justify-between items-center px-4 pb-4 text-xs">
                <div>
                    <span class=" py-1 px-3 rounded-md text-slate-600" :class="addon.status == 0 ? 'bg-red-600 text-white' : 'bg-slate-50'">{{ addon.status == 1 ? $t('Installed') : $t('Not installed') }}</span>
                </div>
                <div>
                    <button v-if="addon.status == 0" @click="setupInstallModal(addon, addon.license)" class="rounded-full border-2 w-full px-10 py-2 hover:border-secondary hover:bg-secondary hover:text-white text-secondary">{{ $t('Install') }}</button>
                    <button v-else @click="setupAddon(addon)" class="rounded-full border-2 w-full px-10 py-2 hover:border-secondary hover:bg-secondary hover:text-white text-secondary">{{ $t('Setup') }}</button>
                </div>
            </div>
        </div>
    </div>

    <Pagination class="mt-3" :pagination="rows.meta"/>

    <Modal :isOpen=isOpenModal>
        <div class="grid grid-cols-1 gap-x-6 gap-y-4">
            <div class="bg-slate-50 mx-[-30px] px-6 mt-[-25px] py-4 border-b">
                <div class="flex items-center gap-x-3">
                    <div>
                        <img class="h-8 w-8" :src="'/images/' + modalLogo" alt="Whatsapp Logo">
                    </div>
                    <div class="text-[16px]">{{ $t(modalTitle) }}</div>
                </div>
                <div class="text-slate-500 font-light text-xs pt-4">{{ modalDescription }}</div>
            </div>
            
            <form @submit.prevent="submitForm()">
                <div class="grid gap-x-6 gap-y-4 sm:grid-cols-2">
                    <div v-for="input in modalInputs" :class="input.class">
                        <FormInput v-if="input.element == 'input'" v-model="form2.settings[input.name]" :error="form2.errors[`settings.${input.name}`]" :name="$t(input.label)" :type="input.type" :class="input.class" />
                        <div v-if="input.element == 'toggle'">
                            <div class="text-sm mb-2">{{ $t(input.label) }}</div>
                            <FormToggleSwitch v-if="input.element == 'toggle'" v-model="form2.settings[input.name]"/>
                        </div>
                    </div>
                    <div v-if="modalTitle == 'Embedded Signup'" class="bg-orange-100 p-2 rounded-md shadow-sm mb-1 col-span-2">
                        <div class="flex items-center gap-x-1 border-b border-slate-500 pb-2 mb-2">
                            <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24"><path fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 11v5m0 5a9 9 0 1 1 0-18a9 9 0 0 1 0 18Zm.05-13v.1h-.1V8h.1Z"/></svg>
                            <p class="text-sm">{{ $t('Webhook setup') }}</p>
                        </div>
                        <span>
                            <p class="text-sm leading-6 break-all">{{ $t('Callback URL') }}: {{ currentURL + '/webhook/waba' }}</p>
                            <p class="text-sm leading-6 break-all">{{ $t('Verify token') }}: {{ getValueByKey('whatsapp_callback_token') }}</p>
                        </span>
                    </div>
                </div>
                <div class="mt-5 border-t pt-5 flex">
                    <button type="button" @click.self="isOpenModal = false" class="inline-flex justify-center rounded-md border border-transparent bg-slate-50 px-4 py-2 text-sm text-slate-500 hover:bg-slate-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 mr-4">{{ $t('Cancel') }}</button>
                    <button 
                        :class="['inline-flex justify-center rounded-md border border-transparent bg-primary px-4 py-2 text-sm text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2', { 'opacity-50': form2.processing }]"
                        :disabled="form2.processing"
                    >
                        <svg v-if="form2.processing" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2A10 10 0 1 0 22 12A10 10 0 0 0 12 2Zm0 18a8 8 0 1 1 8-8A8 8 0 0 1 12 20Z" opacity=".5"/><path fill="currentColor" d="M20 12h2A10 10 0 0 0 12 2V4A8 8 0 0 1 20 12Z"><animateTransform attributeName="transform" dur="1s" from="0 12 12" repeatCount="indefinite" to="360 12 12" type="rotate"/></path></svg>
                        <span v-else>{{ $t('Save') }}</span>
                    </button>
                </div>
            </form>
        </div>
    </Modal>

    <Modal :isOpen=isOpenInstallModal>
        <div class="grid grid-cols-1 gap-x-6 gap-y-4">
            <div class="bg-slate-50 mx-[-30px] px-6 mt-[-25px] py-4 border-b">
                <div class="flex items-center gap-x-3">
                    <div>
                        <img class="h-8 w-8" :src="'/images/' + modalLogo" alt="Whatsapp Logo">
                    </div>
                    <div class="text-[16px]">{{ $t(modalTitle) }}</div>
                </div>
                <div class="text-slate-500 font-light text-xs pt-4">{{ modalDescription }}</div>
            </div>
            
            <form @submit.prevent="submitForm3()">
                <div class="grid gap-x-6 sm:grid-cols-2">
                    <h4 class="text-sm">{{ $t('Envato purchase code') }}</h4>
                    <span class="col-span-2 text-xs text-slate-600 mb-2">{{ installDescription }}</span>
                    <FormInput v-model="form3.purchase_code" :error="form3.errors.purchase_code" :name="''" :type="'text'" :class="'col-span-2'" />
                </div>
                <div class="mt-5 border-t pt-5 flex">
                    <button type="button" @click.self="isOpenInstallModal = false" class="inline-flex justify-center rounded-md border border-transparent bg-slate-50 px-4 py-2 text-sm text-slate-500 hover:bg-slate-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 mr-4">{{ $t('Cancel') }}</button>
                    <button 
                        :class="['inline-flex justify-center rounded-md border border-transparent bg-primary px-4 py-2 text-sm text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2', { 'opacity-50': form3.processing }]"
                        :disabled="form3.processing"
                    >
                        <svg v-if="form3.processing" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24"><path fill="currentColor" d="M12 2A10 10 0 1 0 22 12A10 10 0 0 0 12 2Zm0 18a8 8 0 1 1 8-8A8 8 0 0 1 12 20Z" opacity=".5"/><path fill="currentColor" d="M20 12h2A10 10 0 0 0 12 2V4A8 8 0 0 1 20 12Z"><animateTransform attributeName="transform" dur="1s" from="0 12 12" repeatCount="indefinite" to="360 12 12" type="rotate"/></path></svg>
                        <span v-else>{{ $t('Save') }}</span>
                    </button>
                </div>
            </form>
        </div>
    </Modal>

    <!-- Alert Modal Component-->
    <AlertModal 
        v-model="isOpenAlert" 
        @confirm="() => confirmAlert(deleteAction)"
        :label = "$t('Delete row')" 
        :description = "$t('Are you sure you want to delete this row? This action can not be undone')"
    />
</template>