View file messages/compose.php

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'; ?>