mirror of
https://github.com/itflow-org/itflow
synced 2026-11-11 07:01:16 +00:00
409 lines
23 KiB
PHP
409 lines
23 KiB
PHP
<?php
|
|
/*
|
|
* Client Portal
|
|
* Home - what needs this contact: tickets waiting on their reply or for them
|
|
* to confirm, approvals, invoices past due, quotes waiting for an answer,
|
|
* contracts waiting for a signature;
|
|
* their open tickets, the balance, the request forms they can use,
|
|
* renewals coming up and the devices they use.
|
|
*
|
|
* SCOPING: everything here is keyed to $session_client_id from the session,
|
|
* tickets through portalTicketScopeSql() (their own, or the whole company's
|
|
* for primary and technical contacts), and the money and IT sections are only
|
|
* read for a contact who may see them.
|
|
*/
|
|
|
|
header("Content-Security-Policy: default-src 'self'");
|
|
|
|
require_once "includes/inc_all.php";
|
|
|
|
$scope_sql = portalTicketScopeSql();
|
|
$sees_all = portalSeesAllTickets();
|
|
$can_billing = contactCan('accounting') && $config_module_enable_accounting == 1;
|
|
$can_it = $config_module_enable_itdoc && contactCan('itdoc');
|
|
$ticket_from = "FROM tickets LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id WHERE $scope_sql AND tickets.ticket_archived_at IS NULL";
|
|
|
|
// Tickets - counted, and the ones that need the contact
|
|
$tabs = portalTicketTabs();
|
|
$counts = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT
|
|
COALESCE(SUM({$tabs['open']['where']}), 0) AS open_count,
|
|
COALESCE(SUM({$tabs['resolved']['where']}), 0) AS resolved_count
|
|
$ticket_from"));
|
|
$open_count = intval($counts['open_count']);
|
|
$resolved_count = intval($counts['resolved_count']);
|
|
$you_count = intval(mysqli_fetch_row(mysqli_query($mysqli, "SELECT COUNT(*) $ticket_from AND {$tabs['you']['where']}"))[0]);
|
|
|
|
$needs_you = [];
|
|
$sql = mysqli_query($mysqli, "SELECT " . portalTicketColumnsSql() . " $ticket_from AND ({$tabs['you']['where']} OR {$tabs['resolved']['where']})
|
|
ORDER BY COALESCE(tickets.ticket_updated_at, tickets.ticket_created_at) DESC LIMIT 6");
|
|
while ($row = mysqli_fetch_assoc($sql)) {
|
|
$resolved = !empty($row['ticket_resolved_at']);
|
|
$needs_you[] = [
|
|
'href' => 'ticket.php?id=' . intval($row['ticket_id']),
|
|
'icon' => $resolved ? 'fa-check' : 'fa-reply',
|
|
'tone' => $resolved ? 'is-info' : '',
|
|
'title' => $row['ticket_subject'],
|
|
'line' => ($resolved ? 'Resolved - is it fixed? Close it, or reopen it' : 'We replied - waiting on you') . ' · ' . $row['ticket_prefix'] . $row['ticket_number'],
|
|
];
|
|
}
|
|
|
|
// Tasks on their tickets waiting for the client's approval
|
|
$sql = mysqli_query($mysqli, "SELECT tickets.ticket_id, ticket_prefix, ticket_number, task_name FROM task_approvals
|
|
JOIN tasks ON task_id = approval_task_id
|
|
JOIN tickets ON tickets.ticket_id = task_ticket_id
|
|
LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id
|
|
WHERE $scope_sql AND approval_scope = 'client' AND approval_status = 'pending' AND task_completed_at IS NULL AND tickets.ticket_closed_at IS NULL
|
|
ORDER BY approval_id DESC LIMIT 4");
|
|
while ($row = mysqli_fetch_assoc($sql)) {
|
|
$needs_you[] = [
|
|
'href' => 'ticket.php?id=' . intval($row['ticket_id']),
|
|
'icon' => 'fa-clipboard-check',
|
|
'tone' => '',
|
|
'title' => 'Approve: ' . $row['task_name'],
|
|
'line' => 'Waiting for your approval · ' . $row['ticket_prefix'] . $row['ticket_number'],
|
|
];
|
|
}
|
|
|
|
// Money - what is owed, and what is past due
|
|
$balance = 0.0;
|
|
$overdue = 0.0;
|
|
$overdue_count = 0;
|
|
$next_due = null;
|
|
$client_currency = $session_company_currency;
|
|
if ($can_billing) {
|
|
$client_currency = mysqli_fetch_row(mysqli_query($mysqli, "SELECT client_currency_code FROM clients WHERE client_id = $session_client_id"))[0] ?: $session_company_currency;
|
|
foreach (billingClientOpenInvoices($session_client_id) as $invoice) {
|
|
$left = round(floatval($invoice['invoice_amount']) - floatval($invoice['paid']), 2);
|
|
$balance += $left;
|
|
if ($invoice['invoice_due'] < date('Y-m-d')) {
|
|
$overdue += $left;
|
|
$overdue_count++;
|
|
$needs_you[] = [
|
|
'href' => 'invoice.php?id=' . intval($invoice['invoice_id']),
|
|
'icon' => 'fa-file-invoice-dollar',
|
|
'tone' => 'is-danger',
|
|
'title' => 'Invoice ' . $invoice['invoice_prefix'] . $invoice['invoice_number'] . ' is past due',
|
|
'line' => numfmt_format_currency($currency_format, $left, $client_currency) . ' left - due ' . date('M j, Y', strtotime($invoice['invoice_due'])),
|
|
];
|
|
} elseif ($next_due === null || $invoice['invoice_due'] < $next_due) {
|
|
$next_due = $invoice['invoice_due'];
|
|
}
|
|
}
|
|
|
|
// Quotes waiting for their answer
|
|
$sql = mysqli_query($mysqli, "SELECT quote_id, quote_prefix, quote_number, quote_scope, quote_amount, quote_currency_code, quote_expire FROM quotes
|
|
WHERE quote_client_id = $session_client_id AND " . portalQuoteWaitingSql() . " ORDER BY quote_expire ASC LIMIT 4");
|
|
while ($row = mysqli_fetch_assoc($sql)) {
|
|
$needs_you[] = [
|
|
'href' => 'quote.php?id=' . intval($row['quote_id']),
|
|
'icon' => 'fa-comment-dollar',
|
|
'tone' => '',
|
|
'title' => 'Quote ' . $row['quote_prefix'] . $row['quote_number'] . ' is waiting for your answer',
|
|
'line' => trim($row['quote_scope'] . ' · ' . billingMoney($row['quote_amount'], $row['quote_currency_code']), ' ·') . ' · good until ' . date('M j', strtotime($row['quote_expire'])),
|
|
];
|
|
}
|
|
|
|
// Contracts waiting for their signature
|
|
if (contractsReady() && contractSignaturesReady()) {
|
|
$sql = mysqli_query($mysqli, "SELECT contract_id, contract_name, contract_type FROM contracts WHERE " . portalContractScopeSql() . " AND " . portalContractWaitingSql() . " ORDER BY contract_name ASC LIMIT 4");
|
|
while ($row = mysqli_fetch_assoc($sql)) {
|
|
$needs_you[] = [
|
|
'href' => 'contract.php?id=' . intval($row['contract_id']),
|
|
'icon' => 'fa-file-signature',
|
|
'tone' => '',
|
|
'title' => $row['contract_name'] . ' is waiting for your signature',
|
|
'line' => contractTypeLabel($row['contract_type']) . ' contract - read it and sign it here',
|
|
];
|
|
}
|
|
}
|
|
}
|
|
$pay_href = $can_billing && billingStripeProvider() ? 'unpaid_invoices.php' : 'invoices.php';
|
|
|
|
// Open tickets, newest first
|
|
$recent = mysqli_query($mysqli, "SELECT " . portalTicketColumnsSql() . ", contact_name FROM tickets
|
|
LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id
|
|
LEFT JOIN contacts ON contact_id = tickets.ticket_contact_id
|
|
WHERE $scope_sql AND tickets.ticket_archived_at IS NULL AND {$tabs['open']['where']}
|
|
ORDER BY COALESCE(tickets.ticket_updated_at, tickets.ticket_created_at) DESC LIMIT 5");
|
|
|
|
// Renewals coming up in the next 45 days, and anything that lapsed in the last 30
|
|
$renewals = [];
|
|
if ($can_it) {
|
|
$window = "BETWEEN CURDATE() - INTERVAL 30 DAY AND CURDATE() + INTERVAL 45 DAY";
|
|
$sources = [
|
|
['domains.php', 'fa-globe', 'Domain', "SELECT domain_name, domain_expire, 0 FROM domains WHERE domain_client_id = $session_client_id AND domain_archived_at IS NULL AND domain_expire $window"],
|
|
['domains.php?tab=certificates', 'fa-lock', 'Certificate', "SELECT certificate_name, certificate_expire, 0 FROM certificates WHERE certificate_client_id = $session_client_id AND certificate_archived_at IS NULL AND certificate_expire $window"],
|
|
['licenses.php', 'fa-cube', 'License', "SELECT software_name, software_expire, 0 FROM software WHERE software_client_id = $session_client_id AND software_archived_at IS NULL AND software_expire $window"],
|
|
['asset.php?id=', 'fa-shield-alt', 'Warranty', "SELECT asset_name, asset_warranty_expire, asset_id FROM assets WHERE asset_client_id = $session_client_id AND asset_archived_at IS NULL AND asset_warranty_expire $window"],
|
|
];
|
|
foreach ($sources as [$href, $icon, $kind, $query]) {
|
|
$sql = mysqli_query($mysqli, $query);
|
|
while ($row = mysqli_fetch_row($sql)) {
|
|
$renewals[] = ['href' => $href . (intval($row[2]) ? intval($row[2]) : ''), 'icon' => $icon, 'kind' => $kind, 'name' => $row[0], 'date' => $row[1]];
|
|
}
|
|
}
|
|
usort($renewals, function ($a, $b) { return strcmp($a['date'], $b['date']); });
|
|
}
|
|
|
|
// The devices this contact uses
|
|
$devices = [];
|
|
$sql = mysqli_query($mysqli, "SELECT asset_id, asset_name, asset_type, asset_make, asset_model, asset_warranty_expire, asset_uri_client FROM assets
|
|
WHERE asset_contact_id = $session_contact_id AND asset_client_id = $session_client_id AND asset_archived_at IS NULL ORDER BY asset_name ASC LIMIT 6");
|
|
while ($row = mysqli_fetch_assoc($sql)) {
|
|
$devices[] = $row;
|
|
}
|
|
|
|
// The request forms they can use - ticket templates offered in the portal
|
|
$request_forms = ticketTemplatePortalForms($session_client_id, $sees_all);
|
|
|
|
// How to reach us
|
|
$company = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT company_phone, company_phone_country_code, company_email, company_website FROM companies WHERE company_id = 1"));
|
|
|
|
$hour = intval(date('G'));
|
|
$greeting = $hour < 12 ? 'Good morning' : ($hour < 18 ? 'Good afternoon' : 'Good evening');
|
|
$first_name = strtok(trim((string) $contact['contact_name']), ' ') ?: '';
|
|
?>
|
|
|
|
<div class="itflow-portal-page-head">
|
|
<div>
|
|
<h1><?= escapeHtml(rtrim("$greeting, $first_name", ', ')) ?></h1>
|
|
<p><?= escapeHtml($session_client_name) ?></p>
|
|
</div>
|
|
<div class="d-flex flex-wrap gap-2">
|
|
<?php if ($can_billing && $balance > 0) { ?>
|
|
<a class="btn btn-outline-primary" href="<?= $pay_href ?>"><i class="fas fa-<?= $pay_href === 'unpaid_invoices.php' ? 'credit-card' : 'file-invoice-dollar' ?> me-2"></i><?= $pay_href === 'unpaid_invoices.php' ? 'Pay invoices' : 'Invoices' ?></a>
|
|
<?php } ?>
|
|
</div>
|
|
</div>
|
|
|
|
<?php foreach (portalAnnouncementsFor($session_client_id) as $announcement) {
|
|
$tone_key = isset(PORTAL_ANNOUNCEMENT_TONES[$announcement['announcement_tone']]) ? $announcement['announcement_tone'] : 'info';
|
|
$tone = PORTAL_ANNOUNCEMENT_TONES[$tone_key]; ?>
|
|
<section class="itflow-portal-announcement is-<?= $tone_key ?> mb-3" aria-label="<?= escapeHtml($tone['label']) ?>">
|
|
<span class="itflow-portal-announcement-icon" aria-hidden="true"><i class="fas <?= $tone['icon'] ?>"></i></span>
|
|
<div class="min-w-0">
|
|
<h2 class="itflow-portal-announcement-title"><?= escapeHtml($announcement['announcement_title']) ?></h2>
|
|
<?php if (trim((string) $announcement['announcement_body']) !== '') { ?>
|
|
<div class="itflow-portal-announcement-body"><?= portalAnnouncementBodyHtml($announcement['announcement_body']) ?></div>
|
|
<?php } ?>
|
|
<div class="small text-body-secondary mt-1"><?= escapeHtml($tone['label']) ?> · <?= escapeHtml(date('M j, Y', strtotime($announcement['announcement_starts_at'] ?: $announcement['announcement_created_at']))) ?></div>
|
|
</div>
|
|
</section>
|
|
<?php } ?>
|
|
|
|
<div class="row g-3 mb-4">
|
|
<div class="col-6 col-lg-3">
|
|
<a class="itflow-portal-stat" href="tickets.php">
|
|
<span class="itflow-portal-stat-icon"><i class="fas fa-life-ring"></i></span>
|
|
<span>
|
|
<span class="itflow-portal-stat-value d-block"><?= $open_count ?></span>
|
|
<span class="itflow-portal-stat-label"><?= $open_count === 1 ? 'Open ticket' : 'Open tickets' ?><?= $sees_all ? '' : ' of yours' ?></span>
|
|
</span>
|
|
</a>
|
|
</div>
|
|
<div class="col-6 col-lg-3">
|
|
<a class="itflow-portal-stat<?= $you_count ? ' itflow-portal-stat-alert' : '' ?>" href="tickets.php?tab=you">
|
|
<span class="itflow-portal-stat-icon"><i class="fas fa-reply"></i></span>
|
|
<span>
|
|
<span class="itflow-portal-stat-value d-block"><?= $you_count ?></span>
|
|
<span class="itflow-portal-stat-label">Waiting on you</span>
|
|
</span>
|
|
</a>
|
|
</div>
|
|
<?php if ($can_billing) { ?>
|
|
<div class="col-6 col-lg-3">
|
|
<a class="itflow-portal-stat<?= $overdue > 0 ? ' itflow-portal-stat-danger' : '' ?>" href="<?= $balance > 0 ? $pay_href : 'invoices.php' ?>">
|
|
<span class="itflow-portal-stat-icon"><i class="fas fa-file-invoice-dollar"></i></span>
|
|
<span class="min-w-0">
|
|
<span class="itflow-portal-stat-value d-block"><?= numfmt_format_currency($currency_format, $balance, $client_currency) ?></span>
|
|
<span class="itflow-portal-stat-label">
|
|
<?php if ($overdue > 0) { ?>
|
|
<?= numfmt_format_currency($currency_format, $overdue, $client_currency) ?> past due
|
|
<?php } elseif ($balance > 0 && $next_due) { ?>
|
|
Due <?= date('M j', strtotime($next_due)) ?>
|
|
<?php } else { ?>
|
|
Nothing owed
|
|
<?php } ?>
|
|
</span>
|
|
</span>
|
|
</a>
|
|
</div>
|
|
<?php } ?>
|
|
<?php if ($can_it) { ?>
|
|
<div class="col-6 col-lg-3">
|
|
<a class="itflow-portal-stat" href="#renewals">
|
|
<span class="itflow-portal-stat-icon"><i class="fas fa-calendar-alt"></i></span>
|
|
<span>
|
|
<span class="itflow-portal-stat-value d-block"><?= count($renewals) ?></span>
|
|
<span class="itflow-portal-stat-label"><?= count($renewals) === 1 ? 'Renewal' : 'Renewals' ?> coming up</span>
|
|
</span>
|
|
</a>
|
|
</div>
|
|
<?php } ?>
|
|
</div>
|
|
|
|
<div class="row g-4">
|
|
<div class="col-lg-8">
|
|
|
|
<section class="itflow-portal-panel mb-4">
|
|
<div class="itflow-portal-panel-head">
|
|
<h2><i class="fas fa-bell"></i>Needs you</h2>
|
|
</div>
|
|
<?php if (!$needs_you) { ?>
|
|
<?= emptyStateHtml(['title' => "You're all caught up", 'text' => 'Nothing is waiting on you right now.', 'icon' => 'fa-check', 'filtered' => false]) ?>
|
|
<?php } else { ?>
|
|
<ul class="itflow-portal-list">
|
|
<?php foreach (array_slice($needs_you, 0, 8) as $item) { ?>
|
|
<li>
|
|
<a class="itflow-portal-todo" href="<?= escapeHtml($item['href']) ?>">
|
|
<span class="itflow-portal-todo-icon <?= $item['tone'] ?>"><i class="fas <?= $item['icon'] ?>"></i></span>
|
|
<span class="itflow-portal-todo-main">
|
|
<div><?= escapeHtml($item['title']) ?></div>
|
|
<div><?= escapeHtml($item['line']) ?></div>
|
|
</span>
|
|
<i class="fas fa-chevron-right text-body-secondary small"></i>
|
|
</a>
|
|
</li>
|
|
<?php } ?>
|
|
</ul>
|
|
<?php } ?>
|
|
</section>
|
|
|
|
<section class="itflow-portal-panel">
|
|
<div class="itflow-portal-panel-head">
|
|
<h2><i class="fas fa-life-ring"></i><?= $sees_all ? 'Open tickets' : 'Your open tickets' ?></h2>
|
|
<a href="tickets.php">All tickets</a>
|
|
</div>
|
|
<?php if (!mysqli_num_rows($recent)) { ?>
|
|
<?= emptyStateHtml(['title' => 'No open tickets', 'text' => 'Something not working? Raise a ticket and we will pick it up.', 'icon' => 'fa-life-ring', 'filtered' => false,
|
|
'actions' => [['label' => 'New ticket', 'href' => 'ticket_add.php']]]) ?>
|
|
<?php } else { ?>
|
|
<ul class="itflow-portal-list">
|
|
<?php while ($row = mysqli_fetch_assoc($recent)) {
|
|
$updated = $row['ticket_updated_at'] ?: $row['ticket_created_at']; ?>
|
|
<li>
|
|
<a class="itflow-portal-ticket" href="ticket.php?id=<?= intval($row['ticket_id']) ?>">
|
|
<span class="itflow-portal-ticket-main">
|
|
<span class="itflow-portal-ticket-subject d-block"><?= escapeHtml($row['ticket_subject']) ?></span>
|
|
<span class="itflow-portal-ticket-meta">
|
|
<span><?= escapeHtml($row['ticket_prefix'] . $row['ticket_number']) ?></span>
|
|
<?php if ($sees_all && !empty($row['contact_name'])) { ?><span><i class="fas fa-user me-1"></i><?= escapeHtml($row['contact_name']) ?></span><?php } ?>
|
|
</span>
|
|
</span>
|
|
<span class="itflow-portal-ticket-side">
|
|
<?= portalTicketStateHtml($row) ?>
|
|
<small title="<?= escapeHtml($updated) ?>"><?= timeAgo($updated) ?></small>
|
|
</span>
|
|
</a>
|
|
</li>
|
|
<?php } ?>
|
|
</ul>
|
|
<?php } ?>
|
|
</section>
|
|
|
|
</div>
|
|
<div class="col-lg-4">
|
|
|
|
<?php if ($request_forms) { ?>
|
|
<section class="itflow-portal-panel mb-4">
|
|
<div class="itflow-portal-panel-head">
|
|
<h2><i class="fas fa-clipboard-list"></i>Ask for something</h2>
|
|
<?php if (count($request_forms) > 5) { ?><a href="ticket_add.php">All <?= count($request_forms) ?></a><?php } ?>
|
|
</div>
|
|
<ul class="itflow-portal-list">
|
|
<?php foreach (array_slice($request_forms, 0, 5) as $row) { ?>
|
|
<li>
|
|
<a class="itflow-portal-todo" href="ticket_add.php?form=<?= intval($row['ticket_template_id']) ?>">
|
|
<span class="itflow-portal-tile itflow-portal-tile-sm"><i class="fas fa-fw <?= ticketTemplatePortalIcon($row) ?>"></i></span>
|
|
<span class="itflow-portal-todo-main">
|
|
<div><?= escapeHtml(ticketTemplatePortalTitle($row)) ?></div>
|
|
<?php if (trim((string) $row['ticket_template_portal_description']) !== '') { ?><div><?= escapeHtml($row['ticket_template_portal_description']) ?></div><?php } ?>
|
|
</span>
|
|
<i class="fas fa-chevron-right text-body-secondary small"></i>
|
|
</a>
|
|
</li>
|
|
<?php } ?>
|
|
</ul>
|
|
</section>
|
|
<?php } ?>
|
|
|
|
<?php if ($devices) { ?>
|
|
<section class="itflow-portal-panel mb-4">
|
|
<div class="itflow-portal-panel-head">
|
|
<h2><i class="fas fa-desktop"></i>Your devices</h2>
|
|
<?php if ($can_it) { ?><a href="assets.php">All devices</a><?php } ?>
|
|
</div>
|
|
<ul class="itflow-portal-list">
|
|
<?php foreach ($devices as $device) {
|
|
$warranty = assetWarranty($device['asset_warranty_expire']);
|
|
$what = trim($device['asset_make'] . ' ' . $device['asset_model']) ?: $device['asset_type'];
|
|
?>
|
|
<li>
|
|
<a class="itflow-portal-todo" href="asset.php?id=<?= intval($device['asset_id']) ?>">
|
|
<span class="itflow-portal-todo-icon is-info"><i class="fas fa-<?= getAssetIcon($device['asset_type']) ?>"></i></span>
|
|
<span class="itflow-portal-todo-main">
|
|
<div><?= escapeHtml($device['asset_name']) ?></div>
|
|
<div>
|
|
<?= escapeHtml($what) ?>
|
|
<?php if ($warranty && $warranty['tone'] !== 'success') { ?>
|
|
· <span class="text-<?= $warranty['tone'] ?>-emphasis">Warranty <?= escapeHtml(strtolower($warranty['short'])) ?></span>
|
|
<?php } ?>
|
|
</div>
|
|
</span>
|
|
<i class="fas fa-chevron-right text-body-secondary small"></i>
|
|
</a>
|
|
</li>
|
|
<?php } ?>
|
|
</ul>
|
|
</section>
|
|
<?php } ?>
|
|
|
|
<?php if ($can_it) { ?>
|
|
<section class="itflow-portal-panel mb-4" id="renewals">
|
|
<div class="itflow-portal-panel-head">
|
|
<h2><i class="fas fa-calendar-alt"></i>Coming up</h2>
|
|
</div>
|
|
<?php if (!$renewals) { ?>
|
|
<?= emptyStateHtml(['title' => 'Nothing renewing soon', 'text' => 'Domains, certificates, licenses and warranties due in the next 45 days show here.', 'icon' => 'fa-check', 'filtered' => false]) ?>
|
|
<?php } else { ?>
|
|
<ul class="itflow-portal-list">
|
|
<?php foreach (array_slice($renewals, 0, 8) as $item) {
|
|
$lapsed = $item['date'] < date('Y-m-d'); ?>
|
|
<li>
|
|
<a class="itflow-portal-todo" href="<?= escapeHtml($item['href']) ?>">
|
|
<span class="itflow-portal-todo-icon<?= $lapsed ? ' is-danger' : '' ?>"><i class="fas <?= $item['icon'] ?>"></i></span>
|
|
<span class="itflow-portal-todo-main">
|
|
<div><?= escapeHtml($item['name']) ?></div>
|
|
<div><?= escapeHtml($item['kind']) ?> · <?= $lapsed ? 'expired' : 'renews' ?> <?= escapeHtml(date('M j, Y', strtotime($item['date']))) ?> (<?= timeAgo($item['date']) ?>)</div>
|
|
</span>
|
|
<i class="fas fa-chevron-right text-body-secondary small"></i>
|
|
</a>
|
|
</li>
|
|
<?php } ?>
|
|
</ul>
|
|
<?php } ?>
|
|
</section>
|
|
<?php } ?>
|
|
|
|
<?php if (!empty($company['company_phone']) || !empty($company['company_email'])) { ?>
|
|
<section class="itflow-portal-panel">
|
|
<div class="itflow-portal-panel-head">
|
|
<h2><i class="fas fa-headset"></i>Need us fast?</h2>
|
|
</div>
|
|
<div class="itflow-portal-panel-body">
|
|
<p class="text-body-secondary small mb-2">For anything urgent, call us - and raise a ticket so it is on record.</p>
|
|
<?php if (!empty($company['company_phone'])) { ?>
|
|
<div class="mb-1"><i class="fas fa-fw fa-phone me-2 text-body-secondary"></i><a href="tel:<?= escapeHtml(phoneDialNumber($company['company_phone'], $company['company_phone_country_code'])) ?>"><?= escapeHtml(formatPhoneNumber($company['company_phone'], $company['company_phone_country_code'])) ?></a></div>
|
|
<?php } ?>
|
|
<?php if (!empty($company['company_email'])) { ?>
|
|
<div><i class="fas fa-fw fa-envelope me-2 text-body-secondary"></i><a href="mailto:<?= escapeHtml($company['company_email']) ?>"><?= escapeHtml($company['company_email']) ?></a></div>
|
|
<?php } ?>
|
|
</div>
|
|
</section>
|
|
<?php } ?>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
<?php require_once "includes/footer.php"; ?>
|