shop with parent control
This commit is contained in:
parent
1c84803dc1
commit
4d2cba24bc
203
index.html
203
index.html
@ -24,7 +24,6 @@ body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,s
|
||||
.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}
|
||||
.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-buy{width:100%;margin-top:12px}
|
||||
.btn:hover{opacity:0.9}
|
||||
.btn-green{background:var(--green);color:#fff}
|
||||
.btn-red{background:var(--red);color:#fff}
|
||||
@ -33,6 +32,7 @@ body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,s
|
||||
.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}
|
||||
@ -81,6 +81,10 @@ body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,s
|
||||
|
||||
<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">
|
||||
<button class="btn" onclick="openParentCodeModal()" style="background:var(--green);color:#fff">👨👩👧 Получить код родителя</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@ -98,6 +102,30 @@ body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,s
|
||||
</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>
|
||||
|
||||
<h4 style="margin-bottom:16px">Зарегистрированные родители:</h4>
|
||||
<div id="parents-list" style="margin-bottom:32px"></div>
|
||||
</div>
|
||||
|
||||
<div class="admin-panel">
|
||||
<h3>➕ Добавить товар</h3>
|
||||
<form id="add-form">
|
||||
@ -130,6 +158,11 @@ body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,s
|
||||
</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>
|
||||
@ -145,23 +178,53 @@ body{font:17px/1.6 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,s
|
||||
</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="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 isAdmin = false;
|
||||
const ADMIN_PASS = 'admin123'; // Поменяй на свой!
|
||||
|
||||
// === Загрузка/сохранение ===
|
||||
function loadProducts() {
|
||||
try {
|
||||
const saved = localStorage.getItem('shop-products');
|
||||
products = saved ? JSON.parse(saved) : getDefaults();
|
||||
} catch { products = getDefaults(); }
|
||||
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')) : [];
|
||||
} catch {
|
||||
products = getDefaults();
|
||||
parents = [];
|
||||
purchases = [];
|
||||
}
|
||||
}
|
||||
|
||||
function saveProducts() {
|
||||
localStorage.setItem('shop-products', JSON.stringify(products));
|
||||
localStorage.setItem('shop-parents', JSON.stringify(parents));
|
||||
localStorage.setItem('shop-purchases', JSON.stringify(purchases));
|
||||
}
|
||||
|
||||
function getDefaults() {
|
||||
@ -196,7 +259,7 @@ function render(filter = 'all') {
|
||||
<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>
|
||||
<button class="btn btn-buy" onclick="askParent('${p.name}', ${p.price})">👨👩👧👦 Попросить родителя</button>
|
||||
<button class="btn" style="margin-top:12px;width:100%" onclick="buyProduct(${p.id})">Купить</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
@ -216,6 +279,41 @@ function render(filter = 'all') {
|
||||
</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('');
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// === Фильтры ===
|
||||
@ -275,6 +373,88 @@ 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');
|
||||
}
|
||||
|
||||
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');
|
||||
}
|
||||
}
|
||||
|
||||
// === Родители ===
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
// === Добавление/удаление ===
|
||||
document.getElementById('add-form').addEventListener('submit', (e) => {
|
||||
e.preventDefault();
|
||||
@ -301,19 +481,6 @@ function deleteProduct(id) {
|
||||
}
|
||||
}
|
||||
|
||||
// === Запрос родителю ===
|
||||
function askParent(name, price) {
|
||||
const parentPhone = prompt(
|
||||
`Товар: ${name}\nЦена: ${price} ₸\n\nВведите номер телефона родителя (WhatsApp):`,
|
||||
'77771234567'
|
||||
);
|
||||
if (parentPhone) {
|
||||
const msg = `Здравствуйте! Я хочу купить ${name} за ${price} ₸. Можно?`;
|
||||
const url = `https://wa.me/${parentPhone}?text=${encodeURIComponent(msg)}`;
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
}
|
||||
|
||||
// === Старт ===
|
||||
loadProducts();
|
||||
render();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user