Add mini admin panel

This commit is contained in:
Roman Pyrih
2025-12-17 12:02:31 +01:00
parent eb422001e3
commit 1d05064a51
12 changed files with 499 additions and 0 deletions

61
api/salony/index.php Normal file
View File

@@ -0,0 +1,61 @@
<?php
header('Content-Type: application/json; charset=utf-8');
// ==== DB CONFIG ====
const DB_DSN = 'mysql:host=serwer1852487.home.pl;port=3380;dbname=28477142_0000006;charset=utf8mb4';
const DB_USER = '28477142_0000006';
const DB_PASS = '2aodCAiQSKThx4la6';
try {
$pdo = new PDO(DB_DSN, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);
} catch (Throwable $e) {
http_response_code(500);
echo json_encode(['error' => 'DB error']);
exit;
}
// === GET ALL PLACES ===
$places = $pdo->query("
SELECT id, type, name, woj
FROM salon_places
ORDER BY id ASC
")->fetchAll();
$result = [];
foreach ($places as $place) {
// === GET SHOPS FOR PLACE ===
$stmt = $pdo->prepare("
SELECT address, open_hours, url_address, lat, lng
FROM shops
WHERE place_id = ?
ORDER BY id ASC
");
$stmt->execute([$place['id']]);
$shops = [];
foreach ($stmt as $shop) {
$shops[] = [
'address' => $shop['address'],
'openHours' => $shop['open_hours'],
'urlAddress'=> $shop['url_address'],
'lat' => (string)$shop['lat'],
'lng' => (string)$shop['lng'],
];
}
$result[] = [
'type' => $place['type'],
'name' => $place['name'],
'woj' => $place['woj'] === null ? false : $place['woj'],
'shops' => $shops
];
}
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
exit;

36
salony/actions/add.php Normal file
View File

@@ -0,0 +1,36 @@
<?php
require __DIR__ . '/../db.php';
if ($_POST) {
// === Dodajemy miejsce ===
$stmt = $pdo->prepare("
INSERT INTO salon_places (type, name, woj)
VALUES (?, ?, ?)
");
$stmt->execute([
$_POST['type'],
$_POST['name'],
$_POST['woj'] ?: null
]);
$placeId = $pdo->lastInsertId();
// === Dodajemy sklep (shop) ===
$stmt = $pdo->prepare("
INSERT INTO shops (place_id, address, open_hours, url_address, lat, lng)
VALUES (?, ?, ?, ?, ?, ?)
");
$stmt->execute([
$placeId,
$_POST['address'] ?: null,
$_POST['open_hours'] ?: null,
$_POST['url_address'],
$_POST['lat'],
$_POST['lng'],
]);
header('Location: ../');
exit;
}

13
salony/actions/delete.php Normal file
View File

@@ -0,0 +1,13 @@
<?php
require __DIR__ . '/../db.php';
$id = (int)$_GET['id'];
// Usuwamy sklepy powiązane z miejscem
$pdo->prepare("DELETE FROM shops WHERE place_id = ?")->execute([$id]);
// Usuwamy miejsce
$pdo->prepare("DELETE FROM salon_places WHERE id = ?")->execute([$id]);
header('Location: ../');
exit;

44
salony/actions/edit.php Normal file
View File

@@ -0,0 +1,44 @@
<?php
require __DIR__ . '/../db.php';
$id = (int)($_GET['id'] ?? 0);
if (!$id) {
echo "Brak ID.";
exit;
}
// Pobieramy miejsce
$shops = $pdo->prepare("SELECT * FROM shops WHERE place_id=?");
$shops->execute([$id]);
$shops = $shops->fetchAll();
if ($_POST) {
// Aktualizujemy miejsce
$pdo->prepare("UPDATE salon_places SET type=?, name=?, woj=? WHERE id=?")
->execute([
$_POST['type'],
$_POST['name'],
$_POST['woj'] ?: null,
$id
]);
// Aktualizujemy pierwszy sklep (shop)
$shopId = $shops[0]['id'] ?? null;
if ($shopId) {
$pdo->prepare("
UPDATE shops SET address=?, open_hours=?, url_address=?, lat=?, lng=?
WHERE id=?
")->execute([
$_POST['address'] ?: null,
$_POST['open_hours'] ?: null,
$_POST['url_address'],
$_POST['lat'],
$_POST['lng'],
$shopId
]);
}
header('Location: ../');
exit;
}

View File

@@ -0,0 +1,2 @@
</body>
</html>

View File

@@ -0,0 +1,36 @@
<?php
session_start();
if (!isset($_SESSION['admin_logged_in']) || $_SESSION['admin_logged_in'] !== true) {
header('Location: pages/login.php');
exit;
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Salony Admin</title>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
</head>
<body class="bg-gray-100 min-h-screen">
<header class="bg-white shadow-md px-6 py-4 flex items-center justify-between">
<h1 class="text-2xl font-bold text-gray-800">
<a href="<?php echo __DIR__ . '/../'; ?>">Panel</a>
</h1>
<?php if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true): ?>
<a
href="<?php echo __DIR__ . '/../pages/logout.php'; ?>"
class="flex items-center gap-2 bg-red-600 hover:bg-red-700 text-white px-4 py-2 rounded-md shadow transition-all font-medium">
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h6a2 2 0 012 2v1" />
</svg>
Wyloguj
</a>
<?php endif; ?>
</header>
<main class="p-6">

9
salony/db.php Normal file
View File

@@ -0,0 +1,9 @@
<?php
const DB_DSN = 'mysql:host=serwer1852487.home.pl;port=3380;dbname=28477142_0000006;charset=utf8mb4';
const DB_USER = '28477142_0000006';
const DB_PASS = '2aodCAiQSKThx4la6';
$pdo = new PDO(DB_DSN, DB_USER, DB_PASS, [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

48
salony/index.php Normal file
View File

@@ -0,0 +1,48 @@
<?php
require __DIR__ . '/db.php';
$places = $pdo->query("SELECT * FROM salon_places ORDER BY id DESC")->fetchAll();
include __DIR__ . '/components/header.php';
?>
<div class="max-w-6xl mx-auto px-4 mt-8">
<div class="flex justify-between items-center mb-6">
<h1 class="text-3xl font-bold text-gray-800">Lista miejsc / salonów</h1>
<a href="pages/add.php" class="bg-green-600 hover:bg-green-700 text-white px-5 py-2 rounded shadow transition-all">
+ Dodaj
</a>
</div>
<div class="overflow-x-auto bg-white rounded shadow-lg">
<table class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-100 sticky top-0">
<tr>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">ID</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Nazwa</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Typ</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Woj</th>
<th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Akcje</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<?php foreach ($places as $p): ?>
<tr class="hover:bg-gray-50 transition-colors">
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700"><?= $p['id'] ?></td>
<td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900"><?= htmlspecialchars($p['name']) ?></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700"><?= $p['type'] ?></td>
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-700"><?= $p['woj'] ?: '—' ?></td>
<td class="px-6 py-4 whitespace-nowrap text-sm flex gap-2">
<a href="pages/edit.php?id=<?= $p['id'] ?>"
class="bg-blue-600 hover:bg-blue-700 text-white px-3 py-1 rounded-md shadow transition-colors">Edytuj</a>
<a href="actions/delete.php?id=<?= $p['id'] ?>"
onclick="return confirm('Usunąć?')"
class="bg-red-600 hover:bg-red-700 text-white px-3 py-1 rounded-md shadow transition-colors">Usuń</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<?php include __DIR__ . '/components/footer.php'; ?>

87
salony/pages/add.php Normal file
View File

@@ -0,0 +1,87 @@
<?php
include __DIR__ . '/../db.php';
include __DIR__ . '/../components/header.php';
?>
<div class="max-w-2xl mx-auto mt-10">
<div class="bg-white shadow-lg rounded-lg p-8">
<h1 class="text-2xl font-bold mb-6">Dodaj nowe miejsce / salon</h1>
<form method="post" action="../actions/add.php" class="space-y-4">
<!-- Typ miejsca -->
<div>
<label class="block mb-1 font-medium text-gray-700">Typ miejsca</label>
<select name="type" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="city">City</option>
<option value="woj">Woj</option>
</select>
</div>
<!-- Nazwa -->
<div>
<label class="block mb-1 font-medium text-gray-700">Nazwa</label>
<input name="name" type="text" placeholder="np. Myszków" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<!-- Woj -->
<div>
<label class="block mb-1 font-medium text-gray-700">Woj (opcjonalnie)</label>
<select name="woj" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="">Brak</option>
<option value="Dolnośląskie">Dolnośląskie</option>
<option value="Kujawsko-Pomorskie">Kujawsko-Pomorskie</option>
<option value="Lubelskie">Lubelskie</option>
<option value="Lubuskie">Lubuskie</option>
<option value="Łódzkie">Łódzkie</option>
<option value="Małopolskie">Małopolskie</option>
<option value="Mazowieckie">Mazowieckie</option>
<option value="Opolskie">Opolskie</option>
<option value="Podkarpackie">Podkarpackie</option>
<option value="Podlaskie">Podlaskie</option>
<option value="Pomorskie">Pomorskie</option>
<option value="Śląskie">Śląskie</option>
<option value="Świętokrzyskie">Świętokrzyskie</option>
<option value="Warmińsko-Mazurskie">Warmińsko-Mazurskie</option>
<option value="Wielkopolskie">Wielkopolskie</option>
<option value="Zachodniopomorskie">Zachodniopomorskie</option>
</select>
</div>
<hr class="my-6">
<h2 class="text-xl font-semibold mb-4">Dane sklepu</h2>
<div>
<label class="block mb-1 font-medium text-gray-700">Adres</label>
<input name="address" type="text" placeholder="ul. Kościuszki 67" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div>
<label class="block mb-1 font-medium text-gray-700">Godziny otwarcia</label>
<input name="open_hours" type="text" placeholder="pn.-pt. 9-17 sob. 9-14" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div>
<label class="block mb-1 font-medium text-gray-700">Google Maps URL</label>
<input name="url_address" type="text" placeholder="https://maps.google.com/..." class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block mb-1 font-medium text-gray-700">Lat</label>
<input name="lat" type="text" placeholder="50.5770991" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div>
<label class="block mb-1 font-medium text-gray-700">Lng</label>
<input name="lng" type="text" placeholder="19.3240021" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
</div>
<button type="submit" class="w-full bg-blue-600 text-white font-semibold py-3 rounded-md hover:bg-blue-700 transition-colors">Zapisz</button>
<a href="<?php echo __DIR__ . '/..'; ?>" class="w-full text-center block bg-red-600 text-white font-semibold py-3 rounded-md hover:bg-red-700 transition-colors">Wstecz</a>
</form>
</div>
</div>
<?php include __DIR__ . '/../components/footer.php'; ?>

102
salony/pages/edit.php Normal file
View File

@@ -0,0 +1,102 @@
<?php
include __DIR__ . '/../db.php';
include __DIR__ . '/../components/header.php';
$id = (int)$_GET['id'] ?? 0;
// Pobieramy miejsce
$stmt = $pdo->prepare("SELECT * FROM salon_places WHERE id=?");
$stmt->execute([$id]);
$place = $stmt->fetch();
if (!$place) {
echo "Nie znaleziono miejsca.";
exit;
}
// Pobieramy sklep (shops)
$stmt = $pdo->prepare("SELECT * FROM shops WHERE place_id=?");
$stmt->execute([$id]);
$shops = $stmt->fetchAll();
?>
<div class="max-w-2xl mx-auto mt-10">
<div class="bg-white shadow-lg rounded-lg p-8">
<h1 class="text-2xl font-bold mb-6">Edytuj miejsce / salon</h1>
<form method="post" action="../actions/edit.php?id=<?= $id ?>" class="space-y-4">
<!-- Typ -->
<div>
<label class="block mb-1 font-medium text-gray-700">Typ miejsca</label>
<select name="type" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="city" <?= $place['type']=='city'?'selected':'' ?>>City</option>
<option value="woj" <?= $place['type']=='woj'?'selected':'' ?>>Woj</option>
</select>
</div>
<!-- Nazwa -->
<div>
<label class="block mb-1 font-medium text-gray-700">Nazwa</label>
<input name="name" type="text" value="<?= htmlspecialchars($place['name']) ?>" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<!-- Woj -->
<div>
<label class="block mb-1 font-medium text-gray-700">Woj (opcjonalnie)</label>
<select name="woj" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
<option value="" <?= !$place['woj']?'selected':'' ?>>Brak</option>
<option value="Dolnośląskie" <?= $place['woj']=='Dolnośląskie'?'selected':'' ?>>Dolnośląskie</option>
<option value="Kujawsko-Pomorskie" <?= $place['woj']=='Kujawsko-Pomorskie'?'selected':'' ?>>Kujawsko-Pomorskie</option>
<option value="Lubelskie" <?= $place['woj']=='Lubelskie'?'selected':'' ?>>Lubelskie</option>
<option value="Lubuskie" <?= $place['woj']=='Lubuskie'?'selected':'' ?>>Lubuskie</option>
<option value="Łódzkie" <?= $place['woj']=='Łódzkie'?'selected':'' ?>>Łódzkie</option>
<option value="Małopolskie" <?= $place['woj']=='Małopolskie'?'selected':'' ?>>Małopolskie</option>
<option value="Mazowieckie" <?= $place['woj']=='Mazowieckie'?'selected':'' ?>>Mazowieckie</option>
<option value="Opolskie" <?= $place['woj']=='Opolskie'?'selected':'' ?>>Opolskie</option>
<option value="Podkarpackie" <?= $place['woj']=='Podkarpackie'?'selected':'' ?>>Podkarpackie</option>
<option value="Podlaskie" <?= $place['woj']=='Podlaskie'?'selected':'' ?>>Podlaskie</option>
<option value="Pomorskie" <?= $place['woj']=='Pomorskie'?'selected':'' ?>>Pomorskie</option>
<option value="Śląskie" <?= $place['woj']=='Śląskie'?'selected':'' ?>>Śląskie</option>
<option value="Świętokrzyskie" <?= $place['woj']=='Świętokrzyskie'?'selected':'' ?>>Świętokrzyskie</option>
<option value="Warmińsko-Mazurskie" <?= $place['woj']=='Warmińsko-Mazurskie'?'selected':'' ?>>Warmińsko-Mazurskie</option>
<option value="Wielkopolskie" <?= $place['woj']=='Wielkopolskie'?'selected':'' ?>>Wielkopolskie</option>
<option value="Zachodniopomorskie" <?= $place['woj']=='Zachodniopomorskie'?'selected':'' ?>>Zachodniopomorskie</option>
</select>
</div>
<hr class="my-6">
<h2 class="text-xl font-semibold mb-4">Dane sklepu</h2>
<div>
<label class="block mb-1 font-medium text-gray-700">Adres</label>
<input name="address" type="text" value="<?= htmlspecialchars($shops[0]['address'] ?? '') ?>" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div>
<label class="block mb-1 font-medium text-gray-700">Godziny otwarcia</label>
<input name="open_hours" type="text" value="<?= htmlspecialchars($shops[0]['open_hours'] ?? '') ?>" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div>
<label class="block mb-1 font-medium text-gray-700">Google Maps URL</label>
<input name="url_address" type="text" value="<?= htmlspecialchars($shops[0]['url_address'] ?? '') ?>" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block mb-1 font-medium text-gray-700">Lat</label>
<input name="lat" type="text" value="<?= htmlspecialchars($shops[0]['lat'] ?? '') ?>" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div>
<label class="block mb-1 font-medium text-gray-700">Lng</label>
<input name="lng" type="text" value="<?= htmlspecialchars($shops[0]['lng'] ?? '') ?>" class="w-full p-3 border rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
</div>
<button type="submit" class="w-full bg-blue-600 text-white font-semibold py-3 rounded-md hover:bg-blue-700 transition-colors">Zapisz zmiany</button>
<a href="<?php echo __DIR__ . '/..'; ?>" class="w-full text-center block bg-red-600 text-white font-semibold py-3 rounded-md hover:bg-red-700 transition-colors">Wstecz</a>
</form>
</div>
</div>
<?php include __DIR__ . '/../components/footer.php'; ?>

56
salony/pages/login.php Normal file
View File

@@ -0,0 +1,56 @@
<?php
session_start();
if (isset($_SESSION['admin_logged_in']) && $_SESSION['admin_logged_in'] === true) {
header('Location: index.php');
exit;
}
$error = '';
if ($_POST) {
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$ADMIN_USER = 'admin';
$ADMIN_PASS = 'ProjectPro2025!';
if ($username === $ADMIN_USER && $password === $ADMIN_PASS) {
$_SESSION['admin_logged_in'] = true;
header('Location: ../');
exit;
} else {
$error = 'Nieprawidłowy login lub hasło';
}
}
?>
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<title>Logowanie</title>
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
</head>
<body class="bg-gray-100 flex items-center justify-center h-screen">
<form method="post" class="bg-white p-8 rounded shadow-md w-full max-w-sm">
<h1 class="text-2xl font-bold mb-6 text-center">Panel logowania</h1>
<?php if ($error): ?>
<p class="mb-4 text-red-600"><?= $error ?></p>
<?php endif; ?>
<div class="mb-4">
<label class="block mb-1 font-medium">Login</label>
<input type="text" name="username" class="w-full p-3 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<div class="mb-6">
<label class="block mb-1 font-medium">Hasło</label>
<input type="password" name="password" class="w-full p-3 border rounded focus:outline-none focus:ring-2 focus:ring-blue-500">
</div>
<button type="submit" class="w-full bg-blue-600 hover:bg-blue-700 text-white py-3 rounded-md shadow transition-colors">
Zaloguj
</button>
</form>
</body>
</html>

5
salony/pages/logout.php Normal file
View File

@@ -0,0 +1,5 @@
<?php
session_start();
session_destroy();
header('Location: ../');
exit;