File size: 6.81Kb
<?php
/**
* CMS: LaiCMS (v1.0 Edition 2026)
* File: messages/compose.php
* Оптимизация: PHP 7.4+, UX-Engine, Live Search.
*/
declare(strict_types=1);
require_once '../system/db.php';
require_once '../system/functions.php';
// Проверка авторизации
$my_id = (int)($_SESSION['user_id'] ?? 0);
if (!$my_id) {
header("Location: /users/login.php");
exit;
}
/** * Логика перенаправления
* Если передан ID, сразу переходим в чат.
* Если передано имя пользователя (u), ищем ID в БД.
*/
if (isset($_GET['to_id'])) {
header("Location: chat.php?id=" . (int)$_GET['to_id']);
exit;
}
if (!empty($_GET['u'])) {
$u_name = trim((string)$_GET['u']);
$stmt = $mysqli->prepare("SELECT id FROM users WHERE username = ? LIMIT 1");
$stmt->bind_param("s", $u_name);
$stmt->execute();
$result = $stmt->get_result()->fetch_assoc();
if ($result) {
header("Location: chat.php?id=" . $result['id']);
exit;
} else {
$error = "Пользователь с таким именем не найден.";
}
}
$page_title = "Новый диалог";
include '../system/header.php';
?>
<style>
/* Современный контейнер с эффектом глубины */
.compose-card {
max-width: 500px;
margin: 2rem auto;
padding: 2rem;
border-radius: 24px;
background: var(--pico-card-background-color);
box-shadow: 0 10px 40px rgba(0,0,0,0.05);
border: 1px solid var(--pico-muted-border-color);
transition: transform 0.3s ease;
}
.compose-card:hover { transform: translateY(-5px); }
/* Поле ввода с неоновым акцентом при фокусе */
.search-input-wrapper {
position: relative;
margin-bottom: 1.5rem;
}
input[name="u"] {
padding-left: 3rem !important;
border-radius: 15px !important;
transition: all 0.3s ease;
}
input[name="u"]:focus {
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2) !important;
}
.search-icon {
position: absolute;
left: 1.2rem;
top: 50%;
transform: translateY(-50%);
color: var(--pico-primary);
opacity: 0.7;
}
/* Мощный инструмент 1: Список предложений (Live Suggestions) */
#search-results {
margin-top: -1rem;
margin-bottom: 1rem;
border-radius: 12px;
background: var(--pico-background-color);
display: none; /* Скрыт по умолчанию */
max-height: 200px;
overflow-y: auto;
border: 1px solid var(--pico-muted-border-color);
}
.result-item {
padding: 10px 15px;
cursor: pointer;
display: flex;
align-items: center;
gap: 10px;
transition: background 0.2s;
}
.result-item:hover { background: var(--pico-card-sectioning-background-color); }
.btn-submit {
width: 100%;
border-radius: 15px;
font-weight: 600;
letter-spacing: 0.5px;
}
</style>
<div class="container">
<div class="compose-card">
<hgroup style="text-align: center; margin-bottom: 2rem;">
<h2 style="margin-bottom: 0.5rem;">
<i class="fa-solid fa-paper-plane" style="color: var(--pico-primary);"></i> Найти контакт
</h2>
<p class="secondary">Введите логин друга для начала чата</p>
</hgroup>
<?php if (isset($error)): ?>
<p style="color: var(--pico-form-element-invalid-border-color); font-size: 0.9rem; text-align: center;">
<i class="fa-solid fa-circle-exclamation"></i> <?= $error ?>
</p>
<?php endif; ?>
<form action="" method="GET" id="searchForm">
<div class="search-input-wrapper">
<i class="fa-solid fa-user-search search-icon"></i>
<input type="text"
name="u"
id="uInput"
placeholder="Логин пользователя..."
value="<?= htmlspecialchars($_GET['u'] ?? '') ?>"
autocomplete="off"
required>
</div>
<div id="search-results"></div>
<button type="submit" class="primary btn-submit">
Начать диалог
</button>
</form>
<div style="margin-top: 1.5rem; text-align: center;">
<a href="index.php" class="secondary" style="font-size: 0.9rem; text-decoration: none;">
<i class="fa-solid fa-arrow-left"></i> Назад к сообщениям
</a>
</div>
</div>
</div>
<script>
/**
* Инструмент 3: Реализация Live Search (Живой поиск)
* Предотвращает перезагрузки страницы и делает интерфейс отзывчивым.
*/
const uInput = document.getElementById('uInput');
const resultsBox = document.getElementById('search-results');
let debounceTimer;
uInput.addEventListener('input', () => {
clearTimeout(debounceTimer);
const query = uInput.value.trim();
if (query.length < 2) {
resultsBox.style.display = 'none';
return;
}
// Дебаунс (ожидание окончания ввода), чтобы не спамить в БД
debounceTimer = setTimeout(async () => {
try {
// Предполагается наличие api/search_users.php
const res = await fetch(`/api/search_users.php?q=${encodeURIComponent(query)}`);
const users = await res.json();
if (users.length > 0) {
resultsBox.innerHTML = users.map(user => `
<div class="result-item" onclick="selectUser('${user.username}')">
<img src="${user.avatar || '/assets/no-avatar.png'}" style="width:25px; height:25px; border-radius:50%;">
<span>${user.username}</span>
</div>
`).join('');
resultsBox.style.display = 'block';
} else {
resultsBox.style.display = 'none';
}
} catch (e) {
console.warn("Живой поиск временно недоступен");
}
}, 300);
});
function selectUser(username) {
uInput.value = username;
resultsBox.style.display = 'none';
document.getElementById('searchForm').submit();
}
// Закрытие поиска при клике вне его
document.addEventListener('click', (e) => {
if (!uInput.contains(e.target)) resultsBox.style.display = 'none';
});
</script>
<?php include '../system/footer.php'; ?>