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 | templates/quote-templates/minimal.php +82 -35 2.1.13 → 2.4.2 View file →
@@ -3,8 +3,11 @@
3 3 * Minimal Quote Template - Clean & Simple Design
4 4 * Minimal, clean, and simple quote template
5 5 */
6 6
7 +if ( ! defined( 'ABSPATH' ) ) {
8 + exit;
9 +}
7 10 $text_settings = \EasyInvoice\Helpers\TemplateTextHelper::getQuoteTextSettings();
8 11 $company_info = \EasyInvoice\Helpers\TemplateTextHelper::getCompanyInfo();
9 12 ?>
10 13 <style>
@@ -273,9 +276,9 @@
273 276 font-weight: 600;
274 277 color: var(--text-primary);
275 278 }
276 279
277 -.template-minimal .quote-grand-total {
280 +.template-minimal .quote-totals .quote-grand-total {
278 281 font-size: var(--font-size-lg);
279 282 font-weight: 700;
280 283 color: var(--text-primary);
281 284 border-top: 2px solid var(--border-color);
@@ -366,27 +369,59 @@
366 369 .template-minimal .quote-totals {
367 370 width: 100%;
368 371 }
369 372 }
373 +
374 +/* Shared polish: numbers line up, numeric headings sit over their figures. */
375 +.template-minimal .quote-items th + th { text-align: right; }
376 +.template-minimal .quote-items .item-quantity,
377 +.template-minimal .quote-items .item-price,
378 +.template-minimal .quote-items .item-adjust,
379 +.template-minimal .quote-items .item-total,
380 +.template-minimal .quote-total-value { font-variant-numeric: tabular-nums; white-space: nowrap; }
381 +.template-minimal .meta-value { white-space: nowrap; }
382 +.template-minimal .quote-items .item-adjust { text-align: right; }
383 +.template-minimal .client-contact { font-weight: 500; margin-bottom: 0.15em; }
384 +.template-minimal .client-tax-number,
385 +.template-minimal .company-tax-number { margin-top: 0.35em; }
386 +.template-minimal .quote-items .item-description { white-space: pre-line; }
387 +.template-minimal .document-kind { display: block; font-size: 0.72rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-muted, #8a8a8a); font-family: var(--font-family-body, inherit); font-style: normal; margin-bottom: 0.3em; line-height: 1.2; }
388 +
389 +/* Minimal: hairlines only — no filled panels anywhere. */
390 +.template-minimal .quote-header { margin-bottom: var(--spacing-8); padding-bottom: var(--spacing-6); border-bottom: 1px solid var(--border-color); }
391 +.template-minimal .address-section { margin-bottom: var(--spacing-8); }
392 +.template-minimal .address-block h2 { font-size: var(--font-size-xs); text-transform: uppercase; letter-spacing: 0.14em; color: var(--text-muted); font-weight: 600; margin-bottom: var(--spacing-2); }
393 +.template-minimal .quote-items { border: 0; margin-bottom: var(--spacing-6); }
394 +.template-minimal .quote-items th { background: transparent; color: var(--text-muted); font-size: var(--font-size-xs); text-transform: uppercase; letter-spacing: 0.12em; padding: var(--spacing-2) var(--spacing-3); border-bottom: 1px solid var(--text-primary); }
395 +.template-minimal .quote-items td { padding: var(--spacing-4) var(--spacing-3); }
396 +.template-minimal .quote-items th:first-child, .template-minimal .quote-items td:first-child { padding-left: 0; }
397 +.template-minimal .quote-items th:last-child, .template-minimal .quote-items td:last-child { padding-right: 0; }
398 +.template-minimal .quote-totals { background: transparent; border: 0; padding: 0; width: 320px; }
399 +.template-minimal .quote-total-row { padding: var(--spacing-2) 0; border-bottom: 1px solid var(--border-light); }
400 +.template-minimal .quote-totals .quote-grand-total { border-top: 1px solid var(--text-primary); border-bottom: 0; margin-top: var(--spacing-1); padding-top: var(--spacing-3); font-size: var(--font-size-lg); }
401 +.template-minimal .quote-totals .quote-grand-total .quote-total-value { font-size: var(--font-size-xl); }
402 +.template-minimal .quote-notes, .template-minimal .quote-terms { background: transparent; border: 0; border-top: 1px solid var(--border-light); border-radius: 0; padding: var(--spacing-5) 0 0; margin-top: var(--spacing-6); }
403 +.template-minimal .quote-notes h3, .template-minimal .quote-terms h3 { font-size: var(--font-size-xs); text-transform: uppercase; letter-spacing: 0.14em; color: var(--text-muted); font-weight: 600; margin-bottom: var(--spacing-2); border: 0; padding: 0; }
404 +.template-minimal .quote-footer { background: transparent; border: 0; border-top: 1px solid var(--border-light); padding: var(--spacing-4) 0 0; margin-top: var(--spacing-8); color: var(--text-muted); font-size: var(--font-size-sm); }
370 405 </style>
371 406
372 407 <div class="template template-minimal">
373 - <!-- Header -->
374 408 <div class="quote-header">
375 409 <div class="company-info">
410 + <?php if (!empty($company_info['logo'])): ?>
376 411 <div class="company-logo">
377 - <?php if (!empty($company_info['logo'])): ?>
378 - <img src="<?php echo esc_url($company_info['logo']); ?>" alt="<?php echo esc_attr($company_info['name']); ?>" class="logo-image">
379 - <?php endif; ?>
412 + <img src="<?php echo esc_url($company_info['logo']); ?>" alt="<?php echo esc_attr($company_info['name']); ?>" class="logo-image" onerror="this.parentNode.parentNode.removeChild(this.parentNode)">
380 413 </div>
414 + <?php endif; ?>
381 415 <div class="company-name"><?php echo esc_html($company_info['name']); ?></div>
382 416 <div class="company-details">
383 - <?php echo \EasyInvoice\Helpers\TemplateTextHelper::generateFromSection($company_info, false, 'details-only'); ?>
417 + <?php echo wp_kses_post(\EasyInvoice\Helpers\TemplateTextHelper::generateFromSection($company_info, false, 'details-only')); ?>
384 418 </div>
385 419 </div>
386 420
387 421 <div class="quote-meta">
388 - <div class="quote-title"><?php echo esc_html($quote->getTitle() ?: __('Quote', 'easy-invoice')); ?></div>
422 + <?php $ei_kind = \EasyInvoice\Controllers\SettingsController::getTextQuote(); $ei_title = trim((string) $quote->getTitle()); ?>
423 + <div class="quote-title"><?php if ('' !== $ei_title && 0 !== strcasecmp($ei_title, $ei_kind)) : ?><span class="document-kind"><?php echo esc_html($ei_kind); ?></span><?php endif; ?><?php echo esc_html('' !== $ei_title ? $ei_title : $ei_kind); ?></div>
389 424 <div class="meta-item">
390 425 <span class="meta-label"><?php echo esc_html($text_settings['quote_number']); ?></span>
391 426 <span class="meta-value"><?php echo esc_html($quote->getNumber()); ?></span>
392 427 </div>
@@ -400,25 +435,19 @@
400 435 </div>
401 436 </div>
402 437 </div>
403 438
404 - <!-- Address Section -->
439 + <?php $ei_client_html = \EasyInvoice\Helpers\TemplateTextHelper::generateClientBlock($quote); if ('' !== $ei_client_html) : ?>
405 440 <div class="address-section">
406 441 <div class="address-block">
407 442 <h2><?php echo esc_html($text_settings['to']); ?></h2>
408 443 <div class="address-content">
409 - <div class="client-name"><?php echo esc_html($quote->getCustomerName()); ?></div>
410 - <?php if ($quote->getCustomerAddress()): ?>
411 - <?php echo nl2br(esc_html($quote->getCustomerAddress())); ?><br>
412 - <?php endif; ?>
413 - <?php if ($quote->getCustomerEmail()): ?>
414 - <?php echo esc_html($quote->getCustomerEmail()); ?><br>
415 - <?php endif; ?>
444 + <?php echo wp_kses_post($ei_client_html); ?>
416 445 </div>
417 446 </div>
418 447 </div>
448 + <?php endif; ?>
419 449
420 - <!-- Quote Description -->
421 450 <?php if ($quote->getDescription()): ?>
422 451 <div class="quote-description">
423 452 <div class="description-content"><?php echo wp_kses_post($quote->getDescription()); ?></div>
424 453 </div>
@@ -423,9 +452,18 @@
423 452 <div class="description-content"><?php echo wp_kses_post($quote->getDescription()); ?></div>
424 453 </div>
425 454 <?php endif; ?>
426 455
427 - <!-- Quote Items -->
456 + <?php
457 + // The adjustment column appears only when at least one line uses it.
458 + $ei_show_adjust = \EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField();
459 + if ($ei_show_adjust) {
460 + $ei_show_adjust = false;
461 + foreach ($quote->getItems() as $ei_item) {
462 + if ((float) $ei_item->getAdjustPercentage() != 0.0) { $ei_show_adjust = true; break; }
463 + }
464 + }
465 + ?>
428 466 <table class="quote-items">
429 467 <thead>
430 468 <tr>
431 469 <th><?php echo esc_html($text_settings['service']); ?></th>
@@ -430,15 +468,18 @@
430 468 <tr>
431 469 <th><?php echo esc_html($text_settings['service']); ?></th>
432 470 <th><?php echo esc_html($text_settings['qty']); ?></th>
433 471 <th><?php echo esc_html($text_settings['rate_price']); ?></th>
434 - <?php if (\EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField()): ?>
472 + <?php if ($ei_show_adjust): ?>
435 473 <th><?php echo esc_html($text_settings['adjust']); ?> (%)</th>
436 474 <?php endif; ?>
437 - <th><?php echo esc_html($text_settings['total']); ?></th>
475 + <th><?php echo esc_html($text_settings['line_total'] ?? $text_settings['total']); ?></th>
438 476 </tr>
439 477 </thead>
440 478 <tbody>
479 + <?php if (!$quote->getItems()) : ?>
480 + <tr class="no-items"><td colspan="<?php echo $ei_show_adjust ? 5 : 4; ?>" style="text-align:center;color:#9ca3af;padding:18px;"><?php esc_html_e('No items yet.', 'easy-invoice'); ?></td></tr>
481 + <?php endif; ?>
441 482 <?php foreach ($quote->getItems() as $item): ?>
442 483 <tr>
443 484 <td class="item-name">
444 485 <div class="item-title"><?php echo esc_html($item->getName()); ?></div>
@@ -447,9 +488,9 @@
447 488 <?php endif; ?>
448 489 </td>
449 490 <td class="item-quantity"><?php echo esc_html($item->getQuantity() ?: '0'); ?></td>
450 491 <td class="item-price"><?php echo esc_html((isset($formatter) && $formatter) ? $formatter->format($item->getPrice()) : (new \EasyInvoice\Helpers\QuoteFormatter($quote))->format($item->getPrice())); ?></td>
451 - <?php if (\EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField()): ?>
492 + <?php if ($ei_show_adjust): ?>
452 493 <td class="item-adjust"><?php
453 494 $adjust_percentage = $item->getAdjustPercentage();
454 495 if ($adjust_percentage != 0) {
455 496 echo esc_html($adjust_percentage > 0 ? '+' : '') . esc_html($adjust_percentage) . '%';
@@ -463,9 +504,8 @@
463 504 <?php endforeach; ?>
464 505 </tbody>
465 506 </table>
466 507
467 - <!-- Quote Totals -->
468 508 <div class="quote-totals">
469 509 <?php
470 510 // Ensure we have a formatter
471 511 if (!isset($formatter) || !$formatter) {
@@ -470,15 +510,15 @@
470 510 // Ensure we have a formatter
471 511 if (!isset($formatter) || !$formatter) {
472 512 $formatter = new \EasyInvoice\Helpers\QuoteFormatter($quote);
473 513 }
474 - echo \EasyInvoice\Helpers\TemplateTextHelper::generateTotalsSection($quote, $text_settings, $formatter, 'quote');
514 + echo wp_kses_post(\EasyInvoice\Helpers\TemplateTextHelper::generateTotalsSection($quote, $text_settings, $formatter, 'quote'));
475 515 ?>
516 + </div>
476 517
477 - <!-- Notes -->
478 518 <?php if ($quote->getNotes()): ?>
479 519 <div class="quote-notes">
480 - <h3><?php _e('Notes:', 'easy-invoice'); ?></h3>
520 + <h3><?php esc_html_e('Notes', 'easy-invoice'); ?></h3>
481 521 <div class="notes-content">
482 522 <?php echo wp_kses_post($quote->getNotes() ?: ''); ?>
483 523 </div>
484 524 </div>
@@ -483,15 +523,14 @@
483 523 </div>
484 524 </div>
485 525 <?php endif; ?>
486 526
487 - <!-- Terms and Conditions -->
488 527 <?php
489 528 $terms_conditions = $quote->getTerms() ?: \EasyInvoice\Controllers\SettingsController::getQuoteTermsConditions();
490 529 if ($terms_conditions):
491 530 ?>
492 531 <div class="quote-terms">
493 - <h3><?php _e('Terms & Conditions:', 'easy-invoice'); ?></h3>
532 + <h3><?php esc_html_e('Terms & Conditions', 'easy-invoice'); ?></h3>
494 533 <div class="terms-content">
495 534 <?php echo wp_kses_post($terms_conditions); ?>
496 535 </div>
497 536 </div>
@@ -496,15 +535,23 @@
496 535 </div>
497 536 </div>
498 537 <?php endif; ?>
499 538
500 - <!-- Footer -->
539 + <?php
540 + /**
541 + * Fires inside the document card, after notes and terms and before the
542 + * footer text: attachments, the signature block, e-invoicing notes. Being
543 + * inside the card, it is part of what "Download as PDF" captures.
544 + *
545 + * @param object $document The quote model.
546 + * @param string $type 'quote'.
547 + */
548 + do_action('easy_invoice_document_body_after', $quote, 'quote');
549 +
550 + $ei_footer_text = \EasyInvoice\Helpers\TemplateTextHelper::footerText($quote, 'quote');
551 + if ('' !== trim(wp_strip_all_tags((string) $ei_footer_text))) :
552 + ?>
501 553 <div class="quote-footer">
502 - <?php
503 - $footer_text = $quote->getFooterText();
504 - if (!$footer_text) {
505 - $footer_text = \EasyInvoice\Controllers\SettingsController::getQuoteFooterText();
506 - }
507 - ?>
508 - <p><?php echo wp_kses_post($footer_text); ?></p>
554 + <p><?php echo wp_kses_post($ei_footer_text); ?></p>
509 555 </div>
510 -</div>
556 + <?php endif; ?>
557 +</div>