['label' => 'Waiting for you', 'icon' => 'fa-reply', 'where' => portalQuoteWaitingSql()], 'accepted' => ['label' => 'Accepted', 'icon' => 'fa-thumbs-up', 'where' => "quote_status IN ('Accepted', 'Invoiced')"], 'all' => ['label' => 'All', 'icon' => 'fa-list', 'where' => '1 = 1'], ]; $q = trim((string) ($_GET['q'] ?? '')); $where = "quote_client_id = $session_client_id AND quote_status != 'Draft'"; if ($q !== '') { $q_sql = escapeSql($q); $where .= " AND (CONCAT(quote_prefix, quote_number) LIKE '%$q_sql%' OR quote_scope LIKE '%$q_sql%')"; } $count_sql = []; foreach ($tabs as $key => $t) { $count_sql[] = "COALESCE(SUM({$t['where']}), 0) AS `$key`"; } $counts = array_map('intval', mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT " . implode(', ', $count_sql) . " FROM quotes WHERE $where"))); // The waiting tab when something is waiting, else all of them $tab = isset($tabs[$_GET['tab'] ?? '']) ? $_GET['tab'] : ($counts['waiting'] ? 'waiting' : 'all'); $total = $counts[$tab]; $pages = max(1, (int) ceil($total / $per_page)); $page = min(max(1, intval($_GET['page'] ?? 1)), $pages); $offset = ($page - 1) * $per_page; $quotes = mysqli_query($mysqli, "SELECT quote_id, quote_prefix, quote_number, quote_scope, quote_date, quote_expire, quote_status, quote_amount, quote_monthly_amount, quote_currency_code FROM quotes WHERE $where AND {$tabs[$tab]['where']} ORDER BY " . ($tab === 'waiting' ? 'quote_expire ASC, quote_number ASC' : 'quote_date DESC, quote_number DESC') . " LIMIT $per_page OFFSET $offset"); /** This page's address with some of its settings changed. */ function quotesUrl(array $changes) { global $tab, $q; $params = array_merge(['tab' => $tab, 'q' => $q !== '' ? $q : null], $changes); $params = array_filter($params, function ($v) { return $v !== null && $v !== ''; }); return 'quotes.php' . ($params ? '?' . http_build_query($params) : ''); } ?>

Quotes

'quotes', 'filtered' => true, 'match_text' => 'Nothing here has “' . escapeHtml($q) . '” in its number or scope.', 'clear_url' => quotesUrl(['q' => null, 'page' => null])]) ?> 'Nothing waiting for you', 'text' => 'When we send you a quote, it waits here for your answer.', 'icon' => 'fa-check', 'filtered' => false]) ?> 'No accepted quotes', 'text' => '', 'icon' => 'fa-thumbs-up', 'filtered' => false]) ?> 'No quotes yet', 'text' => 'Need something priced up? Raise a ticket and we will put a quote together.', 'icon' => 'fa-comment-dollar', 'filtered' => false, 'actions' => [['label' => 'Ask for a quote', 'href' => portalAskUrl('Quote request'), 'icon' => 'fa-plus']]]) ?> 1) { ?>
- of