diff --git a/README.md b/README.md index f8969cf..8559d8f 100644 --- a/README.md +++ b/README.md @@ -228,3 +228,9 @@ Das Projekt basiert auf bewährten Web-Standards: * **Strukturierte Anzeige in der Box-Ansicht:** Die öffentliche Ansicht eines Lagerorts per QR-Code (`public_location.php`) zeigt nun Artikelrelationen (z.B. Zubehör innerhalb eines Hauptartikels) hierarchisch eingerückt an. * **Fixes:** * Die störende JavaScript `confirm()`-Meldung beim Löschen von Artikeln in der Übersicht (`articles.php`) wurde durch ein einheitliches, modernes Bootstrap-Modal ersetzt. + +### 19.06.2026 +* **Features:** + * **Notizen:** Neue Funktion "Notizen" hinzugefügt inkl. Rich-Text-Editor. + * **Haushaltsfreigabe:** Notizen können mit dem Haushalt geteilt werden. + * **Design-Update:** Die Notizen-Übersichtsseite nutzt nun eine Split-View (Liste links, Inhalt rechts). diff --git a/fix_files.php b/fix_files.php new file mode 100644 index 0000000..b23740a --- /dev/null +++ b/fix_files.php @@ -0,0 +1,15 @@ +"); +if ($pos1 !== false) { + file_put_contents($f1, substr($c1, 0, $pos1 + strlen("")) . "\n"); +} + +$f2 = '/entwicklung/packliste/src/storage_locations.php'; +$c2 = file_get_contents($f2); +$pos2 = strpos($c2, ""); +if ($pos2 !== false) { + file_put_contents($f2, substr($c2, 0, $pos2 + strlen("")) . "\n"); +} +echo "Cleaned up file endings.\n"; diff --git a/packliste.sql b/packliste.sql index 8f92b93..52e1e3b 100644 --- a/packliste.sql +++ b/packliste.sql @@ -528,3 +528,23 @@ CREATE TABLE `todo_lists` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int( CREATE TABLE `todo_items` ( `id` int(11) NOT NULL AUTO_INCREMENT, `todo_list_id` int(11) NOT NULL, `title` varchar(255) NOT NULL, `is_completed` tinyint(1) DEFAULT 0, `order_index` int(11) DEFAULT 0, PRIMARY KEY (`id`), KEY `todo_list_id` (`todo_list_id`), CONSTRAINT `fk_todo_items_list` FOREIGN KEY (`todo_list_id`) REFERENCES `todo_lists` (`id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; ALTER TABLE `packing_lists` ADD COLUMN `todo_list_id` int(11) DEFAULT NULL; ALTER TABLE `packing_lists` ADD CONSTRAINT `fk_packing_list_todo` FOREIGN KEY (`todo_list_id`) REFERENCES `todo_lists` (`id`) ON DELETE SET NULL; + +-- +-- Table structure for table `notes` +-- +DROP TABLE IF EXISTS `notes`; +CREATE TABLE `notes` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `household_id` int(11) DEFAULT NULL, + `title` varchar(255) NOT NULL, + `content` text NOT NULL, + `is_shared` tinyint(1) DEFAULT 0, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + KEY `user_id` (`user_id`), + KEY `household_id` (`household_id`), + CONSTRAINT `notes_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, + CONSTRAINT `notes_ibfk_2` FOREIGN KEY (`household_id`) REFERENCES `households` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; diff --git a/src/add_note.php b/src/add_note.php new file mode 100644 index 0000000..0ccfa2b --- /dev/null +++ b/src/add_note.php @@ -0,0 +1,124 @@ +prepare("SELECT household_id FROM users WHERE id = ?"); +$stmt_household->bind_param("i", $current_user_id); +$stmt_household->execute(); +$current_user_household_id = $stmt_household->get_result()->fetch_assoc()['household_id']; +$stmt_household->close(); + +$error = ''; + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $title = trim($_POST['title'] ?? ''); + $content = $_POST['content'] ?? ''; + $is_shared = isset($_POST['is_shared']) ? 1 : 0; + + if (empty($title)) { + $error = "Bitte gib einen Titel ein."; + } else { + $stmt = $conn->prepare("INSERT INTO notes (user_id, household_id, title, content, is_shared) VALUES (?, ?, ?, ?, ?)"); + $stmt->bind_param("iissi", $current_user_id, $current_user_household_id, $title, $content, $is_shared); + if ($stmt->execute()) { + $new_id = $stmt->insert_id; + header("Location: edit_note.php?id=$new_id&success=1"); + exit; + } else { + $error = "Fehler beim Speichern der Notiz."; + } + $stmt->close(); + } +} + +$page_title = "Neue Notiz"; +require_once 'header.php'; +?> + + + + +
+
+
+
+

Neue Notiz erstellen

+ Zurück zur Übersicht +
+ + +
+ + +
+
+
+
+ + +
+ +
+ +
+ +
+ + +
+ > + +
Andere Mitglieder deines Haushalts können diese Notiz sehen und bearbeiten.
+
+ + +
+ Abbrechen + +
+
+
+
+
+
+
+ + + + + diff --git a/src/db_connect.php b/src/db_connect.php index 35951b2..75232ff 100644 --- a/src/db_connect.php +++ b/src/db_connect.php @@ -68,4 +68,18 @@ $check_loc_token = $conn->query("SHOW COLUMNS FROM storage_locations LIKE 'publi if ($check_loc_token && $check_loc_token->num_rows == 0) { $conn->query("ALTER TABLE storage_locations ADD COLUMN public_token VARCHAR(64) UNIQUE DEFAULT NULL"); } + +// Ensure notes table exists +$conn->query("CREATE TABLE IF NOT EXISTS notes ( + id INT AUTO_INCREMENT PRIMARY KEY, + user_id INT NOT NULL, + household_id INT DEFAULT NULL, + title VARCHAR(255) NOT NULL, + content TEXT NOT NULL, + is_shared TINYINT(1) DEFAULT 0, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, + FOREIGN KEY (household_id) REFERENCES households(id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci"); ?> diff --git a/src/delete_note.php b/src/delete_note.php new file mode 100644 index 0000000..f2f6348 --- /dev/null +++ b/src/delete_note.php @@ -0,0 +1,21 @@ +prepare("DELETE FROM notes WHERE id = ? AND user_id = ?"); + $stmt->bind_param("ii", $note_id, $current_user_id); + $stmt->execute(); + $stmt->close(); +} + +header("Location: notes.php"); +exit; diff --git a/src/edit_note.php b/src/edit_note.php new file mode 100644 index 0000000..7fa098a --- /dev/null +++ b/src/edit_note.php @@ -0,0 +1,217 @@ +prepare("SELECT household_id FROM users WHERE id = ?"); +$stmt_household->bind_param("i", $current_user_id); +$stmt_household->execute(); +$current_user_household_id = $stmt_household->get_result()->fetch_assoc()['household_id']; +$stmt_household->close(); + +$error = ''; +$success = ''; + +if (isset($_GET['success']) && $_GET['success'] == 1) { + $success = "Notiz erfolgreich gespeichert."; +} + +$note_id = isset($_GET['id']) ? intval($_GET['id']) : (isset($_POST['id']) ? intval($_POST['id']) : 0); + +if (!$note_id) { + header("Location: notes.php"); + exit; +} + +// Fetch note to check permissions +$stmt = $conn->prepare("SELECT * FROM notes WHERE id = ?"); +$stmt->bind_param("i", $note_id); +$stmt->execute(); +$note = $stmt->get_result()->fetch_assoc(); +$stmt->close(); + +if (!$note) { + header("Location: notes.php"); + exit; +} + +$can_edit = false; +if ($note['user_id'] == $current_user_id) { + $can_edit = true; +} else if ($note['household_id'] == $current_user_household_id && $note['is_shared']) { + $can_edit = true; +} + +if (!$can_edit) { + header("Location: notes.php"); + exit; +} + +if ($_SERVER['REQUEST_METHOD'] === 'POST') { + $title = trim($_POST['title'] ?? ''); + $content = $_POST['content'] ?? ''; + $is_shared = isset($_POST['is_shared']) ? 1 : 0; + + if (empty($title)) { + $error = "Bitte gib einen Titel ein."; + } else { + if ($note['user_id'] == $current_user_id) { + $stmt = $conn->prepare("UPDATE notes SET title = ?, content = ?, is_shared = ? WHERE id = ?"); + $stmt->bind_param("ssii", $title, $content, $is_shared, $note_id); + } else { + // Wenn nicht Owner, darf er Titel & Content ändern, aber nicht is_shared + $stmt = $conn->prepare("UPDATE notes SET title = ?, content = ? WHERE id = ?"); + $stmt->bind_param("ssi", $title, $content, $note_id); + } + + if ($stmt->execute()) { + $success = "Notiz erfolgreich aktualisiert."; + // Refresh note data + $stmt_refresh = $conn->prepare("SELECT * FROM notes WHERE id = ?"); + $stmt_refresh->bind_param("i", $note_id); + $stmt_refresh->execute(); + $note = $stmt_refresh->get_result()->fetch_assoc(); + $stmt_refresh->close(); + } else { + $error = "Fehler beim Speichern der Notiz."; + } + $stmt->close(); + } +} + +$page_title = "Notiz bearbeiten"; +require_once 'header.php'; +?> + + + + +
+
+
+
+

Notiz bearbeiten

+ Zurück zur Übersicht +
+ + +
+ + + +
+ + +
+ + +
+
+
+ + +
+ + +
+ +
+ + +
+ +
+ + +
+ > + +
+ +
+ Diese Notiz wird mit dem Haushalt geteilt. +
+ + +
+ + + + Abbrechen + +
+
+
+
+
+
+
+ + + + + + + + diff --git a/src/header.php b/src/header.php index 88cfec2..0c6921c 100644 --- a/src/header.php +++ b/src/header.php @@ -72,6 +72,7 @@ if (isset($_SESSION['user_id'])) { + diff --git a/src/notes.php b/src/notes.php new file mode 100644 index 0000000..217ea7b --- /dev/null +++ b/src/notes.php @@ -0,0 +1,209 @@ +prepare("SELECT household_id FROM users WHERE id = ?"); +$stmt_household->bind_param("i", $current_user_id); +$stmt_household->execute(); +$current_user_household_id = $stmt_household->get_result()->fetch_assoc()['household_id']; +$stmt_household->close(); + +// Fetch notes list +$sql = "SELECT n.*, u.username as owner_name + FROM notes n + JOIN users u ON n.user_id = u.id + WHERE n.user_id = ? OR (n.household_id = ? AND n.is_shared = 1 AND n.household_id IS NOT NULL) + ORDER BY n.updated_at DESC"; +$stmt = $conn->prepare($sql); +$stmt->bind_param("ii", $current_user_id, $current_user_household_id); +$stmt->execute(); +$result = $stmt->get_result(); +$notes = []; +while ($row = $result->fetch_assoc()) { + $notes[] = $row; +} +$stmt->close(); + +// Check if a specific note is selected +$active_note = null; +$active_note_id = isset($_GET['id']) ? intval($_GET['id']) : null; + +if ($active_note_id) { + foreach ($notes as $note) { + if ($note['id'] == $active_note_id) { + $active_note = $note; + break; + } + } +} +?> + + + + + +
+
+

Notizen

+ Neue Notiz +
+ +
+ +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + +
Titel & StatusAktionen
Keine Notizen vorhanden.
+
+ +
+
+ + Ich + + + + + + + +
+
+ + + + + + +
+
+
+
+
+ + +
+ +
+
+
+

+
+
Zuletzt geändert:
+ +
Mit Haushalt geteilt
+ +
+
+
+
+ +
+
+ +
+
+ +
+
+ +

Keine Notiz ausgewählt

+

Wähle links eine Notiz aus der Liste, um ihren Inhalt hier zu lesen.

+ + Jetzt eine Notiz erstellen + +
+
+ +
+
+
+ + + + + + +