diff --git a/src/components/chatAssistance/ChaatInterface.jsx b/src/components/chatAssistance/ChaatInterface.jsx
index 74c6350..2d78a3a 100644
--- a/src/components/chatAssistance/ChaatInterface.jsx
+++ b/src/components/chatAssistance/ChaatInterface.jsx
@@ -8,11 +8,13 @@ import { PaperPlaneIcon, Cross2Icon } from '@radix-ui/react-icons';
import { cn } from '@/lib/utils';
import spiderIcon from '../../assets/spider.png';
import './chat.css';
+import { TypingAnimation } from './TypingAnimation';
+import { StreamingText } from './StreamingText';
export const ChatInterface = ({ triggerAnimation }) => {
// Add API base URL from environment variable
const API_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:5000';
-
+
const [isOpen, setIsOpen] = useState(false);
const [inputMessage, setInputMessage] = useState('');
const [userId, setUserId] = useState(null);
@@ -55,76 +57,104 @@ export const ChatInterface = ({ triggerAnimation }) => {
const newMessages = [...messages, { text: inputMessage, isBot: false }];
setMessages(newMessages);
setInputMessage('');
-
- if (inputMessage.toLowerCase().includes('jump')) {
- triggerAnimation('jump');
- }
+ setBotThinking(true); // Show bot is thinking
try {
+ // Show typing animation while waiting for response
+ setIsTyping(true);
const response = await fetch(`${API_URL}/api/llm/chat`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: inputMessage, userId })
});
-
const data = await response.json();
setMessages([...newMessages, { text: data.reply, isBot: true }]);
} catch (error) {
setMessages([...newMessages, { text: "Oops! Something went wrong. 😵", isBot: true }]);
+ } finally {
+ setIsTyping(false);
+ setBotThinking(false);
}
-
- setIsTyping(false);
};
-
return (
-
+
{isOpen ? (
-
-
+
+
-
-
+
+
SP
-
Spider-Assist
-
{isTyping ? 'Weaving response...' : 'Ready to assist'}
+
Spider-Assist
+
+ {isTyping ? 'Weaving response...' : botThinking ? 'Processing...' : 'Ready to assist'}
+
-
-
-
-
-
+
+
+
+
{messages.map((msg, i) => (
-
{msg.text}
+
+ {msg.isBot ? (
+
+ ) : (
+ msg.text
+ )}
))}
+ {botThinking && (
+
+
+
+ )}
-
-
+
+
) : (
- setIsOpen(true)} className="chat-icon-button h-14 w-14 sm:h-16 sm:w-16 rounded-full bg-gradient-to-r from-red-600 to-red-500 hover:from-red-500 hover:to-red-400 shadow-lg shadow-red-500/20 hover:shadow-red-500/30 transition-all duration-300 hover:scale-105">
-
+ setIsOpen(true)}
+ className="fixed bottom-4 right-4 sm:bottom-6 sm:right-6 chat-icon-button h-12 w-12 sm:h-16 sm:w-16 rounded-full bg-gradient-to-r from-red-600 to-red-500 hover:from-red-500 hover:to-red-400 shadow-lg shadow-red-500/20 hover:shadow-red-500/30 transition-all duration-300 hover:scale-105"
+ >
+
)}
diff --git a/src/components/chatAssistance/StreamingText.jsx b/src/components/chatAssistance/StreamingText.jsx
new file mode 100644
index 0000000..476d91b
--- /dev/null
+++ b/src/components/chatAssistance/StreamingText.jsx
@@ -0,0 +1,80 @@
+import { motion, AnimatePresence } from "framer-motion";
+import { useState, useEffect } from "react";
+
+export const StreamingText = ({ text, onComplete }) => {
+ const [displayedText, setDisplayedText] = useState("");
+ const [currentIndex, setCurrentIndex] = useState(0);
+
+ useEffect(() => {
+ if (currentIndex < text.length) {
+ const timer = setTimeout(() => {
+ setDisplayedText(prev => prev + text[currentIndex]);
+ setCurrentIndex(currentIndex + 1);
+ }, 50); // Slightly faster typing speed
+
+ return () => clearTimeout(timer);
+ } else {
+ onComplete?.();
+ }
+ }, [currentIndex, text]);
+
+ return (
+
+
+
+ {displayedText.split(" ").map((word, idx) => (
+
+
+ {word}
+
+
+
+
+ ))}
+
+ {currentIndex < text.length && (
+
+ )}
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/chatAssistance/TypingAnimation.jsx b/src/components/chatAssistance/TypingAnimation.jsx
new file mode 100644
index 0000000..8f12912
--- /dev/null
+++ b/src/components/chatAssistance/TypingAnimation.jsx
@@ -0,0 +1,23 @@
+import { motion } from "framer-motion";
+
+export const TypingAnimation = () => {
+ return (
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/chatAssistance/chat.css b/src/components/chatAssistance/chat.css
index 1881d36..bccbfcc 100644
--- a/src/components/chatAssistance/chat.css
+++ b/src/components/chatAssistance/chat.css
@@ -1,20 +1,37 @@
/* Modern Chat Interface Styling */
/* Chat Icon Animation */
@keyframes float {
- 0%, 100% {
+
+ 0%,
+ 100% {
transform: translateY(0);
box-shadow: 0 10px 25px -5px rgba(59, 130, 246, 0.4);
}
- 50% {
+
+ 50% {
transform: translateY(-8px);
box-shadow: 0 20px 25px -5px rgba(59, 130, 246, 0.2);
}
}
+@keyframes wave {
+ 0% {
+ transform: translateX(-100%);
+ }
+
+ 100% {
+ transform: translateX(100%);
+ }
+}
+
+.animate-wave {
+ animation: wave 2s linear infinite;
+}
+
/* Chat Icon Glow */
.chat-icon-button {
background: linear-gradient(135deg, #2563eb, #1d4ed8);
- box-shadow:
+ box-shadow:
0 0 20px 2px rgba(37, 99, 235, 0.3),
0 0 0 2px rgba(37, 99, 235, 0.1),
inset 0 0 0 1px rgba(255, 255, 255, 0.1);
@@ -23,7 +40,7 @@
.chat-icon-button:hover {
background: linear-gradient(135deg, #3b82f6, #2563eb);
- box-shadow:
+ box-shadow:
0 0 30px 4px rgba(37, 99, 235, 0.4),
0 0 0 2px rgba(37, 99, 235, 0.2),
inset 0 0 0 1px rgba(255, 255, 255, 0.2);
@@ -36,23 +53,40 @@
/* Add this to your existing animations */
@keyframes typing {
- 0%, 100% { transform: scale(0.8) translateY(0); }
- 50% { transform: scale(1.2) translateY(-2px); }
+
+ 0%,
+ 100% {
+ transform: scale(0.8) translateY(0);
+ }
+
+ 50% {
+ transform: scale(1.2) translateY(-2px);
+ }
}
+
.pulse-border {
animation: pulseBorder 2s infinite;
}
@keyframes pulseBorder {
- 0% { border-color: rgba(59, 130, 246, 0.1); }
- 50% { border-color: rgba(59, 130, 246, 0.3); }
- 100% { border-color: rgba(59, 130, 246, 0.1); }
+ 0% {
+ border-color: rgba(59, 130, 246, 0.1);
+ }
+
+ 50% {
+ border-color: rgba(59, 130, 246, 0.3);
+ }
+
+ 100% {
+ border-color: rgba(59, 130, 246, 0.1);
+ }
}
.glass-morphism {
background: rgba(15, 23, 42, 0.8);
backdrop-filter: blur(12px);
}
+
.typing-dot {
@apply h-2.5 w-2.5 bg-indigo-400 rounded-full;
animation: typing 1.2s ease-in-out infinite;
@@ -70,16 +104,14 @@
}
.chat-message-bot {
- @apply relative before:absolute before:-left-3 before:top-0 before:h-5 before:w-5
- before:rounded-bl-2xl before:bg-indigo-900/40;
+ @apply relative before:absolute before:-left-3 before:top-0 before:h-5 before:w-5 before:rounded-bl-2xl before:bg-indigo-900/40;
backdrop-filter: blur(12px);
box-shadow: 0 4px 15px -3px rgba(99, 102, 241, 0.1);
border: 1px solid rgba(129, 140, 248, 0.1);
}
.chat-message-user {
- @apply relative after:absolute after:-right-3 after:top-0 after:h-5 after:w-5
- after:rounded-br-2xl after:bg-gradient-to-br after:from-violet-500 after:to-purple-600;
+ @apply relative after:absolute after:-right-3 after:top-0 after:h-5 after:w-5 after:rounded-br-2xl after:bg-gradient-to-br after:from-violet-500 after:to-purple-600;
backdrop-filter: blur(12px);
box-shadow: 0 4px 15px -3px rgba(139, 92, 246, 0.15);
border: 1px solid rgba(139, 92, 246, 0.1);
@@ -91,6 +123,7 @@
opacity: 0;
transform: translateY(20px) scale(0.95) rotate(-1deg);
}
+
100% {
opacity: 1;
transform: translateY(0) scale(1) rotate(0);
@@ -106,7 +139,7 @@
background: linear-gradient(165deg, rgba(17, 24, 39, 0.95), rgba(15, 23, 42, 0.85));
backdrop-filter: blur(20px);
border: 1px solid rgba(99, 102, 241, 0.1);
- box-shadow:
+ box-shadow:
0 8px 32px -4px rgba(0, 0, 0, 0.3),
inset 0 0 0 1px rgba(255, 255, 255, 0.05);
}
@@ -128,8 +161,7 @@
}
.chat-message-bot {
- @apply relative before:absolute before:-left-3 before:top-0 before:h-5 before:w-5
- before:rounded-bl-2xl before:bg-slate-800/80;
+ @apply relative before:absolute before:-left-3 before:top-0 before:h-5 before:w-5 before:rounded-bl-2xl before:bg-slate-800/80;
backdrop-filter: blur(12px);
background: linear-gradient(to right, rgba(51, 65, 85, 0.3), rgba(71, 85, 105, 0.2));
box-shadow: 0 4px 15px -3px rgba(51, 65, 85, 0.2);
@@ -137,17 +169,24 @@
}
.chat-message-user {
- @apply relative after:absolute after:-right-3 after:top-0 after:h-5 after:w-5
- after:rounded-br-2xl after:bg-gradient-to-br after:from-blue-600 after:to-indigo-700;
+ @apply relative after:absolute after:-right-3 after:top-0 after:h-5 after:w-5 after:rounded-br-2xl after:bg-gradient-to-br after:from-blue-600 after:to-indigo-700;
backdrop-filter: blur(12px);
background: linear-gradient(to right, rgba(37, 99, 235, 0.9), rgba(79, 70, 229, 0.9));
box-shadow: 0 4px 15px -3px rgba(37, 99, 235, 0.2);
border: 1px solid rgba(37, 99, 235, 0.2);
}
+
/* Enhanced animations */
@keyframes float {
- 0%, 100% { transform: translateY(0) rotate(0deg); }
- 50% { transform: translateY(-10px) rotate(2deg); }
+
+ 0%,
+ 100% {
+ transform: translateY(0) rotate(0deg);
+ }
+
+ 50% {
+ transform: translateY(-10px) rotate(2deg);
+ }
}
.new-message-animation {
@@ -155,8 +194,15 @@
}
@keyframes glowPulse {
- 0%, 100% { box-shadow: 0 0 20px rgba(239, 68, 68, 0.1); }
- 50% { box-shadow: 0 0 30px rgba(239, 68, 68, 0.2); }
+
+ 0%,
+ 100% {
+ box-shadow: 0 0 20px rgba(239, 68, 68, 0.1);
+ }
+
+ 50% {
+ box-shadow: 0 0 30px rgba(239, 68, 68, 0.2);
+ }
}
.thinking-animation {
@@ -168,18 +214,21 @@
content: '';
position: absolute;
inset: 0;
- background: linear-gradient(
- 90deg,
- transparent,
- rgba(239, 68, 68, 0.2),
- transparent
- );
+ background: linear-gradient(90deg,
+ transparent,
+ rgba(239, 68, 68, 0.2),
+ transparent);
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
- 0% { transform: translateX(-100%); }
- 100% { transform: translateX(100%); }
+ 0% {
+ transform: translateX(-100%);
+ }
+
+ 100% {
+ transform: translateX(100%);
+ }
}
.typing-dot {
@@ -191,27 +240,52 @@
opacity: 0.5;
}
-.typing-dot:nth-child(2) { animation-delay: 0.2s; }
-.typing-dot:nth-child(3) { animation-delay: 0.4s; }
+.typing-dot:nth-child(2) {
+ animation-delay: 0.2s;
+}
+
+.typing-dot:nth-child(3) {
+ animation-delay: 0.4s;
+}
@keyframes typingDot {
- 0%, 60%, 100% { transform: translateY(0); opacity: 0.5; }
- 30% { transform: translateY(-4px); opacity: 1; }
+
+ 0%,
+ 60%,
+ 100% {
+ transform: translateY(0);
+ opacity: 0.5;
+ }
+
+ 30% {
+ transform: translateY(-4px);
+ opacity: 1;
+ }
}
+
.pulse-border {
animation: pulseBorder 2s infinite;
}
@keyframes pulseBorder {
- 0% { border-color: rgba(59, 130, 246, 0.1); }
- 50% { border-color: rgba(59, 130, 246, 0.3); }
- 100% { border-color: rgba(59, 130, 246, 0.1); }
+ 0% {
+ border-color: rgba(59, 130, 246, 0.1);
+ }
+
+ 50% {
+ border-color: rgba(59, 130, 246, 0.3);
+ }
+
+ 100% {
+ border-color: rgba(59, 130, 246, 0.1);
+ }
}
.glass-morphism {
background: rgba(15, 23, 42, 0.8);
backdrop-filter: blur(12px);
}
+
.typing-dot {
@apply h-2.5 w-2.5 bg-indigo-400 rounded-full;
animation: typing 1.2s ease-in-out infinite;
@@ -229,16 +303,14 @@
}
.chat-message-bot {
- @apply relative before:absolute before:-left-3 before:top-0 before:h-5 before:w-5
- before:rounded-bl-2xl before:bg-indigo-900/40;
+ @apply relative before:absolute before:-left-3 before:top-0 before:h-5 before:w-5 before:rounded-bl-2xl before:bg-indigo-900/40;
backdrop-filter: blur(12px);
box-shadow: 0 4px 15px -3px rgba(99, 102, 241, 0.1);
border: 1px solid rgba(129, 140, 248, 0.1);
}
.chat-message-user {
- @apply relative after:absolute after:-right-3 after:top-0 after:h-5 after:w-5
- after:rounded-br-2xl after:bg-gradient-to-br after:from-violet-500 after:to-purple-600;
+ @apply relative after:absolute after:-right-3 after:top-0 after:h-5 after:w-5 after:rounded-br-2xl after:bg-gradient-to-br after:from-violet-500 after:to-purple-600;
backdrop-filter: blur(12px);
box-shadow: 0 4px 15px -3px rgba(139, 92, 246, 0.15);
border: 1px solid rgba(139, 92, 246, 0.1);
@@ -246,8 +318,15 @@
/* Enhanced animations */
@keyframes float {
- 0%, 100% { transform: translateY(0) rotate(0deg); }
- 50% { transform: translateY(-10px) rotate(2deg); }
+
+ 0%,
+ 100% {
+ transform: translateY(0) rotate(0deg);
+ }
+
+ 50% {
+ transform: translateY(-10px) rotate(2deg);
+ }
}
.new-message-animation {
@@ -255,8 +334,15 @@
}
@keyframes glowPulse {
- 0%, 100% { box-shadow: 0 0 20px rgba(239, 68, 68, 0.1); }
- 50% { box-shadow: 0 0 30px rgba(239, 68, 68, 0.2); }
+
+ 0%,
+ 100% {
+ box-shadow: 0 0 20px rgba(239, 68, 68, 0.1);
+ }
+
+ 50% {
+ box-shadow: 0 0 30px rgba(239, 68, 68, 0.2);
+ }
}
.thinking-animation {
@@ -268,18 +354,21 @@
content: '';
position: absolute;
inset: 0;
- background: linear-gradient(
- 90deg,
- transparent,
- rgba(239, 68, 68, 0.2),
- transparent
- );
+ background: linear-gradient(90deg,
+ transparent,
+ rgba(239, 68, 68, 0.2),
+ transparent);
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
- 0% { transform: translateX(-100%); }
- 100% { transform: translateX(100%); }
+ 0% {
+ transform: translateX(-100%);
+ }
+
+ 100% {
+ transform: translateX(100%);
+ }
}
.typing-dot {
@@ -291,10 +380,25 @@
opacity: 0.5;
}
-.typing-dot:nth-child(2) { animation-delay: 0.2s; }
-.typing-dot:nth-child(3) { animation-delay: 0.4s; }
+.typing-dot:nth-child(2) {
+ animation-delay: 0.2s;
+}
+
+.typing-dot:nth-child(3) {
+ animation-delay: 0.4s;
+}
@keyframes typingDot {
- 0%, 60%, 100% { transform: translateY(0); opacity: 0.5; }
- 30% { transform: translateY(-4px); opacity: 1; }
+
+ 0%,
+ 60%,
+ 100% {
+ transform: translateY(0);
+ opacity: 0.5;
+ }
+
+ 30% {
+ transform: translateY(-4px);
+ opacity: 1;
+ }
}
\ No newline at end of file
diff --git a/src/components/deployment/AIAnalysis.jsx b/src/components/deployment/AIAnalysis.jsx
new file mode 100644
index 0000000..1389ee0
--- /dev/null
+++ b/src/components/deployment/AIAnalysis.jsx
@@ -0,0 +1,65 @@
+import { motion } from "framer-motion";
+import { StreamingText } from "../chatAssistance/StreamingText";
+
+export const AIAnalysis = ({ logs }) => {
+ return (
+
+
+
+
+
+ AI Analysis
+
+
Real-time deployment insights
+
+
+
+
+
+
Performance Metrics
+
+
Build optimization: 80%
+
+
+
Security Check
+
+
Vulnerability scan: 95% safe
+
+
+
+
+
+
AI Insights
+
+ Live Analysis
+
+
+
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/deployment/LogTerminal.jsx b/src/components/deployment/LogTerminal.jsx
new file mode 100644
index 0000000..de87b75
--- /dev/null
+++ b/src/components/deployment/LogTerminal.jsx
@@ -0,0 +1,39 @@
+import { motion } from "framer-motion";
+
+export const LogTerminal = ({ logs }) => {
+ return (
+
+
+
+ Deployment Logs
+
+
+
+ LIVE
+
+
+
+
+ {logs.map((log, index) => (
+
+ {log}
+
+ ))}
+
+
+ );
+};
\ No newline at end of file
diff --git a/src/components/pages/DeploymentProgress.jsx b/src/components/pages/DeploymentProgress.jsx
index 80dee6d..6374b83 100644
--- a/src/components/pages/DeploymentProgress.jsx
+++ b/src/components/pages/DeploymentProgress.jsx
@@ -2,9 +2,10 @@ import React, { useState, useEffect } from "react";
import { Button } from "@/components/ui/button";
import { useNavigate, useParams, useLocation } from "react-router-dom";
import "./DeploymentProgress.css";
-import NavBar from "../NavBar";
import { PieChart, Pie, Cell, ResponsiveContainer, Tooltip } from "recharts";
import axios from "axios";
+import { AIAnalysis } from "../deployment/AIAnalysis";
+import { LogTerminal } from "../deployment/LogTerminal";
const DeploymentProgress = () => {
const API_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:5000';
@@ -56,21 +57,21 @@ const DeploymentProgress = () => {
useEffect(() => {
let lastFetchedTimestamp = null;
-
+
const fetchLogs = async () => {
try {
const url = lastFetchedTimestamp
? `${API_URL}/getLogs/${id}?since=${lastFetchedTimestamp}`
: `${API_URL}/getLogs/${id}`;
-
+
const response = await fetch(url);
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
-
+
const data = await response.json();
-
+
if (data.logs?.length) {
lastFetchedTimestamp = data.logs[data.logs.length - 1].created_at; // Track last log timestamp
-
+
setLogs((prevLogs) => {
const newLogs = data.logs.map(
(log) =>
@@ -81,18 +82,18 @@ const DeploymentProgress = () => {
return Array.from(new Set([...prevLogs, ...newLogs]));
});
}
-
+
setProgress(data.progress || progress);
setDeploymentStats(data.stats || deploymentStats);
} catch (error) {
console.error("Error fetching logs:", error.message);
}
};
-
+
const interval = setInterval(fetchLogs, 2000);
return () => clearInterval(interval);
}, [id]);
-
+
const handleCancel = () => {
setIsDeploying(false);
@@ -100,132 +101,138 @@ const DeploymentProgress = () => {
};
return (
- {/* Background Effects */}
-
-
-
-
+ {/* Background Effects */}
+
+
+
+
+
+ Deployment Progress
+
+
Live deployment logs and real-time analytics
-
-
-
- Deployment Progress
-
-
Live deployment logs and real-time analytics
-
-
-
- {["Total Deployments", "Success Rate", "Failure Rate"].map((label, index) => (
-
+ {["Total Deployments", "Success Rate", "Failure Rate"].map((label, index) => (
+
-
{label}
-
-
-
-
- {COLORS.map((color, idx) => (
- |
- ))}
-
-
-
-
-
-
- ))}
+
+
+
+
+ {COLORS.map((color, idx) => (
+ |
+ ))}
+
+
+
+
+
+ ))}
+
-
-
+
-
-
+ Deployment Logs
- LIVE
-
-
- {logs.map((log, index) => (
-
- {log}
-
- ))}
-
-
-
-
-
-
+
+ {logs.map((log, index) => (
+
+ {log}
+ ))}
+
+
+
+
+
+ {/* //logs anf ai Analysis */}
+
-
- {isDeploying ? (
- <>
-
+ {isDeploying ? (
+ <>
+
- Cancel Deployment
-
- navigate("/dashboard")}
- className="bg-blue-500/20 text-blue-400 hover:bg-blue-500/30 border
+ Cancel Deployment
+
+ navigate("/dashboard")}
+ className="bg-blue-500/20 text-blue-400 hover:bg-blue-500/30 border
border-blue-500/30 transition-all duration-300">
- View Dashboard
-
- >
- ) : (
- navigate("/")}
- className="bg-blue-500/20 text-blue-400 hover:bg-blue-500/30 border
+ View Dashboard
+
+ >
+ ) : (
+ navigate("/")}
+ className="bg-blue-500/20 text-blue-400 hover:bg-blue-500/30 border
border-blue-500/30 transition-all duration-300">
- Go Back Home
-
- )}
-
+ Go Back Home
+
+ )}
+
-
- {["/assects/images/photoShowcase.png", "/assects/images/showCase.png"].map((img, idx) => (
-
+ {["/assects/images/photoShowcase.png", "/assects/images/showCase.png"].map((img, idx) => (
+
-

-
- {idx === 0 ? "🚀 Try Our Cloud Services!" : "🔒 Secure Your Applications!"}
-
-
- {idx === 0
- ? "Experience seamless deployments. Sign up now for 20% off!"
- : "Ensure your applications stay secure. Learn more."}
-
-
+
+ {idx === 0
+ ? "Experience seamless deployments. Sign up now for 20% off!"
+ : "Ensure your applications stay secure. Learn more."}
+
+
- {idx === 0 ? "Sign Up" : "Learn More"}
-
-
- ))}
+ {idx === 0 ? "Sign Up" : "Learn More"}
+
+ ))}
+
);
};