-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
428 lines (382 loc) Β· 12.3 KB
/
app.js
File metadata and controls
428 lines (382 loc) Β· 12.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
document.addEventListener("DOMContentLoaded", function () {
const menuToggle = document.getElementById("menu-toggle");
const navbarMenu = document.querySelector(".navbar-menu");
menuToggle.addEventListener("click", function () {
navbarMenu.classList.toggle("active");
});
function toggleNavbar() {
var x = document.getElementById("myNavbar");
var toggleButton = document.getElementsByClassName(".navbar-menu");
if (x.className === "navbar") {
x.className += " responsive";
toggleButton.innerHTML = "✖ Close"; // Change to close icon
} else {
x.className = "navbar";
toggleButton.innerHTML = "☰ Menu"; // Change back to menu icon
}
}
});
// ---- Preloader ----
const loader = document.getElementById("preloader");
window.addEventListener("load", function () {
loader.style.display = "none";
});
// -----------Right click disable code ---------
document.addEventListener("contextmenu", function (e) {
// e.preventDefault();
});
// ---- Smooth loading ----
document.addEventListener("DOMContentLoaded", function () {
document.body.classList.add("loaded");
});
// Gsap Animation
window.addEventListener("load", () => {
// Animate the navbar
// gsap.from("nav", { duration: 1.5, y: -50, opacity: 0, ease: "power2.out" });
// Animate the song list containers
gsap.from(".container", {
duration: 1.5,
y: 50,
opacity: 0,
ease: "power2.out",
stagger: 0.2, // Stagger animation for multiple containers
});
// Animate individual song items
gsap.from(".songItem", {
duration: 1.5,
x: -50,
opacity: 0,
ease: "power2.out",
stagger: 0.1, // Stagger animation for song items
delay: 0.5,
});
// Animate the bottom player controls
gsap.from(".bottom", {
duration: 1.5,
y: 50,
opacity: 0,
ease: "power2.out",
delay: 1,
});
});
gsap.to(".footer-container", {
opacity: 1,
y: 0,
duration: 1.5,
ease: "power3.out",
delay: 0.3,
});
gsap.to(".footer-bottom", {
opacity: 1,
y: 0,
duration: 1.2,
ease: "power3.out",
delay: 0.5,
});
// Scrolling to top
const scrollToTopBtn = document.getElementById("scrollToTop");
window.addEventListener("scroll", () => {
if (window.scrollY > 200) {
scrollToTopBtn.classList.add("show");
} else {
scrollToTopBtn.classList.remove("show");
}
});
scrollToTopBtn.addEventListener("click", () => {
window.scrollTo({ top: 0, behavior: "smooth" });
});
// Chatbot DeepSeek ----
function toggleChatbot() {
const chatbot = document.querySelector(".chatbot-container");
chatbot.style.display = chatbot.style.display === "flex" ? "none" : "flex";
}
const responses = [
{
keywords: [
"who is affan",
"what affan does",
"about affan",
"affan asghar",
"md affan asghar",
"tell me about affan",
"who are you",
],
response:
"MD Affan Asghar is a passionate Full Stack Web Developer and Computer Science Engineering student, dedicated to building beautiful, responsive, and user-friendly websites. π»π",
},
{
keywords: [
"your name",
"creator",
"made you",
"built you",
"build",
"who created you",
],
response: "I'm a chatbot created by MD Affan Asghar. π",
},
{
keywords: ["developer name", "who made you", "who is your developer"],
response: "My developer is MD Affan Asghar. π",
},
{
keywords: [
"phone number",
"contact",
"mobile",
"phone",
"how to contact",
"reach affan",
],
response: "You can contact MD Affan Asghar at π 9339828230.",
},
{
keywords: ["email", "mail", "gmail", "email address"],
response: "You can reach him at π§ affanasgar8@gmail.com.",
},
{
keywords: ["address", "location", "where do you live", "where is affan"],
response: "He lives at π Kankinara, Kolkata, West Bengal.",
},
{
keywords: [
"skills",
"expertise",
"technologies",
"tech stack",
"what can affan do",
],
response:
"He is skilled in π₯ Full-Stack Web Development, Node.js, React, Php, MySQL MongoDB, Express.js, JavaScript, HTML, CSS, and more!",
},
{
keywords: [
"projects",
"work",
"portfolio",
"project",
"what has affan built",
],
response:
"His Full Stack projects include π― WanderLust Holidays-Rental-Homes, NoHate website, and a Weather App using React,etc. π",
},
{
keywords: [
"wanderlust",
"wanderlust project",
"holiday project",
"rental homes",
"holiday rental",
],
response:
"WanderLust Holidays-Rental-Homes is a full-stack web application inspired by Airbnb. It allows users to explore, book, and host rental properties with secure authentication, image uploads, filtering, and responsive design. Built using Node.js, Express.js, MongoDB, and EJS for dynamic rendering. π",
},
{
keywords: [
"nohate",
"no hate",
"hate speech",
"nohate website",
"hate detection project",
"anti hate project",
],
response:
"π‘οΈ The NoHate website is a full-stack platform built to detect and filter hate speech in user posts. It uses machine learning for content moderation, with a modern frontend in React and backend in Node.js, Express, and MongoDB. It promotes respectful online communication. π¬π«",
},
{
keywords: ["portfolio", "website", "profile", "personal website"],
response:
"Check out his portfolio here: π https://portfolio-affan.netlify.app/.",
},
{
keywords: [
"college",
"education",
"study",
"degree",
"where did affan study",
],
response:
"He is currently pursuing B.Tech in Computer Science Engineering (CSE) at π« Narula Institute of Technology, Kolkata, India.",
},
{
keywords: ["internship", "experience", "job", "work experience"],
response:
"He is currently working at π’ Ecomservices as a Full Stack Web Developer, focusing on scalable and full stack web applications. Previously, he worked as a Web Developer Intern at πΌ Simtrak Solution Pvt Ltd. π",
},
{
keywords: ["final year project", "academic project", "college project"],
response:
"His final year project is a full-stack web development project that aims to revolutionize the industry. π",
},
{
keywords: ["hobbies", "interests", "passion", "what does affan like"],
response:
"He loves π» coding, designing beautiful websites, learning new tech, and contributing to open-source projects. π",
},
{
keywords: ["social media", "linkedin", "github", "twitter", "instagram"],
response:
"You can connect with him here:\nπ LinkedIn: https://linkedin.com/in/mdaffanasghar/\nπ± GitHub: https://github.com/affancoder",
},
{
keywords: ["career", "future plans", "goal", "aspirations"],
response:
"His goal is to become a highly skilled full-stack developer and work on innovative tech projects. π",
},
{
keywords: ["freelance", "hire", "services", "available for work"],
response:
"Yes! He is available for freelance projects. Contact him at π§ affanasgar8@gmail.com.",
},
{
keywords: ["hi", "hello", "hey", "hii", "greetings"],
response: "Hello! How can I assist you today? π",
},
{
keywords: ["bye", "goodbye", "see you", "good night"],
response: "Goodbye! Have a great day! π",
},
{
keywords: ["thank", "thanks", "appreciate"],
response:
"You're welcome! Let me know if you need anything else about Affan. π",
},
];
function findBestResponse(userMessage) {
userMessage = userMessage.toLowerCase();
// First check for exact matches
for (let entry of responses) {
if (
entry.keywords.some(
(keyword) =>
userMessage === keyword ||
userMessage.includes(keyword) ||
new RegExp(`\\b${keyword}\\b`).test(userMessage)
)
) {
return entry.response;
}
}
// Then check for partial matches
let bestMatch = null;
let highestMatchCount = 0;
for (let entry of responses) {
let matchCount = entry.keywords.filter((keyword) =>
userMessage.includes(keyword)
).length;
if (matchCount > highestMatchCount) {
highestMatchCount = matchCount;
bestMatch = entry.response;
}
}
return bestMatch || null;
}
// Enhanced API call with better fallbacks
async function callDeepSeekAPI(userMessage) {
// Don't call API for simple greetings or common questions
const simpleQuestions = ["hi", "hello", "hey", "bye", "thank"];
if (simpleQuestions.some((q) => userMessage.toLowerCase().includes(q))) {
return null;
}
try {
const response = await fetch(
"https://api.deepseek.com/v1/chat/completions",
{
method: "POST",
headers: {
Authorization:
"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",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "deepseek-chat",
messages: [
{
role: "system",
content:
"You are an assistant that answers questions specifically about MD Affan Asghar, a Full Stack Developer. Keep responses brief (1-2 sentences max) and relevant to Affan's skills, projects, education, or contact info. If the question isn't about Affan, politely decline to answer.",
},
{
role: "user",
content: userMessage,
},
],
temperature: 0.3, // Lower temperature for more focused answers
max_tokens: 100,
}),
timeout: 5000, // Add timeout
}
);
if (!response.ok) {
throw new Error(`API request failed with status ${response.status}`);
}
const data = await response.json();
if (!data.choices?.[0]?.message?.content) {
throw new Error("Invalid API response structure");
}
return data.choices[0].message.content;
} catch (error) {
console.error("DeepSeek API error:", error);
return null; // Return null to trigger local fallback
}
}
function sendMessage() {
const userInput = document.getElementById("userInput");
const message = userInput.value.trim();
if (message === "") return;
addMessage(message, "user-message");
userInput.value = "";
// Show typing indicator
const messageContainer = document.getElementById("chatbotMessages");
const typingIndicator = document.createElement("div");
typingIndicator.className = "bot-message typing";
typingIndicator.textContent = "AffanBot is typing...";
typingIndicator.id = "typingIndicator";
messageContainer.appendChild(typingIndicator);
messageContainer.scrollTop = messageContainer.scrollHeight;
setTimeout(async () => {
try {
// Remove typing indicator
const indicator = document.getElementById("typingIndicator");
if (indicator) indicator.remove();
// First try local responses
let botResponse = findBestResponse(message);
// If no local match found, try API
if (!botResponse) {
const apiResponse = await callDeepSeekAPI(message);
botResponse =
apiResponse ||
"I'm designed to answer questions about MD Affan Asghar. Could you ask something specific about his skills, projects, or contact information?";
}
addMessage(botResponse, "bot-message");
} catch (error) {
console.error("Error generating response:", error);
addMessage(
"I'm having some trouble right now. Please try asking something specific about Affan's skills or projects.",
"bot-message"
);
}
}, 1500);
}
function handleKeyPress(event) {
if (event.key === "Enter") {
sendMessage();
}
}
function addMessage(text, className) {
const messageContainer = document.getElementById("chatbotMessages");
const messageDiv = document.createElement("div");
messageDiv.className = className;
// Handle newlines in responses
if (typeof text === "string" && text.includes("\n")) {
text.split("\n").forEach((line, i) => {
if (i > 0) messageDiv.appendChild(document.createElement("br"));
messageDiv.appendChild(document.createTextNode(line));
});
} else {
messageDiv.textContent = text;
}
messageContainer.appendChild(messageDiv);
messageContainer.scrollTop = messageContainer.scrollHeight;
}