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
← All changes | templates/dashboard-page.php +44 -21 2.3.42.4.1 View file →
@@ -90,15 +90,30 @@
90 90 $amount = isset($data['amount']) && is_numeric($data['amount']) ? $data['amount'] : 0;
91 91 $symbol = isset($data['symbol']) ? $data['symbol'] : '';
92 92 ?>
93 93 <div class="<?php echo $currency_count > 0 ? 'text-sm' : 'text-lg'; ?> font-bold text-gray-900 <?php echo !$is_last ? 'mb-1' : ''; ?>">
94 - <?php echo $symbol . number_format($amount, 2); ?>
94 + <?php echo esc_html($symbol . number_format($amount, 2)); ?>
95 95 <span class="text-xs font-normal text-gray-500"><?php echo esc_html(strtoupper((string)($currency ?? 'USD'))); ?></span>
96 96 </div>
97 97 <?php endforeach; ?>
98 98 </div>
99 99 <?php else: ?>
100 - <p class="mt-1 text-lg font-bold text-gray-500"><?php esc_html_e( 'No revenue recorded', 'easy-invoice' ); ?></p>
100 + <?php
101 + // Show a formatted zero, not a sentence. Every sibling tile on
102 + // this row displays a number ("0"), so putting the prose
103 + // "No revenue recorded" here broke the row's visual rhythm and
104 + // wrapped onto two lines, making this card read as taller and
105 + // more important than the others. The zero carries the same
106 + // meaning and stays scannable alongside them.
107 + $ei_zero_symbol = function_exists('easy_invoice_get_currency_symbol') ? easy_invoice_get_currency_symbol() : '';
108 + $ei_zero_code = function_exists('easy_invoice_get_currency_code') ? easy_invoice_get_currency_code() : '';
109 + ?>
110 + <div class="text-lg font-bold text-gray-900">
111 + <?php echo esc_html($ei_zero_symbol . number_format(0, 2)); ?>
112 + <?php if ($ei_zero_code) : ?>
113 + <span class="text-xs font-normal text-gray-500"><?php echo esc_html(strtoupper((string) $ei_zero_code)); ?></span>
114 + <?php endif; ?>
115 + </div>
101 116 <?php endif; ?>
102 117 </div>
103 118 </div>
104 119 </div>
@@ -111,8 +126,11 @@
111 126 </div>
112 127 <div>
113 128 <h3 class="text-sm font-medium text-gray-500"><?php esc_html_e( 'Unpaid Invoices', 'easy-invoice' ); ?></h3>
114 129 <p class="mt-1 text-2xl font-bold text-yellow-600"><?php echo esc_html($unpaid_invoices); ?></p>
130 + <?php foreach ((array) ($unpaid_amount ?? []) as $ei_cur => $ei_amt) : ?>
131 + <p class="text-xs text-gray-500" style="font-variant-numeric: tabular-nums;"><?php echo esc_html(easy_invoice_format_money((float) $ei_amt, null, (string) $ei_cur)); ?> <?php esc_html_e('outstanding', 'easy-invoice'); ?></p>
132 + <?php endforeach; ?>
115 133 </div>
116 134 </div>
117 135 </div>
118 136 <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1">
@@ -124,14 +142,21 @@
124 142 </div>
125 143 <div>
126 144 <h3 class="text-sm font-medium text-gray-500"><?php esc_html_e( 'Overdue Invoices', 'easy-invoice' ); ?></h3>
127 145 <p class="mt-1 text-2xl font-bold text-red-600"><?php echo esc_html($overdue_invoices); ?></p>
146 + <?php foreach ((array) ($overdue_amount ?? []) as $ei_cur => $ei_amt) : ?>
147 + <p class="text-xs text-gray-500" style="font-variant-numeric: tabular-nums;"><?php echo esc_html(easy_invoice_format_money((float) $ei_amt, null, (string) $ei_cur)); ?> <?php esc_html_e('past due', 'easy-invoice'); ?></p>
148 + <?php endforeach; ?>
128 149 </div>
129 150 </div>
130 151 </div>
131 152 </div>
132 153
133 - <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
154 + <?php // Same 4-column track as the stat row above (grid-cols-4 at lg), so the two
155 + // client cards line up under the first four instead of stretching to half the
156 + // page each. They are the same kind of tile and were rendering at roughly
157 + // double the width of their siblings, which read as unintentional. ?>
158 + <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
134 159 <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1">
135 160 <div class="flex items-center">
136 161 <div class="rounded-full bg-blue-100 p-3 mr-4">
137 162 <svg class="w-6 h-6 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
@@ -206,28 +231,16 @@
206 231 </thead>
207 232 <tbody class="bg-white divide-y divide-gray-200">
208 233 <?php if (!empty($recent_invoices)) : ?>
209 234 <?php foreach ($recent_invoices as $invoice):
210 - $statusClass = [
211 - 'paid' => 'bg-green-100 text-green-800',
212 - 'unpaid' => 'bg-yellow-100 text-yellow-800',
213 - 'overdue' => 'bg-red-100 text-red-800',
214 - 'draft' => 'bg-gray-100 text-gray-800'
215 - ][$invoice->getStatus()] ?? 'bg-gray-100 text-gray-800';
216 -
217 235 $invoiceId = $invoice->getId();
218 236 $invoiceNumber = $invoice->getNumber() ?: ('INV-' . $invoiceId);
219 237 $invoiceTotal = $invoice->getTotal();
220 238 $clientName = $invoice->getCustomerName() ?: __( 'Client', 'easy-invoice' );
221 - $dueDate = $invoice->getDueDate() ?: date('Y-m-d');
222 - $raw_status = $invoice->getStatus();
223 - $status_map = array(
224 - 'paid' => __( 'Paid', 'easy-invoice' ),
225 - 'unpaid' => __( 'Unpaid', 'easy-invoice' ),
226 - 'overdue' => __( 'Overdue', 'easy-invoice' ),
227 - 'draft' => __( 'Draft', 'easy-invoice' ),
228 - );
229 - $status = isset( $status_map[ $raw_status ] ) ? $status_map[ $raw_status ] : esc_html( ucfirst( (string) $raw_status ) );
239 + $dueDate = $invoice->getDueDate() ?: current_time('Y-m-d');
240 + $status_key = \EasyInvoice\Helpers\InvoiceStatus::displayKeyFor( $invoice );
241 + $statusClass = \EasyInvoice\Helpers\InvoiceStatus::badgeClass( $status_key );
242 + $status = \EasyInvoice\Helpers\InvoiceStatus::label( $status_key );
230 243 ?>
231 244 <tr>
232 245 <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900"><?php echo esc_html($invoiceNumber); ?></td>
233 246 <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"><?php echo esc_html($clientName); ?></td>
@@ -242,10 +255,20 @@
242 255 </span>
243 256 </td>
244 257 <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"><?php echo esc_html($dueDate); ?></td>
245 258 <td class="px-6 py-4 whitespace-nowrap text-sm font-medium">
246 - <a href="<?php echo admin_url('admin.php?page=easy-invoice-invoices&view=edit&invoice_id=' . $invoiceId); ?>" class="text-indigo-600 hover:text-indigo-900 mr-3"><?php esc_html_e( 'Edit', 'easy-invoice' ); ?></a>
247 - <a href="<?php echo admin_url('admin.php?page=easy-invoice-invoices&view=view&invoice_id=' . $invoiceId); ?>" class="text-indigo-600 hover:text-indigo-900"><?php esc_html_e( 'View', 'easy-invoice' ); ?></a>
259 + <?php
260 + // Both links pointed at `page=easy-invoice-invoices`, which is
261 + // not a registered admin page — the invoice list is
262 + // `easy-invoice-all` and the editor is `easy-invoice-builder`.
263 + // Every Edit and View link on the dashboard returned a 403
264 + // "you do not have permission" screen.
265 + //
266 + // Now matching what the invoice listing itself uses: Edit opens
267 + // the builder, View opens the public invoice permalink.
268 + ?>
269 + <a href="<?php echo esc_url(admin_url('admin.php?page=easy-invoice-builder&invoice_id=' . $invoiceId)); ?>" class="text-indigo-600 hover:text-indigo-900 mr-3"><?php esc_html_e( 'Edit', 'easy-invoice' ); ?></a>
270 + <a href="<?php echo esc_url(get_permalink($invoiceId)); ?>" target="_blank" rel="noopener" class="text-indigo-600 hover:text-indigo-900"><?php esc_html_e( 'View', 'easy-invoice' ); ?></a>
248 271 </td>
249 272 </tr>
250 273 <?php endforeach; ?>
251 274 <?php else: ?>