Wysyłka ponowna raportów
This commit is contained in:
parent
944cf1608d
commit
7b7cc9c02a
99
admin.php
99
admin.php
@ -22,6 +22,51 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
header('Location: /admin.php');
|
||||
exit;
|
||||
}
|
||||
if ($action === 'save-notification-email') {
|
||||
if (!diagnostic_admin_is_authenticated()) {
|
||||
diagnostic_flash_set('warning', 'Zaloguj się jako administrator, aby zmienić adres powiadomień.');
|
||||
header('Location: /admin.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$notificationEmail = trim((string)($_POST['notification_email'] ?? ''));
|
||||
if (!filter_var($notificationEmail, FILTER_VALIDATE_EMAIL)) {
|
||||
diagnostic_flash_set('danger', 'Podaj poprawny adres e-mail administratora do powiadomień o nowych prośbach o kontakt.');
|
||||
header('Location: /admin.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
diagnostic_admin_setting_set('admin_notification_email', $notificationEmail);
|
||||
diagnostic_flash_set('success', 'Adres e-mail administratora do powiadomień został zapisany.');
|
||||
header('Location: /admin.php');
|
||||
exit;
|
||||
}
|
||||
if ($action === 'resend-report') {
|
||||
if (!diagnostic_admin_is_authenticated()) {
|
||||
diagnostic_flash_set('warning', 'Zaloguj się jako administrator, aby ponownie wysłać raport.');
|
||||
header('Location: /admin.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$attemptId = (int)($_POST['attempt_id'] ?? 0);
|
||||
if ($attemptId <= 0) {
|
||||
diagnostic_flash_set('danger', 'Nie udało się ustalić, dla której próby należy ponownie wysłać raport.');
|
||||
header('Location: /admin.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
$result = diagnostic_admin_resend_report($attemptId);
|
||||
if (!empty($result['success'])) {
|
||||
$attempt = diagnostic_get_attempt($attemptId);
|
||||
$recipient = $attempt['email'] ?? '';
|
||||
diagnostic_flash_set('success', 'Raport został wysłany ponownie do klienta' . ($recipient !== '' ? ' (' . $recipient . ')' : '') . '.');
|
||||
} else {
|
||||
diagnostic_flash_set('danger', 'Nie udało się ponownie wysłać raportu: ' . (string)($result['error'] ?? 'Nieznany błąd.'));
|
||||
}
|
||||
|
||||
header('Location: /admin.php?attempt=' . $attemptId);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (diagnostic_admin_is_authenticated() && ($_GET['export'] ?? '') === 'csv') {
|
||||
@ -45,6 +90,7 @@ if (!$selectedAttempt && !empty($attempts)) {
|
||||
}
|
||||
$questionMap = diagnostic_question_map();
|
||||
$credentials = diagnostic_admin_credentials();
|
||||
$notificationConfig = diagnostic_admin_is_authenticated() ? diagnostic_admin_notification_config() : ['configured_email' => '', 'fallback_email' => '', 'effective_email' => '', 'source' => 'none'];
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="pl">
|
||||
@ -137,6 +183,41 @@ $credentials = diagnostic_admin_credentials();
|
||||
<div class="col-sm-6 col-lg-3"><div class="metric-card"><strong><?= (int)$stats['average_score'] ?>%</strong><span>Średni wynik</span></div></div>
|
||||
</section>
|
||||
|
||||
<section class="surface-card p-4 mb-4">
|
||||
<div class="row g-4 align-items-start">
|
||||
<div class="col-lg-7">
|
||||
<div class="eyebrow mb-2">Powiadomienia o konsultacji</div>
|
||||
<h2 class="h4 mb-2">Adres administratora dla nowych numerów telefonu</h2>
|
||||
<p class="text-secondary mb-3">Gdy użytkownik poda numer telefonu po ukończeniu diagnozy, system wyśle powiadomienie e-mail właśnie na ten adres.</p>
|
||||
<form method="post" class="row g-3" novalidate>
|
||||
<input type="hidden" name="action" value="save-notification-email">
|
||||
<div class="col-md-8 col-lg-7">
|
||||
<label for="notificationEmail" class="form-label">Adres e-mail administratora</label>
|
||||
<input type="email" class="form-control" id="notificationEmail" name="notification_email" placeholder="np. kontakt@twojafirma.pl" value="<?= htmlspecialchars((string)$notificationConfig['configured_email']) ?>" required>
|
||||
</div>
|
||||
<div class="col-md-4 col-lg-3 d-grid align-self-end">
|
||||
<button type="submit" class="btn btn-dark">Zapisz adres</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-lg-5">
|
||||
<div class="compact-card h-100">
|
||||
<strong>Aktywna konfiguracja</strong>
|
||||
<?php if (($notificationConfig['source'] ?? 'none') === 'panel'): ?>
|
||||
<span>Powiadomienia trafiają na: <strong><?= htmlspecialchars((string)$notificationConfig['effective_email']) ?></strong></span>
|
||||
<span class="text-secondary">Źródło: ustawienie zapisane w panelu administracyjnym.</span>
|
||||
<?php elseif (($notificationConfig['source'] ?? 'none') === 'env'): ?>
|
||||
<span>Powiadomienia tymczasowo trafią na: <strong><?= htmlspecialchars((string)$notificationConfig['effective_email']) ?></strong></span>
|
||||
<span class="text-secondary">To fallback testowy z <code>MAIL_TO</code>. Ustaw adres w panelu, aby zarządzać nim bez edycji środowiska.</span>
|
||||
<?php else: ?>
|
||||
<span>Brak ustawionego adresu do powiadomień.</span>
|
||||
<span class="text-secondary">Do czasu zapisania adresu w panelu e-mail o nowej prośbie o kontakt nie zostanie wysłany.</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="row g-4">
|
||||
<div class="col-xl-8 col-xxl-9">
|
||||
<div class="surface-card p-4 h-100">
|
||||
@ -214,6 +295,24 @@ $credentials = diagnostic_admin_credentials();
|
||||
<div class="col-sm-6"><div class="compact-card"><strong>Telefon kontaktowy</strong><span><?= !empty($selectedAttempt['contact_phone']) ? htmlspecialchars((string)$selectedAttempt['contact_phone']) : '—' ?></span></div></div>
|
||||
<div class="col-sm-6"><div class="compact-card"><strong>Prośba o kontakt</strong><span><?= htmlspecialchars((string)($selectedAttempt['consultation_requested_at'] ?? '—')) ?></span></div></div>
|
||||
<div class="col-sm-6"><div class="compact-card"><strong>Zakończono</strong><span><?= htmlspecialchars((string)($selectedAttempt['completed_at'] ?? '—')) ?></span></div></div>
|
||||
<div class="col-12">
|
||||
<div class="compact-card">
|
||||
<strong>Ponowna wysyłka raportu</strong>
|
||||
<?php if (diagnostic_attempt_can_send_report($selectedAttempt)): ?>
|
||||
<span>Wyślij ponownie raport na adres klienta: <?= htmlspecialchars((string)$selectedAttempt['email']) ?></span>
|
||||
<form method="post" class="mt-3">
|
||||
<input type="hidden" name="action" value="resend-report">
|
||||
<input type="hidden" name="attempt_id" value="<?= (int)$selectedAttempt['id'] ?>">
|
||||
<button type="submit" class="btn btn-sm btn-dark">Wyślij ponownie</button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
<span>Ponowna wysyłka będzie dostępna po ukończeniu diagnozy i wygenerowaniu wyniku.</span>
|
||||
<?php endif; ?>
|
||||
<?php if (!empty($selectedAttempt['email_report_error'])): ?>
|
||||
<span class="text-danger small mt-2">Ostatni błąd wysyłki: <?= htmlspecialchars((string)$selectedAttempt['email_report_error']) ?></span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -32,6 +32,14 @@ function ensure_diagnostic_schema(): void
|
||||
if (!diagnostic_schema_column_exists('diagnostic_attempts', 'consultation_requested_at')) {
|
||||
db()->exec("ALTER TABLE diagnostic_attempts ADD COLUMN consultation_requested_at DATETIME NULL AFTER contact_phone");
|
||||
}
|
||||
|
||||
db()->exec(
|
||||
"CREATE TABLE IF NOT EXISTS diagnostic_settings (
|
||||
setting_key VARCHAR(100) NOT NULL PRIMARY KEY,
|
||||
setting_value VARCHAR(255) NULL,
|
||||
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci"
|
||||
);
|
||||
}
|
||||
|
||||
function diagnostic_schema_column_exists(string $tableName, string $columnName): bool
|
||||
@ -321,17 +329,91 @@ function diagnostic_finalize_attempt(int $attemptId): ?array
|
||||
|
||||
$attempt = diagnostic_get_attempt($attemptId);
|
||||
$emailResult = diagnostic_send_report_email($attempt);
|
||||
|
||||
$emailStmt = db()->prepare('UPDATE diagnostic_attempts SET email_report_status = :status, email_report_error = :error WHERE id = :id');
|
||||
$emailStmt->execute([
|
||||
':status' => $emailResult['success'] ? 'sent' : 'failed',
|
||||
':error' => $emailResult['success'] ? null : ($emailResult['error'] ?? 'Nieznany błąd wysyłki e-mail'),
|
||||
':id' => $attemptId,
|
||||
]);
|
||||
diagnostic_store_report_delivery($attemptId, $emailResult);
|
||||
|
||||
return diagnostic_get_attempt($attemptId);
|
||||
}
|
||||
|
||||
function diagnostic_store_report_delivery(int $attemptId, array $emailResult): void
|
||||
{
|
||||
$emailStmt = db()->prepare(
|
||||
'UPDATE diagnostic_attempts
|
||||
SET email_report_status = :status, email_report_error = :error, updated_at = NOW()
|
||||
WHERE id = :id'
|
||||
);
|
||||
$emailStmt->execute([
|
||||
':status' => !empty($emailResult['success']) ? 'sent' : 'failed',
|
||||
':error' => !empty($emailResult['success']) ? null : ($emailResult['error'] ?? 'Nieznany błąd wysyłki e-mail'),
|
||||
':id' => $attemptId,
|
||||
]);
|
||||
}
|
||||
|
||||
function diagnostic_attempt_can_send_report(array $attempt): bool
|
||||
{
|
||||
return ($attempt['status'] ?? '') === 'completed'
|
||||
&& !empty($attempt['email'])
|
||||
&& filter_var((string)$attempt['email'], FILTER_VALIDATE_EMAIL)
|
||||
&& !empty($attempt['result']);
|
||||
}
|
||||
|
||||
function diagnostic_admin_resend_report(int $attemptId): array
|
||||
{
|
||||
$attempt = diagnostic_get_attempt($attemptId);
|
||||
if (!$attempt) {
|
||||
return ['success' => false, 'error' => 'Nie znaleziono wskazanej próby.'];
|
||||
}
|
||||
|
||||
if (!diagnostic_attempt_can_send_report($attempt)) {
|
||||
return ['success' => false, 'error' => 'Raport można wysłać ponownie tylko dla ukończonej próby z poprawnym adresem e-mail i wynikiem.'];
|
||||
}
|
||||
|
||||
$emailResult = diagnostic_send_report_email($attempt);
|
||||
diagnostic_store_report_delivery($attemptId, $emailResult);
|
||||
|
||||
return $emailResult;
|
||||
}
|
||||
|
||||
function diagnostic_email_escape(?string $value): string
|
||||
{
|
||||
return htmlspecialchars((string)$value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
|
||||
}
|
||||
|
||||
function diagnostic_email_document(string $subject, string $preheader, string $contentHtml): string
|
||||
{
|
||||
$safeSubject = diagnostic_email_escape($subject);
|
||||
$safePreheader = diagnostic_email_escape($preheader);
|
||||
|
||||
return '<!doctype html>'
|
||||
. '<html lang="pl"><head><meta charset="UTF-8"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>' . $safeSubject . '</title></head>'
|
||||
. '<body style="margin:0;padding:0;background-color:#f3f4f6;color:#111827;font-family:Inter,Segoe UI,Arial,sans-serif;">'
|
||||
. '<div style="display:none;max-height:0;overflow:hidden;opacity:0;color:transparent;">' . $safePreheader . '</div>'
|
||||
. '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="width:100%;border-collapse:collapse;background-color:#f3f4f6;">'
|
||||
. '<tr><td align="center" style="padding:24px 12px;">'
|
||||
. '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="max-width:680px;width:100%;border-collapse:collapse;background-color:#ffffff;border:1px solid #e5e7eb;border-radius:20px;overflow:hidden;box-shadow:0 12px 32px rgba(15,23,42,0.08);">'
|
||||
. '<tr><td style="padding:32px 32px 12px;background:linear-gradient(135deg,#111827 0%,#1f2937 100%);color:#ffffff;">'
|
||||
. '<div style="font-size:12px;letter-spacing:0.12em;text-transform:uppercase;opacity:0.72;margin-bottom:12px;">Przegląd procesów</div>'
|
||||
. '<div style="font-size:28px;line-height:1.2;font-weight:700;">' . $safeSubject . '</div>'
|
||||
. '</td></tr>'
|
||||
. '<tr><td style="padding:32px;">' . $contentHtml . '</td></tr>'
|
||||
. '<tr><td style="padding:0 32px 32px;color:#6b7280;font-size:13px;line-height:1.6;">Ta wiadomość została wygenerowana automatycznie przez narzędzie diagnozy dojrzałości procesowej.</td></tr>'
|
||||
. '</table>'
|
||||
. '</td></tr></table>'
|
||||
. '</body></html>';
|
||||
}
|
||||
|
||||
function diagnostic_email_data_table(array $rows): string
|
||||
{
|
||||
$html = '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="width:100%;border-collapse:collapse;margin:16px 0 0;">';
|
||||
foreach ($rows as $label => $value) {
|
||||
$html .= '<tr>'
|
||||
. '<td style="padding:12px 0;border-bottom:1px solid #e5e7eb;width:220px;color:#6b7280;font-size:14px;font-weight:600;vertical-align:top;">' . diagnostic_email_escape((string)$label) . '</td>'
|
||||
. '<td style="padding:12px 0;border-bottom:1px solid #e5e7eb;color:#111827;font-size:14px;">' . diagnostic_email_escape((string)$value) . '</td>'
|
||||
. '</tr>';
|
||||
}
|
||||
return $html . '</table>';
|
||||
}
|
||||
|
||||
|
||||
function diagnostic_build_report_html(array $attempt): string
|
||||
{
|
||||
$result = $attempt['result'] ?? [];
|
||||
@ -339,24 +421,51 @@ function diagnostic_build_report_html(array $attempt): string
|
||||
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
|
||||
$resultUrl = $scheme . '://' . $host . '/diagnostic.php?view=result';
|
||||
|
||||
$weakest = '';
|
||||
$priorityCards = '';
|
||||
foreach (($result['weakest_areas'] ?? []) as $area) {
|
||||
$weakest .= '<li><strong>' . htmlspecialchars($area['section_name']) . ':</strong> ' . (int)$area['percentage'] . '% dojrzałości — ten obszar najprawdopodobniej generuje dziś największe tarcia, opóźnienia lub ukryte ryzyka.</li>';
|
||||
$priorityCards .= '<div style="margin:0 0 12px;padding:16px 18px;border:1px solid #e5e7eb;border-radius:14px;background:#f9fafb;">'
|
||||
. '<div style="font-size:12px;letter-spacing:0.08em;text-transform:uppercase;color:#6b7280;margin-bottom:6px;">Priorytet</div>'
|
||||
. '<div style="font-size:16px;font-weight:700;color:#111827;margin-bottom:4px;">' . diagnostic_email_escape($area['section_name'] ?? '') . '</div>'
|
||||
. '<div style="font-size:14px;color:#374151;">' . (int)($area['percentage'] ?? 0) . '% dojrzałości — ten obszar najczęściej wymaga najszybszego uporządkowania.</div>'
|
||||
. '</div>';
|
||||
}
|
||||
if ($priorityCards === '') {
|
||||
$priorityCards = '<p style="margin:0;color:#6b7280;">Brak danych o priorytetowych obszarach do pokazania w tym raporcie.</p>';
|
||||
}
|
||||
|
||||
$recommendations = '';
|
||||
foreach (($result['recommendations'] ?? []) as $item) {
|
||||
$recommendations .= '<li>' . htmlspecialchars($item) . '</li>';
|
||||
$recommendations .= '<li style="margin:0 0 10px;">' . diagnostic_email_escape((string)$item) . '</li>';
|
||||
}
|
||||
if ($recommendations === '') {
|
||||
$recommendations = '<li style="margin:0;">Brak dodatkowych rekomendacji.</li>';
|
||||
}
|
||||
|
||||
return '<div style="font-family:Inter,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif;color:#111827;line-height:1.6">'
|
||||
. '<h1 style="font-size:24px;margin:0 0 12px">Raport z diagnozy dojrzałości procesowej</h1>'
|
||||
. '<p style="margin:0 0 16px">Dziękujemy za wypełnienie diagnozy. Obecny poziom dojrzałości operacyjnej Twojej firmy to <strong>' . htmlspecialchars($result['segment_label'] ?? 'Diagnoza zakończona') . '</strong> (' . (int)($result['percentage_score'] ?? 0) . '%).</p>'
|
||||
. '<p style="margin:0 0 16px">' . htmlspecialchars($result['segment_summary'] ?? '') . '</p>'
|
||||
. '<h2 style="font-size:18px;margin:24px 0 8px">Priorytetowe obszary</h2><ul>' . $weakest . '</ul>'
|
||||
. '<h2 style="font-size:18px;margin:24px 0 8px">Rekomendowane kolejne kroki</h2><ul>' . $recommendations . '</ul>'
|
||||
. '<p style="margin:24px 0 0">Jeśli chcesz omówić wynik i ustalić priorytety zmian, wróć do podsumowania: <a href="' . htmlspecialchars($resultUrl) . '">' . htmlspecialchars($resultUrl) . '</a>.</p>'
|
||||
$content = '<p style="margin:0 0 18px;font-size:16px;line-height:1.7;color:#374151;">Dziękujemy za wypełnienie diagnozy. Obecny poziom dojrzałości operacyjnej Twojej firmy to <strong>' . diagnostic_email_escape($result['segment_label'] ?? 'Diagnoza zakończona') . '</strong>.</p>'
|
||||
. '<table role="presentation" width="100%" cellspacing="0" cellpadding="0" style="width:100%;border-collapse:collapse;margin:0 0 24px;">'
|
||||
. '<tr>'
|
||||
. '<td style="padding:20px;border-radius:18px;background:linear-gradient(135deg,#f9fafb 0%,#eef2f7 100%);border:1px solid #e5e7eb;">'
|
||||
. '<div style="font-size:13px;letter-spacing:0.08em;text-transform:uppercase;color:#6b7280;margin-bottom:8px;">Wynik łączny</div>'
|
||||
. '<div style="font-size:36px;line-height:1;font-weight:700;color:#111827;margin-bottom:10px;">' . (int)($result['percentage_score'] ?? 0) . '%</div>'
|
||||
. '<div style="font-size:15px;line-height:1.7;color:#374151;">' . diagnostic_email_escape($result['segment_summary'] ?? '') . '</div>'
|
||||
. '</td>'
|
||||
. '</tr>'
|
||||
. '</table>'
|
||||
. '<h2 style="font-size:18px;line-height:1.3;margin:0 0 12px;color:#111827;">Priorytetowe obszary do poprawy</h2>'
|
||||
. $priorityCards
|
||||
. '<h2 style="font-size:18px;line-height:1.3;margin:28px 0 12px;color:#111827;">Rekomendowane kolejne kroki</h2>'
|
||||
. '<ul style="margin:0;padding:0 0 0 20px;color:#374151;font-size:15px;line-height:1.7;">' . $recommendations . '</ul>'
|
||||
. '<div style="margin:28px 0 0;padding:18px 20px;border-radius:16px;background:#111827;color:#ffffff;">'
|
||||
. '<div style="font-size:16px;font-weight:700;margin-bottom:6px;">Chcesz omówić wynik z zespołem?</div>'
|
||||
. '<div style="font-size:14px;line-height:1.7;opacity:0.88;margin-bottom:14px;">Wróć do podsumowania diagnozy, aby ustalić priorytety zmian i zamówić kolejny krok.</div>'
|
||||
. '<a href="' . diagnostic_email_escape($resultUrl) . '" style="display:inline-block;padding:12px 18px;border-radius:12px;background:#ffffff;color:#111827;text-decoration:none;font-weight:700;">Otwórz podsumowanie diagnozy</a>'
|
||||
. '</div>';
|
||||
|
||||
return diagnostic_email_document(
|
||||
'Raport z diagnozy dojrzałości procesowej',
|
||||
'Twój wynik diagnozy i rekomendowane kolejne kroki są gotowe.',
|
||||
$content
|
||||
);
|
||||
}
|
||||
|
||||
function diagnostic_build_report_text(array $attempt): string
|
||||
@ -391,6 +500,126 @@ function diagnostic_send_report_email(array $attempt): array
|
||||
return MailService::sendMail($attempt['email'], $subject, $html, $text);
|
||||
}
|
||||
|
||||
function diagnostic_admin_setting_get(string $key): ?string
|
||||
{
|
||||
$stmt = db()->prepare('SELECT setting_value FROM diagnostic_settings WHERE setting_key = :setting_key LIMIT 1');
|
||||
$stmt->execute([':setting_key' => $key]);
|
||||
$value = $stmt->fetchColumn();
|
||||
if ($value === false || $value === null) {
|
||||
return null;
|
||||
}
|
||||
return trim((string)$value);
|
||||
}
|
||||
|
||||
function diagnostic_admin_setting_set(string $key, ?string $value): void
|
||||
{
|
||||
$stmt = db()->prepare(
|
||||
'INSERT INTO diagnostic_settings (setting_key, setting_value)
|
||||
VALUES (:setting_key, :setting_value)
|
||||
ON DUPLICATE KEY UPDATE setting_value = VALUES(setting_value), updated_at = CURRENT_TIMESTAMP'
|
||||
);
|
||||
$stmt->bindValue(':setting_key', $key, PDO::PARAM_STR);
|
||||
if ($value === null || $value === '') {
|
||||
$stmt->bindValue(':setting_value', null, PDO::PARAM_NULL);
|
||||
} else {
|
||||
$stmt->bindValue(':setting_value', $value, PDO::PARAM_STR);
|
||||
}
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
function diagnostic_admin_notification_config(): array
|
||||
{
|
||||
$configuredEmail = diagnostic_admin_setting_get('admin_notification_email') ?? '';
|
||||
if ($configuredEmail !== '' && !filter_var($configuredEmail, FILTER_VALIDATE_EMAIL)) {
|
||||
$configuredEmail = '';
|
||||
}
|
||||
|
||||
$fallbackEmail = trim((string)(getenv('MAIL_TO') ?: ''));
|
||||
if ($fallbackEmail !== '' && !filter_var($fallbackEmail, FILTER_VALIDATE_EMAIL)) {
|
||||
$fallbackEmail = '';
|
||||
}
|
||||
|
||||
$effectiveEmail = $configuredEmail !== '' ? $configuredEmail : $fallbackEmail;
|
||||
$source = $configuredEmail !== '' ? 'panel' : ($fallbackEmail !== '' ? 'env' : 'none');
|
||||
|
||||
return [
|
||||
'configured_email' => $configuredEmail,
|
||||
'fallback_email' => $fallbackEmail,
|
||||
'effective_email' => $effectiveEmail,
|
||||
'source' => $source,
|
||||
];
|
||||
}
|
||||
|
||||
function diagnostic_admin_notification_email(): ?string
|
||||
{
|
||||
$config = diagnostic_admin_notification_config();
|
||||
return $config['effective_email'] !== '' ? $config['effective_email'] : null;
|
||||
}
|
||||
|
||||
function diagnostic_send_consultation_notification(array $attempt): array
|
||||
{
|
||||
$recipient = diagnostic_admin_notification_email();
|
||||
if ($recipient === null) {
|
||||
return ['success' => false, 'error' => 'Brak skonfigurowanego adresu powiadomień administratora', 'reason' => 'missing_recipient'];
|
||||
}
|
||||
|
||||
$phone = trim((string)($attempt['contact_phone'] ?? ''));
|
||||
if ($phone === '') {
|
||||
return ['success' => false, 'error' => 'Brak numeru telefonu do przekazania', 'reason' => 'missing_phone'];
|
||||
}
|
||||
|
||||
$result = $attempt['result'] ?? [];
|
||||
$score = isset($result['percentage_score']) ? (int)$result['percentage_score'] . '%' : '—';
|
||||
$segment = (string)($result['segment_label'] ?? '—');
|
||||
$requestedAt = (string)($attempt['consultation_requested_at'] ?? date('Y-m-d H:i:s'));
|
||||
$respondentEmail = trim((string)($attempt['email'] ?? ''));
|
||||
$marketingConsent = ((int)($attempt['marketing_consent'] ?? 0)) === 1 ? 'Tak' : 'Nie';
|
||||
|
||||
$subject = 'Nowa prośba o konsultację po diagnozie';
|
||||
$html = diagnostic_email_document(
|
||||
$subject,
|
||||
'Użytkownik zakończył diagnozę i poprosił o kontakt telefoniczny.',
|
||||
'<p style="margin:0 0 18px;font-size:16px;line-height:1.7;color:#374151;">Użytkownik zakończył diagnozę i poprosił o dalszą konsultację.</p>'
|
||||
. '<div style="padding:18px 20px;border:1px solid #dbeafe;border-radius:16px;background:#eff6ff;color:#1d4ed8;margin-bottom:20px;">'
|
||||
. '<div style="font-size:13px;letter-spacing:0.08em;text-transform:uppercase;opacity:0.72;margin-bottom:6px;">Telefon kontaktowy</div>'
|
||||
. '<div style="font-size:28px;line-height:1.1;font-weight:700;color:#111827;">' . diagnostic_email_escape($phone) . '</div>'
|
||||
. '</div>'
|
||||
. diagnostic_email_data_table([
|
||||
'ID próby' => (string)(int)($attempt['id'] ?? 0),
|
||||
'E-mail respondenta' => $respondentEmail !== '' ? $respondentEmail : '—',
|
||||
'Data zgłoszenia' => $requestedAt,
|
||||
'Wynik diagnozy' => $score,
|
||||
'Segment' => $segment,
|
||||
'Zgoda marketingowa' => $marketingConsent,
|
||||
])
|
||||
);
|
||||
|
||||
$text = "Nowa prośba o kontakt
|
||||
|
||||
"
|
||||
. "ID próby: " . (int)($attempt['id'] ?? 0) . "
|
||||
"
|
||||
. "E-mail respondenta: " . ($respondentEmail !== '' ? $respondentEmail : '—') . "
|
||||
"
|
||||
. "Telefon kontaktowy: {$phone}
|
||||
"
|
||||
. "Data zgłoszenia: {$requestedAt}
|
||||
"
|
||||
. "Wynik diagnozy: {$score}
|
||||
"
|
||||
. "Segment: {$segment}
|
||||
"
|
||||
. "Zgoda marketingowa: {$marketingConsent}
|
||||
";
|
||||
|
||||
$opts = [];
|
||||
if ($respondentEmail !== '' && filter_var($respondentEmail, FILTER_VALIDATE_EMAIL)) {
|
||||
$opts['reply_to'] = $respondentEmail;
|
||||
}
|
||||
|
||||
return MailService::sendMail($recipient, $subject, $html, $text, $opts);
|
||||
}
|
||||
|
||||
function diagnostic_flash_set(string $type, string $message): void
|
||||
{
|
||||
$_SESSION['diagnostic_flash'] = ['type' => $type, 'message' => $message];
|
||||
|
||||
@ -98,7 +98,18 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
}
|
||||
|
||||
diagnostic_save_contact_phone((int)$attempt['id'], $phone);
|
||||
diagnostic_flash_set('success', 'Dziękujemy. Numer telefonu został zapisany — skontaktujemy się w sprawie dalszej konsultacji.');
|
||||
$updatedAttempt = diagnostic_get_attempt((int)$attempt['id']) ?? $attempt;
|
||||
$notificationResult = diagnostic_send_consultation_notification($updatedAttempt);
|
||||
|
||||
if (!empty($notificationResult['success'])) {
|
||||
diagnostic_flash_set('success', 'Dziękujemy. Numer telefonu został zapisany, a administrator otrzymał powiadomienie e-mail o prośbie o kontakt.');
|
||||
} elseif (($notificationResult['reason'] ?? '') === 'missing_recipient') {
|
||||
diagnostic_flash_set('warning', 'Numer telefonu został zapisany, ale adres powiadomień administratora nie jest jeszcze ustawiony w panelu administracyjnym.');
|
||||
} else {
|
||||
error_log('Consultation notification email failed: ' . ($notificationResult['error'] ?? 'unknown'));
|
||||
diagnostic_flash_set('warning', 'Numer telefonu został zapisany, ale nie udało się wysłać powiadomienia e-mail do administratora.');
|
||||
}
|
||||
|
||||
header('Location: /diagnostic.php?view=result');
|
||||
exit;
|
||||
}
|
||||
|
||||
@ -43,6 +43,8 @@ class MailService
|
||||
|
||||
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
|
||||
try {
|
||||
$mail->CharSet = 'UTF-8';
|
||||
$mail->Encoding = PHPMailer\PHPMailer\PHPMailer::ENCODING_BASE64;
|
||||
$mail->isSMTP();
|
||||
$mail->Host = $cfg['smtp_host'] ?? '';
|
||||
$mail->Port = (int)($cfg['smtp_port'] ?? 587);
|
||||
@ -158,6 +160,8 @@ class MailService
|
||||
{
|
||||
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
|
||||
try {
|
||||
$mail->CharSet = 'UTF-8';
|
||||
$mail->Encoding = PHPMailer\PHPMailer\PHPMailer::ENCODING_BASE64;
|
||||
$mail->isSMTP();
|
||||
$mail->Host = $cfg['smtp_host'] ?? '';
|
||||
$mail->Port = (int)($cfg['smtp_port'] ?? 587);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user