فایلی شێوازی پەڕەی بەڕێوەبەر (css/messages.css)
/* ============================================ ڕێکخستنی سەرەتا ============================================ */
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:Tahoma,'Segoe UI',Arial,sans-serif;background:#0f172a;min-height:100vh;padding:30px 20px;color:#e2e8f0;direction:rtl}
.container{max-width:1200px;margin:0 auto}
/* ============================================ سەرەتای پەڕە ============================================ */
.page-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:25px;flex-wrap:wrap;gap:15px}
.header-title{display:flex;align-items:center;gap:15px}
.header-icon{width:50px;height:50px;background:linear-gradient(135deg,#6366f1,#4f46e5);border-radius:14px;display:flex;align-items:center;justify-content:center;color:#fff;box-shadow:0 8px 20px rgba(99,102,241,0.4)}
.header-icon svg{width:22px;height:22px}
.header-title h1{font-size:24px;font-weight:700;color:#fff}
.header-title p{font-size:13px;color:#94a3b8;margin-top:3px}
/* ============================================ کارتی ئامار ============================================ */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:15px;margin-bottom:25px}
.stat-card{background:rgba(30,41,59,0.7);backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.05);border-radius:16px;padding:20px;display:flex;align-items:center;gap:15px;transition:transform 0.25s ease}
.stat-card:hover{transform:translateY(-3px)}
.stat-icon{width:45px;height:45px;border-radius:12px;display:flex;align-items:center;justify-content:center;color:#fff;flex-shrink:0}
.stat-icon svg{width:20px;height:20px}
.stat-icon.purple{background:linear-gradient(135deg,#6366f1,#4f46e5)}
.stat-icon.green{background:linear-gradient(135deg,#10b981,#059669)}
.stat-icon.orange{background:linear-gradient(135deg,#f59e0b,#d97706)}
.stat-info h3{font-size:22px;font-weight:700;color:#fff}
.stat-info p{font-size:12px;color:#94a3b8;margin-top:2px}
/* ============================================ خشتە ============================================ */
.table-wrapper{background:rgba(30,41,59,0.7);backdrop-filter:blur(20px);border-radius:18px;overflow:hidden;border:1px solid rgba(255,255,255,0.05);box-shadow:0 20px 50px rgba(0,0,0,0.4)}
.table-header{padding:18px 22px;background:rgba(15,23,42,0.5);border-bottom:1px solid rgba(255,255,255,0.05);display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:10px}
.table-header h2{font-size:16px;font-weight:600;color:#fff;display:flex;align-items:center;gap:8px}
.search-box{position:relative;display:flex;align-items:center}
.search-box svg{position:absolute;right:12px;color:#64748b;width:14px;height:14px}
.search-box input{padding:9px 36px 9px 14px;background:rgba(15,23,42,0.7);border:1px solid #334155;border-radius:10px;color:#f1f5f9;font-family:inherit;font-size:13px;outline:none;width:220px;transition:border-color 0.2s ease,box-shadow 0.2s ease}
.search-box input:focus{border-color:#6366f1;box-shadow:0 0 0 3px rgba(99,102,241,0.15)}
table{width:100%;border-collapse:collapse}
thead{background:rgba(15,23,42,0.7)}
th{padding:14px 16px;text-align:right;font-size:13px;font-weight:600;color:#94a3b8;border-bottom:1px solid rgba(255,255,255,0.05);white-space:nowrap}
td{padding:14px 16px;font-size:13px;color:#cbd5e1;border-bottom:1px solid rgba(255,255,255,0.03);vertical-align:middle}
tbody tr{transition:background 0.2s ease}
tbody tr:hover{background:rgba(99,102,241,0.05)}
.subject-badge{display:inline-block;padding:4px 12px;border-radius:20px;font-size:12px;font-weight:500;white-space:nowrap}
.subject-پرسیار{background:rgba(99,102,241,0.2);color:#a5b4fc}
.subject-پێشنیار{background:rgba(16,185,129,0.2);color:#6ee7b7}
.subject-کێشە{background:rgba(239,68,68,0.2);color:#fca5a5}
.subject-هەماهەنگی{background:rgba(245,158,11,0.2);color:#fcd34d}
.subject-زانیاری{background:rgba(6,182,212,0.2);color:#67e8f9}
.msg-name{font-weight:600;color:#fff}
.msg-email{color:#94a3b8;font-size:12px;direction:ltr;text-align:right}
.msg-text{max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:#94a3b8;cursor:help}
.msg-date{font-size:12px;color:#64748b;white-space:nowrap;direction:ltr;text-align:right}
.msg-ip{font-size:11px;color:#64748b;font-family:monospace;direction:ltr;text-align:right}
.btn-view{width:32px;height:32px;background:rgba(99,102,241,0.15);color:#a5b4fc;border:1px solid rgba(99,102,241,0.3);border-radius:8px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:transform 0.2s ease,background 0.2s ease}
.btn-view svg{width:15px;height:15px}
.btn-view:hover{background:rgba(99,102,241,0.3);transform:scale(1.1)}
.empty-state{text-align:center;padding:60px 20px;color:#64748b}
.empty-state svg{width:60px;height:60px;color:#334155;margin-bottom:15px}
.empty-state h3{font-size:17px;color:#94a3b8;margin-bottom:6px}
.empty-state p{font-size:13px}
/* ============================================ مۆداڵ ============================================ */
.modal-overlay{position:fixed;inset:0;background:rgba(0,0,0,0.7);backdrop-filter:blur(5px);display:none;align-items:center;justify-content:center;z-index:9999;padding:20px;animation:fadeIn 0.25s ease}
.modal-overlay.show{display:flex}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}
.modal{background:#1e293b;border-radius:18px;max-width:550px;width:100%;max-height:85vh;overflow-y:auto;border:1px solid rgba(255,255,255,0.1);animation:slideUp 0.3s ease;box-shadow:0 25px 60px rgba(0,0,0,0.6)}
@keyframes slideUp{from{transform:translateY(30px);opacity:0}to{transform:translateY(0);opacity:1}}
.modal-header{padding:20px 25px;background:linear-gradient(135deg,#6366f1,#4f46e5);color:#fff;display:flex;align-items:center;justify-content:space-between}
.modal-header h3{font-size:17px;display:flex;align-items:center;gap:10px}
.modal-close{background:rgba(255,255,255,0.15);border:none;color:#fff;width:32px;height:32px;border-radius:8px;cursor:pointer;display:inline-flex;align-items:center;justify-content:center;transition:background 0.2s}
.modal-close:hover{background:rgba(255,255,255,0.3)}
.modal-body{padding:25px}
.modal-row{margin-bottom:18px;padding-bottom:18px;border-bottom:1px solid rgba(255,255,255,0.05)}
.modal-row:last-child{border-bottom:none;margin-bottom:0;padding-bottom:0}
.modal-label{font-size:12px;color:#94a3b8;margin-bottom:6px}
.modal-value{font-size:14px;color:#f1f5f9;line-height:1.7;word-wrap:break-word}
.modal-value.message-box{background:rgba(15,23,42,0.5);padding:14px;border-radius:10px;border-right:3px solid #6366f1}
/* ============================================ وەڵامدانەوە ============================================ */
@media (max-width:768px){.table-wrapper{overflow-x:auto}table{min-width:700px}.search-box input{width:160px}}
فایلی سکریپتی فۆرم (js/script.js)
// ============================================
// ١. دۆزینەوەی ئێلێمێنتەکان
// ============================================
const form = document.getElementById('contactForm');
const nameInput = document.getElementById('name');
const emailInput = document.getElementById('email');
const subjectInput = document.getElementById('subject');
const messageInput = document.getElementById('message');
const captchaInput = document.getElementById('captcha');
const charCount = document.getElementById('charCount');
const submitBtn = document.getElementById('submitBtn');
// ============================================
// ٢. نیشاندەری پیتەکان
// ============================================
messageInput.addEventListener('input', function () {
const count = this.value.length;
charCount.textContent = count;
const counter = charCount.parentElement;
counter.classList.remove('warning', 'danger');
if (count > 450) {
counter.classList.add('danger');
} else if (count > 350) {
counter.classList.add('warning');
}
});
// ============================================
// ٣. پشکنینی ئیمەیل
// ============================================
function isValidEmail(email) {
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return regex.test(email);
}
// ============================================
// ٤. پیشاندانی هەڵە
// ============================================
function showError(input, message) {
const wrapper = input.closest('.input-wrapper');
const errorSpan = document.getElementById(input.id + 'Error');
if (wrapper) wrapper.classList.add('error');
if (errorSpan) errorSpan.textContent = message;
}
function clearError(input) {
const wrapper = input.closest('.input-wrapper');
const errorSpan = document.getElementById(input.id + 'Error');
if (wrapper) wrapper.classList.remove('error');
if (errorSpan) errorSpan.textContent = '';
}
// ============================================
// ٥. پاککردنەوەی هەڵەکان لە کاتی نووسین
// ============================================
[nameInput, emailInput, subjectInput, messageInput, captchaInput].forEach(input => {
input.addEventListener('input', () => clearError(input));
input.addEventListener('change', () => clearError(input));
});
// ============================================
// ٦. پشکنینی فۆرم
// ============================================
function validateForm() {
let isValid = true;
if (nameInput.value.trim().length < 3) {
showError(nameInput, 'ناو دەبێت لانیکەم ٣ پیت بێت');
isValid = false;
}
if (!isValidEmail(emailInput.value.trim())) {
showError(emailInput, 'تکایە ئیمەیلێکی دروست بنووسە');
isValid = false;
}
if (subjectInput.value === '') {
showError(subjectInput, 'تکایە بابەتێک هەڵبژێرە');
isValid = false;
}
const messageLength = messageInput.value.trim().length;
if (messageLength < 10) {
showError(messageInput, 'نامە دەبێت لانیکەم ١٠ پیت بێت');
isValid = false;
} else if (messageLength > 500) {
showError(messageInput, 'نامە نابێت لە ٥٠٠ پیت زیاتر بێت');
isValid = false;
}
if (captchaInput.value.trim() === '') {
showError(captchaInput, 'تکایە وەڵامی کەپچا بنووسە');
isValid = false;
}
return isValid;
}
// ============================================
// ٧. ناردنی فۆرم بە AJAX
// ============================================
form.addEventListener('submit', function (e) {
e.preventDefault();
if (!validateForm()) {
const firstError = document.querySelector('.input-wrapper.error');
if (firstError) {
firstError.scrollIntoView({ behavior: 'smooth', block: 'center' });
const input = firstError.querySelector('input, select, textarea');
if (input) input.focus();
}
return;
}
submitBtn.classList.add('loading');
submitBtn.disabled = true;
const formData = new FormData(form);
fetch('api/send_message.php', {
method: 'POST',
body: formData
})
.then(response => response.json())
.then(data => {
if (data.success) {
showToast(data.message, 'success');
form.reset();
charCount.textContent = '0';
clearAllErrors();
// نوێکردنەوەی کەپچا دوای ٢ چرکە
setTimeout(() => window.location.reload(), 2000);
} else {
showToast(data.message || 'هەڵەیەک ڕوویدا', 'error');
if (data.errors) {
Object.keys(data.errors).forEach(field => {
const input = document.getElementById(field);
if (input) showError(input, data.errors[field]);
});
}
}
})
.catch(error => {
console.error('هەڵا:', error);
showToast('هەڵەیەک لە پەیوەندیکردن ڕوویدا', 'error');
})
.finally(() => {
submitBtn.classList.remove('loading');
submitBtn.disabled = false;
});
});
// ============================================
// ٨. پاککردنەوەی هەموو هەڵەکان
// ============================================
function clearAllErrors() {
document.querySelectorAll('.input-wrapper.error').forEach(w => w.classList.remove('error'));
document.querySelectorAll('.error-message').forEach(s => s.textContent = '');
}
// ============================================
// ٩. پیشاندانی پەیام
// ============================================
function showToast(message, type = 'success') {
const toast = document.getElementById('toast');
const toastMessage = document.getElementById('toastMessage');
const toastIcon = toast.querySelector('.toast-icon');
toastMessage.textContent = message;
if (type === 'error') {
toast.classList.add('error');
toastIcon.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:20px;height:20px;"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>';
} else {
toast.classList.remove('error');
toastIcon.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="width:20px;height:20px;"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"></path><polyline points="22 4 12 14.01 9 11.01"></polyline></svg>';
}
toast.classList.add('show');
setTimeout(() => toast.classList.remove('show'), 4000);
}
فایلی گرێدانی داتابەیس (api/db.php)
<?php
$db_dir = __DIR__ . '/../data';
$db_file = $db_dir . '/messages.db';
if (!is_dir($db_dir)) { mkdir($db_dir, 0755, true); }
try {
$pdo = new PDO('sqlite:' . $db_file);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$pdo->exec("
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
email TEXT NOT NULL,
subject TEXT NOT NULL,
message TEXT NOT NULL,
ip_address TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)
");
} catch (PDOException $e) { die(json_encode([ 'success' => false, 'message' => 'هەڵە لە گرێدانی داتابەیس: ' . $e->getMessage() ])); }
فایلی پرۆسێسکردنی نامە (api/send_message.php)
<?php
session_start();
header('Content-Type: application/json; charset=utf-8');
require_once __DIR__ . '/db.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { echo json_encode(['success' => false, 'message' => 'داواکاری نادروستە']); exit; }
$name = isset($_POST['name']) ? trim($_POST['name']) : '';
$email = isset($_POST['email']) ? trim($_POST['email']) : '';
$subject = isset($_POST['subject']) ? trim($_POST['subject']) : '';
$message = isset($_POST['message']) ? trim($_POST['message']) : '';
$captcha = isset($_POST['captcha']) ? intval($_POST['captcha']) : 0;
$errors = [];
if (mb_strlen($name) < 3) { $errors['name'] = 'ناو دەبێت لانیکەم ٣ پیت بێت'; }
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $errors['email'] = 'تکایە ئیمەیلێکی دروست بنووسە'; }
$valid_subjects = ['پرسیار', 'پێشنیار', 'کێشە', 'هاواهەنگی', 'زانیاری'];
if (!in_array($subject, $valid_subjects)) { $errors['subject'] = 'تکایە بابەتێکی دروست هەڵبژێرە'; }
$messageLength = mb_strlen($message);
if ($messageLength < 10) { $errors['message'] = 'نامە دەبێت لانیکەم ١٠ پیت بێت'; }
elseif ($messageLength > 500) { $errors['message'] = 'نامە نابێت لە ٥٠٠ پیت زیاتر بێت'; }
if (!isset($_SESSION['captcha_answer']) || $captcha !== $_SESSION['captcha_answer']) { $errors['captcha'] = 'وەڵامی کەپچا هەڵەیە'; }
if (!empty($errors)) { echo json_encode([ 'success' => false, 'message' => 'تکایە هەڵەکان ڕاست بکەوە', 'errors' => $errors ]); exit; }
try {
$ip_address = $_SERVER['REMOTE_ADDR'] ?? 'نەزانراو';
$sql = "INSERT INTO messages (name, email, subject, message, ip_address) VALUES (:name, :email, :subject, :message, :ip)";
$stmt = $pdo->prepare($sql);
$stmt->execute([ ':name' => $name, ':email' => $email, ':subject' => $subject, ':message' => $message, ':ip' => $ip_address ]);
unset($_SESSION['captcha_answer'], $_SESSION['captcha_question']);
echo json_encode([ 'success' => true, 'message' => 'نامەکەت بە سەرکەوتوویی نێردرا. سوپاس بۆ پەیوەندیکردنت!' ]);
} catch (PDOException $e) { echo json_encode([ 'success' => false, 'message' => 'هەڵە لە هەڵگرتنی نامە: ' . $e->getMessage() ]); }
بە هیوای سەرکەوتنتان!
بارکردنی سەرنجەکان...