681 lines
30 KiB
HTML
681 lines
30 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>Школьный магазинчик</title>
|
||
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🏪</text></svg>">
|
||
<style>
|
||
:root{--ink:#0F1218;--cyan:#00E5FF;--cyan-50:#E8FCFF;--white:#fff;--gray-500:#5B6573;--gray-100:#F2F4F7;--green:#25D366;--red:#FF4444}
|
||
*{box-sizing:border-box;margin:0;padding:0}
|
||
body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,sans-serif;color:var(--ink);background:var(--white)}
|
||
.container{max-width:1140px;margin:0 auto;padding:80px 24px}
|
||
.hero{background:var(--ink);color:var(--white);padding:60px 24px}
|
||
.hero h1{font-size:48px;font-weight:800;line-height:1.05;margin-bottom:16px}
|
||
.hero p{font-size:20px;color:#9aa3b2;max-width:600px}
|
||
.section{padding:60px 24px}
|
||
.section h2{font-size:36px;font-weight:700;margin-bottom:32px;text-align:center}
|
||
.grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:24px}
|
||
.card{background:var(--gray-100);border-radius:16px;overflow:hidden;transition:transform .2s}
|
||
.card:hover{transform:translateY(-4px)}
|
||
.card img{width:100%;height:200px;object-fit:cover}
|
||
.card-body{padding:20px}
|
||
.card-title{font-size:20px;font-weight:700;margin-bottom:8px}
|
||
.card-price{font-size:24px;font-weight:800;color:var(--ink);margin-bottom:12px}
|
||
.card-cat{display:inline-block;background:var(--cyan-50);color:var(--ink);padding:4px 12px;border-radius:20px;font-size:14px;font-weight:600;margin-bottom:12px}
|
||
.status-badge{display:inline-block;padding:4px 12px;border-radius:20px;font-size:13px;font-weight:600;margin-left:8px}
|
||
.status-paid{background:#d4edda;color:#155724}
|
||
.status-waiting{background:#fff3cd;color:#856404}
|
||
.btn{display:inline-block;background:var(--cyan);color:var(--ink);padding:14px 28px;border-radius:8px;font-weight:700;text-decoration:none;border:none;cursor:pointer}
|
||
.btn:hover{opacity:0.9}
|
||
.btn-green{background:var(--green);color:#fff}
|
||
.btn-red{background:var(--red);color:#fff}
|
||
.nav{background:var(--ink);padding:16px 24px;position:sticky;top:0;z-index:100}
|
||
.nav-inner{max-width:1140px;margin:0 auto;display:flex;justify-content:space-between;align-items:center}
|
||
.nav a{color:var(--white);text-decoration:none;font-weight:600;margin-left:24px}
|
||
.nav a.active{color:var(--cyan)}
|
||
.admin-panel{background:var(--cyan-50);padding:32px;border-radius:16px;margin-bottom:40px}
|
||
.code-display{background:var(--ink);color:var(--cyan);padding:24px;border-radius:12px;text-align:center;font-size:32px;font-weight:800;letter-spacing:4px;margin:20px 0}
|
||
.form-group{margin-bottom:20px}
|
||
.form-group label{display:block;font-weight:600;margin-bottom:8px}
|
||
.form-group input,.form-group select,.form-group textarea{width:100%;padding:12px;border:1px solid #ddd;border-radius:8px;font-size:16px}
|
||
.filter-bar{display:flex;gap:12px;flex-wrap:wrap;margin-bottom:32px;justify-content:center}
|
||
.filter-btn{padding:10px 20px;border:2px solid var(--gray-100);background:var(--white);border-radius:20px;cursor:pointer;font-weight:600}
|
||
.filter-btn.active{border-color:var(--cyan);background:var(--cyan-50)}
|
||
.empty{text-align:center;padding:60px 24px;color:var(--gray-500)}
|
||
.modal{display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);z-index:1000;align-items:center;justify-content:center}
|
||
.modal.on{display:flex}
|
||
.modal-content{background:var(--white);padding:32px;border-radius:16px;max-width:400px;width:90%}
|
||
.modal h3{margin-bottom:20px}
|
||
.password-input{margin-bottom:16px}
|
||
@media (max-width:640px){.hero h1{font-size:32px}.section h2{font-size:28px}.container{padding:40px 16px}}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<nav class="nav">
|
||
<div class="nav-inner">
|
||
<strong style="color:var(--white);font-size:20px;">🏪 Школьный магазин</strong>
|
||
<div>
|
||
<a href="#" id="nav-home" class="active">Товары</a>
|
||
<a href="#" id="nav-admin">Админка</a>
|
||
</div>
|
||
</div>
|
||
</nav>
|
||
|
||
<section class="hero">
|
||
<div class="container">
|
||
<h1>Добро пожаловать!</h1>
|
||
<p>Вкусные перекусы, школьные принадлежности и приятные мелочи по доступным ценам</p>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="section" id="shop-section">
|
||
<div class="container">
|
||
<h2>🛒 Наши товары</h2>
|
||
|
||
<div class="filter-bar" id="filters">
|
||
<button class="filter-btn active" data-cat="all">Все</button>
|
||
<button class="filter-btn" data-cat="еда">🍫 Еда</button>
|
||
<button class="filter-btn" data-cat="напитки">🥤 Напитки</button>
|
||
<button class="filter-btn" data-cat="школа">✏️ Школа</button>
|
||
<button class="filter-btn" data-cat="разное">🎁 Разное</button>
|
||
</div>
|
||
|
||
<div class="grid" id="products-grid"></div>
|
||
<div class="empty" id="empty-msg" style="display:none">Товаров пока нет 😔</div>
|
||
|
||
<div style="text-align:center;margin-top:40px;display:flex;gap:16px;justify-content:center;flex-wrap:wrap">
|
||
<button class="btn" onclick="openParentCodeModal()" style="background:var(--green);color:#fff">👨👩👧 Получить код родителя</button>
|
||
<button class="btn" onclick="showPage('admin');setTimeout(() => document.getElementById('nav-admin').click(), 100)" style="background:var(--ink);color:#fff">➕ Добавить товар</button>
|
||
<button class="btn" onclick="openPaymentModal()" style="background:#FF5500;color:#fff">💳 Родителям: оплатить онлайн</button>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="section" id="admin-section" style="display:none">
|
||
<div class="container">
|
||
<h2>⚙️ Админка</h2>
|
||
|
||
<div class="admin-panel" id="admin-login">
|
||
<h3>🔐 Вход для владельца</h3>
|
||
<p style="margin-bottom:20px">Введите пароль для управления товарами</p>
|
||
<div class="form-group">
|
||
<input type="password" id="admin-password" class="password-input" placeholder="Пароль">
|
||
</div>
|
||
<button class="btn" onclick="checkPassword()">Войти</button>
|
||
</div>
|
||
|
||
<div id="admin-content" style="display:none">
|
||
<div class="admin-panel">
|
||
<h3>👨👩👧 Родительский контроль</h3>
|
||
<p style="margin-bottom:20px">Дети покупают только с кодом от родителей</p>
|
||
|
||
<form id="parent-form" style="margin-bottom:32px">
|
||
<div class="form-group">
|
||
<label>Имя родителя</label>
|
||
<input type="text" id="parent-name" placeholder="Иванова Мария" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Телефон</label>
|
||
<input type="tel" id="parent-phone" placeholder="+7 777 123 45 67" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Лимит на день (₸)</label>
|
||
<input type="number" id="parent-limit" placeholder="1000" required>
|
||
</div>
|
||
<button type="submit" class="btn btn-green">Зарегистрировать родителя</button>
|
||
</form>
|
||
|
||
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;flex-wrap:wrap;gap:12px">
|
||
<h4 style="margin:0">Зарегистрированные родители:</h4>
|
||
<button class="btn" onclick="printCodes()" style="padding:8px 16px;font-size:14px">🖨️ Распечатать коды</button>
|
||
</div>
|
||
<div id="parents-list" style="margin-bottom:32px"></div>
|
||
</div>
|
||
|
||
<div class="admin-panel">
|
||
<h3>📋 Предоплаченные заказы (онлайн оплата)</h3>
|
||
<p style="margin-bottom:16px;color:var(--gray-500)">Родитель оплатил онлайн → ребёнок показывает код → забирает товар</p>
|
||
<div id="orders-list" style="margin-top:16px"></div>
|
||
</div>
|
||
|
||
<div class="admin-panel">
|
||
<h3>➕ Добавить товар</h3>
|
||
<form id="add-form">
|
||
<div class="form-group">
|
||
<label>Название</label>
|
||
<input type="text" id="prod-name" placeholder="Например: Snickers" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Цена (₸)</label>
|
||
<input type="number" id="prod-price" placeholder="150" required>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Категория</label>
|
||
<select id="prod-cat">
|
||
<option value="еда">🍫 Еда</option>
|
||
<option value="напитки">🥤 Напитки</option>
|
||
<option value="школа">✏️ Школа</option>
|
||
<option value="разное">🎁 Разное</option>
|
||
</select>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Описание</label>
|
||
<textarea id="prod-desc" rows="3" placeholder="Короткое описание"></textarea>
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Картинка (ссылка или оставь пустым)</label>
|
||
<input type="text" id="prod-img" placeholder="https://...">
|
||
</div>
|
||
<button type="submit" class="btn btn-green">Добавить товар</button>
|
||
</form>
|
||
</div>
|
||
|
||
<div class="admin-panel">
|
||
<h3>📊 История покупок</h3>
|
||
<div id="purchases-list" style="margin-top:16px"></div>
|
||
</div>
|
||
|
||
<h3>📦 Все товары</h3>
|
||
<div class="grid" id="admin-grid"></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<div class="modal" id="login-modal">
|
||
<div class="modal-content">
|
||
<h3>🔐 Введите пароль</h3>
|
||
<input type="password" id="modal-password" class="password-input" placeholder="Пароль" style="width:100%;padding:12px;border:1px solid #ddd;border-radius:8px;margin-bottom:16px">
|
||
<button class="btn" onclick="checkModalPassword()">Войти</button>
|
||
<button class="btn" style="background:var(--gray-100);margin-top:12px" onclick="closeModal()">Отмена</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal" id="parent-code-modal">
|
||
<div class="modal-content">
|
||
<h3>👨👩👧 Родительский контроль</h3>
|
||
<p style="margin-bottom:16px">Для покупки нужен код от родителя</p>
|
||
<input type="text" id="parent-code-input" placeholder="Введите код" style="width:100%;padding:12px;border:1px solid #ddd;border-radius:8px;margin-bottom:16px;font-size:18px;text-align:center">
|
||
<button class="btn" onclick="verifyParentCode()">Подтвердить</button>
|
||
<button class="btn" style="background:var(--gray-100);margin-top:12px" onclick="closeParentModal()">Отмена</button>
|
||
<p style="margin-top:20px;font-size:14px;color:var(--gray-500)">Нет кода? Попроси родителей зарегистрироваться в админке</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal" id="payment-modal">
|
||
<div class="modal-content">
|
||
<h3>💳 Онлайн оплата</h3>
|
||
<p style="margin-bottom:16px">Родитель оплачивает — ребёнок забирает</p>
|
||
<div style="background:var(--cyan-50);padding:16px;border-radius:8px;margin-bottom:16px">
|
||
<strong>Товар:</strong> <span id="pay-product"></span><br>
|
||
<strong>Цена:</strong> <span id="pay-price"></span> ₸
|
||
</div>
|
||
<div class="form-group">
|
||
<label>Телефон родителя (для входа)</label>
|
||
<input type="tel" id="pay-phone" placeholder="+7 777 123 45 67" style="width:100%;padding:12px;border:1px solid #ddd;border-radius:8px">
|
||
</div>
|
||
<button class="btn btn-green" onclick="processPayment()" style="width:100%">💳 Оплатить через Kaspi Pay</button>
|
||
<button class="btn" style="background:var(--gray-100);margin-top:12px;width:100%" onclick="closePaymentModal()">Отмена</button>
|
||
<p style="margin-top:16px;font-size:13px;color:var(--gray-500)">🔒 Тестовый режим — оплата не списывается</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="modal" id="success-modal">
|
||
<div class="modal-content" style="text-align:center">
|
||
<h3>✅ Покупка разрешена!</h3>
|
||
<p id="success-message" style="margin:20px 0"></p>
|
||
<div id="success-code" class="code-display"></div>
|
||
<p style="font-size:14px;color:var(--gray-500);margin-bottom:20px">Покажи этот код на кассе</p>
|
||
<button class="btn" onclick="document.getElementById('success-modal').classList.remove('on')">OK</button>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
// === Данные ===
|
||
const CATEGORIES = {еда:'🍫', напитки:'🥤', школа:'✏️', разное:'🎁'};
|
||
let products = [];
|
||
let parents = [];
|
||
let purchases = [];
|
||
let orders = []; // Предоплаченные заказы
|
||
let isAdmin = false;
|
||
const ADMIN_PASS = 'admin123'; // Поменяй на свой!
|
||
|
||
// === Загрузка/сохранение ===
|
||
function loadProducts() {
|
||
try {
|
||
products = localStorage.getItem('shop-products') ? JSON.parse(localStorage.getItem('shop-products')) : getDefaults();
|
||
parents = localStorage.getItem('shop-parents') ? JSON.parse(localStorage.getItem('shop-parents')) : [];
|
||
purchases = localStorage.getItem('shop-purchases') ? JSON.parse(localStorage.getItem('shop-purchases')) : [];
|
||
orders = localStorage.getItem('shop-orders') ? JSON.parse(localStorage.getItem('shop-orders')) : [];
|
||
} catch {
|
||
products = getDefaults();
|
||
parents = [];
|
||
purchases = [];
|
||
orders = [];
|
||
}
|
||
}
|
||
|
||
function saveProducts() {
|
||
localStorage.setItem('shop-products', JSON.stringify(products));
|
||
localStorage.setItem('shop-parents', JSON.stringify(parents));
|
||
localStorage.setItem('shop-purchases', JSON.stringify(purchases));
|
||
localStorage.setItem('shop-orders', JSON.stringify(orders));
|
||
}
|
||
|
||
function getDefaults() {
|
||
return [
|
||
{id:1, name:'Snickers', price:150, cat:'еда', desc:'Шоколадный батончик с нугой', img:'https://picsum.photos/seed/snickers/400/300'},
|
||
{id:2, name:'Coca-Cola', price:200, cat:'напитки', desc:'Газировка 0.5л', img:'https://picsum.photos/seed/coke/400/300'},
|
||
{id:3, name:'Тетрадь 12л', price:80, cat:'школа', desc:'В клетку, 12 листов', img:'https://picsum.photos/seed/notebook/400/300'},
|
||
{id:4, name:'Чипсы Lay\'s', price:350, cat:'еда', desc:'Вкус краба', img:'https://picsum.photos/seed/chips/400/300'},
|
||
{id:5, name:'Ручка синяя', price:120, cat:'школа', desc:'Шариковая, 0.7мм', img:'https://picsum.photos/seed/pen/400/300'},
|
||
{id:6, name:'Жвачка Love Is', price:50, cat:'еда', desc:'Клубничная', img:'https://picsum.photos/seed/gum/400/300'}
|
||
];
|
||
}
|
||
|
||
// === Рендер ===
|
||
function render(filter = 'all') {
|
||
const grid = document.getElementById('products-grid');
|
||
const adminGrid = document.getElementById('admin-grid');
|
||
const empty = document.getElementById('empty-msg');
|
||
|
||
const filtered = filter === 'all' ? products : products.filter(p => p.cat === filter);
|
||
|
||
if (filtered.length === 0) {
|
||
grid.innerHTML = '';
|
||
empty.style.display = 'block';
|
||
} else {
|
||
empty.style.display = 'none';
|
||
grid.innerHTML = filtered.map(p => `
|
||
<div class="card">
|
||
<img src="${p.img || 'https://picsum.photos/400/300'}" alt="${p.name}">
|
||
<div class="card-body">
|
||
<span class="card-cat">${CATEGORIES[p.cat]} ${p.cat}</span>
|
||
<div class="card-title">${p.name}</div>
|
||
<div class="card-price">${p.price} ₸</div>
|
||
<p style="color:var(--gray-500);font-size:14px">${p.desc || ''}</p>
|
||
<div style="display:flex;gap:8px;margin-top:12px">
|
||
<button class="btn" style="flex:1" onclick="buyProduct(${p.id})">Купить</button>
|
||
<button class="btn btn-green" style="flex:1" onclick="openPaymentModalForProduct(${JSON.stringify(p).replace(/"/g, '"')})">💳 Оплатить</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
}
|
||
|
||
// Админка
|
||
if (adminGrid) {
|
||
adminGrid.innerHTML = products.map(p => `
|
||
<div class="card">
|
||
<img src="${p.img || 'https://picsum.photos/400/300'}" alt="${p.name}">
|
||
<div class="card-body">
|
||
<span class="card-cat">${CATEGORIES[p.cat]} ${p.cat}</span>
|
||
<div class="card-title">${p.name}</div>
|
||
<div class="card-price">${p.price} ₸</div>
|
||
<button class="btn btn-red" style="margin-top:12px;width:100%" onclick="deleteProduct(${p.id})">Удалить</button>
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
}
|
||
|
||
// Родители
|
||
const parentsList = document.getElementById('parents-list');
|
||
if (parentsList) {
|
||
parentsList.innerHTML = parents.length === 0 ? '<p style="color:var(--gray-500)">Пока нет зарегистрированных родителей</p>' :
|
||
parents.map(par => `
|
||
<div class="card" style="margin-bottom:16px;padding:16px">
|
||
<strong>${par.name}</strong> (${par.phone})<br>
|
||
<span style="color:var(--gray-500)">Код: <strong style="color:var(--cyan)">${par.code}</strong></span> |
|
||
Лимит: <strong>${par.limit} ₸</strong> |
|
||
Потрачено сегодня: <strong>${getSpentToday(par.id)} ₸</strong> |
|
||
<button class="btn btn-red" style="margin-left:12px;padding:6px 12px;font-size:14px" onclick="deleteParent(${par.id})">Удалить</button>
|
||
</div>
|
||
`).join('');
|
||
}
|
||
|
||
// Покупки
|
||
const purchasesList = document.getElementById('purchases-list');
|
||
if (purchasesList) {
|
||
purchasesList.innerHTML = purchases.length === 0 ? '<p style="color:var(--gray-500)">Покупок пока нет</p>' :
|
||
purchases.slice(-10).reverse().map(p => `
|
||
<div style="padding:12px;border-bottom:1px solid var(--gray-100)">
|
||
<strong>${p.product}</strong> — ${p.price} ₸ |
|
||
Родитель: <strong>${p.parentName}</strong> |
|
||
${new Date(p.date).toLocaleString('ru-RU')}
|
||
</div>
|
||
`).join('');
|
||
}
|
||
|
||
// Предоплаченные заказы
|
||
const ordersList = document.getElementById('orders-list');
|
||
if (ordersList) {
|
||
const activeOrders = orders.filter(o => !o.pickedUp);
|
||
const completedOrders = orders.filter(o => o.pickedUp);
|
||
|
||
if (activeOrders.length === 0 && completedOrders.length === 0) {
|
||
ordersList.innerHTML = '<p style="color:var(--gray-500)">Предоплаченных заказов пока нет</p>';
|
||
} else {
|
||
let html = '';
|
||
if (activeOrders.length > 0) {
|
||
html += '<h5 style="margin:16px 0 8px;color:var(--green)">⏳ Ожидают выдачи:</h5>';
|
||
html += activeOrders.map(o => `
|
||
<div class="card" style="margin-bottom:12px;padding:16px;border-left:4px solid var(--green)">
|
||
<strong>${o.product}</strong>
|
||
<span class="status-badge status-waiting">⏳ Ждёт выдачи</span><br>
|
||
<span style="color:var(--gray-500)">Родитель: ${o.parentName} (${o.parentPhone})</span><br>
|
||
<span style="color:var(--gray-500)">Код выдачи: <strong style="color:var(--cyan);font-size:20px">${o.code}</strong></span><br>
|
||
<span style="color:var(--gray-500)">Оплачено: ${o.price} ₸ | ${new Date(o.date).toLocaleString('ru-RU')}</span><br>
|
||
<div style="display:flex;gap:8px;margin-top:12px">
|
||
<button class="btn btn-green" style="flex:1;padding:8px 16px" onclick="markAsPickedUp(${o.id})">✅ Товар выдан</button>
|
||
<button class="btn" style="flex:1;padding:8px 16px;background:#25D366;color:#fff" onclick="resendWhatsApp('${o.parentPhone}','${o.product}',${o.price},'${o.code}')">📱 WhatsApp</button>
|
||
</div>
|
||
</div>
|
||
`).join('');
|
||
}
|
||
if (completedOrders.length > 0) {
|
||
html += '<h5 style="margin:16px 0 8px;color:var(--gray-500)">✅ Выданные:</h5>';
|
||
html += completedOrders.slice(-5).reverse().map(o => `
|
||
<div class="card" style="margin-bottom:12px;padding:16px;border-left:4px solid #28a745">
|
||
<strong>${o.product}</strong>
|
||
<span class="status-badge status-paid">✅ Выдан</span><br>
|
||
<span style="color:var(--gray-500)">Родитель: ${o.parentName} | Код: ${o.code}</span><br>
|
||
<span style="color:var(--gray-500)">Выдан: ${new Date(o.pickedUpAt).toLocaleString('ru-RU')}</span>
|
||
</div>
|
||
`).join('');
|
||
}
|
||
ordersList.innerHTML = html;
|
||
}
|
||
}
|
||
}
|
||
|
||
function getSpentToday(parentId) {
|
||
const today = new Date().toDateString();
|
||
return purchases
|
||
.filter(p => p.parentId === parentId && new Date(p.date).toDateString() === today)
|
||
.reduce((sum, p) => sum + p.price, 0);
|
||
}
|
||
|
||
// === Фильтры ===
|
||
document.getElementById('filters').addEventListener('click', (e) => {
|
||
if (e.target.classList.contains('filter-btn')) {
|
||
document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
|
||
e.target.classList.add('active');
|
||
render(e.target.dataset.cat);
|
||
}
|
||
});
|
||
|
||
// === Навигация ===
|
||
document.getElementById('nav-home').addEventListener('click', (e) => {
|
||
e.preventDefault();
|
||
showPage('home');
|
||
});
|
||
document.getElementById('nav-admin').addEventListener('click', (e) => {
|
||
e.preventDefault();
|
||
showPage('admin');
|
||
});
|
||
|
||
function showPage(page) {
|
||
document.getElementById('shop-section').style.display = page === 'home' ? 'block' : 'none';
|
||
document.getElementById('admin-section').style.display = page === 'admin' ? 'block' : 'none';
|
||
document.getElementById('nav-home').classList.toggle('active', page === 'home');
|
||
document.getElementById('nav-admin').classList.toggle('active', page === 'admin');
|
||
}
|
||
|
||
// === Админка ===
|
||
function checkPassword() {
|
||
const pass = document.getElementById('admin-password').value;
|
||
if (pass === ADMIN_PASS) {
|
||
isAdmin = true;
|
||
document.getElementById('admin-login').style.display = 'none';
|
||
document.getElementById('admin-content').style.display = 'block';
|
||
render();
|
||
} else {
|
||
alert('Неверный пароль!');
|
||
}
|
||
}
|
||
|
||
function checkModalPassword() {
|
||
const pass = document.getElementById('modal-password').value;
|
||
if (pass === ADMIN_PASS) {
|
||
isAdmin = true;
|
||
closeModal();
|
||
showPage('admin');
|
||
document.getElementById('admin-login').style.display = 'none';
|
||
document.getElementById('admin-content').style.display = 'block';
|
||
render();
|
||
} else {
|
||
alert('Неверный пароль!');
|
||
}
|
||
}
|
||
|
||
function closeModal() {
|
||
document.getElementById('login-modal').classList.remove('on');
|
||
}
|
||
|
||
// === Покупки ===
|
||
let currentProduct = null;
|
||
|
||
function buyProduct(id) {
|
||
currentProduct = products.find(p => p.id === id);
|
||
openParentCodeModal();
|
||
}
|
||
|
||
function openParentCodeModal() {
|
||
document.getElementById('parent-code-input').value = '';
|
||
document.getElementById('parent-code-modal').classList.add('on');
|
||
}
|
||
|
||
function closeParentModal() {
|
||
document.getElementById('parent-code-modal').classList.remove('on');
|
||
}
|
||
|
||
let currentProductForPayment = null;
|
||
|
||
function openPaymentModal() {
|
||
document.getElementById('payment-modal').classList.add('on');
|
||
}
|
||
|
||
function closePaymentModal() {
|
||
document.getElementById('payment-modal').classList.remove('on');
|
||
}
|
||
|
||
function openPaymentModalForProduct(product) {
|
||
currentProductForPayment = product;
|
||
document.getElementById('pay-product').textContent = product.name;
|
||
document.getElementById('pay-price').textContent = product.price;
|
||
document.getElementById('payment-modal').classList.add('on');
|
||
}
|
||
|
||
function processPayment() {
|
||
const phone = document.getElementById('pay-phone').value.trim();
|
||
if (!phone || !currentProductForPayment) {
|
||
alert('Введите номер телефона и выберите товар');
|
||
return;
|
||
}
|
||
|
||
// Имитация оплаты Kaspi Pay
|
||
const orderCode = Math.floor(100000 + Math.random() * 900000).toString();
|
||
const order = {
|
||
id: Date.now(),
|
||
productId: currentProductForPayment.id,
|
||
product: currentProductForPayment.name,
|
||
price: currentProductForPayment.price,
|
||
parentPhone: phone,
|
||
parentName: phone,
|
||
code: orderCode,
|
||
date: new Date().toISOString(),
|
||
pickedUp: false,
|
||
pickedUpAt: null
|
||
};
|
||
|
||
orders.push(order);
|
||
saveProducts();
|
||
|
||
closePaymentModal();
|
||
|
||
// Отправка в WhatsApp
|
||
const whatsappMessage = `✅ *Оплата в школьном магазине*\n\nТовар: ${order.product}\nЦена: ${order.price} ₸\n\n🔑 *Ваш код выдачи: ${orderCode}*\n\nПокажите этот код продавцу и получите товар.\nСпасибо за покупку! 🏪`;
|
||
const whatsappUrl = `https://wa.me/${phone.replace(/\D/g, '')}?text=${encodeURIComponent(whatsappMessage)}`;
|
||
|
||
document.getElementById('success-message').textContent = `✅ Оплата прошла успешно!\n\nКод отправлен в WhatsApp на номер ${phone}`;
|
||
document.getElementById('success-code').textContent = orderCode;
|
||
document.getElementById('success-modal').classList.add('on');
|
||
|
||
// Открываем WhatsApp через 1 секунду
|
||
setTimeout(() => {
|
||
if (confirm('📱 Открыть WhatsApp для отправки кода родителю?')) {
|
||
window.open(whatsappUrl, '_blank');
|
||
}
|
||
}, 1000);
|
||
|
||
currentProductForPayment = null;
|
||
document.getElementById('pay-phone').value = '';
|
||
}
|
||
|
||
function verifyParentCode() {
|
||
const code = document.getElementById('parent-code-input').value.trim();
|
||
const parent = parents.find(p => p.code === code);
|
||
|
||
if (!parent) {
|
||
alert('❌ Неверный код! Попроси родителя ввести код.');
|
||
return;
|
||
}
|
||
|
||
const spentToday = getSpentToday(parent.id);
|
||
const productPrice = currentProduct ? currentProduct.price : 0;
|
||
|
||
if (spentToday + productPrice > parent.limit) {
|
||
alert(`⚠️ Превышен лимит! Сегодня потрачено: ${spentToday} ₸ из ${parent.limit} ₸`);
|
||
return;
|
||
}
|
||
|
||
// Успешная покупка
|
||
if (currentProduct) {
|
||
purchases.push({
|
||
parentId: parent.id,
|
||
parentName: parent.name,
|
||
productId: currentProduct.id,
|
||
product: currentProduct.name,
|
||
price: currentProduct.price,
|
||
date: new Date().toISOString()
|
||
});
|
||
saveProducts();
|
||
|
||
document.getElementById('success-message').textContent = `${parent.name}, ваш ребёнок покупает: ${currentProduct.name} за ${currentProduct.price} ₸`;
|
||
document.getElementById('success-code').textContent = code;
|
||
document.getElementById('parent-code-modal').classList.remove('on');
|
||
document.getElementById('success-modal').classList.add('on');
|
||
}
|
||
}
|
||
|
||
function markAsPickedUp(orderId) {
|
||
if (confirm('Подтвердить выдачу товара?')) {
|
||
const order = orders.find(o => o.id === orderId);
|
||
if (order) {
|
||
order.pickedUp = true;
|
||
order.pickedUpAt = new Date().toISOString();
|
||
saveProducts();
|
||
render();
|
||
alert('✅ Товар выдан!');
|
||
}
|
||
}
|
||
}
|
||
|
||
function resendWhatsApp(phone, product, price, code) {
|
||
const message = `✅ *Оплата в школьном магазине*\n\nТовар: ${product}\nЦена: ${price} ₸\n\n🔑 *Ваш код выдачи: ${code}*\n\nПокажите этот код продавцу и получите товар.\nСпасибо за покупку! 🏪`;
|
||
const url = `https://wa.me/${phone.replace(/\D/g, '')}?text=${encodeURIComponent(message)}`;
|
||
window.open(url, '_blank');
|
||
}
|
||
|
||
// === Родители ===
|
||
document.getElementById('parent-form').addEventListener('submit', (e) => {
|
||
e.preventDefault();
|
||
const parent = {
|
||
id: Date.now(),
|
||
name: document.getElementById('parent-name').value,
|
||
phone: document.getElementById('parent-phone').value,
|
||
limit: Number(document.getElementById('parent-limit').value),
|
||
code: generateCode()
|
||
};
|
||
parents.push(parent);
|
||
saveProducts();
|
||
render();
|
||
e.target.reset();
|
||
alert(`✅ Родитель зарегистрирован! Код: ${parent.code}`);
|
||
});
|
||
|
||
function generateCode() {
|
||
return Math.floor(1000 + Math.random() * 9000).toString();
|
||
}
|
||
|
||
function deleteParent(id) {
|
||
if (confirm('Удалить этого родителя?')) {
|
||
parents = parents.filter(p => p.id !== id);
|
||
saveProducts();
|
||
render();
|
||
}
|
||
}
|
||
|
||
function printCodes() {
|
||
if (parents.length === 0) {
|
||
alert('Пока нет зарегистрированных родителей!');
|
||
return;
|
||
}
|
||
const content = parents.map(p =>
|
||
`${p.name} (${p.phone}) — КОД: ${p.code} (лимит ${p.limit}₸)`
|
||
).join('\n\n');
|
||
|
||
const printWindow = window.open('', '', 'width=600,height=400');
|
||
printWindow.document.write(`
|
||
<html><head><title>Коды родителей</title>
|
||
<style>
|
||
body{font-family:Arial,sans-serif;padding:40px}
|
||
h1{color:#0F1218}
|
||
.code{background:#E8FCFF;padding:15px;margin:10px 0;border-radius:8px;font-size:18px}
|
||
.code strong{color:#00E5FF;font-size:24px}
|
||
</style>
|
||
</head><body>
|
||
<h1>🏪 Школьный магазин — Коды родителей</h1>
|
||
<p style="color:#5B6573">Распечатайте этот список и повесьте на кассе для проверки</p>
|
||
${parents.map(p => `<div class="code"><strong>КОД: ${p.code}</strong><br>${p.name} (${p.phone})<br>Лимит: ${p.limit}₸</div>`).join('')}
|
||
<p style="margin-top:30px;color:#5B6573;font-size:14px">Распечатано: ${new Date().toLocaleString('ru-RU')}</p>
|
||
</body></html>
|
||
`);
|
||
printWindow.document.close();
|
||
printWindow.print();
|
||
}
|
||
|
||
// === Добавление/удаление ===
|
||
document.getElementById('add-form').addEventListener('submit', (e) => {
|
||
e.preventDefault();
|
||
const product = {
|
||
id: Date.now(),
|
||
name: document.getElementById('prod-name').value,
|
||
price: Number(document.getElementById('prod-price').value),
|
||
cat: document.getElementById('prod-cat').value,
|
||
desc: document.getElementById('prod-desc').value,
|
||
img: document.getElementById('prod-img').value || 'https://picsum.photos/400/300'
|
||
};
|
||
products.push(product);
|
||
saveProducts();
|
||
render();
|
||
e.target.reset();
|
||
alert('✅ Товар добавлен!');
|
||
});
|
||
|
||
function deleteProduct(id) {
|
||
if (confirm('Удалить этот товар?')) {
|
||
products = products.filter(p => p.id !== id);
|
||
saveProducts();
|
||
render();
|
||
}
|
||
}
|
||
|
||
// === Старт ===
|
||
loadProducts();
|
||
render();
|
||
</script>
|
||
</body>
|
||
</html>
|