| Server IP : 193.86.120.172 / Your IP : 216.73.216.67 Web Server : Apache/2.4.63 (Unix) System : Linux JServices 3.10.108 #86003 SMP Wed Oct 22 13:20:46 CST 2025 x86_64 User : kubec ( 1026) PHP Version : 8.2.28 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /volume1/web/kadernictvidenisa_cz/includes/ |
Upload File : |
<?php
// ============================================
// includes/mailer.php
// Microsoft 365 – OAuth2 + SMTP AUTH XOAUTH2
// Bez Composeru, čistě PHP streams
// ============================================
require_once __DIR__ . '/config.php';
require_once __DIR__ . '/db.php';
// -----------------------------------------------
// OAuth2 – získání / obnova access tokenu
// -----------------------------------------------
function ms_get_access_token(): string {
// Zkus načíst platný token z DB
$stmt = db()->prepare(
"SELECT access_token, expires_at FROM oauth_tokeny
WHERE provider = 'microsoft' ORDER BY id DESC LIMIT 1"
);
$stmt->execute();
$row = $stmt->fetch();
if ($row && new DateTime() < new DateTime($row['expires_at'])) {
return $row['access_token'];
}
// Token vypršel nebo neexistuje → obnov přes refresh_token
if ($row) {
$stmt2 = db()->prepare(
"SELECT refresh_token FROM oauth_tokeny
WHERE provider = 'microsoft' ORDER BY id DESC LIMIT 1"
);
$stmt2->execute();
$r = $stmt2->fetch();
if ($r) {
return ms_refresh_token($r['refresh_token']);
}
}
throw new RuntimeException(
'OAuth2 token není k dispozici. Dokončete prvotní autorizaci na /admin/oauth-setup.php'
);
}
function ms_refresh_token(string $refresh_token): string {
$url = 'https://login.microsoftonline.com/' . MS_TENANT_ID . '/oauth2/v2.0/token';
$body = http_build_query([
'client_id' => MS_CLIENT_ID,
'client_secret' => MS_CLIENT_SECRET,
'grant_type' => 'refresh_token',
'refresh_token' => $refresh_token,
'scope' => 'https://outlook.office365.com/SMTP.Send offline_access',
]);
$ctx = stream_context_create(['http' => [
'method' => 'POST',
'header' => "Content-Type: application/x-www-form-urlencoded\r\n",
'content' => $body,
'timeout' => 10,
]]);
$resp = file_get_contents($url, false, $ctx);
if ($resp === false) throw new RuntimeException('Nepodařilo se kontaktovat Microsoft OAuth2 server.');
$data = json_decode($resp, true);
if (!isset($data['access_token'])) {
throw new RuntimeException('OAuth2 refresh selhal: ' . ($data['error_description'] ?? $resp));
}
$expires_at = date('Y-m-d H:i:s', time() + (int)$data['expires_in'] - 60);
db()->prepare("
UPDATE oauth_tokeny
SET access_token = ?, refresh_token = ?, expires_at = ?
WHERE provider = 'microsoft'
")->execute([$data['access_token'], $data['refresh_token'] ?? $refresh_token, $expires_at]);
return $data['access_token'];
}
// -----------------------------------------------
// SMTP odesílání s XOAUTH2
// -----------------------------------------------
function smtp_send(string $to, string $to_name, string $subject, string $html_body): bool {
try {
$access_token = ms_get_access_token();
} catch (RuntimeException $e) {
error_log('[Mailer] Token error: ' . $e->getMessage());
return false;
}
$smtp_user = defined('MS_SMTP_USER') ? MS_SMTP_USER : MS_FROM_EMAIL;
$xoauth2 = base64_encode("user=" . $smtp_user . "\x01auth=Bearer " . $access_token . "\x01\x01");
$boundary = md5(uniqid('', true));
$headers = "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/alternative; boundary=\"{$boundary}\"\r\n";
$headers .= "From: " . mime_encode(MS_FROM_NAME) . " <" . MS_FROM_EMAIL . ">\r\n";
$headers .= "To: " . mime_encode($to_name) . " <{$to}>\r\n";
$headers .= "Subject: " . mime_encode($subject) . "\r\n";
$headers .= "X-Mailer: KadernictviMailer/2.0\r\n";
$plain = html_entity_decode(
strip_tags(str_replace('<br>', "\n", str_replace('<br/>', "\n", str_replace('<br />', "\n", $html_body)))),
ENT_QUOTES, 'UTF-8'
);
$body = "--{$boundary}\r\n";
$body .= "Content-Type: text/plain; charset=utf-8\r\n";
$body .= "Content-Transfer-Encoding: base64\r\n\r\n";
$body .= chunk_split(base64_encode($plain)) . "\r\n";
$body .= "--{$boundary}\r\n";
$body .= "Content-Type: text/html; charset=utf-8\r\n";
$body .= "Content-Transfer-Encoding: base64\r\n\r\n";
$body .= chunk_split(base64_encode($html_body)) . "\r\n";
$body .= "--{$boundary}--\r\n";
$errno = 0; $errstr = '';
$sock = fsockopen('smtp.office365.com', 587, $errno, $errstr, 15);
if (!$sock) {
error_log("[Mailer] fsockopen selhal: {$errstr}");
return false;
}
$read = function() use ($sock): string {
$resp = '';
while ($line = fgets($sock, 512)) {
$resp .= $line;
if (isset($line[3]) && $line[3] === ' ') break;
}
return $resp;
};
$cmd = function(string $c) use ($sock, $read): string {
fwrite($sock, $c . "\r\n");
$r = $read();
error_log('[Mailer] ' . substr($c, 0, 20) . ' => ' . trim(substr($r, 0, 80)));
return $r;
};
$read(); // banner
$cmd('EHLO ' . gethostname());
$cmd('STARTTLS');
stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
$cmd('EHLO ' . gethostname());
// AUTH
fwrite($sock, 'AUTH XOAUTH2 ' . $xoauth2 . "\r\n");
$r = $read();
error_log('[Mailer] AUTH => ' . trim(substr($r, 0, 80)));
if (strpos($r, '235') === false) {
error_log("[Mailer] AUTH selhal: {$r}");
fclose($sock);
return false;
}
$r = $cmd('MAIL FROM:<' . MS_FROM_EMAIL . '>');
if (strpos($r, '250') === false) {
error_log("[Mailer] MAIL FROM selhal: {$r}");
fclose($sock);
return false;
}
$r = $cmd('RCPT TO:<' . $to . '>');
if (strpos($r, '250') === false) {
error_log("[Mailer] RCPT TO selhal: {$r}");
fclose($sock);
return false;
}
$cmd('DATA');
fwrite($sock, $headers . "\r\n" . $body . "\r\n.\r\n");
$r = $read();
error_log('[Mailer] DATA response: ' . trim($r));
$cmd('QUIT');
fclose($sock);
$ok = strpos($r, '250') !== false;
if (!$ok) error_log("[Mailer] Odesílání selhalo: {$r}");
return $ok;
}
function mime_encode(string $text): string {
return '=?UTF-8?B?' . base64_encode($text) . '?=';
}
// -----------------------------------------------
// E-mailové šablony
// -----------------------------------------------
function email_potvrzeni(array $rez, string $sluzba_nazev): bool {
$zmena_url = BASE_URL . '/zmena-rezervace.php?token=' . urlencode($rez['token_zmena']);
$zruseni_url = BASE_URL . '/zruseni-rezervace.php?token=' . urlencode($rez['token_zmena']);
$ics_url = BASE_URL . '/api/ics?token=' . urlencode($rez['token_zmena']);
$datum_fmt = datum_cs($rez['datum']);
$html = email_layout("
<h2 style='color:#6b21a8;margin:0 0 16px'>Vaše rezervace je přijata ✂️</h2>
<p>Dobrý den, <strong>{$rez['jmeno']} {$rez['prijmeni']}</strong>,</p>
<p>potvrzujeme přijetí vaší rezervace.<br><strong>Jakmile ji kadeřnice potvrdí, dostanete další e-mail.</strong></p>
" . tabulka_rezervace($sluzba_nazev, $datum_fmt, $rez['cas_od'], $rez['cena'], $rez['poznamka'] ?? '', $rez['doplnky'] ?? [], isset($rez['cena_upravena']) ? (float)$rez['cena_upravena'] : null) . "
<p>Potřebujete termín změnit nebo zrušit?</p>
<p style='text-align:center;margin:24px 0'>
<a href='{$zmena_url}' style='background:#9333ea;color:#fff;padding:12px 24px;border-radius:24px;text-decoration:none;margin-right:8px'>Změnit termín</a>
<a href='{$zruseni_url}' style='background:#f3e8ff;color:#6b21a8;padding:12px 24px;border-radius:24px;text-decoration:none;border:1px solid #e9d5ff'>Zrušit rezervaci</a>
</p>
<p style='text-align:center;margin-top:12px'>
<a href='{$ics_url}' style='background:#f3e8ff;color:#6b21a8;padding:10px 20px;border-radius:24px;text-decoration:none;border:1px solid #e9d5ff;font-size:13px'>📅 Přidat do kalendáře</a>
</p>
");
return smtp_send($rez['email'], $rez['jmeno'] . ' ' . $rez['prijmeni'],
'Přijetí rezervace – ' . salon_nazev(), $html);
}
function email_potvrzeni_adminem(array $rez, string $sluzba_nazev, bool $nova = false): bool {
$datum_fmt = datum_cs($rez['datum']);
$nadpis = $nova ? 'Rezervace potvrzena ✅' : 'Rezervace potvrzena ✅';
$zprava = $nova
? 'vaše rezervace byla vytvořena a <strong>potvrzena</strong>. Těšíme se na vás!'
: 'vaši rezervaci jsme potvrdili. Těšíme se na vás!';
$zmena_url = BASE_URL . '/zmena-rezervace.php?token=' . urlencode($rez['token_zmena']);
$zruseni_url = BASE_URL . '/zruseni-rezervace.php?token=' . urlencode($rez['token_zmena']);
$ics_url = BASE_URL . '/api/ics?token=' . urlencode($rez['token_zmena']);
$html = email_layout("
<h2 style='color:#6b21a8;margin:0 0 16px'>{$nadpis}</h2>
<p>Dobrý den, <strong>{$rez['jmeno']} {$rez['prijmeni']}</strong>,</p>
<p>{$zprava}</p>
" . tabulka_rezervace($sluzba_nazev, $datum_fmt, $rez['cas_od'], $rez['cena'], $rez['poznamka'] ?? '', $rez['doplnky'] ?? [], isset($rez['cena_upravena']) ? (float)$rez['cena_upravena'] : null) . "
<p>Potřebujete termín změnit nebo zrušit?</p>
<p style='text-align:center;margin:24px 0'>
<a href='{$zmena_url}' style='background:#9333ea;color:#fff;padding:12px 24px;border-radius:24px;text-decoration:none;margin-right:8px'>Změnit termín</a>
<a href='{$zruseni_url}' style='background:#f3e8ff;color:#6b21a8;padding:12px 24px;border-radius:24px;text-decoration:none;border:1px solid #e9d5ff'>Zrušit rezervaci</a>
</p>
<p style='text-align:center;margin-top:12px'>
<a href='{$ics_url}' style='background:#f3e8ff;color:#6b21a8;padding:10px 20px;border-radius:24px;text-decoration:none;border:1px solid #e9d5ff;font-size:13px'>📅 Přidat do kalendáře</a>
</p>
");
return smtp_send($rez['email'], $rez['jmeno'] . ' ' . $rez['prijmeni'],
'Rezervace potvrzena – ' . salon_nazev(), $html);
}
function email_zmena_ceny(array $rez, string $sluzba_nazev): bool {
$zmena_url = BASE_URL . '/zmena-rezervace.php?token=' . urlencode($rez['token_zmena']);
$zruseni_url = BASE_URL . '/zruseni-rezervace.php?token=' . urlencode($rez['token_zmena']);
$datum_fmt = datum_cs($rez['datum']);
$html = email_layout("
<h2 style='color:#6b21a8;margin:0 0 16px'>Aktualizace ceny rezervace ✂️</h2>
<p>Dobrý den, <strong>{$rez['jmeno']} {$rez['prijmeni']}</strong>,</p>
<p>cena vaší rezervace byla upravena. Níže najdete aktuální přehled.</p>
" . tabulka_rezervace($sluzba_nazev, $datum_fmt, $rez['cas_od'], $rez['cena'], $rez['poznamka'] ?? '', $rez['doplnky'] ?? [], isset($rez['cena_upravena']) ? (float)$rez['cena_upravena'] : null) . "
<p>Potřebujete termín změnit nebo zrušit?</p>
<p style='text-align:center;margin:24px 0'>
<a href='{$zmena_url}' style='background:#9333ea;color:#fff;padding:12px 24px;border-radius:24px;text-decoration:none;margin-right:8px'>Změnit termín</a>
<a href='{$zruseni_url}' style='background:#f3e8ff;color:#6b21a8;padding:12px 24px;border-radius:24px;text-decoration:none;border:1px solid #e9d5ff'>Zrušit rezervaci</a>
</p>
");
return smtp_send($rez['email'], $rez['jmeno'] . ' ' . $rez['prijmeni'],
'Aktualizace ceny – ' . salon_nazev(), $html);
}
function email_pripominka(array $rez, string $sluzba_nazev, int $hodin_predem): bool {
$zmena_url = BASE_URL . '/zmena-rezervace.php?token=' . urlencode($rez['token_zmena']);
$zruseni_url = BASE_URL . '/zruseni-rezervace.php?token=' . urlencode($rez['token_zmena']);
$ics_url = BASE_URL . '/api/ics?token=' . urlencode($rez['token_zmena']);
$datum_fmt = datum_cs($rez['datum']);
$kdy = $hodin_predem >= 24 && $hodin_predem % 24 === 0
? ($hodin_predem === 24 ? 'zítra' : 'za ' . ($hodin_predem / 24) . ' dny')
: 'za ' . $hodin_predem . ' hodin';
$html = email_layout("
<h2 style='color:#6b21a8;margin:0 0 16px'>Připomenutí rezervace ⏰</h2>
<p>Dobrý den, <strong>{$rez['jmeno']} {$rez['prijmeni']}</strong>,</p>
<p>připomínáme, že máte {$kdy} naplánovanou návštěvu u nás.</p>
" . tabulka_rezervace($sluzba_nazev, $datum_fmt, $rez['cas_od'], $rez['cena'], $rez['poznamka'] ?? '', $rez['doplnky'] ?? [], isset($rez['cena_upravena']) ? (float)$rez['cena_upravena'] : null) . "
<p>Potřebujete termín změnit nebo zrušit?</p>
<p style='text-align:center;margin:24px 0'>
<a href='{$zmena_url}' style='background:#9333ea;color:#fff;padding:12px 24px;border-radius:24px;text-decoration:none;margin-right:8px'>Změnit termín</a>
<a href='{$zruseni_url}' style='background:#f3e8ff;color:#6b21a8;padding:12px 24px;border-radius:24px;text-decoration:none;border:1px solid #e9d5ff'>Zrušit rezervaci</a>
</p>
<p style='text-align:center;margin-top:12px'>
<a href='{$ics_url}' style='background:#f3e8ff;color:#6b21a8;padding:10px 20px;border-radius:24px;text-decoration:none;border:1px solid #e9d5ff;font-size:13px'>📅 Přidat do kalendáře</a>
</p>
");
return smtp_send($rez['email'], $rez['jmeno'] . ' ' . $rez['prijmeni'],
'Připomenutí rezervace – ' . salon_nazev(), $html);
}
function email_zadost_hodnoceni(array $rez, string $sluzba_nazev): bool {
$datum_fmt = datum_cs($rez['datum']);
$hodnoceni_url = BASE_URL . '/hodnoceni.php?token=' . urlencode($rez['token_zmena']);
$stars_html = '';
for ($i = 1; $i <= 5; $i++) {
$stars_html .= "<a href='{$hodnoceni_url}&hvezdy={$i}' style='display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;background:#faf5ff;border:2px solid #e9d5ff;text-decoration:none;font-size:20px;color:#d8b4fe;margin:0 4px'>★</a>";
}
$html = email_layout("
<h2 style='color:#6b21a8;margin:0 0 16px'>Jak jste byl spokojen? ⭐</h2>
<p>Dobrý den, <strong>{$rez['jmeno']} {$rez['prijmeni']}</strong>,</p>
<p>děkujeme za návštěvu. Ohodnotíte nám prosím vaši zkušenost?</p>
<p style='font-weight:600;margin:16px 0 4px'>{$sluzba_nazev} · {$datum_fmt}</p>
<p style='text-align:center;margin:20px 0'>{$stars_html}</p>
<p style='text-align:center;color:#9ca3af;font-size:13px'>Klikněte na počet hvězdiček, hodnocení se uloží okamžitě</p>
");
return smtp_send($rez['email'], $rez['jmeno'] . ' ' . $rez['prijmeni'],
'Jak jste byl spokojen? – ' . salon_nazev(), $html);
}
function email_nove_hodnoceni(array $rez, int $hvezdy): bool {
$admin_email = nastaveni('salon_email');
if (!$admin_email) return false;
$stars_html = '';
for ($i = 1; $i <= 5; $i++) {
$color = $i <= $hvezdy ? '#f59e0b' : '#e5e7eb';
$stars_html .= "<span style='color:{$color};font-size:20px'>★</span>";
}
$kalendar_url = BASE_URL . '/admin.html#kalendar/' . $rez['datum'];
$html = email_layout("
<div style='background:#f3e8ff;border-radius:10px;padding:12px 16px;margin-bottom:20px;color:#6b21a8;font-weight:600;font-size:16px'>
⭐ Nové hodnocení rezervace
</div>
<table style='width:100%;border-collapse:collapse;margin-bottom:20px;font-size:14px'>
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Zákazník</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>" . htmlspecialchars($rez['jmeno'] . ' ' . $rez['prijmeni']) . "</td></tr>
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Datum</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>" . datum_cs($rez['datum']) . "</td></tr>
<tr><td style='padding:8px;color:#6b7280'>Hodnocení</td><td style='padding:8px'>{$stars_html}</td></tr>
</table>
<p style='text-align:center'>
<a href='{$kalendar_url}' style='background:#9333ea;color:#fff;padding:11px 24px;border-radius:24px;text-decoration:none;font-size:14px'>Otevřít v kalendáři</a>
</p>
");
return smtp_send($admin_email, salon_nazev(), 'Nové hodnocení – ' . salon_nazev(), $html);
}
function email_zmena_terminu(array $rez, string $sluzba_nazev): bool {
$zmena_url = BASE_URL . '/zmena-rezervace.php?token=' . urlencode($rez['token_zmena']);
$zruseni_url = BASE_URL . '/zruseni-rezervace.php?token=' . urlencode($rez['token_zmena']);
$ics_url = BASE_URL . '/api/ics?token=' . urlencode($rez['token_zmena']);
$datum_fmt = datum_cs($rez['datum']);
$html = email_layout("
<h2 style='color:#6b21a8;margin:0 0 16px'>Změna termínu rezervace ✂️</h2>
<p>Dobrý den, <strong>{$rez['jmeno']} {$rez['prijmeni']}</strong>,</p>
<p>váš termín byl změněn. Níže najdete aktuální informace o rezervaci.</p>
" . tabulka_rezervace($sluzba_nazev, $datum_fmt, $rez['cas_od'], $rez['cena'], $rez['poznamka'] ?? '') . "
<p>Potřebujete termín dále změnit nebo zrušit?</p>
<p style='text-align:center;margin:24px 0'>
<a href='{$zmena_url}' style='background:#9333ea;color:#fff;padding:12px 24px;border-radius:24px;text-decoration:none;margin-right:8px'>Změnit termín</a>
<a href='{$zruseni_url}' style='background:#f3e8ff;color:#6b21a8;padding:12px 24px;border-radius:24px;text-decoration:none;border:1px solid #e9d5ff'>Zrušit rezervaci</a>
</p>
<p style='text-align:center;margin-top:12px'>
<a href='{$ics_url}' style='background:#f3e8ff;color:#6b21a8;padding:10px 20px;border-radius:24px;text-decoration:none;border:1px solid #e9d5ff;font-size:13px'>📅 Přidat do kalendáře</a>
</p>
");
return smtp_send($rez['email'], $rez['jmeno'] . ' ' . $rez['prijmeni'],
'Změna termínu – ' . salon_nazev(), $html);
}
function email_zruseni(array $rez, string $sluzba_nazev, string $kym): bool {
$datum_fmt = datum_cs($rez['datum']);
$zprava = $kym === 'admin'
? 'Vaši rezervaci jsme museli zrušit. Omlouváme se za komplikace.'
: 'Vaše rezervace byla úspěšně zrušena na vaši žádost.';
$duvod = !empty($rez['duvod_zruseni'])
? "<p style='background:#fff3f3;border-left:3px solid #991b1b;padding:10px 14px;border-radius:4px;margin:12px 0;font-size:14px'><strong>Důvod:</strong> " . htmlspecialchars($rez['duvod_zruseni'], ENT_QUOTES, 'UTF-8') . "</p>"
: '';
$html = email_layout("
<h2 style='color:#991b1b;margin:0 0 16px'>Rezervace zrušena</h2>
<p>Dobrý den, <strong>{$rez['jmeno']} {$rez['prijmeni']}</strong>,</p>
<p>{$zprava}</p>
{$duvod}
" . tabulka_rezervace($sluzba_nazev, $datum_fmt, $rez['cas_od'], null) . "
<p style='text-align:center;margin-top:24px'>
<a href='" . BASE_URL . "' style='background:#9333ea;color:#fff;padding:12px 24px;border-radius:24px;text-decoration:none'>Rezervovat nový termín</a>
</p>
");
return smtp_send($rez['email'], $rez['jmeno'] . ' ' . $rez['prijmeni'],
'Zrušení rezervace – ' . salon_nazev(), $html);
}
function tabulka_rezervace(string $sluzba, string $datum, string $cas, ?string $cena, string $poznamka = '', array $doplnky = [], ?float $cena_upravena = null): string {
$cena_upravena_val = $cena_upravena;
$extra_cena_tbl = 0;
foreach ($doplnky as $d) { $extra_cena_tbl += (float)$d['cena']; }
$zakladni_num = ($cena !== null && $cena !== '' && $cena !== '0' && $cena !== 'Individuální') ? (float)str_replace(' ', '', $cena) : 0;
if ($cena_upravena_val !== null) {
// Cena byla ručně upravena — zobrazit jen finální cenu
$cena_row = '';
$doplnky = []; // Neskrýváme doplňky — ale v emailu je nezobrazujeme
$celkem_row = "<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff;font-weight:600'>Celkem</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff;color:#6b21a8'>" . number_format((float)$cena_upravena_val, 0, ',', ' ') . " Kč</td></tr>";
} else {
$celkem_tbl = $zakladni_num + $extra_cena_tbl;
if ($celkem_tbl > 0 && !empty($doplnky)) {
$cena_row = "<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Základní cena</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>{$cena} Kč</td></tr>";
} elseif ($zakladni_num > 0) {
$cena_row = "<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Cena</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>{$cena} Kč</td></tr>";
} else {
$cena_row = '';
}
$celkem_row = ($celkem_tbl > 0 && !empty($doplnky))
? "<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff;font-weight:600'>Celkem</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff;color:#6b21a8'>" . number_format($celkem_tbl, 0, ',', ' ') . " Kč</td></tr>"
: '';
}
$doplnky_row = '';
if (!empty($doplnky)) {
$doplnky_html = "<div style='background:#faf5ff;border-radius:6px;padding:8px 10px;'>";
$extra_cena = 0;
foreach ($doplnky as $d) {
$doplnky_html .= "<div style='display:flex;justify-content:space-between;font-size:13px;padding:3px 0;color:#6b21a8'><span>" . htmlspecialchars($d['nazev']) . "</span><span>+" . number_format((float)$d['cena'], 0, ',', ' ') . " Kč</span></div>";
$extra_cena += (float)$d['cena'];
}
$doplnky_html .= "</div>";
$doplnky_row = "<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Doplňky</td><td style='padding:8px;border-bottom:1px solid #f3e8ff'>{$doplnky_html}</td></tr>";
}
$poznamka_row = !empty($poznamka)
? "<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Poznámka</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>" . htmlspecialchars($poznamka) . "</td></tr>"
: '';
return "
<table style='width:100%;border-collapse:collapse;margin:20px 0;font-size:14px'>
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Služba</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>{$sluzba}</td></tr>
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Datum</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>{$datum}</td></tr>
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Čas</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>{$cas}</td></tr>
{$cena_row}
{$doplnky_row}
{$celkem_row}
{$poznamka_row}
</table>";
}
function email_footer(): string {
return "
<div style='margin-top:24px;padding-top:16px;border-top:1px solid #f3e8ff;text-align:center;font-size:11px;color:#9ca3af'>
© " . date('Y') . " " . htmlspecialchars(salon_nazev()) . "
·
Rezervační systém vytvořil <a href='https://jservices.cz' style='color:#a855f7;text-decoration:none;font-weight:500'>J Services</a>
</div>
";
}
function email_layout(string $content): string {
return "<!DOCTYPE html><html><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'></head>
<body style='margin:0;padding:0;background:#f9fafb;font-family:Arial,sans-serif;font-size:15px;line-height:1.6'>
<table width='100%' cellpadding='0' cellspacing='0'><tr><td align='center' style='padding:32px 16px'>
<table width='100%' style='max-width:560px;background:#fff;border-radius:16px;overflow:hidden;border:1px solid #f3e8ff' cellpadding='0' cellspacing='0'>
<tr><td style='background:#9333ea;padding:20px 32px;text-align:center'>
<span style='color:#fff;font-size:20px;font-weight:600'>✂️ " . salon_nazev() . "</span>
</td></tr>
<tr><td style='padding:28px 32px'>{$content}</td></tr>
<tr><td style='background:#faf5ff;padding:14px 32px;text-align:center;font-size:12px;color:#9ca3af'>
© " . date('Y') . " " . htmlspecialchars(salon_nazev()) . " · Automaticky generovaný e-mail, neodpovídejte na něj.<br>
Rezervační systém vytvořil <a href='https://jservices.cz' style='color:#a855f7;text-decoration:none;font-weight:500'>J Services</a>
</td></tr>
</table></td></tr></table></body></html>";
}
function datum_cs(string $datum): string {
$ts = strtotime($datum);
$mesice = ['','ledna','února','března','dubna','května','června','července','srpna','září','října','listopadu','prosince'];
$dny = ['neděle','pondělí','úterý','středa','čtvrtek','pátek','sobota'];
return $dny[date('w', $ts)] . ' ' . (int)date('j', $ts) . '. ' . $mesice[(int)date('n', $ts)] . ' ' . date('Y', $ts);
}
// -----------------------------------------------
// Notifikace pro admina
// -----------------------------------------------
function email_notifikace_admin(array $rez, string $sluzba_nazev, string $typ): bool {
$admin_email = nastaveni('salon_email', MS_FROM_EMAIL);
$datum_fmt = datum_cs($rez['datum']);
$barva = $typ === 'nova' ? '#166534' : ($typ === 'zrusena' ? '#991b1b' : '#92400e');
$bgbarva = $typ === 'nova' ? '#dcfce7' : ($typ === 'zrusena' ? '#fee2e2' : '#fef3c7');
$ikona = $typ === 'nova' ? '🆕' : ($typ === 'zrusena' ? '❌' : ($typ === 'zmenena' ? '💰' : '🔄'));
$nadpis = $typ === 'nova' ? 'Nová rezervace' : ($typ === 'zrusena' ? 'Rezervace zrušena' : ($typ === 'zmenena' ? 'Změna ceny rezervace' : 'Rezervace změněna'));
$predmet = $ikona . ' ' . $nadpis . ' – ' . $rez['jmeno'] . ' ' . $rez['prijmeni'];
$telefon_row = !empty($rez['telefon'])
? "<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Telefon</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>" . htmlspecialchars($rez['telefon']) . "</td></tr>"
: '';
$poznamka_row = !empty($rez['poznamka'])
? "<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Poznámka</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>" . htmlspecialchars($rez['poznamka']) . "</td></tr>"
: '';
// Doplňky
$doplnky_admin = $rez['doplnky'] ?? [];
$extra_cena = 0;
$doplnky_admin_row = '';
if (!empty($doplnky_admin)) {
$doplnky_html = "<div style='background:#faf5ff;border-radius:6px;padding:6px 10px;'>";
foreach ($doplnky_admin as $d) {
$extra_cena += (float)$d['cena'];
$doplnky_html .= "<div style='display:flex;justify-content:space-between;font-size:13px;padding:2px 0;color:#6b21a8'><span>" . htmlspecialchars($d['nazev']) . "</span><span>+" . number_format((float)$d['cena'], 0, ',', ' ') . " Kč</span></div>";
}
$doplnky_html .= "</div>";
$doplnky_admin_row = "<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Doplňky</td><td style='padding:8px;border-bottom:1px solid #f3e8ff'>{$doplnky_html}</td></tr>";
}
// Pokud existuje cena_upravena, je to finální — nepřičítat doplňky
if (isset($rez['cena_upravena']) && $rez['cena_upravena'] !== null && $rez['cena_upravena'] !== '') {
$celkem_cena = (float)$rez['cena_upravena'];
$doplnky_admin_row = ''; // Při upravené ceně nezobrazujeme doplňky zvlášť
} else {
$zakladni_cena = (float)str_replace(' ', '', $rez['cena'] ?? '0');
$celkem_cena = $zakladni_cena + $extra_cena;
}
$cena_display = $celkem_cena > 0 ? number_format($celkem_cena, 0, ',', ' ') . ' Kč' : ($rez['cena'] ? $rez['cena'] . ' Kč' : 'Individuální');
$html = email_layout("
<div style='background:{$bgbarva};border-radius:10px;padding:12px 16px;margin-bottom:20px;color:{$barva};font-weight:600;font-size:16px'>
{$ikona} {$nadpis}
</div>
<table style='width:100%;border-collapse:collapse;margin-bottom:20px;font-size:14px'>
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Zákazník</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>" . htmlspecialchars($rez['jmeno'] . ' ' . $rez['prijmeni']) . "</td></tr>
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>E-mail</td><td style='padding:8px;border-bottom:1px solid #f3e8ff'><a href='mailto:" . htmlspecialchars($rez['email']) . "' style='color:#7c3aed'>" . htmlspecialchars($rez['email']) . "</a></td></tr>
{$telefon_row}
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Služba</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>" . htmlspecialchars($sluzba_nazev) . "</td></tr>
{$doplnky_admin_row}
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Datum</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>{$datum_fmt}</td></tr>
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Čas</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>" . htmlspecialchars($rez['cas_od']) . "</td></tr>
<tr><td style='padding:8px;color:#6b7280;border-bottom:1px solid #f3e8ff'>Celkem</td><td style='padding:8px;font-weight:600;border-bottom:1px solid #f3e8ff'>{$cena_display}</td></tr>
{$poznamka_row}
</table>
<p style='text-align:center'>
<a href='" . BASE_URL . "/admin.html#kalendar/" . $rez['datum'] . "' style='background:#9333ea;color:#fff;padding:11px 24px;border-radius:24px;text-decoration:none;font-size:14px'>Otevřít v kalendáři</a>
</p>
");
return smtp_send($admin_email, salon_nazev(), $predmet, $html);
}