Revert to version 8c7bb7e
This commit is contained in:
parent
fa17a21ac6
commit
ad144cc3b9
194
admin.php
194
admin.php
@ -1,194 +0,0 @@
|
||||
<?php
|
||||
session_start();
|
||||
require_once 'db/config.php';
|
||||
|
||||
// --- Простая аутентификация ---
|
||||
$admin_password = 'admin'; // В реальном проекте используйте более надежный способ хранения пароля
|
||||
|
||||
$is_authenticated = isset($_SESSION['is_authenticated']) && $_SESSION['is_authenticated'] === true;
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['password'])) {
|
||||
if ($_POST['password'] === $admin_password) {
|
||||
$_SESSION['is_authenticated'] = true;
|
||||
header('Location: admin.php');
|
||||
exit;
|
||||
} else {
|
||||
$login_error = 'Неверный пароль';
|
||||
}
|
||||
}
|
||||
|
||||
if (!$is_authenticated) {
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Админ-панель - Вход</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-4">
|
||||
<h1 class="text-center mb-4">Вход в админ-панель</h1>
|
||||
<form method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Пароль</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<?php if (isset($login_error)): ?>
|
||||
<div class="alert alert-danger"><?php echo $login_error; ?></div>
|
||||
<?php endif; ?>
|
||||
<button type="submit" class="btn btn-primary w-100">Войти</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<?php
|
||||
exit;
|
||||
}
|
||||
|
||||
// --- Логика CRUD ---
|
||||
|
||||
// Добавление букета
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['add_bouquet'])) {
|
||||
$name = $_POST['name'];
|
||||
$description = $_POST['description'];
|
||||
$price = $_POST['price'];
|
||||
$image_url = $_POST['image_url'];
|
||||
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare('INSERT INTO bouquets (name, description, price, image_url) VALUES (?, ?, ?, ?)');
|
||||
$stmt->execute([$name, $description, $price, $image_url]);
|
||||
header('Location: admin.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Редактирование букета
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['edit_bouquet'])) {
|
||||
$id = $_POST['id'];
|
||||
$name = $_POST['name'];
|
||||
$description = $_POST['description'];
|
||||
$price = $_POST['price'];
|
||||
$image_url = $_POST['image_url'];
|
||||
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare('UPDATE bouquets SET name = ?, description = ?, price = ?, image_url = ? WHERE id = ?');
|
||||
$stmt->execute([$name, $description, $price, $image_url, $id]);
|
||||
header('Location: admin.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
// Удаление букета
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['delete_bouquet'])) {
|
||||
$id = $_POST['id'];
|
||||
$pdo = db();
|
||||
$stmt = $pdo->prepare('DELETE FROM bouquets WHERE id = ?');
|
||||
$stmt->execute([$id]);
|
||||
header('Location: admin.php');
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
// --- Получение данных ---
|
||||
$pdo = db();
|
||||
$bouquets = $pdo->query('SELECT * FROM bouquets ORDER BY id DESC')->fetchAll();
|
||||
|
||||
$edit_bouquet_data = null;
|
||||
if (isset($_GET['edit'])) {
|
||||
$id = $_GET['edit'];
|
||||
$stmt = $pdo->prepare('SELECT * FROM bouquets WHERE id = ?');
|
||||
$stmt->execute([$id]);
|
||||
$edit_bouquet_data = $stmt->fetch();
|
||||
}
|
||||
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Админ-панель</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="admin.php">Админ-панель</a>
|
||||
<a href="index.php" class="btn btn-outline-light">На сайт</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
<!-- Форма добавления/редактирования -->
|
||||
<div class="col-md-4">
|
||||
<h3><?php echo $edit_bouquet_data ? 'Редактировать букет' : 'Добавить букет'; ?></h3>
|
||||
<form method="POST">
|
||||
<?php if ($edit_bouquet_data): ?>
|
||||
<input type="hidden" name="id" value="<?php echo $edit_bouquet_data['id']; ?>">
|
||||
<?php endif; ?>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Название</label>
|
||||
<input type="text" class="form-control" id="name" name="name" value="<?php echo htmlspecialchars($edit_bouquet_data['name'] ?? ''); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="description" class="form-label">Описание</label>
|
||||
<textarea class="form-control" id="description" name="description" rows="3" required><?php echo htmlspecialchars($edit_bouquet_data['description'] ?? ''); ?></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="price" class="form-label">Цена</label>
|
||||
<input type="number" step="0.01" class="form-control" id="price" name="price" value="<?php echo htmlspecialchars($edit_bouquet_data['price'] ?? ''); ?>" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="image_url" class="form-label">URL изображения</label>
|
||||
<input type="text" class="form-control" id="image_url" name="image_url" value="<?php echo htmlspecialchars($edit_bouquet_data['image_url'] ?? ''); ?>" required>
|
||||
</div>
|
||||
<?php if ($edit_bouquet_data): ?>
|
||||
<button type="submit" name="edit_bouquet" class="btn btn-primary">Сохранить</button>
|
||||
<a href="admin.php" class="btn btn-secondary">Отмена</a>
|
||||
<?php else: ?>
|
||||
<button type="submit" name="add_bouquet" class="btn btn-success">Добавить</button>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<!-- Список букетов -->
|
||||
<div class="col-md-8">
|
||||
<h3>Список букетов</h3>
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Фото</th>
|
||||
<th>Название</th>
|
||||
<th>Цена</th>
|
||||
<th>Действия</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($bouquets as $bouquet): ?>
|
||||
<tr>
|
||||
<td><?php echo $bouquet['id']; ?></td>
|
||||
<td><img src="<?php echo htmlspecialchars($bouquet['image_url']); ?>" alt="" width="50"></td>
|
||||
<td><?php echo htmlspecialchars($bouquet['name']); ?></td>
|
||||
<td><?php echo htmlspecialchars($bouquet['price']); ?></td>
|
||||
<td>
|
||||
<a href="admin.php?edit=<?php echo $bouquet['id']; ?>" class="btn btn-sm btn-primary">Ред.</a>
|
||||
<form method="POST" style="display:inline-block;" onsubmit="return confirm('Вы уверены?');">
|
||||
<input type="hidden" name="id" value="<?php echo $bouquet['id']; ?>">
|
||||
<button type="submit" name="delete_bouquet" class="btn btn-sm btn-danger">Удал.</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
5
admin/config.php
Normal file
5
admin/config.php
Normal file
@ -0,0 +1,5 @@
|
||||
<?php
|
||||
// Admin credentials
|
||||
define('ADMIN_USER', 'admin');
|
||||
define('ADMIN_PASS', 'password');
|
||||
?>
|
||||
45
admin/index.php
Normal file
45
admin/index.php
Normal file
@ -0,0 +1,45 @@
|
||||
<?php
|
||||
session_start();
|
||||
if (isset($_SESSION['loggedin']) && $_SESSION['loggedin'] === true) {
|
||||
header('Location: dashboard.php');
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Admin Login</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-lg-4">
|
||||
<div class="card mt-5">
|
||||
<div class="card-body">
|
||||
<h3 class="card-title text-center">Admin Login</h3>
|
||||
<form action="auth.php" method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="username" class="form-label">Username</label>
|
||||
<input type="text" class="form-control" id="username" name="username" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="password" class="form-label">Password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" required>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100">Login</button>
|
||||
<?php if (isset($_GET['error'])): ?>
|
||||
<div class="alert alert-danger mt-3" role="alert">
|
||||
Invalid credentials.
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,31 +0,0 @@
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `bouquets` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`description` TEXT,
|
||||
`price` DECIMAL(10, 2) NOT NULL,
|
||||
`image_url` VARCHAR(255)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `orders` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`customer_name` VARCHAR(255) NOT NULL,
|
||||
`bouquet_id` INT NOT NULL,
|
||||
`phone` VARCHAR(50) NOT NULL,
|
||||
`address` TEXT NOT NULL,
|
||||
`delivery_date` DATE NOT NULL,
|
||||
`order_date` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`bouquet_id`) REFERENCES `bouquets`(`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS `migrations` (
|
||||
`migration` VARCHAR(255) NOT NULL,
|
||||
PRIMARY KEY (`migration`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- Insert some sample bouquets
|
||||
INSERT INTO `bouquets` (`name`, `description`, `price`, `image_url`) VALUES
|
||||
('Classic Rose Bouquet', 'A beautiful bouquet of one dozen red roses.', 45.99, 'https://picsum.photos/seed/rose-bouquet/800/600'),
|
||||
('Sunny Day Bouquet', 'A cheerful mix of sunflowers and white daisies.', 35.50, 'https://picsum.photos/seed/sunflower-bouquet/800/600'),
|
||||
('Elegant Lily Bouquet', 'Stunning white lilies for any occasion.', 55.00, 'https://picsum.photos/seed/lily-bouquet/800/600'),
|
||||
('Vibrant Tulip Mix', 'A colorful assortment of fresh tulips.', 42.75, 'https://picsum.photos/seed/tulip-bouquet/800/600');
|
||||
@ -1 +0,0 @@
|
||||
ALTER TABLE `orders` ADD COLUMN `note` TEXT NULL DEFAULT NULL AFTER `delivery_date`;
|
||||
516
index.php
516
index.php
@ -1,444 +1,190 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
ini_set('display_errors', 1);
|
||||
ini_set('display_startup_errors', 1);
|
||||
error_reporting(E_ALL);
|
||||
require_once 'db/config.php';
|
||||
|
||||
// --- DB MIGRATIONS ---
|
||||
try {
|
||||
$pdo = db();
|
||||
$pdo->exec('CREATE TABLE IF NOT EXISTS `migrations` (`migration` VARCHAR(255) NOT NULL, PRIMARY KEY (`migration`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;');
|
||||
$executed_migrations_stmt = $pdo->query('SELECT migration FROM migrations');
|
||||
$executed_migrations = $executed_migrations_stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||
$migration_files = glob('db/migrations/*.sql');
|
||||
sort($migration_files);
|
||||
foreach ($migration_files as $file) {
|
||||
$migration_name = basename($file);
|
||||
if (!in_array($migration_name, $executed_migrations)) {
|
||||
$sql = file_get_contents($file);
|
||||
$pdo->exec($sql);
|
||||
$stmt = $pdo->prepare('INSERT INTO migrations (migration) VALUES (?)');
|
||||
$stmt->execute([$migration_name]);
|
||||
}
|
||||
}
|
||||
} catch (PDOException $e) {
|
||||
error_log('Migration Error: ' . $e->getMessage());
|
||||
}
|
||||
// --- END DB MIGRATIONS ---
|
||||
|
||||
$p_title = 'Flower Shop';
|
||||
$p_description = 'Beautiful bouquets for any occasion.';
|
||||
|
||||
try {
|
||||
$pdo = db();
|
||||
$stmt = $pdo->query('SELECT * FROM bouquets ORDER BY name ASC');
|
||||
$bouquets = $stmt->fetchAll();
|
||||
} catch (PDOException $e) {
|
||||
error_log('DB Error: ' . $e->getMessage());
|
||||
$bouquets = [];
|
||||
$db_error = 'Sorry, we were unable to load the bouquets at this time. Please try again later.';
|
||||
}
|
||||
|
||||
$status_message = '';
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$customer_name = trim($_POST['name'] ?? '');
|
||||
$bouquet_id = (int)($_POST['bouquet'] ?? 0);
|
||||
$phone = trim($_POST['phone'] ?? '');
|
||||
$address = trim($_POST['address'] ?? '');
|
||||
$delivery_date = trim($_POST['delivery_date'] ?? '');
|
||||
$note = trim($_POST['note'] ?? '');
|
||||
|
||||
if (empty($customer_name) || empty($bouquet_id) || empty($phone) || empty($address) || empty($delivery_date)) {
|
||||
$status_message = '<div class="alert alert-danger">Please fill in all required fields.</div>';
|
||||
} else {
|
||||
try {
|
||||
$sql = "INSERT INTO orders (customer_name, bouquet_id, phone, address, delivery_date, note) VALUES (:name, :bouquet, :phone, :address, :date, :note)";
|
||||
$stmt = $pdo->prepare($sql);
|
||||
$stmt->execute([
|
||||
':name' => $customer_name,
|
||||
':bouquet' => $bouquet_id,
|
||||
':phone' => $phone,
|
||||
':address' => $address,
|
||||
':date' => $delivery_date,
|
||||
':note' => $note
|
||||
]);
|
||||
$status_message = '<div class="alert alert-success">Thank you for your order! We will contact you shortly.</div>';
|
||||
} catch (PDOException $e) {
|
||||
error_log('Order submission error: ' . $e->getMessage());
|
||||
$status_message = '<div class="alert alert-danger">We could not process your order. Please try again.</div>';
|
||||
}
|
||||
// Handle form submission
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['customer_name'])) {
|
||||
try {
|
||||
$pdoconnection = db();
|
||||
$statement = $pdoconnection->prepare(
|
||||
'INSERT INTO orders (customer_name, phone, address, bouquet_id) VALUES (:customer_name, :phone, :address, :bouquet_id)'
|
||||
);
|
||||
$statement->execute([
|
||||
':customer_name' => $_POST['customer_name'],
|
||||
':phone' => $_POST['phone'],
|
||||
':address' => $_POST['address'],
|
||||
':bouquet_id' => (int)$_POST['bouquet_id'],
|
||||
]);
|
||||
// Redirect or show success message
|
||||
header('Location: ' . $_SERVER['PHP_SELF'] . '?order=success');
|
||||
exit;
|
||||
} catch (PDOException $e) {
|
||||
die("Order placement failed: " . $e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$pdoconnection = db();
|
||||
$statement = $pdoconnection->query('SELECT id, name, description, price, image_url FROM bouquets');
|
||||
$bouquets = $statement->fetchAll();
|
||||
} catch (PDOException $e) {
|
||||
die("Database error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="description" content="<?= htmlspecialchars($p_description) ?>">
|
||||
<title><?= htmlspecialchars($p_title) ?></title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Flower Shop</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500&family=Playfair+Display:wght@700&display=swap" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;700&family=Playfair+Display:wght@700&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
:root {
|
||||
--bg-color: #ffffff;
|
||||
--text-color: #000000;
|
||||
--border-color: #eeeeee;
|
||||
--body-font: 'Montserrat', sans-serif;
|
||||
--title-font: 'Playfair Display', serif;
|
||||
}
|
||||
body {
|
||||
background-color: var(--bg-color);
|
||||
font-family: var(--body-font);
|
||||
color: var(--text-color);
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
background-color: #fdf2e9; /* Light pinkish-beige */
|
||||
}
|
||||
h1, h2, h3, .navbar-brand {
|
||||
font-family: 'Playfair Display', serif;
|
||||
}
|
||||
.navbar {
|
||||
font-family: var(--body-font);
|
||||
background-color: var(--bg-color) !important;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
box-shadow: none;
|
||||
}
|
||||
.navbar-brand {
|
||||
font-family: var(--title-font);
|
||||
font-weight: 700;
|
||||
font-size: 1.75rem;
|
||||
color: var(--text-color) !important;
|
||||
}
|
||||
.nav-link {
|
||||
font-weight: 500;
|
||||
color: var(--text-color) !important;
|
||||
text-transform: uppercase;
|
||||
font-size: 0.9rem;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
.header-icons .nav-link {
|
||||
font-size: 1.2rem;
|
||||
background-color: #fdf2e9;
|
||||
}
|
||||
.hero {
|
||||
position: relative;
|
||||
padding: 8rem 2rem;
|
||||
background-color: #fadadd; /* Lighter pink */
|
||||
padding: 4rem 0;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
background: url('assets/pasted-20250911-145034-379d8f9f.jpg') no-repeat center center;
|
||||
background-size: cover;
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
}
|
||||
.hero::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
z-index: 1;
|
||||
}
|
||||
.hero .container {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
.hero h1, .section-title, .card-title {
|
||||
font-family: var(--title-font);
|
||||
font-weight: 700;
|
||||
}
|
||||
.hero h1 {
|
||||
font-family: var(--title-font);
|
||||
font-size: 4.5rem;
|
||||
color: #ffffff;
|
||||
text-shadow: none;
|
||||
margin: 0 2rem;
|
||||
}
|
||||
.hero .lead {
|
||||
color: #ffffff;
|
||||
text-shadow: none;
|
||||
font-size: 1rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
.hero-arrow {
|
||||
color: #fff;
|
||||
font-size: 2.5rem;
|
||||
text-decoration: none;
|
||||
opacity: 0.8;
|
||||
}
|
||||
.section-title {
|
||||
color: var(--text-color);
|
||||
font-size: 2rem;
|
||||
}
|
||||
.btn-primary {
|
||||
background-color: var(--text-color);
|
||||
border-color: var(--text-color);
|
||||
color: var(--bg-color);
|
||||
font-weight: 700;
|
||||
padding: 0.75rem 1.5rem;
|
||||
transition: none;
|
||||
border-radius: 0;
|
||||
background-color: #e67e22; /* Coral accent */
|
||||
border-color: #e67e22;
|
||||
}
|
||||
.btn-primary:hover {
|
||||
background-color: #333333;
|
||||
border-color: #333333;
|
||||
background-color: #d35400;
|
||||
border-color: #d35400;
|
||||
}
|
||||
.form-control, .form-select {
|
||||
border-radius: 0;
|
||||
}
|
||||
.form-control:focus, .form-select:focus {
|
||||
border-color: var(--text-color);
|
||||
box-shadow: 0 0 0 0.2rem rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
footer {
|
||||
background-color: var(--bg-color);
|
||||
color: var(--text-color);
|
||||
padding: 2rem 0;
|
||||
margin-top: 4rem;
|
||||
border-top: 1px solid var(--border-color);
|
||||
}
|
||||
.bouquets-list .row {
|
||||
gap: 3rem 0;
|
||||
}
|
||||
.bouquet-card {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch;
|
||||
.card {
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
gap: 2rem;
|
||||
margin-bottom: 2rem !important;
|
||||
transition: transform .2s;
|
||||
}
|
||||
.bouquet-card-reverse {
|
||||
flex-direction: row-reverse;
|
||||
.card:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
.bouquet-card .card-image {
|
||||
flex: 1 1 50%;
|
||||
}
|
||||
.bouquet-card .card-image img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
max-height: 500px;
|
||||
.card-img-top {
|
||||
height: 300px;
|
||||
object-fit: cover;
|
||||
}
|
||||
.bouquet-card .card-title-container {
|
||||
flex: 0 0 50px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 300px;
|
||||
}
|
||||
.bouquet-card .card-title-vertical {
|
||||
display: flex;
|
||||
flex-direction: column-reverse;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
.bouquet-card .card-title-vertical .dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: #000;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.bouquet-card .card-title-vertical .line {
|
||||
width: 1px;
|
||||
height: 70px;
|
||||
background-color: #000;
|
||||
}
|
||||
.bouquet-card .card-title {
|
||||
writing-mode: vertical-rl;
|
||||
transform: rotate(180deg);
|
||||
font-family: 'Poppins', sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 1.5rem;
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
}
|
||||
.bouquet-card .card-body {
|
||||
flex: 1 1 45%;
|
||||
padding: 1rem;
|
||||
}
|
||||
.bouquet-card .card-text {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
font-size: 1rem;
|
||||
color: #6c757d;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
.bouquet-card .btn-outline-dark {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
font-weight: 500;
|
||||
font-size: 1rem;
|
||||
padding: 0.75rem 2rem;
|
||||
border-radius: 50px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.bouquet-card .price {
|
||||
font-family: 'Poppins', sans-serif;
|
||||
font-size: 1.75rem;
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
}
|
||||
.section-title-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
justify-content: center;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
.decorator-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background-color: var(--text-color);
|
||||
border-radius: 50%;
|
||||
}
|
||||
.decorator-line {
|
||||
width: 40px;
|
||||
height: 1px;
|
||||
background-color: var(--text-color);
|
||||
footer {
|
||||
background-color: #343a40;
|
||||
color: white;
|
||||
padding: 2rem 0;
|
||||
}
|
||||
</style>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<nav class="navbar navbar-expand-lg navbar-light sticky-top">
|
||||
<!-- Navigation -->
|
||||
<nav class="navbar navbar-expand-lg navbar-light">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="#">Fleur</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<a class="navbar-brand" href="#">Flower Shop</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav mx-auto">
|
||||
<li class="nav-item"><a class="nav-link" href="#">Home</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#bouquets">Bouquets</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#order">Order</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/admin.php">Admin</a></li>
|
||||
</ul>
|
||||
<ul class="navbar-nav header-icons">
|
||||
<li class="nav-item"><a class="nav-link" href="#">🔍</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#">👤</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#">👜</a></li>
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<li class="nav-item"><a class="nav-link" href="#bouquets">Букеты</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="#order">Заказать</a></li>
|
||||
<li class="nav-item"><a class="nav-link" href="/admin">Админ-панель</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Hero Section -->
|
||||
<header class="hero">
|
||||
<div class="container">
|
||||
<a href="#" class="hero-arrow">⟵</a>
|
||||
<div>
|
||||
<h1 class="display-3">The Art of Simplicity</h1>
|
||||
<p class="lead">Handmade Bouquets</p>
|
||||
</div>
|
||||
<a href="#" class="hero-arrow">⟶</a>
|
||||
<h1>Flower Shop</h1>
|
||||
<p class="lead">Свежие букеты для любого повода с доставкой на дом.</p>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main class="container-fluid my-5">
|
||||
<section id="bouquets" class="my-5">
|
||||
<div class="section-title-container">
|
||||
<div class="decorator-dot"></div>
|
||||
<div class="decorator-line"></div>
|
||||
<h2 class="section-title mb-0">Our Bouquets</h2>
|
||||
</div>
|
||||
<?php if (!empty($db_error)): ?>
|
||||
<div class="alert alert-danger"><?= htmlspecialchars($db_error) ?></div>
|
||||
<?php elseif (empty($bouquets)): ?>
|
||||
<div class="alert alert-info">Bouquets will be available soon.</div>
|
||||
<?php else: ?>
|
||||
<div class="bouquets-list">
|
||||
<div class="row">
|
||||
<?php
|
||||
$image_urls = [
|
||||
'https://media-api.xogrp.com/images/1edfbffe-ca90-4381-a78f-d8c9d9485765~rs_768.h-cr_0.209.1094.1303',
|
||||
'https://m.media-amazon.com/images/I/71fpxULF4xL._UF894,1000_QL80_.jpg',
|
||||
'https://www.odealarose.com/blog/wp-content/uploads/2025/04/flowers-with-eucalyptus-768x512.jpg',
|
||||
'https://www.lyttonrosebotanical.com/cdn/shop/files/rn-image_picker_lib_temp_a4ee8946-d08b-47d3-a6d9-0e22b4607417.jpg?v=1733076272&width=1946'
|
||||
];
|
||||
foreach ($bouquets as $key => $bouquet):
|
||||
$image_url = $image_urls[$key % count($image_urls)];
|
||||
?>
|
||||
<div class="col-12">
|
||||
<div class="card bouquet-card <?= ($key % 2 !== 0) ? 'bouquet-card-reverse' : '' ?>">
|
||||
<div class="card-image">
|
||||
<img src="<?= $image_url ?>" alt="<?= htmlspecialchars($bouquet['name']) ?>">
|
||||
</div>
|
||||
<div class="card-title-container">
|
||||
<div class="card-title-vertical">
|
||||
<h5 class="card-title"><?= htmlspecialchars($bouquet['name']) ?></h5>
|
||||
<div class="line"></div>
|
||||
<div class="dot"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body d-flex flex-column <?= ($key % 2 !== 0) ? 'text-lg-end' : '' ?>">
|
||||
<div class="mt-auto">
|
||||
<p class="card-text mb-4"><?= htmlspecialchars($bouquet['description']) ?></p>
|
||||
<div class="price mb-4">$<?= htmlspecialchars(number_format((float)$bouquet['price'], 2)) ?></div>
|
||||
<a href="#order" class="btn btn-outline-dark">Order</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Success Message -->
|
||||
<?php if (isset($_GET['order']) && $_GET['order'] === 'success'): ?>
|
||||
<div class="container mt-4">
|
||||
<div class="alert alert-success text-center" role="alert">
|
||||
Спасибо за ваш заказ! Мы скоро с вами свяжемся.
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<!-- Bouquets Section -->
|
||||
<section id="bouquets" class="py-5">
|
||||
<div class="container">
|
||||
<h2 class="text-center mb-4">Наши Букеты</h2>
|
||||
<div class="row">
|
||||
<?php if (empty($bouquets)): ?>
|
||||
<p class="text-center">Букеты скоро появятся!</p>
|
||||
<?php else: ?>
|
||||
<?php foreach ($bouquets as $bouquet): ?>
|
||||
<div class="col-md-4 mb-4">
|
||||
<div class="card h-100">
|
||||
<img src="<?= htmlspecialchars($bouquet['image_url']) ?>" class="card-img-top" alt="<?= htmlspecialchars($bouquet['name']) ?>">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title"><?= htmlspecialchars($bouquet['name']) ?></h5>
|
||||
<p class="card-text"><?= htmlspecialchars($bouquet['description']) ?></p>
|
||||
<p class="card-text"><strong><?= htmlspecialchars($bouquet['price']) ?> руб.</strong></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="order" class="my-5 pt-5">
|
||||
<h2 class="section-title text-center mb-4">Place an Order</h2>
|
||||
<!-- Order Form Section -->
|
||||
<section id="order" class="py-5 bg-light">
|
||||
<div class="container">
|
||||
<h2 class="text-center mb-4">Оформить Заказ</h2>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<?= $status_message ?>
|
||||
<div class="card p-4 shadow-sm border-0">
|
||||
<form action="/#order" method="POST" novalidate>
|
||||
<div class="mb-3">
|
||||
<label for="name" class="form-label">Your Name</label>
|
||||
<input type="text" class="form-control" id="name" name="name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="bouquet" class="form-label">Select a Bouquet</label>
|
||||
<select class="form-select" id="bouquet" name="bouquet" required>
|
||||
<option value="" disabled selected>Choose...</option>
|
||||
<?php foreach ($bouquets as $bouquet): ?>
|
||||
<option value="<?= $bouquet['id'] ?>"><?= htmlspecialchars($bouquet['name']) ?> - $<?= htmlspecialchars(number_format((float)$bouquet['price'], 2)) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="phone" class="form-label">Phone Number</label>
|
||||
<input type="tel" class="form-control" id="phone" name="phone" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="address" class="form-label">Delivery Address</label>
|
||||
<textarea class="form-control" id="address" name="address" rows="3" required></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="delivery_date" class="form-label">Delivery Date</label>
|
||||
<input type="date" class="form-control" id="delivery_date" name="delivery_date" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="note" class="form-label">Note (optional)</label>
|
||||
<textarea class="form-control" id="note" name="note" rows="3" maxlength="300"></textarea>
|
||||
</div>
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary btn-lg">Submit Order</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<form action="index.php" method="POST">
|
||||
<div class="mb-3">
|
||||
<label for="customer_name" class="form-label">Ваше Имя</label>
|
||||
<input type="text" class="form-control" id="customer_name" name="customer_name" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="phone" class="form-label">Телефон</label>
|
||||
<input type="tel" class="form-control" id="phone" name="phone" required>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="address" class="form-label">Адрес Доставки</label>
|
||||
<textarea class="form-control" id="address" name="address" rows="3" required></textarea>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="bouquet_id" class="form-label">Выберите Букет</label>
|
||||
<select class="form-select" id="bouquet_id" name="bouquet_id" required>
|
||||
<?php foreach ($bouquets as $bouquet): ?>
|
||||
<option value="<?= $bouquet['id'] ?>"><?= htmlspecialchars($bouquet['name']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" class="btn btn-primary w-100">Заказать</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer class="text-center">
|
||||
<div class="container">
|
||||
<p>© <?= date('Y') ?> Fleur. All rights reserved.</p>
|
||||
<p>© <?= date('Y') ?> Flowera. Все права защищены.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user