PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.2.0
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.2.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 / quote-templates / modern.php

modern.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.2.0, at templates/quote-templates/modern.php

529 lines 20.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Modern Quote Template (Refactored to Minimal style)
4 * This file reuses the Minimal template structure and styling
5 */
6
7 $text_settings = \EasyInvoice\Helpers\TemplateTextHelper::getQuoteTextSettings();
8 $company_info = \EasyInvoice\Helpers\TemplateTextHelper::getCompanyInfo();
9 // Ensure a formatter is available
10 if (!isset($formatter) || !$formatter) {
11 $formatter = new \EasyInvoice\Helpers\QuoteFormatter($quote ?? null);
12 }
13 ?>
14 <style>
15 /* Minimal-inspired Modern Template (blue accent only) */
16 :root {
17 --primary-color: #2563eb; /* blue-600 */
18 --primary-light: #3b82f6; /* blue-500 */
19 --primary-dark: #1e40af; /* blue-800 */
20 --secondary-color: #9ca3af;
21 --accent-color: #2563eb;
22 --success-color: #10b981;
23 --warning-color: #f59e0b;
24 --error-color: #ef4444;
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: #eef2ff; /* subtle blue tint */
33 --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
34 --font-family-heading: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
35 --font-size-xs: 0.75rem; --font-size-sm: 0.875rem; --font-size-base: 1rem; --font-size-lg: 1.125rem; --font-size-xl: 1.25rem; --font-size-2xl: 1.5rem; --font-size-3xl: 1.875rem; --font-size-4xl: 2.25rem;
36 --spacing-1: 0.25rem; --spacing-2: 0.5rem; --spacing-3: 0.75rem; --spacing-4: 1rem; --spacing-5: 1.25rem; --spacing-6: 1.5rem; --spacing-8: 2rem; --spacing-10: 2.5rem; --spacing-12: 3rem; --spacing-16: 4rem; --spacing-20: 5rem;
37 --radius-sm: 0.25rem; --radius-md: 0.375rem; --radius-lg: 0.5rem; --radius-xl: 0.75rem; --radius-2xl: 1rem;
38 --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
39 }
40
41 .template-modern { font-family: var(--font-family); background: var(--background-primary); color: var(--text-primary); max-width: 800px; margin: 0 auto; padding: var(--spacing-8); line-height: 1.6; }
42 .template-modern .quote-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--spacing-12); padding-bottom: var(--spacing-8); border-bottom: 1px solid var(--border-light); }
43 .template-modern .company-info { flex: 1; }
44 .template-modern .company-logo { margin-bottom: 0; }
45 .template-modern .logo-image { max-height: 60px; max-width: 200px; object-fit: contain; filter: drop-shadow(0 2px 4px rgba(0,0,0,0.1)); }
46 .template-modern .company-name { font-family: var(--font-family-heading); font-size: var(--font-size-2xl); font-weight: 700; color: var(--text-primary); margin-bottom: var(--spacing-3); line-height: 1.2; }
47 .template-modern .company-details { color: var(--text-secondary); font-size: var(--font-size-sm); line-height: 1.5; }
48 .template-modern .quote-meta { text-align: right; min-width: 200px; }
49 .template-modern .quote-title { font-family: var(--font-family-heading); font-size: var(--font-size-2xl); font-weight: 700; color: var(--text-primary); margin-bottom: var(--spacing-2); }
50 .template-modern .meta-item { color: var(--text-secondary); font-size: var(--font-size-sm); }
51 .template-modern .meta-value { color: var(--text-primary); font-weight: 600; }
52 .template-modern .address-section { display: grid; grid-template-columns: 1fr 1fr; gap: var(--spacing-8); margin-bottom: var(--spacing-12); }
53 .template-modern .address-block h2 { font-family: var(--font-family-heading); font-size: var(--font-size-lg); font-weight: 600; color: var(--text-primary); margin-bottom: var(--spacing-4); text-transform: uppercase; letter-spacing: 0.05em; }
54 .template-modern .client-name { font-weight: 600; color: var(--text-primary); font-size: var(--font-size-base); margin-bottom: var(--spacing-2); }
55 .template-modern .address-content { color: var(--text-secondary); font-size: var(--font-size-sm); line-height: 1.5; }
56 .template-modern .quote-items { width: 100%; border-collapse: separate; border-spacing: 0; margin-bottom: var(--spacing-12); }
57 .template-modern .quote-items th { background: var(--background-secondary); color: var(--text-secondary); font-weight: 600; text-align: left; padding: var(--spacing-4) var(--spacing-5); font-size: var(--font-size-sm); text-transform: uppercase; letter-spacing: 0.05em; border-top: 1px solid var(--border-light); border-bottom: 1px solid var(--border-light); }
58 .template-modern .quote-items td { padding: var(--spacing-4) var(--spacing-5); border-bottom: 1px solid var(--border-light); vertical-align: top; }
59 .template-modern .item-name .item-title { font-weight: 600; color: var(--text-primary); margin-bottom: var(--spacing-1); }
60 .template-modern .item-description { color: var(--text-muted); font-size: var(--font-size-sm); line-height: 1.4; }
61 .template-modern .item-quantity, .template-modern .item-price, .template-modern .item-total { text-align: right; font-weight: 500; color: var(--text-primary); }
62 .template-modern .quote-totals { margin-left: auto; width: 360px; background: var(--background-secondary); padding: var(--spacing-6); border-radius: var(--radius-lg); border: 1px solid var(--border-color); }
63 .template-modern .quote-total-row { display: flex; justify-content: space-between; align-items: center; padding: var(--spacing-3) 0; border-bottom: 1px solid var(--border-light); }
64 .template-modern .quote-total-row:last-child { border-bottom: none; }
65 .template-modern .quote-total-label { font-weight: 500; color: var(--text-secondary); }
66 .template-modern .quote-total-value { font-weight: 600; color: var(--text-primary); }
67 .template-modern .quote-grand-total { font-size: var(--font-size-xl); font-weight: 700; color: var(--text-primary); border-top: 2px solid var(--border-light); padding-top: var(--spacing-4); margin-top: var(--spacing-4); }
68 .template-modern .quote-notes { margin-top: var(--spacing-12); padding: var(--spacing-6); background: var(--background-accent); border-radius: var(--radius-lg); border-left: 4px solid var(--primary-color); }
69 .template-modern .quote-terms { margin-top: var(--spacing-12); padding: var(--spacing-6); background: var(--background-secondary); border-radius: var(--radius-lg); border: 1px solid var(--border-color); }
70 .template-modern .quote-footer { margin-top: var(--spacing-12); padding: var(--spacing-6); text-align: center; background: var(--background-secondary); border-radius: var(--radius-lg); border: 1px solid var(--border-color); }
71 @media (max-width: 768px) { .template-modern { padding: var(--spacing-4);} .template-modern .quote-header { flex-direction: column; gap: var(--spacing-4);} .template-modern .address-section { grid-template-columns: 1fr; gap: var(--spacing-6);} .template-modern .quote-totals { width: 100%; } }
72
73 .template-modern .company-info {
74 display: flex;
75 flex-direction: column;
76 gap: var(--spacing-4);
77 }
78
79 .template-modern .company-logo {
80 margin-bottom: 0;
81 }
82
83 .template-modern .logo-image {
84 max-height: 60px;
85 max-width: 200px;
86 object-fit: contain;
87 filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.15));
88 }
89
90 .template-modern .company-name {
91 font-family: var(--font-family-heading);
92 font-size: var(--font-size-2xl);
93 font-weight: 700;
94 color: var(--text-primary);
95 margin-bottom: var(--spacing-3);
96 line-height: 1.2;
97 }
98
99 .template-modern .company-details {
100 color: var(--text-secondary);
101 font-size: var(--font-size-sm);
102 line-height: 1.5;
103 }
104
105 .template-modern .quote-meta {
106 display: flex;
107 flex-direction: column;
108 gap: var(--spacing-4);
109 background: var(--background-primary);
110 padding: var(--spacing-6);
111 border-radius: var(--radius-lg);
112 border: 1px solid var(--border-color);
113 box-shadow: var(--shadow-md);
114 min-width: 300px;
115 }
116
117 .template-modern .quote-title {
118 font-family: var(--font-family-heading);
119 font-size: var(--font-size-2xl);
120 font-weight: 700;
121 color: var(--primary-color);
122 margin-bottom: var(--spacing-4);
123 text-align: center;
124 text-transform: uppercase;
125 letter-spacing: -0.025em;
126 }
127
128 .template-modern .meta-item {
129 display: flex;
130 justify-content: space-between;
131 align-items: center;
132 padding: var(--spacing-3) 0;
133 border-bottom: 1px solid var(--border-light);
134 }
135
136 .template-modern .meta-item:last-child {
137 border-bottom: none;
138 }
139
140 .template-modern .meta-label {
141 font-size: var(--font-size-sm);
142 color: var(--text-secondary);
143 font-weight: 500;
144 }
145
146 .template-modern .meta-value {
147 font-size: var(--font-size-base);
148 color: var(--text-primary);
149 font-weight: 600;
150 }
151
152 /* Address Section */
153 .template-modern .address-section {
154 display: grid;
155 grid-template-columns: 1fr 1fr;
156 gap: var(--spacing-8);
157 margin-bottom: var(--spacing-12);
158 }
159
160 .template-modern .address-block {
161 background: var(--background-secondary);
162 padding: var(--spacing-6);
163 border-radius: var(--radius-lg);
164 border: 1px solid var(--border-color);
165 position: relative;
166 overflow: hidden;
167 }
168
169 .template-modern .address-block::before {
170 content: '';
171 position: absolute;
172 top: 0;
173 left: 0;
174 right: 0;
175 height: 3px;
176 background: var(--primary-color);
177 }
178
179 .template-modern .address-block h2 {
180 font-family: var(--font-family-heading);
181 font-size: var(--font-size-lg);
182 font-weight: 600;
183 color: var(--text-primary);
184 margin-bottom: var(--spacing-4);
185 text-transform: uppercase;
186 letter-spacing: 0.05em;
187 }
188
189 .template-modern .client-name {
190 font-weight: 600;
191 color: var(--text-primary);
192 font-size: var(--font-size-base);
193 margin-bottom: var(--spacing-2);
194 }
195
196 .template-modern .address-content {
197 color: var(--text-secondary);
198 font-size: var(--font-size-sm);
199 line-height: 1.5;
200 }
201
202 /* Quote Items Table */
203 .template-modern .quote-items {
204 width: 100%;
205 border-collapse: separate;
206 border-spacing: 0;
207 margin-bottom: var(--spacing-12);
208 background: var(--background-primary);
209 border-radius: var(--radius-xl);
210 overflow: hidden;
211 box-shadow: var(--shadow-xl);
212 border: 1px solid var(--border-color);
213 }
214
215 .template-modern .quote-items th {
216 background: linear-gradient(135deg, var(--primary-light), var(--primary-color));
217 color: white;
218 font-weight: 600;
219 text-align: left;
220 padding: var(--spacing-5) var(--spacing-6);
221 font-size: var(--font-size-sm);
222 text-transform: uppercase;
223 letter-spacing: 0.05em;
224 }
225
226 .template-modern .quote-items td {
227 padding: var(--spacing-5) var(--spacing-6);
228 border-bottom: 1px solid var(--border-light);
229 vertical-align: top;
230 }
231
232 .template-modern .quote-items tr:last-child td {
233 border-bottom: none;
234 }
235
236 .template-modern .quote-items tr:hover {
237 background: var(--background-accent);
238 }
239
240 .template-modern .item-name .item-title {
241 font-weight: 600;
242 color: var(--text-primary);
243 margin-bottom: var(--spacing-1);
244 }
245
246 .template-modern .item-description {
247 color: var(--text-muted);
248 font-size: var(--font-size-sm);
249 line-height: 1.4;
250 font-weight: normal;
251 }
252
253 .template-modern .item-quantity,
254 .template-modern .item-price,
255 .template-modern .item-total {
256 text-align: right;
257 font-weight: 500;
258 color: var(--text-primary);
259 }
260
261 /* Quote Totals */
262 .template-modern .quote-totals {
263 margin-left: auto;
264 width: 420px;
265 background: #ffffff;
266 padding: var(--spacing-8);
267 border-radius: var(--radius-xl);
268 border: 1px solid var(--border-color);
269 box-shadow: var(--shadow-lg);
270 position: relative;
271 }
272
273 .template-modern .quote-totals::before { display: none; }
274
275 .template-modern .quote-total-row {
276 display: flex;
277 justify-content: space-between;
278 align-items: center;
279 padding: var(--spacing-3) 0;
280 border-bottom: 1px solid var(--border-light);
281 }
282
283 .template-modern .quote-total-row:last-child {
284 border-bottom: none;
285 }
286
287 .template-modern .quote-total-label {
288 font-weight: 500;
289 color: var(--text-secondary);
290 }
291
292 .template-modern .quote-total-value {
293 font-weight: 600;
294 color: var(--text-primary);
295 }
296
297 .template-modern .quote-grand-total {
298 font-size: var(--font-size-xl);
299 font-weight: 700;
300 color: var(--primary-color);
301 border-top: 2px solid var(--primary-color);
302 padding-top: var(--spacing-4);
303 margin-top: var(--spacing-4);
304 }
305
306 /* Notes Section */
307 .template-modern .quote-notes {
308 margin-top: var(--spacing-12);
309 padding: var(--spacing-8);
310 background: var(--background-accent);
311 border-radius: var(--radius-xl);
312 border-left: 4px solid var(--primary-color);
313 box-shadow: var(--shadow-md);
314 }
315
316 .template-modern .quote-notes h3 {
317 font-family: var(--font-family-heading);
318 font-size: var(--font-size-lg);
319 font-weight: 600;
320 color: var(--text-primary);
321 margin-bottom: var(--spacing-4);
322 }
323
324 .template-modern .notes-content {
325 color: var(--text-secondary);
326 line-height: 1.6;
327 }
328
329 /* Terms and Conditions Section */
330 .template-modern .quote-terms {
331 margin-top: var(--spacing-12);
332 padding: var(--spacing-8);
333 background: var(--background-secondary);
334 border-radius: var(--radius-xl);
335 border: 1px solid var(--border-color);
336 box-shadow: var(--shadow-md);
337 }
338
339 .template-modern .quote-terms h3 {
340 font-family: var(--font-family-heading);
341 font-size: var(--font-size-lg);
342 font-weight: 600;
343 color: var(--text-primary);
344 margin-bottom: var(--spacing-4);
345 }
346
347 .template-modern .terms-content {
348 color: var(--text-secondary);
349 line-height: 1.6;
350 }
351
352 /* Footer */
353 .template-modern .quote-footer {
354 margin-top: var(--spacing-12);
355 padding: var(--spacing-6);
356 text-align: center;
357 background: var(--background-secondary);
358 border-radius: var(--radius-lg);
359 border: 1px solid var(--border-color);
360 }
361
362 .template-modern .quote-footer p {
363 margin: 0;
364 color: var(--text-secondary);
365 font-size: var(--font-size-sm);
366 }
367
368 /* Responsive Design */
369 @media (max-width: 768px) {
370 .template-modern {
371 padding: var(--spacing-4);
372 }
373
374 .template-modern .quote-header {
375 grid-template-columns: 1fr;
376 gap: var(--spacing-6);
377 }
378
379 .template-modern .quote-meta {
380 min-width: auto;
381 }
382
383 .template-modern .address-section {
384 grid-template-columns: 1fr;
385 gap: var(--spacing-6);
386 }
387
388 .template-modern .quote-totals {
389 width: 100%;
390 }
391 }
392 </style>
393
394 <div class="template template-modern">
395 <!-- Header -->
396 <div class="quote-header">
397 <div class="company-info">
398 <div class="company-logo">
399 <?php if (!empty($company_info['logo'])): ?>
400 <img src="<?php echo esc_url($company_info['logo']); ?>" alt="<?php echo esc_attr($company_info['name']); ?>" class="logo-image">
401 <?php endif; ?>
402 </div>
403 <div class="company-name"><?php echo esc_html($company_info['name']); ?></div>
404 <div class="company-details">
405 <?php echo \EasyInvoice\Helpers\TemplateTextHelper::generateFromSection($company_info, false, 'details-only'); ?>
406 </div>
407 </div>
408
409 <div class="quote-meta">
410 <div class="quote-title"><?php echo esc_html($quote->getTitle() ?: __('Quote', 'easy-invoice')); ?></div>
411 <div class="meta-item">
412 <span class="meta-label"><?php echo esc_html($text_settings['quote_number']); ?></span>
413 <span class="meta-value"><?php echo esc_html($quote->getNumber()); ?></span>
414 </div>
415 <div class="meta-item">
416 <span class="meta-label"><?php echo esc_html($text_settings['quote_date']); ?></span>
417 <span class="meta-value"><?php echo esc_html(\EasyInvoice\Controllers\SettingsController::formatDate($quote->getIssueDate())); ?></span>
418 </div>
419 <div class="meta-item">
420 <span class="meta-label"><?php echo esc_html($text_settings['valid_until']); ?></span>
421 <span class="meta-value"><?php echo esc_html(\EasyInvoice\Controllers\SettingsController::formatDate($quote->getExpiryDate())); ?></span>
422 </div>
423 </div>
424 </div>
425
426 <!-- Address Section -->
427 <div class="address-section">
428 <div class="address-block">
429 <h2><?php echo esc_html($text_settings['to']); ?></h2>
430 <div class="address-content">
431 <div class="client-name"><?php echo esc_html($quote->getCustomerName()); ?></div>
432 <?php if ($quote->getCustomerAddress()): ?>
433 <?php echo nl2br(esc_html($quote->getCustomerAddress())); ?><br>
434 <?php endif; ?>
435 <?php if ($quote->getCustomerEmail()): ?>
436 <?php echo esc_html($quote->getCustomerEmail()); ?><br>
437 <?php endif; ?>
438 </div>
439 </div>
440 </div>
441
442 <!-- Quote Description -->
443 <?php if ($quote->getDescription()): ?>
444 <div class="quote-description" style="margin-bottom: 1.5rem;">
445 <div class="description-content" style="color:#6b7280; line-height:1.6; font-size:0.875rem; white-space:pre-wrap;">
446 <?php echo wp_kses_post($quote->getDescription()); ?>
447 </div>
448 </div>
449 <?php endif; ?>
450
451 <!-- Quote Items -->
452 <table class="quote-items">
453 <thead>
454 <tr>
455 <th><?php echo esc_html($text_settings['service']); ?></th>
456 <th><?php echo esc_html($text_settings['qty']); ?></th>
457 <th><?php echo esc_html($text_settings['rate_price']); ?></th>
458 <?php if (\EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField()): ?>
459 <th><?php echo esc_html($text_settings['adjust']); ?> (%)</th>
460 <?php endif; ?>
461 <th><?php echo esc_html($text_settings['total']); ?></th>
462 </tr>
463 </thead>
464 <tbody>
465 <?php foreach ($quote->getItems() as $item): ?>
466 <tr>
467 <td class="item-name">
468 <div class="item-title"><?php echo esc_html($item->getName()); ?></div>
469 <?php if ($item->getDescription()): ?>
470 <div class="item-description"><?php echo esc_html($item->getDescription()); ?></div>
471 <?php endif; ?>
472 </td>
473 <td class="item-quantity"><?php echo esc_html($item->getQuantity() ?: '0'); ?></td>
474 <td class="item-price"><?php echo esc_html($formatter->format($item->getPrice())); ?></td>
475 <?php if (\EasyInvoice\Controllers\SettingsController::shouldShowQuoteAdjustField()): ?>
476 <td class="item-adjust"><?php
477 $adjust_percentage = $item->getAdjustPercentage();
478 if ($adjust_percentage != 0) {
479 echo esc_html($adjust_percentage > 0 ? '+' : '') . esc_html($adjust_percentage) . '%';
480 } else {
481 echo esc_html__('', 'easy-invoice');
482 }
483 ?></td>
484 <?php endif; ?>
485 <td class="item-total"><?php echo esc_html($formatter->format($item->getAmount())); ?></td>
486 </tr>
487 <?php endforeach; ?>
488 </tbody>
489 </table>
490
491 <!-- Quote Totals -->
492 <div class="quote-totals">
493 <?php echo \EasyInvoice\Helpers\TemplateTextHelper::generateTotalsSection($quote, $text_settings, $formatter, 'quote'); ?>
494 </div>
495
496 <!-- Notes -->
497 <?php if ($quote->getNotes()): ?>
498 <div class="quote-notes">
499 <h3><?php _e('Notes:', 'easy-invoice'); ?></h3>
500 <div class="notes-content">
501 <?php echo wp_kses_post($quote->getNotes() ?: ''); ?>
502 </div>
503 </div>
504 <?php endif; ?>
505
506 <!-- Terms and Conditions -->
507 <?php
508 $terms_conditions = $quote->getTerms() ?: \EasyInvoice\Controllers\SettingsController::getQuoteTermsConditions();
509 if ($terms_conditions):
510 ?>
511 <div class="quote-terms">
512 <h3><?php _e('Terms & Conditions:', 'easy-invoice'); ?></h3>
513 <div class="terms-content">
514 <?php echo wp_kses_post($terms_conditions); ?>
515 </div>
516 </div>
517 <?php endif; ?>
518
519 <!-- Footer -->
520 <div class="quote-footer">
521 <?php
522 $footer_text = $quote->getFooterText();
523 if (!$footer_text) {
524 $footer_text = \EasyInvoice\Controllers\SettingsController::getQuoteFooterText();
525 }
526 ?>
527 <p><?php echo wp_kses_post($footer_text); ?></p>
528 </div>
529 </div>