Autosave: 20260715-060021
This commit is contained in:
parent
bb9b9b3670
commit
82bca45582
@ -445,6 +445,73 @@ try {
|
||||
require_once 'layout_header.php';
|
||||
?>
|
||||
|
||||
<style>
|
||||
.cc-callcenter-table tbody td {
|
||||
padding-top: .5rem;
|
||||
padding-bottom: .5rem;
|
||||
}
|
||||
|
||||
.cc-callcenter-table .small {
|
||||
line-height: 1.15;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form {
|
||||
padding: .5rem !important;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form.has-accent {
|
||||
border-left: .45rem solid var(--cc-assessor-accent, #adb5bd);
|
||||
background: linear-gradient(135deg, rgba(var(--cc-assessor-accent-rgb, 173, 181, 189), .12) 0%, rgba(255, 255, 255, .98) 72%);
|
||||
}
|
||||
|
||||
.cc-callcenter-assessor-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .3rem;
|
||||
background-color: rgba(var(--cc-assessor-accent-rgb, 173, 181, 189), .12);
|
||||
color: #212529;
|
||||
border-color: rgba(var(--cc-assessor-accent-rgb, 173, 181, 189), .28) !important;
|
||||
}
|
||||
|
||||
.cc-callcenter-color-dot {
|
||||
width: .55rem;
|
||||
height: .55rem;
|
||||
border-radius: 999px;
|
||||
background: var(--cc-assessor-accent, #adb5bd);
|
||||
border: 1px solid rgba(0, 0, 0, .12);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .22);
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-row {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
gap: .35rem;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-row .form-select {
|
||||
min-width: 11rem;
|
||||
flex: 1 1 11rem;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-submit {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.cc-callcenter-actions {
|
||||
gap: .35rem !important;
|
||||
}
|
||||
|
||||
.cc-callcenter-action-btn {
|
||||
padding: .2rem .55rem;
|
||||
line-height: 1.1;
|
||||
font-size: .78rem;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<main class="container-fluid py-4">
|
||||
<section class="mb-4">
|
||||
<div class="d-flex flex-column flex-xl-row justify-content-between align-items-xl-center gap-3">
|
||||
@ -579,7 +646,7 @@ require_once 'layout_header.php';
|
||||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle mb-0">
|
||||
<table class="table table-hover align-middle mb-0 cc-callcenter-table">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>N° Pedido</th>
|
||||
@ -712,7 +779,7 @@ require_once 'layout_header.php';
|
||||
<div class="small text-muted mt-1">Nota: <?php echo htmlspecialchars(cc_test_display_value($order['nota_seguimiento'], 'Sin nota interna')); ?></div>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<div class="d-flex flex-column gap-2 align-items-stretch">
|
||||
<div class="d-flex flex-column gap-1 align-items-stretch cc-callcenter-actions">
|
||||
<?php if (in_array($_SESSION['user_role'] ?? '', ['Administrador', 'admin'], true)): ?>
|
||||
<?php
|
||||
$orderUserId = $order['user_id'] ?? null;
|
||||
@ -728,15 +795,13 @@ require_once 'layout_header.php';
|
||||
}
|
||||
}
|
||||
|
||||
$assignFormClass = 'border rounded-3 p-2 text-start shadow-sm';
|
||||
$assignFormClass = 'border rounded-3 p-1 text-start shadow-sm cc-callcenter-assign-form';
|
||||
$assignFormStyle = '';
|
||||
if ($unassigned) {
|
||||
$assignFormClass .= ' bg-light';
|
||||
} elseif ($assignedAssessorKey === 'KARINA') {
|
||||
$assignFormClass .= ' bg-primary-subtle border-primary';
|
||||
} elseif ($assignedAssessorKey === 'ESTEFANYA') {
|
||||
$assignFormClass .= ' bg-success-subtle border-success';
|
||||
} elseif ($assignedAssessorKey === 'CARMEN') {
|
||||
$assignFormClass .= ' bg-warning-subtle border-warning';
|
||||
} elseif ($assignedAssessorKey !== null) {
|
||||
$assignFormClass .= ' has-accent';
|
||||
$assignFormStyle = cc_test_assessor_css_vars($assignedAssessorKey, $assessors[$assignedAssessorKey]['color_hex'] ?? null);
|
||||
} else {
|
||||
$assignFormClass .= ' bg-secondary-subtle border-secondary';
|
||||
}
|
||||
@ -748,7 +813,7 @@ require_once 'layout_header.php';
|
||||
: ($assignedAssessorKey !== null ? 'Guardar asignación' : 'Desasignar');
|
||||
?>
|
||||
|
||||
<form method="post" class="<?php echo $assignFormClass; ?>">
|
||||
<form method="post" class="<?php echo htmlspecialchars($assignFormClass); ?>"<?php echo $assignFormStyle !== '' ? ' style="' . htmlspecialchars($assignFormStyle, ENT_QUOTES) . '"' : ''; ?>>
|
||||
<input type="hidden" name="action" value="assign_assessor">
|
||||
<input type="hidden" name="source_key" value="<?php echo htmlspecialchars($order['source_key']); ?>">
|
||||
|
||||
@ -756,36 +821,37 @@ require_once 'layout_header.php';
|
||||
<div class="small text-uppercase text-muted fw-semibold">Asignar a asesora</div>
|
||||
<?php if ($unassigned): ?>
|
||||
<span class="badge bg-light text-dark border">Sin asignar</span>
|
||||
<?php elseif ($assignedAssessorKey === 'KARINA'): ?>
|
||||
<span class="badge bg-primary-subtle text-primary-emphasis border">KARINA</span>
|
||||
<?php elseif ($assignedAssessorKey === 'ESTEFANYA'): ?>
|
||||
<span class="badge bg-success-subtle text-success-emphasis border">ESTEFANYA</span>
|
||||
<?php elseif ($assignedAssessorKey === 'CARMEN'): ?>
|
||||
<span class="badge bg-warning-subtle text-warning-emphasis border">CARMEN</span>
|
||||
<?php elseif ($assignedAssessorKey !== null): ?>
|
||||
<span class="badge border cc-callcenter-assessor-badge">
|
||||
<span class="cc-callcenter-color-dot" aria-hidden="true"></span>
|
||||
<?php echo htmlspecialchars((string) ($assessors[$assignedAssessorKey]['label'] ?? $assignedAssessorKey)); ?>
|
||||
</span>
|
||||
<?php else: ?>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis border">Asignado</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<select name="target_assessor" class="form-select form-select-sm mb-2">
|
||||
<option value=""<?php echo ($selectedAssessorKeyForSelect === '') ? ' selected' : ''; ?>>Sin asignar</option>
|
||||
<div class="cc-callcenter-assign-row">
|
||||
<select name="target_assessor" class="form-select form-select-sm">
|
||||
<option value=""<?php echo ($selectedAssessorKeyForSelect === '') ? ' selected' : ''; ?>>Sin asignar</option>
|
||||
|
||||
<?php if ($unassigned): ?>
|
||||
<?php foreach ($assessors as $assessorKey => $assessor): ?>
|
||||
<option value="<?php echo htmlspecialchars($assessorKey); ?>"<?php echo ($selectedAssessorKeyForSelect === $assessorKey) ? ' selected' : ''; ?>><?php echo htmlspecialchars($assessor['label']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php elseif ($assignedAssessorKey !== null): ?>
|
||||
<option value="<?php echo htmlspecialchars((string) $assignedAssessorKey); ?>" selected><?php echo htmlspecialchars((string) ($assessors[$assignedAssessorKey]['label'] ?? $assignedAssessorKey)); ?></option>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
<?php if ($unassigned): ?>
|
||||
<?php foreach ($assessors as $assessorKey => $assessor): ?>
|
||||
<option value="<?php echo htmlspecialchars($assessorKey); ?>"<?php echo ($selectedAssessorKeyForSelect === $assessorKey) ? ' selected' : ''; ?>><?php echo htmlspecialchars($assessor['label']); ?></option>
|
||||
<?php endforeach; ?>
|
||||
<?php elseif ($assignedAssessorKey !== null): ?>
|
||||
<option value="<?php echo htmlspecialchars((string) $assignedAssessorKey); ?>" selected><?php echo htmlspecialchars((string) ($assessors[$assignedAssessorKey]['label'] ?? $assignedAssessorKey)); ?></option>
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
|
||||
<button type="submit" class="btn btn-sm btn-primary w-100"><?php echo htmlspecialchars((string) $buttonLabel); ?></button>
|
||||
<button type="submit" class="btn btn-sm btn-primary cc-callcenter-assign-submit cc-callcenter-action-btn"><?php echo htmlspecialchars((string) $buttonLabel); ?></button>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($order['telefono_url'])): ?>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-primary"
|
||||
class="btn btn-sm btn-primary cc-callcenter-action-btn"
|
||||
data-source-key="<?php echo htmlspecialchars($order['source_key']); ?>"
|
||||
data-modal-id="<?php echo htmlspecialchars($modalId); ?>"
|
||||
data-phone="<?php echo htmlspecialchars((string) ($order['celular'] ?? '')); ?>"
|
||||
@ -795,14 +861,14 @@ require_once 'layout_header.php';
|
||||
<i class="bi bi-telephone-outbound"></i> Llamar / Gestionar
|
||||
</button>
|
||||
<?php else: ?>
|
||||
<button type="button" class="btn btn-sm btn-primary" disabled>Sin teléfono</button>
|
||||
<button type="button" class="btn btn-sm btn-primary cc-callcenter-action-btn" disabled>Sin teléfono</button>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($order['whatsapp_url'])): ?>
|
||||
<a href="<?php echo htmlspecialchars($order['whatsapp_url']); ?>" target="_blank" rel="noopener" class="btn btn-sm btn-outline-success">
|
||||
<a href="<?php echo htmlspecialchars($order['whatsapp_url']); ?>" target="_blank" rel="noopener" class="btn btn-sm btn-outline-success cc-callcenter-action-btn">
|
||||
<i class="bi bi-whatsapp"></i> WhatsApp
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
<button type="button" class="btn btn-sm btn-outline-dark" data-bs-toggle="modal" data-bs-target="#<?php echo htmlspecialchars($modalId); ?>">
|
||||
<button type="button" class="btn btn-sm btn-outline-dark cc-callcenter-action-btn" data-bs-toggle="modal" data-bs-target="#<?php echo htmlspecialchars($modalId); ?>">
|
||||
<i class="bi bi-sliders"></i> Gestionar
|
||||
</button>
|
||||
</div>
|
||||
|
||||
3
db/migrations/091_add_color_hex_to_users.sql
Normal file
3
db/migrations/091_add_color_hex_to_users.sql
Normal file
@ -0,0 +1,3 @@
|
||||
-- Add configurable color for call center assessors in the assignment panel.
|
||||
ALTER TABLE `users`
|
||||
ADD COLUMN IF NOT EXISTS `color_hex` VARCHAR(7) NULL AFTER `nombre_asesor`;
|
||||
@ -414,6 +414,28 @@ try {
|
||||
}));
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'update_assessor_color') {
|
||||
$assessorKey = cc_test_normalize_user_key((string) ($_POST['assessor_key'] ?? ''));
|
||||
if ($assessorKey === '' || !isset($assessors[$assessorKey])) {
|
||||
throw new RuntimeException('No se encontró la asesora seleccionada.');
|
||||
}
|
||||
|
||||
$colorHex = cc_test_normalize_hex_color((string) ($_POST['color_hex'] ?? ''));
|
||||
if ($colorHex === null) {
|
||||
throw new RuntimeException('Selecciona un color válido.');
|
||||
}
|
||||
|
||||
cc_test_ensure_column($pdo, 'users', 'color_hex', 'VARCHAR(7) NULL AFTER `nombre_asesor`');
|
||||
|
||||
$stmtUpdateAssessorColor = $pdo->prepare('UPDATE users SET color_hex = :color_hex WHERE id = :id LIMIT 1');
|
||||
$stmtUpdateAssessorColor->bindValue(':color_hex', $colorHex, PDO::PARAM_STR);
|
||||
$stmtUpdateAssessorColor->bindValue(':id', (int) ($assessors[$assessorKey]['id'] ?? 0), PDO::PARAM_INT);
|
||||
$stmtUpdateAssessorColor->execute();
|
||||
|
||||
$noticeMessage = 'Color actualizado para ' . ($assessors[$assessorKey]['label'] ?? $assessorKey) . '.';
|
||||
$assessors[$assessorKey]['color_hex'] = $colorHex;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'auto_assign_cupo') {
|
||||
$openStates = cc_test_open_states();
|
||||
|
||||
@ -690,6 +712,21 @@ try {
|
||||
'remaining' => $remaining,
|
||||
'text_class' => (string) ($styles['text'] ?? 'text-secondary'),
|
||||
'badge_class' => (string) ($styles['badge'] ?? 'bg-secondary-subtle text-secondary-emphasis border'),
|
||||
'accent_style' => cc_test_assessor_css_vars($assessorKey, $assessors[$assessorKey]['color_hex'] ?? null),
|
||||
];
|
||||
}
|
||||
|
||||
$assessorUiCatalog = [];
|
||||
foreach ($orderedAssessorKeys as $assessorKey) {
|
||||
if (!isset($assessors[$assessorKey])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$catalogColorHex = cc_test_assessor_effective_color_hex($assessorKey, $assessors[$assessorKey]['color_hex'] ?? null);
|
||||
$assessorUiCatalog[$assessorKey] = [
|
||||
'label' => (string) ($assessors[$assessorKey]['label'] ?? $assessorKey),
|
||||
'color_hex' => $catalogColorHex,
|
||||
'contrast_hex' => cc_test_assessor_contrast_text_hex($catalogColorHex),
|
||||
];
|
||||
}
|
||||
|
||||
@ -798,8 +835,62 @@ require_once 'layout_header.php';
|
||||
box-shadow: inset 4px 0 0 #0d6efd;
|
||||
}
|
||||
|
||||
.cc-callcenter-assessor-summary-card {
|
||||
border-left: .45rem solid var(--cc-assessor-accent, #adb5bd) !important;
|
||||
background-color: rgba(var(--cc-assessor-accent-rgb, 173, 181, 189), .16);
|
||||
box-shadow: inset 0 0 0 1px rgba(var(--cc-assessor-accent-rgb, 173, 181, 189), .22);
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form {
|
||||
padding: .5rem !important;
|
||||
width: 100%;
|
||||
padding: .72rem !important;
|
||||
border: 1px solid rgba(var(--cc-assessor-accent-rgb, 173, 181, 189), .38) !important;
|
||||
border-left: .55rem solid var(--cc-assessor-accent, #adb5bd);
|
||||
background-color: var(--cc-assessor-accent, #adb5bd);
|
||||
color: var(--cc-assessor-accent-contrast, #212529);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form.is-unassigned {
|
||||
border-color: rgba(0, 0, 0, .10) !important;
|
||||
border-left-color: #FFFFFF;
|
||||
background-color: #FFFFFF;
|
||||
color: #212529;
|
||||
box-shadow: 0 .65rem 1.4rem rgba(15, 23, 42, .06), inset 0 0 0 1px rgba(0, 0, 0, .05);
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form .text-muted {
|
||||
color: var(--cc-assessor-accent-contrast, #212529) !important;
|
||||
opacity: .88;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form.is-unassigned .text-muted {
|
||||
color: #6C757D !important;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form .cc-callcenter-assessor-badge {
|
||||
background-color: rgba(0, 0, 0, .16);
|
||||
color: var(--cc-assessor-accent-contrast, #212529);
|
||||
border-color: rgba(0, 0, 0, .16) !important;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form.is-unassigned .cc-callcenter-assessor-badge {
|
||||
background-color: #F8F9FA;
|
||||
color: #6C757D;
|
||||
border-color: rgba(0, 0, 0, .12) !important;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .04);
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form .cc-callcenter-assessor-badge .cc-callcenter-color-dot {
|
||||
border: 1px solid rgba(0, 0, 0, .18);
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form.is-unassigned .cc-callcenter-assessor-badge .cc-callcenter-color-dot {
|
||||
background: #ADB5BD;
|
||||
border-color: rgba(0, 0, 0, .12);
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-row {
|
||||
@ -807,20 +898,126 @@ require_once 'layout_header.php';
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
gap: .35rem;
|
||||
padding: .5rem;
|
||||
border-radius: .95rem;
|
||||
background-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form.is-unassigned .cc-callcenter-assign-row {
|
||||
background-color: #FFFFFF;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-row .form-select {
|
||||
min-width: 11rem;
|
||||
flex: 1 1 11rem;
|
||||
min-width: 10rem;
|
||||
flex: 1 1 10rem;
|
||||
border-color: rgba(0, 0, 0, .18);
|
||||
background-color: rgba(0, 0, 0, .12);
|
||||
color: var(--cc-assessor-accent-contrast, #212529);
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form.is-unassigned .cc-callcenter-assign-row .form-select {
|
||||
border-color: rgba(0, 0, 0, .16);
|
||||
background-color: #FFFFFF;
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-row .form-select:focus {
|
||||
border-color: rgba(0, 0, 0, .24);
|
||||
box-shadow: 0 0 0 .2rem rgba(0, 0, 0, .12);
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-submit {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
border-color: rgba(0, 0, 0, .18) !important;
|
||||
background-color: rgba(0, 0, 0, .16) !important;
|
||||
color: var(--cc-assessor-accent-contrast, #212529) !important;
|
||||
font-weight: 700;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
|
||||
}
|
||||
|
||||
.cc-callcenter-actions {
|
||||
gap: .35rem !important;
|
||||
.cc-callcenter-assessor-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: .3rem;
|
||||
background-color: var(--cc-assessor-accent, #adb5bd);
|
||||
color: var(--cc-assessor-accent-contrast, #212529);
|
||||
border-color: var(--cc-assessor-accent, #adb5bd) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.cc-callcenter-color-trigger {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: .3rem;
|
||||
padding: .2rem .55rem;
|
||||
white-space: nowrap;
|
||||
border-color: rgba(0, 0, 0, .18) !important;
|
||||
background-color: rgba(0, 0, 0, .12);
|
||||
color: var(--cc-assessor-accent-contrast, #212529);
|
||||
font-weight: 700;
|
||||
box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .08);
|
||||
}
|
||||
|
||||
.cc-callcenter-color-trigger:hover:not(:disabled),
|
||||
.cc-callcenter-assign-submit:hover:not(:disabled) {
|
||||
filter: brightness(.97);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.cc-callcenter-color-trigger:disabled {
|
||||
opacity: .72;
|
||||
background-color: rgba(0, 0, 0, .10);
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form.is-unassigned .cc-callcenter-color-trigger {
|
||||
background-color: #F1F3F5;
|
||||
color: #6C757D;
|
||||
border-color: rgba(0, 0, 0, .12) !important;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form.is-unassigned .cc-callcenter-color-trigger:disabled {
|
||||
background-color: #F1F3F5;
|
||||
}
|
||||
|
||||
.cc-callcenter-color-trigger .cc-callcenter-color-dot {
|
||||
width: .72rem;
|
||||
height: .72rem;
|
||||
border-radius: 999px;
|
||||
background: var(--cc-assessor-accent, #adb5bd);
|
||||
border: 1px solid rgba(0, 0, 0, .24);
|
||||
box-shadow: none;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.cc-callcenter-assign-form.is-unassigned .cc-callcenter-color-trigger .cc-callcenter-color-dot {
|
||||
background: #ADB5BD;
|
||||
border-color: rgba(0, 0, 0, .16);
|
||||
}
|
||||
|
||||
.cc-callcenter-assessor-badge .cc-callcenter-color-dot {
|
||||
width: .55rem;
|
||||
height: .55rem;
|
||||
border-radius: 999px;
|
||||
background: var(--cc-assessor-accent-contrast, #212529);
|
||||
border: 1px solid rgba(255, 255, 255, .35);
|
||||
box-shadow: none;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.cc-callcenter-assessor-summary-card .cc-callcenter-color-dot {
|
||||
width: .55rem;
|
||||
height: .55rem;
|
||||
border-radius: 999px;
|
||||
background: var(--cc-assessor-accent, #adb5bd);
|
||||
border: 1px solid rgba(0, 0, 0, .12);
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .22);
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.cc-callcenter-action-btn {
|
||||
@ -1015,10 +1212,13 @@ require_once 'layout_header.php';
|
||||
|
||||
<div class="d-flex flex-wrap gap-2 align-items-stretch justify-content-lg-end">
|
||||
<?php foreach ($assessorSummaryCards as $assessorCard): ?>
|
||||
<div class="border rounded-3 bg-light px-3 py-2" style="min-width: 240px;">
|
||||
<div class="border rounded-3 bg-light px-3 py-2 cc-callcenter-assessor-summary-card" style="min-width: 240px; <?php echo htmlspecialchars((string) $assessorCard['accent_style']); ?>">
|
||||
<div class="d-flex justify-content-between align-items-center gap-2">
|
||||
<div class="fw-bold <?php echo htmlspecialchars((string) $assessorCard['text_class']); ?>"><?php echo htmlspecialchars((string) $assessorCard['label']); ?></div>
|
||||
<span class="badge <?php echo htmlspecialchars((string) $assessorCard['badge_class']); ?>">Pendientes: <?php echo (int) $assessorCard['pending']; ?></span>
|
||||
<div class="fw-bold d-flex align-items-center gap-2">
|
||||
<span class="cc-callcenter-color-dot" aria-hidden="true"></span>
|
||||
<span><?php echo htmlspecialchars((string) $assessorCard['label']); ?></span>
|
||||
</div>
|
||||
<span class="badge border cc-callcenter-assessor-badge">Pendientes: <?php echo (int) $assessorCard['pending']; ?></span>
|
||||
</div>
|
||||
<div class="mt-2">
|
||||
<div class="small text-muted">Cupo restante (<?php echo (int) $cupoObjetivoPorAsesora; ?>)</div>
|
||||
@ -1171,51 +1371,46 @@ require_once 'layout_header.php';
|
||||
}
|
||||
}
|
||||
|
||||
$assignFormClass = 'border rounded-3 p-1 text-start shadow-sm cc-callcenter-assign-form';
|
||||
if ($unassigned) {
|
||||
$assignFormClass .= ' bg-light';
|
||||
} elseif ($assignedAssessorKey === 'KARINA') {
|
||||
$assignFormClass .= ' bg-primary-subtle border-primary';
|
||||
} elseif ($assignedAssessorKey === 'ESTEFANYA') {
|
||||
$assignFormClass .= ' bg-success-subtle border-success';
|
||||
} elseif ($assignedAssessorKey === 'CARMEN') {
|
||||
$assignFormClass .= ' bg-warning-subtle border-warning';
|
||||
} else {
|
||||
$assignFormClass .= ' bg-secondary-subtle border-secondary';
|
||||
}
|
||||
$selectedAssessorKeyForSelect = $assignedAssessorKey !== null
|
||||
? (string) $assignedAssessorKey
|
||||
: '';
|
||||
|
||||
if ($unassigned) {
|
||||
$selectedAssessorKeyForSelect = !empty($recommendedAssessorKey) ? (string) $recommendedAssessorKey : '';
|
||||
} else {
|
||||
$selectedAssessorKeyForSelect = $assignedAssessorKey !== null ? (string) $assignedAssessorKey : '';
|
||||
}
|
||||
$assignAccentKey = $selectedAssessorKeyForSelect !== ''
|
||||
? (string) $selectedAssessorKeyForSelect
|
||||
: ($assignedAssessorKey !== null ? (string) $assignedAssessorKey : '');
|
||||
|
||||
$buttonLabel = $unassigned
|
||||
? 'Asignar pedido'
|
||||
: ($assignedAssessorKey !== null ? 'Guardar asignación' : 'Desasignar');
|
||||
$assignAccentHex = $assignAccentKey !== ''
|
||||
? cc_test_assessor_effective_color_hex(
|
||||
$assignAccentKey,
|
||||
$assessors[$assignAccentKey]['color_hex'] ?? null
|
||||
)
|
||||
: '#FFFFFF';
|
||||
|
||||
$assignFormStyle = cc_test_assessor_css_vars(
|
||||
$assignAccentKey !== '' ? $assignAccentKey : 'DEFAULT',
|
||||
$assignAccentHex
|
||||
);
|
||||
$assignFormIsUnassigned = $assignAccentKey === '';
|
||||
|
||||
$badgeLabel = $unassigned
|
||||
? 'Sin asignar'
|
||||
: (string) ($assessors[$assignedAssessorKey]['label'] ?? ($assignedAssessorKey ?? 'Asignado'));
|
||||
?>
|
||||
|
||||
<form method="post" class="<?php echo $assignFormClass; ?>">
|
||||
<form method="post" class="border rounded-3 p-1 text-start cc-callcenter-assign-form<?php echo $assignFormIsUnassigned ? ' is-unassigned' : ''; ?>" style="<?php echo htmlspecialchars($assignFormStyle); ?>">
|
||||
<input type="hidden" name="action" value="assign_assessor">
|
||||
<input type="hidden" name="source_key" value="<?php echo htmlspecialchars($order['source_key']); ?>">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center gap-2 mb-1">
|
||||
<div class="small text-uppercase text-muted fw-semibold">Asignar a asesora</div>
|
||||
<?php if ($unassigned): ?>
|
||||
<span class="badge bg-light text-dark border">Sin asignar</span>
|
||||
<?php elseif ($assignedAssessorKey === 'KARINA'): ?>
|
||||
<span class="badge bg-primary-subtle text-primary-emphasis border">KARINA</span>
|
||||
<?php elseif ($assignedAssessorKey === 'ESTEFANYA'): ?>
|
||||
<span class="badge bg-success-subtle text-success-emphasis border">ESTEFANYA</span>
|
||||
<?php elseif ($assignedAssessorKey === 'CARMEN'): ?>
|
||||
<span class="badge bg-warning-subtle text-warning-emphasis border">CARMEN</span>
|
||||
<?php else: ?>
|
||||
<span class="badge bg-secondary-subtle text-secondary-emphasis border">Asignado</span>
|
||||
<?php endif; ?>
|
||||
<span class="badge border cc-callcenter-assessor-badge">
|
||||
<span class="cc-callcenter-color-dot" aria-hidden="true"></span>
|
||||
<span class="cc-callcenter-assessor-label"><?php echo htmlspecialchars($badgeLabel); ?></span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="cc-callcenter-assign-row">
|
||||
<select name="target_assessor" class="form-select form-select-sm">
|
||||
<select name="target_assessor" class="form-select form-select-sm js-assessor-select">
|
||||
<option value=""<?php echo ($selectedAssessorKeyForSelect === '') ? ' selected' : ''; ?>>Sin asignar</option>
|
||||
|
||||
<?php if ($unassigned): ?>
|
||||
@ -1227,7 +1422,13 @@ require_once 'layout_header.php';
|
||||
<?php endif; ?>
|
||||
</select>
|
||||
|
||||
<button type="submit" class="btn btn-sm btn-primary cc-callcenter-assign-submit cc-callcenter-action-btn"><?php echo htmlspecialchars((string) $buttonLabel); ?></button>
|
||||
<button type="button" class="btn btn-sm cc-callcenter-color-trigger js-assessor-color-trigger" title="Selecciona una asesora para cambiar su color" aria-label="Selecciona una asesora para cambiar su color"<?php echo $selectedAssessorKeyForSelect === '' ? ' disabled' : ''; ?>>
|
||||
<span class="cc-callcenter-color-dot" aria-hidden="true"></span>
|
||||
<i class="bi bi-palette"></i>
|
||||
<span>Color</span>
|
||||
</button>
|
||||
|
||||
<button type="submit" class="btn btn-sm cc-callcenter-assign-submit cc-callcenter-action-btn">Asignar pedido</button>
|
||||
</div>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
@ -1748,6 +1949,50 @@ require_once 'layout_header.php';
|
||||
", $modalsHtml); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="modal fade" id="ccAssessorColorModal" tabindex="-1" aria-labelledby="ccAssessorColorModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<form method="post" id="ccAssessorColorForm">
|
||||
<div class="modal-header align-items-start gap-2">
|
||||
<div>
|
||||
<div class="small text-uppercase text-muted fw-semibold">Color de asesora</div>
|
||||
<h3 class="modal-title h5 mb-0" id="ccAssessorColorModalLabel">Configurar color</h3>
|
||||
</div>
|
||||
<button type="button" class="btn-close mt-1" data-bs-dismiss="modal" aria-label="Cerrar"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" name="action" value="update_assessor_color">
|
||||
<input type="hidden" name="assessor_key" id="ccAssessorColorAssessorKey">
|
||||
<div class="mb-3">
|
||||
<label for="ccAssessorColorAssessorLabel" class="form-label">Asesora</label>
|
||||
<input type="text" class="form-control" id="ccAssessorColorAssessorLabel" readonly>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="ccAssessorColorInput" class="form-label">Color</label>
|
||||
<div class="d-flex align-items-center gap-3 flex-wrap">
|
||||
<input type="color" class="form-control form-control-color" id="ccAssessorColorInput" name="color_hex" value="#0D6EFD" title="Elegir color">
|
||||
<code class="small" id="ccAssessorColorHexText">#0D6EFD</code>
|
||||
</div>
|
||||
<div class="form-text">Este color se aplicará a la franja, al badge y al panel de rendimiento de la asesora.</div>
|
||||
</div>
|
||||
<div class="rounded-4 border p-3" id="ccAssessorColorPreview">
|
||||
<div class="small text-muted">Vista previa</div>
|
||||
<div class="fw-semibold mt-1" id="ccAssessorColorPreviewLabel">Asesora</div>
|
||||
<code class="small" id="ccAssessorColorPreviewHex">#0D6EFD</code>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer d-flex justify-content-between flex-wrap gap-2">
|
||||
<div class="small text-muted">Guarda un color diferente para reconocer rápido cada asesora.</div>
|
||||
<div class="d-flex gap-2 ms-auto flex-wrap">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Cancelar</button>
|
||||
<button type="submit" class="btn btn-primary">Guardar color</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="position-fixed bottom-0 end-0 p-3" id="airDroidAssistPanel" style="z-index: 1080; max-width: 26rem; width: min(26rem, calc(100vw - 1.5rem));">
|
||||
<div class="card border-primary shadow-lg d-none" id="airDroidAssistCard">
|
||||
<div class="card-header bg-primary text-white d-flex align-items-start justify-content-between gap-3">
|
||||
@ -1786,6 +2031,7 @@ require_once 'layout_header.php';
|
||||
<script>
|
||||
const provinciasPorDepartamento = <?php echo json_encode($provinciasPorDepartamentoContraentrega, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>;
|
||||
const distritosPorProvincia = <?php echo json_encode($distritosPorProvinciaContraentrega, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>;
|
||||
const ccAssessorCatalog = <?php echo json_encode($assessorUiCatalog, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); ?>;
|
||||
|
||||
function getLocationControls(sourceKey) {
|
||||
return {
|
||||
@ -2454,6 +2700,159 @@ const clearSelectedOrders = document.getElementById('clearSelectedOrders');
|
||||
const bulkOrderCheckboxes = Array.from(document.querySelectorAll('.js-bulk-order-checkbox'));
|
||||
const quickSelectButtons = Array.from(document.querySelectorAll('.js-quick-select-btn'));
|
||||
const bulkAssessorSelect = bulkAssignForm ? bulkAssignForm.querySelector('select[name="target_assessor"]') : null;
|
||||
const ccAssessorColorModalElement = document.getElementById('ccAssessorColorModal');
|
||||
const ccAssessorColorModalInstance = ccAssessorColorModalElement && window.bootstrap && window.bootstrap.Modal
|
||||
? window.bootstrap.Modal.getOrCreateInstance(ccAssessorColorModalElement)
|
||||
: null;
|
||||
const ccAssessorColorAssessorKey = document.getElementById('ccAssessorColorAssessorKey');
|
||||
const ccAssessorColorAssessorLabel = document.getElementById('ccAssessorColorAssessorLabel');
|
||||
const ccAssessorColorInput = document.getElementById('ccAssessorColorInput');
|
||||
const ccAssessorColorHexText = document.getElementById('ccAssessorColorHexText');
|
||||
const ccAssessorColorPreview = document.getElementById('ccAssessorColorPreview');
|
||||
const ccAssessorColorPreviewLabel = document.getElementById('ccAssessorColorPreviewLabel');
|
||||
const ccAssessorColorPreviewHex = document.getElementById('ccAssessorColorPreviewHex');
|
||||
|
||||
function normalizeAssessorHexColor(value) {
|
||||
value = String(value || '').trim().toUpperCase();
|
||||
if (!value) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (value.charAt(0) !== '#') {
|
||||
value = '#' + value;
|
||||
}
|
||||
|
||||
return /^#[0-9A-F]{6}$/.test(value) ? value : '';
|
||||
}
|
||||
|
||||
function assessorHexToRgbTriplet(hex) {
|
||||
const normalized = normalizeAssessorHexColor(hex);
|
||||
if (!normalized) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const intValue = parseInt(normalized.slice(1), 16);
|
||||
return [
|
||||
(intValue >> 16) & 255,
|
||||
(intValue >> 8) & 255,
|
||||
intValue & 255
|
||||
];
|
||||
}
|
||||
|
||||
function syncAssessorColorPreview(colorHex, assessorLabel) {
|
||||
const resolvedHex = normalizeAssessorHexColor(colorHex) || '#ADB5BD';
|
||||
const rgb = assessorHexToRgbTriplet(resolvedHex) || [173, 181, 189];
|
||||
const backgroundColor = 'rgba(' + rgb.join(', ') + ', .16)';
|
||||
const borderColor = 'rgba(' + rgb.join(', ') + ', .28)';
|
||||
|
||||
if (ccAssessorColorPreview) {
|
||||
ccAssessorColorPreview.style.background = backgroundColor;
|
||||
ccAssessorColorPreview.style.borderColor = borderColor;
|
||||
}
|
||||
if (ccAssessorColorPreviewLabel) {
|
||||
ccAssessorColorPreviewLabel.textContent = assessorLabel || 'Asesora';
|
||||
}
|
||||
if (ccAssessorColorPreviewHex) {
|
||||
ccAssessorColorPreviewHex.textContent = resolvedHex;
|
||||
}
|
||||
if (ccAssessorColorHexText) {
|
||||
ccAssessorColorHexText.textContent = resolvedHex;
|
||||
}
|
||||
}
|
||||
|
||||
function syncAssessorFormAccent(form) {
|
||||
if (!form) {
|
||||
return;
|
||||
}
|
||||
|
||||
const select = form.querySelector('.js-assessor-select');
|
||||
const colorButton = form.querySelector('.js-assessor-color-trigger');
|
||||
const assessorKey = select ? (select.value || '') : '';
|
||||
const config = assessorKey && ccAssessorCatalog[assessorKey] ? ccAssessorCatalog[assessorKey] : null;
|
||||
const isUnassigned = !assessorKey || !config;
|
||||
const colorHex = isUnassigned
|
||||
? '#FFFFFF'
|
||||
: (normalizeAssessorHexColor(config ? config.color_hex : '') || '#ADB5BD');
|
||||
const rgb = assessorHexToRgbTriplet(colorHex) || [255, 255, 255];
|
||||
const contrastHex = isUnassigned
|
||||
? '#212529'
|
||||
: (normalizeAssessorHexColor(config ? config.contrast_hex : '') || '#212529');
|
||||
|
||||
form.classList.toggle('is-unassigned', isUnassigned);
|
||||
form.style.setProperty('--cc-assessor-accent', colorHex);
|
||||
form.style.setProperty('--cc-assessor-accent-rgb', rgb.join(', '));
|
||||
form.style.setProperty('--cc-assessor-accent-contrast', contrastHex);
|
||||
|
||||
if (colorButton) {
|
||||
colorButton.disabled = !assessorKey;
|
||||
const buttonTitle = assessorKey && config
|
||||
? 'Cambiar color de ' + config.label
|
||||
: 'Selecciona una asesora para cambiar su color';
|
||||
colorButton.title = buttonTitle;
|
||||
colorButton.setAttribute('aria-label', buttonTitle);
|
||||
|
||||
const dot = colorButton.querySelector('.cc-callcenter-color-dot');
|
||||
if (dot) {
|
||||
dot.style.backgroundColor = isUnassigned ? '#ADB5BD' : colorHex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function openAssessorColorModal(trigger) {
|
||||
const form = trigger ? trigger.closest('form') : null;
|
||||
const select = form ? form.querySelector('.js-assessor-select') : null;
|
||||
const assessorKey = select ? (select.value || '') : '';
|
||||
const config = assessorKey && ccAssessorCatalog[assessorKey] ? ccAssessorCatalog[assessorKey] : null;
|
||||
|
||||
if (!assessorKey || !config) {
|
||||
alert('Selecciona una asesora para cambiar su color.');
|
||||
return;
|
||||
}
|
||||
|
||||
const colorHex = normalizeAssessorHexColor(config.color_hex) || '#ADB5BD';
|
||||
|
||||
if (ccAssessorColorAssessorKey) {
|
||||
ccAssessorColorAssessorKey.value = assessorKey;
|
||||
}
|
||||
if (ccAssessorColorAssessorLabel) {
|
||||
ccAssessorColorAssessorLabel.value = config.label || assessorKey;
|
||||
}
|
||||
if (ccAssessorColorInput) {
|
||||
ccAssessorColorInput.value = colorHex.toLowerCase();
|
||||
}
|
||||
|
||||
syncAssessorColorPreview(colorHex, config.label || assessorKey);
|
||||
|
||||
if (ccAssessorColorModalInstance) {
|
||||
ccAssessorColorModalInstance.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
document.querySelectorAll('.cc-callcenter-assign-form').forEach(function (form) {
|
||||
syncAssessorFormAccent(form);
|
||||
|
||||
const select = form.querySelector('.js-assessor-select');
|
||||
if (select) {
|
||||
select.addEventListener('change', function () {
|
||||
syncAssessorFormAccent(form);
|
||||
});
|
||||
}
|
||||
|
||||
const colorButton = form.querySelector('.js-assessor-color-trigger');
|
||||
if (colorButton) {
|
||||
colorButton.addEventListener('click', function () {
|
||||
openAssessorColorModal(this);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (ccAssessorColorInput) {
|
||||
ccAssessorColorInput.addEventListener('input', function () {
|
||||
const label = ccAssessorColorAssessorLabel ? (ccAssessorColorAssessorLabel.value || 'Asesora') : 'Asesora';
|
||||
syncAssessorColorPreview(this.value, label);
|
||||
});
|
||||
}
|
||||
|
||||
function getSelectedBulkOrderCheckboxes() {
|
||||
return bulkOrderCheckboxes.filter(function (checkbox) {
|
||||
|
||||
@ -17,6 +17,110 @@ function cc_test_ensure_column(PDO $pdo, string $table, string $column, string $
|
||||
$cache[$key] = true;
|
||||
}
|
||||
|
||||
function cc_test_column_exists(PDO $pdo, string $table, string $column): bool
|
||||
{
|
||||
static $cache = [];
|
||||
$key = $table . '.' . $column;
|
||||
if (array_key_exists($key, $cache)) {
|
||||
return $cache[$key];
|
||||
}
|
||||
|
||||
try {
|
||||
$stmt = $pdo->prepare("SHOW COLUMNS FROM `{$table}` LIKE ?");
|
||||
$stmt->execute([$column]);
|
||||
$cache[$key] = (bool) $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
} catch (Throwable $exception) {
|
||||
$cache[$key] = false;
|
||||
}
|
||||
|
||||
return $cache[$key];
|
||||
}
|
||||
|
||||
function cc_test_normalize_hex_color(?string $value): ?string
|
||||
{
|
||||
$value = strtoupper(trim((string) $value));
|
||||
if ($value === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($value[0] !== '#') {
|
||||
$value = '#' . $value;
|
||||
}
|
||||
|
||||
return preg_match('/^#[0-9A-F]{6}$/', $value) ? $value : null;
|
||||
}
|
||||
|
||||
function cc_test_hex_to_rgb_triplet(string $hex): ?array
|
||||
{
|
||||
$normalized = cc_test_normalize_hex_color($hex);
|
||||
if ($normalized === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$normalized = ltrim($normalized, '#');
|
||||
|
||||
return [
|
||||
hexdec(substr($normalized, 0, 2)),
|
||||
hexdec(substr($normalized, 2, 2)),
|
||||
hexdec(substr($normalized, 4, 2)),
|
||||
];
|
||||
}
|
||||
|
||||
function cc_test_assessor_default_color_hex(string $assessorKey): string
|
||||
{
|
||||
return match (cc_test_normalize_user_key($assessorKey)) {
|
||||
'KARINA' => '#0D6EFD',
|
||||
'ESTEFANYA' => '#198754',
|
||||
'CARMEN' => '#FF00FF',
|
||||
default => '#6C757D',
|
||||
};
|
||||
}
|
||||
|
||||
function cc_test_assessor_effective_color_hex(string $assessorKey, ?string $storedColorHex = null): string
|
||||
{
|
||||
return cc_test_normalize_hex_color($storedColorHex) ?? cc_test_assessor_default_color_hex($assessorKey);
|
||||
}
|
||||
|
||||
function cc_test_hex_relative_luminance(string $hex): float
|
||||
{
|
||||
$rgb = cc_test_hex_to_rgb_triplet($hex) ?? [108, 117, 125];
|
||||
$linear = array_map(
|
||||
static function (int $channel): float {
|
||||
$value = $channel / 255;
|
||||
return $value <= 0.03928
|
||||
? $value / 12.92
|
||||
: pow(($value + 0.055) / 1.055, 2.4);
|
||||
},
|
||||
$rgb
|
||||
);
|
||||
|
||||
return (0.2126 * $linear[0]) + (0.7152 * $linear[1]) + (0.0722 * $linear[2]);
|
||||
}
|
||||
|
||||
function cc_test_assessor_contrast_text_hex(string $hex): string
|
||||
{
|
||||
static $darkText = '#212529';
|
||||
static $darkLuminance = null;
|
||||
|
||||
if ($darkLuminance === null) {
|
||||
$darkLuminance = cc_test_hex_relative_luminance($darkText);
|
||||
}
|
||||
|
||||
$luminance = cc_test_hex_relative_luminance($hex);
|
||||
$contrastWithWhite = 1.05 / ($luminance + 0.05);
|
||||
$contrastWithDark = ($luminance + 0.05) / ($darkLuminance + 0.05);
|
||||
|
||||
return $contrastWithDark >= $contrastWithWhite ? $darkText : '#FFFFFF';
|
||||
}
|
||||
|
||||
function cc_test_assessor_css_vars(string $assessorKey, ?string $storedColorHex = null): string
|
||||
{
|
||||
$hex = cc_test_assessor_effective_color_hex($assessorKey, $storedColorHex);
|
||||
$rgb = cc_test_hex_to_rgb_triplet($hex) ?? [108, 117, 125];
|
||||
|
||||
return '--cc-assessor-accent:' . $hex . '; --cc-assessor-accent-rgb:' . implode(', ', $rgb) . '; --cc-assessor-accent-contrast:' . cc_test_assessor_contrast_text_hex($hex) . ';';
|
||||
}
|
||||
|
||||
function cc_test_ensure_tracking_table(PDO $pdo): void
|
||||
{
|
||||
static $checked = false;
|
||||
@ -140,7 +244,9 @@ function cc_test_fetch_assessors(PDO $pdo, array $allowedNames = []): array
|
||||
$allowedNames = cc_test_default_assessor_keys();
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare("SELECT id, username, nombre_asesor FROM users WHERE role = 'Asesor'");
|
||||
$hasColorColumn = cc_test_column_exists($pdo, 'users', 'color_hex');
|
||||
$selectColorColumn = $hasColorColumn ? ', color_hex' : ', NULL AS color_hex';
|
||||
$stmt = $pdo->prepare("SELECT id, username, nombre_asesor{$selectColorColumn} FROM users WHERE role = 'Asesor'");
|
||||
$stmt->execute();
|
||||
|
||||
$allowedLookup = array_fill_keys(array_map('strtoupper', $allowedNames), true);
|
||||
@ -155,6 +261,7 @@ function cc_test_fetch_assessors(PDO $pdo, array $allowedNames = []): array
|
||||
$byKey[$key] = [
|
||||
'id' => (int) $row['id'],
|
||||
'label' => trim((string) ($row['nombre_asesor'] ?: $row['username'] ?: ('Asesor #' . (int) $row['id']))),
|
||||
'color_hex' => cc_test_normalize_hex_color($row['color_hex'] ?? null),
|
||||
];
|
||||
}
|
||||
|
||||
@ -627,22 +734,22 @@ function cc_test_row_background_style(string $estado): string
|
||||
'POR LLAMAR', 'DEVOLVER LLAMADA' => '#ffffff',
|
||||
|
||||
// Amarillo
|
||||
'OBSERVADO' => '#fff3cd',
|
||||
'OBSERVADO' => '#FFFF00',
|
||||
|
||||
// Verde claro
|
||||
'SE ENVIO NUMERO DE CUENTA' => '#d1e7dd',
|
||||
// Verde brillante
|
||||
'SE ENVIO NUMERO DE CUENTA' => '#00FF00',
|
||||
|
||||
// Naranja
|
||||
'CONFIRMADO CONTRAENTREGA' => '#ffb74d',
|
||||
|
||||
// Verde
|
||||
'CONFIRMADO ENVIO' => '#b6f1c7',
|
||||
// Verde Google
|
||||
'CONFIRMADO ENVIO' => '#34A853',
|
||||
|
||||
// Rojo
|
||||
'CANCELADO' => '#f8d7da',
|
||||
'CANCELADO' => '#FF0000',
|
||||
|
||||
// Plomo
|
||||
'REPETIDO' => '#d6d8db',
|
||||
'REPETIDO' => '#CCCCCC',
|
||||
|
||||
default => '#ffffff',
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user