| @@ -48,9 +48,8 @@ | ||
| 48 | 48 | $invoices_list_url = admin_url('admin.php?page=' . PagesSlugs::ALL_INVOICES); |
| 49 | 49 | ?> |
| 50 | 50 | |
| 51 | 51 | <div class="p-8"> |
| 52 | - <!-- Page Header --> | |
| 53 | 52 | <div class="ei-app-page-header bg-white border-b border-gray-200 px-6 easy-invoice-admin-page-header"> |
| 54 | 53 | <div class="flex items-center justify-between"> |
| 55 | 54 | <div> |
| 56 | 55 | <h1 class="text-2xl font-bold text-gray-900"><?php esc_html_e( 'Dashboard', 'easy-invoice' ); ?></h1> |
| @@ -58,9 +57,8 @@ | ||
| 58 | 57 | </div> |
| 59 | 58 | </div> |
| 60 | 59 | </div> |
| 61 | 60 | |
| 62 | - <!-- Stats Cards --> | |
| 63 | 61 | <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8 mt-8"> |
| 64 | 62 | <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1"> |
| 65 | 63 | <div class="flex items-center"> |
| 66 | 64 | <div class="rounded-full bg-indigo-100 p-3 mr-4"> |
| @@ -92,15 +90,30 @@ | ||
| 92 | 90 | $amount = isset($data['amount']) && is_numeric($data['amount']) ? $data['amount'] : 0; |
| 93 | 91 | $symbol = isset($data['symbol']) ? $data['symbol'] : ''; |
| 94 | 92 | ?> |
| 95 | 93 | <div class="<?php echo $currency_count > 0 ? 'text-sm' : 'text-lg'; ?> font-bold text-gray-900 <?php echo !$is_last ? 'mb-1' : ''; ?>"> |
| 96 | - <?php echo $symbol . number_format($amount, 2); ?> | |
| 94 | + <?php echo esc_html($symbol . number_format($amount, 2)); ?> | |
| 97 | 95 | <span class="text-xs font-normal text-gray-500"><?php echo esc_html(strtoupper((string)($currency ?? 'USD'))); ?></span> |
| 98 | 96 | </div> |
| 99 | 97 | <?php endforeach; ?> |
| 100 | 98 | </div> |
| 101 | 99 | <?php else: ?> |
| 102 | - <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> | |
| 103 | 116 | <?php endif; ?> |
| 104 | 117 | </div> |
| 105 | 118 | </div> |
| 106 | 119 | </div> |
| @@ -113,8 +126,11 @@ | ||
| 113 | 126 | </div> |
| 114 | 127 | <div> |
| 115 | 128 | <h3 class="text-sm font-medium text-gray-500"><?php esc_html_e( 'Unpaid Invoices', 'easy-invoice' ); ?></h3> |
| 116 | 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; ?> | |
| 117 | 133 | </div> |
| 118 | 134 | </div> |
| 119 | 135 | </div> |
| 120 | 136 | <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1"> |
| @@ -126,15 +142,21 @@ | ||
| 126 | 142 | </div> |
| 127 | 143 | <div> |
| 128 | 144 | <h3 class="text-sm font-medium text-gray-500"><?php esc_html_e( 'Overdue Invoices', 'easy-invoice' ); ?></h3> |
| 129 | 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; ?> | |
| 130 | 149 | </div> |
| 131 | 150 | </div> |
| 132 | 151 | </div> |
| 133 | 152 | </div> |
| 134 | 153 | |
| 135 | - <!-- Client Stats Cards --> | |
| 136 | - <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"> | |
| 137 | 159 | <div class="bg-white rounded-lg shadow p-6 transition-transform duration-300 hover:shadow-md hover:-translate-y-1"> |
| 138 | 160 | <div class="flex items-center"> |
| 139 | 161 | <div class="rounded-full bg-blue-100 p-3 mr-4"> |
| 140 | 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"> |
| @@ -164,9 +186,8 @@ | ||
| 164 | 186 | </div> |
| 165 | 187 | </div> |
| 166 | 188 | </div> |
| 167 | 189 | |
| 168 | - <!-- Monthly Revenue Chart --> | |
| 169 | 190 | <div class="bg-white rounded-lg shadow p-6 mb-8 border border-gray-100"> |
| 170 | 191 | <h2 class="text-lg font-medium text-gray-900 mb-1"><?php esc_html_e( 'Monthly Revenue', 'easy-invoice' ); ?></h2> |
| 171 | 192 | <?php if ($easy_invoice_has_chart_data) : ?> |
| 172 | 193 | <p class="text-sm text-gray-500 mb-4"><?php esc_html_e( 'Paid amounts recorded over the last twelve months, by currency.', 'easy-invoice' ); ?></p> |
| @@ -191,9 +212,8 @@ | ||
| 191 | 212 | </div> |
| 192 | 213 | <?php endif; ?> |
| 193 | 214 | </div> |
| 194 | 215 | |
| 195 | - <!-- Recent Invoices --> | |
| 196 | 216 | <div class="bg-white rounded-lg shadow"> |
| 197 | 217 | <div class="px-6 py-4 border-b border-gray-200"> |
| 198 | 218 | <h2 class="text-lg font-medium text-gray-900"><?php esc_html_e( 'Recent Invoices', 'easy-invoice' ); ?></h2> |
| 199 | 219 | </div> |
| @@ -211,28 +231,16 @@ | ||
| 211 | 231 | </thead> |
| 212 | 232 | <tbody class="bg-white divide-y divide-gray-200"> |
| 213 | 233 | <?php if (!empty($recent_invoices)) : ?> |
| 214 | 234 | <?php foreach ($recent_invoices as $invoice): |
| 215 | - $statusClass = [ | |
| 216 | - 'paid' => 'bg-green-100 text-green-800', | |
| 217 | - 'unpaid' => 'bg-yellow-100 text-yellow-800', | |
| 218 | - 'overdue' => 'bg-red-100 text-red-800', | |
| 219 | - 'draft' => 'bg-gray-100 text-gray-800' | |
| 220 | - ][$invoice->getStatus()] ?? 'bg-gray-100 text-gray-800'; | |
| 221 | - | |
| 222 | 235 | $invoiceId = $invoice->getId(); |
| 223 | 236 | $invoiceNumber = $invoice->getNumber() ?: ('INV-' . $invoiceId); |
| 224 | 237 | $invoiceTotal = $invoice->getTotal(); |
| 225 | 238 | $clientName = $invoice->getCustomerName() ?: __( 'Client', 'easy-invoice' ); |
| 226 | - $dueDate = $invoice->getDueDate() ?: date('Y-m-d'); | |
| 227 | - $raw_status = $invoice->getStatus(); | |
| 228 | - $status_map = array( | |
| 229 | - 'paid' => __( 'Paid', 'easy-invoice' ), | |
| 230 | - 'unpaid' => __( 'Unpaid', 'easy-invoice' ), | |
| 231 | - 'overdue' => __( 'Overdue', 'easy-invoice' ), | |
| 232 | - 'draft' => __( 'Draft', 'easy-invoice' ), | |
| 233 | - ); | |
| 234 | - $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 ); | |
| 235 | 243 | ?> |
| 236 | 244 | <tr> |
| 237 | 245 | <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900"><?php echo esc_html($invoiceNumber); ?></td> |
| 238 | 246 | <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"><?php echo esc_html($clientName); ?></td> |
| @@ -247,10 +255,20 @@ | ||
| 247 | 255 | </span> |
| 248 | 256 | </td> |
| 249 | 257 | <td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500"><?php echo esc_html($dueDate); ?></td> |
| 250 | 258 | <td class="px-6 py-4 whitespace-nowrap text-sm font-medium"> |
| 251 | - <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> | |
| 252 | - <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> | |
| 253 | 271 | </td> |
| 254 | 272 | </tr> |
| 255 | 273 | <?php endforeach; ?> |
| 256 | 274 | <?php else: ?> |