diff --git a/api/index.php b/api/index.php index 23bfb5b..7786135 100644 --- a/api/index.php +++ b/api/index.php @@ -1000,6 +1000,18 @@ try { case 'recipe_library_toggle_favorite': recipeLibraryToggleFavorite($db); break; + case 'recipe_tags_list': + recipeTagsList($db); + break; + case 'recipe_tags_add': + recipeTagsAdd($db); + break; + case 'recipe_tags_remove': + recipeTagsRemove($db); + break; + case 'recipe_tags_update': + recipeTagsUpdate($db); + break; case 'recipes_list': recipesList($db); break; @@ -12404,6 +12416,90 @@ function recipeLibraryToggleFavorite(PDO $db): void { echo json_encode(['success' => true, 'is_favorite' => (bool)$fav]); } +function recipeTagsList(PDO $db): void { + $rows = $db->query("SELECT id, key, label, icon, sort_order FROM recipe_tags ORDER BY sort_order ASC, id ASC")->fetchAll(); + echo json_encode(['success' => true, 'tags' => $rows]); +} + +function recipeTagsAdd(PDO $db): void { + $input = json_decode(file_get_contents('php://input'), true) ?? []; + $label = trim($input['label'] ?? ''); + $icon = trim($input['icon'] ?? '🏷️'); + + if ($label === '') { + echo json_encode(['success' => false, 'error' => 'label required']); + return; + } + + $key = mb_strtolower(trim($label)); + $key = preg_replace('/[^a-z0-9]+/u', '_', $key); + $key = trim($key, '_'); + if ($key === '') { + echo json_encode(['success' => false, 'error' => 'invalid label']); + return; + } + + $stmt = $db->prepare("SELECT id FROM recipe_tags WHERE key = ?"); + $stmt->execute([$key]); + if ($stmt->fetch()) { + echo json_encode(['success' => false, 'error' => 'tag already exists']); + return; + } + + $maxOrder = (int)$db->query("SELECT COALESCE(MAX(sort_order), 0) FROM recipe_tags")->fetchColumn(); + + $stmt = $db->prepare("INSERT INTO recipe_tags (key, label, icon, sort_order) VALUES (?, ?, ?, ?)"); + $stmt->execute([$key, $label, $icon, $maxOrder + 1]); + + echo json_encode(['success' => true, 'key' => $key]); +} + +function recipeTagsRemove(PDO $db): void { + $input = json_decode(file_get_contents('php://input'), true) ?? []; + $key = trim($input['key'] ?? ''); + + if ($key === '') { + echo json_encode(['success' => false, 'error' => 'key required']); + return; + } + + $rows = $db->query("SELECT recipe_json FROM recipe_library")->fetchAll(PDO::FETCH_COLUMN); + foreach ($rows as $json) { + $data = json_decode($json, true); + if (in_array($key, $data['tags'] ?? [], true)) { + echo json_encode(['success' => false, 'error' => 'tag still used by a recipe']); + return; + } + } + + $db->prepare("DELETE FROM recipe_tags WHERE key = ?")->execute([$key]); + echo json_encode(['success' => true]); +} + +function recipeTagsUpdate(PDO $db): void { + $input = json_decode(file_get_contents('php://input'), true) ?? []; + $key = trim($input['key'] ?? ''); + $label = trim($input['label'] ?? ''); + $icon = trim($input['icon'] ?? ''); + + if ($key === '' || $label === '') { + echo json_encode(['success' => false, 'error' => 'key and label required']); + return; + } + + $stmt = $db->prepare("SELECT id FROM recipe_tags WHERE key = ?"); + $stmt->execute([$key]); + if (!$stmt->fetch()) { + echo json_encode(['success' => false, 'error' => 'tag not found']); + return; + } + + $stmt = $db->prepare("UPDATE recipe_tags SET label = ?, icon = ? WHERE key = ?"); + $stmt->execute([$label, $icon ?: '🏷️', $key]); + + echo json_encode(['success' => true]); +} + // ===== SHARED APP DATA FUNCTIONS ===== function appSettingsGet(PDO $db): void {