displayClientsPage(); break; case PagesSlugs::CLIENT_EDIT: $this->displayClientEditPage(); break; case PagesSlugs::CLIENT_VIEW: $this->displayClientViewPage(); break; default: $this->displayClientsPage(); break; } } /** * Display clients page */ protected function displayClientsPage() { // Pagination settings $per_page = 20; $current_page = isset($_GET['paged']) ? max(1, intval($_GET['paged'])) : 1; // Get repository $repository = ClientServiceProvider::getClientRepository(); // Get all clients first to calculate total $all_clients = $repository->all(); $total_clients = count($all_clients); $total_pages = ceil($total_clients / $per_page); // Get paginated clients $offset = ($current_page - 1) * $per_page; $clients = array_slice($all_clients, $offset, $per_page); // Initialize stats $stats = [ 'total_clients' => $total_clients, 'total_invoices' => 0, 'total_revenue' => [], 'pending_invoices' => 0 ]; // Calculate total revenue from all clients' invoices // Revenue and counts from SQL over the persisted totals; this used to load // every invoice on the site as a model to render three header cards. $invoice_repository = InvoiceServiceProvider::getInvoiceRepository(); $paid = \EasyInvoice\Services\InvoiceTotalsCache::paidRevenue(); $revenue_by_currency = []; foreach ($paid['revenue'] as $currency_code => $row) { $revenue_by_currency[$currency_code] = [ 'amount' => (float) $row['amount'], 'symbol' => $row['symbol'], 'currency_code' => $currency_code, ]; } $stats['total_revenue'] = $revenue_by_currency; $stats['total_invoices'] = (int) $invoice_repository->count(); $stats['pending_invoices'] = (int) \EasyInvoice\Services\InvoiceTotalsCache::outstanding()['count']; // Prepare template data with pagination $template_data = [ 'clients' => $clients, 'stats' => $stats, 'current_page' => $current_page, 'per_page' => $per_page, 'total_clients' => $total_clients, 'total_pages' => $total_pages ]; // Display the template $this->displayTemplate( EASY_INVOICE_PLUGIN_DIR . 'templates/clients-page.php', $template_data ); } /** * Display client edit page */ protected function displayClientEditPage() { $check = $this->checkCapability('ei_manage_clients'); if (is_wp_error($check)) { wp_die(esc_html($check->get_error_message())); } $client_id = isset($_GET['client_id']) ? intval($_GET['client_id']) : 0; if ($client_id <= 0) { wp_die(esc_html__('Invalid client ID', 'easy-invoice')); } // Get client from repository $repository = ClientServiceProvider::getClientRepository(); $client = $repository->find($client_id); if (!$client) { wp_die(esc_html__('Client not found', 'easy-invoice')); } // Display the template $this->displayTemplate( EASY_INVOICE_PLUGIN_DIR . 'templates/client-edit-page.php', ['client' => $client] ); } /** * Display client view page */ protected function displayClientViewPage() { $check = $this->checkCapability('ei_view_clients'); if (is_wp_error($check)) { wp_die(esc_html($check->get_error_message())); } $client_id = isset($_GET['client_id']) ? intval($_GET['client_id']) : 0; if ($client_id <= 0) { wp_die(esc_html__('Invalid client ID', 'easy-invoice')); } // Get client from repository $repository = ClientServiceProvider::getClientRepository(); $client = $repository->find($client_id); if (!$client) { wp_die(esc_html__('Client not found', 'easy-invoice')); } // Get client invoices $invoices = []; $invoice_repository = InvoiceServiceProvider::getInvoiceRepository(); // Query invoices for this client $args = array( 'post_type' => 'easy_invoice', 'post_status' => 'publish', 'meta_query' => array( array( 'key' => '_easy_invoice_client_id', 'value' => $client_id, 'compare' => '=' ) ), 'posts_per_page' => -1, 'orderby' => 'date', 'order' => 'DESC' ); $invoice_posts = get_posts($args); foreach ($invoice_posts as $post) { $invoice = $invoice_repository->find($post->ID); if ($invoice) { $invoices[] = array( 'id' => $invoice->getId(), 'title' => $invoice->getTitle() ?: $invoice->getNumber(), 'invoice_number' => $invoice->getNumber(), 'date' => $invoice->getIssueDate(), 'due_date' => $invoice->getDueDate(), 'amount' => $invoice->getTotal(), 'status' => $invoice->getStatus() ); } } // Get client quotes $quotes = []; $quote_repository = QuoteServiceProvider::getQuoteRepository(); // Query quotes for this client $quote_args = array( 'post_type' => 'easy_invoice_quote', 'post_status' => 'publish', 'meta_query' => array( array( 'key' => '_easy_invoice_client_id', 'value' => $client_id, 'compare' => '=' ) ), 'posts_per_page' => -1, 'orderby' => 'date', 'order' => 'DESC' ); $quote_posts = get_posts($quote_args); foreach ($quote_posts as $post) { $quote = $quote_repository->find($post->ID); if ($quote) { $quotes[] = array( 'id' => $quote->getId(), 'title' => $quote->getTitle() ?: $quote->getNumber(), 'quote_number' => $quote->getNumber(), 'date' => $quote->getIssueDate(), 'expiry_date' => $quote->getExpiryDate(), 'amount' => $quote->getTotal(), 'status' => $quote->getStatus() ); } } // Get client role information $user = get_user_by('ID', $client_id); $client_role = $user ? $user->roles[0] ?? 'client' : 'client'; // Display the template $this->displayTemplate( EASY_INVOICE_PLUGIN_DIR . 'templates/client-view-page.php', [ 'client' => $client, 'invoices' => $invoices, 'quotes' => $quotes, 'client_role' => $client_role ] ); } /** * Get client stats * * @return array */ public function getClientStats() { $repository = ClientServiceProvider::getClientRepository(); $clients = $repository->all(); return [ 'total_clients' => count($clients) ]; } /** * Delete a client */ public function deleteClient() { if (!$this->handleAjaxSecurity(($_POST['nonce'] ?? ''))) { return; } // Check client ID if (!isset($_POST['client_id']) || empty($_POST['client_id'])) { wp_send_json_error(array('message' => 'Invalid client ID')); } $client_id = intval($_POST['client_id']); // Delete client $repository = ClientServiceProvider::getClientRepository(); $result = $repository->delete($client_id); if ($result) { wp_send_json_success(array('message' => 'Client deleted successfully')); } else { wp_send_json_error(array('message' => 'Error deleting client')); } } }