Browse Source

fix: resolve custom content page refresh and MCP is_enabled errors

1. Fixed page refresh showing "no custom content" briefly:
   - Added loading state check while shop is being determined from URL
   - Shows loading spinner instead of "no content" during initialization
   - Added "noShopSelected" message when no shop is available

2. Fixed MCP list_custom_contents tool error:
   - Removed non-existent is_enabled column from query
   - Column doesn't exist in custom_content table
   - All content is now treated as enabled

Added translations for noShopSelected in EN, DE, HU.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fszontagh 4 months ago
parent
commit
faef3214ad

+ 19 - 3
shopcall.ai-main/src/components/CustomContentList.tsx

@@ -27,6 +27,7 @@ import {
 import { supabase } from "@/lib/supabase";
 import { useShop } from "@/components/context/ShopContext";
 import { useTranslation } from 'react-i18next';
+import { Loader2 } from "lucide-react";
 
 interface CustomContentListProps {
   contentType?: "text_entry" | "pdf_upload";
@@ -57,7 +58,7 @@ export function CustomContentList({
   const [viewContentId, setViewContentId] = useState<string | null>(null);
   const [retryingId, setRetryingId] = useState<string | null>(null);
   const { toast } = useToast();
-  const { selectedShop } = useShop();
+  const { selectedShop, isLoading: isShopLoading } = useShop();
 
   // Fetch content list
   const { data, isLoading, refetch } = useQuery({
@@ -202,8 +203,23 @@ export function CustomContentList({
     }
   };
 
-  if (isLoading) {
-    return <div className="text-center py-8 text-slate-400">{t('customContent.list.loading')}</div>;
+  // Show loading state while shop is being determined from URL or while fetching content
+  if (isShopLoading || isLoading) {
+    return (
+      <div className="text-center py-8 text-slate-400 flex items-center justify-center gap-2">
+        <Loader2 className="h-4 w-4 animate-spin" />
+        {t('customContent.list.loading')}
+      </div>
+    );
+  }
+
+  // Only show "no content" if shop is loaded and data is empty
+  if (!selectedShop) {
+    return (
+      <div className="text-center py-8 text-slate-400">
+        {t('customContent.list.noShopSelected')}
+      </div>
+    );
   }
 
   if (!data || data.length === 0) {

+ 6 - 1
shopcall.ai-main/src/i18n/locales/de.json

@@ -1386,7 +1386,11 @@
         "noCustomUrls": "Noch keine benutzerdefinierten URLs hinzugefügt",
         "domainError": "Die URL muss von derselben Domain wie Ihr Shop stammen",
         "deleteTitle": "Benutzerdefinierte URL löschen",
-        "deleteDescription": "Möchten Sie diese benutzerdefinierte URL wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden."
+        "deleteDescription": "Möchten Sie diese benutzerdefinierte URL wirklich löschen? Diese Aktion kann nicht rückgängig gemacht werden.",
+        "scraping": "Wird gescrapt...",
+        "pending": "Ausstehend",
+        "scraped": "Gescrapt",
+        "failed": "Fehlgeschlagen"
       },
       "contentViewer": {
         "title": "Gescrapte Inhalte",
@@ -1553,6 +1557,7 @@
     },
     "list": {
       "loading": "Wird geladen...",
+      "noShopSelected": "Bitte wählen Sie zuerst einen Shop aus.",
       "noContent": "Noch kein benutzerdefinierter Inhalt. Laden Sie ein PDF hoch oder erstellen Sie einen Texteintrag, um zu beginnen.",
       "view": "Inhalt anzeigen",
       "table": {

+ 6 - 1
shopcall.ai-main/src/i18n/locales/en.json

@@ -1542,7 +1542,11 @@
         "noCustomUrls": "No custom URLs added yet",
         "domainError": "URL must be from the same domain as your store",
         "deleteTitle": "Delete Custom URL",
-        "deleteDescription": "Are you sure you want to delete this custom URL? This action cannot be undone."
+        "deleteDescription": "Are you sure you want to delete this custom URL? This action cannot be undone.",
+        "scraping": "Scraping...",
+        "pending": "Pending",
+        "scraped": "Scraped",
+        "failed": "Failed"
       },
       "contentViewer": {
         "title": "Scraped Content",
@@ -1726,6 +1730,7 @@
     },
     "list": {
       "loading": "Loading...",
+      "noShopSelected": "Please select a shop first.",
       "noContent": "No custom content yet. Upload a PDF or create a text entry to get started.",
       "view": "View content",
       "table": {

+ 6 - 1
shopcall.ai-main/src/i18n/locales/hu.json

@@ -1532,7 +1532,11 @@
         "noCustomUrls": "Még nincsenek egyedi URL-ek hozzáadva",
         "domainError": "Az URL-nek ugyanarról a domainről kell származnia, mint az áruházának",
         "deleteTitle": "Egyedi URL Törlése",
-        "deleteDescription": "Biztosan törölni szeretné ezt az egyedi URL-t? Ez a művelet nem vonható vissza."
+        "deleteDescription": "Biztosan törölni szeretné ezt az egyedi URL-t? Ez a művelet nem vonható vissza.",
+        "scraping": "Beolvasás...",
+        "pending": "Várakozik",
+        "scraped": "Beolvasva",
+        "failed": "Sikertelen"
       },
       "contentViewer": {
         "title": "Scraped Tartalom",
@@ -1676,6 +1680,7 @@
     },
     "list": {
       "loading": "Betöltés...",
+      "noShopSelected": "Kérjük, először válasszon boltot.",
       "noContent": "Még nincs egyedi tartalom. Töltsön fel egy PDF-et vagy hozzon létre egy szöveges bejegyzést a kezdéshez.",
       "view": "Tartalom megtekintése",
       "table": {

+ 3 - 2
supabase/functions/_shared/mcp-qdrant-helpers.ts

@@ -415,9 +415,10 @@ export async function listCustomContents(
     console.log(`[MCP Qdrant] Listing custom content for store: ${storeId}`);
 
     // Query custom_content table directly
+    // Note: is_enabled column does not exist in the table, all content is enabled by default
     const { data: contents, error } = await supabase
       .from('custom_content')
-      .select('id, title, content_type, original_filename, page_count, chunk_count, sync_status, is_enabled, created_at')
+      .select('id, title, content_type, original_filename, page_count, chunk_count, sync_status, created_at')
       .eq('store_id', storeId)
       .order('created_at', { ascending: false });
 
@@ -437,7 +438,7 @@ export async function listCustomContents(
       pageCount: item.page_count || undefined,
       chunkCount: item.chunk_count || undefined,
       syncStatus: item.sync_status || 'unknown',
-      isEnabled: item.is_enabled !== false, // Default to true if not set
+      isEnabled: true, // All content is enabled (no is_enabled column in table)
       createdAt: item.created_at,
     }));
   } catch (error) {