PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.0
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.0
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 2.1.15 2.1.16 2.1.2 All 57 releases
easy-invoice / templates / invoice-templates / classic.php

classic.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.4.0, at templates/invoice-templates/classic.php

578 lines 20.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Classic Template - Traditional Design
4 * Classic, traditional, and timeless invoice template
5 */
6
7 if ( ! defined( 'ABSPATH' ) ) {
8 exit;
9 }
10 $text_settings = \EasyInvoice\Helpers\TemplateTextHelper::forDocument(\EasyInvoice\Helpers\TemplateTextHelper::getInvoiceTextSettings(), $invoice);
11 $ei_is_credit_note = \EasyInvoice\Helpers\TemplateTextHelper::isCreditNote($invoice);
12 $company_info = \EasyInvoice\Helpers\TemplateTextHelper::getCompanyInfo();
13 ?>
14 <style>
15 /* Classic Template - Traditional Design */
16 :root {
17 --primary-color: #1f2937;
18 --primary-light: #374151;
19 --primary-dark: #111827;
20 --secondary-color: #6b7280;
21 --accent-color: #d97706;
22 --success-color: #059669;
23 --warning-color: #d97706;
24 --error-color: #dc2626;
25 --text-primary: #111827;
26 --text-secondary: #6b7280;
27 --text-muted: #9ca3af;
28 --border-color: #d1d5db;
29 --border-light: #e5e7eb;
30 --background-primary: #ffffff;
31 --background-secondary: #f9fafb;
32 --background-accent: #f3f4f6;
33
34 --font-family: 'Times New Roman', Times, serif;
35 --font-family-heading: 'Times New Roman', Times, serif;
36 --font-family-body: 'Times New Roman', Times, serif;
37
38 --font-size-xs: 0.75rem;
39 --font-size-sm: 0.875rem;
40 --font-size-base: 1rem;
41 --font-size-lg: 1.125rem;
42 --font-size-xl: 1.25rem;
43 --font-size-2xl: 1.5rem;
44 --font-size-3xl: 1.875rem;
45 --font-size-4xl: 2.25rem;
46
47 --spacing-1: 0.25rem;
48 --spacing-2: 0.5rem;
49 --spacing-3: 0.75rem;
50 --spacing-4: 1rem;
51 --spacing-5: 1.25rem;
52 --spacing-6: 1.5rem;
53 --spacing-8: 2rem;
54 --spacing-10: 2.5rem;
55 --spacing-12: 3rem;
56 --spacing-16: 4rem;
57 --spacing-20: 5rem;
58
59 --radius-sm: 0.25rem;
60 --radius-md: 0.375rem;
61 --radius-lg: 0.5rem;
62 --radius-xl: 0.75rem;
63 --radius-2xl: 1rem;
64
65 --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
66 --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
67 --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
68 --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
69 }
70
71 .template-classic {
72 font-family: var(--font-family-body);
73 background: var(--background-primary);
74 color: var(--text-primary);
75 max-width: 900px;
76 margin: 0 auto;
77 padding: var(--spacing-8);
78 line-height: 1.6;
79 border: 2px solid var(--border-color);
80 }
81
82 /* Header Section */
83 .template-classic .invoice-header {
84 display: flex;
85 justify-content: space-between;
86 align-items: flex-start;
87 margin-bottom: var(--spacing-12);
88 padding-bottom: var(--spacing-8);
89 border-bottom: 3px double var(--border-color);
90 }
91
92 .template-classic .company-info {
93 flex: 1;
94 }
95
96 .template-classic .company-logo {
97 margin-bottom: 0;
98 }
99
100 .template-classic .logo-image {
101 max-height: 60px;
102 max-width: 200px;
103 object-fit: contain;
104 filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.1));
105 }
106
107 .template-classic .company-name {
108 font-family: var(--font-family-heading);
109 font-size: var(--font-size-2xl);
110 font-weight: 700;
111 color: var(--text-primary);
112 margin-bottom: var(--spacing-3);
113 line-height: 1.2;
114 }
115
116 .template-classic .company-details {
117 color: var(--text-secondary);
118 font-size: var(--font-size-sm);
119 line-height: 1.5;
120 }
121
122 .template-classic .invoice-meta {
123 text-align: right;
124 min-width: 250px;
125 border: 1px solid var(--border-color);
126 padding: var(--spacing-4);
127 background: var(--background-secondary);
128 }
129
130 .template-classic .invoice-title {
131 font-family: var(--font-family-heading);
132 font-size: var(--font-size-xl);
133 font-weight: 700;
134 color: var(--text-primary);
135 margin-bottom: var(--spacing-4);
136 text-transform: uppercase;
137 letter-spacing: 0.1em;
138 border-bottom: 1px solid var(--border-color);
139 padding-bottom: var(--spacing-2);
140 }
141
142 .template-classic .meta-item {
143 display: flex;
144 justify-content: space-between;
145 align-items: center;
146 margin-bottom: var(--spacing-2);
147 padding-bottom: var(--spacing-2);
148 border-bottom: 1px solid var(--border-light);
149 }
150
151 .template-classic .meta-item:last-child {
152 margin-bottom: 0;
153 padding-bottom: 0;
154 border-bottom: none;
155 }
156
157 .template-classic .meta-label {
158 font-size: var(--font-size-sm);
159 color: var(--text-secondary);
160 font-weight: 600;
161 }
162
163 .template-classic .meta-value {
164 font-size: var(--font-size-sm);
165 color: var(--text-primary);
166 font-weight: 500;
167 }
168
169 /* Address Section */
170 .template-classic .address-section {
171 display: grid;
172 grid-template-columns: 1fr 1fr;
173 gap: var(--spacing-8);
174 margin-bottom: var(--spacing-12);
175 }
176
177 .template-classic .address-block {
178 border: 1px solid var(--border-color);
179 padding: var(--spacing-4);
180 background: var(--background-secondary);
181 }
182
183 .template-classic .address-block h2 {
184 font-family: var(--font-family-heading);
185 font-size: var(--font-size-base);
186 font-weight: 700;
187 color: var(--text-primary);
188 margin-bottom: var(--spacing-3);
189 text-transform: uppercase;
190 letter-spacing: 0.05em;
191 border-bottom: 1px solid var(--border-color);
192 padding-bottom: var(--spacing-2);
193 }
194
195 .template-classic .client-name {
196 font-weight: 600;
197 color: var(--text-primary);
198 font-size: var(--font-size-base);
199 margin-bottom: var(--spacing-2);
200 }
201
202 .template-classic .address-content {
203 color: var(--text-secondary);
204 font-size: var(--font-size-sm);
205 line-height: 1.5;
206 }
207
208 /* Invoice Items Table */
209 .template-classic .invoice-items {
210 width: 100%;
211 border-collapse: collapse;
212 margin-bottom: var(--spacing-12);
213 background: var(--background-primary);
214 border: 1px solid var(--border-color);
215 }
216
217 .template-classic .invoice-items th {
218 background: var(--primary-color);
219 color: white;
220 font-weight: 700;
221 text-align: left;
222 padding: var(--spacing-3) var(--spacing-4);
223 font-size: var(--font-size-sm);
224 text-transform: uppercase;
225 letter-spacing: 0.05em;
226 border: 1px solid var(--border-color);
227 }
228
229 .template-classic .invoice-items td {
230 padding: var(--spacing-3) var(--spacing-4);
231 border: 1px solid var(--border-color);
232 vertical-align: top;
233 }
234
235 .template-classic .item-name .item-title {
236 font-weight: 600;
237 color: var(--text-primary);
238 margin-bottom: var(--spacing-1);
239 }
240
241 .template-classic .item-description {
242 color: var(--text-muted);
243 font-size: var(--font-size-sm);
244 line-height: 1.4;
245 font-weight: normal;
246 }
247
248 .template-classic .item-quantity,
249 .template-classic .item-price,
250 .template-classic .item-total {
251 text-align: right;
252 font-weight: 500;
253 color: var(--text-primary);
254 }
255
256 /* Invoice Totals */
257 .template-classic .invoice-totals {
258 margin-left: auto;
259 width: 350px;
260 background: var(--background-secondary);
261 padding: var(--spacing-6);
262 border: 1px solid var(--border-color);
263 }
264
265 .template-classic .invoice-total-row {
266 display: flex;
267 justify-content: space-between;
268 align-items: center;
269 padding: var(--spacing-2) 0;
270 border-bottom: 1px solid var(--border-light);
271 }
272
273 .template-classic .invoice-total-row:last-child {
274 border-bottom: none;
275 }
276
277 .template-classic .invoice-total-label {
278 font-weight: 600;
279 color: var(--text-secondary);
280 }
281
282 .template-classic .invoice-total-value {
283 font-weight: 700;
284 color: var(--text-primary);
285 }
286
287 .template-classic .invoice-totals .invoice-grand-total {
288 font-size: var(--font-size-lg);
289 font-weight: 700;
290 color: var(--primary-color);
291 border-top: 2px solid var(--primary-color);
292 padding-top: var(--spacing-3);
293 margin-top: var(--spacing-3);
294 }
295
296 /* Notes Section */
297 .template-classic .invoice-notes {
298 margin-top: var(--spacing-8);
299 padding: var(--spacing-6);
300 background: var(--background-secondary);
301 border-radius: var(--radius-lg);
302 border: 1px solid var(--border-color);
303 }
304
305 .template-classic .invoice-notes h3 {
306 font-family: var(--font-family-heading);
307 font-size: var(--font-size-lg);
308 font-weight: 600;
309 color: var(--text-primary);
310 margin-bottom: var(--spacing-3);
311 border-bottom: 1px solid var(--border-color);
312 padding-bottom: var(--spacing-2);
313 }
314
315 .template-classic .notes-content {
316 color: var(--text-secondary);
317 font-size: var(--font-size-sm);
318 line-height: 1.6;
319 }
320
321 .template-classic .invoice-terms {
322 margin-top: var(--spacing-8);
323 padding: var(--spacing-6);
324 background: var(--background-secondary);
325 border-radius: var(--radius-lg);
326 border: 1px solid var(--border-color);
327 }
328
329 .template-classic .invoice-terms h3 {
330 font-family: var(--font-family-heading);
331 font-size: var(--font-size-lg);
332 font-weight: 600;
333 color: var(--text-primary);
334 margin-bottom: var(--spacing-3);
335 border-bottom: 1px solid var(--border-color);
336 padding-bottom: var(--spacing-2);
337 }
338
339 .template-classic .terms-content {
340 color: var(--text-secondary);
341 font-size: var(--font-size-sm);
342 line-height: 1.6;
343 }
344
345 .template-classic .invoice-footer {
346 margin-top: var(--spacing-8);
347 padding-top: var(--spacing-6);
348 border-top: 2px solid var(--border-light);
349 text-align: center;
350 color: var(--text-secondary);
351 font-size: var(--font-size-sm);
352 }
353
354 /* Footer */
355 .template-classic .invoice-footer {
356 margin-top: var(--spacing-12);
357 padding: var(--spacing-6);
358 text-align: center;
359 background: var(--primary-color);
360 color: white;
361 border: 1px solid var(--border-color);
362 }
363
364 .template-classic .invoice-footer p {
365 margin: 0;
366 font-size: var(--font-size-sm);
367 opacity: 0.9;
368 }
369
370 /* Responsive Design */
371 @media (max-width: 768px) {
372 .template-classic {
373 padding: var(--spacing-4);
374 }
375
376 .template-classic .invoice-header {
377 flex-direction: column;
378 gap: var(--spacing-6);
379 }
380
381 .template-classic .invoice-meta {
382 min-width: auto;
383 }
384
385 .template-classic .address-section {
386 grid-template-columns: 1fr;
387 gap: var(--spacing-6);
388 }
389
390 .template-classic .invoice-totals {
391 width: 100%;
392 }
393 }
394
395 /* Shared polish: numbers line up, numeric headings sit over their figures. */
396 .template-classic .invoice-items th + th { text-align: right; }
397 .template-classic .invoice-items .item-quantity,
398 .template-classic .invoice-items .item-price,
399 .template-classic .invoice-items .item-adjust,
400 .template-classic .invoice-items .item-total,
401 .template-classic .invoice-total-value { font-variant-numeric: tabular-nums; white-space: nowrap; }
402 .template-classic .meta-value { white-space: nowrap; }
403 .template-classic .invoice-items .item-adjust { text-align: right; }
404 .template-classic .client-contact { font-weight: 500; margin-bottom: 0.15em; }
405 .template-classic .client-tax-number,
406 .template-classic .company-tax-number { margin-top: 0.35em; }
407 .template-classic .invoice-items .item-description { white-space: pre-line; }
408 .template-classic .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; }
409
410 /* Classic: the ledger look — serif, a dark header row, rules instead of cell grids. */
411 .template-classic .invoice-items th, .template-classic .invoice-items td { border-left: 0; border-right: 0; }
412 .template-classic .invoice-items { border-left: 0; border-right: 0; border-top: 0; }
413 .template-classic .invoice-items th { padding: var(--spacing-3) var(--spacing-4); letter-spacing: 0.1em; font-size: var(--font-size-xs); }
414 .template-classic .invoice-items td { padding: var(--spacing-4); }
415 .template-classic .address-block { background: transparent; border: 0; padding: 0; }
416 .template-classic .address-block h2 { font-size: var(--font-size-xs); letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-muted); border-bottom: 1px solid var(--border-color); padding-bottom: var(--spacing-2); margin-bottom: var(--spacing-3); }
417 .template-classic .invoice-meta { background: transparent; border: 0; padding: 0; }
418 .template-classic .invoice-title { border-bottom: 2px solid var(--text-primary); }
419 .template-classic .invoice-totals { background: transparent; border: 0; padding: 0; width: 340px; }
420 .template-classic .invoice-total-row { border-bottom: 1px solid var(--border-light); padding: var(--spacing-2) 0; }
421 .template-classic .invoice-totals .invoice-grand-total { border-top: 2px solid var(--text-primary); border-bottom: 3px double var(--text-primary); color: var(--text-primary); padding: var(--spacing-3) 0; }
422 .template-classic .invoice-notes, .template-classic .invoice-terms { background: transparent; border: 0; border-top: 1px solid var(--border-color); border-radius: 0; padding: var(--spacing-5) 0 0; margin-top: var(--spacing-6); }
423 .template-classic .invoice-notes h3, .template-classic .invoice-terms h3 { border: 0; padding: 0; font-size: var(--font-size-base); margin-bottom: var(--spacing-2); }
424 .template-classic .invoice-footer { background: transparent; color: var(--text-secondary); border: 0; border-top: 1px solid var(--border-color); padding: var(--spacing-5) 0 0; margin-top: var(--spacing-8); font-style: italic; }
425 .template-classic .invoice-totals .invoice-paid-row .invoice-total-value { color: var(--success-color, #047857); }
426 .template-classic .invoice-totals .invoice-balance-due { font-weight: 700; }
427 .template-classic .invoice-totals .invoice-balance-due .invoice-total-label { color: inherit; font-weight: 700; }
428 .template-classic .meta-amount-due .meta-value { font-weight: 700; font-size: 1.08em; }
429 </style>
430
431 <div class="template template-classic">
432 <div class="invoice-header">
433 <div class="company-info">
434 <?php if (!empty($company_info['logo'])): ?>
435 <div class="company-logo">
436 <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)">
437 </div>
438 <?php endif; ?>
439 <div class="company-name"><?php echo esc_html($company_info['name']); ?></div>
440 <div class="company-details">
441 <?php echo wp_kses_post(\EasyInvoice\Helpers\TemplateTextHelper::generateFromSection($company_info, false, 'details-only')); ?>
442 </div>
443 </div>
444
445 <div class="invoice-meta">
446 <?php $ei_kind = \EasyInvoice\Helpers\TemplateTextHelper::documentKind($invoice); $ei_title = trim((string) $invoice->getTitle()); ?>
447 <div class="invoice-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>
448 <div class="meta-item">
449 <span class="meta-label"><?php echo esc_html($text_settings['invoice_number']); ?></span>
450 <span class="meta-value"><?php echo esc_html($invoice->getNumber()); ?></span>
451 </div>
452 <div class="meta-item">
453 <span class="meta-label"><?php echo esc_html($text_settings['invoice_date']); ?></span>
454 <span class="meta-value"><?php echo esc_html(\EasyInvoice\Controllers\SettingsController::formatDate($invoice->getIssueDate())); ?></span>
455 </div>
456 <?php if (empty($ei_is_credit_note)) : ?>
457 <div class="meta-item">
458 <span class="meta-label"><?php echo esc_html($text_settings['due_date']); ?></span>
459 <span class="meta-value"><?php echo esc_html(\EasyInvoice\Controllers\SettingsController::formatDate($invoice->getDueDate())); ?></span>
460 </div>
461 <?php endif; ?>
462 <?php if (empty($ei_is_credit_note)) : ?>
463 <div class="meta-item meta-amount-due">
464 <span class="meta-label"><?php echo esc_html($text_settings['total_due']); ?></span>
465 <span class="meta-value"><?php echo esc_html($formatter->format(\EasyInvoice\Helpers\TemplateTextHelper::amountDue($invoice))); ?></span>
466 </div>
467 <?php endif; ?>
468 </div>
469 </div>
470
471 <?php $ei_client_html = \EasyInvoice\Helpers\TemplateTextHelper::generateClientBlock($invoice); if ('' !== $ei_client_html) : ?>
472 <div class="address-section">
473 <div class="address-block">
474 <h2><?php echo esc_html($text_settings['to']); ?></h2>
475 <div class="address-content">
476 <?php echo wp_kses_post($ei_client_html); ?>
477 </div>
478 </div>
479 </div>
480 <?php endif; ?>
481
482 <?php
483 // The adjustment column appears only when at least one line uses it.
484 $ei_show_adjust = \EasyInvoice\Controllers\SettingsController::shouldShowInvoiceAdjustField();
485 if ($ei_show_adjust) {
486 $ei_show_adjust = false;
487 foreach ($invoice->getItems() as $ei_item) {
488 if ((float) $ei_item->getAdjustPercentage() != 0.0) { $ei_show_adjust = true; break; }
489 }
490 }
491 ?>
492 <table class="invoice-items">
493 <thead>
494 <tr>
495 <th><?php echo esc_html($text_settings['service']); ?></th>
496 <th><?php echo esc_html($text_settings['qty']); ?></th>
497 <th><?php echo esc_html($text_settings['rate_price']); ?></th>
498 <?php if ($ei_show_adjust): ?>
499 <th><?php echo esc_html($text_settings['adjust']); ?> (%)</th>
500 <?php endif; ?>
501 <th><?php echo esc_html($text_settings['line_total'] ?? $text_settings['total']); ?></th>
502 </tr>
503 </thead>
504 <tbody>
505 <?php if (!$invoice->getItems()) : ?>
506 <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>
507 <?php endif; ?>
508 <?php foreach ($invoice->getItems() as $item): ?>
509 <tr>
510 <td class="item-name">
511 <div class="item-title"><?php echo esc_html($item->getName()); ?></div>
512 <?php if ($item->getDescription()): ?>
513 <div class="item-description"><?php echo esc_html($item->getDescription()); ?></div>
514 <?php endif; ?>
515 </td>
516 <td class="item-quantity"><?php echo esc_html($item->getQuantity() ?: '0'); ?></td>
517 <td class="item-price"><?php echo esc_html($formatter->format($item->getPrice())); ?></td>
518 <?php if ($ei_show_adjust): ?>
519 <td class="item-adjust"><?php
520 $adjust_percentage = $item->getAdjustPercentage();
521 if ($adjust_percentage != 0) {
522 echo esc_html($adjust_percentage > 0 ? '+' : '') . esc_html($adjust_percentage) . '%';
523 } else {
524 echo esc_html__('—', 'easy-invoice');
525 }
526 ?></td>
527 <?php endif; ?>
528 <td class="item-total"><?php echo esc_html($formatter->format($item->getAmount())); ?></td>
529 </tr>
530 <?php endforeach; ?>
531 </tbody>
532 </table>
533
534 <div class="invoice-totals">
535 <?php echo wp_kses_post(\EasyInvoice\Helpers\TemplateTextHelper::generateTotalsSection($invoice, $text_settings, $formatter, 'invoice')); ?>
536 </div>
537
538 <?php if ($invoice->getNotes()): ?>
539 <div class="invoice-notes">
540 <h3><?php esc_html_e('Notes', 'easy-invoice'); ?></h3>
541 <div class="notes-content">
542 <?php echo wp_kses_post($invoice->getNotes() ?: ''); ?>
543 </div>
544 </div>
545 <?php endif; ?>
546
547 <?php
548 $terms_conditions = empty($ei_is_credit_note) ? ($invoice->getTerms() ?: \EasyInvoice\Controllers\SettingsController::getInvoiceTermsConditions()) : '';
549 if ($terms_conditions):
550 ?>
551 <div class="invoice-terms">
552 <h3><?php esc_html_e('Terms & Conditions', 'easy-invoice'); ?></h3>
553 <div class="terms-content">
554 <?php echo wp_kses_post($terms_conditions); ?>
555 </div>
556 </div>
557 <?php endif; ?>
558
559 <?php
560 /**
561 * Fires inside the document card, after notes and terms and before the
562 * footer text: attachments, the signature block, e-invoicing notes. Being
563 * inside the card, it is part of what "Download as PDF" captures.
564 *
565 * @param object $document The invoice model.
566 * @param string $type 'invoice'.
567 */
568 do_action('easy_invoice_document_body_after', $invoice, 'invoice');
569
570 $ei_footer_text = \EasyInvoice\Helpers\TemplateTextHelper::footerText($invoice, 'invoice');
571 if ('' !== trim(wp_strip_all_tags((string) $ei_footer_text))) :
572 ?>
573 <div class="invoice-footer">
574 <p><?php echo wp_kses_post($ei_footer_text); ?></p>
575 </div>
576 <?php endif; ?>
577 </div>
578