پررررررررر
This commit is contained in:
parent
3f48850ff5
commit
6c608b6ba5
@ -33,21 +33,21 @@ require_once 'includes/header.php';
|
||||
<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="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>
|
||||
<p class="text-muted px-3">استفاده از بهترین مواد اولیه و کنترل کیفی دقیق در تمام مراحل تولید.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4" data-aos="fade-up" data-aos-delay="200">
|
||||
<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>
|
||||
<p class="text-muted px-3">تمام محصولات ما با عشق و دقت توسط هنرمندان ماهر ساخته میشوند.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4" data-aos="fade-up" data-aos-delay="300">
|
||||
<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>
|
||||
<p class="text-muted px-3">خلق آثاری مدرن و در عین حال کلاسیک که هیچگاه از مد نمیافتند.</p>
|
||||
</div>
|
||||
|
||||
347
admin/assets/css/admin_main.css
Normal file
347
admin/assets/css/admin_main.css
Normal 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 */
|
||||
|
||||
2
admin/cache/sales_chart.json
vendored
2
admin/cache/sales_chart.json
vendored
@ -1 +1 @@
|
||||
{"labels":["1404-09"],"data":[2940000]}
|
||||
{"labels":[],"data":[]}
|
||||
@ -1,66 +1,63 @@
|
||||
<?php
|
||||
$page_title = 'داشبورد';
|
||||
require_once __DIR__ . '/header.php';
|
||||
?>
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="admin-header">
|
||||
<h1>گزارشها</h1>
|
||||
<h1><?php echo $page_title; ?></h1>
|
||||
</div>
|
||||
|
||||
<div id="dashboard-error" class="card d-none" style="color: var(--admin-danger);"><div class="card-body"></div></div>
|
||||
|
||||
<style>
|
||||
.stat-cards-grid-reports {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||
gap: 1.5rem;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="stat-cards-grid-reports">
|
||||
<div class="dashboard-container">
|
||||
<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="icon-container" style="background-color: #28a74555;"><i class="fas fa-dollar-sign" style="color: #28a745;"></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="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 bg-primary"><i class="fas fa-truck"></i></div>
|
||||
<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 bg-danger"><i class="fas fa-times-circle"></i></div>
|
||||
<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 bg-warning"><i class="fas fa-spinner"></i></div>
|
||||
<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" style="background-color: #6f42c1;"><i class="fas fa-eye"></i></div>
|
||||
<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>
|
||||
|
||||
|
||||
<div class="chart-container" style="position: relative; height:40vh; max-height: 450px;">
|
||||
<h5>نمودار فروش ماهانه (سفارشات تحویل شده)</h5>
|
||||
|
||||
@ -3,10 +3,10 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<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">
|
||||
|
||||
<!-- Unified Stylesheet -->
|
||||
<!-- Main Admin Stylesheet -->
|
||||
<link rel="stylesheet" href="assets/css/admin_style.css?v=<?php echo time(); ?>">
|
||||
|
||||
<!-- SweetAlert2 -->
|
||||
@ -18,5 +18,5 @@
|
||||
<body class="admin-dark-theme">
|
||||
|
||||
<div class="admin-wrapper">
|
||||
<?php require_once 'nav.php'; ?>
|
||||
<div class="admin-main-content">
|
||||
<?php require_once 'nav.php'; // The sidebar is included here ?>
|
||||
<main class="admin-main-content">
|
||||
@ -1,7 +1,6 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
// If the user is already logged in, redirect them to the admin dashboard
|
||||
if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true) {
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
@ -9,71 +8,62 @@ if (isset($_SESSION['is_admin']) && $_SESSION['is_admin'] === true) {
|
||||
|
||||
$error = '';
|
||||
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';
|
||||
|
||||
if (isset($_POST['password']) && $_POST['password'] === $hardcoded_password) {
|
||||
// On successful login, set a session variable
|
||||
$_SESSION['is_admin'] = true;
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
} else {
|
||||
$error = 'رمز عبور اشتباه است.';
|
||||
$error = 'رمز عبور وارد شده اشتباه است.';
|
||||
}
|
||||
}
|
||||
$page_title = 'ورود به پنل مدیریت';
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="fa" dir="rtl">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>ورود به پنل مدیریت</title>
|
||||
<title><?= $page_title; ?></title>
|
||||
<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/custom.css?v=<?php echo time(); ?>">
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<link rel="stylesheet" href="assets/css/admin_main.css?v=<?= time(); ?>">
|
||||
</head>
|
||||
<body class="bg-dark text-white">
|
||||
<body class="admin-theme">
|
||||
|
||||
<div class="admin-login-wrapper">
|
||||
<div class="admin-login-box">
|
||||
<h2>پنل مدیریت آتیمه</h2>
|
||||
<p>برای دسترسی به پنل، لطفاً وارد شوید.</p>
|
||||
|
||||
<div class="container">
|
||||
<div class="row justify-content-center align-items-center" style="height: 100vh;">
|
||||
<div class="col-md-4">
|
||||
<div class="card bg-dark-2">
|
||||
<div class="card-body p-4">
|
||||
<h1 class="font-lalezar text-center mb-4">ورود به پنل</h1>
|
||||
<p class="text-center text-muted mb-4">رمز عبور: admin123</p>
|
||||
<?php if ($error): ?>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
Swal.fire({
|
||||
toast: true,
|
||||
position: 'top-start',
|
||||
icon: 'error',
|
||||
title: '<?php echo $error; ?>',
|
||||
showConfirmButton: false,
|
||||
timer: 3000,
|
||||
timerProgressBar: true,
|
||||
background: '#2C2C2C',
|
||||
color: '#D5D5D5'
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<div class="alert alert-danger mb-3"><?= $error; ?></div>
|
||||
<p class="text-center text-muted mb-4">رمز عبور پیشفرض: <code>admin123</code></p>
|
||||
<?php endif; ?>
|
||||
<form method="POST">
|
||||
<div class="mb-3">
|
||||
|
||||
<form method="POST" action="login.php">
|
||||
<div class="form-group">
|
||||
<label for="password" class="form-label">رمز عبور</label>
|
||||
<input type="password" class="form-control bg-dark text-white" id="password" name="password" required>
|
||||
<input type="password" class="form-control" id="password" name="password" required autofocus>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary">ورود</button>
|
||||
<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>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</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>
|
||||
@ -3,35 +3,31 @@
|
||||
<div class="sidebar-header">
|
||||
<h2><a href="index.php">آتیمه<span>.</span></a></h2>
|
||||
</div>
|
||||
<nav>
|
||||
<ul class="admin-nav">
|
||||
<li class="admin-nav-item">
|
||||
<a class="admin-nav-link <?php echo ($current_page == 'index.php') ? 'active' : ''; ?>" href="index.php">
|
||||
<i class="fas fa-tachometer-alt"></i>
|
||||
<span>داشبورد اصلی</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="admin-nav-item">
|
||||
<a class="admin-nav-link <?php echo ($current_page == 'dashboard.php') ? 'active' : ''; ?>" href="dashboard.php">
|
||||
<i class="fas fa-chart-line"></i>
|
||||
<span>گزارشها</span>
|
||||
<a class="admin-nav-link <?php echo ($current_page == 'index.php' || $current_page == 'dashboard.php') ? 'active' : ''; ?>" href="index.php">
|
||||
<i class="ri-dashboard-line"></i>
|
||||
<span>داشبورد</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="admin-nav-item">
|
||||
<a class="admin-nav-link <?php echo in_array($current_page, ['products.php', 'add_product.php', 'edit_product.php']) ? 'active' : ''; ?>" href="products.php">
|
||||
<i class="fas fa-box"></i>
|
||||
<i class="ri-shopping-cart-2-line"></i>
|
||||
<span>محصولات</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="admin-nav-item">
|
||||
<a class="admin-nav-link <?php echo ($current_page == 'orders.php') ? 'active' : ''; ?>" href="orders.php">
|
||||
<i class="fas fa-receipt"></i>
|
||||
<i class="ri-file-list-3-line"></i>
|
||||
<span>سفارشات</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
<div class="sidebar-footer">
|
||||
<a href="../index.php" target="_blank"><i class="fas fa-external-link-alt"></i> مشاهده سایت</a>
|
||||
<hr style="border-color: var(--admin-border); margin: 1rem 0;">
|
||||
<a href="logout.php"><i class="fas fa-sign-out-alt"></i> خروج</a>
|
||||
<a href="../index.php" target="_blank"><i class="ri-external-link-line"></i> مشاهده سایت</a>
|
||||
<hr style="border-color: var(--admin-border-light); margin: 1rem 0;">
|
||||
<a href="logout.php"><i class="ri-logout-box-line"></i> خروج</a>
|
||||
</div>
|
||||
</aside>
|
||||
@ -102,7 +102,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
<button class="modal-close">×</button>
|
||||
</div>
|
||||
<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>
|
||||
<strong>آدرس:</strong> <?php echo htmlspecialchars($order['billing_address'] . ", " . $order['billing_city'] . ", " . $order['billing_province']); ?><br>
|
||||
<strong>تلفن:</strong> <?php echo htmlspecialchars($order['billing_phone']); ?></p>
|
||||
|
||||
@ -3,46 +3,70 @@ header('Content-Type: application/json');
|
||||
require_once '../db/config.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'];
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
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'] ?? '';
|
||||
$phone = $data['phone'] ?? '';
|
||||
|
||||
if (empty($tracking_id) || empty($phone)) {
|
||||
$response['message'] = 'کد رهگیری و شماره تلفن الزامی است.';
|
||||
echo json_encode($response);
|
||||
exit;
|
||||
if (empty($tracking_id)) {
|
||||
throw new Exception('کد رهگیری سفارش الزامی است.');
|
||||
}
|
||||
|
||||
try {
|
||||
$db = db();
|
||||
$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
|
||||
JOIN users u ON o.user_id = u.id
|
||||
WHERE o.tracking_id = :tracking_id AND o.billing_phone = :phone"
|
||||
WHERE o.tracking_id = :tracking_id"
|
||||
);
|
||||
$stmt->bindParam(':tracking_id', $tracking_id);
|
||||
$stmt->bindParam(':phone', $phone);
|
||||
$stmt->execute();
|
||||
$stmt->execute([':tracking_id' => $tracking_id]);
|
||||
$order = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ($order) {
|
||||
$order_id = $order['id'];
|
||||
$products_stmt = $db->prepare(
|
||||
"SELECT p.name, p.price, p.image, oi.quantity, oi.color
|
||||
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);
|
||||
$items_json = $order['items_json'];
|
||||
$items = json_decode($items_json, true);
|
||||
$products = [];
|
||||
|
||||
// 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['status_jalali'] = get_persian_status($order['status']);
|
||||
|
||||
|
||||
$response['success'] = true;
|
||||
$response['message'] = 'سفارش یافت شد.';
|
||||
@ -53,11 +77,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
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);
|
||||
} else {
|
||||
echo json_encode($response);
|
||||
|
||||
}
|
||||
?>
|
||||
@ -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;
|
||||
|
||||
}
|
||||
@ -1,356 +1,3 @@
|
||||
/* General Body Styles */
|
||||
body {
|
||||
font-family: 'Vazirmatn', sans-serif;
|
||||
background-color: #f8f9fa;
|
||||
color: #212529;
|
||||
font-weight: 400;
|
||||
direction: rtl;
|
||||
text-align: right;
|
||||
.empty-cart-container .btn-checkout i {
|
||||
color: inherit !important;
|
||||
}
|
||||
|
||||
.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
BIN
assets/pasted-20251206-134906-08663223.jpg
Normal file
BIN
assets/pasted-20251206-134906-08663223.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 181 KiB |
BIN
assets/vm-shot-2025-12-06T13-48-54-374Z.jpg
Normal file
BIN
assets/vm-shot-2025-12-06T13-48-54-374Z.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
10
cart.php
10
cart.php
@ -23,7 +23,7 @@ $total_price = 0;
|
||||
<?php else: ?>
|
||||
<div class="text-center mb-5">
|
||||
<h1 class="fw-bold display-5">سبد خرید شما</h1>
|
||||
<p class="text-white-50 fs-5">جزئیات سفارش خود را بررسی و نهایی کنید.</p>
|
||||
<p class="text-muted fs-5">جزئیات سفارش خود را بررسی و نهایی کنید.</p>
|
||||
</div>
|
||||
<div class="row g-5">
|
||||
<div class="col-lg-8">
|
||||
@ -48,10 +48,10 @@ $total_price = 0;
|
||||
</div>
|
||||
<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>
|
||||
<?php if (!empty($item['color'])): ?>
|
||||
<?php if (!empty($item['color'])) : ?>
|
||||
<div class="d-flex align-items-center">
|
||||
<small class="text-white-50 me-2">رنگ:</small>
|
||||
<span class="d-inline-block rounded-circle border" style="width: 20px; height: 20px; background-color: <?php echo htmlspecialchars($item['color']); ?>;"></span>
|
||||
<small class="text-muted me-2">رنگ:</small>
|
||||
<span class="cart-item-color-swatch" style="background-color: <?php echo htmlspecialchars($item['color']); ?>;"></span>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
@ -92,7 +92,7 @@ $total_price = 0;
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
274
checkout.php
274
checkout.php
@ -1,185 +1,185 @@
|
||||
<?php
|
||||
session_start();
|
||||
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'])) {
|
||||
header('Location: shop.php');
|
||||
exit;
|
||||
exit();
|
||||
}
|
||||
|
||||
$cart_items = $_SESSION['cart'];
|
||||
$total_price = array_reduce($cart_items, function ($sum, $item) {
|
||||
return $sum + ($item['price'] * $item['quantity']);
|
||||
}, 0);
|
||||
$product_details = [];
|
||||
$total_price = 0;
|
||||
|
||||
// User and address data
|
||||
$logged_in_user = null;
|
||||
$user_addresses = [];
|
||||
$is_logged_in = isset($_SESSION['user_id']);
|
||||
// 2. Process cart items directly from the session
|
||||
foreach ($cart_items as $cart_item_id => $item) {
|
||||
// Ensure item has required data
|
||||
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 {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$logged_in_user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
$user_stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?");
|
||||
$user_stmt->execute([$user_id]);
|
||||
$user = $user_stmt->fetch(PDO::FETCH_ASSOC) ?: [];
|
||||
|
||||
$stmt = $pdo->prepare("SELECT * FROM user_addresses WHERE user_id = ? ORDER BY is_default DESC, id DESC");
|
||||
$stmt->execute([$_SESSION['user_id']]);
|
||||
$user_addresses = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
$address_stmt = $pdo->prepare("SELECT * FROM user_addresses WHERE user_id = ? ORDER BY id DESC LIMIT 1");
|
||||
$address_stmt->execute([$user_id]);
|
||||
$address = $address_stmt->fetch(PDO::FETCH_ASSOC) ?: [];
|
||||
} catch (PDOException $e) {
|
||||
// In a real app, log this error
|
||||
die("Error fetching user data.");
|
||||
error_log("Checkout user fetch error: " . $e->getMessage());
|
||||
// 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">
|
||||
<div class="row">
|
||||
<!-- Billing Details Column -->
|
||||
<div class="col-lg-8">
|
||||
<h2 class="mb-4">جزئیات صورتحساب</h2>
|
||||
|
||||
<?php
|
||||
if (isset($_SESSION['error_message'])) {
|
||||
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>';
|
||||
unset($_SESSION['error_message']);
|
||||
if (!empty($_SESSION['checkout_errors'])) {
|
||||
echo '<div class="alert alert-danger"><ul>';
|
||||
foreach ($_SESSION['checkout_errors'] as $error) {
|
||||
echo '<li>' . htmlspecialchars($error) . '</li>';
|
||||
}
|
||||
echo '</ul></div>';
|
||||
// Unset the session variable so it doesn't show again on refresh
|
||||
unset($_SESSION['checkout_errors']);
|
||||
}
|
||||
?>
|
||||
<div class="text-center mb-5">
|
||||
<h1 class="fw-bold">تکمیل فرآیند خرید</h1>
|
||||
<p class="text-muted">فقط یک قدم دیگر تا نهایی شدن سفارش شما باقیست.</p>
|
||||
</div>
|
||||
|
||||
<form action="checkout_handler.php" method="POST">
|
||||
<div class="row g-5">
|
||||
<!-- Shipping Details -->
|
||||
<div class="col-lg-7">
|
||||
<h3 class="mb-4">اطلاعات ارسال</h3>
|
||||
<form id="checkout-form" action="checkout_handler.php" method="POST">
|
||||
|
||||
<?php if ($is_logged_in && !empty($user_addresses)): ?>
|
||||
<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 class="checkout-card">
|
||||
<div class="card-header">اطلاعات تماس</div>
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="firstName" class="form-label">نام</label>
|
||||
<input type="text" class="form-control" id="firstName" name="first_name" value="<?= htmlspecialchars($user['first_name'] ?? '') ?>" required>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="card bg-dark border-secondary shadow-sm rounded-4">
|
||||
<div class="card-body p-4">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-6">
|
||||
<label for="first_name" class="form-label">نام</label>
|
||||
<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>
|
||||
<div class="invalid-feedback"></div>
|
||||
<div class="col-md-6 mb-3">
|
||||
<label for="lastName" class="form-label">نام خانوادگی</label>
|
||||
<input type="text" class="form-control" id="lastName" name="last_name" value="<?= htmlspecialchars($user['last_name'] ?? '') ?>" required>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label for="last_name" 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>
|
||||
<div class="invalid-feedback"></div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<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">
|
||||
<div class="col-md-6 mb-3">
|
||||
<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'] ?? ''); ?>">
|
||||
<div class="invalid-feedback"></div>
|
||||
<input type="email" class="form-control" id="email" name="email" value="<?= htmlspecialchars($user['email'] ?? '') ?>">
|
||||
</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 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>
|
||||
|
||||
<!-- Order Summary -->
|
||||
<div class="col-lg-5">
|
||||
<div class="card bg-dark border-secondary shadow-sm rounded-4 sticky-top" style="top: 100px;">
|
||||
<div class="card-body p-4">
|
||||
<h4 class="card-title fw-bold mb-4">خلاصه سفارش</h4>
|
||||
<ul class="list-group list-group-flush mb-4">
|
||||
<?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 class="checkout-card">
|
||||
<div class="card-header">آدرس جهت ارسال</div>
|
||||
<div class="card-body">
|
||||
<div class="mb-3">
|
||||
<label for="address" class="form-label">آدرس</label>
|
||||
<input type="text" class="form-control" id="address" name="address_line" placeholder="خیابان اصلی، کوچه فرعی، پلاک ۱۲۳" value="<?= htmlspecialchars($address['address_line'] ?? '') ?>" required>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div class="row">
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="city" class="form-label">شهر</label>
|
||||
<input type="text" class="form-control" id="city" name="city" value="<?= htmlspecialchars($address['city'] ?? '') ?>" required>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="state" class="form-label">استان</label>
|
||||
<input type="text" class="form-control" id="state" name="province" value="<?= htmlspecialchars($address['province'] ?? '') ?>" required>
|
||||
</div>
|
||||
<div class="col-md-4 mb-3">
|
||||
<label for="zip" class="form-label">کد پستی</label>
|
||||
<input type="text" class="form-control" id="zip" name="postal_code" value="<?= htmlspecialchars($address['postal_code'] ?? '') ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<span class="fw-bold"><?php echo number_format($item['price'] * $item['quantity']); ?></span>
|
||||
</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="d-flex justify-content-between mb-2">
|
||||
<span class="text-muted">جمع کل</span>
|
||||
<span><?php echo number_format($total_price); ?> تومان</span>
|
||||
<div class="summary-totals">
|
||||
<div class="total-row">
|
||||
<span class="label">جمع کل</span>
|
||||
<span class="value">T <?= number_format($total_price) ?></span>
|
||||
</div>
|
||||
<div class="d-flex justify-content-between mb-3">
|
||||
<span class="text-muted">هزینه ارسال</span>
|
||||
<span class="text-success">رایگان</span>
|
||||
<div class="total-row">
|
||||
<span class="label">هزینه ارسال</span>
|
||||
<span class="value">T <?= number_format($shipping_cost) ?></span>
|
||||
</div>
|
||||
<hr class="border-secondary">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<span class="h5 fw-bold">مبلغ نهایی</span>
|
||||
<span class="h5 fw-bolder text-primary"><?php echo number_format($total_price); ?> تومان</span>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary btn-lg">ثبت نهایی سفارش</button>
|
||||
</div>
|
||||
<div class="text-center mt-3">
|
||||
<small class="text-muted"><i class="ri-lock-line me-1"></i> پرداخت امن و مطمئن</small>
|
||||
<div class="total-row grand-total mt-3">
|
||||
<span class="label">مبلغ قابل پرداخت</span>
|
||||
<span class="value">T <?= number_format($grand_total) ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script src="assets/js/checkout_validation.js?v=<?php echo time(); ?>"></script>
|
||||
<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>
|
||||
</main>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
@ -1,109 +1,158 @@
|
||||
<?php
|
||||
session_start();
|
||||
|
||||
|
||||
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') {
|
||||
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');
|
||||
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->beginTransaction();
|
||||
|
||||
try {
|
||||
// 4. Prepare order data
|
||||
$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);
|
||||
$pdo->beginTransaction();
|
||||
|
||||
// 5. Insert the order into the database using the correct, updated column names
|
||||
$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) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
||||
// 5. User Handling (Guest or Logged in)
|
||||
$user_id = $_SESSION['user_id'] ?? null;
|
||||
|
||||
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;
|
||||
$status = 'Processing'; // Default status
|
||||
$final_email = ($email !== false && $email !== '') ? $email : null;
|
||||
$full_name = $first_name . ' ' . $last_name;
|
||||
$items_json_encoded = json_encode($items_for_json, JSON_UNESCAPED_UNICODE);
|
||||
|
||||
$stmt->execute([
|
||||
$order_stmt->execute([
|
||||
$user_id,
|
||||
$billing_name,
|
||||
$final_email,
|
||||
$full_name,
|
||||
$email,
|
||||
$phone_number,
|
||||
$province,
|
||||
$city,
|
||||
$address_line,
|
||||
$postal_code,
|
||||
$total_amount,
|
||||
$products_data_json,
|
||||
$status
|
||||
$grand_total, // Storing the final amount including shipping
|
||||
$items_json_encoded,
|
||||
$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();
|
||||
|
||||
// 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']);
|
||||
$_SESSION['success_message'] = "سفارش شما با موفقیت ثبت شد! کد پیگیری شما: <strong>" . htmlspecialchars($tracking_id) . "</strong>";
|
||||
// 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.
|
||||
unset($_SESSION['form_data']);
|
||||
|
||||
header('Location: index.php');
|
||||
exit;
|
||||
header('Location: track_order.php?tracking_id=' . $tracking_id);
|
||||
exit();
|
||||
|
||||
} catch (Exception $e) {
|
||||
// 9. If anything fails, rollback and redirect with an error
|
||||
$pdo->rollBack();
|
||||
error_log("Order Creation Failed: " . $e->getMessage()); // Log error for admin
|
||||
$_SESSION['error_message'] = 'خطایی در ثبت سفارش رخ داد. لطفاً دوباره تلاش کنید.';
|
||||
// Log the detailed error for developers
|
||||
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');
|
||||
exit;
|
||||
exit();
|
||||
}
|
||||
52
contact.php
52
contact.php
@ -11,11 +11,11 @@ if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['contact_form'])) {
|
||||
$message = trim(filter_input(INPUT_POST, 'message', FILTER_SANITIZE_STRING));
|
||||
|
||||
if (empty($name) || empty($email) || empty($message)) {
|
||||
$_SESSION['flash_message'] = ['type' => 'error', 'message' => 'لطفاً تمام فیلدها را پر کنید.'];
|
||||
$_SESSION['flash_message'] = ['type' => 'warning', 'message' => 'لطفاً تمام فیلدها را پر کنید.'];
|
||||
} elseif (!$email) {
|
||||
$_SESSION['flash_message'] = ['type' => 'error', 'message' => 'آدرس ایمیل وارد شده معتبر نیست.'];
|
||||
} else {
|
||||
$to_email = getenv('MAIL_TO') ?: 'support@atimeh.com';
|
||||
$to_email = getenv('MAIL_TO') ?: 'support@atimeh.com'; // Fallback 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");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Check for flash message
|
||||
$flash_message = $_SESSION['flash_message'] ?? null;
|
||||
if ($flash_message) {
|
||||
// Clear the message from session so it doesn't show again
|
||||
unset($_SESSION['flash_message']);
|
||||
}
|
||||
?>
|
||||
@ -49,21 +52,21 @@ if ($flash_message) {
|
||||
<div class="contact-info h-100 d-flex flex-column justify-content-center">
|
||||
<h3 class="mb-4">راههای ارتباطی</h3>
|
||||
<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>
|
||||
<strong>آدرس:</strong>
|
||||
<p class="text-muted mb-0">تهران، خیابان هنر، کوچه خلاقیت، پلاک ۱۲</p>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
<strong>ایمیل:</strong>
|
||||
<p class="mb-0"><a href="mailto:info@atimeh.com">info@atimeh.com</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
<strong>تلفن:</strong>
|
||||
<p class="mb-0"><a href="tel:+982112345678">۰۲۱-۱۲۳۴۵۶۷۸</a></p>
|
||||
@ -71,17 +74,17 @@ if ($flash_message) {
|
||||
</div>
|
||||
<hr class="my-4" style="border-color: var(--luxury-border);">
|
||||
<h4 class="h5 mb-3">ما را دنبال کنید</h4>
|
||||
<div class="d-flex">
|
||||
<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="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="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>
|
||||
<div class="d-flex gap-2">
|
||||
<a href="#" class="social-btn"><i class="ri-instagram-line"></i></a>
|
||||
<a href="#" class="social-btn"><i class="ri-telegram-line"></i></a>
|
||||
<a href="#" class="social-btn"><i class="ri-whatsapp-line"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-7">
|
||||
<h3 class="mb-4">فرم تماس</h3>
|
||||
<form action="contact.php" method="POST">
|
||||
<input type="hidden" name="contact_form">
|
||||
<input type="hidden" name="contact_form" value="1">
|
||||
<div class="mb-4">
|
||||
<label for="name" class="form-label">نام شما</label>
|
||||
<input type="text" class="form-control" id="name" name="name" required>
|
||||
@ -103,25 +106,28 @@ if ($flash_message) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SweetAlert for flash messages -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
<?php if ($flash_message): ?>
|
||||
const swalConfig = {
|
||||
title: '<?php echo $flash_message["type"] === "success" ? "موفق" : "خطا"; ?>',
|
||||
text: '<?php echo addslashes($flash_message["message"]); ?>',
|
||||
Swal.fire({
|
||||
title: '<?php echo addslashes($flash_message["message"]); ?>',
|
||||
icon: '<?php echo $flash_message["type"]; ?>',
|
||||
confirmButtonText: 'باشه',
|
||||
};
|
||||
|
||||
// Apply dark theme to SweetAlert2
|
||||
if (document.body.classList.contains('dark-luxury')) {
|
||||
swalConfig.background = 'var(--luxury-surface)';
|
||||
swalConfig.color = 'var(--luxury-text)';
|
||||
swalConfig.confirmButtonColor = 'var(--luxury-primary)';
|
||||
toast: true,
|
||||
position: 'top-start',
|
||||
showConfirmButton: false,
|
||||
timer: 5000,
|
||||
timerProgressBar: true,
|
||||
showCloseButton: true,
|
||||
didOpen: (toast) => {
|
||||
toast.addEventListener('mouseenter', Swal.stopTimer);
|
||||
toast.addEventListener('mouseleave', Swal.resumeTimer);
|
||||
},
|
||||
customClass: {
|
||||
popup: 'dark-theme-toast'
|
||||
}
|
||||
|
||||
Swal.fire(swalConfig);
|
||||
});
|
||||
<?php endif; ?>
|
||||
});
|
||||
</script>
|
||||
|
||||
1
db/migrations/015_allow_null_password_in_users.sql
Normal file
1
db/migrations/015_allow_null_password_in_users.sql
Normal 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
86
faq.php
Normal 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'; ?>
|
||||
@ -11,9 +11,10 @@
|
||||
<h5 class="fw-bold mb-3">دسترسی سریع</h5>
|
||||
<ul class="list-unstyled">
|
||||
<li><a href="shop.php" class="text-white-50">فروشگاه</a></li>
|
||||
<li><a href="#" class="text-white-50">درباره ما</a></li>
|
||||
<li><a href="#" 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="about.php" 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>
|
||||
</div>
|
||||
<div class="col-lg-3 col-md-6 mb-4 mb-lg-0">
|
||||
|
||||
270
includes/jdf.php
270
includes/jdf.php
@ -1,24 +1,258 @@
|
||||
<?php
|
||||
|
||||
// Jalali (Shamsi) to Gregorian and vice-versa converter in PHP
|
||||
// Original source: https://github.com/moradin/Jalali/blob/master/jdf.php
|
||||
// Simplified for this project.
|
||||
/*
|
||||
Farsi Jalali (Shamsi) Date and Time Functions
|
||||
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='') {
|
||||
$g_d_m = array(0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334);
|
||||
$jy = ($gy <= 1600) ? 0 : 979;
|
||||
$gy -= ($gy <= 1600) ? 621 : 1600;
|
||||
$gy2 = ($gm > 2) ? ($gy + 1) : $gy;
|
||||
$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));
|
||||
$days %= 1461;
|
||||
$jy += (int)(($days - 1) / 365);
|
||||
if ($days > 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;
|
||||
LICENSE: FREE FOR NON-COMMERCIAL USE
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
*/
|
||||
|
||||
function jdate($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_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);
|
||||
}
|
||||
|
||||
?>
|
||||
107
index.php
107
index.php
@ -1,26 +1,41 @@
|
||||
<?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 = 'صفحه اصلی';
|
||||
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 -->
|
||||
<section class="hero-section vh-100 d-flex align-items-center" style="background: #111;">
|
||||
<!-- Hero Section -->
|
||||
<section class="hero-section vh-100 d-flex align-items-center">
|
||||
<div class="video-background-wrapper">
|
||||
<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">
|
||||
</video>
|
||||
</div>
|
||||
<div class="container position-relative">
|
||||
<h1 class="display-3 fw-bold mb-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>
|
||||
<div class="container position-relative text-center">
|
||||
<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-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>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
|
||||
<!-- Featured Products Section -->
|
||||
<section id="featured-products" class="py-5">
|
||||
<!-- Featured Products Section -->
|
||||
<section id="featured-products" class="py-5">
|
||||
<div class="container">
|
||||
<?php
|
||||
if (isset($_SESSION['success_message'])) {
|
||||
@ -32,37 +47,38 @@ include 'includes/header.php';
|
||||
unset($_SESSION['error_message']);
|
||||
}
|
||||
?>
|
||||
<div class="text-center mb-5" data-aos="fade-up">
|
||||
<h2 class="display-5 fw-bold">مجموعه برگزیده ما</h2>
|
||||
<p class="fs-5">دستچین شده برای سلیقههای خاص.</p>
|
||||
<div class="section-title text-center mb-5" data-aos="fade-up">
|
||||
<h1>مجموعه برگزیده ما</h1>
|
||||
<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
|
||||
require_once 'db/config.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);
|
||||
|
||||
$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>';
|
||||
echo '<div class="col-12"><p class="text-center text-muted">هیچ محصولی برای نمایش وجود ندارد.</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>';
|
||||
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>
|
||||
<?php
|
||||
$delay += 150;
|
||||
}
|
||||
}
|
||||
@ -72,26 +88,31 @@ include 'includes/header.php';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<div class="text-center mt-5" data-aos="fade-up">
|
||||
<a href="shop.php" class="btn btn-outline-gold btn-lg">مشاهده تمام محصولات</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- About Us Section -->
|
||||
<section id="about-us" class="py-5">
|
||||
<div class="text-center mt-5" data-aos="fade-up">
|
||||
<a href="shop.php" class="btn btn-primary">مشاهده تمام محصولات</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- About Us Section -->
|
||||
<section id="about-us" class="py-5">
|
||||
<div class="container">
|
||||
<div class="row align-items-center">
|
||||
<div class="row align-items-center g-5">
|
||||
<div class="col-md-6" data-aos="fade-right">
|
||||
<img src="assets/images/pexels/about-us-34942790.jpg" alt="درباره ما" class="img-fluid rounded-4 shadow-lg">
|
||||
<img src="<?= htmlspecialchars($about_us_image_url) ?>" alt="درباره ما" class="about-us-image img-fluid">
|
||||
</div>
|
||||
<div class="col-md-6 mt-4 mt-md-0 ps-md-5" data-aos="fade-left">
|
||||
<h2 class="display-5 fw-bold">داستان آتیمه</h2>
|
||||
<p class="text-muted fs-5 mt-3">ما در آتیمه، به تلفیق هنر سنتی و طراحی مدرن باور داریم. هر محصول، حاصل ساعتها کار دست هنرمندان ماهر و استفاده از بهترین چرمهای طبیعی است. هدف ما خلق آثاری است که نه تنها یک وسیله، بلکه بخشی از داستان و استایل شما باشند.</p>
|
||||
<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-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>
|
||||
</section>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php include 'includes/footer.php'; ?>
|
||||
30
login.php
30
login.php
@ -14,17 +14,15 @@ $page_title = "ورود یا ثبتنام";
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php echo $page_title; ?> - آتیمه</title>
|
||||
<title><?= $page_title; ?> - آتیمه</title>
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet">
|
||||
<!-- Vazirmatn Font -->
|
||||
<link href="https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css" rel="stylesheet" type="text/css" />
|
||||
<!-- Remixicon -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.css" rel="stylesheet" />
|
||||
<!-- Main Custom CSS (for variables) -->
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<!-- Custom Auth CSS -->
|
||||
<link rel="stylesheet" href="assets/css/auth_style.css?v=<?php echo time(); ?>">
|
||||
<link rel="stylesheet" href="assets/css/dark_luxury.css?v=<?= time(); ?>">
|
||||
</head>
|
||||
<body>
|
||||
<body class="dark-luxury">
|
||||
|
||||
<div class="auth-wrapper">
|
||||
<!-- Left Side: Background Image and Branding -->
|
||||
@ -38,14 +36,15 @@ $page_title = "ورود یا ثبتنام";
|
||||
<!-- Right Side: Form -->
|
||||
<div class="auth-form-wrapper">
|
||||
<div class="auth-form-container">
|
||||
<div class="form-header text-center">
|
||||
<div class="form-header">
|
||||
<div class="logo">آتیمه</div>
|
||||
<h2>ورود یا ثبتنام</h2>
|
||||
<p>برای دریافت کد یکبار مصرف، ایمیل خود را وارد کنید.</p>
|
||||
</div>
|
||||
|
||||
<?php if(isset($_SESSION['flash_message'])): ?>
|
||||
<div class="alert alert-<?php echo $_SESSION['flash_message']['type']; ?> alert-dismissible fade show" role="alert">
|
||||
<?php echo htmlspecialchars($_SESSION['flash_message']['message']); ?>
|
||||
<div class="alert alert-<?= htmlspecialchars($_SESSION['flash_message']['type']); ?> alert-dismissible fade show" role="alert">
|
||||
<?= htmlspecialchars($_SESSION['flash_message']['message']); ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php unset($_SESSION['flash_message']); ?>
|
||||
@ -62,17 +61,8 @@ $page_title = "ورود یا ثبتنام";
|
||||
</div>
|
||||
</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">
|
||||
<p><a href="index.php">بازگشت به صفحه اصلی</a></p>
|
||||
<p><a href="index.php"><i class="ri-arrow-right-line"></i> بازگشت به صفحه اصلی</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
70
product.php
70
product.php
@ -50,18 +50,18 @@ if (!empty($product['colors'])) {
|
||||
<div class="row g-5">
|
||||
<div class="col-lg-6" data-aos="fade-right">
|
||||
<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 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>
|
||||
|
||||
<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>
|
||||
|
||||
<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">
|
||||
<input type="hidden" name="product_id" value="<?php echo $product['id']; ?>">
|
||||
@ -72,22 +72,22 @@ if (!empty($product['colors'])) {
|
||||
<h5 class="mb-3">انتخاب رنگ:</h5>
|
||||
<div class="color-swatches">
|
||||
<?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' : ''; ?>>
|
||||
<label class="btn" for="color_<?php echo $index; ?>" style="background-color: <?php echo htmlspecialchars($color_hex); ?>;" title="<?php echo htmlspecialchars($color_hex); ?>"></label>
|
||||
<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); ?>;"></label>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<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>
|
||||
<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 class="d-grid gap-2">
|
||||
<button type="submit" class="btn btn-primary btn-lg"><i class="fas fa-shopping-cart me-2"></i> افزودن به سبد خرید</button>
|
||||
<div class="d-grid gap-2 add-to-cart-btn">
|
||||
<button type="submit" class="btn btn-primary"><i class="ri-shopping-bag-add-line"></i> افزودن به سبد خرید</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -105,16 +105,17 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
$flash_message = $_SESSION['flash_message'];
|
||||
unset($_SESSION['flash_message']);
|
||||
echo "Swal.fire({
|
||||
title: '" . addslashes($flash_message['message']) . "',
|
||||
icon: '" . $flash_message['type'] . "',
|
||||
title: '".addslashes($flash_message['message'])."',
|
||||
icon: '". $flash_message['type'] ."',
|
||||
toast: true,
|
||||
position: 'top-start',
|
||||
showConfirmButton: false,
|
||||
timer: 4000,
|
||||
timerProgressBar: true,
|
||||
showCloseButton: true,
|
||||
didOpen: (toast) => {
|
||||
toast.onmouseenter = Swal.stopTimer;
|
||||
toast.onmouseleave = Swal.resumeTimer;
|
||||
toast.addEventListener('mouseenter', Swal.stopTimer);
|
||||
toast.addEventListener('mouseleave', Swal.resumeTimer);
|
||||
},
|
||||
customClass: {
|
||||
popup: 'dark-theme-toast'
|
||||
@ -152,46 +153,5 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
});
|
||||
</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'; ?>
|
||||
667
profile.php
667
profile.php
@ -1,8 +1,10 @@
|
||||
<?php
|
||||
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
require_once 'includes/jdf.php'; // For Jalali date conversion
|
||||
|
||||
|
||||
if (!isset($_SESSION['user_id'])) {
|
||||
header('Location: login.php');
|
||||
exit;
|
||||
@ -11,6 +13,128 @@ if (!isset($_SESSION['user_id'])) {
|
||||
$user_id = $_SESSION['user_id'];
|
||||
$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
|
||||
$stmt = $pdo->prepare("SELECT * FROM users WHERE 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]);
|
||||
$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 = 'حساب کاربری';
|
||||
require_once 'includes/header.php';
|
||||
?>
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-color: #f4f7f6;
|
||||
}
|
||||
.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>
|
||||
<?php
|
||||
// Simple router to determine the current page
|
||||
$page = $_GET['page'] ?? 'dashboard';
|
||||
?>
|
||||
|
||||
<div class="container my-5">
|
||||
<div class="profile-container">
|
||||
<!-- Profile Sidebar -->
|
||||
<div class="profile-sidebar">
|
||||
<aside class="profile-sidebar">
|
||||
<div class="user-card">
|
||||
<div class="user-avatar">
|
||||
<?php echo strtoupper(substr($user['first_name'], 0, 1)); ?>
|
||||
<i class="ri-user-fill"></i>
|
||||
</div>
|
||||
<h5><?php echo htmlspecialchars($user['first_name'] . ' ' . $user['last_name']); ?></h5>
|
||||
<p><?php echo htmlspecialchars($user['email']); ?></p>
|
||||
<h5><?= htmlspecialchars(($user['first_name'] ?? '') . ' ' . ($user['last_name'] ?? '')); ?></h5>
|
||||
<p><?= htmlspecialchars($user['email'] ?? ''); ?></p>
|
||||
</div>
|
||||
<ul class="nav flex-column profile-nav" id="profileTab" role="tablist">
|
||||
<ul class="nav flex-column profile-nav">
|
||||
<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>
|
||||
سفارشات من
|
||||
</a>
|
||||
</li>
|
||||
<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>
|
||||
آدرسهای من
|
||||
</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 class="nav-item">
|
||||
<a class="nav-link" href="logout.php">
|
||||
@ -205,101 +211,322 @@ require_once 'includes/header.php';
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</aside>
|
||||
|
||||
<!-- Profile Content -->
|
||||
<div class="profile-content">
|
||||
<div class="tab-content" id="profileTabContent">
|
||||
<!-- Orders Tab -->
|
||||
<div class="tab-pane fade show active" id="orders" role="tabpanel" aria-labelledby="orders-tab">
|
||||
<h3>تاریخچه سفارشات</h3>
|
||||
<?php if (empty($orders)): ?>
|
||||
<div class="alert alert-light text-center">شما هنوز هیچ سفارشی ثبت نکردهاید.</div>
|
||||
<?php else: ?>
|
||||
<div class="accordion order-accordion" id="ordersAccordion">
|
||||
<?php foreach ($orders as $index => $order): ?>
|
||||
<?php
|
||||
$items = json_decode($order['items_json'], true);
|
||||
$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>
|
||||
<main class="profile-content">
|
||||
<?php if (isset($flash_message)): ?>
|
||||
<div class="alert alert-<?= $flash_message_type; ?> alert-dismissible fade show" role="alert">
|
||||
<?= htmlspecialchars($flash_message); ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</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; ?>
|
||||
<?php if ($page === 'dashboard'): ?>
|
||||
<div class="dashboard-welcome">
|
||||
<h3 class="dashboard-title">سلام، <?= htmlspecialchars($user['first_name'] ?? 'کاربر'); ?> عزیز!</h3>
|
||||
<p>به پنل کاربری خود در [نام فروشگاه] خوش آمدید. از اینجا میتوانید آخرین سفارشات خود را مشاهده کرده، اطلاعات حساب خود را مدیریت کنید و آدرسهای خود را بهروزرسانی نمایید.</p>
|
||||
</div>
|
||||
|
||||
<table class="table order-details-table">
|
||||
<tbody>
|
||||
<?php foreach ($items as $item): ?>
|
||||
<!-- Placeholder for summary cards -->
|
||||
<div class="row g-4">
|
||||
<div class="col-md-6">
|
||||
<div class="summary-card">
|
||||
<i class="ri-shopping-cart-2-line"></i>
|
||||
<div class="summary-card-info">
|
||||
<span>تعداد کل سفارشات</span>
|
||||
<strong><?= count($orders); ?></strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="summary-card">
|
||||
<i class="ri-wallet-3-line"></i>
|
||||
<div class="summary-card-info">
|
||||
<span>مجموع خرید شما</span>
|
||||
<strong><?= number_format($total_purchase_amount); ?> تومان</strong>
|
||||
</div>
|
||||
</div>
|
||||
</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>
|
||||
<td><img src="<?php echo htmlspecialchars($item['image_url']); ?>" alt="<?php echo htmlspecialchars($item['name']); ?>"></td>
|
||||
<td>
|
||||
<?php echo htmlspecialchars($item['name']); ?>
|
||||
<?php if (!empty($item['color'])): ?>
|
||||
<br>
|
||||
<small>
|
||||
رنگ:
|
||||
<span class="product-color-swatch" style="background-color: <?php echo htmlspecialchars($item['color']); ?>" title="<?php echo htmlspecialchars($item['color']); ?>"></span>
|
||||
</small>
|
||||
<?php endif; ?>
|
||||
<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>
|
||||
<td><?php echo $item['quantity']; ?> عدد</td>
|
||||
<td class="text-start"><?php echo number_format($item['price']); ?> تومان</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 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>
|
||||
|
||||
<?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>
|
||||
|
||||
<!-- Addresses Tab -->
|
||||
<div class="tab-pane fade" id="addresses" role="tabpanel" aria-labelledby="addresses-tab">
|
||||
<h3>آدرسهای من</h3>
|
||||
<!-- Address management will be implemented here -->
|
||||
<?php elseif ($page === 'account'): ?>
|
||||
<div class="dashboard-card">
|
||||
<h3 class="dashboard-card-header">جزئیات حساب</h3>
|
||||
<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>
|
||||
|
||||
<?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">×</span>
|
||||
<div id="modal-body">
|
||||
<!-- Order details will be injected here by JavaScript -->
|
||||
</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
|
||||
require_once 'includes/footer.php';
|
||||
?>
|
||||
|
||||
|
||||
54
shop.php
54
shop.php
@ -16,42 +16,50 @@ try {
|
||||
?>
|
||||
|
||||
<main class="container py-5">
|
||||
<div class="text-center mb-5" data-aos="fade-down">
|
||||
<h1 class="display-4 fw-bold">مجموعه کامل محصولات</h1>
|
||||
<p class="fs-5">دستسازههایی از چرم طبیعی، با عشق و دقت.</p>
|
||||
<div class="section-title text-center mb-5" data-aos="fade-down">
|
||||
<h1>مجموعه کامل محصولات</h1>
|
||||
<p class="fs-5 text-muted">دستسازههایی از چرم طبیعی، با عشق و دقت.</p>
|
||||
</div>
|
||||
|
||||
<?php if (!empty($db_error)): ?>
|
||||
<div class="alert alert-danger">
|
||||
<?php echo $db_error; ?>
|
||||
<?= $db_error; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (empty($products) && empty($db_error)): ?>
|
||||
<div class="col-12">
|
||||
<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
|
||||
if (!empty($products)) {
|
||||
$delay = 0;
|
||||
foreach ($products as $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=' . htmlspecialchars($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=' . htmlspecialchars($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>';
|
||||
foreach ($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=<?= htmlspecialchars($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=<?= htmlspecialchars($product['id']) ?>">
|
||||
<?= htmlspecialchars($product['name']) ?>
|
||||
</a>
|
||||
</h3>
|
||||
<p class="product-price"><?= number_format($product['price']) ?> تومان</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
$delay = ($delay + 100) % 400; // Stagger animation delay
|
||||
}
|
||||
} else if (empty($db_error)) {
|
||||
echo '<div class="col-12"><p class="text-center text-white-50 fs-4">در حال حاضر محصولی برای نمایش وجود ندارد.</p></div>';
|
||||
}
|
||||
endforeach;
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
|
||||
<?php require_once 'includes/footer.php'; ?>
|
||||
53
terms.php
Normal file
53
terms.php
Normal 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'; ?>
|
||||
112
track_order.php
112
track_order.php
@ -3,83 +3,77 @@ $page_title = "پیگیری سفارش";
|
||||
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>
|
||||
|
||||
|
||||
<div class="track-container">
|
||||
<h1>پیگیری سفارش</h1>
|
||||
<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>
|
||||
<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="form-group">
|
||||
<label for="phone">شماره تلفن</label>
|
||||
<input type="text" id="phone" name="phone" required>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary"><i class="ri-search-line me-2"></i>جستجو</button>
|
||||
</div>
|
||||
<button type="submit" class="btn-track">جستجو</button>
|
||||
</form>
|
||||
<div id="result-message" style="margin-top: 20px; font-weight: bold;"></div>
|
||||
|
||||
<div id="result-message" class="mt-3"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- The Modal -->
|
||||
<div id="order-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<span class="close-btn">×</span>
|
||||
<div id="order-modal" class="order-modal">
|
||||
<div class="order-modal-content">
|
||||
<span class="order-modal-close-btn">×</span>
|
||||
<div id="modal-body">
|
||||
<!-- Order details will be injected here by JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
const form = document.getElementById('track-order-form');
|
||||
const modal = document.getElementById('order-modal');
|
||||
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');
|
||||
|
||||
form.addEventListener('submit', function (e) {
|
||||
form.addEventListener('submit', async function (e) {
|
||||
e.preventDefault();
|
||||
const trackingId = document.getElementById('tracking_id').value;
|
||||
const phone = document.getElementById('phone').value;
|
||||
|
||||
resultMessage.textContent = 'در حال جستجو...';
|
||||
resultMessage.style.color = 'var(--luxury-text-muted)';
|
||||
resultMessage.innerHTML = `<div class="spinner-border spinner-border-sm" role="status"><span class="visually-hidden">Loading...</span></div> در حال جستجو...`;
|
||||
resultMessage.className = 'text-muted';
|
||||
|
||||
fetch('api/get_order_details.php', {
|
||||
try {
|
||||
const response = await fetch('api/get_order_details.php', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
tracking_id: trackingId,
|
||||
phone: phone
|
||||
}),
|
||||
})
|
||||
.then(response => {
|
||||
body: JSON.stringify({ tracking_id: trackingId }),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
throw new Error(`خطای سرور: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.success) {
|
||||
resultMessage.textContent = '';
|
||||
displayOrderDetails(data.order, data.products);
|
||||
modal.style.display = 'block';
|
||||
} else {
|
||||
resultMessage.textContent = data.message;
|
||||
resultMessage.style.color = '#ff6b6b'; // A clearer error color
|
||||
resultMessage.className = 'text-danger fw-bold';
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error:', error);
|
||||
} catch (error) {
|
||||
console.error('Fetch Error:', error);
|
||||
resultMessage.textContent = 'خطا در برقراری ارتباط با سرور.';
|
||||
resultMessage.style.color = '#ff6b6b';
|
||||
});
|
||||
resultMessage.className = 'text-danger fw-bold';
|
||||
}
|
||||
});
|
||||
|
||||
function displayOrderDetails(order, products) {
|
||||
@ -101,51 +95,47 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
products.forEach(p => {
|
||||
productsHtml += `
|
||||
<tr>
|
||||
<td><img src="assets/images/products/${p.image}" alt="${p.name}">${p.name}</td>
|
||||
<td>${p.quantity}</td>
|
||||
<td>${p.color || '-'}</td>
|
||||
<td>${parseInt(p.price).toLocaleString()} تومان</td>
|
||||
<td>${(p.quantity * p.price).toLocaleString()} تومان</td>
|
||||
<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>
|
||||
`;
|
||||
productsHtml += `</tbody></table></div>`;
|
||||
|
||||
modalBody.innerHTML = `
|
||||
<div class="modal-header">
|
||||
<div class="order-modal-header">
|
||||
<h2>جزئیات سفارش</h2>
|
||||
<p>کد رهگیری: ${order.tracking_id}</p>
|
||||
<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.full_name}</p>
|
||||
<p><strong>ایمیل:</strong> ${order.email}</p>
|
||||
<p><strong>تلفن:</strong> ${order.billing_phone}</p>
|
||||
</div>
|
||||
<div class="detail-box">
|
||||
<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.address}</p>
|
||||
<p><strong>آدرس:</strong> ${order.address}</p>
|
||||
</div>
|
||||
${productsHtml}
|
||||
</div>
|
||||
<div class="total-price-container">
|
||||
<p>جمع کل: ${parseInt(order.total_price).toLocaleString()} تومان</p>
|
||||
<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>
|
||||
`;
|
||||
}
|
||||
|
||||
closeBtn.onclick = function () {
|
||||
modal.style.display = 'none';
|
||||
}
|
||||
|
||||
window.onclick = function (event) {
|
||||
closeBtn.onclick = () => modal.style.display = 'none';
|
||||
window.onclick = (event) => {
|
||||
if (event.target == modal) {
|
||||
modal.style.display = 'none';
|
||||
}
|
||||
|
||||
27
verify.php
27
verify.php
@ -15,17 +15,15 @@ $page_title = "تایید کد یکبار مصرف";
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?php echo $page_title; ?> - آتیمه</title>
|
||||
<title><?= $page_title; ?> - آتیمه</title>
|
||||
<!-- Bootstrap CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.rtl.min.css" rel="stylesheet">
|
||||
<!-- Vazirmatn Font -->
|
||||
<link href="https://cdn.jsdelivr.net/gh/rastikerdar/vazirmatn@v33.003/Vazirmatn-font-face.css" rel="stylesheet" type="text/css" />
|
||||
<!-- Remixicon -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/remixicon@4.2.0/fonts/remixicon.css" rel="stylesheet" />
|
||||
<!-- Main Custom CSS (for variables) -->
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<!-- Custom Auth CSS -->
|
||||
<link rel="stylesheet" href="assets/css/auth_style.css?v=<?php echo time(); ?>">
|
||||
<link rel="stylesheet" href="assets/css/dark_luxury.css?v=<?= time(); ?>">
|
||||
</head>
|
||||
<body>
|
||||
<body class="dark-luxury">
|
||||
|
||||
<div class="auth-wrapper">
|
||||
<div class="auth-bg">
|
||||
@ -37,24 +35,25 @@ $page_title = "تایید کد یکبار مصرف";
|
||||
|
||||
<div class="auth-form-wrapper">
|
||||
<div class="auth-form-container">
|
||||
<div class="form-header text-center">
|
||||
<div class="form-header">
|
||||
<div class="logo">آتیمه</div>
|
||||
<h2>تایید کد</h2>
|
||||
<p>کد ۶ رقمی ارسال شده به <strong><?php echo $email_for_display; ?></strong> را وارد کنید.</p>
|
||||
<p>کد ۶ رقمی ارسال شده به <strong class="d-block mt-2"><?= $email_for_display; ?></strong> را وارد کنید.</p>
|
||||
</div>
|
||||
|
||||
<?php if(isset($_SESSION['flash_message'])): ?>
|
||||
<div class="alert alert-<?php echo $_SESSION['flash_message']['type']; ?> alert-dismissible fade show" role="alert">
|
||||
<?php echo htmlspecialchars($_SESSION['flash_message']['message']); ?>
|
||||
<div class="alert alert-<?= htmlspecialchars($_SESSION['flash_message']['type']); ?> alert-dismissible fade show" role="alert">
|
||||
<?= htmlspecialchars($_SESSION['flash_message']['message']); ?>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
<?php unset($_SESSION['flash_message']); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<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">
|
||||
<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 class="d-grid mt-4">
|
||||
@ -63,7 +62,7 @@ $page_title = "تایید کد یکبار مصرف";
|
||||
</form>
|
||||
|
||||
<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>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user