Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 27 additions & 15 deletions assets/js/components/AIFormBuilder.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
v-if="currentStage === 'input'"
:initialDescription="formDescription"
:initialSelectedPrompt="selectedPrompt"
:initialIntegration="selectedIntegration"
:generating="isGenerating"
@go-back="goBack"
@start-generation="handleStartGeneration"
@update:selectedPrompt="selectedPrompt = $event"
@update:selectedIntegration="selectedIntegration = $event"
@update:formDescription="formDescription = $event"
/>

Expand Down Expand Up @@ -58,20 +60,21 @@ export default {
return {
// Stage management
currentStage: 'input', // 'input', 'generating', 'success'

// Form data
formDescription: '',
selectedPrompt: '',
selectedIntegration: '',
isGenerating: false,
formTitle: 'Generated Form',
formId: null,

// Chat data
chatMessages: [],

// Form fields
formFields: [],

// API data
generatedFormData: null,
sessionId: null
Expand All @@ -95,11 +98,12 @@ export default {
handleStartGeneration(data) {
this.formDescription = data.description;
this.selectedPrompt = data.selectedPrompt;
this.selectedIntegration = data.integration || '';
this.isGenerating = true;
this.currentStage = 'generating';

// Call AI form generation API
this.callAIFormGenerationAPI(data.description);
this.callAIFormGenerationAPI(data.description, data.integration);
},

handleGenerationComplete() {
Expand All @@ -108,26 +112,34 @@ export default {
this.initializeChatData();
},

async callAIFormGenerationAPI(prompt) {
async callAIFormGenerationAPI(prompt, integration = '') {
try {
// Get configuration with fallbacks
const config = window.wpufAIFormBuilder || {};
const restUrl = config.rest_url || (window.location.origin + '/wp-json/');
const nonce = config.nonce || '';


// Build request body
const requestBody = {
prompt: prompt,
session_id: this.getSessionId(),
form_type: config.formType || 'post', // Pass form type to API
provider: config.provider || 'openai'
// Note: temperature and max_tokens are now handled by backend based on model configuration
};

// Add integration parameter if selected
if (integration) {
requestBody.integration = integration;
}

const response = await fetch(restUrl + 'wpuf/v1/ai-form-builder/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': nonce
},
body: JSON.stringify({
prompt: prompt,
session_id: this.getSessionId(),
form_type: config.formType || 'post', // Pass form type to API
provider: config.provider || 'openai'
// Note: temperature and max_tokens are now handled by backend based on model configuration
})
body: JSON.stringify(requestBody)
});

if (!response.ok) {
Expand Down
167 changes: 165 additions & 2 deletions assets/js/components/FormInputStage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,31 @@
</div>
</div>

<!-- Integration Selector (Only for Post Forms) -->
<div v-if="formType === 'post' && availableIntegrations.length > 0" class="wpuf-mb-6">
<label class="wpuf-block wpuf-text-gray-900 wpuf-mb-2 wpuf-text-[16px] wpuf-font-medium">
{{ __('Form Type (Optional)', 'wp-user-frontend') }}
</label>
<select
v-model="selectedIntegration"
class="wpuf-block !wpuf-w-full wpuf-max-w-full !wpuf-py-[10px] !wpuf-px-[14px] wpuf-text-gray-700 wpuf-font-normal !wpuf-shadow-sm wpuf-border !wpuf-border-gray-300 !wpuf-rounded-[6px] focus:!wpuf-ring-emerald-500 focus:!wpuf-border-emerald-500 hover:wpuf-border-gray-400 !wpuf-text-base !wpuf-leading-6 wpuf-bg-white wpuf-transition-all"
style="width: 100% !important; max-width: 100% !important;"
@change="onIntegrationChange"
>
<option value="">{{ __('Regular Form (No Integration)', 'wp-user-frontend') }}</option>
<option
v-for="integration in availableIntegrations"
:key="integration.id"
:value="integration.id"
>
{{ integration.label }}
</option>
</select>
<p class="wpuf-text-sm wpuf-text-gray-500 wpuf-mt-2">
{{ __('Choose a form type if you want to create a form for a specific integration', 'wp-user-frontend') }}
</p>
</div>

<!-- Prompt Templates -->
<div class="wpuf-mb-6">
<p class="wpuf-text-gray-900 wpuf-mb-4 wpuf-text-[16px]">
Expand Down Expand Up @@ -79,6 +104,10 @@ export default {
type: String,
default: ''
},
initialIntegration: {
type: String,
default: ''
},
initialSelectedPrompt: {
type: [String, Object],
default: ''
Expand Down Expand Up @@ -154,9 +183,21 @@ export default {
maxDescriptionLength: 300,
formType: formType,
promptTemplates: promptTemplates,
promptAIInstructions: promptAIInstructions
promptAIInstructions: promptAIInstructions,
selectedIntegration: this.initialIntegration || '',
availableIntegrations: [],
loadingIntegrations: false
};
},

mounted() {
// Fetch available integrations when component mounts
this.fetchAvailableIntegrations();
// Emit initial integration to parent if provided
if (this.initialIntegration) {
this.$emit('update:selectedIntegration', this.selectedIntegration);
}
},
watch: {
generating(newVal) {
this.isGenerating = newVal;
Expand All @@ -179,6 +220,127 @@ export default {
methods: {
__: window.__ || ((text) => text),

async fetchAvailableIntegrations() {
// Only fetch integrations for post forms
if (this.formType !== 'post') {
return;
}

this.loadingIntegrations = true;

try {
const config = window.wpufAIFormBuilder || {};
const restUrl = config.rest_url || (window.location.origin + '/wp-json/');
const nonce = config.nonce || '';

const response = await fetch(restUrl + 'wpuf/v1/ai-form-builder/integrations?form_type=' + this.formType, {
method: 'GET',
headers: {
'Content-Type': 'application/json',
'X-WP-Nonce': nonce
}
});

if (response.ok) {
const result = await response.json();
if (result.success && result.integrations) {
this.availableIntegrations = result.integrations;
}
}
} catch (error) {
console.error('Error fetching integrations:', error);
} finally {
this.loadingIntegrations = false;
}
},

onIntegrationChange() {
// Update prompt templates based on selected integration
this.updatePromptTemplates();

// Clear current prompt selection when integration changes
this.selectedPrompt = '';
this.formDescription = '';

// Emit the selected integration to parent
this.$emit('update:selectedIntegration', this.selectedIntegration);
this.$emit('update:selectedPrompt', '');
this.$emit('update:formDescription', '');
},

updatePromptTemplates() {
// Only update for post forms
if (this.formType !== 'post') {
return;
}

if (this.selectedIntegration === 'woocommerce') {
// WooCommerce-specific prompts
this.promptTemplates = [
{ id: 'woo_simple_product', label: this.__('Simple Product', 'wp-user-frontend') },
{ id: 'woo_digital_product', label: this.__('Digital Product', 'wp-user-frontend') },
{ id: 'woo_service_listing', label: this.__('Service Listing', 'wp-user-frontend') },
{ id: 'woo_handmade_product', label: this.__('Handmade Product', 'wp-user-frontend') }
];

this.promptAIInstructions = {
woo_simple_product: 'Create a WooCommerce Simple Product form with product title, product description, short description, regular price (_regular_price), sale price (_sale_price), featured image, product gallery (_product_image), product categories (product_cat), product tags (product_tag), catalog visibility (_visibility)',
woo_digital_product: 'Create a WooCommerce Digital Product form with product title, product description, regular price (_regular_price), featured image, product categories (product_cat), product tags (product_tag), SKU (_sku)',
woo_service_listing: 'Create a WooCommerce Service form with product title, product description, regular price (_regular_price), featured image, product categories (product_cat), purchase note (_purchase_note)',
woo_handmade_product: 'Create a WooCommerce Handmade Product form with product title, product description, short description, regular price (_regular_price), featured image, product gallery (_product_image), product categories (product_cat), product tags (product_tag), product attributes (pa_size, pa_color), weight (_weight), dimensions (_length, _width, _height)'
};
} else if (this.selectedIntegration === 'edd') {
// Easy Digital Downloads prompts
this.promptTemplates = [
{ id: 'edd_digital_download', label: this.__('Digital Download', 'wp-user-frontend') },
{ id: 'edd_software', label: this.__('Software Product', 'wp-user-frontend') },
{ id: 'edd_ebook', label: this.__('eBook', 'wp-user-frontend') },
{ id: 'edd_course', label: this.__('Online Course', 'wp-user-frontend') }
];

this.promptAIInstructions = {
edd_digital_download: 'Create an EDD Digital Download form with download title, download description, short description, price (edd_price), downloadable files (edd_download_files), featured image, download categories (download_category), download tags (download_tag)',
edd_software: 'Create an EDD Software Product form with download title, download description, price (edd_price), downloadable files (edd_download_files), product notes (edd_product_notes), featured image, download categories (download_category)',
edd_ebook: 'Create an EDD eBook form with download title, download description, short description, price (edd_price), downloadable files (edd_download_files), featured image, download categories (download_category), download tags (download_tag)',
edd_course: 'Create an EDD Online Course form with download title, download description, price (edd_price), downloadable files (edd_download_files), product notes (edd_product_notes), featured image, download categories (download_category)'
};
} else if (this.selectedIntegration === 'events_calendar') {
// The Events Calendar prompts
this.promptTemplates = [
{ id: 'event_conference', label: this.__('Conference Event', 'wp-user-frontend') },
{ id: 'event_workshop', label: this.__('Workshop/Training', 'wp-user-frontend') },
{ id: 'event_meetup', label: this.__('Meetup/Networking', 'wp-user-frontend') },
{ id: 'event_webinar', label: this.__('Webinar', 'wp-user-frontend') }
];

this.promptAIInstructions = {
event_conference: 'Create a Conference Event form with event title, event details, event start date (_EventStartDate), event end date (_EventEndDate), venue name (_EventVenueName), event address, event city, event cost (_EventCost), currency symbol (_EventCurrencySymbol), featured image, event categories (tribe_events_cat), event tags',
event_workshop: 'Create a Workshop/Training Event form with event title, event details, event start date (_EventStartDate), event end date (_EventEndDate), venue name (_EventVenueName), event address, event cost (_EventCost), featured image, event categories (tribe_events_cat)',
event_meetup: 'Create a Meetup/Networking Event form with event title, event details, short description, event start date (_EventStartDate), event end date (_EventEndDate), venue name (_EventVenueName), event address, event website (_EventURL), featured image, event categories (tribe_events_cat), event tags',
event_webinar: 'Create a Webinar Event form with event title, event details, event start date (_EventStartDate), event end date (_EventEndDate), event website (_EventURL), event cost (_EventCost), currency symbol (_EventCurrencySymbol), featured image, event categories (tribe_events_cat)'
};
} else {
// Default post form prompts (no integration selected)
this.promptTemplates = [
{ id: 'paid_guest_post', label: this.__('Paid Guest Post', 'wp-user-frontend') },
{ id: 'portfolio_submission', label: this.__('Portfolio Submission', 'wp-user-frontend') },
{ id: 'classified_ads', label: this.__('Classified Ads', 'wp-user-frontend') },
{ id: 'coupon_submission', label: this.__('Coupon Submission', 'wp-user-frontend') },
{ id: 'real_estate', label: this.__('Real Estate Property Listing', 'wp-user-frontend') },
{ id: 'news_press', label: this.__('News/Press Release Submission', 'wp-user-frontend') },
];

this.promptAIInstructions = {
paid_guest_post: 'Create a Paid Guest Post submission form with title, content, author name, email, category',
portfolio_submission: 'Create a Portfolio Submission form with title, description, name, email, skills, portfolio files',
classified_ads: 'Create a Classified Ads submission form with title, description, category, price, address field, contact email',
coupon_submission: 'Create a Coupon Submission form with title, description, business name, discount amount, expiration date',
real_estate: 'Create a Real Estate Property Listing form with title, description, address field, price, bedrooms, bathrooms, images',
news_press: 'Create a News/Press Release submission form with headline, content, author, contact email, category'
};
}
},

selectPrompt(tpl) {
this.selectedPrompt = tpl;
// Use the detailed AI instruction instead of just the template name
Expand All @@ -204,7 +366,8 @@ export default {

this.$emit('start-generation', {
description: this.formDescription,
selectedPrompt: this.selectedPrompt?.id || this.selectedPrompt || ''
selectedPrompt: this.selectedPrompt?.id || this.selectedPrompt || '',
integration: this.selectedIntegration
});
}
}
Expand Down
Loading
Loading