From 32e2a2a82e5e498e8e52768c8dc390623be23fec Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Sun, 28 Jun 2026 13:04:29 -0500 Subject: [PATCH] feat: per-category greeting menu in bot config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a "Por Categoría" tab in the bot config UI where each permission category (1, 2, 3) can be assigned its own greeting button menu. When a user writes without an active context, the bot shows the menu configured for their category instead of falling through to the global greeting text. NormalBot.process() now checks per_type[X].greeting_menu first, which directly references a menu key and serves as both greeting and fallback for that category. Fully backward-compatible with existing greeting_flow. Co-Authored-By: Claude Sonnet 4.6 --- admin/DashboardController.php | 36 +++++++++++++++++++++++++++++++++++ public/index.php | 15 +++++++++++++++ services/NormalBot.php | 13 +++++++++++++ 3 files changed, 64 insertions(+) diff --git a/admin/DashboardController.php b/admin/DashboardController.php index c5fbac6..be801a2 100644 --- a/admin/DashboardController.php +++ b/admin/DashboardController.php @@ -2372,6 +2372,34 @@ HTML; $flows = $config['flows'] ?? []; $aiProviderOpenai = $aiProviderVal === 'openai' ? ' selected' : ''; $aiProviderMock = $aiProviderVal === 'mock' ? ' selected' : ''; + + // Per-category config HTML + $perTypeConfig = $config['per_type'] ?? []; + $menuKeysList = array_keys($menus); + $catLabels = ['1' => 'Categoría 1 — Solo recibe info', '2' => 'Categoría 2 — Solo descarga informes', '3' => 'Categoría 3 — Reporta y recibe']; + $categoryTabHtml = ''; + foreach ([1, 2, 3] as $cat) { + $catCfg = $perTypeConfig[(string)$cat] ?? []; + $selMenu = $catCfg['greeting_menu'] ?? ''; + $opts = ''; + foreach ($menuKeysList as $mk) { + $s = $selMenu === $mk ? ' selected' : ''; + $opts .= ''; + } + $label = $catLabels[(string)$cat]; + $categoryTabHtml .= << +
{$label}
+
+ + +
Menú en botones que se muestra cuando el usuario escribe por primera vez o sin contexto activo
+
+ +CATHTML; + } $aiModelMini = $aiModelVal === 'gpt-4o-mini' ? ' selected' : ''; $aiModel4o = $aiModelVal === 'gpt-4o' ? ' selected' : ''; $aiModel35 = $aiModelVal === 'gpt-3.5-turbo' ? ' selected' : ''; @@ -2384,6 +2412,7 @@ HTML; + @@ -2551,6 +2580,13 @@ HTML; + +
+
👥 Configuración por Categoría
+

Define qué menú de bienvenida ve cada categoría de usuario cuando escribe por primera vez o sin contexto activo. El menú debe ser de tipo botón.

+ {$categoryTabHtml} +
+
🤖 Inteligencia Artificial
diff --git a/public/index.php b/public/index.php index f7e4955..02d7246 100644 --- a/public/index.php +++ b/public/index.php @@ -410,6 +410,21 @@ $routes = [ $aiProvider = trim($_POST['ai_provider'] ?? ''); if ($aiProvider !== '') $config['ai_provider'] = $aiProvider; + // Per-category menus + $perTypeMenus = $_POST['per_type_menu'] ?? []; + $perType = []; + foreach ([1, 2, 3] as $cat) { + $mk = trim($perTypeMenus[$cat] ?? ''); + if ($mk !== '') { + $perType[(string)$cat] = [ + 'greeting_menu' => $mk, + 'greeting' => '', + 'fallback' => '', + ]; + } + } + if (!empty($perType)) $config['per_type'] = $perType; + // General $greeting = trim($_POST['greeting'] ?? ''); if ($greeting !== '') $config['greeting'] = $greeting; diff --git a/services/NormalBot.php b/services/NormalBot.php index 1038875..ac29eeb 100644 --- a/services/NormalBot.php +++ b/services/NormalBot.php @@ -46,6 +46,13 @@ class NormalBot return null; } + // Per-type greeting_menu: direct menu for this category (greeting + fallback in one) + $greetingMenuKey = $perType['greeting_menu'] ?? null; + if ($greetingMenuKey !== null && $currentNode === null && isset($menus[$greetingMenuKey])) { + ConversationContext::updateNode($ctxId, null); + return self::buildMenuResponse($menus[$greetingMenuKey], $context['from'], $company); + } + $greeting = $perType['greeting'] ?? $config['greeting'] ?? null; if ($greeting !== null && $currentNode === null) { $greetingFlowId = $perType['greeting_flow'] ?? 'greeting'; @@ -65,6 +72,12 @@ class NormalBot return self::handleFlow($flows[$fallbackFlowId], $context, $company, $ctxId, $menus); } + // greeting_menu also serves as fallback when nothing else matched + if ($greetingMenuKey !== null && isset($menus[$greetingMenuKey])) { + ConversationContext::updateNode($ctxId, null); + return self::buildMenuResponse($menus[$greetingMenuKey], $context['from'], $company); + } + $fallback = $perType['fallback'] ?? $config['fallback'] ?? null; if ($fallback !== null) { ConversationContext::updateNode($ctxId, null);