Compare commits
5 Commits
3250ae4832
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac2cd8efbc | ||
|
|
f7939c573a | ||
|
|
8eb1ff11a2 | ||
| e5fd3d0bd8 | |||
| 400221a2c5 |
BIN
Hochzeit-G-stebuch-1/.DS_Store
vendored
BIN
Hochzeit-G-stebuch-1/.DS_Store
vendored
Binary file not shown.
@@ -1,433 +0,0 @@
|
|||||||
<?php
|
|
||||||
$brautpaar_namen = "Damian & Melissa";
|
|
||||||
$upload_verzeichnis = __DIR__ . '/uploads/';
|
|
||||||
|
|
||||||
function get_image_count($dir) {
|
|
||||||
if (!is_dir($dir)) return 0;
|
|
||||||
$files = scandir($dir);
|
|
||||||
return count(array_filter($files, function($f) use ($dir) {
|
|
||||||
return is_file($dir . $f) && !str_starts_with($f, '.');
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
$current_count = get_image_count($upload_verzeichnis);
|
|
||||||
|
|
||||||
// Bilder für die Galerie laden (nur die neuesten 30, um Abstürze am Handy zu vermeiden)
|
|
||||||
$gallery_images = [];
|
|
||||||
if (is_dir($upload_verzeichnis)) {
|
|
||||||
$files = scandir($upload_verzeichnis);
|
|
||||||
$valid_files = [];
|
|
||||||
foreach ($files as $f) {
|
|
||||||
if (is_file($upload_verzeichnis . $f) && !str_starts_with($f, '.')) {
|
|
||||||
$valid_files[] = $f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZUVERLÄSSIGE SORTIERUNG: Alphabetisch absteigend, da Dateiname = Zeitstempel
|
|
||||||
rsort($valid_files);
|
|
||||||
|
|
||||||
$gallery_images = array_slice($valid_files, 0, 30);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['photos'])) {
|
|
||||||
$cleanName = 'Foto';
|
|
||||||
|
|
||||||
if (!is_dir($upload_verzeichnis)) {
|
|
||||||
mkdir($upload_verzeichnis, 0777, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
$uploadedCount = 0;
|
|
||||||
foreach ($_FILES['photos']['tmp_name'] as $key => $tmpName) {
|
|
||||||
if ($tmpName != "") {
|
|
||||||
$extension = strtolower(pathinfo($_FILES['photos']['name'][$key], PATHINFO_EXTENSION));
|
|
||||||
$newName = $cleanName . '_' . time() . '_' . substr(md5(uniqid()), 0, 6) . '.' . $extension;
|
|
||||||
if (move_uploaded_file($tmpName, $upload_verzeichnis . $newName)) {
|
|
||||||
$uploadedCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
echo json_encode([
|
|
||||||
'success' => true,
|
|
||||||
'count' => $uploadedCount,
|
|
||||||
'newTotal' => get_image_count($upload_verzeichnis)
|
|
||||||
]);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
|
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="de">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Fotobox - <?php echo $brautpaar_namen; ?></title>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Montserrat:wght@300;400;600&display=swap" rel="stylesheet">
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
/* Farbpalette */
|
|
||||||
--dark-green: #484D46;
|
|
||||||
--olive-green: #5F6251;
|
|
||||||
--brown: #856856;
|
|
||||||
--light-brown: #A88F79;
|
|
||||||
--beige: #BEB7AD;
|
|
||||||
--bg-page: #FAF9F7;
|
|
||||||
--white: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
* { box-sizing: border-box; }
|
|
||||||
|
|
||||||
body {
|
|
||||||
font-family: 'Montserrat', sans-serif;
|
|
||||||
background-color: var(--bg-page);
|
|
||||||
color: var(--dark-green);
|
|
||||||
margin: 0;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: flex-start; /* Wichtig für die Galerie */
|
|
||||||
min-height: 100vh;
|
|
||||||
padding: 20px;
|
|
||||||
transition: align-items 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
max-width: 500px;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
background: var(--white);
|
|
||||||
padding: 40px 30px;
|
|
||||||
border-radius: 12px;
|
|
||||||
box-shadow: 0 10px 40px rgba(72, 77, 70, 0.1);
|
|
||||||
overflow: hidden;
|
|
||||||
margin-top: 20px;
|
|
||||||
transition: margin-top 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-family: 'Playfair Display', serif;
|
|
||||||
font-size: clamp(1.2rem, 7vw, 2.5rem);
|
|
||||||
white-space: nowrap;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
font-weight: 400;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
color: var(--dark-green);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-header {
|
|
||||||
font-size: 0.85rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 3px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
border-bottom: 1px solid var(--beige);
|
|
||||||
padding-bottom: 20px;
|
|
||||||
color: var(--light-brown);
|
|
||||||
}
|
|
||||||
|
|
||||||
.counter-box {
|
|
||||||
margin: 0 0 20px 0;
|
|
||||||
padding: 15px;
|
|
||||||
background: var(--beige);
|
|
||||||
border-radius: 8px;
|
|
||||||
color: var(--dark-green);
|
|
||||||
}
|
|
||||||
|
|
||||||
.counter-number {
|
|
||||||
display: block;
|
|
||||||
font-family: 'Playfair Display', serif;
|
|
||||||
font-size: 2.2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.counter-label {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
text-transform: uppercase;
|
|
||||||
letter-spacing: 1px;
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tabs Navigation */
|
|
||||||
.tabs {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 10px;
|
|
||||||
margin-bottom: 30px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-btn {
|
|
||||||
background: var(--bg-page);
|
|
||||||
color: var(--light-brown);
|
|
||||||
border: 1px solid var(--beige);
|
|
||||||
padding: 10px 20px;
|
|
||||||
border-radius: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-family: 'Montserrat', sans-serif;
|
|
||||||
font-weight: 600;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-btn.active {
|
|
||||||
background: var(--olive-green);
|
|
||||||
color: var(--white);
|
|
||||||
border-color: var(--olive-green);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Upload Bereich */
|
|
||||||
.form-group { margin-bottom: 25px; text-align: left; }
|
|
||||||
|
|
||||||
.upload-area {
|
|
||||||
border: 2px dashed var(--light-brown);
|
|
||||||
border-radius: 8px;
|
|
||||||
padding: 40px 30px;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: var(--white);
|
|
||||||
transition: all 0.3s;
|
|
||||||
color: var(--olive-green);
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-area:hover {
|
|
||||||
background: var(--bg-page);
|
|
||||||
border-color: var(--olive-green);
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-area.uploading {
|
|
||||||
pointer-events: none;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Progress Bar */
|
|
||||||
#progress-wrapper { display: none; margin-top: 20px; text-align: left; }
|
|
||||||
.progress-bar-container {
|
|
||||||
width: 100%; height: 6px; background: var(--beige);
|
|
||||||
margin-top: 10px; border-radius: 3px; overflow: hidden;
|
|
||||||
}
|
|
||||||
#progress-bar { height: 100%; background: var(--olive-green); width: 0%; transition: width 0.2s; }
|
|
||||||
|
|
||||||
/* Galerie Bereich */
|
|
||||||
#gallery-section { display: none; }
|
|
||||||
.gallery-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
gap: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.gallery-item {
|
|
||||||
width: 100%;
|
|
||||||
aspect-ratio: 1 / 1;
|
|
||||||
object-fit: cover;
|
|
||||||
border-radius: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: transform 0.2s;
|
|
||||||
background-color: var(--beige);
|
|
||||||
}
|
|
||||||
|
|
||||||
.gallery-item:hover { transform: scale(1.03); }
|
|
||||||
|
|
||||||
.empty-gallery {
|
|
||||||
grid-column: 1 / -1;
|
|
||||||
color: var(--light-brown);
|
|
||||||
font-size: 0.9rem;
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Lightbox (Vollbild) */
|
|
||||||
.lightbox {
|
|
||||||
display: none;
|
|
||||||
position: fixed;
|
|
||||||
z-index: 9999;
|
|
||||||
top: 0; left: 0; width: 100%; height: 100%;
|
|
||||||
background-color: rgba(72, 77, 70, 0.95);
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
padding: 20px;
|
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lightbox.show { display: flex; opacity: 1; }
|
|
||||||
|
|
||||||
.lightbox img {
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 90vh;
|
|
||||||
border-radius: 8px;
|
|
||||||
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
.close-lightbox {
|
|
||||||
position: absolute;
|
|
||||||
top: 20px; right: 30px;
|
|
||||||
color: var(--white);
|
|
||||||
font-size: 40px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-family: sans-serif;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Success Screen */
|
|
||||||
.success-screen { display: none; animation: fadeIn 0.5s ease; }
|
|
||||||
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
|
||||||
.heart { font-size: 2.5rem; margin: 20px 0; color: var(--brown); }
|
|
||||||
|
|
||||||
.btn-primary {
|
|
||||||
background: var(--olive-green); color: var(--white); border: none; border-radius: 6px;
|
|
||||||
padding: 16px 30px; width: 100%; text-transform: uppercase; letter-spacing: 2px;
|
|
||||||
font-weight: 600; cursor: pointer; transition: background 0.3s;
|
|
||||||
}
|
|
||||||
.btn-primary:hover { background: var(--dark-green); }
|
|
||||||
.btn-outline { background: none; color: var(--dark-green); border: 1px solid var(--dark-green); margin-top: 20px; }
|
|
||||||
.btn-outline:hover { background: var(--bg-page); }
|
|
||||||
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
|
|
||||||
<div class="container">
|
|
||||||
<div id="main-ui">
|
|
||||||
<h1><?php echo $brautpaar_namen; ?></h1>
|
|
||||||
<div class="sub-header">Unsere Hochzeitsgalerie</div>
|
|
||||||
|
|
||||||
<div class="counter-box">
|
|
||||||
<span class="counter-number" id="live-counter"><?php echo $current_count; ?></span>
|
|
||||||
<span class="counter-label">Bilder wurden geteilt</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="tabs">
|
|
||||||
<button class="tab-btn active" id="btn-upload" onclick="switchTab('upload')">Hochladen</button>
|
|
||||||
<button class="tab-btn" id="btn-gallery" onclick="switchTab('gallery')">Galerie</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="upload-section">
|
|
||||||
<form id="upload-form">
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="upload-area" id="drop-area" onclick="document.getElementById('photos').click()">
|
|
||||||
<span style="display:block; margin-bottom: 10px; font-size: 2rem;">📸</span>
|
|
||||||
<span>Klicken zum Auswählen<br>oder Kamera öffnen</span>
|
|
||||||
<input type="file" id="photos" name="photos[]" accept="image/*" multiple style="display:none">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<div id="progress-wrapper">
|
|
||||||
<div id="status-text" style="font-size: 0.9rem; font-weight: 600; text-align: center;">Upload startet...</div>
|
|
||||||
<div class="progress-bar-container">
|
|
||||||
<div id="progress-bar"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="gallery-section">
|
|
||||||
<div class="gallery-grid">
|
|
||||||
<?php if (count($gallery_images) > 0): ?>
|
|
||||||
<?php foreach ($gallery_images as $img): ?>
|
|
||||||
<img src="uploads/<?php echo urlencode($img); ?>" class="gallery-item" loading="lazy" onclick="openLightbox(this.src)" alt="Hochzeitsfoto">
|
|
||||||
<?php endforeach; ?>
|
|
||||||
<?php else: ?>
|
|
||||||
<div class="empty-gallery">Noch keine Bilder hochgeladen. Sei der oder die Erste!</div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="success-ui" class="success-screen">
|
|
||||||
<div class="heart">♥</div>
|
|
||||||
<h2 style="font-family: 'Playfair Display', serif;">Vielen Dank!</h2>
|
|
||||||
<p>Deine Bilder wurden erfolgreich zur Galerie hinzugefügt.</p>
|
|
||||||
<button class="btn-primary btn-outline" onclick="location.reload()">Zur Galerie & Mehr teilen</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="lightbox" class="lightbox" onclick="closeLightbox(event)">
|
|
||||||
<span class="close-lightbox" onclick="closeLightbox(event)">×</span>
|
|
||||||
<img id="lightbox-img" src="" alt="Vollbild">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// --- Upload Logik ---
|
|
||||||
const fileInput = document.getElementById('photos');
|
|
||||||
const dropArea = document.getElementById('drop-area');
|
|
||||||
const counterDisplay = document.getElementById('live-counter');
|
|
||||||
const progressWrapper = document.getElementById('progress-wrapper');
|
|
||||||
const progressBar = document.getElementById('progress-bar');
|
|
||||||
const statusText = document.getElementById('status-text');
|
|
||||||
|
|
||||||
fileInput.onchange = () => {
|
|
||||||
const files = fileInput.files;
|
|
||||||
if(files.length === 0) return;
|
|
||||||
|
|
||||||
dropArea.classList.add('uploading');
|
|
||||||
dropArea.innerHTML = `<span style="display:block; margin-bottom: 10px; font-size: 2rem;">⏳</span><span>Wird verarbeitet...</span>`;
|
|
||||||
progressWrapper.style.display = 'block';
|
|
||||||
|
|
||||||
const formData = new FormData();
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
|
||||||
formData.append('photos[]', files[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
const xhr = new XMLHttpRequest();
|
|
||||||
xhr.open('POST', '', true);
|
|
||||||
|
|
||||||
xhr.upload.onprogress = (e) => {
|
|
||||||
if (e.lengthComputable) {
|
|
||||||
const percent = Math.round((e.loaded / e.total) * 100);
|
|
||||||
progressBar.style.width = percent + '%';
|
|
||||||
statusText.innerText = percent + '% hochgeladen...';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
xhr.onload = () => {
|
|
||||||
if (xhr.status === 200) {
|
|
||||||
const resp = JSON.parse(xhr.responseText);
|
|
||||||
if(resp.success) {
|
|
||||||
counterDisplay.innerText = resp.newTotal;
|
|
||||||
document.getElementById('main-ui').style.display = 'none';
|
|
||||||
document.getElementById('success-ui').style.display = 'block';
|
|
||||||
|
|
||||||
// FIX: Zentriert den Success-Screen wieder perfekt in der Mitte!
|
|
||||||
document.body.style.alignItems = 'center';
|
|
||||||
document.querySelector('.container').style.marginTop = '0';
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
alert("Fehler beim Upload. Bitte prüfe die Dateigröße.");
|
|
||||||
dropArea.classList.remove('uploading');
|
|
||||||
dropArea.innerHTML = `<span style="display:block; margin-bottom: 10px; font-size: 2rem;">📸</span><span>Klicken zum Auswählen<br>oder Kamera öffnen</span>`;
|
|
||||||
progressWrapper.style.display = 'none';
|
|
||||||
fileInput.value = '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
xhr.send(formData);
|
|
||||||
};
|
|
||||||
|
|
||||||
// --- Tabs Navigation ---
|
|
||||||
function switchTab(tab) {
|
|
||||||
document.getElementById('upload-section').style.display = tab === 'upload' ? 'block' : 'none';
|
|
||||||
document.getElementById('gallery-section').style.display = tab === 'gallery' ? 'block' : 'none';
|
|
||||||
|
|
||||||
document.getElementById('btn-upload').classList.toggle('active', tab === 'upload');
|
|
||||||
document.getElementById('btn-gallery').classList.toggle('active', tab === 'gallery');
|
|
||||||
}
|
|
||||||
|
|
||||||
// --- Lightbox Logik ---
|
|
||||||
const lightbox = document.getElementById('lightbox');
|
|
||||||
const lightboxImg = document.getElementById('lightbox-img');
|
|
||||||
|
|
||||||
function openLightbox(imageSrc) {
|
|
||||||
lightboxImg.src = imageSrc;
|
|
||||||
lightbox.classList.add('show');
|
|
||||||
document.body.style.overflow = 'hidden'; // Verhindert scrollen im Hintergrund
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeLightbox(e) {
|
|
||||||
// Schließt nur, wenn man aufs X oder den dunklen Hintergrund klickt (nicht aufs Bild selbst)
|
|
||||||
if (e.target === lightbox || e.target.className === 'close-lightbox') {
|
|
||||||
lightbox.classList.remove('show');
|
|
||||||
document.body.style.overflow = 'auto'; // Scrollen wieder erlauben
|
|
||||||
setTimeout(() => { lightboxImg.src = ''; }, 300); // Bild leeren nach Animation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
BIN
Hochzeit-G-stebuch/.DS_Store
vendored
BIN
Hochzeit-G-stebuch/.DS_Store
vendored
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
hello :)
|
|
||||||
434
index.php
434
index.php
@@ -1 +1,433 @@
|
|||||||
hello :)
|
<?php
|
||||||
|
$brautpaar_namen = "Damian & Melissa";
|
||||||
|
$upload_verzeichnis = __DIR__ . '/uploads/';
|
||||||
|
|
||||||
|
function get_image_count($dir) {
|
||||||
|
if (!is_dir($dir)) return 0;
|
||||||
|
$files = scandir($dir);
|
||||||
|
return count(array_filter($files, function($f) use ($dir) {
|
||||||
|
return is_file($dir . $f) && !str_starts_with($f, '.');
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
$current_count = get_image_count($upload_verzeichnis);
|
||||||
|
|
||||||
|
// Bilder für die Galerie laden (nur die neuesten 30, um Abstürze am Handy zu vermeiden)
|
||||||
|
$gallery_images = [];
|
||||||
|
if (is_dir($upload_verzeichnis)) {
|
||||||
|
$files = scandir($upload_verzeichnis);
|
||||||
|
$valid_files = [];
|
||||||
|
foreach ($files as $f) {
|
||||||
|
if (is_file($upload_verzeichnis . $f) && !str_starts_with($f, '.')) {
|
||||||
|
$valid_files[] = $f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZUVERLÄSSIGE SORTIERUNG: Alphabetisch absteigend, da Dateiname = Zeitstempel
|
||||||
|
rsort($valid_files);
|
||||||
|
|
||||||
|
$gallery_images = array_slice($valid_files, 0, 30);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_FILES['photos'])) {
|
||||||
|
$cleanName = 'Foto';
|
||||||
|
|
||||||
|
if (!is_dir($upload_verzeichnis)) {
|
||||||
|
mkdir($upload_verzeichnis, 0777, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$uploadedCount = 0;
|
||||||
|
foreach ($_FILES['photos']['tmp_name'] as $key => $tmpName) {
|
||||||
|
if ($tmpName != "") {
|
||||||
|
$extension = strtolower(pathinfo($_FILES['photos']['name'][$key], PATHINFO_EXTENSION));
|
||||||
|
$newName = $cleanName . '_' . time() . '_' . substr(md5(uniqid()), 0, 6) . '.' . $extension;
|
||||||
|
if (move_uploaded_file($tmpName, $upload_verzeichnis . $newName)) {
|
||||||
|
$uploadedCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
'success' => true,
|
||||||
|
'count' => $uploadedCount,
|
||||||
|
'newTotal' => get_image_count($upload_verzeichnis)
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="de">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Fotobox - <?php echo $brautpaar_namen; ?></title>
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,700;1,400&family=Montserrat:wght@300;400;600&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
/* Farbpalette */
|
||||||
|
--dark-green: #484D46;
|
||||||
|
--olive-green: #5F6251;
|
||||||
|
--brown: #856856;
|
||||||
|
--light-brown: #A88F79;
|
||||||
|
--beige: #BEB7AD;
|
||||||
|
--bg-page: #FAF9F7;
|
||||||
|
--white: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
* { box-sizing: border-box; }
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Montserrat', sans-serif;
|
||||||
|
background-color: var(--bg-page);
|
||||||
|
color: var(--dark-green);
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: flex-start; /* Wichtig für die Galerie */
|
||||||
|
min-height: 100vh;
|
||||||
|
padding: 20px;
|
||||||
|
transition: align-items 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
max-width: 500px;
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
background: var(--white);
|
||||||
|
padding: 40px 30px;
|
||||||
|
border-radius: 12px;
|
||||||
|
box-shadow: 0 10px 40px rgba(72, 77, 70, 0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
margin-top: 20px;
|
||||||
|
transition: margin-top 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-family: 'Playfair Display', serif;
|
||||||
|
font-size: clamp(1.2rem, 7vw, 2.5rem);
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
font-weight: 400;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
color: var(--dark-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sub-header {
|
||||||
|
font-size: 0.85rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 3px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-bottom: 1px solid var(--beige);
|
||||||
|
padding-bottom: 20px;
|
||||||
|
color: var(--light-brown);
|
||||||
|
}
|
||||||
|
|
||||||
|
.counter-box {
|
||||||
|
margin: 0 0 20px 0;
|
||||||
|
padding: 15px;
|
||||||
|
background: var(--beige);
|
||||||
|
border-radius: 8px;
|
||||||
|
color: var(--dark-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.counter-number {
|
||||||
|
display: block;
|
||||||
|
font-family: 'Playfair Display', serif;
|
||||||
|
font-size: 2.2rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.counter-label {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
opacity: 0.85;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tabs Navigation */
|
||||||
|
.tabs {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn {
|
||||||
|
background: var(--bg-page);
|
||||||
|
color: var(--light-brown);
|
||||||
|
border: 1px solid var(--beige);
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: 'Montserrat', sans-serif;
|
||||||
|
font-weight: 600;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-btn.active {
|
||||||
|
background: var(--olive-green);
|
||||||
|
color: var(--white);
|
||||||
|
border-color: var(--olive-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Upload Bereich */
|
||||||
|
.form-group { margin-bottom: 25px; text-align: left; }
|
||||||
|
|
||||||
|
.upload-area {
|
||||||
|
border: 2px dashed var(--light-brown);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 40px 30px;
|
||||||
|
cursor: pointer;
|
||||||
|
background-color: var(--white);
|
||||||
|
transition: all 0.3s;
|
||||||
|
color: var(--olive-green);
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-area:hover {
|
||||||
|
background: var(--bg-page);
|
||||||
|
border-color: var(--olive-green);
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-area.uploading {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Progress Bar */
|
||||||
|
#progress-wrapper { display: none; margin-top: 20px; text-align: left; }
|
||||||
|
.progress-bar-container {
|
||||||
|
width: 100%; height: 6px; background: var(--beige);
|
||||||
|
margin-top: 10px; border-radius: 3px; overflow: hidden;
|
||||||
|
}
|
||||||
|
#progress-bar { height: 100%; background: var(--olive-green); width: 0%; transition: width 0.2s; }
|
||||||
|
|
||||||
|
/* Galerie Bereich */
|
||||||
|
#gallery-section { display: none; }
|
||||||
|
.gallery-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-item {
|
||||||
|
width: 100%;
|
||||||
|
aspect-ratio: 1 / 1;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: transform 0.2s;
|
||||||
|
background-color: var(--beige);
|
||||||
|
}
|
||||||
|
|
||||||
|
.gallery-item:hover { transform: scale(1.03); }
|
||||||
|
|
||||||
|
.empty-gallery {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
color: var(--light-brown);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Lightbox (Vollbild) */
|
||||||
|
.lightbox {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
z-index: 9999;
|
||||||
|
top: 0; left: 0; width: 100%; height: 100%;
|
||||||
|
background-color: rgba(72, 77, 70, 0.95);
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightbox.show { display: flex; opacity: 1; }
|
||||||
|
|
||||||
|
.lightbox img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 90vh;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0,0,0,0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-lightbox {
|
||||||
|
position: absolute;
|
||||||
|
top: 20px; right: 30px;
|
||||||
|
color: var(--white);
|
||||||
|
font-size: 40px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-family: sans-serif;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Success Screen */
|
||||||
|
.success-screen { display: none; animation: fadeIn 0.5s ease; }
|
||||||
|
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
|
||||||
|
.heart { font-size: 2.5rem; margin: 20px 0; color: var(--brown); }
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background: var(--olive-green); color: var(--white); border: none; border-radius: 6px;
|
||||||
|
padding: 16px 30px; width: 100%; text-transform: uppercase; letter-spacing: 2px;
|
||||||
|
font-weight: 600; cursor: pointer; transition: background 0.3s;
|
||||||
|
}
|
||||||
|
.btn-primary:hover { background: var(--dark-green); }
|
||||||
|
.btn-outline { background: none; color: var(--dark-green); border: 1px solid var(--dark-green); margin-top: 20px; }
|
||||||
|
.btn-outline:hover { background: var(--bg-page); }
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div id="main-ui">
|
||||||
|
<h1><?php echo $brautpaar_namen; ?></h1>
|
||||||
|
<div class="sub-header">Unsere Hochzeitsgalerie</div>
|
||||||
|
|
||||||
|
<div class="counter-box">
|
||||||
|
<span class="counter-number" id="live-counter"><?php echo $current_count; ?></span>
|
||||||
|
<span class="counter-label">Bilder wurden geteilt</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="tabs">
|
||||||
|
<button class="tab-btn active" id="btn-upload" onclick="switchTab('upload')">Hochladen</button>
|
||||||
|
<button class="tab-btn" id="btn-gallery" onclick="switchTab('gallery')">Galerie</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="upload-section">
|
||||||
|
<form id="upload-form">
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="upload-area" id="drop-area" onclick="document.getElementById('photos').click()">
|
||||||
|
<span style="display:block; margin-bottom: 10px; font-size: 2rem;">📸</span>
|
||||||
|
<span>Klicken zum Auswählen<br>oder Kamera öffnen</span>
|
||||||
|
<input type="file" id="photos" name="photos[]" accept="image/*" multiple style="display:none">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<div id="progress-wrapper">
|
||||||
|
<div id="status-text" style="font-size: 0.9rem; font-weight: 600; text-align: center;">Upload startet...</div>
|
||||||
|
<div class="progress-bar-container">
|
||||||
|
<div id="progress-bar"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="gallery-section">
|
||||||
|
<div class="gallery-grid">
|
||||||
|
<?php if (count($gallery_images) > 0): ?>
|
||||||
|
<?php foreach ($gallery_images as $img): ?>
|
||||||
|
<img src="uploads/<?php echo urlencode($img); ?>" class="gallery-item" loading="lazy" onclick="openLightbox(this.src)" alt="Hochzeitsfoto">
|
||||||
|
<?php endforeach; ?>
|
||||||
|
<?php else: ?>
|
||||||
|
<div class="empty-gallery">Noch keine Bilder hochgeladen. Sei der oder die Erste!</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="success-ui" class="success-screen">
|
||||||
|
<div class="heart">♥</div>
|
||||||
|
<h2 style="font-family: 'Playfair Display', serif;">Vielen Dank!</h2>
|
||||||
|
<p>Deine Bilder wurden erfolgreich zur Galerie hinzugefügt.</p>
|
||||||
|
<button class="btn-primary btn-outline" onclick="location.reload()">Zur Galerie & Mehr teilen</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="lightbox" class="lightbox" onclick="closeLightbox(event)">
|
||||||
|
<span class="close-lightbox" onclick="closeLightbox(event)">×</span>
|
||||||
|
<img id="lightbox-img" src="" alt="Vollbild">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// --- Upload Logik ---
|
||||||
|
const fileInput = document.getElementById('photos');
|
||||||
|
const dropArea = document.getElementById('drop-area');
|
||||||
|
const counterDisplay = document.getElementById('live-counter');
|
||||||
|
const progressWrapper = document.getElementById('progress-wrapper');
|
||||||
|
const progressBar = document.getElementById('progress-bar');
|
||||||
|
const statusText = document.getElementById('status-text');
|
||||||
|
|
||||||
|
fileInput.onchange = () => {
|
||||||
|
const files = fileInput.files;
|
||||||
|
if(files.length === 0) return;
|
||||||
|
|
||||||
|
dropArea.classList.add('uploading');
|
||||||
|
dropArea.innerHTML = `<span style="display:block; margin-bottom: 10px; font-size: 2rem;">⏳</span><span>Wird verarbeitet...</span>`;
|
||||||
|
progressWrapper.style.display = 'block';
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
formData.append('photos[]', files[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open('POST', '', true);
|
||||||
|
|
||||||
|
xhr.upload.onprogress = (e) => {
|
||||||
|
if (e.lengthComputable) {
|
||||||
|
const percent = Math.round((e.loaded / e.total) * 100);
|
||||||
|
progressBar.style.width = percent + '%';
|
||||||
|
statusText.innerText = percent + '% hochgeladen...';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onload = () => {
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
const resp = JSON.parse(xhr.responseText);
|
||||||
|
if(resp.success) {
|
||||||
|
counterDisplay.innerText = resp.newTotal;
|
||||||
|
document.getElementById('main-ui').style.display = 'none';
|
||||||
|
document.getElementById('success-ui').style.display = 'block';
|
||||||
|
|
||||||
|
// FIX: Zentriert den Success-Screen wieder perfekt in der Mitte!
|
||||||
|
document.body.style.alignItems = 'center';
|
||||||
|
document.querySelector('.container').style.marginTop = '0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert("Fehler beim Upload. Bitte prüfe die Dateigröße.");
|
||||||
|
dropArea.classList.remove('uploading');
|
||||||
|
dropArea.innerHTML = `<span style="display:block; margin-bottom: 10px; font-size: 2rem;">📸</span><span>Klicken zum Auswählen<br>oder Kamera öffnen</span>`;
|
||||||
|
progressWrapper.style.display = 'none';
|
||||||
|
fileInput.value = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xhr.send(formData);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Tabs Navigation ---
|
||||||
|
function switchTab(tab) {
|
||||||
|
document.getElementById('upload-section').style.display = tab === 'upload' ? 'block' : 'none';
|
||||||
|
document.getElementById('gallery-section').style.display = tab === 'gallery' ? 'block' : 'none';
|
||||||
|
|
||||||
|
document.getElementById('btn-upload').classList.toggle('active', tab === 'upload');
|
||||||
|
document.getElementById('btn-gallery').classList.toggle('active', tab === 'gallery');
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Lightbox Logik ---
|
||||||
|
const lightbox = document.getElementById('lightbox');
|
||||||
|
const lightboxImg = document.getElementById('lightbox-img');
|
||||||
|
|
||||||
|
function openLightbox(imageSrc) {
|
||||||
|
lightboxImg.src = imageSrc;
|
||||||
|
lightbox.classList.add('show');
|
||||||
|
document.body.style.overflow = 'hidden'; // Verhindert scrollen im Hintergrund
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeLightbox(e) {
|
||||||
|
// Schließt nur, wenn man aufs X oder den dunklen Hintergrund klickt (nicht aufs Bild selbst)
|
||||||
|
if (e.target === lightbox || e.target.className === 'close-lightbox') {
|
||||||
|
lightbox.classList.remove('show');
|
||||||
|
document.body.style.overflow = 'auto'; // Scrollen wieder erlauben
|
||||||
|
setTimeout(() => { lightboxImg.src = ''; }, 300); // Bild leeren nach Animation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user