| <template>
    <div>
        <Head title="ChatGPT Seeder"/>
        <Heading class="mb-4">ChatGPT Seeder</Heading>
        <form @submit.prevent="submitForm" ref="form" method="post" class="space-y-8">
            <div class="bg-white dark:bg-gray-800 rounded-lg shadow">
                <div class="flex flex-col md:flex-row md:items-center border-b border-gray-100 dark:border-gray-700">
                    <div class="px-6 md:px-8 mt-1 md:mt-1 w-full md:w-1/5">
                        <label class="inline-block leading-tight space-x-1" for="content_type">
                            <span>Data Type</span>
                            <span class="text-red-500 text-sm">*</span>
                        </label>
                    </div>
                    <div class="mt-1 md:mt-0 pb-5 px-6 md:px-8 md:w-3/5 w-full md:py-5">
                        <div class="space-y-1">
                            <select class="w-full form-control form-input form-input-bordered" v-model="form.data_type"
                                    required>
                                <option value="">Select Data Type</option>
                                <option value="real">Real Data</option>
                                <option value="fake">Fake Data</option>
                            </select>
                        </div>
                    </div>
                </div>
                <div class="flex flex-col md:flex-row md:items-center border-b border-gray-100 dark:border-gray-700">
                    <div class="px-6 md:px-8 mt-1 md:mt-1 w-full md:w-1/5">
                        <label class="inline-block leading-tight space-x-1" for="database_table">
                            <span>Database Table</span>
                            <span class="text-red-500 text-sm">*</span>
                        </label>
                    </div>
                    <div class="mt-1 md:mt-0 pb-5 px-6 md:px-8 md:w-3/5 w-full md:py-5">
                        <div class="space-y-1">
                            <select v-model="form.database_table"
                                    class="w-full form-control form-input form-input-bordered"
                                    id="database_table"
                                    @change="getColumns($event)" required>
                                <option value="">Select Table</option>
                                <option v-for="table in this.tables" :value="table"
                                        :key="table">{{ table }}
                                </option>
                            </select>
                        </div>
                    </div>
                </div>
                <div class="flex flex-col md:flex-row md:items-center border-b border-gray-100 dark:border-gray-700">
                    <div class="px-6 md:px-8 mt-1 md:mt-1 w-full md:w-1/5">
                        <label class="inline-block leading-tight space-x-1" for="number_of_records">
                            <span>Number of Records</span>
                            <span class="text-red-500 text-sm">*</span>
                        </label>
                    </div>
                    <div class="mt-1 md:mt-0 pb-5 px-6 md:px-8 md:w-3/5 w-full md:py-5">
                        <div class="space-y-1">
                            <input type="text" class="w-full form-control form-input form-input-bordered"
                                   v-model="form.number_of_records" required>
                        </div>
                    </div>
                </div>
                <div class="flex flex-col md:flex-row md:items-center border-b border-gray-100 dark:border-gray-700">
                    <div class="px-6 md:px-8 mt-1 md:mt-1 w-full md:w-1/5">
                        <label class="inline-block leading-tight space-x-1" for="data_required">
                            <span>Data Description</span>
                            <span class="text-red-500 text-sm">*</span>
                        </label>
                    </div>
                    <div class="mt-1 md:mt-0 pb-5 px-6 md:px-8 md:w-3/5 w-full md:py-5">
                        <div class="space-y-1">
                            <input type="text" class="w-full form-control form-input form-input-bordered"
                                   placeholder="Describe the data you are looking for.."
                                   v-model="form.data_required" required>
                        </div>
                    </div>
                </div>
                <div class="flex flex-col md:flex-row md:items-center border-b border-gray-100 dark:border-gray-700"
                     id="available_columns" ref="columns">
                    <div class="px-6 md:px-8 mt-1 md:mt-1 w-full md:w-1/5 py-6">
                        <label class="inline-block leading-tight space-x-1" for="collumns">
                            <span>Available Columns:</span>
                            <span class="text-red-500 text-sm">*</span>
                        </label>
                    </div>
                    <div class="mt-2 pb-5 px-2 md:px-2 md:w-3/5 w-full md:py-5 flex justify-center">
                        <div class="space-y-1" v-if="this.columns.length > 0">
                            <div class="container mx-auto">
                                <table class="table-auto md:w-1/3">
                                    <thead>
                                    <tr class="text-xs">
                                        <th class="border border-gray-200 dark:border-gray-600 bg-gray-100 dark:bg-gray-700 px-4 py-3">
                                            Select
                                        </th>
                                        <th class="border border-gray-200 dark:border-gray-600 bg-gray-100 dark:bg-gray-700 px-4 py-3">
                                            Name
                                        </th>
                                        <th class="border border-gray-200 dark:border-gray-600 bg-gray-100 dark:bg-gray-700 px-4 py-3">
                                            Type
                                        </th>
                                        <th class="border border-gray-200 dark:border-gray-600 bg-gray-100 dark:bg-gray-700 px-4 py-3">
                                            Length
                                        </th>
                                        <th class="border border-gray-200 dark:border-gray-600 bg-gray-100 dark:bg-gray-700 px-4 py-3">
                                            Nullable
                                        </th>
                                        <th class="border border-gray-200 dark:border-gray-600 bg-gray-100 dark:bg-gray-700 px-4 py-3">
                                            Default
                                        </th>
                                    </tr>
                                    </thead>
                                    <tbody class="text-center">
                                    <tr v-for="(column, index) in this.columns" :key="index"
                                        class="hover:bg-gray-100 dark:hover:bg-gray-600">
                                        <td class="border border-gray-100 dark:border-gray-700 px-4 py-1">
                                            <input v-if="!column.column_not_nullable" type="checkbox"
                                                   class="w-4 form-control form-input-bordered"
                                                   :value="column.column_name"
                                                   v-model="form.selected_columns">
                                            <input v-if="column.column_not_nullable" type="checkbox"
                                                   class="w-4 form-control form-input-bordered"
                                                   :checked="column.column_not_nullable"
                                                   :disabled="true">
                                        </td>
                                        <td class="border border-gray-100 dark:border-gray-700 px-4 py-1">
                                            {{ column.column_name }}
                                        </td>
                                        <td class="border border-gray-100 dark:border-gray-700 px-4 py-1">
                                            {{ column.column_type }}
                                        </td>
                                        <td class="border border-gray-100 dark:border-gray-700 px-4 py-1">
                                            {{ column.column_length }}
                                        </td>
                                        <td class="border border-gray-100 dark:border-gray-700 px-4 py-1">
                                            {{ !column.column_not_nullable }}
                                        </td>
                                        <td class="border border-gray-100 dark:border-gray-700 px-4 py-1">
                                            {{ column.column_default }}
                                        </td>
                                    </tr>
                                    </tbody>
                                </table>
                            </div>
                        </div>
                        <div v-if="this.form.database_table !== '' && this.columns.length === 0"
                             class="text-red-500 font-bold mt-4 flex justify-center text-center">
                            This table has no columns.
                        </div>
                    </div>
                </div>
            </div>
            <div v-if="isLoading" class="mt-4 flex justify-center">
                <img src="/vendor/chatgpt-seeder/images/loading-spinner.gif" alt="Loading" width="46"
                     class="flex justify-center bg-opacity-80 z-50"/>
            </div>
            <div v-if="this.message" class="text-green-500 font-bold mt-4 flex justify-center capitalize">
                {{ this.message }}
            </div>
            <div v-if="this.error" class="text-red-500 font-bold mt-4 flex justify-center text-center">
                {{ this.error }}
            </div>
            <div
                class="flex flex-col md:flex-row md:items-center justify-center md:justify space-y-2 md:space-y-0 space-x-3">
                <button type="button"
                        class="bg-gray-700 text-white font-bold py-2 px-4 rounded"
                        @click="clearForm">
                    Clear
                </button>
                <button type="submit"
                        class="shadow relative bg-primary-500 hover:bg-primary-900 text-white dark:text-gray-900 cursor-pointer rounded text-sm font-bold focus:outline-none focus:ring ring-primary-200 dark:ring-gray-600 inline-flex items-center justify-center h-9 px-3 shadow relative bg-primary-500 hover:bg-primary-400 text-white dark:text-gray-900">
                    <span class="">Generate Data</span>
                </button>
            </div>
        </form>
    </div>
    <div v-if="showModal" class="modal fixed inset-0 flex items-center justify-center z-40"
         @click="handleOutsideClick">
        <div class="fixed inset-0 bg-black opacity-50"></div>
        <diver
            class="relative bg-white dark:bg-gray-800 rounded-lg shadow-lg max-w-2xl w-full mx-4 overflow-y-auto border border-gray-200 dark:border-gray-600">
            <div class="flex items-center justify-between px-6 py-4 border-b border-gray-200 dark:border-gray-600">
                <h2 class="text-md font-bold">Preview Data</h2>
                <button @click="closeModal"
                        class="text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none">
                    <svg class="w-6 h-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
                         stroke-linecap="round" stroke-linejoin="round">
                        <path d="M6 18L18 6M6 6l12 12"></path>
                    </svg>
                </button>
            </div>
            <div class="px-6 py-4">
                <div class="flex justify-center overflow-x max-h-[calc(100vh-5em)]">
                    <table class="table-auto overflow-scroll min-w-[20rem]">
                        <thead>
                        <tr>
                            <th v-for="key in this.keys" :key="key"
                                class="border border-gray-200 dark:border-gray-600 bg-gray-100 dark:bg-gray-700 px-4 py-2 capitalize">
                                {{ key }}
                            </th>
                        </tr>
                        </thead>
                        <tbody>
                        <tr v-for="item in this.sample_data" :key="item"
                            class="hover:bg-gray-400 dark:hover:bg-gray-700">
                            <td v-for="key in this.keys" :key="key"
                                class="border border-gray-200 dark:border-gray-600 px-4 py-1 text-center">
                                <template v-if="typeof item[key] === 'object'">
                                    <span v-for="(value, subKey) in item[key]" :key="subKey">
                                      {{ subKey }}: {{ value }}
                                    </span>
                                </template>
                                <template v-else>
                                    {{ item[key] }}
                                </template>
                            </td>
                        </tr>
                        </tbody>
                    </table>
                </div>
                <div class="flex justify-center mb-4 mt-2">
                    Total Tokens Used: {{ this.usage.total_tokens }}
                </div>
                <div class="flex justify-center mt-8">
                    <button class="px-4 py-2 bg-green-500 text-white rounded-md mr-2 rounded" @click="proceed">Proceed
                    </button>
                    <button
                        class="bg-primary-500 text-white font-bold py-2 px-4 border-b-4 border-primary-500 hover:border-blue-500 rounded mr-2"
                        @click="reGenerate">
                        Regenerate
                    </button>
                    <button class="px-4 py-2 bg-red-500 text-white rounded-md rounded" @click="closeModal">Close
                    </button>
                </div>
            </div>
        </diver>
    </div>
</template>
<script>
export default {
    data() {
        return {
            tables: [],
            columns: [],
            form: {
                data_type: '',
                database_table: '',
                number_of_records: '',
                selected_columns: [],
                seed_data: []
            },
            usage: null,
            keys: [],
            sample_data: [],
            generate_retry: 3,
            retry_count: 0,
            showModal: false,
            isLoading: false,
            message: '',
            error: '',
        };
    },
    mounted() {
        this.getTables();
        this.getGenerateRetry();
    },
    methods: {
        getGenerateRetry() {
            try {
                Nova.request().get('/nova-vendor/chatgpt-seeder/chatgpt-seeder/get-generate-retry', {}).then(({data}) => {
                    this.generate_retry = data.generate_retry;
                })
            } catch (e) {
                this.error = e.message;
            }
        },
        getTables() {
            try {
                Nova.request().get('/nova-vendor/chatgpt-seeder/chatgpt-seeder/tables', {}).then(({data}) => {
                    this.tables = data.tables;
                })
            } catch (e) {
                this.error = e.message;
            }
        },
        getColumns(table) {
            try {
                this.clearError();
                this.columns = [];
                this.form.selected_columns = [];
                this.database_table = table.target.value;
                Nova.request().get('/nova-vendor/chatgpt-seeder/chatgpt-seeder/columns/' + table.target.value, {}).then(({data}) => {
                    if (data.exception) {
                        this.isLoading = false;
                        this.error = data.exception_message;
                    } else {
                        this.columns = data.columns
                    }
                })
            } catch (e) {
                this.error = e.message;
            }
        },
        submitForm() {
            this.clearError();
            this.resetRetry();
            this.generate();
        },
        generate() {
            try {
                this.clearError();
                this.message = ''
                this.isLoading = true;
                if (this.retry_count <= this.generate_retry) {
                    this.form.columns = this.columns;
                    Nova.request().post('/nova-vendor/chatgpt-seeder/chatgpt-seeder/generate', this.form)
                        .then(({data}) => {
                            if (data.api_response_error) {
                                this.isLoading = false;
                                this.error = data.api_response_error
                            } else if (data.exception) {
                                this.isLoading = false;
                                this.error = data.exception_message;
                            } else {
                                this.usage = data.usage;
                                if (data.data) {
                                    this.content = data.data;
                                    data = data.data.slice(0, 8);
                                    if (data.length > 1) {
                                        this.sample_data = data;
                                        this.keys = Object.keys(data[0]);
                                        this.isLoading = false;
                                        this.openModal();
                                    } else {
                                        this.retry_count++;
                                        this.generate();
                                    }
                                } else {
                                    this.retry_count++;
                                    this.generate();
                                }
                            }
                        })
                } else {
                    this.isLoading = false;
                    this.error = 'Retry limit exceeded! Please refine your data description for more accurate results!'
                }
            } catch (e) {
                this.error = e.message;
            }
        },
        proceed() {
            try {
                this.clearError();
                this.form.seed_data = this.content
                Nova.request().post('/nova-vendor/chatgpt-seeder/chatgpt-seeder/proceed', this.form)
                    .then(({data}) => {
                        if (data.exception) {
                            this.isLoading = false;
                            this.error = data.exception_message;
                        } else {
                            if (data.succeed) {
                                this.isLoading = false;
                                this.message = this.form.database_table + ' table seeded successfully!'
                            } else {
                                this.isLoading = false;
                                this.message = 'Data return is invalid!'
                            }
                        }
                    })
            } catch (e) {
                this.error = e.message;
            }
        },
        reGenerate() {
            this.resetRetry();
            this.submitForm();
        },
        resetRetry() {
            this.retry_count = 0;
        },
        clearForm() {
            this.columns = [];
            this.selected_columns = [];
            this.form.data_type = null;
            this.form.database_table = null;
            this.form.number_of_records = null;
            this.form.data_required = null;
            this.form.seed_data = [];
            this.keys = [];
            this.sample_data = [];
            this.resetRetry();
            this.clearError();
            this.message = '';
            this.isLoading = false;
        },
        clearError() {
            this.error = '';
        },
        openModal() {
            this.showModal = true;
        },
        closeModal() {
            this.showModal = false;
            this.message = ''
        },
        handleOutsideClick() {
            this.closeModal();
        },
    },
}
</script>
<style>
</style>
 |