PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.1
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.1
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 / client-view-page.php

client-view-page.php in Easy Invoice – Invoice Generator, PDF Quotes & Payments 2.4.1, at templates/client-view-page.php

363 lines 22.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Exit if accessed directly
3 if (!defined('ABSPATH')) {
4 exit;
5 }
6
7 // Client data and invoices are passed from the render_client_view_page method
8 ?>
9
10 <div class="p-8">
11 <div class="flex justify-between items-center mb-6">
12 <div>
13 <h1 class="text-2xl font-bold text-gray-900 flex items-center">
14 <i class="fas fa-user-tie text-gray-400 mr-3"></i>
15 <span><?php echo esc_html($client->getBusinessClientName() ?: $client->getFirstName() . ' ' . $client->getLastName()); ?></span>
16 </h1>
17 <p class="text-sm text-gray-500 mt-1">
18 Client Overview & Invoice History
19 </p>
20 </div>
21 <div>
22 <a href="?page=easy-invoice-clients" class="text-gray-600 hover:text-indigo-600 mr-4 font-medium text-sm">
23 <i class="fas fa-arrow-left mr-1"></i> Back to Clients
24 </a>
25 <a href="?page=easy-invoice-client-edit&client_id=<?php echo esc_attr($client->getId()); ?>" class="bg-indigo-600 text-white px-4 py-2 rounded-lg hover:bg-indigo-700 text-sm font-semibold shadow-sm">
26 <i class="fas fa-pen mr-2"></i>Edit Client
27 </a>
28 </div>
29 </div>
30
31 <div class="bg-white p-6 rounded-xl border border-gray-200 shadow-sm mb-8">
32 <div class="flex items-center justify-between pb-4 border-b border-gray-200 mb-4">
33 <h4 class="text-lg font-semibold text-gray-800 flex items-center">
34 <i class="fas fa-user-check text-indigo-500 mr-3"></i>
35 <span><?php esc_html_e('Client Details', 'easy-invoice'); ?></span>
36 </h4>
37 </div>
38
39 <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-x-8 gap-y-6 pt-2">
40 <div class="flex items-start group">
41 <div class="flex-shrink-0 w-8 text-center pt-1"><i class="fas fa-user-tie text-gray-400 group-hover:text-indigo-500 transition-colors"></i></div>
42 <div class="ml-3">
43 <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Full Name', 'easy-invoice'); ?></label>
44 <p class="text-sm font-semibold text-gray-800 mt-1"><?php echo esc_html($client->getFirstName() . ' ' . $client->getLastName()); ?></p>
45 </div>
46 </div>
47
48 <div class="flex items-start group">
49 <div class="flex-shrink-0 w-8 text-center pt-1"><i class="fas fa-building text-gray-400 group-hover:text-indigo-500 transition-colors"></i></div>
50 <div class="ml-3">
51 <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Company', 'easy-invoice'); ?></label>
52 <p class="text-sm font-semibold text-gray-800 mt-1"><?php echo esc_html($client->getBusinessClientName() ?: 'N/A'); ?></p>
53 </div>
54 </div>
55
56 <div class="flex items-start group">
57 <div class="flex-shrink-0 w-8 text-center pt-1"><i class="fas fa-envelope text-gray-400 group-hover:text-indigo-500 transition-colors"></i></div>
58 <div class="ml-3">
59 <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Email', 'easy-invoice'); ?></label>
60 <p class="text-sm text-gray-800 mt-1 break-all"><?php echo esc_html($client->getEmail()); ?></p>
61 </div>
62 </div>
63
64 <div class="flex items-start group">
65 <div class="flex-shrink-0 w-8 text-center pt-1"><i class="fas fa-phone-alt text-gray-400 group-hover:text-indigo-500 transition-colors"></i></div>
66 <div class="ml-3">
67 <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Phone', 'easy-invoice'); ?></label>
68 <p class="text-sm text-gray-800 mt-1"><?php echo esc_html($client->getPhone() ?: 'N/A'); ?></p>
69 </div>
70 </div>
71
72 <div class="flex items-start group">
73 <div class="flex-shrink-0 w-8 text-center pt-1"><i class="fas fa-at text-gray-400 group-hover:text-indigo-500 transition-colors"></i></div>
74 <div class="ml-3">
75 <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Username', 'easy-invoice'); ?></label>
76 <p class="text-sm text-gray-800 mt-1"><?php echo esc_html($client->getUsername()); ?></p>
77 </div>
78 </div>
79
80 <div class="flex items-start group">
81 <div class="flex-shrink-0 w-8 text-center pt-1"><i class="fas fa-id-card text-gray-400 group-hover:text-indigo-500 transition-colors"></i></div>
82 <div class="ml-3">
83 <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Client ID', 'easy-invoice'); ?></label>
84 <p class="text-sm text-gray-800 mt-1"><?php echo esc_html($client->getId()); ?></p>
85 </div>
86 </div>
87
88 <div class="flex items-start group">
89 <div class="flex-shrink-0 w-8 text-center pt-1"><i class="fas fa-user-shield text-gray-400 group-hover:text-indigo-500 transition-colors"></i></div>
90 <div class="ml-3">
91 <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Role', 'easy-invoice'); ?></label>
92 <div class="mt-1">
93 <?php
94 $role_class = 'bg-blue-100 text-blue-800';
95 $role_icon = 'fas fa-user';
96
97 if (isset($client_role)) {
98 switch ($client_role) {
99 case 'administrator':
100 $role_class = 'bg-red-100 text-red-800';
101 $role_icon = 'fas fa-crown';
102 break;
103 case 'editor':
104 $role_class = 'bg-purple-100 text-purple-800';
105 $role_icon = 'fas fa-user-edit';
106 break;
107 case 'author':
108 $role_class = 'bg-green-100 text-green-800';
109 $role_icon = 'fas fa-user-edit';
110 break;
111 case 'contributor':
112 $role_class = 'bg-yellow-100 text-yellow-800';
113 $role_icon = 'fas fa-user-plus';
114 break;
115 case 'subscriber':
116 $role_class = 'bg-gray-100 text-gray-800';
117 $role_icon = 'fas fa-user';
118 break;
119 default:
120 $role_class = 'bg-blue-100 text-blue-800';
121 $role_icon = 'fas fa-user';
122 }
123 }
124 ?>
125 <span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium <?php echo esc_attr($role_class); ?>">
126 <i class="<?php echo esc_attr($role_icon); ?> mr-1"></i>
127 <?php echo esc_html(ucfirst($client_role ?? 'client')); ?>
128 </span>
129 </div>
130 </div>
131 </div>
132
133 <div class="flex items-start group">
134 <div class="flex-shrink-0 w-8 text-center pt-1"><i class="fas fa-globe-americas text-gray-400 group-hover:text-indigo-500 transition-colors"></i></div>
135 <div class="ml-3">
136 <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Website', 'easy-invoice'); ?></label>
137 <p class="text-sm text-gray-800 mt-1">
138 <?php if ($client->getWebsite()): ?>
139 <a href="<?php echo esc_url($client->getWebsite()); ?>" target="_blank" class="text-indigo-600 hover:text-indigo-800 hover:underline">
140 <?php echo esc_html($client->getWebsite()); ?>
141 </a>
142 <?php else: ?>
143 N/A
144 <?php endif; ?>
145 </p>
146 </div>
147 </div>
148
149 <div class="flex items-start group md:col-span-2 lg:col-span-3">
150 <div class="flex-shrink-0 w-8 text-center pt-1"><i class="fas fa-map-marker-alt text-gray-400 group-hover:text-indigo-500 transition-colors"></i></div>
151 <div class="ml-3">
152 <label class="block text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Address', 'easy-invoice'); ?></label>
153 <p class="text-sm text-gray-800 mt-1 whitespace-pre-wrap"><?php echo esc_html($client->getAddress() ?: 'N/A'); ?></p>
154 </div>
155 </div>
156 </div>
157
158 <?php if ($client->getExtraInfo()): ?>
159 <div class="mt-6 pt-6 border-t border-gray-200">
160 <h3 class="text-sm font-semibold text-gray-800 mb-2 flex items-center">
161 <i class="fas fa-info-circle text-gray-400 mr-2"></i>
162 <span><?php esc_html_e('Extra Info', 'easy-invoice'); ?></span>
163 </h3>
164 <div class="bg-gray-50 p-4 rounded-md text-sm text-gray-700 prose max-w-none">
165 <?php echo nl2br(esc_html($client->getExtraInfo())); ?>
166 </div>
167 </div>
168 <?php endif; ?>
169 </div>
170
171 <?php
172 /**
173 * Fires after the client's details, before their invoices.
174 *
175 * Where an addon adds something that belongs to the client rather than to
176 * any one document -- Pro shows the card on file here, with the control
177 * to remove it.
178 *
179 * @param int $client_id Client (WordPress user) id.
180 */
181 do_action('easy_invoice_client_view_after_details', (int) $client->getId());
182 ?>
183
184 <div class="bg-white shadow-sm rounded-xl border border-gray-200">
185 <div class="p-6 border-b border-gray-200">
186 <h2 class="text-lg font-semibold text-gray-800 flex items-center">
187 <i class="fas fa-file-invoice-dollar text-indigo-500 mr-3"></i>
188 <span><?php esc_html_e('Invoices', 'easy-invoice'); ?></span>
189 </h2>
190 </div>
191
192 <?php if (empty($invoices)): ?>
193 <div class="text-center py-12">
194 <div class="text-gray-400 mb-4"><i class="fas fa-file-invoice fa-4x"></i></div>
195 <p class="text-gray-500 font-medium mb-4"><?php esc_html_e('No invoices found for this client.', 'easy-invoice'); ?></p>
196 </div>
197 <?php else: ?>
198 <div class="overflow-x-auto">
199 <table class="min-w-full divide-y divide-gray-200">
200 <thead class="bg-gray-50">
201 <tr>
202 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Invoice', 'easy-invoice'); ?></th>
203 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Date', 'easy-invoice'); ?></th>
204 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Due Date', 'easy-invoice'); ?></th>
205 <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Amount', 'easy-invoice'); ?></th>
206 <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Status', 'easy-invoice'); ?></th>
207 <th scope="col" class="relative px-6 py-3">
208 <span class="sr-only"><?php esc_html_e('Actions', 'easy-invoice'); ?></span>
209 </th>
210 </tr>
211 </thead>
212 <tbody class="bg-white divide-y divide-gray-200">
213 <?php foreach ($invoices as $invoice):
214 $status_key = \EasyInvoice\Helpers\InvoiceStatus::displayKey( (string) $invoice['status'], $invoice['due_date'] ?? null );
215 $status_class = \EasyInvoice\Helpers\InvoiceStatus::badgeClass( $status_key );
216 $status_icon = [ 'paid' => 'fas fa-check-circle', 'partial' => 'fas fa-adjust', 'overdue' => 'fas fa-exclamation-triangle', 'draft' => 'fas fa-pencil-alt', 'cancelled' => 'fas fa-ban' ][ $status_key ] ?? 'fas fa-file-invoice';
217 ?>
218 <tr>
219 <td class="px-6 py-4 whitespace-nowrap">
220 <div class="flex flex-col">
221 <div class="text-sm font-semibold text-indigo-600 hover:text-indigo-800">
222 <a href="<?php echo esc_url(get_permalink($invoice['id'])); ?>"><?php echo esc_html($invoice['title']); ?></a>
223 </div>
224 <div class="text-xs text-gray-500 font-mono">
225 <?php echo esc_html($invoice['invoice_number']); ?>
226 </div>
227 </div>
228 </td>
229 <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
230 <?php echo esc_html(gmdate("M d, Y", strtotime($invoice['date']))); ?>
231 </td>
232 <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
233 <?php echo esc_html(gmdate("M d, Y", strtotime($invoice['due_date']))); ?>
234 </td>
235 <td class="px-6 py-4 whitespace-nowrap text-right text-sm text-gray-800 font-medium">
236 <?php
237 // Use InvoiceFormatter for proper currency formatting
238 $formatter = new \EasyInvoice\Helpers\InvoiceFormatter();
239 echo esc_html($formatter->format($invoice['amount'] ?? 0));
240 ?>
241 </td>
242 <td class="px-6 py-4 whitespace-nowrap text-center">
243 <span class="px-3 py-1 inline-flex text-xs leading-5 font-semibold rounded-full <?php echo esc_attr($status_class); ?>">
244 <i class="<?php echo esc_attr($status_icon); ?> mr-1.5"></i>
245 <?php echo esc_html( \EasyInvoice\Helpers\InvoiceStatus::label( $status_key ) ); ?>
246 </span>
247 </td>
248 <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium space-x-3">
249 <a href="<?php echo esc_url(get_permalink($invoice['id'])); ?>" class="text-indigo-600 hover:text-indigo-900" data-tooltip="View Invoice">
250 <i class="fas fa-eye"></i>
251 </a>
252 <a href="?page=easy-invoice-builder&invoice_id=<?php echo esc_attr($invoice['id']); ?>" class="text-gray-500 hover:text-indigo-900" data-tooltip="Edit Invoice">
253 <i class="fas fa-pen"></i>
254 </a>
255 </td>
256 </tr>
257 <?php endforeach; ?>
258 </tbody>
259 </table>
260 </div>
261 <?php endif; ?>
262 </div>
263
264 <div class="bg-white shadow-sm rounded-xl border border-gray-200 mt-6">
265 <div class="p-6 border-b border-gray-200">
266 <h2 class="text-lg font-semibold text-gray-800 flex items-center">
267 <i class="fas fa-file-contract text-green-500 mr-3"></i>
268 <span><?php esc_html_e('Quotes', 'easy-invoice'); ?></span>
269 </h2>
270 </div>
271
272 <?php if (empty($quotes)): ?>
273 <div class="text-center py-12">
274 <div class="text-gray-400 mb-4"><i class="fas fa-file-contract fa-4x"></i></div>
275 <p class="text-gray-500 font-medium mb-4"><?php esc_html_e('No quotes found for this client.', 'easy-invoice'); ?></p>
276 </div>
277 <?php else: ?>
278 <div class="overflow-x-auto">
279 <table class="min-w-full divide-y divide-gray-200">
280 <thead class="bg-gray-50">
281 <tr>
282 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Quote', 'easy-invoice'); ?></th>
283 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Date', 'easy-invoice'); ?></th>
284 <th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Expiry Date', 'easy-invoice'); ?></th>
285 <th scope="col" class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Amount', 'easy-invoice'); ?></th>
286 <th scope="col" class="px-6 py-3 text-center text-xs font-medium text-gray-500 uppercase tracking-wider"><?php esc_html_e('Status', 'easy-invoice'); ?></th>
287 <th scope="col" class="relative px-6 py-3">
288 <span class="sr-only"><?php esc_html_e('Actions', 'easy-invoice'); ?></span>
289 </th>
290 </tr>
291 </thead>
292 <tbody class="bg-white divide-y divide-gray-200">
293 <?php foreach ($quotes as $quote):
294 $status_class = '';
295 $status_icon = '';
296 switch ($quote['status']) {
297 case 'accepted':
298 $status_class = 'bg-green-100 text-green-800';
299 $status_icon = 'fas fa-check-circle';
300 break;
301 case 'pending':
302 $status_class = 'bg-yellow-100 text-yellow-800';
303 $status_icon = 'fas fa-hourglass-half';
304 break;
305 case 'declined':
306 $status_class = 'bg-red-100 text-red-800';
307 $status_icon = 'fas fa-times-circle';
308 break;
309 case 'expired':
310 $status_class = 'bg-gray-100 text-gray-800';
311 $status_icon = 'fas fa-clock';
312 break;
313 default:
314 $status_class = 'bg-gray-100 text-gray-800';
315 $status_icon = 'fas fa-question-circle';
316 }
317 ?>
318 <tr>
319 <td class="px-6 py-4 whitespace-nowrap">
320 <div class="flex flex-col">
321 <div class="text-sm font-semibold text-green-600 hover:text-green-800">
322 <a href="<?php echo esc_url(get_permalink($quote['id'])); ?>"><?php echo esc_html($quote['title']); ?></a>
323 </div>
324 <div class="text-xs text-gray-500 font-mono">
325 <?php echo esc_html($quote['quote_number']); ?>
326 </div>
327 </div>
328 </td>
329 <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
330 <?php echo esc_html(gmdate("M d, Y", strtotime($quote['date']))); ?>
331 </td>
332 <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
333 <?php echo esc_html(gmdate("M d, Y", strtotime($quote['expiry_date']))); ?>
334 </td>
335 <td class="px-6 py-4 whitespace-nowrap text-right text-sm text-gray-800 font-medium">
336 <?php
337 // Use QuoteFormatter for proper currency formatting
338 $formatter = new \EasyInvoice\Helpers\QuoteFormatter();
339 echo esc_html($formatter->format($quote['amount'] ?? 0));
340 ?>
341 </td>
342 <td class="px-6 py-4 whitespace-nowrap text-center">
343 <span class="px-3 py-1 inline-flex text-xs leading-5 font-semibold rounded-full <?php echo esc_attr($status_class); ?>">
344 <i class="<?php echo esc_attr($status_icon); ?> mr-1.5"></i>
345 <?php echo esc_html(ucfirst($quote['status'])); ?>
346 </span>
347 </td>
348 <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium space-x-3">
349 <a href="<?php echo esc_url(get_permalink($quote['id'])); ?>" class="text-green-600 hover:text-green-900" data-tooltip="View Quote">
350 <i class="fas fa-eye"></i>
351 </a>
352 <a href="?page=easy-invoice-quote-builder&quote_id=<?php echo esc_attr($quote['id']); ?>" class="text-gray-500 hover:text-green-900" data-tooltip="Edit Quote">
353 <i class="fas fa-pen"></i>
354 </a>
355 </td>
356 </tr>
357 <?php endforeach; ?>
358 </tbody>
359 </table>
360 </div>
361 <?php endif; ?>
362 </div>
363 </div>