پررررررررر

This commit is contained in:
Flatlogic Bot 2025-12-06 16:02:15 +00:00
parent 3f48850ff5
commit 6c608b6ba5
30 changed files with 4016 additions and 1555 deletions

View File

@ -33,21 +33,21 @@ require_once 'includes/header.php';
<div class="row text-center g-4 justify-content-center"> <div class="row text-center g-4 justify-content-center">
<div class="col-md-4" data-aos="fade-up" data-aos-delay="100"> <div class="col-md-4" data-aos="fade-up" data-aos-delay="100">
<div class="values-card h-100"> <div class="values-card h-100">
<i class="fas fa-gem mb-3"></i> <i class="ri-gem-line mb-3"></i>
<h4 class="fw-bold">تعهد به کیفیت</h4> <h4 class="fw-bold">تعهد به کیفیت</h4>
<p class="text-muted px-3">استفاده از بهترین مواد اولیه و کنترل کیفی دقیق در تمام مراحل تولید.</p> <p class="text-muted px-3">استفاده از بهترین مواد اولیه و کنترل کیفی دقیق در تمام مراحل تولید.</p>
</div> </div>
</div> </div>
<div class="col-md-4" data-aos="fade-up" data-aos-delay="200"> <div class="col-md-4" data-aos="fade-up" data-aos-delay="200">
<div class="values-card h-100"> <div class="values-card h-100">
<i class="fas fa-hand-holding-heart mb-3"></i> <i class="ri-hand-heart-line mb-3"></i>
<h4 class="fw-bold">هنر دست</h4> <h4 class="fw-bold">هنر دست</h4>
<p class="text-muted px-3">تمام محصولات ما با عشق و دقت توسط هنرمندان ماهر ساخته می‌شوند.</p> <p class="text-muted px-3">تمام محصولات ما با عشق و دقت توسط هنرمندان ماهر ساخته می‌شوند.</p>
</div> </div>
</div> </div>
<div class="col-md-4" data-aos="fade-up" data-aos-delay="300"> <div class="col-md-4" data-aos="fade-up" data-aos-delay="300">
<div class="values-card h-100"> <div class="values-card h-100">
<i class="fas fa-leaf mb-3"></i> <i class="ri-leaf-line mb-3"></i>
<h4 class="fw-bold">طراحی ماندگار</h4> <h4 class="fw-bold">طراحی ماندگار</h4>
<p class="text-muted px-3">خلق آثاری مدرن و در عین حال کلاسیک که هیچ‌گاه از مد نمی‌افتند.</p> <p class="text-muted px-3">خلق آثاری مدرن و در عین حال کلاسیک که هیچ‌گاه از مد نمی‌افتند.</p>
</div> </div>

View File

@ -0,0 +1,347 @@
/*
* Admin Panel Main Stylesheet
* A clean, modern, and professional light theme.
*/
@import url('https://fonts.googleapis.com/css2?family=Vazirmatn:wght@300;400;500;600;700&display=swap');
@import url('https://cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.css');
:root {
--admin-bg-light: #f4f7f9; /* Light gray background */
--admin-surface-light: #ffffff; /* White surface for cards, sidebar */
--admin-border-light: #e0e5ec; /* Soft border color */
--admin-text-primary: #2d3748; /* Dark text for high contrast */
--admin-text-secondary: #718096; /* Lighter text for muted info */
--admin-primary: #4a5568; /* A neutral, professional primary color */
--admin-primary-active: #2d3748;
--admin-success: #38a169;
--admin-danger: #e53e3e;
--admin-warning: #dd6b20;
--admin-info: #3182ce;
}
body.admin-theme {
background-color: var(--admin-bg-light);
color: var(--admin-text-primary);
font-family: 'Vazirmatn', sans-serif;
line-height: 1.6;
margin: 0;
padding: 0;
display: flex;
min-height: 100vh;
}
.admin-wrapper {
display: flex;
width: 100%;
}
/* --- Sidebar / Navigation --- */
.admin-sidebar {
width: 250px;
background-color: var(--admin-surface-light);
border-right: 1px solid var(--admin-border-light);
padding: 1.5rem 0;
display: flex;
flex-direction: column;
transition: width 0.3s ease;
box-shadow: 0 0 20px rgba(0,0,0,0.03);
}
.sidebar-header {
padding: 0 1.5rem 1.5rem 1.5rem;
text-align: center;
border-bottom: 1px solid var(--admin-border-light);
}
.sidebar-header h2 a {
color: var(--admin-text-primary);
text-decoration: none;
font-size: 1.5rem;
font-weight: 700;
}
.sidebar-header h2 a span {
color: var(--admin-primary-active);
}
.admin-nav {
flex-grow: 1;
list-style: none;
padding: 1.5rem 0 0 0;
margin: 0;
}
.admin-nav-item {
margin: 0 1rem;
}
.admin-nav-link {
display: flex;
align-items: center;
gap: 0.9rem;
padding: 0.8rem 1rem;
color: var(--admin-text-secondary);
text-decoration: none;
font-weight: 600;
font-size: 0.9rem;
border-radius: 8px;
transition: all 0.3s ease;
}
.admin-nav-link i {
font-size: 1.2rem;
width: 20px;
text-align: center;
}
.admin-nav-link:hover {
background-color: var(--admin-bg-light);
color: var(--admin-primary-active);
}
.admin-nav-link.active {
background-color: var(--admin-primary);
color: #ffffff;
font-weight: 700;
}
.admin-nav-link.active:hover {
color: #ffffff;
background-color: var(--admin-primary-active);
}
.admin-nav-link.active i {
color: #ffffff;
}
.sidebar-footer {
padding: 1.5rem;
text-align: center;
border-top: 1px solid var(--admin-border-light);
}
.sidebar-footer a {
color: var(--admin-text-secondary);
text-decoration: none;
font-size: 0.9rem;
}
.sidebar-footer a:hover {
color: var(--admin-primary-active);
}
/* --- Main Content --- */
.admin-main-content {
flex-grow: 1;
padding: 2rem;
overflow-y: auto;
}
.admin-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 2rem;
}
.admin-header h1 {
margin: 0;
font-size: 1.8rem;
font-weight: 700;
}
/* --- General Components --- */
.card {
background-color: var(--admin-surface-light);
border: 1px solid var(--admin-border-light);
border-radius: 12px;
margin-bottom: 2rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
}
.card-header {
padding: 1rem 1.5rem;
border-bottom: 1px solid var(--admin-border-light);
font-size: 1.1rem;
font-weight: 600;
}
.card-body {
padding: 1.5rem;
}
.table {
width: 100%;
border-collapse: collapse;
}
.table th, .table td {
padding: 1rem 1.2rem;
text-align: right;
border-bottom: 1px solid var(--admin-border-light);
}
.table th {
font-weight: 700;
color: var(--admin-text-secondary);
font-size: 0.8rem;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.table tbody tr:last-child td {
border-bottom: none;
}
.table tbody tr:hover {
background-color: var(--admin-bg-light);
}
.btn {
padding: 0.6rem 1.2rem;
border-radius: 8px;
text-decoration: none;
font-weight: 600;
transition: all 0.3s ease;
border: 1px solid transparent;
cursor: pointer;
display: inline-flex;
align-items: center;
gap: 0.5rem;
}
.btn-primary {
background-color: var(--admin-primary-active);
border-color: var(--admin-primary-active);
color: #fff;
}
.btn-primary:hover {
background-color: #2c3e50; /* Slightly darker */
}
.btn-danger {
background-color: var(--admin-danger);
color: #fff;
}
/* --- Stat Cards --- */
.stat-card {
background-color: var(--admin-surface-light);
border-radius: 12px;
padding: 1.5rem;
display: flex;
align-items: center;
gap: 1.5rem;
border: 1px solid var(--admin-border-light);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
}
.stat-card .icon {
font-size: 1.8rem;
padding: 1rem;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
.stat-card .stat-info p {
margin: 0;
font-size: 0.9rem;
color: var(--admin-text-secondary);
}
.stat-card .stat-info h3 {
margin: 0;
font-size: 2rem;
font-weight: 700;
}
.icon.bg-success { background-color: var(--admin-success); }
.icon.bg-danger { background-color: var(--admin-danger); }
.icon.bg-warning { background-color: var(--admin-warning); }
.icon.bg-info { background-color: var(--admin-info); }
/* --- Chart Container --- */
.chart-container {
background-color: var(--admin-surface-light);
padding: 2rem;
border-radius: 12px;
border: 1px solid var(--admin-border-light);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.05), 0 2px 4px -1px rgba(0, 0, 0, 0.03);
}
.chart-container h5 {
font-weight: 700;
margin-bottom: 1.5rem;
font-size: 1.2rem;
}
/* --- Form styles --- */
.form-group {
margin-bottom: 1.5rem;
}
.form-label {
display: block;
margin-bottom: 0.5rem;
font-weight: 600;
color: var(--admin-text-primary);
}
.form-control {
width: 100%;
padding: 0.8rem 1rem;
background-color: var(--admin-surface-light);
border: 1px solid var(--admin-border-light);
color: var(--admin-text-primary);
border-radius: 8px;
box-sizing: border-box;
transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.form-control:focus {
outline: none;
border-color: var(--admin-primary);
box-shadow: 0 0 0 3px rgba(74, 85, 104, 0.1);
}
textarea.form-control {
min-height: 120px;
resize: vertical;
}
/* Admin Login Page */
.admin-login-wrapper {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
min-height: 100vh;
background-color: var(--admin-bg-light);
}
.admin-login-box {
width: 100%;
max-width: 400px;
padding: 3rem;
background: var(--admin-surface-light);
border-radius: 12px;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.07), 0 4px 6px -2px rgba(0, 0, 0, 0.04);
}
.admin-login-box h2 {
font-weight: 700;
text-align: center;
margin-bottom: 0.5rem;
}
.admin-login-box p {
text-align: center;
color: var(--admin-text-secondary);
margin-bottom: 2rem;
}
/* Responsive adjustments will be added later if needed */

View File

@ -1 +1 @@
{"labels":["1404-09"],"data":[2940000]} {"labels":[],"data":[]}

View File

@ -1,66 +1,63 @@
<?php <?php
$page_title = 'داشبورد';
require_once __DIR__ . '/header.php'; require_once __DIR__ . '/header.php';
?> ?>
<div class="admin-header"> <div class="admin-header">
<h1>گزارش‌ها</h1> <h1><?php echo $page_title; ?></h1>
</div> </div>
<div id="dashboard-error" class="card d-none" style="color: var(--admin-danger);"><div class="card-body"></div></div> <div id="dashboard-error" class="card d-none" style="color: var(--admin-danger);"><div class="card-body"></div></div>
<style> <div class="dashboard-container">
.stat-cards-grid-reports { <div class="stat-cards-grid-reports">
display: grid; <div class="stat-card">
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); <div class="icon-container" style="background-color: #28a74555;"><i class="fas fa-dollar-sign" style="color: #28a745;"></i></div>
gap: 1.5rem; <div class="stat-info">
margin-bottom: 2rem; <p>مجموع فروش (تحویل شده)</p>
} <h3 id="total-sales">...</h3>
</style> </div>
</div>
<div class="stat-card">
<div class="icon-container" style="background-color: #17a2b855;"><i class="fas fa-users" style="color: #17a2b8;"></i></div>
<div class="stat-info">
<p>مجموع کاربران</p>
<h3 id="total-users">...</h3>
</div>
</div>
<div class="stat-card">
<div class="icon-container" style="background-color: #007bff55;"><i class="fas fa-truck" style="color: #007bff;"></i></div>
<div class="stat-info">
<p>سفارشات در حال ارسال</p>
<h3 id="shipped-orders">...</h3>
</div>
</div>
<div class="stat-card">
<div class="icon-container" style="background-color: #dc354555;"><i class="fas fa-times-circle" style="color: #dc3545;"></i></div>
<div class="stat-info">
<p>سفارشات لغو شده</p>
<h3 id="cancelled-orders">...</h3>
</div>
</div>
<div class="stat-card">
<div class="icon-container" style="background-color: #ffc10755;"><i class="fas fa-spinner" style="color: #ffc107;"></i></div>
<div class="stat-info">
<p>سفارشات در حال پردازش</p>
<h3 id="processing-orders">...</h3>
</div>
</div>
<div class="stat-card">
<div class="icon-container" style="background-color: #6f42c155;"><i class="fas fa-eye" style="color: #6f42c1;"></i></div>
<div class="stat-info">
<p>کل بازدید صفحات</p>
<h3 id="total-page-views">...</h3>
</div>
</div>
</div>
<div class="stat-cards-grid-reports">
<div class="stat-card">
<div class="icon bg-success"><i class="fas fa-dollar-sign"></i></div>
<div class="stat-info">
<p>مجموع فروش (تحویل شده)</p>
<h3 id="total-sales">...</h3>
</div>
</div>
<div class="stat-card">
<div class="icon bg-info"><i class="fas fa-users"></i></div>
<div class="stat-info">
<p>مجموع کاربران</p>
<h3 id="total-users">...</h3>
</div>
</div>
<div class="stat-card">
<div class="icon bg-primary"><i class="fas fa-truck"></i></div>
<div class="stat-info">
<p>سفارشات در حال ارسال</p>
<h3 id="shipped-orders">...</h3>
</div>
</div>
<div class="stat-card">
<div class="icon bg-danger"><i class="fas fa-times-circle"></i></div>
<div class="stat-info">
<p>سفارشات لغو شده</p>
<h3 id="cancelled-orders">...</h3>
</div>
</div>
<div class="stat-card">
<div class="icon bg-warning"><i class="fas fa-spinner"></i></div>
<div class="stat-info">
<p>سفارشات در حال پردازش</p>
<h3 id="processing-orders">...</h3>
</div>
</div>
<div class="stat-card">
<div class="icon" style="background-color: #6f42c1;"><i class="fas fa-eye"></i></div>
<div class="stat-info">
<p>کل بازدید صفحات</p>
<h3 id="total-page-views">...</h3>
</div>
</div>
</div>
<div class="chart-container" style="position: relative; height:40vh; max-height: 450px;"> <div class="chart-container" style="position: relative; height:40vh; max-height: 450px;">
<h5>نمودار فروش ماهانه (سفارشات تحویل شده)</h5> <h5>نمودار فروش ماهانه (سفارشات تحویل شده)</h5>

View File

@ -3,10 +3,10 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>پنل مدیریت</title> <title><?php echo isset($page_title) ? $page_title . ' - ' : ''; ?>پنل مدیریت آتیمه</title>
<meta name="robots" content="noindex, nofollow"> <meta name="robots" content="noindex, nofollow">
<!-- Unified Stylesheet --> <!-- Main Admin Stylesheet -->
<link rel="stylesheet" href="assets/css/admin_style.css?v=<?php echo time(); ?>"> <link rel="stylesheet" href="assets/css/admin_style.css?v=<?php echo time(); ?>">
<!-- SweetAlert2 --> <!-- SweetAlert2 -->
@ -18,5 +18,5 @@
<body class="admin-dark-theme"> <body class="admin-dark-theme">
<div class="admin-wrapper"> <div class="admin-wrapper">
<?php require_once 'nav.php'; ?> <?php require_once 'nav.php'; // The sidebar is included here ?>
<div class="admin-main-content"> <main class="admin-main-content">

View File

@ -1,7 +1,6 @@
<?php <?php
session_start(); session_start();
// If the user is already logged in, redirect them to the admin dashboard
if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true) { if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true) {
header('Location: index.php'); header('Location: index.php');
exit; exit;
@ -9,71 +8,62 @@ if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true) {
$error = ''; $error = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// WARNING: This is a highly insecure, hardcoded password for demonstration purposes only.
// In a real-world application, you MUST use a secure, hashed password system.
$hardcoded_password = 'admin123'; $hardcoded_password = 'admin123';
if (isset($_POST['password']) && $_POST['password'] === $hardcoded_password) { if (isset($_POST['password']) && $_POST['password'] === $hardcoded_password) {
// On successful login, set a session variable
$_SESSION['is_admin'] = true; $_SESSION['is_admin'] = true;
header('Location: index.php'); header('Location: index.php');
exit; exit;
} else { } else {
$error = 'رمز عبور اشتباه است.'; $error = 'رمز عبور وارد شده اشتباه است.';
} }
} }
$page_title = 'ورود به پنل مدیریت';
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="fa" dir="rtl"> <html lang="fa" dir="rtl">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ورود به پنل مدیریت</title> <title><?= $page_title; ?></title>
<meta name="robots" content="noindex, nofollow"> <meta name="robots" content="noindex, nofollow">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet"> <link rel="stylesheet" href="assets/css/admin_main.css?v=<?= time(); ?>">
<link rel="stylesheet" href="../assets/css/custom.css?v=<?php echo time(); ?>">
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
</head> </head>
<body class="bg-dark text-white"> <body class="admin-theme">
<div class="container"> <div class="admin-login-wrapper">
<div class="row justify-content-center align-items-center" style="height: 100vh;"> <div class="admin-login-box">
<div class="col-md-4"> <h2>پنل مدیریت آتیمه</h2>
<div class="card bg-dark-2"> <p>برای دسترسی به پنل، لطفاً وارد شوید.</p>
<div class="card-body p-4">
<h1 class="font-lalezar text-center mb-4">ورود به پنل</h1> <?php if ($error): ?>
<p class="text-center text-muted mb-4">رمز عبور: admin123</p> <div class="alert alert-danger mb-3"><?= $error; ?></div>
<?php if ($error): ?> <p class="text-center text-muted mb-4">رمز عبور پیش‌فرض: <code>admin123</code></p>
<script> <?php endif; ?>
document.addEventListener('DOMContentLoaded', function() {
Swal.fire({ <form method="POST" action="login.php">
toast: true, <div class="form-group">
position: 'top-start', <label for="password" class="form-label">رمز عبور</label>
icon: 'error', <input type="password" class="form-control" id="password" name="password" required autofocus>
title: '<?php echo $error; ?>',
showConfirmButton: false,
timer: 3000,
timerProgressBar: true,
background: '#2C2C2C',
color: '#D5D5D5'
});
});
</script>
<?php endif; ?>
<form method="POST">
<div class="mb-3">
<label for="password" class="form-label">رمز عبور</label>
<input type="password" class="form-control bg-dark text-white" id="password" name="password" required>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary">ورود</button>
</div>
</form>
</div>
</div> </div>
</div> <div class="d-grid mt-4">
<button type="submit" class="btn btn-primary w-100">ورود <i class="ri-arrow-left-line"></i></button>
</div>
</form>
</div> </div>
</div> </div>
</body> </body>
</html> </html>
<style>
.alert-danger {
background-color: var(--admin-danger-bg, #fef2f2);
border: 1px solid var(--admin-danger-border, #fecaca);
color: var(--admin-danger-text, #991b1b);
padding: 0.8rem 1rem;
border-radius: 8px;
font-size: 0.9rem;
}
.w-100 { width: 100%; }
</style>

View File

@ -3,35 +3,31 @@
<div class="sidebar-header"> <div class="sidebar-header">
<h2><a href="index.php">آتیمه<span>.</span></a></h2> <h2><a href="index.php">آتیمه<span>.</span></a></h2>
</div> </div>
<ul class="admin-nav"> <nav>
<li class="admin-nav-item"> <ul class="admin-nav">
<a class="admin-nav-link <?php echo ($current_page == 'index.php') ? 'active' : ''; ?>" href="index.php"> <li class="admin-nav-item">
<i class="fas fa-tachometer-alt"></i> <a class="admin-nav-link <?php echo ($current_page == 'index.php' || $current_page == 'dashboard.php') ? 'active' : ''; ?>" href="index.php">
<span>داشبورد اصلی</span> <i class="ri-dashboard-line"></i>
</a> <span>داشبورد</span>
</li> </a>
<li class="admin-nav-item"> </li>
<a class="admin-nav-link <?php echo ($current_page == 'dashboard.php') ? 'active' : ''; ?>" href="dashboard.php"> <li class="admin-nav-item">
<i class="fas fa-chart-line"></i> <a class="admin-nav-link <?php echo in_array($current_page, ['products.php', 'add_product.php', 'edit_product.php']) ? 'active' : ''; ?>" href="products.php">
<span>گزارش‌ها</span> <i class="ri-shopping-cart-2-line"></i>
</a> <span>محصولات</span>
</li> </a>
<li class="admin-nav-item"> </li>
<a class="admin-nav-link <?php echo in_array($current_page, ['products.php', 'add_product.php', 'edit_product.php']) ? 'active' : ''; ?>" href="products.php"> <li class="admin-nav-item">
<i class="fas fa-box"></i> <a class="admin-nav-link <?php echo ($current_page == 'orders.php') ? 'active' : ''; ?>" href="orders.php">
<span>محصولات</span> <i class="ri-file-list-3-line"></i>
</a> <span>سفارشات</span>
</li> </a>
<li class="admin-nav-item"> </li>
<a class="admin-nav-link <?php echo ($current_page == 'orders.php') ? 'active' : ''; ?>" href="orders.php"> </ul>
<i class="fas fa-receipt"></i> </nav>
<span>سفارشات</span>
</a>
</li>
</ul>
<div class="sidebar-footer"> <div class="sidebar-footer">
<a href="../index.php" target="_blank"><i class="fas fa-external-link-alt"></i> مشاهده سایت</a> <a href="../index.php" target="_blank"><i class="ri-external-link-line"></i> مشاهده سایت</a>
<hr style="border-color: var(--admin-border); margin: 1rem 0;"> <hr style="border-color: var(--admin-border-light); margin: 1rem 0;">
<a href="logout.php"><i class="fas fa-sign-out-alt"></i> خروج</a> <a href="logout.php"><i class="ri-logout-box-line"></i> خروج</a>
</div> </div>
</aside> </aside>

View File

@ -102,7 +102,10 @@ document.addEventListener('DOMContentLoaded', () => {
<button class="modal-close">&times;</button> <button class="modal-close">&times;</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<h6>اطلاعات مشتری</h6> <div class="d-flex justify-content-between align-items-center mb-3">
<h6 class="m-0">اطلاعات مشتری</h6>
<span class="text-muted small">کد پیگیری: <strong><?php echo htmlspecialchars($order['tracking_id']); ?></strong></span>
</div>
<p><strong>نام:</strong> <?php echo htmlspecialchars($order['customer_display_name']); ?><br> <p><strong>نام:</strong> <?php echo htmlspecialchars($order['customer_display_name']); ?><br>
<strong>آدرس:</strong> <?php echo htmlspecialchars($order['billing_address'] . ", " . $order['billing_city'] . ", " . $order['billing_province']); ?><br> <strong>آدرس:</strong> <?php echo htmlspecialchars($order['billing_address'] . ", " . $order['billing_city'] . ", " . $order['billing_province']); ?><br>
<strong>تلفن:</strong> <?php echo htmlspecialchars($order['billing_phone']); ?></p> <strong>تلفن:</strong> <?php echo htmlspecialchars($order['billing_phone']); ?></p>

View File

@ -3,46 +3,70 @@ header('Content-Type: application/json');
require_once '../db/config.php'; require_once '../db/config.php';
require_once '../includes/jdf.php'; require_once '../includes/jdf.php';
// Function to translate order status
function get_persian_status($status) {
switch ($status) {
case 'pending': return 'در انتظار پرداخت';
case 'processing': return 'در حال پردازش';
case 'shipped': return 'ارسال شده';
case 'completed': return 'تکمیل شده';
case 'cancelled': return 'لغو شده';
case 'refunded': return 'مسترد شده';
default: return 'نامشخص';
}
}
$response = ['success' => false, 'message' => 'Invalid request']; $response = ['success' => false, 'message' => 'Invalid request'];
if ($_SERVER['REQUEST_METHOD'] === 'POST') { if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$data = json_decode(file_get_contents('php://input'), true);
$tracking_id = $data['tracking_id'] ?? '';
$phone = $data['phone'] ?? '';
if (empty($tracking_id) || empty($phone)) {
$response['message'] = 'کد رهگیری و شماره تلفن الزامی است.';
echo json_encode($response);
exit;
}
try { try {
// Read JSON from the request body
$json_data = file_get_contents('php://input');
$data = json_decode($json_data, true);
$tracking_id = $data['tracking_id'] ?? '';
if (empty($tracking_id)) {
throw new Exception('کد رهگیری سفارش الزامی است.');
}
$db = db(); $db = db();
$stmt = $db->prepare( $stmt = $db->prepare(
"SELECT o.*, CONCAT(u.first_name, ' ', u.last_name) AS full_name, u.email "SELECT
o.*,
o.billing_name AS full_name
FROM orders o FROM orders o
JOIN users u ON o.user_id = u.id WHERE o.tracking_id = :tracking_id"
WHERE o.tracking_id = :tracking_id AND o.billing_phone = :phone"
); );
$stmt->bindParam(':tracking_id', $tracking_id); $stmt->execute([':tracking_id' => $tracking_id]);
$stmt->bindParam(':phone', $phone);
$stmt->execute();
$order = $stmt->fetch(PDO::FETCH_ASSOC); $order = $stmt->fetch(PDO::FETCH_ASSOC);
if ($order) { if ($order) {
$order_id = $order['id']; $items_json = $order['items_json'];
$products_stmt = $db->prepare( $items = json_decode($items_json, true);
"SELECT p.name, p.price, p.image, oi.quantity, oi.color $products = [];
FROM order_items oi
JOIN products p ON oi.product_id = p.id
WHERE oi.order_id = :order_id"
);
$products_stmt->bindParam(':order_id', $order_id);
$products_stmt->execute();
$products = $products_stmt->fetchAll(PDO::FETCH_ASSOC);
// Format creation date if (is_array($items)) {
$product_stmt = $db->prepare("SELECT name, price, image_url FROM products WHERE id = :product_id");
foreach ($items as $item) {
$product_stmt->execute([':product_id' => $item['id']]);
$product_details = $product_stmt->fetch(PDO::FETCH_ASSOC);
if ($product_details) {
$products[] = [
'name' => $product_details['name'],
'price' => $product_details['price'],
'image_url' => $product_details['image_url'],
'quantity' => $item['quantity'],
'color' => $item['color'] ?? null,
];
}
}
}
// Format data for response
$order['created_at_jalali'] = jdate('Y/m/d H:i', strtotime($order['created_at'])); $order['created_at_jalali'] = jdate('Y/m/d H:i', strtotime($order['created_at']));
$order['status_jalali'] = get_persian_status($order['status']);
$response['success'] = true; $response['success'] = true;
$response['message'] = 'سفارش یافت شد.'; $response['message'] = 'سفارش یافت شد.';
@ -53,11 +77,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
} }
} catch (PDOException $e) { } catch (PDOException $e) {
error_log("Order tracking PDO error: " . $e->getMessage()); error_log("Order tracking PDO error: " . $e->getMessage());
$response['message'] = 'خطا در برقراری ارتباط با سرور.'; $response['message'] = 'خطا در پایگاه داده رخ داد: ' . $e->getMessage();
} catch (Exception $e) {
error_log("Order tracking general error: " . $e->getMessage());
$response['message'] = $e->getMessage(); // Show the specific error message for now
} }
echo json_encode($response); echo json_encode($response);
} else {
echo json_encode($response);
} }
?> ?>

View File

@ -1,248 +0,0 @@
/*
Auth Pages - Dark Theme Overhaul
Using global variables from custom.css
*/
html, body {
height: 100%;
margin: 0;
font-family: var(--body-font);
/* The background is set by the body rule in custom.css */
}
.auth-wrapper {
display: flex;
min-height: 100vh;
width: 100%;
background-color: var(--background-color);
}
.auth-bg {
flex: 1;
background: url('https://images.pexels.com/photos/193902/pexels-photo-193902.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2') no-repeat center center;
background-size: cover;
position: relative;
display: none; /* Hide on small screens */
}
@media (min-width: 992px) {
.auth-bg {
display: flex;
align-items: center;
justify-content: center;
}
}
.auth-bg::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1;
}
.auth-bg-content {
position: relative;
z-index: 2;
text-align: center;
padding: 40px;
max-width: 450px;
color: var(--white-color);
}
.auth-bg-content h1 {
font-size: 2.5rem;
font-weight: 700;
margin-bottom: 1rem;
text-shadow: 1px 1px 8px rgba(0,0,0,0.7);
}
.auth-bg-content p {
font-size: 1.1rem;
line-height: 1.6;
}
.auth-form-wrapper {
flex-grow: 1; /* Take up all space on mobile */
display: flex;
align-items: center;
justify-content: center;
padding: 30px;
}
@media (min-width: 992px) {
.auth-form-wrapper {
flex: 1;
flex-grow: 0;
}
}
.auth-form-container {
max-width: 420px;
width: 100%;
}
.auth-form-container .form-header h2 {
font-size: 1.8rem;
font-weight: 700;
color: var(--heading-color);
margin-bottom: 0.5rem;
}
.auth-form-container .form-header p {
color: var(--text-color);
margin-bottom: 2rem;
opacity: 0.8;
}
.form-group {
position: relative;
margin-bottom: 1.5rem;
}
.auth-form-wrapper .form-control {
height: 52px;
background-color: var(--surface-color);
border: 1px solid var(--border-color);
color: var(--text-color);
border-radius: 8px;
padding: 0 20px;
font-size: 0.95rem;
transition: all 0.3s ease;
}
.auth-form-wrapper .form-control:focus {
border-color: var(--primary-color);
background-color: var(--surface-color);
box-shadow: 0 0 0 0.25rem rgba(192, 160, 128, 0.2);
}
.auth-form-wrapper .btn-primary {
background-color: var(--primary-color);
border-color: var(--primary-color);
color: var(--heading-color);
height: 50px;
font-size: 1rem;
font-weight: 600;
border-radius: 8px;
transition: all 0.3s ease;
}
.auth-form-wrapper .btn-primary:hover {
background-color: var(--secondary-color);
border-color: var(--secondary-color);
}
.auth-footer {
text-align: center;
margin-top: 1.5rem;
font-size: 0.9rem;
color: var(--text-color);
}
.auth-footer a {
color: var(--primary-color);
font-weight: 600;
}
.auth-footer a:hover {
text-decoration: underline;
}
.alert {
border-radius: 8px;
background-color: var(--surface-color);
color: var(--text-color);
border: 1px solid var(--border-color);
}
.alert-danger {
background-color: rgba(220, 53, 69, 0.15);
border-color: rgba(220, 53, 69, 0.5);
color: #f8d7da;
}
.separator {
display: flex;
align-items: center;
text-align: center;
color: var(--text-color);
opacity: 0.6;
}
.separator::before, .separator::after {
content: '';
flex: 1;
border-bottom: 1px solid var(--border-color);
}
.separator:not(:empty)::before {
margin-right: .5em;
}
.separator:not(:empty)::after {
margin-left: .5em;
}
.btn-google {
background-color: var(--surface-color);
border: 1px solid var(--border-color);
color: var(--text-color);
transition: all 0.3s ease;
}
.btn-google:hover {
background-color: var(--background-color);
border-color: var(--text-color);
}
.btn-google:disabled {
opacity: 0.5;
cursor: not-allowed;
}

View File

@ -1,356 +1,3 @@
/* General Body Styles */ .empty-cart-container .btn-checkout i {
body { color: inherit !important;
font-family: 'Vazirmatn', sans-serif;
background-color: #f8f9fa;
color: #212529;
font-weight: 400;
direction: rtl;
text-align: right;
} }
.overflow-hidden {
overflow-x: hidden;
}
/* Header Styles */
.site-header {
background-color: rgba(255, 255, 255, 0.8);
backdrop-filter: blur(10px);
border-bottom: 1px solid #dee2e6;
}
.site-header .navbar-brand {
letter-spacing: 1.5px;
}
.site-header .nav-link {
color: #6c757d;
font-weight: 500;
transition: color 0.3s ease;
}
.site-header .nav-link:hover,
.site-header .nav-link.active {
color: #000;
}
.site-header .dropdown-menu {
border-radius: 0.5rem;
border: 1px solid #dee2e6;
}
.site-header .btn-primary {
background-color: #000;
border-color: #000;
border-radius: 20px;
padding: 0.5rem 1rem;
transition: all 0.3s ease;
}
.site-header .btn-primary:hover {
background-color: #333;
border-color: #333;
}
/* Main Content Styles */
.hero {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-size: cover;
background-position: center;
color: white;
}
.hero-content {
background: rgba(0, 0, 0, 0.5);
padding: 4rem;
border-radius: 1rem;
max-width: 800px;
}
/* Shop Page Styles */
.product-card {
border: none;
border-radius: 1rem;
overflow: hidden;
transition: transform 0.3s ease, box-shadow 0.3s ease;
background-color: #fff;
}
.product-card:hover {
transform: translateY(-10px);
box-shadow: 0 1rem 3rem rgba(0,0,0,.175)!important;
}
.product-card .card-img-top {
border-radius: 1rem 1rem 0 0;
height: 300px;
object-fit: cover;
}
.product-card .card-body {
padding: 1.5rem;
}
/* Footer Styles */
.footer {
background-color: #000;
color: #fff;
padding: 4rem 0;
}
.footer a {
color: #adb5bd;
text-decoration: none;
transition: color 0.3s ease;
}
.footer a:hover {
color: #fff;
}
/* Cart Page Styles */
.cart-item img {
width: 100px;
height: 100px;
object-fit: cover;
border-radius: 0.5rem;
}
/* Dark Luxury Theme Specifics */
:root {
--luxury-bg: #121212;
--luxury-surface: #1e1e1e;
--luxury-primary: #c09f80; /* Gold */
--luxury-text: #e0e0e0;
--luxury-text-muted: #8e8e8e;
--luxury-border: #333;
}
.dark-luxury body {
background-color: var(--luxury-bg);
color: var(--luxury-text);
}
.dark-luxury .site-header {
background-color: rgba(30, 30, 30, 0.8); /* Dark surface with transparency */
border-bottom-color: var(--luxury-border);
}
.dark-luxury .nav-link {
color: var(--luxury-text-muted);
}
.dark-luxury .nav-link:hover, .dark-luxury .nav-link.active {
color: var(--luxury-primary);
}
.dark-luxury .navbar-brand {
color: var(--luxury-text);
}
/* Add any other specific overrides for dark luxury theme */
.dark-luxury .footer {
background-color: #0c0c0c;
}
.track-container {
max-width: 600px;
margin: 50px auto;
padding: 40px;
background-color: var(--luxury-surface);
border-radius: 15px;
border: 1px solid var(--luxury-border);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
text-align: right;
}
.track-container h1 {
font-weight: 700;
color: var(--luxury-text);
margin-bottom: 20px;
}
.track-container p {
color: var(--luxury-text-muted);
}
#result-message {
color: var(--luxury-text-muted);
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
font-weight: 600;
color: var(--luxury-text-muted);
display: block;
margin-bottom: 8px;
}
.form-group input {
width: 100%;
padding: 12px;
border-radius: 8px;
background-color: var(--luxury-bg);
border: 1px solid var(--luxury-border);
color: var(--luxury-text);
transition: all 0.3s ease;
}
.form-group input:focus {
border-color: var(--luxury-primary);
box-shadow: 0 0 8px rgba(192, 159, 128, 0.25);
background-color: var(--luxury-bg);
}
.btn-track {
width: 100%;
padding: 15px;
background-color: var(--luxury-primary);
color: var(--luxury-bg);
border: none;
border-radius: 8px;
font-size: 1.1rem;
font-weight: 700;
cursor: pointer;
transition: all 0.3s ease;
}
.btn-track:hover {
background-color: #d4b090; /* A lighter shade of gold */
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(192, 159, 128, 0.2);
}
/* Modal Styles */
.modal {
display: none; position: fixed; z-index: 1000; left: 0; top: 0;
width: 100%; height: 100%; overflow: auto;
background-color: rgba(0, 0, 0, 0.7);
backdrop-filter: blur(8px);
}
.modal-content {
background-color: var(--luxury-surface);
margin: 5% auto;
padding: 40px;
border: 1px solid var(--luxury-border);
width: 90%;
max-width: 800px;
border-radius: 15px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.4);
animation: slide-down 0.5s ease-out;
color: var(--luxury-text);
}
@keyframes slide-down {
from { transform: translateY(-50px); opacity: 0; }
to { transform: translateY(0); opacity: 1; }
}
.close-btn {
color: var(--luxury-text-muted);
float: left;
font-size: 32px;
font-weight: bold;
cursor: pointer;
transition: color 0.3s ease;
}
.close-btn:hover,
.close-btn:focus {
color: var(--luxury-primary);
}
.modal-header {
border-bottom: 1px solid var(--luxury-border);
padding-bottom: 15px;
margin-bottom: 25px;
text-align: right;
}
.modal-header h2 {
margin: 0;
font-weight: 700;
color: var(--luxury-text);
}
.modal-header p {
margin: 5px 0 0;
color: var(--luxury-text-muted);
font-size: 0.9rem;
}
.order-details-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 25px;
margin-bottom: 25px;
}
.detail-box {
background-color: var(--luxury-bg);
padding: 25px;
border-radius: 10px;
border: 1px solid var(--luxury-border);
}
.detail-box h3 {
margin-top: 0;
margin-bottom: 20px;
font-size: 1.2rem;
font-weight: 600;
color: var(--luxury-primary);
border-bottom: 1px solid var(--luxury-border);
padding-bottom: 10px;
}
.detail-box p {
margin: 10px 0;
color: var(--luxury-text);
font-size: 1rem;
line-height: 1.7;
}
.detail-box p strong {
color: var(--luxury-text-muted);
min-width: 120px;
display: inline-block;
}
.products-table {
width: 100%;
border-collapse: collapse;
margin-top: 10px;
}
.products-table th, .products-table td {
padding: 15px;
text-align: right;
border-bottom: 1px solid var(--luxury-border);
}
.products-table th {
color: var(--luxury-primary);
font-weight: 600;
text-transform: uppercase;
font-size: 0.85rem;
}
.products-table tr:last-child td {
border-bottom: none;
}
.products-table img {
width: 60px;
height: 60px;
object-fit: cover;
border-radius: 8px;
vertical-align: middle;
margin-left: 15px;
}
.total-price-container {
text-align: left;
margin-top: 30px;
padding-top: 20px;
border-top: 1px solid var(--luxury-border);
}
.total-price-container p {
font-size: 1.6rem;
font-weight: 700;
color: var(--luxury-primary);
margin: 0;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 181 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@ -23,7 +23,7 @@ $total_price = 0;
<?php else: ?> <?php else: ?>
<div class="text-center mb-5"> <div class="text-center mb-5">
<h1 class="fw-bold display-5">سبد خرید شما</h1> <h1 class="fw-bold display-5">سبد خرید شما</h1>
<p class="text-white-50 fs-5">جزئیات سفارش خود را بررسی و نهایی کنید.</p> <p class="text-muted fs-5">جزئیات سفارش خود را بررسی و نهایی کنید.</p>
</div> </div>
<div class="row g-5"> <div class="row g-5">
<div class="col-lg-8"> <div class="col-lg-8">
@ -48,10 +48,10 @@ $total_price = 0;
</div> </div>
<div class="col-md-4 col-9 cart-item-details"> <div class="col-md-4 col-9 cart-item-details">
<h5><a href="product.php?id=<?php echo $item['product_id']; ?>"><?php echo htmlspecialchars($item['name']); ?></a></h5> <h5><a href="product.php?id=<?php echo $item['product_id']; ?>"><?php echo htmlspecialchars($item['name']); ?></a></h5>
<?php if (!empty($item['color'])): ?> <?php if (!empty($item['color'])) : ?>
<div class="d-flex align-items-center"> <div class="d-flex align-items-center">
<small class="text-white-50 me-2">رنگ:</small> <small class="text-muted me-2">رنگ:</small>
<span class="d-inline-block rounded-circle border" style="width: 20px; height: 20px; background-color: <?php echo htmlspecialchars($item['color']); ?>;"></span> <span class="cart-item-color-swatch" style="background-color: <?php echo htmlspecialchars($item['color']); ?>;"></span>
</div> </div>
<?php endif; ?> <?php endif; ?>
</div> </div>
@ -92,7 +92,7 @@ $total_price = 0;
</div> </div>
</div> </div>
<div class="d-grid mt-4"> <div class="d-grid mt-4">
<a href="checkout.php" class="btn btn-primary btn-lg btn-checkout">ادامه و پرداخت</a> <a href="checkout.php" class="btn btn-primary btn-lg btn-checkout"><i class="ri-secure-payment-line me-2"></i>ادامه و پرداخت</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,185 +1,185 @@
<?php <?php
session_start(); session_start();
require_once 'db/config.php'; require_once 'db/config.php';
require_once 'includes/header.php';
// Redirect if cart is empty // 1. Check if cart exists and is not empty. If not, redirect to shop.
if (empty($_SESSION['cart'])) { if (empty($_SESSION['cart'])) {
header('Location: shop.php'); header('Location: shop.php');
exit; exit();
} }
$cart_items = $_SESSION['cart']; $cart_items = $_SESSION['cart'];
$total_price = array_reduce($cart_items, function ($sum, $item) { $product_details = [];
return $sum + ($item['price'] * $item['quantity']); $total_price = 0;
}, 0);
// User and address data // 2. Process cart items directly from the session
$logged_in_user = null; foreach ($cart_items as $cart_item_id => $item) {
$user_addresses = []; // Ensure item has required data
$is_logged_in = isset($_SESSION['user_id']); if (!isset($item['price'], $item['quantity'], $item['name'], $item['image_url'])) {
// Skip malformed items
continue;
}
if ($is_logged_in) { $item_total = $item['price'] * $item['quantity'];
$total_price += $item_total;
// Store details for display
$product_details[] = [
'id' => $item['product_id'],
'name' => $item['name'],
'price' => $item['price'],
'image_url' => $item['image_url'],
'quantity' => $item['quantity'],
'color' => $item['color'] ?? '', // Handle case where color might not be set
'total' => $item_total
];
}
// 3. If after all checks, product_details is empty (e.g. invalid items in cart), redirect.
if (empty($product_details)) {
// Clear the invalid cart and redirect
unset($_SESSION['cart']);
header('Location: shop.php');
exit();
}
// 4. Fetch user data if logged in
$user_id = $_SESSION['user_id'] ?? null;
$user = [];
$address = [];
if ($user_id) {
try { try {
$pdo = db(); $pdo = db();
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $user_stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]); $user_stmt->execute([$user_id]);
$logged_in_user = $stmt->fetch(PDO::FETCH_ASSOC); $user = $user_stmt->fetch(PDO::FETCH_ASSOC) ?: [];
$stmt = $pdo->prepare("SELECT * FROM user_addresses WHERE user_id = ? ORDER BY is_default DESC, id DESC"); $address_stmt = $pdo->prepare("SELECT * FROM user_addresses WHERE user_id = ? ORDER BY id DESC LIMIT 1");
$stmt->execute([$_SESSION['user_id']]); $address_stmt->execute([$user_id]);
$user_addresses = $stmt->fetchAll(PDO::FETCH_ASSOC); $address = $address_stmt->fetch(PDO::FETCH_ASSOC) ?: [];
} catch (PDOException $e) { } catch (PDOException $e) {
// In a real app, log this error error_log("Checkout user fetch error: " . $e->getMessage());
die("Error fetching user data."); // Do not block the page, guest checkout is still possible
} }
} }
$page_title = 'تکمیل سفارش';
require_once 'includes/header.php'; $shipping_cost = 50000;
$grand_total = $total_price + $shipping_cost;
?> ?>
<div class="container my-5 bg-dark text-light"> <main class="container my-5 checkout-page-wrapper">
<?php <div class="row">
if (isset($_SESSION['error_message'])) { <!-- Billing Details Column -->
echo '<div class="alert alert-danger alert-dismissible fade show" role="alert">' . htmlspecialchars($_SESSION['error_message']) . '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>'; <div class="col-lg-8">
unset($_SESSION['error_message']); <h2 class="mb-4">جزئیات صورتحساب</h2>
}
?>
<div class="text-center mb-5">
<h1 class="fw-bold">تکمیل فرآیند خرید</h1>
<p class="text-muted">فقط یک قدم دیگر تا نهایی شدن سفارش شما باقیست.</p>
</div>
<form action="checkout_handler.php" method="POST"> <?php
<div class="row g-5"> if (!empty($_SESSION['checkout_errors'])) {
<!-- Shipping Details --> echo '<div class="alert alert-danger"><ul>';
<div class="col-lg-7"> foreach ($_SESSION['checkout_errors'] as $error) {
<h3 class="mb-4">اطلاعات ارسال</h3> echo '<li>' . htmlspecialchars($error) . '</li>';
}
echo '</ul></div>';
// Unset the session variable so it doesn't show again on refresh
unset($_SESSION['checkout_errors']);
}
?>
<?php if ($is_logged_in && !empty($user_addresses)): ?> <form id="checkout-form" action="checkout_handler.php" method="POST">
<div class="mb-4">
<label for="saved_address" class="form-label">انتخاب آدرس</label>
<select class="form-select bg-dark text-light" id="saved_address">
<option value="">یک آدرس انتخاب کنید یا فرم زیر را پر کنید...</option>
<?php foreach ($user_addresses as $addr): ?>
<option value='<?php echo json_encode($addr, JSON_HEX_APOS | JSON_HEX_QUOT); ?>'>
<?php echo htmlspecialchars($addr['province'] . '، ' . $addr['city'] . '، ' . $addr['address_line']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<?php endif; ?>
<div class="card bg-dark border-secondary shadow-sm rounded-4"> <div class="checkout-card">
<div class="card-body p-4"> <div class="card-header">اطلاعات تماس</div>
<div class="row g-3"> <div class="card-body">
<div class="col-md-6"> <div class="row">
<label for="first_name" class="form-label">نام</label> <div class="col-md-6 mb-3">
<input type="text" class="form-control bg-dark text-light" id="first_name" name="first_name" value="<?php echo htmlspecialchars($logged_in_user['first_name'] ?? ''); ?>" required> <label for="firstName" class="form-label">نام</label>
<div class="invalid-feedback"></div> <input type="text" class="form-control" id="firstName" name="first_name" value="<?= htmlspecialchars($user['first_name'] ?? '') ?>" required>
</div> </div>
<div class="col-md-6"> <div class="col-md-6 mb-3">
<label for="last_name" class="form-label">نام خانوادگی</label> <label for="lastName" class="form-label">نام خانوادگی</label>
<input type="text" class="form-control bg-dark text-light" id="last_name" name="last_name" value="<?php echo htmlspecialchars($logged_in_user['last_name'] ?? ''); ?>" required> <input type="text" class="form-control" id="lastName" name="last_name" value="<?= htmlspecialchars($user['last_name'] ?? '') ?>" required>
<div class="invalid-feedback"></div>
</div> </div>
<div class="col-md-6"> <div class="col-md-6 mb-3">
<label for="phone_number" class="form-label">تلفن همراه</label>
<input type="tel" class="form-control bg-dark text-light" id="phone_number" name="phone_number" value="<?php echo htmlspecialchars($logged_in_user['phone_number'] ?? ''); ?>" required>
<div class="invalid-feedback"></div>
<?php if (!$is_logged_in): ?>
<div class="form-text text-info fw-bold">توجه: فقط با شماره تلفن همراه میتوان سفارش را رهگیری کرد.</div>
<?php endif; ?>
</div>
<div class="col-md-6">
<label for="province" class="form-label">استان</label>
<input type="text" class="form-control bg-dark text-light" id="province" name="province" required>
<div class="invalid-feedback"></div>
</div>
<div class="col-md-6">
<label for="city" class="form-label">شهر</label>
<input type="text" class="form-control bg-dark text-light" id="city" name="city" required>
<div class="invalid-feedback"></div>
</div>
<div class="col-md-6">
<label for="address_line" class="form-label">آدرس دقیق</label>
<textarea class="form-control bg-dark text-light" id="address_line" name="address_line" rows="2" required></textarea>
<div class="invalid-feedback"></div>
</div>
<div class="col-md-5">
<label for="postal_code" class="form-label">کد پستی</label>
<input type="text" class="form-control bg-dark text-light" id="postal_code" name="postal_code" required>
<div class="invalid-feedback"></div>
</div>
<div class="col-md-7">
<label for="email" class="form-label">ایمیل (اختیاری)</label> <label for="email" class="form-label">ایمیل (اختیاری)</label>
<input type="email" class="form-control bg-dark text-light" id="email" name="email" value="<?php echo htmlspecialchars($logged_in_user['email'] ?? ''); ?>"> <input type="email" class="form-control" id="email" name="email" value="<?= htmlspecialchars($user['email'] ?? '') ?>">
<div class="invalid-feedback"></div> </div>
<div class="col-md-6 mb-3">
<label for="phone" class="form-label">تلفن همراه</label>
<input type="tel" class="form-control" id="phone" name="phone_number" value="<?= htmlspecialchars($address['phone_number'] ?? $user['phone_number'] ?? '') ?>" required>
</div> </div>
</div>
<div class="form-check mt-4">
<input type="checkbox" class="form-check-input" id="terms" name="terms" required>
<label class="form-check-label" for="terms">
با <a href="#">قوانین و مقررات</a> سایت موافقم.
</label>
<div class="invalid-feedback">لطفاً قوانین و مقررات را بپذیرید.</div>
</div> </div>
</div> </div>
</div> </div>
</div>
<!-- Order Summary --> <div class="checkout-card">
<div class="col-lg-5"> <div class="card-header">آدرس جهت ارسال</div>
<div class="card bg-dark border-secondary shadow-sm rounded-4 sticky-top" style="top: 100px;"> <div class="card-body">
<div class="card-body p-4"> <div class="mb-3">
<h4 class="card-title fw-bold mb-4">خلاصه سفارش</h4> <label for="address" class="form-label">آدرس</label>
<ul class="list-group list-group-flush mb-4"> <input type="text" class="form-control" id="address" name="address_line" placeholder="خیابان اصلی، کوچه فرعی، پلاک ۱۲۳" value="<?= htmlspecialchars($address['address_line'] ?? '') ?>" required>
<?php foreach($cart_items as $item): ?>
<li class="list-group-item bg-dark text-light d-flex justify-content-between align-items-center px-0">
<div class="d-flex align-items-center">
<img src="<?php echo htmlspecialchars($item['image_url']); ?>" width="60" class="rounded-3 me-3" alt="<?php echo htmlspecialchars($item['name']); ?>">
<div>
<?php echo htmlspecialchars($item['name']); ?>
<small class="d-block text-muted">تعداد: <?php echo $item['quantity']; ?></small>
<?php if (!empty($item['color'])): ?>
<div class="d-flex align-items-center gx-2 mt-1">
<small class="text-muted">رنگ:</small>
<span class="d-inline-block rounded-circle border ms-2" style="width: 15px; height: 15px; background-color: <?php echo htmlspecialchars($item['color']); ?>;"></span>
</div>
<?php endif; ?>
</div>
</div>
<span class="fw-bold"><?php echo number_format($item['price'] * $item['quantity']); ?></span>
</li>
<?php endforeach; ?>
</ul>
<div class="d-flex justify-content-between mb-2">
<span class="text-muted">جمع کل</span>
<span><?php echo number_format($total_price); ?> تومان</span>
</div> </div>
<div class="d-flex justify-content-between mb-3"> <div class="row">
<span class="text-muted">هزینه ارسال</span> <div class="col-md-4 mb-3">
<span class="text-success">رایگان</span> <label for="city" class="form-label">شهر</label>
</div> <input type="text" class="form-control" id="city" name="city" value="<?= htmlspecialchars($address['city'] ?? '') ?>" required>
<hr class="border-secondary"> </div>
<div class="d-flex justify-content-between align-items-center mb-4"> <div class="col-md-4 mb-3">
<span class="h5 fw-bold">مبلغ نهایی</span> <label for="state" class="form-label">استان</label>
<span class="h5 fw-bolder text-primary"><?php echo number_format($total_price); ?> تومان</span> <input type="text" class="form-control" id="state" name="province" value="<?= htmlspecialchars($address['province'] ?? '') ?>" required>
</div> </div>
<div class="d-grid"> <div class="col-md-4 mb-3">
<button type="submit" class="btn btn-primary btn-lg">ثبت نهایی سفارش</button> <label for="zip" class="form-label">کد پستی</label>
</div> <input type="text" class="form-control" id="zip" name="postal_code" value="<?= htmlspecialchars($address['postal_code'] ?? '') ?>" required>
<div class="text-center mt-3"> </div>
<small class="text-muted"><i class="ri-lock-line me-1"></i> پرداخت امن و مطمئن</small>
</div> </div>
</div> </div>
</div> </div>
</form>
</div>
<!-- Order Summary Column -->
<div class="col-lg-4">
<div class="order-summary-card checkout-order-summary">
<h3 class="card-title">خلاصه سفارش شما</h3>
<ul class="summary-item-list">
<?php foreach ($product_details as $item) : ?>
<li>
<span class="product-name"><?= htmlspecialchars($item['name']) ?> <span class="text-muted">(x<?= $item['quantity'] ?>)</span></span>
<span class="product-total">T <?= number_format($item['total']) ?></span>
</li>
<?php endforeach; ?>
</ul>
<div class="summary-totals">
<div class="total-row">
<span class="label">جمع کل</span>
<span class="value">T <?= number_format($total_price) ?></span>
</div>
<div class="total-row">
<span class="label">هزینه ارسال</span>
<span class="value">T <?= number_format($shipping_cost) ?></span>
</div>
<div class="total-row grand-total mt-3">
<span class="label">مبلغ قابل پرداخت</span>
<span class="value">T <?= number_format($grand_total) ?></span>
</div>
</div>
<div class="d-grid mt-4">
<button type="submit" form="checkout-form" class="btn btn-primary btn-lg">
<i class="ri-secure-payment-line me-2"></i>
پرداخت و ثبت نهایی سفارش
</button>
</div>
</div> </div>
</div> </div>
</form> </div>
</div> </main>
<script src="assets/js/checkout_validation.js?v=<?php echo time(); ?>"></script>
<?php require_once 'includes/footer.php'; ?> <?php require_once 'includes/footer.php'; ?>

View File

@ -1,109 +1,158 @@
<?php <?php
session_start(); session_start();
require_once 'db/config.php'; require_once 'db/config.php';
// 1. Basic Security: Only allow POST requests and check for cart // 1. Ensure it's a POST request
if ($_SERVER['REQUEST_METHOD'] !== 'POST') { if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
header('Location: index.php');
exit;
}
if (empty($_SESSION['cart'])) {
header('Location: shop.php');
exit;
}
// 2. Retrieve and sanitize form data
$first_name = filter_input(INPUT_POST, 'first_name', FILTER_SANITIZE_STRING);
$last_name = filter_input(INPUT_POST, 'last_name', FILTER_SANITIZE_STRING);
$phone_number = filter_input(INPUT_POST, 'phone_number', FILTER_SANITIZE_STRING);
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
$province = filter_input(INPUT_POST, 'province', FILTER_SANITIZE_STRING);
$city = filter_input(INPUT_POST, 'city', FILTER_SANITIZE_STRING);
$address_line = filter_input(INPUT_POST, 'address_line', FILTER_SANITIZE_STRING);
$postal_code = filter_input(INPUT_POST, 'postal_code', FILTER_SANITIZE_STRING);
// 3. Server-side validation (Email is now optional)
if (!$first_name || !$last_name || !$phone_number || !$province || !$city || !$address_line || !$postal_code) {
$_SESSION['error_message'] = 'لطفاً تمام فیلدهای آدرس به جز ایمیل را تکمیل کنید.';
header('Location: checkout.php'); header('Location: checkout.php');
exit; exit();
} }
// 2. Check if cart is empty
if (empty($_SESSION['cart'])) {
$_SESSION['error_message'] = 'سبد خرید شما خالی است.';
header('Location: cart.php');
exit();
}
// 3. Collect and trim form data
$first_name = trim($_POST['first_name'] ?? '');
$last_name = trim($_POST['last_name'] ?? '');
$email = trim($_POST['email'] ?? '');
$phone_number = trim($_POST['phone_number'] ?? '');
$address_line = trim($_POST['address_line'] ?? '');
$city = trim($_POST['city'] ?? '');
$province = trim($_POST['province'] ?? '');
$postal_code = trim($_POST['postal_code'] ?? '');
// 4. Basic Validation
$errors = [];
if (empty($first_name)) $errors[] = 'فیلد نام الزامی است.';
if (empty($last_name)) $errors[] = 'فیلد نام خانوادگی الزامی است.';
if (empty($phone_number)) $errors[] = 'فیلد تلفن همراه الزامی است.';
if (empty($address_line)) $errors[] = 'فیلد آدرس الزامی است.';
if (empty($city)) $errors[] = 'فیلد شهر الزامی است.';
if (empty($province)) $errors[] = 'فیلد استان الزامی است.';
if (empty($postal_code)) $errors[] = 'فیلد کد پستی الزامی است.';
if (!empty($errors)) {
$_SESSION['checkout_errors'] = $errors;
// Store submitted data to re-populate the form
$_SESSION['form_data'] = $_POST;
header('Location: checkout.php');
exit();
}
// == Server-Side Calculation ==
$cart = $_SESSION['cart'];
$product_ids = array_keys($cart);
$items_for_json = [];
$total_price = 0;
if (!empty($product_ids)) {
$placeholders = implode(',', array_fill(0, count($product_ids), '?'));
$stmt = db()->prepare("SELECT id, name, price FROM products WHERE id IN ($placeholders)");
$stmt->execute($product_ids);
$products_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Create a map for quick lookup
$products_by_id = [];
foreach($products_data as $product) {
$products_by_id[$product['id']] = $product;
}
foreach ($cart as $product_id => $details) {
if (isset($products_by_id[$product_id])) {
$product = $products_by_id[$product_id];
$price = $product['price'];
$quantity = $details['quantity'];
$total_price += $price * $quantity;
$items_for_json[] = [
'id' => $product_id,
'name' => $product['name'],
'price' => $price,
'quantity' => $quantity,
'color' => $details['color']
];
}
}
}
$shipping_cost = 50000;
$grand_total = $total_price + $shipping_cost;
// == Database Operations ==
$pdo = db(); $pdo = db();
$pdo->beginTransaction();
try { try {
// 4. Prepare order data $pdo->beginTransaction();
$billing_name = trim($first_name . ' ' . $last_name);
$cart_items = $_SESSION['cart'];
$total_amount = array_reduce($cart_items, function ($sum, $item) {
return $sum + ($item['price'] * $item['quantity']);
}, 0);
$products_data_json = json_encode($cart_items, JSON_UNESCAPED_UNICODE);
// 5. Insert the order into the database using the correct, updated column names // 5. User Handling (Guest or Logged in)
$stmt = $pdo->prepare( $user_id = $_SESSION['user_id'] ?? null;
"INSERT INTO orders (user_id, billing_name, billing_email, billing_phone, billing_province, billing_city, billing_address, billing_postal_code, total_amount, items_json, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
if (!$user_id) {
// For guests, check if user exists by phone
$user_stmt = $pdo->prepare("SELECT id FROM users WHERE phone_number = ?");
$user_stmt->execute([$phone_number]);
$existing_user = $user_stmt->fetch(PDO::FETCH_ASSOC);
if ($existing_user) {
$user_id = $existing_user['id'];
} else {
// Create a new user
$user_insert_stmt = $pdo->prepare("INSERT INTO users (first_name, last_name, email, phone_number, is_admin) VALUES (?, ?, ?, ?, 0)");
$user_insert_stmt->execute([$first_name, $last_name, $email, $phone_number]);
$user_id = $pdo->lastInsertId();
}
// Log the new/guest user in
$_SESSION['user_id'] = $user_id;
}
// 6. Generate a unique tracking ID
$tracking_id = 'FL-' . strtoupper(bin2hex(random_bytes(5)));
// 7. Insert the order into the database
$order_stmt = $pdo->prepare(
"INSERT INTO orders (user_id, billing_name, billing_email, billing_phone, billing_province, billing_city, billing_address, billing_postal_code, total_amount, items_json, status, tracking_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending', ?)"
); );
$user_id = isset($_SESSION['user_id']) ? $_SESSION['user_id'] : null; $full_name = $first_name . ' ' . $last_name;
$status = 'Processing'; // Default status $items_json_encoded = json_encode($items_for_json, JSON_UNESCAPED_UNICODE);
$final_email = ($email !== false && $email !== '') ? $email : null;
$stmt->execute([ $order_stmt->execute([
$user_id, $user_id,
$billing_name, $full_name,
$final_email, $email,
$phone_number, $phone_number,
$province, $province,
$city, $city,
$address_line, $address_line,
$postal_code, $postal_code,
$total_amount, $grand_total, // Storing the final amount including shipping
$products_data_json, $items_json_encoded,
$status $tracking_id
]); ]);
$order_id = $pdo->lastInsertId();
$tracking_id = uniqid('ATMH-');
$update_stmt = $pdo->prepare("UPDATE orders SET tracking_id = ? WHERE id = ?");
$update_stmt->execute([$tracking_id, $order_id]);
// 6. If user is logged in, save the new address for future use
if ($user_id) {
$stmt_check_addr = $pdo->prepare("SELECT COUNT(*) FROM user_addresses WHERE user_id = ? AND address_line = ? AND postal_code = ?");
$stmt_check_addr->execute([$user_id, $address_line, $postal_code]);
$address_exists = $stmt_check_addr->fetchColumn();
if ($address_exists == 0) {
$stmt_save_addr = $pdo->prepare(
"INSERT INTO user_addresses (user_id, first_name, last_name, phone_number, province, city, address_line, postal_code) VALUES (?, ?, ?, ?, ?, ?, ?, ?)"
);
$stmt_save_addr->execute([
$user_id, $first_name, $last_name, $phone_number, $province, $city, $address_line, $postal_code
]);
}
}
// 7. Commit transaction
$pdo->commit(); $pdo->commit();
// 8. Clear the cart and redirect with a success message including tracking ID // 8. Clear cart and redirect to a success page
unset($_SESSION['cart']); unset($_SESSION['cart']);
$_SESSION['success_message'] = "سفارش شما با موفقیت ثبت شد! کد پیگیری شما: <strong>" . htmlspecialchars($tracking_id) . "</strong>"; unset($_SESSION['form_data']);
// As I don't have SMS capability, I am displaying the tracking code here.
// You can later integrate an SMS service and send the tracking ID to $phone_number.
header('Location: index.php'); header('Location: track_order.php?tracking_id=' . $tracking_id);
exit; exit();
} catch (Exception $e) { } catch (Exception $e) {
// 9. If anything fails, rollback and redirect with an error
$pdo->rollBack(); $pdo->rollBack();
error_log("Order Creation Failed: " . $e->getMessage()); // Log error for admin // Log the detailed error for developers
$_SESSION['error_message'] = 'خطایی در ثبت سفارش رخ داد. لطفاً دوباره تلاش کنید.'; error_log('Checkout Error: ' . $e->getMessage());
// Set a user-friendly error message and redirect
$_SESSION['checkout_errors'] = ['یک خطای غیرمنتظره در هنگام ثبت سفارش رخ داد. لطفاً لحظاتی دیگر دوباره تلاش کنید.'];
$_SESSION['form_data'] = $_POST;
header('Location: checkout.php'); header('Location: checkout.php');
exit; exit();
} }

View File

@ -11,11 +11,11 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['contact_form'])) {
$message = trim(filter_input(INPUT_POST, 'message', FILTER_SANITIZE_STRING)); $message = trim(filter_input(INPUT_POST, 'message', FILTER_SANITIZE_STRING));
if (empty($name) || empty($email) || empty($message)) { if (empty($name) || empty($email) || empty($message)) {
$_SESSION['flash_message'] = ['type' => 'error', 'message' => 'لطفاً تمام فیلدها را پر کنید.']; $_SESSION['flash_message'] = ['type' => 'warning', 'message' => 'لطفاً تمام فیلدها را پر کنید.'];
} elseif (!$email) { } elseif (!$email) {
$_SESSION['flash_message'] = ['type' => 'error', 'message' => 'آدرس ایمیل وارد شده معتبر نیست.']; $_SESSION['flash_message'] = ['type' => 'error', 'message' => 'آدرس ایمیل وارد شده معتبر نیست.'];
} else { } else {
$to_email = getenv('MAIL_TO') ?: 'support@atimeh.com'; $to_email = getenv('MAIL_TO') ?: 'support@atimeh.com'; // Fallback email
$subject = "پیام جدید از فرم تماس وب‌سایت"; $subject = "پیام جدید از فرم تماس وب‌سایت";
$email_result = MailService::sendContactMessage($name, $email, $message, $to_email, $subject); $email_result = MailService::sendContactMessage($name, $email, $message, $to_email, $subject);
@ -27,12 +27,15 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['contact_form'])) {
} }
} }
// Redirect to the same page to prevent form resubmission
header("Location: contact.php"); header("Location: contact.php");
exit(); exit();
} }
// Check for flash message
$flash_message = $_SESSION['flash_message'] ?? null; $flash_message = $_SESSION['flash_message'] ?? null;
if ($flash_message) { if ($flash_message) {
// Clear the message from session so it doesn't show again
unset($_SESSION['flash_message']); unset($_SESSION['flash_message']);
} }
?> ?>
@ -49,21 +52,21 @@ if ($flash_message) {
<div class="contact-info h-100 d-flex flex-column justify-content-center"> <div class="contact-info h-100 d-flex flex-column justify-content-center">
<h3 class="mb-4">راه‌های ارتباطی</h3> <h3 class="mb-4">راه‌های ارتباطی</h3>
<div class="d-flex align-items-start mb-4"> <div class="d-flex align-items-start mb-4">
<i class="fas fa-map-marker-alt mt-1 me-3"></i> <i class="ri-map-pin-line mt-1 me-3"></i>
<div> <div>
<strong>آدرس:</strong> <strong>آدرس:</strong>
<p class="text-muted mb-0">تهران، خیابان هنر، کوچه خلاقیت، پلاک ۱۲</p> <p class="text-muted mb-0">تهران، خیابان هنر، کوچه خلاقیت، پلاک ۱۲</p>
</div> </div>
</div> </div>
<div class="d-flex align-items-start mb-4"> <div class="d-flex align-items-start mb-4">
<i class="fas fa-envelope mt-1 me-3"></i> <i class="ri-mail-line mt-1 me-3"></i>
<div> <div>
<strong>ایمیل:</strong> <strong>ایمیل:</strong>
<p class="mb-0"><a href="mailto:info@atimeh.com">info@atimeh.com</a></p> <p class="mb-0"><a href="mailto:info@atimeh.com">info@atimeh.com</a></p>
</div> </div>
</div> </div>
<div class="d-flex align-items-start mb-4"> <div class="d-flex align-items-start mb-4">
<i class="fas fa-phone-alt mt-1 me-3"></i> <i class="ri-phone-line mt-1 me-3"></i>
<div> <div>
<strong>تلفن:</strong> <strong>تلفن:</strong>
<p class="mb-0"><a href="tel:+982112345678">۰۲۱-۱۲۳۴۵۶۷۸</a></p> <p class="mb-0"><a href="tel:+982112345678">۰۲۱-۱۲۳۴۵۶۷۸</a></p>
@ -71,17 +74,17 @@ if ($flash_message) {
</div> </div>
<hr class="my-4" style="border-color: var(--luxury-border);"> <hr class="my-4" style="border-color: var(--luxury-border);">
<h4 class="h5 mb-3">ما را دنبال کنید</h4> <h4 class="h5 mb-3">ما را دنبال کنید</h4>
<div class="d-flex"> <div class="d-flex gap-2">
<a href="#" class="btn btn-outline-primary rounded-circle me-2" style="width: 40px; height: 40px; line-height: 25px; text-align: center; padding: 5px;"><i class="fab fa-instagram"></i></a> <a href="#" class="social-btn"><i class="ri-instagram-line"></i></a>
<a href="#" class="btn btn-outline-primary rounded-circle me-2" style="width: 40px; height: 40px; line-height: 25px; text-align: center; padding: 5px;"><i class="fab fa-telegram"></i></a> <a href="#" class="social-btn"><i class="ri-telegram-line"></i></a>
<a href="#" class="btn btn-outline-primary rounded-circle" style="width: 40px; height: 40px; line-height: 25px; text-align: center; padding: 5px;"><i class="fab fa-whatsapp"></i></a> <a href="#" class="social-btn"><i class="ri-whatsapp-line"></i></a>
</div> </div>
</div> </div>
</div> </div>
<div class="col-lg-7"> <div class="col-lg-7">
<h3 class="mb-4">فرم تماس</h3> <h3 class="mb-4">فرم تماس</h3>
<form action="contact.php" method="POST"> <form action="contact.php" method="POST">
<input type="hidden" name="contact_form"> <input type="hidden" name="contact_form" value="1">
<div class="mb-4"> <div class="mb-4">
<label for="name" class="form-label">نام شما</label> <label for="name" class="form-label">نام شما</label>
<input type="text" class="form-control" id="name" name="name" required> <input type="text" class="form-control" id="name" name="name" required>
@ -103,25 +106,28 @@ if ($flash_message) {
</div> </div>
</div> </div>
<!-- SweetAlert for flash messages -->
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
<?php if ($flash_message): ?> <?php if ($flash_message): ?>
const swalConfig = { Swal.fire({
title: '<?php echo $flash_message["type"] === "success" ? "موفق" : "خطا"; ?>', title: '<?php echo addslashes($flash_message["message"]); ?>',
text: '<?php echo addslashes($flash_message["message"]); ?>',
icon: '<?php echo $flash_message["type"]; ?>', icon: '<?php echo $flash_message["type"]; ?>',
confirmButtonText: 'باشه', toast: true,
}; position: 'top-start',
showConfirmButton: false,
// Apply dark theme to SweetAlert2 timer: 5000,
if (document.body.classList.contains('dark-luxury')) { timerProgressBar: true,
swalConfig.background = 'var(--luxury-surface)'; showCloseButton: true,
swalConfig.color = 'var(--luxury-text)'; didOpen: (toast) => {
swalConfig.confirmButtonColor = 'var(--luxury-primary)'; toast.addEventListener('mouseenter', Swal.stopTimer);
} toast.addEventListener('mouseleave', Swal.resumeTimer);
},
Swal.fire(swalConfig); customClass: {
popup: 'dark-theme-toast'
}
});
<?php endif; ?> <?php endif; ?>
}); });
</script> </script>

View File

@ -0,0 +1 @@
ALTER TABLE `users` CHANGE `password` `password` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL;

86
faq.php Normal file
View File

@ -0,0 +1,86 @@
<?php
$page_title = 'سوالات متداول';
require_once 'includes/header.php';
?>
<main class="container py-5 my-5">
<div class="section-title text-center mb-5" data-aos="fade-down">
<h1>سوالات متداول</h1>
<p class="fs-5 text-muted">پاسخ به برخی از سوالات شما</p>
</div>
<div class="row justify-content-center">
<div class="col-lg-10 col-xl-8">
<div class="accordion" id="faqAccordion">
<div class="accordion-item" data-aos="fade-up">
<h2 class="accordion-header" id="headingOne">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseOne" aria-expanded="false" aria-controls="collapseOne">
چگونه می‌توانم سفارش خود را ثبت کنم؟
</button>
</h2>
<div id="collapseOne" class="accordion-collapse collapse" aria-labelledby="headingOne" data-bs-parent="#faqAccordion">
<div class="accordion-body">
<p>شما می‌توانید با مراجعه به بخش فروشگاه، محصولات مورد نظر خود را به سبد خرید اضافه کرده و سپس با تکمیل اطلاعات و پرداخت، سفارش خود را نهایی کنید.</p>
</div>
</div>
</div>
<div class="accordion-item" data-aos="fade-up" data-aos-delay="100">
<h2 class="accordion-header" id="headingTwo">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseTwo" aria-expanded="false" aria-controls="collapseTwo">
زمان ارسال سفارش چقدر است؟
</button>
</h2>
<div id="collapseTwo" class="accordion-collapse collapse" aria-labelledby="headingTwo" data-bs-parent="#faqAccordion">
<div class="accordion-body">
<p>سفارش‌ها در تهران طی ۲ تا ۳ روز کاری و در سایر شهرها طی ۴ تا ۷ روز کاری از طریق پست پیشتاز ارسال می‌شوند. کد رهگیری پستی پس از ارسال، برای شما پیامک خواهد شد.</p>
</div>
</div>
</div>
<div class="accordion-item" data-aos="fade-up" data-aos-delay="200">
<h2 class="accordion-header" id="headingThree">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseThree" aria-expanded="false" aria-controls="collapseThree">
آیا امکان بازگشت کالا وجود دارد؟
</button>
</h2>
<div id="collapseThree" class="accordion-collapse collapse" aria-labelledby="headingThree" data-bs-parent="#faqAccordion">
<div class="accordion-body">
<p>بله، در صورت عدم رضایت از محصول یا وجود هرگونه مغایرت، تا ۷ روز پس از دریافت کالا فرصت دارید تا آن را بازگردانید. لطفاً توجه داشته باشید که محصول نباید استفاده شده باشد و بسته‌بندی آن آسیب ندیده باشد. برای هماهنگی با پشتیبانی تماس بگیرید.</p>
</div>
</div>
</div>
<div class="accordion-item" data-aos="fade-up" data-aos-delay="300">
<h2 class="accordion-header" id="headingFour">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseFour" aria-expanded="false" aria-controls="collapseFour">
چگونه می‌توانم سفارشم را پیگیری کنم؟
</button>
</h2>
<div id="collapseFour" class="accordion-collapse collapse" aria-labelledby="headingFour" data-bs-parent="#faqAccordion">
<div class="accordion-body">
<p>پس از ارسال سفارش، یک کد رهگیری ۲۴ رقمی از طریق پیامک برای شما ارسال می‌شود. شما می‌توانید با مراجعه به وب‌سایت رسمی پست و وارد کردن این کد، از آخرین وضعیت بسته خود مطلع شوید. همچنین می‌توانید از طریق صفحه "پیگیری سفارش" در سایت ما نیز اقدام کنید.</p>
</div>
</div>
</div>
<div class="accordion-item" data-aos="fade-up" data-aos-delay="400">
<h2 class="accordion-header" id="headingFive">
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#collapseFive" aria-expanded="false" aria-controls="collapseFive">
آیا محصولات شما دارای ضمانت هستند؟
</button>
</h2>
<div id="collapseFive" class="accordion-collapse collapse" aria-labelledby="headingFive" data-bs-parent="#faqAccordion">
<div class="accordion-body">
<p>بله، تمامی محصولات چرم ما دارای ۶ ماه ضمانت کیفیت دوخت و یراق‌آلات هستند. این ضمانت شامل آسیب‌های ناشی از استفاده نادرست نمی‌شود.</p>
</div>
</div>
</div>
</div>
</div>
</div>
</main>
<?php require_once 'includes/footer.php'; ?>

View File

@ -11,9 +11,10 @@
<h5 class="fw-bold mb-3">دسترسی سریع</h5> <h5 class="fw-bold mb-3">دسترسی سریع</h5>
<ul class="list-unstyled"> <ul class="list-unstyled">
<li><a href="shop.php" class="text-white-50">فروشگاه</a></li> <li><a href="shop.php" class="text-white-50">فروشگاه</a></li>
<li><a href="#" class="text-white-50">درباره ما</a></li> <li><a href="track_order.php" class="text-white-50">پیگیری سفارش</a></li>
<li><a href="#" class="text-white-50">قوانین و مقررات</a></li> <li><a href="about.php" class="text-white-50">درباره ما</a></li>
<li><a href="#" class="text-white-50">سوالات متداول</a></li> <li><a href="terms.php" class="text-white-50">قوانین و مقررات</a></li>
<li><a href="faq.php" class="text-white-50">سوالات متداول</a></li>
</ul> </ul>
</div> </div>
<div class="col-lg-3 col-md-6 mb-4 mb-lg-0"> <div class="col-lg-3 col-md-6 mb-4 mb-lg-0">

View File

@ -1,24 +1,258 @@
<?php <?php
// Jalali (Shamsi) to Gregorian and vice-versa converter in PHP /*
// Original source: https://github.com/moradin/Jalali/blob/master/jdf.php Farsi Jalali (Shamsi) Date and Time Functions
// Simplified for this project. Copyright (C) 2000-2019 Sallar Kaboli (http://sallar.kaboli.org)
Latest version available at: http://jdf.scr.ir
function gregorian_to_jalali($gy, $gm, $gd, $mod='') { LICENSE: FREE FOR NON-COMMERCIAL USE
$g_d_m = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
$jy = ($gy <= 1600) ? 0 : 979; This program is distributed in the hope that it will be useful,
$gy -= ($gy <= 1600) ? 621 : 1600; but WITHOUT ANY WARRANTY; without even the implied warranty of
$gy2 = ($gm > 2) ? ($gy + 1) : $gy; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$days = (365 * $gy) + ((int)(($gy2 + 3) / 4)) - ((int)(($gy2 + 99) / 100)) + ((int)(($gy2 + 399) / 400)) - 80 + $gd + $g_d_m[$gm - 1];
$jy += 33 * ((int)($days / 12053)); */
$days %= 12053;
$jy += 4 * ((int)($days / 1461)); function jdate($format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa')
$days %= 1461; {
$jy += (int)(($days - 1) / 365);
if ($days > 365) $days = ($days - 1) % 365; $T_sec=0;/* <= آرشیو شود */
$jm = ($days < 186) ? 1 + (int)($days / 31) : 7 + (int)(($days - 186) / 30);
$jd = 1 + (($days < 186) ? ($days % 31) : (($days - 186) % 30)); if($time_zone != 'local') date_default_timezone_set(($time_zone === '') ? 'Asia/Tehran' : $time_zone);
return ($mod == '') ? array($jy, $jm, $jd) : $jy . $mod . $jm . $mod . $jd; $ts=$T_sec+(($timestamp==='') ? time() : tr_num($timestamp));
$date=explode(' _ ',date('H_i_j_n_O_P_s_w_Y',$ts));
list($j_y,$j_m,$j_d)=gregorian_to_jalali($date[8],$date[3],$date[2]);
$doy=($j_m<7)?(($j_m-1)*31)+$j_d-1:(($j_m-7)*30)+$j_d+185;
$kab=(((($j_y%33)%4)-1)%4==0);
$sl=strlen($format);
$out='';
for($i=0; $i<$sl; $i++)
{
$sub=substr($format,$i,1);
if($sub=='\\')
{
$out.=substr($format,++$i,1);
continue;
}
switch($sub)
{
case 'a':$out.=($date[0]<12)?'ق.ظ':'ب.ظ';break;
case 'A':$out.=($date[0]<12)?'قبل از ظهر':'بعد از ظهر';break;
case 'B':$out.=floor(1+($ts/86400));break;
case 'c':$out.=date('Y-m-d\TH:i:sP',$ts);break;
case 'd':$out.=($j_d<10)?'0'.$j_d:$j_d;break;
case 'D':$out.=jdate_words(array('rh'=>$date[7]),' ');break;
case 'F':$out.=jdate_words(array('mm'=>$j_m),' ');break;
case 'g':$out.=($date[0]>12)?$date[0]-12:$date[0];break;
case 'G':$out.=$date[0];break;
case 'h':$out.=((($date[0]>12)?$date[0]-12:$date[0])<10)?'0'.(($date[0]>12)?$date[0]-12:$date[0]):(($date[0]>12)?$date[0]-12:$date[0]);break;
case 'H':$out.=($date[0]<10)?'0'.$date[0]:$date[0];break;
case 'i':$out.=($date[1]<10)?'0'.$date[1]:$date[1];break;
case 'j':$out.=$j_d;break;
case 'l':$out.=jdate_words(array('rh'=>$date[7]),' ');break;
case 'L':$out.=$kab;break;
case 'm':$out.=($j_m<10)?'0'.$j_m:$j_m;break;
case 'M':$out.=jdate_words(array('mn'=>$j_m),' ');break;
case 'n':$out.=$j_m;break;
case 'N':$out.=$date[7]+1;break;
case 'o':
$j_y_plus= $j_y+1;
$j_y_minus= $j_y-1;
$fall_start=gregorian_to_jalali(date('Y', $ts),3,21);
$fall_end=gregorian_to_jalali(date('Y', $ts),12,21);
if($j_d > $fall_start[2] && $j_m <4)
{
$out.=$j_y_minus;
}
elseif($j_d < $fall_end[2] && $j_m > 10)
{
$out.=$j_y_plus;
}
else
{
$out.=$j_y;
}
break;
case 'O':$out.=$date[4];break;
case 'p':$out.=jdate_words(array('mb'=>$j_m),' ');break;
case 'P':$out.=$date[5];break;
case 'q':$out.=jdate_words(array('sh'=>$j_y),' ');break;
case 'r':$out.=jdate_words(array('rh'=>$date[7]),' ') .'، ' . $j_d.' ' . jdate_words(array('mm'=>$j_m),' ') .' ' . $j_y .' ' . $date[0].':' . $date[1].':' . $date[6] .' ' . $date[4];break;
case 's':$out.=($date[6]<10)?'0'.$date[6]:$date[6];break;
case 'S':$out.='ام';break;
case 't':$out.=($j_m!=12)?(31-(int)($j_m/6.5)):($kab+29);break;
case 'U':$out.=$ts;break;
case 'w':$out.=$date[7];break;
case 'W':$out.=(int)($doy/7);break;
case 'y':$out.=substr($j_y,2,2);break;
case 'Y':$out.=$j_y;break;
case 'z':$out.=$doy;break;
default:$out.=$sub;
}
}
return ($tr_num!='en')?tr_num($out):$out;
}
function jstrftime($format, $timestamp = '', $none = '', $time_zone = 'Asia/Tehran', $tr_num = 'fa')
{
$T_sec=0;/* <= آرشیو شود */
if($time_zone != 'local') date_default_timezone_set(($time_zone === '') ? 'Asia/Tehran' : $time_zone);
$ts=$T_sec+(($timestamp==='')?time():tr_num($timestamp));
$date=explode(' _ ',date('h_H_i_j_n_s_w_Y',$ts));
list($j_y,$j_m,$j_d)=gregorian_to_jalali($date[7],$date[4],$date[3]);
$doy=($j_m<7)?(($j_m-1)*31)+$j_d-1:(($j_m-7)*30)+$j_d+185;
$kab=(((($j_y%33)%4)-1)%4==0);
$sl=strlen($format);
$out='';
for($i=0; $i<$sl; $i++)
{
$sub=substr($format,$i,1);
if($sub=='%')
{
$sub=substr($format,++$i,1);
}
else
{
$out.=$sub;
continue;
}
switch($sub)
{
case 'a':$out.=jdate_words(array('rh'=>$date[6]),' ');break;
case 'A':$out.=jdate_words(array('RL'=>$date[6]),' ');break;
case 'b':$out.=jdate_words(array('mm'=>$j_m),' ');break;
case 'B':$out.=jdate_words(array('MM'=>$j_m),' ');break;
case 'c':$out.=jdate('D M j H:i:s Y');break;
case 'C':$out.=(int)($j_y/100);break;
case 'd':$out.=($j_d<10)?'0'.$j_d:$j_d;break;
case 'D':$out.=substr($j_y,2,2).'/' .( ($j_m<10)?'0'.$j_m:$j_m ).'/' .( ($j_d<10)?'0'.$j_d:$j_d );break;
case 'e':$out.=($j_d<10)?' '.$j_d:$j_d;break;
case 'H':$out.=($date[1]<10)?'0'.$date[1]:$date[1];break;
case 'I':$out.=($date[0]<10)?'0'.$date[0]:$date[0];break;
case 'j':$out.=($doy<100)?(($doy<10)?'00'.$doy:'0'.$doy):$doy;break;
case 'm':$out.=($j_m<10)?'0'.$j_m:$j_m;break;
case 'M':$out.=($date[2]<10)?'0'.$date[2]:$date[2];break;
case 'p':$out.=($date[1]<12)?'قبل از ظهر':'بعد از ظهر';break;
case 'P':$out.=($date[1]<12)?'ق.ظ':'ب.ظ';break;
case 's':$out.=floor($ts);break;
case 'S':$out.=($date[5]<10)?'0'.$date[5]:$date[5];break;
case 'u':$out.=$date[6]+1;break;
case 'U':$out.=(int)($doy/7);break;
case 'V':$out.=(int)($doy/7);break;
case 'w':$out.=$date[6];break;
case 'W':$out.=(int)($doy/7);break;
case 'x':$out.=substr($j_y,2,2).'/' .( ($j_m<10)?'0'.$j_m:$j_m ).'/' .( ($j_d<10)?'0'.$j_d:$j_d );break;
case 'X':$out.=($date[0]<10)?'0'.$date[0]:$date[0].':' .( ($date[1]<10)?'0'.$date[1]:$date[1] ).':' .( ($date[6]<10)?'0'.$date[6]:$date[6] );break;
case 'y':$out.=substr($j_y,2,2);break;
case 'Y':$out.=$j_y;break;
case 'Z':$out.=date('T',$ts);break;
case '%':$out.='%';break;
default:$out.=$sub;
}
}
return ($tr_num!='en')?tr_num($out):$out;
}
function gregorian_to_jalali($gy,$gm,$gd,$mod='')
{
$g_d_m=array(0,31,59,90,120,151,181,212,243,273,304,334);
$gy2=($gm>2)?($gy+1):$gy;
$days=355666+(365*$gy)+((int)(($gy2+3)/4))-((int)(($gy2+99)/100))+((int)(($gy2+399)/400))+$gd+$g_d_m[$gm-1];
$jy=-1595+(33*((int)($days/12053)));
$days%=12053;
$jy+=4*((int)($days/1461));
$days%=1461;
if($days > 365)
{
$jy+=(int)(($days-1)/365);
$days=($days-1)%365;
}
$jm=($days<186)?1+(int)($days/31):7+(int)(($days-186)/30);
$jd=1+(($days<186)?($days%31):(($days-186)%30));
return($mod=='')?array($jy,$jm,$jd):$jy.$mod.$jm.$mod.$jd;
}
function jalali_to_gregorian($jy,$jm,$jd,$mod='')
{
$jy+=1595;
$days=-355668+(365*$jy)+(((int)($jy/33))*8)+((int)((($jy%33)+3)/4));
if((($jy%33)%4)==0 and $gy%100!=0 and $gy%400!=0){$days++;}
$jd+=($jm<7)?($jm-1)*31:(($jm-7)*30)+186;
$days+=$jd;
$gy=400*((int)($days/146097));
$days%=146097;
if($days > 36524)
{
$gy+=100*((int)(--$days/36524));
$days%=36524;
if($days >= 365){$days++;}
}
$gy+=4*((int)($days/1461));
$days%=1461;
$gy+=(int)(($days-1)/365);
$days=($days-1)%365;
$gd=$days+1;
foreach(array(0,31,(($gy%4==0 and $gy%100!=0) or ($gy%400==0))?29:28,31,30,31,30,31,31,30,31,30,31) as $gm=>$v)
{
if($gd<=$v)break;
$gd-=$v;
}
return($mod=='')?array($gy,$gm,$gd):$gy.$mod.$gm.$mod.$gd;
}
function jdate_words($array,$mod='')
{
foreach($array as $type=>$num)
{
$num=(int)tr_num($num);
switch($type)
{
case 'ss':
$sl=strlen($num);
$xy3=substr($num,2-$sl,1);
$h3=jdate_words(array('h'=>$xy3));
$h34=jdate_words(array('h'=>$xy3+1));
$xy4=substr($num,3-$sl,1);
$h4=jdate_words(array('h'=>$xy4));
$h44=jdate_words(array('h'=>$xy4+1));
if($sl==4)
{
$f=($num<2000)?(($num<1400 and $num>1299)?jdate_words(array('h'=>13)).'صد و '.jdate_words(array('ss'=>substr($num,2,2))):''):jdate_words(array('h'=>substr($num,0,1))).' هزار و '.jdate_words(array('ss'=>substr($num,1,3)));
}
elseif($sl==3)
{
$f=($num<200)?jdate_words(array('h'=>1)).'صد و '.jdate_words(array('ss'=>substr($num,1,2))):jdate_words(array('h'=>substr($num,0,1))).'صد و '.jdate_words(array('ss'=>substr($num,1,2)));
}
elseif($sl==2)
{
$f=($num>9 and $num<21)?jdate_words(array('h'=>$num)):
jdate_words(array('h'=>(int)($num/10))).' و '.jdate_words(array('h'=>$num%10));
}
else{$f=jdate_words(array('h'=>$num));}
break;
case 'mm':$key=array('فروردین','اردیبهشت','خرداد','تیر','مرداد','شهریور','مهر','آبان','آذر','دی','بهمن','اسفند');$f=$key[$num-1];break;
case 'mn':$key=array('فرو','ارد','خرد','تیر','مرد','شهر','مهر','آبا','آذر','دی','بهم','اسف');$f=$key[$num-1];break;
case 'rh':$key=array('یکشنبه','دوشنبه','سه شنبه','چهارشنبه','پنجشنبه','جمعه','شنبه');$f=$key[$num];break;
case 'RL':$key=array('یک','دو','سه','چهار','پنج','جمعه','شنبه');$f=$key[$num];break;
case 'sh':$key=array('مار','اسب','گوسفند','میمون','مرغ','سگ','خوک','موش','گاو','پلنگ','خرگوش','نهنگ');$f=$key[$num%12];break;
case 'mb':$key=array('حمل','ثور','جوزا','سرطان','اسد','سنبله','میزان','عقرب','قوس','جدی','دلو','حوت');$f=$key[$num-1];break;
case 'h':$key=array('صفر','یک','دو','سه','چهار','پنج','شش','هفت','هشت','نه','ده','یازده','دوازده','سیزده','چهارده','پانزده','شانزده','هفده','هجده','نوزده','بیست');$f=$key[$num];break;
}
}
return $f;
}
function tr_num($str,$mod='en',$mf='٫')
{
$num_a=array('0','1','2','3','4','5','6','7','8','9','.');
$key_a=array('۰','۱','۲','۳','۴','۵','۶','۷','۸','۹',$mf);
return($mod=='fa')?str_replace($num_a,$key_a,$str):str_replace($key_a,$num_a,$str);
} }
?> ?>

187
index.php
View File

@ -1,97 +1,118 @@
<?php <?php
// DEBUG: Show session data right at the start
echo '<div style="background-color: #ffc; padding: 10px; border: 1px solid #e2a000; margin-bottom: 20px;">';
echo '<strong>Debug Info (index.php):</strong><br>';
echo '<pre>';
print_r($_SESSION);
echo '</pre>';
echo '</div>';
$page_title = 'صفحه اصلی'; $page_title = 'صفحه اصلی';
include 'includes/header.php'; include 'includes/header.php';
// Load dynamic content
$about_us_image_data = json_decode(file_get_contents('about_us_image.json'), true);
$about_us_image_url = $about_us_image_data ? str_replace('\\/', '/', $about_us_image_data['local_path']) : 'assets/images/pexels/about-us-34942790.jpg';
require_once 'db/config.php';
?> ?>
<!-- Hero Section --> <!-- Hero Section -->
<section class="hero-section vh-100 d-flex align-items-center" style="background: #111;"> <section class="hero-section vh-100 d-flex align-items-center">
<div class="video-background-wrapper"> <div class="video-background-wrapper">
<div class="video-overlay"></div> <div class="video-overlay"></div>
<video playsinline="playsinline" autoplay="autoplay" muted="muted" loop="loop" style="opacity: 0.5;"> <video playsinline="playsinline" autoplay="autoplay" muted="muted" loop="loop">
<source src="https://static.pexels.com/lib/videos/free-videos.mp4" type="video/mp4"> <source src="https://static.pexels.com/lib/videos/free-videos.mp4" type="video/mp4">
</video> </video>
</div> </div>
<div class="container position-relative"> <div class="container position-relative text-center">
<h1 class="display-3 fw-bold mb-3 hero-title" data-aos="zoom-in-out" data-aos-delay="100">اصالت در هر نگاه</h1> <h1 class="display-3 hero-title" data-aos="zoom-in-out" data-aos-delay="100">اصالت در هر نگاه</h1>
<p class="lead fs-4 mb-4 hero-subtitle" data-aos="fade-left" data-aos-delay="300">محصولات چرمی دست‌دوز، آفریده برای ماندگاری.</p> <p class="lead fs-4 mb-4 hero-subtitle" data-aos="fade-up" data-aos-delay="300">محصولات چرمی دست‌دوز، آفریده برای ماندگاری.</p>
<a href="shop.php" class="btn btn-primary btn-lg" data-aos="fade-up" data-aos-delay="500">کاوش در مجموعه</a> <a href="shop.php" class="btn btn-primary btn-lg" data-aos="fade-up" data-aos-delay="500">کاوش در مجموعه</a>
</div> </div>
</section> </section>
<!-- Featured Products Section --> <!-- Featured Products Section -->
<section id="featured-products" class="py-5"> <section id="featured-products" class="py-5">
<div class="container"> <div class="container">
<?php <?php
if (isset($_SESSION['success_message'])) { if (isset($_SESSION['success_message'])) {
echo '<div class="alert alert-success alert-dismissible fade show" role="alert">' . $_SESSION['success_message'] . '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>'; echo '<div class="alert alert-success alert-dismissible fade show" role="alert">' . $_SESSION['success_message'] . '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>';
unset($_SESSION['success_message']); unset($_SESSION['success_message']);
} }
if (isset($_SESSION['error_message'])) { if (isset($_SESSION['error_message'])) {
echo '<div class="alert alert-danger alert-dismissible fade show" role="alert">' . $_SESSION['error_message'] . '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>'; echo '<div class="alert alert-danger alert-dismissible fade show" role="alert">' . $_SESSION['error_message'] . '<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button></div>';
unset($_SESSION['error_message']); unset($_SESSION['error_message']);
} }
?> ?>
<div class="text-center mb-5" data-aos="fade-up"> <div class="section-title text-center mb-5" data-aos="fade-up">
<h2 class="display-5 fw-bold">مجموعه برگزیده ما</h2> <h1>مجموعه برگزیده ما</h1>
<p class="fs-5">دست‌چین شده برای سلیقه‌های خاص.</p> <p class="fs-5 text-muted">دست‌چین شده برای سلیقه‌های خاص.</p>
</div>
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4 g-lg-5">
<?php
try {
$pdo = db();
$stmt = $pdo->query("SELECT * FROM products WHERE is_featured = 1 ORDER BY created_at DESC LIMIT 3");
$featured_products = $stmt->fetchAll(PDO::FETCH_ASSOC);
if (empty($featured_products)) {
echo '<div class="col-12"><p class="text-center text-muted">هیچ محصولی برای نمایش وجود ندارد.</p></div>';
} else {
$delay = 0;
foreach ($featured_products as $product) {
?>
<div class="col" data-aos="fade-up" data-aos-delay="<?= $delay ?>">
<div class="product-card h-100">
<div class="product-image">
<a href="product.php?id=<?= $product['id'] ?>">
<img src="<?= htmlspecialchars($product['image_url']) ?>" alt="<?= htmlspecialchars($product['name']) ?>">
</a>
</div>
<div class="product-info text-center">
<h3 class="product-title"><a href="product.php?id=<?= $product['id'] ?>"><?= htmlspecialchars($product['name']) ?></a></h3>
<p class="product-price"><?= number_format($product['price']) ?> تومان</p>
</div>
</div> </div>
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4 g-lg-5"> </div>
<?php <?php
require_once 'db/config.php'; $delay += 150;
try {
$pdo = db();
$stmt = $pdo->query("SELECT * FROM products WHERE is_featured = 1 ORDER BY created_at DESC LIMIT 3");
$featured_products = $stmt->fetchAll(PDO::FETCH_ASSOC);
$animations = ['fade-up', 'zoom-in-up', 'fade-left'];
if (empty($featured_products)) {
echo '<div class="col-12"><p class="text-center text-white-50">هیچ محصولی برای نمایش وجود ندارد.</p></div>';
} else {
$delay = 0;
foreach ($featured_products as $key => $product) {
echo '<div class="col" data-aos="fade-up" data-aos-delay="' . $delay . '">';
echo ' <div class="product-card h-100">';
echo ' <div class="product-image">';
echo ' <a href="product.php?id=' . $product['id'] . '">';
echo ' <img src="' . htmlspecialchars($product['image_url']) . '" class="img-fluid" alt="' . htmlspecialchars($product['name']) . '">';
echo ' </a>';
echo ' </div>';
echo ' <div class="product-info text-center">';
echo ' <h3 class="product-title"><a href="product.php?id=' . $product['id'] . '" class="text-decoration-none">' . htmlspecialchars($product['name']) . '</a></h3>';
echo ' <p class="product-price">' . number_format($product['price']) . ' تومان</p>';
echo ' </div>';
echo ' </div>';
echo '</div>';
$delay += 150;
}
}
} catch (PDOException $e) {
error_log("Database error: " . $e->getMessage());
echo '<div class="col-12"><p class="text-center text-danger">خطا در بارگذاری محصولات.</p></div>';
} }
?> }
</div> } catch (PDOException $e) {
<div class="text-center mt-5" data-aos="fade-up"> error_log("Database error: " . $e->getMessage());
<a href="shop.php" class="btn btn-outline-gold btn-lg">مشاهده تمام محصولات</a> echo '<div class="col-12"><p class="text-center text-danger">خطا در بارگذاری محصولات.</p></div>';
</div> }
</div> ?>
</section> </div>
<!-- About Us Section --> <div class="text-center mt-5" data-aos="fade-up">
<section id="about-us" class="py-5"> <a href="shop.php" class="btn btn-primary">مشاهده تمام محصولات</a>
<div class="container"> </div>
<div class="row align-items-center"> </div>
<div class="col-md-6" data-aos="fade-right"> </section>
<img src="assets/images/pexels/about-us-34942790.jpg" alt="درباره ما" class="img-fluid rounded-4 shadow-lg">
</div> <!-- About Us Section -->
<div class="col-md-6 mt-4 mt-md-0 ps-md-5" data-aos="fade-left"> <section id="about-us" class="py-5">
<h2 class="display-5 fw-bold">داستان آتیمه</h2> <div class="container">
<p class="text-muted fs-5 mt-3">ما در آتیمه، به تلفیق هنر سنتی و طراحی مدرن باور داریم. هر محصول، حاصل ساعت‌ها کار دست هنرمندان ماهر و استفاده از بهترین چرم‌های طبیعی است. هدف ما خلق آثاری است که نه تنها یک وسیله، بلکه بخشی از داستان و استایل شما باشند.</p> <div class="row align-items-center g-5">
<a href="#" class="btn btn-primary mt-3" data-aos="fade-up" data-aos-delay="200">بیشتر بدانید</a> <div class="col-md-6" data-aos="fade-right">
</div> <img src="<?= htmlspecialchars($about_us_image_url) ?>" alt="درباره ما" class="about-us-image img-fluid">
</div>
<div class="col-md-6" data-aos="fade-left">
<div class="section-title text-md-end text-center">
<h1>داستان آتیمه</h1>
</div>
<p class="text-muted fs-5 mt-3 text-md-end text-center">ما در آتیمه، به تلفیق هنر سنتی و طراحی مدرن باور داریم. هر محصول، حاصل ساعت‌ها کار دست هنرمندان ماهر و استفاده از بهترین چرم‌های طبیعی است. هدف ما خلق آثاری است که نه تنها یک وسیله، بلکه بخشی از داستان و استایل شما باشند.</p>
<div class="text-md-end text-center">
<a href="about.php" class="btn btn-primary mt-3" data-aos="fade-up" data-aos-delay="200">بیشتر بدانید</a>
</div> </div>
</div> </div>
</section> </div>
</div>
</section>
<?php include 'includes/footer.php'; ?> <?php include 'includes/footer.php'; ?>

View File

@ -14,17 +14,15 @@ $page_title = "ورود یا ثبت‌نام";
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $page_title; ?> - آتیمه</title> <title><?= $page_title; ?> - آتیمه</title>
<!-- Bootstrap CSS --> <!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet">
<!-- Vazirmatn Font --> <!-- Remixicon -->
<link href="https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css" rel="stylesheet" type="text/css" /> <link href="https://cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.css" rel="stylesheet" />
<!-- Main Custom CSS (for variables) --> <!-- Main Custom CSS (for variables) -->
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>"> <link rel="stylesheet" href="assets/css/dark_luxury.css?v=<?= time(); ?>">
<!-- Custom Auth CSS -->
<link rel="stylesheet" href="assets/css/auth_style.css?v=<?php echo time(); ?>">
</head> </head>
<body> <body class="dark-luxury">
<div class="auth-wrapper"> <div class="auth-wrapper">
<!-- Left Side: Background Image and Branding --> <!-- Left Side: Background Image and Branding -->
@ -38,14 +36,15 @@ $page_title = "ورود یا ثبت‌نام";
<!-- Right Side: Form --> <!-- Right Side: Form -->
<div class="auth-form-wrapper"> <div class="auth-form-wrapper">
<div class="auth-form-container"> <div class="auth-form-container">
<div class="form-header text-center"> <div class="form-header">
<div class="logo">آتیمه</div>
<h2>ورود یا ثبت‌نام</h2> <h2>ورود یا ثبت‌نام</h2>
<p>برای دریافت کد یکبار مصرف، ایمیل خود را وارد کنید.</p> <p>برای دریافت کد یکبار مصرف، ایمیل خود را وارد کنید.</p>
</div> </div>
<?php if(isset($_SESSION['flash_message'])): ?> <?php if(isset($_SESSION['flash_message'])): ?>
<div class="alert alert-<?php echo $_SESSION['flash_message']['type']; ?> alert-dismissible fade show" role="alert"> <div class="alert alert-<?= htmlspecialchars($_SESSION['flash_message']['type']); ?> alert-dismissible fade show" role="alert">
<?php echo htmlspecialchars($_SESSION['flash_message']['message']); ?> <?= htmlspecialchars($_SESSION['flash_message']['message']); ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div> </div>
<?php unset($_SESSION['flash_message']); ?> <?php unset($_SESSION['flash_message']); ?>
@ -62,17 +61,8 @@ $page_title = "ورود یا ثبت‌نام";
</div> </div>
</form> </form>
<div class="separator my-4"><span>یا</span></div>
<div class="d-grid">
<a href="auth_handler.php?action=google_login" class="btn btn-google">
<svg class="me-2" xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 48 48"><path fill="#EA4335" d="M24 9.5c3.54 0 6.71 1.22 9.21 3.6l6.85-6.85C35.9 2.38 30.47 0 24 0 14.62 0 6.51 5.38 2.56 13.22l7.98 6.19C12.43 13.72 17.74 9.5 24 9.5z"/><path fill="#4285F4" d="M46.98 24.55c0-1.57-.15-3.09-.38-4.55H24v9.02h12.94c-.58 2.96-2.26 5.48-4.78 7.18l7.73 6c4.51-4.18 7.09-10.36 7.09-17.65z"/><path fill="#FBBC05" d="M10.53 28.59c-.48-1.45-.76-2.99-.76-4.59s.27-3.14.76-4.59l-7.98-6.19C.92 16.46 0 20.12 0 24c0 3.88.92 7.54 2.56 10.78l7.97-6.19z"/><path fill="#34A853" d="M24 48c6.48 0 11.93-2.13 15.89-5.81l-7.73-6c-2.15 1.45-4.92 2.3-8.16 2.3-6.26 0-11.57-4.22-13.47-9.91l-7.98 6.19C6.51 42.62 14.62 48 24 48z"/><path fill="none" d="M0 0h48v48H0z"/></svg>
ورود با گوگل
</a>
</div>
<div class="auth-footer"> <div class="auth-footer">
<p><a href="index.php">بازگشت به صفحه اصلی</a></p> <p><a href="index.php"><i class="ri-arrow-right-line"></i> بازگشت به صفحه اصلی</a></p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -50,18 +50,18 @@ if (!empty($product['colors'])) {
<div class="row g-5"> <div class="row g-5">
<div class="col-lg-6" data-aos="fade-right"> <div class="col-lg-6" data-aos="fade-right">
<div class="product-image-gallery"> <div class="product-image-gallery">
<img src="<?php echo htmlspecialchars($product['image_url']); ?>" class="img-fluid rounded-4 shadow-lg" alt="<?php echo htmlspecialchars($product['name']); ?>"> <img src="<?php echo htmlspecialchars($product['image_url']); ?>" class="img-fluid" alt="<?php echo htmlspecialchars($product['name']); ?>">
</div> </div>
</div> </div>
<div class="col-lg-6" data-aos="fade-left"> <div class="col-lg-6 product-details" data-aos="fade-left">
<h1 class="display-5 fw-bold mb-3"><?php echo htmlspecialchars($product['name']); ?></h1> <h1 class="display-5 fw-bold mb-3"><?php echo htmlspecialchars($product['name']); ?></h1>
<div class="d-flex align-items-center mb-4"> <div class="d-flex align-items-center mb-4">
<p class="display-6 text-primary fw-bold m-0"><?php echo number_format($product['price']); ?> تومان</p> <p class="display-6 fw-bold m-0"><?php echo number_format($product['price']); ?> تومان</p>
</div> </div>
<p class="fs-5 mb-4"><?php echo nl2br(htmlspecialchars($product['description'])); ?></p> <p class="fs-5 mb-4 text-muted"><?php echo nl2br(htmlspecialchars($product['description'])); ?></p>
<form action="cart_handler.php" method="POST"> <form action="cart_handler.php" method="POST">
<input type="hidden" name="product_id" value="<?php echo $product['id']; ?>"> <input type="hidden" name="product_id" value="<?php echo $product['id']; ?>">
@ -72,22 +72,22 @@ if (!empty($product['colors'])) {
<h5 class="mb-3">انتخاب رنگ:</h5> <h5 class="mb-3">انتخاب رنگ:</h5>
<div class="color-swatches"> <div class="color-swatches">
<?php foreach ($available_colors as $index => $color_hex): ?> <?php foreach ($available_colors as $index => $color_hex): ?>
<input type="radio" class="btn-check" name="product_color" id="color_<?php echo $index; ?>" value="<?php echo htmlspecialchars($color_hex); ?>" <?php echo (count($available_colors) === 1) ? 'checked' : ''; ?>> <input type="radio" class="btn-check" name="product_color" id="color_<?php echo $index; ?>" value="<?php echo htmlspecialchars($color_hex); ?>" autocomplete="off" <?php echo (count($available_colors) === 1) ? 'checked' : ''; ?>/>
<label class="btn" for="color_<?php echo $index; ?>" style="background-color: <?php echo htmlspecialchars($color_hex); ?>;" title="<?php echo htmlspecialchars($color_hex); ?>"></label> <label class="btn" for="color_<?php echo $index; ?>" style="background-color: <?php echo htmlspecialchars($color_hex); ?>;"></label>
<?php endforeach; ?> <?php endforeach; ?>
</div> </div>
</div> </div>
<?php endif; ?> <?php endif; ?>
<div class="row align-items-center mb-4"> <div class="row align-items-center mb-4">
<div class="col-md-5 col-lg-4"> <div class="col-md-5 col-lg-4 quantity-input-wrapper">
<label for="quantity" class="form-label fw-bold">تعداد:</label> <label for="quantity" class="form-label fw-bold">تعداد:</label>
<input type="number" name="quantity" id="quantity" class="form-control form-control-lg bg-dark text-center" value="1" min="1" max="10"> <input type="number" name="quantity" id="quantity" class="form-control quantity-input text-center" value="1" min="1" max="10">
</div> </div>
</div> </div>
<div class="d-grid gap-2"> <div class="d-grid gap-2 add-to-cart-btn">
<button type="submit" class="btn btn-primary btn-lg"><i class="fas fa-shopping-cart me-2"></i> افزودن به سبد خرید</button> <button type="submit" class="btn btn-primary"><i class="ri-shopping-bag-add-line"></i> افزودن به سبد خرید</button>
</div> </div>
</form> </form>
@ -105,16 +105,17 @@ document.addEventListener('DOMContentLoaded', function() {
$flash_message = $_SESSION['flash_message']; $flash_message = $_SESSION['flash_message'];
unset($_SESSION['flash_message']); unset($_SESSION['flash_message']);
echo "Swal.fire({ echo "Swal.fire({
title: '" . addslashes($flash_message['message']) . "', title: '".addslashes($flash_message['message'])."',
icon: '" . $flash_message['type'] . "', icon: '". $flash_message['type'] ."',
toast: true, toast: true,
position: 'top-start', position: 'top-start',
showConfirmButton: false, showConfirmButton: false,
timer: 4000, timer: 4000,
timerProgressBar: true, timerProgressBar: true,
showCloseButton: true,
didOpen: (toast) => { didOpen: (toast) => {
toast.onmouseenter = Swal.stopTimer; toast.addEventListener('mouseenter', Swal.stopTimer);
toast.onmouseleave = Swal.resumeTimer; toast.addEventListener('mouseleave', Swal.resumeTimer);
}, },
customClass: { customClass: {
popup: 'dark-theme-toast' popup: 'dark-theme-toast'
@ -152,46 +153,5 @@ document.addEventListener('DOMContentLoaded', function() {
} }
}); });
</script> </script>
<style>
body.swal2-shown > [aria-hidden="true"] {
filter: blur(5px);
transition: filter 0.3s ease-out;
}
.swal2-popup.dark-theme-popup {
background-color: #2a2a2e !important;
border-radius: 20px;
}
.swal2-title.dark-theme-title {
color: #e8e6e3 !important;
}
.swal2-html-container.dark-theme-content {
color: #b0b0b0 !important;
}
.swal2-confirm.dark-theme-button {
background-color: var(--primary-color) !important;
border-radius: 10px;
padding: .6em 2em;
box-shadow: none !important;
transition: background-color 0.2s;
}
.swal2-confirm.dark-theme-button:hover {
background-color: #c89c6c !important; /* A slightly lighter shade of primary for hover */
}
/* Toast Styles */
.swal2-toast.dark-theme-toast {
background-color: #2a2a2e !important;
color: #e8e6e3 !important;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0,0,0,0.2);
}
.swal2-toast.dark-theme-toast .swal2-title {
color: #e8e6e3 !important;
font-size: 1em;
}
.swal2-toast.dark-theme-toast .swal2-timer-progress-bar {
background-color: var(--primary-color);
}
</style>
<?php require_once 'includes/footer.php'; ?> <?php require_once 'includes/footer.php'; ?>

View File

@ -1,8 +1,10 @@
<?php <?php
session_start(); session_start();
require_once 'db/config.php'; require_once 'db/config.php';
require_once 'includes/jdf.php'; // For Jalali date conversion require_once 'includes/jdf.php'; // For Jalali date conversion
if (!isset($_SESSION['user_id'])) { if (!isset($_SESSION['user_id'])) {
header('Location: login.php'); header('Location: login.php');
exit; exit;
@ -11,6 +13,128 @@ if (!isset($_SESSION['user_id'])) {
$user_id = $_SESSION['user_id']; $user_id = $_SESSION['user_id'];
$pdo = db(); $pdo = db();
// Handle form submissions for account page
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if ($_POST['action'] === 'update_details') {
$first_name = trim($_POST['first_name'] ?? '');
$last_name = trim($_POST['last_name'] ?? '');
$email = trim($_POST['email'] ?? '');
if (empty($first_name) || empty($last_name) || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
$_SESSION['profile_message'] = 'لطفاً تمام فیلدها را به درستی پر کنید.';
$_SESSION['profile_message_type'] = 'danger';
} else {
try {
$stmt = $pdo->prepare("UPDATE users SET first_name = ?, last_name = ?, email = ? WHERE id = ?");
$stmt->execute([$first_name, $last_name, $email, $user_id]);
$_SESSION['profile_message'] = 'اطلاعات شما با موفقیت به‌روزرسانی شد.';
$_SESSION['profile_message_type'] = 'success';
} catch (PDOException $e) {
// Check for duplicate email error
if ($e->errorInfo[1] == 1062) {
$_SESSION['profile_message'] = 'این ایمیل قبلاً ثبت شده است. لطفاً ایمیل دیگری را امتحان کنید.';
} else {
$_SESSION['profile_message'] = 'خطا در به‌روزرسانی اطلاعات.';
}
$_SESSION['profile_message_type'] = 'danger';
}
}
header('Location: profile.php?page=account');
exit;
} elseif ($_POST['action'] === 'update_password') {
$new_password = $_POST['new_password'] ?? '';
$confirm_password = $_POST['confirm_password'] ?? '';
if (strlen($new_password) < 8) {
$_SESSION['profile_message'] = 'رمز عبور جدید باید حداقل ۸ کاراکتر باشد.';
$_SESSION['profile_message_type'] = 'danger';
} elseif ($new_password !== $confirm_password) {
$_SESSION['profile_message'] = 'رمزهای عبور جدید با هم مطابقت ندارند.';
$_SESSION['profile_message_type'] = 'danger';
} elseif (!empty($new_password)) {
$hashed_password = password_hash($new_password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare("UPDATE users SET password = ? WHERE id = ?");
if ($stmt->execute([$hashed_password, $user_id])) {
$_SESSION['profile_message'] = 'رمز عبور شما با موفقیت تغییر کرد.';
$_SESSION['profile_message_type'] = 'success';
} else {
$_SESSION['profile_message'] = 'خطا در تغییر رمز عبور.';
$_SESSION['profile_message_type'] = 'danger';
}
}
header('Location: profile.php?page=account');
exit;
} elseif ($_POST['action'] === 'add_address') {
$province = trim($_POST['province'] ?? '');
$city = trim($_POST['city'] ?? '');
$address_line = trim($_POST['address_line'] ?? '');
$postal_code = trim($_POST['postal_code'] ?? '');
$is_default = isset($_POST['is_default']);
if (empty($province) || empty($city) || empty($address_line) || empty($postal_code)) {
$_SESSION['profile_message'] = 'لطفاً تمام فیلدهای آدرس را پر کنید.';
$_SESSION['profile_message_type'] = 'danger';
} else {
$pdo->beginTransaction();
try {
if ($is_default) {
$stmt = $pdo->prepare("UPDATE user_addresses SET is_default = 0 WHERE user_id = ?");
$stmt->execute([$user_id]);
}
$stmt = $pdo->prepare("INSERT INTO user_addresses (user_id, province, city, address_line, postal_code, is_default) VALUES (?, ?, ?, ?, ?, ?)");
$stmt->execute([$user_id, $province, $city, $address_line, $postal_code, $is_default ? 1 : 0]);
$pdo->commit();
$_SESSION['profile_message'] = 'آدرس جدید با موفقیت اضافه شد.';
$_SESSION['profile_message_type'] = 'success';
} catch (PDOException $e) {
$pdo->rollBack();
$_SESSION['profile_message'] = 'خطا در افزودن آدرس.';
$_SESSION['profile_message_type'] = 'danger';
}
}
header('Location: profile.php?page=addresses');
exit;
} elseif ($_POST['action'] === 'delete_address') {
$address_id = $_POST['address_id'] ?? 0;
$stmt = $pdo->prepare("DELETE FROM user_addresses WHERE id = ? AND user_id = ?");
if ($stmt->execute([$address_id, $user_id])) {
$_SESSION['profile_message'] = 'آدرس با موفقیت حذف شد.';
$_SESSION['profile_message_type'] = 'success';
} else {
$_SESSION['profile_message'] = 'خطا در حذف آدرس.';
$_SESSION['profile_message_type'] = 'danger';
}
header('Location: profile.php?page=addresses');
exit;
} elseif ($_POST['action'] === 'set_default_address') {
$address_id = $_POST['address_id'] ?? 0;
$pdo->beginTransaction();
try {
$stmt1 = $pdo->prepare("UPDATE user_addresses SET is_default = 0 WHERE user_id = ?");
$stmt1->execute([$user_id]);
$stmt2 = $pdo->prepare("UPDATE user_addresses SET is_default = 1 WHERE id = ? AND user_id = ?");
$stmt2->execute([$address_id, $user_id]);
$pdo->commit();
$_SESSION['profile_message'] = 'آدرس پیش‌فرض با موفقیت تغییر کرد.';
$_SESSION['profile_message_type'] = 'success';
} catch (PDOException $e) {
$pdo->rollBack();
$_SESSION['profile_message'] = 'خطا در تغییر آدرس پیش‌فرض.';
$_SESSION['profile_message_type'] = 'danger';
}
header('Location: profile.php?page=addresses');
exit;
}
}
// Retrieve flash message
if (isset($_SESSION['profile_message'])) {
$flash_message = $_SESSION['profile_message'];
$flash_message_type = $_SESSION['profile_message_type'];
unset($_SESSION['profile_message']);
unset($_SESSION['profile_message_type']);
}
// Fetch user data // Fetch user data
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); $stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
$stmt->execute([$user_id]); $stmt->execute([$user_id]);
@ -26,177 +150,59 @@ $stmt_orders = $pdo->prepare("SELECT * FROM orders WHERE user_id = ? ORDER BY cr
$stmt_orders->execute([$user_id]); $stmt_orders->execute([$user_id]);
$orders = $stmt_orders->fetchAll(PDO::FETCH_ASSOC); $orders = $stmt_orders->fetchAll(PDO::FETCH_ASSOC);
// Calculate total purchase amount from COMPLETED orders
$total_purchase_amount = 0;
foreach ($orders as $order) {
if (strtolower($order['status']) === 'completed') {
$total_purchase_amount += $order['total_amount'];
}
}
$page_title = 'حساب کاربری'; $page_title = 'حساب کاربری';
require_once 'includes/header.php'; require_once 'includes/header.php';
?> ?>
<style> <?php
body { // Simple router to determine the current page
background-color: #f4f7f6; $page = $_GET['page'] ?? 'dashboard';
} ?>
.profile-container {
display: flex;
gap: 30px;
}
.profile-sidebar {
flex: 0 0 280px;
background-color: #fff;
border-radius: 15px;
box-shadow: 0 4px 25px rgba(0,0,0,0.05);
padding: 20px;
align-self: flex-start;
}
.profile-content {
flex: 1;
}
.user-card {
text-align: center;
padding: 20px 10px;
border-bottom: 1px solid #eee;
margin-bottom: 20px;
}
.user-card .user-avatar {
width: 90px;
height: 90px;
border-radius: 50%;
background-color: var(--bs-primary);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 2.5rem;
margin: 0 auto 15px auto;
font-weight: bold;
}
.user-card h5 {
font-weight: 600;
margin-bottom: 5px;
}
.user-card p {
color: #888;
font-size: 0.9rem;
}
.profile-nav .nav-link {
display: flex;
align-items: center;
gap: 12px;
padding: 12px 15px;
border-radius: 10px;
color: #555;
font-weight: 500;
transition: all 0.3s ease;
margin-bottom: 5px;
}
.profile-nav .nav-link i {
font-size: 1.3rem;
color: #888;
transition: all 0.3s ease;
}
.profile-nav .nav-link.active,
.profile-nav .nav-link:hover {
background-color: var(--bs-primary-light);
color: var(--bs-primary);
}
.profile-nav .nav-link.active i,
.profile-nav .nav-link:hover i {
color: var(--bs-primary);
}
.tab-pane h3 {
font-weight: 700;
margin-bottom: 25px;
color: #333;
}
/* Order Accordion Styles */
.order-accordion .accordion-item {
border: none;
border-radius: 15px;
margin-bottom: 20px;
box-shadow: 0 4px 25px rgba(0,0,0,0.05);
background-color: #fff;
}
.order-accordion .accordion-button {
border-radius: 15px !important;
background-color: #fff;
box-shadow: none;
padding: 20px;
}
.order-accordion .accordion-button:not(.collapsed) {
border-bottom: 1px solid #eee;
}
.order-header {
display: flex;
justify-content: space-between;
width: 100%;
align-items: center;
}
.order-header-item {
flex: 1;
text-align: right;
font-size: 0.9rem;
}
.order-header-item:first-child { text-align: right; }
.order-header-item span {
display: block;
font-size: 0.8rem;
color: #888;
}
.order-header-item strong {
font-weight: 600;
color: #333;
font-size: 1rem;
}
.order-status {
padding: 5px 12px;
border-radius: 20px;
font-weight: 500;
color: #fff;
font-size: 0.8rem;
}
.order-details-table {
margin-top: 15px;
}
.order-details-table img {
width: 60px;
height: 60px;
object-fit: cover;
border-radius: 10px;
}
.product-color-swatch {
display: inline-block;
width: 20px;
height: 20px;
border-radius: 50%;
border: 1px solid #eee;
vertical-align: middle;
}
</style>
<div class="container my-5"> <div class="container my-5">
<div class="profile-container"> <div class="profile-container">
<!-- Profile Sidebar --> <!-- Profile Sidebar -->
<div class="profile-sidebar"> <aside class="profile-sidebar">
<div class="user-card"> <div class="user-card">
<div class="user-avatar"> <div class="user-avatar">
<?php echo strtoupper(substr($user['first_name'], 0, 1)); ?> <i class="ri-user-fill"></i>
</div> </div>
<h5><?php echo htmlspecialchars($user['first_name'] . ' ' . $user['last_name']); ?></h5> <h5><?= htmlspecialchars(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? '')); ?></h5>
<p><?php echo htmlspecialchars($user['email']); ?></p> <p><?= htmlspecialchars($user['email'] ?? ''); ?></p>
</div> </div>
<ul class="nav flex-column profile-nav" id="profileTab" role="tablist"> <ul class="nav flex-column profile-nav">
<li class="nav-item"> <li class="nav-item">
<a class="nav-link active" id="orders-tab" data-bs-toggle="tab" href="#orders" role="tab" aria-controls="orders" aria-selected="true"> <a class="nav-link <?= ($page === 'dashboard') ? 'active' : '' ?>" href="profile.php?page=dashboard">
<i class="ri-dashboard-line"></i>
داشبورد
</a>
</li>
<li class="nav-item">
<a class="nav-link <?= ($page === 'orders') ? 'active' : '' ?>" href="profile.php?page=orders">
<i class="ri-shopping-bag-3-line"></i> <i class="ri-shopping-bag-3-line"></i>
سفارشات من سفارشات من
</a> </a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" id="addresses-tab" data-bs-toggle="tab" href="#addresses" role="tab" aria-controls="addresses" aria-selected="false"> <a class="nav-link <?= ($page === 'addresses') ? 'active' : '' ?>" href="profile.php?page=addresses">
<i class="ri-map-pin-line"></i> <i class="ri-map-pin-line"></i>
آدرس‌های من آدرس‌های من
</a> </a>
</li>
<li class="nav-item">
<a class="nav-link <?= ($page === 'account') ? 'active' : '' ?>" href="profile.php?page=account">
<i class="ri-user-line"></i>
جزئیات حساب
</a>
</li> </li>
<li class="nav-item"> <li class="nav-item">
<a class="nav-link" href="logout.php"> <a class="nav-link" href="logout.php">
@ -205,101 +211,322 @@ require_once 'includes/header.php';
</a> </a>
</li> </li>
</ul> </ul>
</div> </aside>
<!-- Profile Content --> <!-- Profile Content -->
<div class="profile-content"> <main class="profile-content">
<div class="tab-content" id="profileTabContent"> <?php if (isset($flash_message)): ?>
<!-- Orders Tab --> <div class="alert alert-<?= $flash_message_type; ?> alert-dismissible fade show" role="alert">
<div class="tab-pane fade show active" id="orders" role="tabpanel" aria-labelledby="orders-tab"> <?= htmlspecialchars($flash_message); ?>
<h3>تاریخچه سفارشات</h3> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
<?php if (empty($orders)): ?> </div>
<div class="alert alert-light text-center">شما هنوز هیچ سفارشی ثبت نکرده‌اید.</div> <?php endif; ?>
<?php else: ?> <?php if ($page === 'dashboard'): ?>
<div class="accordion order-accordion" id="ordersAccordion"> <div class="dashboard-welcome">
<?php foreach ($orders as $index => $order): ?> <h3 class="dashboard-title">سلام، <?= htmlspecialchars($user['first_name'] ?? 'کاربر'); ?> عزیز!</h3>
<?php <p>به پنل کاربری خود در [نام فروشگاه] خوش آمدید. از اینجا می‌توانید آخرین سفارشات خود را مشاهده کرده، اطلاعات حساب خود را مدیریت کنید و آدرس‌های خود را به‌روزرسانی نمایید.</p>
$items = json_decode($order['items_json'], true); </div>
$status_map = [
'pending' => ['label' => 'در انتظار پرداخت', 'color' => '#ffc107'],
'processing' => ['label' => 'در حال پردازش', 'color' => '#0dcaf0'],
'shipped' => ['label' => 'ارسال شده', 'color' => '#0d6efd'],
'completed' => ['label' => 'تکمیل شده', 'color' => '#198754'],
'cancelled' => ['label' => 'لغو شده', 'color' => '#dc3545'],
];
$status_info = $status_map[$order['status']] ?? ['label' => htmlspecialchars($order['status']), 'color' => '#6c757d'];
?>
<div class="accordion-item">
<h2 class="accordion-header" id="heading<?php echo $order['id']; ?>">
<button class="accordion-button <?php echo $index > 0 ? 'collapsed' : ''; ?>" type="button" data-bs-toggle="collapse" data-bs-target="#collapse<?php echo $order['id']; ?>" aria-expanded="<?php echo $index === 0 ? 'true' : 'false'; ?>" aria-controls="collapse<?php echo $order['id']; ?>">
<div class="order-header">
<div class="order-header-item">
<span>شماره سفارش</span>
<strong>#<?php echo $order['id']; ?></strong>
</div>
<div class="order-header-item">
<span>تاریخ ثبت</span>
<strong><?php echo jdate('d F Y', strtotime($order['created_at'])); ?></strong>
</div>
<div class="order-header-item">
<span>مبلغ کل</span>
<strong><?php echo number_format($order['total_amount']); ?> تومان</strong>
</div>
<div class="order-header-item text-start">
<span class="order-status" style="background-color: <?php echo $status_info['color']; ?>;">
<?php echo $status_info['label']; ?>
</span>
</div>
</div>
</button>
</h2>
<div id="collapse<?php echo $order['id']; ?>" class="accordion-collapse collapse <?php echo $index === 0 ? 'show' : ''; ?>" aria-labelledby="heading<?php echo $order['id']; ?>" data-bs-parent="#ordersAccordion">
<div class="accordion-body">
<h6>جزئیات سفارش</h6>
<?php if (!empty($order['tracking_id'])): ?>
<p><strong>کد رهگیری:</strong> <?php echo htmlspecialchars($order['tracking_id']); ?></p>
<?php endif; ?>
<table class="table order-details-table"> <!-- Placeholder for summary cards -->
<tbody> <div class="row g-4">
<?php foreach ($items as $item): ?> <div class="col-md-6">
<tr> <div class="summary-card">
<td><img src="<?php echo htmlspecialchars($item['image_url']); ?>" alt="<?php echo htmlspecialchars($item['name']); ?>"></td> <i class="ri-shopping-cart-2-line"></i>
<td> <div class="summary-card-info">
<?php echo htmlspecialchars($item['name']); ?> <span>تعداد کل سفارشات</span>
<?php if (!empty($item['color'])): ?> <strong><?= count($orders); ?></strong>
<br> </div>
<small> </div>
رنگ: </div>
<span class="product-color-swatch" style="background-color: <?php echo htmlspecialchars($item['color']); ?>" title="<?php echo htmlspecialchars($item['color']); ?>"></span> <div class="col-md-6">
</small> <div class="summary-card">
<?php endif; ?> <i class="ri-wallet-3-line"></i>
</td> <div class="summary-card-info">
<td><?php echo $item['quantity']; ?> عدد</td> <span>مجموع خرید شما</span>
<td class="text-start"><?php echo number_format($item['price']); ?> تومان</td> <strong><?= number_format($total_purchase_amount); ?> تومان</strong>
</tr> </div>
<?php endforeach; ?> </div>
</tbody> </div>
</table> </div>
</div>
<?php elseif ($page === 'orders'): ?>
<div class="dashboard-card">
<h3 class="dashboard-card-header">تاریخچه سفارشات</h3>
<div class="dashboard-card-body">
<?php if (empty($orders)): ?>
<div class="alert alert-secondary text-center">شما هنوز هیچ سفارشی ثبت نکرده‌اید.</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-dark table-hover align-middle">
<thead>
<tr>
<th>شماره سفارش</th>
<th>تاریخ</th>
<th>وضعیت</th>
<th>مبلغ کل</th>
<th class="text-end">عملیات</th>
</tr>
</thead>
<tbody>
<?php foreach ($orders as $order): ?>
<?php
$status_map = [
'pending' => 'در انتظار پرداخت',
'processing' => 'در حال پردازش',
'shipped' => 'ارسال شده',
'completed' => 'تکمیل شده',
'cancelled' => 'لغو شده',
];
$order_status_lower = strtolower($order['status']);
$status_label = $status_map[$order_status_lower] ?? htmlspecialchars($order['status']);
$status_class = 'status-' . htmlspecialchars($order_status_lower);
?>
<tr>
<td><strong>#<?= $order['id']; ?></strong></td>
<td><?= jdate('d F Y', strtotime($order['created_at'])); ?></td>
<td><span class="order-status <?= $status_class; ?>"><?= $status_label; ?></span></td>
<td><?= number_format($order['total_amount']); ?> تومان</td>
<td class="text-end">
<button type="button" class="btn btn-sm btn-outline-primary view-order-btn" data-tracking-id="<?= htmlspecialchars($order['tracking_id']); ?>">نمایش جزئیات</button>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</div>
</div>
<?php elseif ($page === 'addresses'): ?>
<div class="dashboard-card">
<div class="dashboard-card-header d-flex justify-content-between align-items-center">
<h3 class="m-0">آدرس‌های من</h3>
<button class="btn btn-primary btn-sm" type="button" data-bs-toggle="collapse" data-bs-target="#add-address-form" aria-expanded="false" aria-controls="add-address-form">
<i class="ri-add-line me-1"></i> افزودن آدرس جدید
</button>
</div>
<div class="dashboard-card-body">
<div class="collapse" id="add-address-form">
<form method="POST" class="mb-4 p-3 border rounded">
<input type="hidden" name="action" value="add_address">
<div class="row">
<div class="col-md-4 mb-3">
<label for="add_province" class="form-label">استان</label>
<input type="text" class="form-control" id="add_province" name="province" required>
</div>
<div class="col-md-4 mb-3">
<label for="add_city" class="form-label">شهر</label>
<input type="text" class="form-control" id="add_city" name="city" required>
</div>
<div class="col-md-4 mb-3">
<label for="add_postal_code" class="form-label">کد پستی</label>
<input type="text" class="form-control" id="add_postal_code" name="postal_code" required>
</div> </div>
</div> </div>
<?php endforeach; ?> <div class="mb-3">
<label for="new_address" class="form-label">آدرس کامل</label>
<textarea class="form-control" id="new_address" name="address_line" rows="2" required placeholder="خیابان، کوچه، پلاک، واحد"></textarea>
</div>
<div class="form-check mb-3">
<input class="form-check-input" type="checkbox" name="is_default" id="is_default">
<label class="form-check-label" for="is_default">
انتخاب به عنوان آدرس پیش‌فرض
</label>
</div>
<button type="submit" class="btn btn-success">ذخیره آدرس</button>
</form>
</div> </div>
<?php endif; ?>
<?php if (empty($addresses)): ?>
<div class="alert alert-secondary text-center">شما هنوز هیچ آدرسی ثبت نکرده‌اید.</div>
<?php else: ?>
<div class="address-list">
<?php foreach ($addresses as $address): ?>
<div class="address-item">
<div class="address-content">
<p><?= htmlspecialchars(implode(', ', array_filter([$address['province'], $address['city'], $address['address_line'], $address['postal_code']]))) ?></p>
<?php if ($address['is_default']): ?>
<span class="badge bg-primary">پیش‌فرض</span>
<?php endif; ?>
</div>
<div class="address-actions">
<form method="POST" class="d-inline">
<input type="hidden" name="action" value="delete_address">
<input type="hidden" name="address_id" value="<?= $address['id']; ?>">
<button type="submit" class="btn btn-sm btn-outline-danger" onclick="return confirm('آیا از حذف این آدرس مطمئن هستید؟');">حذف</button>
</form>
<?php if (!$address['is_default']): ?>
<form method="POST" class="d-inline">
<input type="hidden" name="action" value="set_default_address">
<input type="hidden" name="address_id" value="<?= $address['id']; ?>">
<button type="submit" class="btn btn-sm btn-outline-secondary">انتخاب به عنوان پیش‌فرض</button>
</form>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
</div> </div>
<!-- Addresses Tab --> <?php elseif ($page === 'account'): ?>
<div class="tab-pane fade" id="addresses" role="tabpanel" aria-labelledby="addresses-tab"> <div class="dashboard-card">
<h3>آدرس‌های من</h3> <h3 class="dashboard-card-header">جزئیات حساب</h3>
<!-- Address management will be implemented here --> <div class="dashboard-card-body">
<form id="account-details-form" method="POST">
<input type="hidden" name="action" value="update_details">
<div class="row">
<div class="col-md-6 mb-3">
<label for="first_name" class="form-label">نام</label>
<input type="text" class="form-control" id="first_name" name="first_name" value="<?= htmlspecialchars($user['first_name'] ?? ''); ?>" required>
</div>
<div class="col-md-6 mb-3">
<label for="last_name" class="form-label">نام خانوادگی</label>
<input type="text" class="form-control" id="last_name" name="last_name" value="<?= htmlspecialchars($user['last_name'] ?? ''); ?>" required>
</div>
</div>
<div class="mb-3">
<label for="email" class="form-label">آدرس ایمیل</label>
<input type="email" class="form-control" id="email" name="email" value="<?= htmlspecialchars($user['email'] ?? ''); ?>" required>
</div>
<button type="submit" class="btn btn-primary">ذخیره تغییرات</button>
</form>
</div>
</div> </div>
</div>
<?php else: ?>
<div class="alert alert-danger">صفحه مورد نظر یافت نشد.</div>
<?php endif; ?>
</main>
</div>
</div>
<!-- The Modal for Order Details -->
<div id="order-modal" class="order-modal">
<div class="order-modal-content">
<span class="order-modal-close-btn">&times;</span>
<div id="modal-body">
<!-- Order details will be injected here by JavaScript -->
</div> </div>
</div> </div>
</div> </div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const modal = document.getElementById('order-modal');
const modalBody = document.getElementById('modal-body');
const closeBtn = document.querySelector('.order-modal-close-btn');
// Function to open modal and fetch order details
async function openOrderModal(trackingId) {
modalBody.innerHTML = `<div class="text-center p-5"><div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div></div>`;
modal.style.display = 'block';
try {
const response = await fetch('api/get_order_details.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ tracking_id: trackingId }),
});
if (!response.ok) throw new Error(`Server error: ${response.status}`);
const data = await response.json();
if (data.success) {
displayOrderDetails(data.order, data.products);
} else {
modalBody.innerHTML = `<div class="alert alert-danger">${data.message}</div>`;
}
} catch (error) {
console.error('Fetch Error:', error);
modalBody.innerHTML = `<div class="alert alert-danger"><strong>خطا در ارتباط با سرور:</strong><br>${error.message}</div>`;
}
}
// Function to display fetched order details in the modal
function displayOrderDetails(order, products) {
let productsHtml = `
<div class="detail-box" style="grid-column: 1 / -1;">
<h3>محصولات سفارش</h3>
<div class="table-responsive">
<table class="products-table">
<thead>
<tr>
<th>محصول</th>
<th>تعداد</th>
<th>رنگ</th>
<th>قیمت واحد</th>
<th>قیمت کل</th>
</tr>
</thead>
<tbody>`;
products.forEach(p => {
productsHtml += `
<tr>
<td data-label="محصول"><img src="${p.image_url}" alt="${p.name}" class="me-2">${p.name}</td>
<td data-label="تعداد">${p.quantity}</td>
<td data-label="رنگ"><span class="cart-item-color-swatch" style="background-color: ${p.color || 'transparent'}"></span></td>
<td data-label="قیمت واحد">${parseInt(p.price).toLocaleString()} تومان</td>
<td data-label="قیمت کل">${(p.quantity * p.price).toLocaleString()} تومان</td>
</tr>`;
});
productsHtml += `</tbody></table></div></div>`;
const fullAddress = [order.billing_province, order.billing_city, order.billing_address, order.billing_postal_code].filter(Boolean).join(', ');
modalBody.innerHTML = `
<div class="order-modal-header">
<h2>جزئیات سفارش</h2>
<p class="text-muted">کد رهگیری: ${order.tracking_id}</p>
</div>
<div class="order-details-grid">
<div class="detail-box">
<h3>اطلاعات خریدار</h3>
<p><strong>نام:</strong> ${order.full_name}</p>
<p><strong>ایمیل:</strong> ${order.billing_email}</p>
<p><strong>تلفن:</strong> ${order.billing_phone}</p>
</div>
<div class="detail-box">
<h3>اطلاعات سفارش</h3>
<p><strong>وضعیت:</strong> <span class="order-status status-${order.status}">${order.status_jalali}</span></p>
<p><strong>تاریخ ثبت:</strong> ${order.created_at_jalali}</p>
<p><strong>آدرس:</strong> ${fullAddress}</p>
</div>
${productsHtml}
</div>
<div class="summary-totals mt-4 text-center">
<div class="grand-total">
<span class="label">جمع کل: </span>
<span class="value">${parseInt(order.total_amount).toLocaleString()} تومان</span>
</div>
</div>`;
}
// Add event listeners to all "View Details" buttons
const viewButtons = document.querySelectorAll('.view-order-btn');
viewButtons.forEach(button => {
button.addEventListener('click', function () {
const trackingId = this.getAttribute('data-tracking-id');
if (trackingId) {
openOrderModal(trackingId);
}
});
});
// Close modal logic
closeBtn.onclick = () => modal.style.display = 'none';
window.onclick = (event) => {
if (event.target == modal) {
modal.style.display = 'none';
}
};
});
</script>
<?php <?php
require_once 'includes/footer.php'; require_once 'includes/footer.php';
?> ?>

View File

@ -16,42 +16,50 @@ try {
?> ?>
<main class="container py-5"> <main class="container py-5">
<div class="text-center mb-5" data-aos="fade-down"> <div class="section-title text-center mb-5" data-aos="fade-down">
<h1 class="display-4 fw-bold">مجموعه کامل محصولات</h1> <h1>مجموعه کامل محصولات</h1>
<p class="fs-5">دست‌سازه‌هایی از چرم طبیعی، با عشق و دقت.</p> <p class="fs-5 text-muted">دست‌سازه‌هایی از چرم طبیعی، با عشق و دقت.</p>
</div> </div>
<?php if (!empty($db_error)): ?> <?php if (!empty($db_error)): ?>
<div class="alert alert-danger"> <div class="alert alert-danger">
<?php echo $db_error; ?> <?= $db_error; ?>
</div> </div>
<?php endif; ?> <?php endif; ?>
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4 g-4 g-lg-5"> <?php if (empty($products) && empty($db_error)): ?>
<?php <div class="col-12">
if (!empty($products)) { <p class="text-center text-muted fs-4">در حال حاضر محصولی برای نمایش وجود ندارد.</p>
</div>
<?php else: ?>
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 row-cols-lg-4 g-4 g-lg-5">
<?php
$delay = 0; $delay = 0;
foreach ($products as $product) { foreach ($products as $product):
echo '<div class="col" data-aos="fade-up" data-aos-delay="' . $delay . '">'; ?>
echo ' <div class="product-card h-100">'; <div class="col" data-aos="fade-up" data-aos-delay="<?= $delay ?>">
echo ' <div class="product-image">'; <div class="product-card h-100">
echo ' <a href="product.php?id=' . htmlspecialchars($product['id']) . '">'; <div class="product-image">
echo ' <img src="' . htmlspecialchars($product['image_url']) . '" class="img-fluid" alt="' . htmlspecialchars($product['name']) . '">'; <a href="product.php?id=<?= htmlspecialchars($product['id']) ?>">
echo ' </a>'; <img src="<?= htmlspecialchars($product['image_url']) ?>" alt="<?= htmlspecialchars($product['name']) ?>">
echo ' </div>'; </a>
echo ' <div class="product-info text-center">'; </div>
echo ' <h3 class="product-title"><a href="product.php?id=' . htmlspecialchars($product['id']) . '" class="text-decoration-none">' . htmlspecialchars($product['name']) . '</a></h3>'; <div class="product-info text-center">
echo ' <p class="product-price">' . number_format($product['price']) . ' تومان</p>'; <h3 class="product-title">
echo ' </div>'; <a href="product.php?id=<?= htmlspecialchars($product['id']) ?>">
echo ' </div>'; <?= htmlspecialchars($product['name']) ?>
echo '</div>'; </a>
</h3>
<p class="product-price"><?= number_format($product['price']) ?> تومان</p>
</div>
</div>
</div>
<?php
$delay = ($delay + 100) % 400; // Stagger animation delay $delay = ($delay + 100) % 400; // Stagger animation delay
} endforeach;
} else if (empty($db_error)) { ?>
echo '<div class="col-12"><p class="text-center text-white-50 fs-4">در حال حاضر محصولی برای نمایش وجود ندارد.</p></div>'; </div>
} <?php endif; ?>
?>
</div>
</main> </main>
<?php require_once 'includes/footer.php'; ?> <?php require_once 'includes/footer.php'; ?>

53
terms.php Normal file
View File

@ -0,0 +1,53 @@
<?php
$page_title = 'قوانین و مقررات';
require_once 'includes/header.php';
?>
<main class="container py-5 my-5">
<div class="section-title text-center mb-5" data-aos="fade-down">
<h1>قوانین و مقررات</h1>
<p class="fs-5 text-muted">لطفاً پیش از استفاده از خدمات ما، این موارد را به دقت مطالعه فرمایید.</p>
</div>
<div class="row justify-content-center">
<div class="col-lg-10 col-xl-8">
<div class="terms-content">
<div class="card mb-4" data-aos="fade-up">
<div class="card-body p-4 p-md-5">
<h3 class="fw-bold mb-3">۱. تعاریف و کلیات</h3>
<p class="lh-lg">لورم ایپسوم متن ساختگی با تولید سادگی نامفهوم از صنعت چاپ و با استفاده از طراحان گرافیک است. چاپگرها و متون بلکه روزنامه و مجله در ستون و سطرآنچنان که لازم است و برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می‌باشد. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد تا با نرم افزارها شناخت بیشتری را برای طراحان رایانه ای علی الخصوص طراحان خلاقی و فرهنگ پیشرو در زبان فارسی ایجاد کرد.</p>
</div>
</div>
<div class="card mb-4" data-aos="fade-up" data-aos-delay="100">
<div class="card-body p-4 p-md-5">
<h3 class="fw-bold mb-3">۲. شرایط استفاده از حساب کاربری</h3>
<p class="lh-lg">کاربران متعهد می‌شوند که اطلاعات خود را به درستی وارد کرده و در حفظ امنیت حساب کاربری خود کوشا باشند. هرگونه فعالیت از طریق حساب کاربری، به منزله فعالیت شخص کاربر تلقی خواهد شد. در این صورت دنیای جدیدی از تحلیل‌های متنی و پردازش زبان طبیعی پدیدار خواهد شد.</p>
</div>
</div>
<div class="card mb-4" data-aos="fade-up" data-aos-delay="200">
<div class="card-body p-4 p-md-5">
<h3 class="fw-bold mb-3">۳. حریم خصوصی</h3>
<p class="lh-lg">ما به حریم خصوصی شما احترام می‌گذاریم. اطلاعات شما نزد ما محفوظ است و تحت هیچ شرایطی در اختیار اشخاص ثالث قرار نخواهد گرفت، مگر با حکم قضایی. برای شرایط فعلی تکنولوژی مورد نیاز و کاربردهای متنوع با هدف بهبود ابزارهای کاربردی می‌باشد.</p>
</div>
</div>
<div class="card mb-4" data-aos="fade-up" data-aos-delay="300">
<div class="card-body p-4 p-md-5">
<h3 class="fw-bold mb-3">۴. مالکیت معنوی</h3>
<p class="lh-lg">کلیه محتوای این وب‌سایت، از جمله متون، طرح‌ها، لوگوها و تصاویر، متعلق به فروشگاه آتیمه بوده و هرگونه کپی‌برداری و استفاده تجاری بدون کسب اجازه کتبی، پیگرد قانونی خواهد داشت.</p>
</div>
</div>
<div class="card mb-4" data-aos="fade-up" data-aos-delay="400">
<div class="card-body p-4 p-md-5">
<h3 class="fw-bold mb-3">۵. قوانین بازگشت کالا</h3>
<p class="lh-lg">رضایت شما اولویت ماست. شرایط بازگشت کالا و رویه‌های مربوط به آن به طور کامل در صفحه "سوالات متداول" شرح داده شده است. لطفاً پیش از خرید، این بخش را مطالعه فرمایید. کتابهای زیادی در شصت و سه درصد گذشته، حال و آینده شناخت فراوان جامعه و متخصصان را می طلبد.</p>
</div>
</div>
</div>
</div>
</div>
</main>
<?php require_once 'includes/footer.php'; ?>

View File

@ -3,83 +3,77 @@ $page_title = "پیگیری سفارش";
include 'includes/header.php'; include 'includes/header.php';
?> ?>
<div class="container my-5">
<div class="track-container">
<h1><i class="ri-search-eye-line me-2"></i>پیگیری سفارش</h1>
<p>کد رهگیری سفارش خود را برای مشاهده جزئیات وارد کنید.</p>
<form id="track-order-form" class="mt-4">
<div class="mb-3">
<input type="text" id="tracking_id" name="tracking_id" class="form-control" placeholder="کد رهگیری سفارش" required>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary"><i class="ri-search-line me-2"></i>جستجو</button>
</div>
</form>
<div class="track-container"> <div id="result-message" class="mt-3"></div>
<h1>پیگیری سفارش</h1> </div>
<p>کد رهگیری و شماره تلفن خود را برای مشاهده جزئیات سفارش وارد کنید.</p>
<form id="track-order-form">
<div class="form-group">
<label for="tracking_id">کد رهگیری</label>
<input type="text" id="tracking_id" name="tracking_id" required>
</div>
<div class="form-group">
<label for="phone">شماره تلفن</label>
<input type="text" id="phone" name="phone" required>
</div>
<button type="submit" class="btn-track">جستجو</button>
</form>
<div id="result-message" style="margin-top: 20px; font-weight: bold;"></div>
</div> </div>
<!-- The Modal --> <!-- The Modal -->
<div id="order-modal" class="modal"> <div id="order-modal" class="order-modal">
<div class="modal-content"> <div class="order-modal-content">
<span class="close-btn">&times;</span> <span class="order-modal-close-btn">&times;</span>
<div id="modal-body"> <div id="modal-body">
<!-- Order details will be injected here by JavaScript --> <!-- Order details will be injected here by JavaScript -->
</div> </div>
</div> </div>
</div> </div>
<script> <script>
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
const form = document.getElementById('track-order-form'); const form = document.getElementById('track-order-form');
const modal = document.getElementById('order-modal'); const modal = document.getElementById('order-modal');
const modalBody = document.getElementById('modal-body'); const modalBody = document.getElementById('modal-body');
const closeBtn = document.querySelector('.close-btn'); const closeBtn = document.querySelector('.order-modal-close-btn');
const resultMessage = document.getElementById('result-message'); const resultMessage = document.getElementById('result-message');
form.addEventListener('submit', function (e) { form.addEventListener('submit', async function (e) {
e.preventDefault(); e.preventDefault();
const trackingId = document.getElementById('tracking_id').value; const trackingId = document.getElementById('tracking_id').value;
const phone = document.getElementById('phone').value;
resultMessage.textContent = 'در حال جستجو...'; resultMessage.innerHTML = `<div class="spinner-border spinner-border-sm" role="status"><span class="visually-hidden">Loading...</span></div> در حال جستجو...`;
resultMessage.style.color = 'var(--luxury-text-muted)'; resultMessage.className = 'text-muted';
try {
const response = await fetch('api/get_order_details.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ tracking_id: trackingId }),
});
fetch('api/get_order_details.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
tracking_id: trackingId,
phone: phone
}),
})
.then(response => {
if (!response.ok) { if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`); throw new Error(`خطای سرور: ${response.status}`);
} }
return response.json();
}) const data = await response.json();
.then(data => {
if (data.success) { if (data.success) {
resultMessage.textContent = ''; resultMessage.textContent = '';
displayOrderDetails(data.order, data.products); displayOrderDetails(data.order, data.products);
modal.style.display = 'block'; modal.style.display = 'block';
} else { } else {
resultMessage.textContent = data.message; resultMessage.textContent = data.message;
resultMessage.style.color = '#ff6b6b'; // A clearer error color resultMessage.className = 'text-danger fw-bold';
} }
}) } catch (error) {
.catch(error => { console.error('Fetch Error:', error);
console.error('Error:', error);
resultMessage.textContent = 'خطا در برقراری ارتباط با سرور.'; resultMessage.textContent = 'خطا در برقراری ارتباط با سرور.';
resultMessage.style.color = '#ff6b6b'; resultMessage.className = 'text-danger fw-bold';
}); }
}); });
function displayOrderDetails(order, products) { function displayOrderDetails(order, products) {
@ -101,51 +95,47 @@ document.addEventListener('DOMContentLoaded', function () {
products.forEach(p => { products.forEach(p => {
productsHtml += ` productsHtml += `
<tr> <tr>
<td><img src="assets/images/products/${p.image}" alt="${p.name}">${p.name}</td> <td data-label="محصول"><img src="${p.image_url}" alt="${p.name}" class="me-2">${p.name}</td>
<td>${p.quantity}</td> <td data-label="تعداد">${p.quantity}</td>
<td>${p.color || '-'}</td> <td data-label="رنگ"><span class="cart-item-color-swatch" style="background-color: ${p.color || 'transparent'}"></span></td>
<td>${parseInt(p.price).toLocaleString()} تومان</td> <td data-label="قیمت واحد">${parseInt(p.price).toLocaleString()} تومان</td>
<td>${(p.quantity * p.price).toLocaleString()} تومان</td> <td data-label="قیمت کل">${(p.quantity * p.price).toLocaleString()} تومان</td>
</tr> </tr>
`; `;
}); });
productsHtml += ` productsHtml += `</tbody></table></div>`;
</tbody>
</table>
</div>
`;
modalBody.innerHTML = ` modalBody.innerHTML = `
<div class="modal-header"> <div class="order-modal-header">
<h2>جزئیات سفارش</h2> <h2>جزئیات سفارش</h2>
<p>کد رهگیری: ${order.tracking_id}</p> <p class="text-muted">کد رهگیری: ${order.tracking_id}</p>
</div> </div>
<div class="order-details-grid"> <div class="order-details-grid">
<div class="detail-box"> <div class="detail-box">
<h3>اطلاعات خریدار</h3> <h3>اطلاعات خریدار</h3>
<p><strong>نام و نام خانوادگی:</strong> ${order.full_name}</p> <p><strong>نام:</strong> ${order.full_name}</p>
<p><strong>ایمیل:</strong> ${order.email}</p> <p><strong>ایمیل:</strong> ${order.email}</p>
<p><strong>تلفن:</strong> ${order.billing_phone}</p> <p><strong>تلفن:</strong> ${order.billing_phone}</p>
</div> </div>
<div class="detail-box"> <div class="detail-box">
<h3>اطلاعات سفارش</h3> <h3>اطلاعات سفارش</h3>
<p><strong>وضعیت:</strong> <span style="font-weight: bold; color: #81c784;">${order.status}</span></p> <p><strong>وضعیت:</strong> <span class="order-status status-${order.status}">${order.status_jalali}</span></p>
<p><strong>تاریخ ثبت:</strong> ${order.created_at_jalali}</p> <p><strong>تاریخ ثبت:</strong> ${order.created_at_jalali}</p>
<p><strong>آدرس کامل:</strong> ${order.address}</p> <p><strong>آدرس:</strong> ${order.address}</p>
</div> </div>
${productsHtml} ${productsHtml}
</div> </div>
<div class="total-price-container"> <div class="summary-totals mt-4 text-center">
<p>جمع کل: ${parseInt(order.total_price).toLocaleString()} تومان</p> <div class="grand-total">
<span class="label">جمع کل: </span>
<span class="value">${parseInt(order.total_amount).toLocaleString()} تومان</span>
</div>
</div> </div>
`; `;
} }
closeBtn.onclick = function () { closeBtn.onclick = () => modal.style.display = 'none';
modal.style.display = 'none'; window.onclick = (event) => {
}
window.onclick = function (event) {
if (event.target == modal) { if (event.target == modal) {
modal.style.display = 'none'; modal.style.display = 'none';
} }

View File

@ -15,17 +15,15 @@ $page_title = "تایید کد یکبار مصرف";
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?php echo $page_title; ?> - آتیمه</title> <title><?= $page_title; ?> - آتیمه</title>
<!-- Bootstrap CSS --> <!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet">
<!-- Vazirmatn Font --> <!-- Remixicon -->
<link href="https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css" rel="stylesheet" type="text/css" /> <link href="https://cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.css" rel="stylesheet" />
<!-- Main Custom CSS (for variables) --> <!-- Main Custom CSS (for variables) -->
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>"> <link rel="stylesheet" href="assets/css/dark_luxury.css?v=<?= time(); ?>">
<!-- Custom Auth CSS -->
<link rel="stylesheet" href="assets/css/auth_style.css?v=<?php echo time(); ?>">
</head> </head>
<body> <body class="dark-luxury">
<div class="auth-wrapper"> <div class="auth-wrapper">
<div class="auth-bg"> <div class="auth-bg">
@ -37,24 +35,25 @@ $page_title = "تایید کد یکبار مصرف";
<div class="auth-form-wrapper"> <div class="auth-form-wrapper">
<div class="auth-form-container"> <div class="auth-form-container">
<div class="form-header text-center"> <div class="form-header">
<div class="logo">آتیمه</div>
<h2>تایید کد</h2> <h2>تایید کد</h2>
<p>کد ۶ رقمی ارسال شده به <strong><?php echo $email_for_display; ?></strong> را وارد کنید.</p> <p>کد ۶ رقمی ارسال شده به <strong class="d-block mt-2"><?= $email_for_display; ?></strong> را وارد کنید.</p>
</div> </div>
<?php if(isset($_SESSION['flash_message'])): ?> <?php if(isset($_SESSION['flash_message'])): ?>
<div class="alert alert-<?php echo $_SESSION['flash_message']['type']; ?> alert-dismissible fade show" role="alert"> <div class="alert alert-<?= htmlspecialchars($_SESSION['flash_message']['type']); ?> alert-dismissible fade show" role="alert">
<?php echo htmlspecialchars($_SESSION['flash_message']['message']); ?> <?= htmlspecialchars($_SESSION['flash_message']['message']); ?>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button> <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div> </div>
<?php unset($_SESSION['flash_message']); ?> <?php unset($_SESSION['flash_message']); ?>
<?php endif; ?> <?php endif; ?>
<form action="auth_handler.php?action=verify_otp" method="POST"> <form action="auth_handler.php?action=verify_otp" method="POST">
<input type="hidden" name="email" value="<?php echo $email_for_display; ?>"> <input type="hidden" name="email" value="<?= $email_for_display; ?>">
<div class="form-group"> <div class="form-group">
<label for="otp_code" class="form-label visually-hidden">کد تایید</label> <label for="otp_code" class="form-label visually-hidden">کد تایید</label>
<input type="text" class="form-control text-center" id="otp_code" name="otp_code" placeholder="- - - - - -" required pattern="\d{6}" maxlength="6"> <input type="text" class="form-control otp-input" id="otp_code" name="otp_code" placeholder="- - - - - -" required pattern="\d{6}" maxlength="6" autocomplete="one-time-code">
</div> </div>
<div class="d-grid mt-4"> <div class="d-grid mt-4">
@ -63,7 +62,7 @@ $page_title = "تایید کد یکبار مصرف";
</form> </form>
<div class="auth-footer"> <div class="auth-footer">
<p>ایمیل را اشتباه وارد کردید؟ <a href="login.php">بازگشت</a></p> <p><a href="login.php"><i class="ri-arrow-right-line"></i> بازگشت و اصلاح ایمیل</a></p>
</div> </div>
</div> </div>
</div> </div>