philippurbschat.de/plants/index.php

341 lines
25 KiB
PHP

<?php
// Version: 01.10.2025 16:15 (FINAL & COMPLETE)
$current_project = 'plants';
require_once '../auth.php';
session_start();
$is_logged_in = isset($_SESSION['user_id']);
$username = $_SESSION['username'] ?? '';
$user_theme = 'auto';
if ($is_logged_in) {
require_once 'db.php';
try {
$stmt = $pdo->prepare("SELECT theme FROM users WHERE id = ?");
$stmt->execute([$_SESSION['user_id']]);
$result = $stmt->fetch();
if ($result && !empty($result['theme'])) {
$user_theme = $result['theme'];
}
} catch (PDOException $e) {
// Fehler ignorieren
}
}
?>
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Plants</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Alan+Sans:wght@300;400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="components.css">
</head>
<body data-theme="<?php echo htmlspecialchars($user_theme); ?>">
<?php if ($is_logged_in): ?>
<header class="main-header">
<div class="container">
<div class="logo-title-container">
<img src="img/logo.webp" alt="Plants App Logo" class="header-logo">
<h1>Plants</h1>
</div>
<div class="header-controls">
<a href="lexikon.php" id="lexiconBtn" class="add-btn icon-btn" title="Lexikon">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"></path><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"></path></svg>
</a>
<div class="header-button-group">
<button id="addPlantBtn" class="add-btn">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
<span>Hinzufügen</span>
</button>
<button id="settingsBtn" class="add-btn icon-btn" title="Einstellungen">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
</button>
</div>
</div>
</div>
</header>
<main class="container">
<div id="dashboard-main-content">
<div class="dashboard-controls">
<div class="sort-container">
<select id="sortSelect">
<option value="date_desc">Neueste zuerst</option>
<option value="name_asc">Name (A-Z)</option>
<option value="watering_due">Gießen (bald fällig)</option>
</select>
</div>
<div class="view-toggle">
<button id="viewGridBtn" class="view-btn active" title="Grid-Ansicht">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7"></rect><rect x="14" y="3" width="7" height="7"></rect><rect x="14" y="14" width="7" height="7"></rect><rect x="3" y="14" width="7" height="7"></rect></svg>
</button>
<button id="viewListBtn" class="view-btn" title="Listen-Ansicht">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="6" x2="21" y2="6"></line><line x1="8" y1="12" x2="21" y2="12"></line><line x1="8" y1="18" x2="21" y2="18"></line><line x1="3" y1="6" x2="3.01" y2="6"></line><line x1="3" y1="12" x2="3.01" y2="12"></line><line x1="3" y1="18" x2="3.01" y2="18"></line></svg>
</button>
</div>
</div>
<div id="plant-dashboard" class="plant-grid">
<!-- Inhalt wird von main.js geladen -->
</div>
</div>
</main>
<!-- =========== MODALS =========== -->
<div id="plantModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h2 id="modalTitle">Neue Pflanze hinzufügen</h2>
<button class="close-btn">&times;</button>
</div>
<div id="formContent" class="modal-body">
<form id="plantForm" enctype="multipart/form-data">
<input type="hidden" id="plantId" name="id">
<input type="hidden" id="currentPhoto" name="current_photo">
<input type="hidden" id="aiFullResponse" name="ai_full_response_json">
<input type="hidden" id="aiEnrichmentResponse" name="ai_enrichment_json">
<div class="form-group-upload">
<div id="initialUploadArea" class="upload-area">
<button type="button" id="startCameraBtn" class="btn"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path><circle cx="12" cy="13" r="4"></circle></svg><span>Kamera</span></button>
<label for="plantPhoto" class="btn btn-secondary"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 15 9 5 19"></polyline></svg><span>Auswählen</span></label>
</div>
<div id="imagePreviewContainer" class="image-preview-wrapper" style="display: none;">
<img id="imagePreview" src="#" alt="Vorschau">
<div class="ai-animation-overlay">
<div class="ai-loader"></div>
<div class="ai-analysis-text">Analysiere...</div>
</div>
<div class="preview-actions">
<label for="plantPhoto" class="card-btn" title="Datei auswählen"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg></label>
<button type="button" id="retakePhotoBtn" class="card-btn" title="Neues Foto aufnehmen"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path><circle cx="12" cy="13" r="4"></circle></svg></button>
</div>
</div>
<input type="file" id="plantPhoto" name="photo" accept="image/*" style="display: none;">
</div>
<div id="ai-analysis-section" class="form-group" style="display: none;"><button type="button" id="analyzeBtn" class="btn btn-ai"><span role="img" aria-label="magic wand">✨</span><span>Automatisch erkennen</span></button></div>
<div class="form-group"><label for="plantName">Name der Pflanze</label><input type="text" id="plantName" name="name" required><button type="button" id="retryAiBtn" class="btn-retry" style="display: none;">Falsche Pflanze? Erneut versuchen.</button></div>
<div class="form-group"><label for="latinName">Botanischer Name (optional)</label><input type="text" id="latinName" name="latin_name"></div>
<div class="form-group"><label for="wateringInterval">Gießintervall (in Tagen)</label><input type="number" id="wateringInterval" name="watering_interval"></div>
<div class="form-group"><label for="fertilizingInterval">Düngeintervall (in Tagen)</label><input type="number" id="fertilizingInterval" name="fertilizing_interval"></div>
<div class="form-group"><label for="careTips">Pflegetipps</label><textarea id="careTips" name="care_tips" rows="4"></textarea></div>
<div class="form-actions"><button type="submit" class="btn">Pflanze speichern</button></div>
</form>
</div>
<div id="cameraView" class="modal-body" style="display: none;">
<div class="video-container"><video id="videoElement" autoplay></video><div class="viewfinder-overlay"><div class="viewfinder-corner top-left"></div><div class="viewfinder-corner top-right"></div><div class="viewfinder-corner bottom-left"></div><div class="viewfinder-corner bottom-right"></div><div class="viewfinder-focus-point"></div></div></div>
<div class="camera-controls"><button id="captureBtn" class="btn">Foto aufnehmen</button></div>
<canvas id="photoCanvas" style="display: none;"></canvas>
</div>
</div>
</div>
<div id="diaryModal" class="modal">
<div class="modal-content diary-modal-content">
<div class="modal-header"><h2 id="diaryPlantName">Tagebuch</h2><button class="close-btn">&times;</button></div>
<div id="diaryModalBody" class="modal-body"><div id="diaryContentWrapper"><div id="diaryContent" class="diary-timeline"></div></div><div id="diaryCameraView" style="display: none;"><div class="video-container"><video id="diaryVideoElement" autoplay></video><div class="viewfinder-overlay"><div class="viewfinder-corner top-left"></div><div class="viewfinder-corner top-right"></div><div class="viewfinder-corner bottom-left"></div><div class="viewfinder-corner bottom-right"></div><div class="viewfinder-focus-point"></div></div></div><div class="camera-controls"><button id="diaryCaptureBtn" class="btn">Foto aufnehmen</button></div><canvas id="diaryPhotoCanvas" style="display: none;"></canvas></div></div>
<div class="modal-footer"><form id="diaryForm" class="diary-form" enctype="multipart/form-data"><input type="hidden" id="diaryPlantId" name="plant_id"><div id="diaryFormContent"><div class="form-group"><textarea name="notes" class="diary-input" placeholder="Neue Notiz hinzufügen..." rows="2"></textarea></div><div class="diary-form-options"><div class="diary-form-attachments"><div id="diaryInitialUploadArea" class="upload-area small"><button type="button" id="startDiaryCameraBtn" class="btn"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path><circle cx="12" cy="13" r="4"></circle></svg></button><label for="diaryPhoto" class="btn btn-secondary"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 15 9 5 19"></polyline></svg></label></div><div id="diaryImagePreviewContainer" class="image-preview-wrapper small" style="display: none;"><img id="diaryImagePreview" src="#" alt="Vorschau"><button type="button" id="removeDiaryPhotoBtn" class="remove-photo-btn">&times;</button></div><input type="file" id="diaryPhoto" name="photo" accept="image/*" style="display:none;"></div><div class="diary-form-milestone"><input type="checkbox" id="is_milestone" name="is_milestone"><label for="is_milestone">⭐ Meilenstein</label></div></div><button type="submit" class="btn">Eintragen</button></div></form></div>
</div>
</div>
<div id="settingsModal" class="modal">
<div class="modal-content settings-modal-content">
<div class="modal-header">
<h2>Einstellungen</h2>
<button class="close-btn">&times;</button>
</div>
<div class="modal-body">
<div class="settings-profile-banner">
<div class="profile-pic-container">
<img src="" alt="Profilbild" class="profile-pic" id="settings-profile-pic">
<button class="btn-change-pic" title="Bild ändern">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"><path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z"></path><circle cx="12" cy="13" r="4"></circle></svg>
</button>
</div>
<div class="profile-info">
<span class="profile-username" id="settings-username"></span>
<button class="btn-edit-username" title="Namen ändern">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z"></path></svg>
</button>
</div>
</div>
<div class="settings-card">
<h3>Statistiken</h3>
<div class="settings-row">
<span>Anzahl Pflanzen</span>
<span class="settings-value" id="stats-plant-count">...</span>
</div>
<div class="settings-row">
<span>Verbleibende KI-Aktionen</span>
<span class="settings-value" id="stats-ai-credits">...</span>
</div>
</div>
<div class="settings-card">
<h3>Automatisierung</h3>
<div class="settings-row">
<span>Gießintervall vorschlagen</span>
<label class="toggle-switch">
<input type="checkbox" id="auto-fill-watering">
<span class="slider"></span>
</label>
</div>
<div class="settings-row">
<span>Düngeintervall vorschlagen</span>
<label class="toggle-switch">
<input type="checkbox" id="auto-fill-fertilizing">
<span class="slider"></span>
</label>
</div>
<div class="settings-row">
<span>Pflegetipps vorschlagen</span>
<label class="toggle-switch">
<input type="checkbox" id="auto-fill-care-tips">
<span class="slider"></span>
</label>
</div>
</div>
<div class="settings-card">
<h3>Privatsphäre</h3>
<div class="settings-row">
<div>
<span>Fotos öffentlich teilen</span>
<p class="settings-description">Erlaube, dass deine schönsten Pflanzenfotos anonym im öffentlichen Lexikon gezeigt werden.</p>
</div>
<label class="toggle-switch">
<input type="checkbox" id="allow-photo-sharing">
<span class="slider"></span>
</label>
</div>
</div>
<div class="settings-card">
<h3>Benachrichtigungen</h3>
<div class="settings-row">
<span>Gießen (Push)</span>
<label class="toggle-switch"><input type="checkbox" id="notify-watering-push"><span class="slider"></span></label>
</div>
<div class="settings-row">
<span>Gießen (E-Mail)</span>
<label class="toggle-switch"><input type="checkbox" id="notify-watering-email"><span class="slider"></span></label>
</div>
<div class="settings-row">
<span>Düngen (Push)</span>
<label class="toggle-switch"><input type="checkbox" id="notify-fertilizing-push"><span class="slider"></span></label>
</div>
<div class="settings-row">
<span>Düngen (E-Mail)</span>
<label class="toggle-switch"><input type="checkbox" id="notify-fertilizing-email"><span class="slider"></span></label>
</div>
<div class="settings-row">
<span>Newsletter</span>
<label class="toggle-switch"><input type="checkbox" id="notify-newsletter"><span class="slider"></span></label>
</div>
</div>
<div class="settings-card">
<h3>Darstellung</h3>
<div class="settings-row">
<span>Theme</span>
<div class="theme-selector">
<button class="theme-btn" data-theme="light">Hell</button>
<button class="theme-btn" data-theme="dark">Dunkel</button>
<button class="theme-btn" data-theme="auto">Auto</button>
</div>
</div>
</div>
<div class="settings-card">
<h3>Konto verwalten</h3>
<button class="btn btn-secondary full-width" id="changePasswordBtn">Passwort ändern</button>
<button class="btn btn-secondary full-width" id="logoutBtn">Ausloggen</button>
<button class="btn btn-danger full-width" id="deleteAccountBtn">Konto löschen</button>
</div>
</div>
</div>
</div>
<div id="plantDetailOverlay" class="plant-detail-overlay">
<div id="plantDetailContent" class="plant-detail-content"></div>
<button id="plantDetailCloseBtn" class="plant-detail-close-btn">&times;</button>
</div>
<!-- =========== MODAL für LEXIKON-DETAILS (NEU) =========== -->
<div id="lexiconDetailModal" class="modal">
<div class="modal-content lexicon-detail-modal-content">
<div class="modal-header">
<h2 id="lexiconModalPlantName">Pflanzen-Detail</h2>
<button class="close-btn">&times;</button>
</div>
<div class="modal-body">
<div class="lexicon-modal-layout">
<div class="lexicon-modal-image-gallery">
<div class="lexicon-modal-image-container">
<img id="lexiconModalImage" src="" alt="Pflanzenbild">
</div>
<div class="lexicon-modal-thumbnails">
<!-- Thumbnails werden hier von lexikon.js eingefügt -->
</div>
</div>
<div class="lexicon-modal-info">
<span id="lexiconModalLatinName" class="lexicon-modal-latin"></span>
<div class="lexicon-modal-meta">
<div>
<strong>Familie:</strong>
<span id="lexiconModalFamily"></span>
</div>
<div>
<strong>Gattung:</strong>
<span id="lexiconModalGenus"></span>
</div>
</div>
<div class="lexicon-modal-description">
<!-- Beschreibung wird hier von lexikon.js eingefügt -->
</div>
</div>
</div>
</div>
</div>
</div>
<script type="module" src="main.js"></script>
<?php else: ?>
<div class="auth-container">
<div class="auth-box">
<div class="logo-title-container"><img src="img/logo.webp" alt="Plants App Logo" class="header-logo"><h1>Plants</h1></div>
<div id="login-form-container">
<h2>Willkommen zurück!</h2><p class="auth-subtitle">Bitte logge dich ein, um deine Pflanzen zu sehen.</p>
<form id="loginForm">
<div class="form-group"><label for="loginEmail">E-Mail</label><input type="email" id="loginEmail" name="email" required autocomplete="email"></div>
<div class="form-group"><label for="loginPassword">Passwort</label><input type="password" id="loginPassword" name="password" required autocomplete="current-password"></div>
<button type="submit" class="btn auth-btn">Einloggen</button>
</form>
<p class="auth-switch">Noch kein Konto? <a href="#" id="showRegister">Jetzt registrieren</a></p>
</div>
<div id="register-form-container" style="display: none;">
<h2>Erstelle dein Konto</h2><p class="auth-subtitle">Verwalte deine grünen Freunde an einem Ort.</p>
<form id="registerForm">
<div class="form-group"><label for="registerUsername">Dein Name</label><input type="text" id="registerUsername" name="username" required autocomplete="name"></div>
<div class="form-group"><label for="registerEmail">E-Mail</label><input type="email" id="registerEmail" name="email" required autocomplete="email"></div>
<div class="form-group"><label for="registerPassword">Passwort (min. 8 Zeichen)</label><input type="password" id="registerPassword" name="password" required autocomplete="new-password"></div>
<button type="submit" class="btn auth-btn">Konto erstellen</button>
</form>
<p class="auth-switch">Schon dabei? <a href="#" id="showLogin">Zum Login</a></p>
</div>
</div>
</div>
<script type="module" src="auth.js"></script>
<?php endif; ?>
</body>
</html>