PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.2
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.2
2.4.3 2.4.4 2.4.2 2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 All 60 releases
← All changes | assets/js/invoice-form.js +108 -0 2.1.0 → 2.4.2 View file →
@@ -378,5 +378,113 @@
378 378 // Update the visual state - ensure only the new template is selected
379 379 $mainGrid.find('.template-card').removeClass('selected');
380 380 $mainGrid.find('.template-card[data-template-id="' + templateId + '"]').addClass('selected');
381 381 }
382 +
383 + // Save to Item Library functionality
384 + $(document).on('click', '.save-to-library-btn', function(e) {
385 + e.preventDefault();
386 +
387 + var $btn = $(this);
388 + var itemIndex = $btn.data('item-index');
389 + // Find the closest item container (either invoice-item or quote-item)
390 + var $itemContainer = $btn.closest('.invoice-item, .quote-item');
391 +
392 + if (!$itemContainer.length) {
393 + return;
394 + }
395 +
396 + // Get item data from the form
397 + var itemData = {
398 + title: '',
399 + description: '',
400 + price: 0,
401 + quantity: 0,
402 + taxable: 0
403 + };
404 +
405 + // Extract data from the item fields
406 + $itemContainer.find('input, textarea, select').each(function() {
407 + var $field = $(this);
408 + var name = $field.attr('name');
409 + var value = $field.val();
410 + var type = $field.attr('type');
411 +
412 + if (name) {
413 + // Handle array names like items[0][title] or quote_items[0][title]
414 + var matches = name.match(/(items|quote_items)\[\d+\]\[(.+)\]/);
415 + if (matches && matches[2]) {
416 + if (type === 'checkbox' || type === 'radio') {
417 + itemData[matches[2]] = $field.is(':checked') ? 1 : 0;
418 + } else {
419 + itemData[matches[2]] = value;
420 + }
421 + }
422 + }
423 + });
424 +
425 + // Convert numeric fields
426 + itemData.price = parseFloat(itemData.price) || 0;
427 + itemData.quantity = parseInt(itemData.quantity) || 0;
428 + itemData.taxable = parseInt(itemData.taxable) || 0;
429 +
430 + // Validate required fields
431 + if (!itemData.title || !itemData.title.trim()) {
432 + if (typeof EasyInvoiceToast !== 'undefined') {
433 + EasyInvoiceToast.error('Please fill in item title before saving to library');
434 + } else {
435 + alert('Please fill in item title before saving to library');
436 + }
437 + return;
438 + }
439 +
440 + if (!itemData.price || itemData.price <= 0) {
441 + if (typeof EasyInvoiceToast !== 'undefined') {
442 + EasyInvoiceToast.error('Please fill in item price before saving to library');
443 + } else {
444 + alert('Please fill in item price before saving to library');
445 + }
446 + return;
447 + }
448 +
449 + // Show loading state
450 + var originalHtml = $btn.html();
451 + $btn.html('<i class="fas fa-spinner fa-spin"></i>').prop('disabled', true);
452 +
453 + // AJAX call to save to item library
454 + $.ajax({
455 + url: ajaxurl,
456 + type: 'POST',
457 + data: {
458 + action: 'easy_invoice_pro_add_item',
459 + nonce: $btn.data('nonce'),
460 + item_data: JSON.stringify(itemData)
461 + },
462 + success: function(response) {
463 + if (response.success) {
464 + if (typeof EasyInvoiceToast !== 'undefined') {
465 + EasyInvoiceToast.success('Item saved to library successfully!');
466 + } else {
467 + alert('Item saved to library successfully!');
468 + }
469 + } else {
470 + if (typeof EasyInvoiceToast !== 'undefined') {
471 + EasyInvoiceToast.error(response.data.message || 'Failed to save item');
472 + } else {
473 + alert('Failed to save item: ' + (response.data.message || 'Unknown error'));
474 + }
475 + }
476 + },
477 + error: function() {
478 + if (typeof EasyInvoiceToast !== 'undefined') {
479 + EasyInvoiceToast.error('Error saving item to library');
480 + } else {
481 + alert('Error saving item to library');
482 + }
483 + },
484 + complete: function() {
485 + // Restore button
486 + $btn.html(originalHtml).prop('disabled', false);
487 + }
488 + });
489 + });
382 490 });