diff --git a/client/assets.php b/client/assets.php
index 6ca5184f5..86150d1b5 100644
--- a/client/assets.php
+++ b/client/assets.php
@@ -25,6 +25,9 @@ $assets_sql = mysqli_query($mysqli, "SELECT asset_description, asset_id, asset_m
+
+ = portalEmptyState('There are no assets on this account yet.') ?>
+
@@ -84,6 +87,7 @@ $assets_sql = mysqli_query($mysqli, "SELECT asset_description, asset_id, asset_m
+
diff --git a/client/certificates.php b/client/certificates.php
index daed5d169..e1c23654b 100644
--- a/client/certificates.php
+++ b/client/certificates.php
@@ -18,6 +18,9 @@ $certificates_sql = mysqli_query($mysqli, "SELECT certificate_id, certificate_na
+
+ = portalEmptyState('There are no web certificates on this account yet.') ?>
+
@@ -49,6 +52,7 @@ $certificates_sql = mysqli_query($mysqli, "SELECT certificate_id, certificate_na
+
diff --git a/client/contacts.php b/client/contacts.php
index 3e6a30a0e..da6ad32e5 100644
--- a/client/contacts.php
+++ b/client/contacts.php
@@ -26,6 +26,9 @@ $contacts_sql = mysqli_query($mysqli, "SELECT contact_id, contact_name, contact_
+
+ = portalEmptyState('There are no contacts on this account yet.') ?>
+
@@ -68,6 +71,7 @@ $contacts_sql = mysqli_query($mysqli, "SELECT contact_id, contact_name, contact_
+
diff --git a/client/documents.php b/client/documents.php
index 9fb6cb5aa..845c94524 100644
--- a/client/documents.php
+++ b/client/documents.php
@@ -31,6 +31,9 @@ $documents_sql = mysqli_query($mysqli, "SELECT document_id, document_name, docum
+
+ = portalEmptyState('There are no documents shared with you yet.') ?>
+
@@ -73,6 +76,7 @@ $documents_sql = mysqli_query($mysqli, "SELECT document_id, document_name, docum
+
diff --git a/client/domains.php b/client/domains.php
index f66cfa7e2..03c5d8b32 100644
--- a/client/domains.php
+++ b/client/domains.php
@@ -18,6 +18,9 @@ $domains_sql = mysqli_query($mysqli, "SELECT domain_id, domain_name, domain_expi
+
+ = portalEmptyState('There are no domains on this account yet.') ?>
+
@@ -43,6 +46,7 @@ $domains_sql = mysqli_query($mysqli, "SELECT domain_id, domain_name, domain_expi
+
diff --git a/client/functions.php b/client/functions.php
index 142b82259..18f3bfe03 100644
--- a/client/functions.php
+++ b/client/functions.php
@@ -72,6 +72,21 @@ function enforceContactCan($capability) {
}
}
+/*
+ * The empty state for the portal's list pages.
+ *
+ * Every list page here renders a header row and then a while loop, so a client
+ * with no assets, no quotes or no documents used to get a table with nothing
+ * under it - indistinguishable from a page that failed to load. This says so
+ * instead.
+ *
+ * Default is neutral, for a list that simply has nothing in it yet. Pass
+ * 'success' where empty is genuinely good news (nothing owed, nothing unpaid).
+ */
+function portalEmptyState($message, $icon = 'fa-inbox', $type = 'secondary') {
+ return '' . $message . '
';
+}
+
/*
* Returns appropriate FontAwesome icon for file extension
*/
diff --git a/client/invoices.php b/client/invoices.php
index 37f61ba2d..74abf32f9 100644
--- a/client/invoices.php
+++ b/client/invoices.php
@@ -20,6 +20,9 @@ $invoices_sql = mysqli_query($mysqli, "SELECT invoice_amount, invoice_date, invo
+
+ = portalEmptyState('There are no invoices on this account yet.') ?>
+
@@ -89,6 +92,7 @@ $invoices_sql = mysqli_query($mysqli, "SELECT invoice_amount, invoice_date, invo
+
diff --git a/client/quotes.php b/client/quotes.php
index bc084818f..985210d63 100644
--- a/client/quotes.php
+++ b/client/quotes.php
@@ -19,6 +19,9 @@ $quotes_sql = mysqli_query($mysqli, "SELECT quote_amount, quote_date, quote_id,
+
+ = portalEmptyState('There are no quotes on this account yet.') ?>
+
@@ -80,6 +83,7 @@ $quotes_sql = mysqli_query($mysqli, "SELECT quote_amount, quote_date, quote_id,
+
diff --git a/client/recurring_invoices.php b/client/recurring_invoices.php
index 4573e5678..a5bd1da47 100644
--- a/client/recurring_invoices.php
+++ b/client/recurring_invoices.php
@@ -35,6 +35,9 @@ $payment_provider_threshold = floatval($row['payment_provider_threshold']);
+
+ = portalEmptyState('There are no recurring invoices set up on this account.') ?>
+
@@ -105,6 +108,7 @@ $payment_provider_threshold = floatval($row['payment_provider_threshold']);
+
diff --git a/client/statement.php b/client/statement.php
index 338485c8a..d3641a255 100644
--- a/client/statement.php
+++ b/client/statement.php
@@ -60,9 +60,7 @@ $statement_total = 0;
-
- There is nothing outstanding on this account.
-
+ = portalEmptyState('There is nothing outstanding on this account.', 'fa-check', 'success') ?>
diff --git a/client/ticket_view_all.php b/client/ticket_view_all.php
index 5eed18891..a0f86097f 100644
--- a/client/ticket_view_all.php
+++ b/client/ticket_view_all.php
@@ -41,6 +41,9 @@ $all_tickets = mysqli_query($mysqli, "SELECT ticket_id, ticket_prefix, ticket_nu
+
+ = portalEmptyState('There are no tickets for this account.') ?>
+
@@ -71,6 +74,7 @@ $all_tickets = mysqli_query($mysqli, "SELECT ticket_id, ticket_prefix, ticket_nu
?>
+
+
+ = portalEmptyState($status === '%' ? 'You have no tickets.' : 'You have no ' . strtolower($status) . ' tickets.') ?>
+
@@ -80,6 +83,7 @@ $total_tickets = intval($row['total_tickets']);
?>
+
diff --git a/client/unpaid_invoices.php b/client/unpaid_invoices.php
index 874107dd3..7bd75f2d1 100644
--- a/client/unpaid_invoices.php
+++ b/client/unpaid_invoices.php
@@ -80,6 +80,9 @@ $balance = $invoice_amounts - $amount_paid;
+
+ = portalEmptyState('There is nothing unpaid on this account.', 'fa-check', 'success') ?>
+
@@ -197,6 +200,7 @@ $balance = $invoice_amounts - $amount_paid;
+