|
|
@@ -1,14 +1,11 @@
|
|
|
-import { useState, useEffect, useRef } from "react";
|
|
|
+import { useState } from "react";
|
|
|
import { Button } from "@/components/ui/button";
|
|
|
import { Input } from "@/components/ui/input";
|
|
|
import { Label } from "@/components/ui/label";
|
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
|
import { Alert, AlertDescription } from "@/components/ui/alert";
|
|
|
-import {
|
|
|
- Dialog,
|
|
|
- DialogContent,
|
|
|
-} from "@/components/ui/dialog";
|
|
|
-import { AlertCircle, Loader2, Sparkles, Brain } from "lucide-react";
|
|
|
+import { LoadingScreen } from "@/components/ui/loading-screen";
|
|
|
+import { AlertCircle } from "lucide-react";
|
|
|
import { useToast } from "@/hooks/use-toast";
|
|
|
import { supabase } from "@/lib/supabase";
|
|
|
import { useShop } from "@/components/context/ShopContext";
|
|
|
@@ -54,39 +51,11 @@ export function CustomContentTextEntry({ onSuccess }: CustomContentTextEntryProp
|
|
|
const [saving, setSaving] = useState(false);
|
|
|
const [error, setError] = useState<string | null>(null);
|
|
|
const [editorHasContent, setEditorHasContent] = useState(false);
|
|
|
- const [loadingMessage, setLoadingMessage] = useState("");
|
|
|
- const loadingIntervalRef = useRef<NodeJS.Timeout | null>(null);
|
|
|
const { toast } = useToast();
|
|
|
const { selectedShop } = useShop();
|
|
|
|
|
|
- // Get loading messages from translations
|
|
|
- const loadingMessages = t('customContent.textEntry.savingMessages', { returnObjects: true }) as string[];
|
|
|
-
|
|
|
- // Rotate loading messages while saving
|
|
|
- useEffect(() => {
|
|
|
- if (saving && Array.isArray(loadingMessages) && loadingMessages.length > 0) {
|
|
|
- // Set initial message
|
|
|
- setLoadingMessage(loadingMessages[Math.floor(Math.random() * loadingMessages.length)]);
|
|
|
-
|
|
|
- // Rotate messages every 2.5 seconds
|
|
|
- loadingIntervalRef.current = setInterval(() => {
|
|
|
- setLoadingMessage(loadingMessages[Math.floor(Math.random() * loadingMessages.length)]);
|
|
|
- }, 2500);
|
|
|
- } else {
|
|
|
- // Clear interval when not saving
|
|
|
- if (loadingIntervalRef.current) {
|
|
|
- clearInterval(loadingIntervalRef.current);
|
|
|
- loadingIntervalRef.current = null;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return () => {
|
|
|
- if (loadingIntervalRef.current) {
|
|
|
- clearInterval(loadingIntervalRef.current);
|
|
|
- loadingIntervalRef.current = null;
|
|
|
- }
|
|
|
- };
|
|
|
- }, [saving, loadingMessages]);
|
|
|
+ // Get AI loading messages from translations
|
|
|
+ const loadingMessages = t('common.loadingMessages.ai', { returnObjects: true }) as string[];
|
|
|
|
|
|
// Initialize TipTap editor for WYSIWYG mode
|
|
|
const editor = useEditor({
|
|
|
@@ -329,42 +298,16 @@ export function CustomContentTextEntry({ onSuccess }: CustomContentTextEntryProp
|
|
|
</Button>
|
|
|
</div>
|
|
|
|
|
|
- {/* Loading Dialog */}
|
|
|
- <Dialog open={saving} onOpenChange={() => {}}>
|
|
|
- <DialogContent className="bg-slate-800 border-slate-700 sm:max-w-md" hideCloseButton>
|
|
|
- <div className="flex flex-col items-center justify-center py-8 space-y-6">
|
|
|
- {/* Animated Icon */}
|
|
|
- <div className="relative">
|
|
|
- <div className="w-20 h-20 rounded-full bg-gradient-to-br from-cyan-500/20 to-purple-500/20 flex items-center justify-center">
|
|
|
- <Brain className="w-10 h-10 text-cyan-400 animate-pulse" />
|
|
|
- </div>
|
|
|
- <div className="absolute -top-1 -right-1">
|
|
|
- <Sparkles className="w-6 h-6 text-yellow-400 animate-bounce" />
|
|
|
- </div>
|
|
|
- <div className="absolute -bottom-1 -left-1">
|
|
|
- <Loader2 className="w-5 h-5 text-purple-400 animate-spin" />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
-
|
|
|
- {/* Loading Message */}
|
|
|
- <div className="text-center space-y-2">
|
|
|
- <p className="text-lg font-medium text-white animate-pulse">
|
|
|
- {loadingMessage}
|
|
|
- </p>
|
|
|
- <p className="text-sm text-slate-400">
|
|
|
- {t('customContent.textEntry.saving')}
|
|
|
- </p>
|
|
|
- </div>
|
|
|
-
|
|
|
- {/* Progress dots */}
|
|
|
- <div className="flex space-x-2">
|
|
|
- <div className="w-2 h-2 bg-cyan-400 rounded-full animate-bounce" style={{ animationDelay: '0ms' }} />
|
|
|
- <div className="w-2 h-2 bg-cyan-400 rounded-full animate-bounce" style={{ animationDelay: '150ms' }} />
|
|
|
- <div className="w-2 h-2 bg-cyan-400 rounded-full animate-bounce" style={{ animationDelay: '300ms' }} />
|
|
|
- </div>
|
|
|
- </div>
|
|
|
- </DialogContent>
|
|
|
- </Dialog>
|
|
|
+ {/* Loading Screen Overlay */}
|
|
|
+ {saving && (
|
|
|
+ <div className="fixed inset-0 z-50">
|
|
|
+ <LoadingScreen
|
|
|
+ messages={loadingMessages}
|
|
|
+ showAnimatedIcon
|
|
|
+ subtitle={t('customContent.textEntry.saving')}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ )}
|
|
|
</div>
|
|
|
);
|
|
|
}
|