Spaces:
Running
Running
Upload 19 files
Browse files- .gitattributes +3 -0
- about.html +153 -0
- admin.css +711 -0
- admin.html +258 -0
- admin.js +516 -0
- contact.html +130 -0
- css/admin.css +489 -0
- css/login.css +197 -0
- css/pages.css +516 -0
- css/style.css +755 -0
- follow.html +169 -0
- images/bot-message-logo.png +3 -0
- images/menu-logo.png +3 -0
- images/welcome-logo.png +3 -0
- index.html +91 -18
- js/admin.js +350 -0
- js/login.js +114 -0
- js/script.js +656 -0
- login.html +54 -0
- style.css +480 -18
.gitattributes
CHANGED
@@ -33,3 +33,6 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
images/bot-message-logo.png filter=lfs diff=lfs merge=lfs -text
|
37 |
+
images/menu-logo.png filter=lfs diff=lfs merge=lfs -text
|
38 |
+
images/welcome-logo.png filter=lfs diff=lfs merge=lfs -text
|
about.html
ADDED
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<meta name="description" content="About DeepSeek - Learn about our mission and team">
|
7 |
+
<meta name="theme-color" content="#4285f4">
|
8 |
+
<title>About Us - DeepSeek</title>
|
9 |
+
<link rel="stylesheet" href="css/style.css">
|
10 |
+
<link rel="stylesheet" href="css/pages.css">
|
11 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
12 |
+
</head>
|
13 |
+
<body>
|
14 |
+
<header class="page-header">
|
15 |
+
<nav class="main-nav">
|
16 |
+
<div class="logo">
|
17 |
+
<img src="images/logo.png" alt="DeepSeek Logo" width="40" height="40">
|
18 |
+
<span>DeepSeek</span>
|
19 |
+
</div>
|
20 |
+
<ul class="nav-links">
|
21 |
+
<li><a href="index.html">Home</a></li>
|
22 |
+
<li><a href="about.html" class="active">About</a></li>
|
23 |
+
<li><a href="contact.html">Contact</a></li>
|
24 |
+
<li><a href="follow.html">Follow Us</a></li>
|
25 |
+
</ul>
|
26 |
+
</nav>
|
27 |
+
</header>
|
28 |
+
|
29 |
+
<main class="page-content">
|
30 |
+
<section class="hero-section">
|
31 |
+
<h1>About DeepSeek</h1>
|
32 |
+
<p class="section-desc">Pioneering the future of AI-powered conversations</p>
|
33 |
+
</section>
|
34 |
+
|
35 |
+
<section class="about-section">
|
36 |
+
<div class="about-content">
|
37 |
+
<div class="mission-vision">
|
38 |
+
<div class="mission">
|
39 |
+
<h2><i class="fas fa-bullseye"></i> Our Mission</h2>
|
40 |
+
<p>To make AI technology accessible and beneficial for everyone, enhancing human capabilities through intuitive and intelligent conversations.</p>
|
41 |
+
</div>
|
42 |
+
<div class="vision">
|
43 |
+
<h2><i class="fas fa-eye"></i> Our Vision</h2>
|
44 |
+
<p>To be the world's leading conversational AI platform, fostering meaningful interactions between humans and machines.</p>
|
45 |
+
</div>
|
46 |
+
</div>
|
47 |
+
|
48 |
+
<div class="values-section">
|
49 |
+
<h2>Our Core Values</h2>
|
50 |
+
<div class="values-grid">
|
51 |
+
<div class="value-item">
|
52 |
+
<i class="fas fa-shield-alt"></i>
|
53 |
+
<h3>Trust & Security</h3>
|
54 |
+
<p>We prioritize user privacy and data security in everything we do.</p>
|
55 |
+
</div>
|
56 |
+
<div class="value-item">
|
57 |
+
<i class="fas fa-lightbulb"></i>
|
58 |
+
<h3>Innovation</h3>
|
59 |
+
<p>We continuously push the boundaries of what's possible with AI.</p>
|
60 |
+
</div>
|
61 |
+
<div class="value-item">
|
62 |
+
<i class="fas fa-users"></i>
|
63 |
+
<h3>User-Centric</h3>
|
64 |
+
<p>Our users' needs and experiences drive our development.</p>
|
65 |
+
</div>
|
66 |
+
<div class="value-item">
|
67 |
+
<i class="fas fa-handshake"></i>
|
68 |
+
<h3>Collaboration</h3>
|
69 |
+
<p>We believe in the power of working together to achieve greatness.</p>
|
70 |
+
</div>
|
71 |
+
</div>
|
72 |
+
</div>
|
73 |
+
|
74 |
+
<div class="team-section">
|
75 |
+
<h2>Our Leadership Team</h2>
|
76 |
+
<div class="team-grid">
|
77 |
+
<div class="team-member">
|
78 |
+
<img src="images/team/ceo.jpg" alt="CEO" class="member-photo">
|
79 |
+
<h3>John Smith</h3>
|
80 |
+
<p class="position">CEO & Founder</p>
|
81 |
+
<p class="bio">20+ years of experience in AI and Machine Learning</p>
|
82 |
+
</div>
|
83 |
+
<div class="team-member">
|
84 |
+
<img src="images/team/cto.jpg" alt="CTO" class="member-photo">
|
85 |
+
<h3>Sarah Johnson</h3>
|
86 |
+
<p class="position">CTO</p>
|
87 |
+
<p class="bio">Former Tech Lead at major AI research labs</p>
|
88 |
+
</div>
|
89 |
+
<div class="team-member">
|
90 |
+
<img src="images/team/cpo.jpg" alt="CPO" class="member-photo">
|
91 |
+
<h3>Michael Chen</h3>
|
92 |
+
<p class="position">Chief Product Officer</p>
|
93 |
+
<p class="bio">Expert in AI product development and UX design</p>
|
94 |
+
</div>
|
95 |
+
</div>
|
96 |
+
</div>
|
97 |
+
|
98 |
+
<div class="achievements-section">
|
99 |
+
<h2>Our Achievements</h2>
|
100 |
+
<div class="achievements-grid">
|
101 |
+
<div class="achievement-item">
|
102 |
+
<span class="number">1M+</span>
|
103 |
+
<p>Active Users</p>
|
104 |
+
</div>
|
105 |
+
<div class="achievement-item">
|
106 |
+
<span class="number">50+</span>
|
107 |
+
<p>Countries</p>
|
108 |
+
</div>
|
109 |
+
<div class="achievement-item">
|
110 |
+
<span class="number">10M+</span>
|
111 |
+
<p>Conversations</p>
|
112 |
+
</div>
|
113 |
+
<div class="achievement-item">
|
114 |
+
<span class="number">99.9%</span>
|
115 |
+
<p>Uptime</p>
|
116 |
+
</div>
|
117 |
+
</div>
|
118 |
+
</div>
|
119 |
+
</div>
|
120 |
+
</section>
|
121 |
+
</main>
|
122 |
+
|
123 |
+
<footer class="page-footer">
|
124 |
+
<div class="footer-content">
|
125 |
+
<div class="footer-section">
|
126 |
+
<h3>DeepSeek</h3>
|
127 |
+
<p>Advancing AI technology to help people communicate and solve problems more effectively.</p>
|
128 |
+
</div>
|
129 |
+
<div class="footer-section">
|
130 |
+
<h3>Quick Links</h3>
|
131 |
+
<ul>
|
132 |
+
<li><a href="index.html">Home</a></li>
|
133 |
+
<li><a href="about.html">About</a></li>
|
134 |
+
<li><a href="contact.html">Contact</a></li>
|
135 |
+
<li><a href="follow.html">Follow Us</a></li>
|
136 |
+
</ul>
|
137 |
+
</div>
|
138 |
+
<div class="footer-section">
|
139 |
+
<h3>Connect With Us</h3>
|
140 |
+
<div class="social-links">
|
141 |
+
<a href="#" aria-label="Facebook"><i class="fab fa-facebook"></i></a>
|
142 |
+
<a href="#" aria-label="Twitter"><i class="fab fa-twitter"></i></a>
|
143 |
+
<a href="#" aria-label="LinkedIn"><i class="fab fa-linkedin"></i></a>
|
144 |
+
<a href="#" aria-label="Instagram"><i class="fab fa-instagram"></i></a>
|
145 |
+
</div>
|
146 |
+
</div>
|
147 |
+
</div>
|
148 |
+
<div class="footer-bottom">
|
149 |
+
<p>© 2024 DeepSeek. All rights reserved.</p>
|
150 |
+
</div>
|
151 |
+
</footer>
|
152 |
+
</body>
|
153 |
+
</html>
|
admin.css
ADDED
@@ -0,0 +1,711 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Reset and base styles */
|
2 |
+
* {
|
3 |
+
margin: 0;
|
4 |
+
padding: 0;
|
5 |
+
box-sizing: border-box;
|
6 |
+
font-family: 'Arial', sans-serif;
|
7 |
+
}
|
8 |
+
|
9 |
+
body {
|
10 |
+
background-color: #f5f5f5;
|
11 |
+
min-height: 100vh;
|
12 |
+
display: flex;
|
13 |
+
}
|
14 |
+
|
15 |
+
.hidden {
|
16 |
+
display: none !important;
|
17 |
+
}
|
18 |
+
|
19 |
+
/* Login Screen Styles */
|
20 |
+
.login-container {
|
21 |
+
width: 100%;
|
22 |
+
height: 100vh;
|
23 |
+
display: flex;
|
24 |
+
align-items: center;
|
25 |
+
justify-content: center;
|
26 |
+
background-color: #f5f5f5;
|
27 |
+
}
|
28 |
+
|
29 |
+
.login-box {
|
30 |
+
background-color: white;
|
31 |
+
border-radius: 10px;
|
32 |
+
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
|
33 |
+
padding: 40px;
|
34 |
+
width: 400px;
|
35 |
+
max-width: 90%;
|
36 |
+
text-align: center;
|
37 |
+
}
|
38 |
+
|
39 |
+
.login-box .logo-container {
|
40 |
+
width: 80px;
|
41 |
+
height: 80px;
|
42 |
+
margin: 0 auto 20px;
|
43 |
+
}
|
44 |
+
|
45 |
+
.login-box .logo {
|
46 |
+
width: 100%;
|
47 |
+
height: 100%;
|
48 |
+
object-fit: contain;
|
49 |
+
}
|
50 |
+
|
51 |
+
.login-box h2 {
|
52 |
+
font-size: 24px;
|
53 |
+
margin-bottom: 30px;
|
54 |
+
color: #333;
|
55 |
+
}
|
56 |
+
|
57 |
+
.input-group {
|
58 |
+
position: relative;
|
59 |
+
margin-bottom: 20px;
|
60 |
+
}
|
61 |
+
|
62 |
+
.input-group i {
|
63 |
+
position: absolute;
|
64 |
+
left: 15px;
|
65 |
+
top: 50%;
|
66 |
+
transform: translateY(-50%);
|
67 |
+
color: #888;
|
68 |
+
}
|
69 |
+
|
70 |
+
.input-group input {
|
71 |
+
width: 100%;
|
72 |
+
padding: 15px 15px 15px 45px;
|
73 |
+
border: 1px solid #ddd;
|
74 |
+
border-radius: 5px;
|
75 |
+
font-size: 16px;
|
76 |
+
outline: none;
|
77 |
+
transition: border-color 0.3s;
|
78 |
+
}
|
79 |
+
|
80 |
+
.input-group input:focus {
|
81 |
+
border-color: #4285f4;
|
82 |
+
}
|
83 |
+
|
84 |
+
.login-btn {
|
85 |
+
width: 100%;
|
86 |
+
padding: 15px;
|
87 |
+
background-color: #4285f4;
|
88 |
+
color: white;
|
89 |
+
border: none;
|
90 |
+
border-radius: 5px;
|
91 |
+
font-size: 16px;
|
92 |
+
cursor: pointer;
|
93 |
+
transition: background-color 0.3s;
|
94 |
+
}
|
95 |
+
|
96 |
+
.login-btn:hover {
|
97 |
+
background-color: #3367d6;
|
98 |
+
}
|
99 |
+
|
100 |
+
.error-message {
|
101 |
+
color: #d32f2f;
|
102 |
+
margin-top: 15px;
|
103 |
+
font-size: 14px;
|
104 |
+
}
|
105 |
+
|
106 |
+
/* Admin Panel Styles */
|
107 |
+
.admin-container {
|
108 |
+
display: flex;
|
109 |
+
width: 100%;
|
110 |
+
height: 100vh;
|
111 |
+
}
|
112 |
+
|
113 |
+
/* Sidebar Styles */
|
114 |
+
.admin-sidebar {
|
115 |
+
width: 250px;
|
116 |
+
background-color: #2c3e50;
|
117 |
+
color: white;
|
118 |
+
height: 100vh;
|
119 |
+
overflow-y: auto;
|
120 |
+
}
|
121 |
+
|
122 |
+
.admin-logo {
|
123 |
+
padding: 20px;
|
124 |
+
display: flex;
|
125 |
+
align-items: center;
|
126 |
+
gap: 10px;
|
127 |
+
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
128 |
+
}
|
129 |
+
|
130 |
+
.admin-logo .logo {
|
131 |
+
width: 40px;
|
132 |
+
height: 40px;
|
133 |
+
object-fit: contain;
|
134 |
+
}
|
135 |
+
|
136 |
+
.admin-logo h2 {
|
137 |
+
font-size: 18px;
|
138 |
+
font-weight: 500;
|
139 |
+
}
|
140 |
+
|
141 |
+
.admin-menu {
|
142 |
+
list-style-type: none;
|
143 |
+
padding: 20px 0;
|
144 |
+
}
|
145 |
+
|
146 |
+
.admin-menu li {
|
147 |
+
padding: 12px 20px;
|
148 |
+
cursor: pointer;
|
149 |
+
transition: background-color 0.3s;
|
150 |
+
display: flex;
|
151 |
+
align-items: center;
|
152 |
+
gap: 10px;
|
153 |
+
}
|
154 |
+
|
155 |
+
.admin-menu li:hover {
|
156 |
+
background-color: rgba(255, 255, 255, 0.1);
|
157 |
+
}
|
158 |
+
|
159 |
+
.admin-menu li.active {
|
160 |
+
background-color: rgba(255, 255, 255, 0.2);
|
161 |
+
border-left: 4px solid #4285f4;
|
162 |
+
}
|
163 |
+
|
164 |
+
.admin-menu li i {
|
165 |
+
width: 20px;
|
166 |
+
text-align: center;
|
167 |
+
}
|
168 |
+
|
169 |
+
/* Content Area Styles */
|
170 |
+
.admin-content {
|
171 |
+
flex-grow: 1;
|
172 |
+
padding: 20px;
|
173 |
+
overflow-y: auto;
|
174 |
+
height: 100vh;
|
175 |
+
}
|
176 |
+
|
177 |
+
.admin-header {
|
178 |
+
display: flex;
|
179 |
+
justify-content: space-between;
|
180 |
+
align-items: center;
|
181 |
+
margin-bottom: 20px;
|
182 |
+
padding-bottom: 15px;
|
183 |
+
border-bottom: 1px solid #e0e0e0;
|
184 |
+
}
|
185 |
+
|
186 |
+
.admin-header h2 {
|
187 |
+
font-size: 24px;
|
188 |
+
color: #333;
|
189 |
+
}
|
190 |
+
|
191 |
+
.save-btn {
|
192 |
+
padding: 10px 20px;
|
193 |
+
background-color: #4285f4;
|
194 |
+
color: white;
|
195 |
+
border: none;
|
196 |
+
border-radius: 5px;
|
197 |
+
cursor: pointer;
|
198 |
+
display: flex;
|
199 |
+
align-items: center;
|
200 |
+
gap: 8px;
|
201 |
+
transition: background-color 0.3s;
|
202 |
+
}
|
203 |
+
|
204 |
+
.save-btn:hover {
|
205 |
+
background-color: #3367d6;
|
206 |
+
}
|
207 |
+
|
208 |
+
.secondary-btn {
|
209 |
+
padding: 8px 15px;
|
210 |
+
background-color: #f1f3f4;
|
211 |
+
color: #333;
|
212 |
+
border: 1px solid #ddd;
|
213 |
+
border-radius: 5px;
|
214 |
+
cursor: pointer;
|
215 |
+
display: flex;
|
216 |
+
align-items: center;
|
217 |
+
gap: 5px;
|
218 |
+
transition: background-color 0.3s;
|
219 |
+
}
|
220 |
+
|
221 |
+
.secondary-btn:hover {
|
222 |
+
background-color: #e8eaed;
|
223 |
+
}
|
224 |
+
|
225 |
+
/* Tab Content Styles */
|
226 |
+
.tab-content {
|
227 |
+
display: none;
|
228 |
+
}
|
229 |
+
|
230 |
+
.tab-content.active {
|
231 |
+
display: block;
|
232 |
+
}
|
233 |
+
|
234 |
+
.settings-card {
|
235 |
+
background-color: white;
|
236 |
+
border-radius: 8px;
|
237 |
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
|
238 |
+
padding: 25px;
|
239 |
+
margin-bottom: 25px;
|
240 |
+
}
|
241 |
+
|
242 |
+
.settings-card h3 {
|
243 |
+
font-size: 18px;
|
244 |
+
margin-bottom: 15px;
|
245 |
+
color: #333;
|
246 |
+
}
|
247 |
+
|
248 |
+
.settings-card p {
|
249 |
+
color: #666;
|
250 |
+
margin-bottom: 20px;
|
251 |
+
font-size: 14px;
|
252 |
+
}
|
253 |
+
|
254 |
+
.form-group {
|
255 |
+
margin-bottom: 20px;
|
256 |
+
}
|
257 |
+
|
258 |
+
.form-group:last-child {
|
259 |
+
margin-bottom: 0;
|
260 |
+
}
|
261 |
+
|
262 |
+
.form-group label {
|
263 |
+
display: block;
|
264 |
+
margin-bottom: 8px;
|
265 |
+
font-weight: 500;
|
266 |
+
color: #333;
|
267 |
+
}
|
268 |
+
|
269 |
+
.form-group input[type="text"],
|
270 |
+
.form-group input[type="password"],
|
271 |
+
.form-group select,
|
272 |
+
.form-group textarea {
|
273 |
+
width: 100%;
|
274 |
+
padding: 12px 15px;
|
275 |
+
border: 1px solid #ddd;
|
276 |
+
border-radius: 5px;
|
277 |
+
font-size: 14px;
|
278 |
+
outline: none;
|
279 |
+
transition: border-color 0.3s;
|
280 |
+
}
|
281 |
+
|
282 |
+
.form-group input:focus,
|
283 |
+
.form-group select:focus,
|
284 |
+
.form-group textarea:focus {
|
285 |
+
border-color: #4285f4;
|
286 |
+
}
|
287 |
+
|
288 |
+
.input-with-action {
|
289 |
+
position: relative;
|
290 |
+
display: flex;
|
291 |
+
}
|
292 |
+
|
293 |
+
.input-with-action input {
|
294 |
+
flex-grow: 1;
|
295 |
+
padding-right: 40px;
|
296 |
+
}
|
297 |
+
|
298 |
+
.toggle-btn {
|
299 |
+
position: absolute;
|
300 |
+
right: 10px;
|
301 |
+
top: 50%;
|
302 |
+
transform: translateY(-50%);
|
303 |
+
background: none;
|
304 |
+
border: none;
|
305 |
+
color: #888;
|
306 |
+
cursor: pointer;
|
307 |
+
}
|
308 |
+
|
309 |
+
.help-text {
|
310 |
+
font-size: 12px;
|
311 |
+
color: #888;
|
312 |
+
margin-top: 5px;
|
313 |
+
}
|
314 |
+
|
315 |
+
/* Range slider styles */
|
316 |
+
input[type="range"] {
|
317 |
+
width: 100%;
|
318 |
+
height: 5px;
|
319 |
+
-webkit-appearance: none;
|
320 |
+
background: #ddd;
|
321 |
+
outline: none;
|
322 |
+
border-radius: 5px;
|
323 |
+
}
|
324 |
+
|
325 |
+
input[type="range"]::-webkit-slider-thumb {
|
326 |
+
-webkit-appearance: none;
|
327 |
+
appearance: none;
|
328 |
+
width: 18px;
|
329 |
+
height: 18px;
|
330 |
+
border-radius: 50%;
|
331 |
+
background: #4285f4;
|
332 |
+
cursor: pointer;
|
333 |
+
border: 2px solid white;
|
334 |
+
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
|
335 |
+
}
|
336 |
+
|
337 |
+
.slider-description {
|
338 |
+
display: flex;
|
339 |
+
justify-content: space-between;
|
340 |
+
margin-top: 8px;
|
341 |
+
font-size: 12px;
|
342 |
+
color: #888;
|
343 |
+
}
|
344 |
+
|
345 |
+
/* Checkbox styles */
|
346 |
+
.checkbox-group {
|
347 |
+
display: flex;
|
348 |
+
align-items: center;
|
349 |
+
gap: 10px;
|
350 |
+
}
|
351 |
+
|
352 |
+
.checkbox-group input[type="checkbox"] {
|
353 |
+
width: 18px;
|
354 |
+
height: 18px;
|
355 |
+
cursor: pointer;
|
356 |
+
}
|
357 |
+
|
358 |
+
/* Radio button styles */
|
359 |
+
.tone-options {
|
360 |
+
display: flex;
|
361 |
+
flex-wrap: wrap;
|
362 |
+
gap: 15px;
|
363 |
+
margin-top: 5px;
|
364 |
+
}
|
365 |
+
|
366 |
+
.tone-option {
|
367 |
+
display: flex;
|
368 |
+
align-items: center;
|
369 |
+
gap: 8px;
|
370 |
+
}
|
371 |
+
|
372 |
+
.tone-option input[type="radio"] {
|
373 |
+
width: 16px;
|
374 |
+
height: 16px;
|
375 |
+
cursor: pointer;
|
376 |
+
}
|
377 |
+
|
378 |
+
/* Model description */
|
379 |
+
.model-description {
|
380 |
+
background-color: #f9f9f9;
|
381 |
+
padding: 15px;
|
382 |
+
border-radius: 5px;
|
383 |
+
border-left: 4px solid #4285f4;
|
384 |
+
}
|
385 |
+
|
386 |
+
/* Preview container */
|
387 |
+
.preview-container {
|
388 |
+
background-color: #f9f9f9;
|
389 |
+
border-radius: 8px;
|
390 |
+
padding: 20px;
|
391 |
+
margin-top: 15px;
|
392 |
+
}
|
393 |
+
|
394 |
+
.preview-message {
|
395 |
+
background-color: white;
|
396 |
+
border-radius: 8px;
|
397 |
+
padding: 15px;
|
398 |
+
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
|
399 |
+
}
|
400 |
+
|
401 |
+
.preview-question {
|
402 |
+
font-weight: bold;
|
403 |
+
margin-bottom: 10px;
|
404 |
+
color: #333;
|
405 |
+
}
|
406 |
+
|
407 |
+
.preview-response {
|
408 |
+
color: #444;
|
409 |
+
line-height: 1.5;
|
410 |
+
}
|
411 |
+
|
412 |
+
/* Analytics styles */
|
413 |
+
.analytics-grid {
|
414 |
+
display: grid;
|
415 |
+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
|
416 |
+
gap: 20px;
|
417 |
+
margin-bottom: 30px;
|
418 |
+
}
|
419 |
+
|
420 |
+
.analytics-card {
|
421 |
+
background-color: #f9f9f9;
|
422 |
+
border-radius: 8px;
|
423 |
+
padding: 20px;
|
424 |
+
text-align: center;
|
425 |
+
}
|
426 |
+
|
427 |
+
.analytics-card h4 {
|
428 |
+
font-size: 14px;
|
429 |
+
margin-bottom: 10px;
|
430 |
+
color: #666;
|
431 |
+
}
|
432 |
+
|
433 |
+
.analytics-number {
|
434 |
+
font-size: 24px;
|
435 |
+
font-weight: bold;
|
436 |
+
color: #333;
|
437 |
+
}
|
438 |
+
|
439 |
+
.chart-container {
|
440 |
+
background-color: #f9f9f9;
|
441 |
+
border-radius: 8px;
|
442 |
+
padding: 20px;
|
443 |
+
}
|
444 |
+
|
445 |
+
.chart-container h4 {
|
446 |
+
font-size: 16px;
|
447 |
+
margin-bottom: 15px;
|
448 |
+
color: #333;
|
449 |
+
}
|
450 |
+
|
451 |
+
.placeholder-chart {
|
452 |
+
height: 200px;
|
453 |
+
display: flex;
|
454 |
+
flex-direction: column;
|
455 |
+
}
|
456 |
+
|
457 |
+
.chart-bars {
|
458 |
+
display: flex;
|
459 |
+
justify-content: space-between;
|
460 |
+
align-items: flex-end;
|
461 |
+
height: 180px;
|
462 |
+
padding: 0 10px;
|
463 |
+
}
|
464 |
+
|
465 |
+
.chart-bar {
|
466 |
+
width: 30px;
|
467 |
+
background-color: #4285f4;
|
468 |
+
border-radius: 5px 5px 0 0;
|
469 |
+
}
|
470 |
+
|
471 |
+
.chart-labels {
|
472 |
+
display: flex;
|
473 |
+
justify-content: space-between;
|
474 |
+
margin-top: 10px;
|
475 |
+
padding: 0 10px;
|
476 |
+
}
|
477 |
+
|
478 |
+
.chart-labels span {
|
479 |
+
font-size: 12px;
|
480 |
+
color: #888;
|
481 |
+
}
|
482 |
+
|
483 |
+
.common-questions {
|
484 |
+
list-style-type: none;
|
485 |
+
}
|
486 |
+
|
487 |
+
.common-questions li {
|
488 |
+
padding: 10px 0;
|
489 |
+
border-bottom: 1px solid #eee;
|
490 |
+
display: flex;
|
491 |
+
align-items: center;
|
492 |
+
gap: 15px;
|
493 |
+
}
|
494 |
+
|
495 |
+
.common-questions li:last-child {
|
496 |
+
border-bottom: none;
|
497 |
+
}
|
498 |
+
|
499 |
+
.question-count {
|
500 |
+
background-color: #4285f4;
|
501 |
+
color: white;
|
502 |
+
width: 30px;
|
503 |
+
height: 30px;
|
504 |
+
border-radius: 50%;
|
505 |
+
display: flex;
|
506 |
+
align-items: center;
|
507 |
+
justify-content: center;
|
508 |
+
font-size: 12px;
|
509 |
+
font-weight: bold;
|
510 |
+
}
|
511 |
+
|
512 |
+
/* Responsive design */
|
513 |
+
@media (max-width: 1200px) {
|
514 |
+
.analytics-grid {
|
515 |
+
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
516 |
+
}
|
517 |
+
}
|
518 |
+
|
519 |
+
@media (max-width: 992px) {
|
520 |
+
.admin-sidebar {
|
521 |
+
width: 200px;
|
522 |
+
}
|
523 |
+
|
524 |
+
.settings-card {
|
525 |
+
padding: 20px;
|
526 |
+
}
|
527 |
+
}
|
528 |
+
|
529 |
+
@media (max-width: 768px) {
|
530 |
+
.admin-container {
|
531 |
+
flex-direction: column;
|
532 |
+
}
|
533 |
+
|
534 |
+
.admin-sidebar {
|
535 |
+
width: 100%;
|
536 |
+
height: auto;
|
537 |
+
position: sticky;
|
538 |
+
top: 0;
|
539 |
+
z-index: 100;
|
540 |
+
}
|
541 |
+
|
542 |
+
.admin-menu {
|
543 |
+
display: flex;
|
544 |
+
padding: 10px;
|
545 |
+
overflow-x: auto;
|
546 |
+
-webkit-overflow-scrolling: touch;
|
547 |
+
}
|
548 |
+
|
549 |
+
.admin-menu li {
|
550 |
+
padding: 10px 15px;
|
551 |
+
white-space: nowrap;
|
552 |
+
border-left: none !important;
|
553 |
+
}
|
554 |
+
|
555 |
+
.admin-logo {
|
556 |
+
justify-content: center;
|
557 |
+
padding: 10px;
|
558 |
+
}
|
559 |
+
|
560 |
+
.admin-content {
|
561 |
+
padding: 15px;
|
562 |
+
height: calc(100vh - 120px);
|
563 |
+
}
|
564 |
+
|
565 |
+
.analytics-grid {
|
566 |
+
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
567 |
+
gap: 15px;
|
568 |
+
}
|
569 |
+
|
570 |
+
.login-box {
|
571 |
+
width: 90%;
|
572 |
+
max-width: 350px;
|
573 |
+
padding: 30px;
|
574 |
+
}
|
575 |
+
}
|
576 |
+
|
577 |
+
@media (max-width: 576px) {
|
578 |
+
.admin-header {
|
579 |
+
flex-direction: column;
|
580 |
+
gap: 10px;
|
581 |
+
align-items: flex-start;
|
582 |
+
}
|
583 |
+
|
584 |
+
.admin-actions {
|
585 |
+
width: 100%;
|
586 |
+
display: flex;
|
587 |
+
justify-content: flex-end;
|
588 |
+
}
|
589 |
+
|
590 |
+
.settings-card {
|
591 |
+
padding: 15px;
|
592 |
+
}
|
593 |
+
|
594 |
+
.analytics-grid {
|
595 |
+
grid-template-columns: 1fr 1fr;
|
596 |
+
}
|
597 |
+
|
598 |
+
.tone-options {
|
599 |
+
flex-direction: column;
|
600 |
+
gap: 10px;
|
601 |
+
}
|
602 |
+
|
603 |
+
.form-group input[type="text"],
|
604 |
+
.form-group input[type="password"],
|
605 |
+
.form-group select,
|
606 |
+
.form-group textarea {
|
607 |
+
font-size: 16px; /* Prevent zoom on mobile */
|
608 |
+
}
|
609 |
+
}
|
610 |
+
|
611 |
+
/* Dark mode support */
|
612 |
+
@media (prefers-color-scheme: dark) {
|
613 |
+
body {
|
614 |
+
background-color: #1a1a1a;
|
615 |
+
color: #ffffff;
|
616 |
+
}
|
617 |
+
|
618 |
+
.login-box,
|
619 |
+
.settings-card,
|
620 |
+
.admin-content {
|
621 |
+
background-color: #2d2d2d;
|
622 |
+
color: #ffffff;
|
623 |
+
}
|
624 |
+
|
625 |
+
.input-group input,
|
626 |
+
.form-group input[type="text"],
|
627 |
+
.form-group input[type="password"],
|
628 |
+
.form-group select,
|
629 |
+
.form-group textarea {
|
630 |
+
background-color: #3d3d3d;
|
631 |
+
color: #ffffff;
|
632 |
+
border-color: #4d4d4d;
|
633 |
+
}
|
634 |
+
|
635 |
+
.admin-sidebar {
|
636 |
+
background-color: #2d2d2d;
|
637 |
+
}
|
638 |
+
|
639 |
+
.preview-container {
|
640 |
+
background-color: #3d3d3d;
|
641 |
+
}
|
642 |
+
|
643 |
+
.preview-message {
|
644 |
+
background-color: #4d4d4d;
|
645 |
+
color: #ffffff;
|
646 |
+
}
|
647 |
+
}
|
648 |
+
|
649 |
+
/* Touch device optimizations */
|
650 |
+
@media (hover: none) {
|
651 |
+
.admin-menu li:hover {
|
652 |
+
background-color: transparent;
|
653 |
+
}
|
654 |
+
|
655 |
+
.admin-menu li:active {
|
656 |
+
background-color: rgba(255, 255, 255, 0.1);
|
657 |
+
}
|
658 |
+
}
|
659 |
+
|
660 |
+
/* Accessibility improvements */
|
661 |
+
:focus {
|
662 |
+
outline: 2px solid #4285f4;
|
663 |
+
outline-offset: 2px;
|
664 |
+
}
|
665 |
+
|
666 |
+
.sr-only {
|
667 |
+
position: absolute;
|
668 |
+
width: 1px;
|
669 |
+
height: 1px;
|
670 |
+
padding: 0;
|
671 |
+
margin: -1px;
|
672 |
+
overflow: hidden;
|
673 |
+
clip: rect(0, 0, 0, 0);
|
674 |
+
border: 0;
|
675 |
+
}
|
676 |
+
|
677 |
+
/* Notification styles */
|
678 |
+
.notification {
|
679 |
+
position: fixed;
|
680 |
+
top: 20px;
|
681 |
+
right: 20px;
|
682 |
+
padding: 15px 20px;
|
683 |
+
border-radius: 5px;
|
684 |
+
background-color: white;
|
685 |
+
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);
|
686 |
+
z-index: 1000;
|
687 |
+
transition: transform 0.3s, opacity 0.3s;
|
688 |
+
transform: translateY(0);
|
689 |
+
opacity: 1;
|
690 |
+
}
|
691 |
+
|
692 |
+
.notification-info {
|
693 |
+
border-left: 4px solid #4285f4;
|
694 |
+
}
|
695 |
+
|
696 |
+
.notification-success {
|
697 |
+
border-left: 4px solid #0f9d58;
|
698 |
+
}
|
699 |
+
|
700 |
+
.notification-warning {
|
701 |
+
border-left: 4px solid #f4b400;
|
702 |
+
}
|
703 |
+
|
704 |
+
.notification-error {
|
705 |
+
border-left: 4px solid #db4437;
|
706 |
+
}
|
707 |
+
|
708 |
+
.notification-hide {
|
709 |
+
transform: translateY(-20px);
|
710 |
+
opacity: 0;
|
711 |
+
}
|
admin.html
ADDED
@@ -0,0 +1,258 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Muhafiz AI Admin Panel</title>
|
7 |
+
<link rel="stylesheet" href="css/admin.css">
|
8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
9 |
+
<script>
|
10 |
+
// Authentication check
|
11 |
+
if (localStorage.getItem('adminLoggedIn') !== 'true') {
|
12 |
+
// Store the current URL to redirect back after login
|
13 |
+
const currentPath = window.location.pathname;
|
14 |
+
const redirectUrl = 'login.html?redirect=' + encodeURIComponent(currentPath);
|
15 |
+
window.location.href = redirectUrl;
|
16 |
+
}
|
17 |
+
</script>
|
18 |
+
</head>
|
19 |
+
<body>
|
20 |
+
<div class="admin-container">
|
21 |
+
<!-- Sidebar -->
|
22 |
+
<aside class="sidebar">
|
23 |
+
<div class="sidebar-header">
|
24 |
+
<img src="images/logo.png" alt="Muhafiz AI Logo" class="admin-logo">
|
25 |
+
<h2>Admin Panel</h2>
|
26 |
+
</div>
|
27 |
+
<nav class="sidebar-nav">
|
28 |
+
<a href="#dashboard" class="nav-item active" data-tab="dashboard">
|
29 |
+
<i class="fas fa-chart-line"></i>
|
30 |
+
<span>Dashboard</span>
|
31 |
+
</a>
|
32 |
+
<a href="#conversations" class="nav-item" data-tab="conversations">
|
33 |
+
<i class="fas fa-comments"></i>
|
34 |
+
<span>Conversations</span>
|
35 |
+
</a>
|
36 |
+
<a href="#users" class="nav-item" data-tab="users">
|
37 |
+
<i class="fas fa-users"></i>
|
38 |
+
<span>Users</span>
|
39 |
+
</a>
|
40 |
+
<a href="#settings" class="nav-item" data-tab="settings">
|
41 |
+
<i class="fas fa-cog"></i>
|
42 |
+
<span>Settings</span>
|
43 |
+
</a>
|
44 |
+
<a href="#analytics" class="nav-item" data-tab="analytics">
|
45 |
+
<i class="fas fa-chart-bar"></i>
|
46 |
+
<span>Analytics</span>
|
47 |
+
</a>
|
48 |
+
</nav>
|
49 |
+
<div class="sidebar-footer">
|
50 |
+
<button id="logoutBtn" class="logout-btn">
|
51 |
+
<i class="fas fa-sign-out-alt"></i>
|
52 |
+
<span>Logout</span>
|
53 |
+
</button>
|
54 |
+
</div>
|
55 |
+
</aside>
|
56 |
+
|
57 |
+
<!-- Main Content -->
|
58 |
+
<main class="main-content">
|
59 |
+
<!-- Top Bar -->
|
60 |
+
<header class="top-bar">
|
61 |
+
<div class="search-bar">
|
62 |
+
<i class="fas fa-search"></i>
|
63 |
+
<input type="text" placeholder="Search...">
|
64 |
+
</div>
|
65 |
+
<div class="top-bar-actions">
|
66 |
+
<button class="theme-toggle" id="adminThemeToggle">
|
67 |
+
<i class="fas fa-moon"></i>
|
68 |
+
</button>
|
69 |
+
<div class="admin-profile">
|
70 |
+
<img src="images/admin-avatar.png" alt="Admin" class="admin-avatar">
|
71 |
+
<span>Admin</span>
|
72 |
+
</div>
|
73 |
+
</div>
|
74 |
+
</header>
|
75 |
+
|
76 |
+
<!-- Dashboard Tab -->
|
77 |
+
<div class="tab-content active" id="dashboard">
|
78 |
+
<h2>Dashboard</h2>
|
79 |
+
<div class="stats-grid">
|
80 |
+
<div class="stat-card">
|
81 |
+
<div class="stat-icon"><i class="fas fa-users"></i></div>
|
82 |
+
<div class="stat-info">
|
83 |
+
<h3>Total Users</h3>
|
84 |
+
<p>1,234</p>
|
85 |
+
</div>
|
86 |
+
</div>
|
87 |
+
<div class="stat-card">
|
88 |
+
<div class="stat-icon"><i class="fas fa-comments"></i></div>
|
89 |
+
<div class="stat-info">
|
90 |
+
<h3>Conversations</h3>
|
91 |
+
<p>5,678</p>
|
92 |
+
</div>
|
93 |
+
</div>
|
94 |
+
<div class="stat-card">
|
95 |
+
<div class="stat-icon"><i class="fas fa-clock"></i></div>
|
96 |
+
<div class="stat-info">
|
97 |
+
<h3>Avg. Response Time</h3>
|
98 |
+
<p>1.5s</p>
|
99 |
+
</div>
|
100 |
+
</div>
|
101 |
+
<div class="stat-card">
|
102 |
+
<div class="stat-icon"><i class="fas fa-chart-line"></i></div>
|
103 |
+
<div class="stat-info">
|
104 |
+
<h3>Success Rate</h3>
|
105 |
+
<p>98.5%</p>
|
106 |
+
</div>
|
107 |
+
</div>
|
108 |
+
</div>
|
109 |
+
<div class="charts-grid">
|
110 |
+
<div class="chart-card">
|
111 |
+
<h3>User Activity</h3>
|
112 |
+
<div class="chart-placeholder">
|
113 |
+
<!-- Chart will be rendered here -->
|
114 |
+
</div>
|
115 |
+
</div>
|
116 |
+
<div class="chart-card">
|
117 |
+
<h3>Response Times</h3>
|
118 |
+
<div class="chart-placeholder">
|
119 |
+
<!-- Chart will be rendered here -->
|
120 |
+
</div>
|
121 |
+
</div>
|
122 |
+
</div>
|
123 |
+
</div>
|
124 |
+
|
125 |
+
<!-- Settings Tab -->
|
126 |
+
<div class="tab-content" id="settings">
|
127 |
+
<h2>Settings</h2>
|
128 |
+
<div class="settings-grid">
|
129 |
+
<div class="settings-card">
|
130 |
+
<h3>OpenRouter API Configuration</h3>
|
131 |
+
<form id="apiSettingsForm">
|
132 |
+
<div class="form-group">
|
133 |
+
<label for="apiKey">OpenRouter API Key</label>
|
134 |
+
<div class="input-with-copy">
|
135 |
+
<input type="password" id="apiKey" name="apiKey">
|
136 |
+
<button type="button" class="copy-btn" title="Toggle visibility">
|
137 |
+
<i class="fas fa-eye"></i>
|
138 |
+
</button>
|
139 |
+
</div>
|
140 |
+
</div>
|
141 |
+
<div class="form-group">
|
142 |
+
<label for="siteUrl">Your Site URL</label>
|
143 |
+
<input type="url" id="siteUrl" name="siteUrl" placeholder="https://your-site.com">
|
144 |
+
</div>
|
145 |
+
<div class="form-group">
|
146 |
+
<label for="siteName">Your Site Name</label>
|
147 |
+
<input type="text" id="siteName" name="siteName" placeholder="Muhafiz AI">
|
148 |
+
</div>
|
149 |
+
<button type="submit" class="btn-primary">Save API Settings</button>
|
150 |
+
</form>
|
151 |
+
</div>
|
152 |
+
<div class="settings-card">
|
153 |
+
<h3>Model Settings</h3>
|
154 |
+
<form id="modelSettingsForm">
|
155 |
+
<div class="form-group">
|
156 |
+
<label for="modelSelect">Select Model</label>
|
157 |
+
<select id="modelSelect" name="model">
|
158 |
+
<option value="qwen/qwen3-14b:free">Qwen 14B (Free)</option>
|
159 |
+
<option value="mistralai/mistral-7b-instruct:free">Mistral 7B Instruct (Free)</option>
|
160 |
+
<option value="meta-llama/codellama-34b-instruct:free">CodeLlama 34B (Free)</option>
|
161 |
+
<option value="gryphe/mythomist-7b:free">MythoMist 7B (Free)</option>
|
162 |
+
<option value="anthropic/claude-3-opus:ultra">Claude 3 Opus (Ultra)</option>
|
163 |
+
<option value="anthropic/claude-3-sonnet:beta">Claude 3 Sonnet (Beta)</option>
|
164 |
+
</select>
|
165 |
+
</div>
|
166 |
+
<div class="form-group">
|
167 |
+
<label for="temperature">Temperature</label>
|
168 |
+
<div class="range-with-value">
|
169 |
+
<input type="range" id="temperature" name="temperature" min="0" max="1" step="0.1" value="0.7">
|
170 |
+
<span class="range-value">0.7</span>
|
171 |
+
</div>
|
172 |
+
<small class="help-text">Controls randomness: 0 is focused, 1 is creative</small>
|
173 |
+
</div>
|
174 |
+
<div class="form-group">
|
175 |
+
<label for="maxTokens">Max Tokens</label>
|
176 |
+
<input type="number" id="maxTokens" name="maxTokens" min="1" max="4096" value="2048">
|
177 |
+
<small class="help-text">Maximum length of the response</small>
|
178 |
+
</div>
|
179 |
+
<div class="form-group">
|
180 |
+
<label class="checkbox-label">
|
181 |
+
<input type="checkbox" id="streamResponse" name="streamResponse" checked>
|
182 |
+
<span>Stream Response</span>
|
183 |
+
</label>
|
184 |
+
<small class="help-text">Show response as it's being generated</small>
|
185 |
+
</div>
|
186 |
+
<button type="submit" class="btn-primary">Apply Model Settings</button>
|
187 |
+
<button type="button" class="btn-secondary" id="testModel">
|
188 |
+
<i class="fas fa-vial"></i> Test Model
|
189 |
+
</button>
|
190 |
+
</form>
|
191 |
+
</div>
|
192 |
+
</div>
|
193 |
+
<div class="card">
|
194 |
+
<h3>Test API Response</h3>
|
195 |
+
<div class="form-group">
|
196 |
+
<label for="testMessage">Test Message</label>
|
197 |
+
<input type="text" id="testMessage" placeholder="Enter a test message" value="Hello! Can you hear me?">
|
198 |
+
</div>
|
199 |
+
<div class="test-response-container" style="display: none;">
|
200 |
+
<h4>API Response:</h4>
|
201 |
+
<div id="testResponse" class="test-response"></div>
|
202 |
+
<div id="testError" class="test-error"></div>
|
203 |
+
</div>
|
204 |
+
<button id="testApiBtn" class="btn-secondary">
|
205 |
+
<i class="fas fa-vial"></i> Test API Response
|
206 |
+
</button>
|
207 |
+
</div>
|
208 |
+
</div>
|
209 |
+
</main>
|
210 |
+
</div>
|
211 |
+
<script src="js/admin.js"></script>
|
212 |
+
<style>
|
213 |
+
.test-response-container {
|
214 |
+
margin-top: 16px;
|
215 |
+
padding: 16px;
|
216 |
+
border-radius: 8px;
|
217 |
+
background: var(--hover-bg);
|
218 |
+
}
|
219 |
+
|
220 |
+
.test-response {
|
221 |
+
white-space: pre-wrap;
|
222 |
+
font-family: monospace;
|
223 |
+
margin-top: 8px;
|
224 |
+
padding: 12px;
|
225 |
+
border-radius: 6px;
|
226 |
+
background: var(--admin-bg);
|
227 |
+
border: 1px solid var(--border-color);
|
228 |
+
max-height: 200px;
|
229 |
+
overflow-y: auto;
|
230 |
+
}
|
231 |
+
|
232 |
+
.test-error {
|
233 |
+
color: var(--error-color);
|
234 |
+
margin-top: 8px;
|
235 |
+
font-size: 14px;
|
236 |
+
}
|
237 |
+
|
238 |
+
#testApiBtn {
|
239 |
+
margin-top: 16px;
|
240 |
+
width: 100%;
|
241 |
+
}
|
242 |
+
|
243 |
+
#testApiBtn.loading {
|
244 |
+
opacity: 0.7;
|
245 |
+
cursor: not-allowed;
|
246 |
+
}
|
247 |
+
|
248 |
+
#testApiBtn.loading i {
|
249 |
+
animation: spin 1s linear infinite;
|
250 |
+
}
|
251 |
+
|
252 |
+
@keyframes spin {
|
253 |
+
from { transform: rotate(0deg); }
|
254 |
+
to { transform: rotate(360deg); }
|
255 |
+
}
|
256 |
+
</style>
|
257 |
+
</body>
|
258 |
+
</html>
|
admin.js
ADDED
@@ -0,0 +1,516 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// DOM Elements for Admin Panel
|
2 |
+
const loginScreen = document.getElementById('login-screen');
|
3 |
+
const adminPanel = document.getElementById('admin-panel');
|
4 |
+
const usernameInput = document.getElementById('username');
|
5 |
+
const passwordInput = document.getElementById('password');
|
6 |
+
const loginBtn = document.getElementById('login-btn');
|
7 |
+
const loginError = document.getElementById('login-error');
|
8 |
+
const logoutBtn = document.getElementById('logout-btn');
|
9 |
+
const sectionTitle = document.getElementById('section-title');
|
10 |
+
const saveBtn = document.getElementById('save-btn');
|
11 |
+
const menuItems = document.querySelectorAll('.admin-menu li');
|
12 |
+
const tabContents = document.querySelectorAll('.tab-content');
|
13 |
+
|
14 |
+
// API Settings Form Elements
|
15 |
+
const apiKeyInput = document.getElementById('api-key');
|
16 |
+
const toggleApiKeyBtn = document.getElementById('toggle-api-key');
|
17 |
+
const apiEndpointInput = document.getElementById('api-endpoint');
|
18 |
+
const testApiBtn = document.getElementById('test-api-btn');
|
19 |
+
|
20 |
+
// Model Settings Form Elements
|
21 |
+
const modelSelect = document.getElementById('model-select');
|
22 |
+
const modelDescription = document.getElementById('model-description');
|
23 |
+
const temperatureSlider = document.getElementById('temperature');
|
24 |
+
const tempValue = document.getElementById('temp-value');
|
25 |
+
const maxTokensSlider = document.getElementById('max-tokens');
|
26 |
+
const tokensValue = document.getElementById('tokens-value');
|
27 |
+
|
28 |
+
// Instructions Form Elements
|
29 |
+
const chatbotInstructions = document.getElementById('chatbot-instructions');
|
30 |
+
const includeKnowledgeBase = document.getElementById('include-knowledge-base');
|
31 |
+
const templateSelect = document.getElementById('template-select');
|
32 |
+
const applyTemplateBtn = document.getElementById('apply-template-btn');
|
33 |
+
|
34 |
+
// Tone Settings Form Elements
|
35 |
+
const toneOptions = document.querySelectorAll('input[name="tone"]');
|
36 |
+
const responseStyle = document.getElementById('response-style');
|
37 |
+
const customToneInstructions = document.getElementById('custom-tone-instructions');
|
38 |
+
const generatePreviewBtn = document.getElementById('generate-preview-btn');
|
39 |
+
const previewResponse = document.querySelector('.preview-response');
|
40 |
+
|
41 |
+
// Advanced Settings Form Elements
|
42 |
+
const enableMemory = document.getElementById('enable-memory');
|
43 |
+
const memoryLimit = document.getElementById('memory-limit');
|
44 |
+
const enableStreaming = document.getElementById('enable-streaming');
|
45 |
+
const enableWebSearch = document.getElementById('enable-web-search');
|
46 |
+
const widgetPosition = document.getElementById('widget-position');
|
47 |
+
const primaryColor = document.getElementById('primary-color');
|
48 |
+
const autoOpen = document.getElementById('auto-open');
|
49 |
+
|
50 |
+
// Chat configuration object (will be loaded from localStorage)
|
51 |
+
let chatConfig = {
|
52 |
+
apiKey: '',
|
53 |
+
apiEndpoint: 'https://api.deepseek.com/v1/chat/completions',
|
54 |
+
model: 'deepseek-chat',
|
55 |
+
instructions: 'You are a helpful, friendly AI assistant called DeepSeek.',
|
56 |
+
toneStyle: 'friendly',
|
57 |
+
responseStyle: 'balanced',
|
58 |
+
customTone: '',
|
59 |
+
maxTokens: 1000,
|
60 |
+
temperature: 0.7,
|
61 |
+
memory: true,
|
62 |
+
memoryContext: 10,
|
63 |
+
streaming: true,
|
64 |
+
webSearch: false,
|
65 |
+
widgetPosition: 'bottom-right',
|
66 |
+
primaryColor: '#4285f4',
|
67 |
+
autoOpen: true
|
68 |
+
};
|
69 |
+
|
70 |
+
// Admin Templates
|
71 |
+
const templates = {
|
72 |
+
'customer-support': {
|
73 |
+
instructions: 'You are DeepSeek, a helpful customer support assistant. Your role is to provide clear, accurate information about our products and services, help troubleshoot issues, and ensure customers feel valued and supported. Be friendly but professional, offer solutions rather than just explanations, and ask clarifying questions when needed.',
|
74 |
+
tone: 'professional'
|
75 |
+
},
|
76 |
+
'technical-assistant': {
|
77 |
+
instructions: 'You are DeepSeek, a technical assistant specializing in programming, software development, and IT support. Provide detailed technical explanations, code samples when appropriate, and help users solve technical problems. Use precise terminology but remain accessible to users with varying levels of technical expertise.',
|
78 |
+
tone: 'professional'
|
79 |
+
},
|
80 |
+
'creative-writer': {
|
81 |
+
instructions: 'You are DeepSeek, a creative writing assistant. Help users with storytelling, poetry, creative content ideas, and writing improvements. Be imaginative, inspirational, and provide examples that showcase various writing styles. When asked to generate creative content, aim for originality and emotional resonance.',
|
82 |
+
tone: 'casual'
|
83 |
+
},
|
84 |
+
'research-assistant': {
|
85 |
+
instructions: 'You are DeepSeek, a research assistant with broad knowledge across academic fields. Help users find information, explore concepts, understand complex topics, and organize research findings. Provide comprehensive and nuanced responses while maintaining academic rigor. Cite limitations of your knowledge when appropriate.',
|
86 |
+
tone: 'formal'
|
87 |
+
}
|
88 |
+
};
|
89 |
+
|
90 |
+
// Model descriptions
|
91 |
+
const modelDescriptions = {
|
92 |
+
'deepseek-chat': '<strong>DeepSeek Chat:</strong> General-purpose AI designed for conversation, providing helpful and accurate responses across a wide range of topics.',
|
93 |
+
'deepseek-chat-plus': '<strong>DeepSeek Chat Plus:</strong> Enhanced version of DeepSeek Chat with improved reasoning capabilities and more extensive knowledge base. Ideal for complex conversations.',
|
94 |
+
'deepseek-coder': '<strong>DeepSeek Coder:</strong> Specialized model for programming and software development tasks. Excels at code generation, debugging, and technical explanations.',
|
95 |
+
'deepseek-research': '<strong>DeepSeek Research:</strong> Advanced model optimized for research tasks, data analysis, and academic content. Features in-depth knowledge across scientific domains.'
|
96 |
+
};
|
97 |
+
|
98 |
+
// Add error handling wrapper
|
99 |
+
function handleAsyncError(fn) {
|
100 |
+
return async function(...args) {
|
101 |
+
try {
|
102 |
+
await fn.apply(this, args);
|
103 |
+
} catch (error) {
|
104 |
+
console.error('Error:', error);
|
105 |
+
showNotification(error.message, 'error');
|
106 |
+
}
|
107 |
+
};
|
108 |
+
}
|
109 |
+
|
110 |
+
// Handle login with rate limiting
|
111 |
+
let loginAttempts = 0;
|
112 |
+
let lastLoginAttempt = 0;
|
113 |
+
|
114 |
+
async function handleLogin() {
|
115 |
+
const now = Date.now();
|
116 |
+
const timeSinceLastAttempt = now - lastLoginAttempt;
|
117 |
+
|
118 |
+
// Rate limiting
|
119 |
+
if (loginAttempts >= 5 && timeSinceLastAttempt < 300000) { // 5 minutes lockout
|
120 |
+
const remainingTime = Math.ceil((300000 - timeSinceLastAttempt) / 60000);
|
121 |
+
loginError.textContent = `Too many attempts. Please try again in ${remainingTime} minutes.`;
|
122 |
+
return;
|
123 |
+
}
|
124 |
+
|
125 |
+
const username = usernameInput.value;
|
126 |
+
const password = passwordInput.value;
|
127 |
+
|
128 |
+
if (!username || !password) {
|
129 |
+
loginError.textContent = 'Please enter both username and password.';
|
130 |
+
return;
|
131 |
+
}
|
132 |
+
|
133 |
+
const storedUsername = localStorage.getItem('adminUsername');
|
134 |
+
const storedPassword = localStorage.getItem('adminPassword');
|
135 |
+
|
136 |
+
lastLoginAttempt = now;
|
137 |
+
|
138 |
+
if (username === storedUsername && password === storedPassword) {
|
139 |
+
loginAttempts = 0;
|
140 |
+
loginScreen.classList.add('hidden');
|
141 |
+
adminPanel.classList.remove('hidden');
|
142 |
+
loadConfig();
|
143 |
+
setFormValues();
|
144 |
+
} else {
|
145 |
+
loginAttempts++;
|
146 |
+
loginError.textContent = 'Invalid username or password';
|
147 |
+
setTimeout(() => {
|
148 |
+
loginError.textContent = '';
|
149 |
+
}, 3000);
|
150 |
+
}
|
151 |
+
}
|
152 |
+
|
153 |
+
// Handle logout with confirmation
|
154 |
+
function handleLogout() {
|
155 |
+
if (hasUnsavedChanges()) {
|
156 |
+
if (!confirm('You have unsaved changes. Are you sure you want to logout?')) {
|
157 |
+
return;
|
158 |
+
}
|
159 |
+
}
|
160 |
+
|
161 |
+
adminPanel.classList.add('hidden');
|
162 |
+
loginScreen.classList.remove('hidden');
|
163 |
+
usernameInput.value = '';
|
164 |
+
passwordInput.value = '';
|
165 |
+
resetUnsavedChanges();
|
166 |
+
}
|
167 |
+
|
168 |
+
// Track unsaved changes
|
169 |
+
let hasUnsavedChanges = () => false;
|
170 |
+
let resetUnsavedChanges = () => {};
|
171 |
+
|
172 |
+
// Set up change tracking
|
173 |
+
function setupChangeTracking() {
|
174 |
+
const formElements = document.querySelectorAll('input, select, textarea');
|
175 |
+
let initialValues = new Map();
|
176 |
+
|
177 |
+
formElements.forEach(element => {
|
178 |
+
initialValues.set(element, element.value);
|
179 |
+
|
180 |
+
element.addEventListener('change', () => {
|
181 |
+
const hasChanges = Array.from(formElements).some(el =>
|
182 |
+
initialValues.get(el) !== el.value
|
183 |
+
);
|
184 |
+
hasUnsavedChanges = () => hasChanges;
|
185 |
+
});
|
186 |
+
});
|
187 |
+
|
188 |
+
resetUnsavedChanges = () => {
|
189 |
+
formElements.forEach(element => {
|
190 |
+
initialValues.set(element, element.value);
|
191 |
+
});
|
192 |
+
hasUnsavedChanges = () => false;
|
193 |
+
};
|
194 |
+
}
|
195 |
+
|
196 |
+
// Save configuration with validation
|
197 |
+
async function saveConfig() {
|
198 |
+
// Validate API settings
|
199 |
+
if (!apiKeyInput.value) {
|
200 |
+
showNotification('API Key is required.', 'error');
|
201 |
+
return;
|
202 |
+
}
|
203 |
+
|
204 |
+
if (!apiEndpointInput.value) {
|
205 |
+
showNotification('API Endpoint is required.', 'error');
|
206 |
+
return;
|
207 |
+
}
|
208 |
+
|
209 |
+
// Validate model settings
|
210 |
+
if (parseFloat(temperatureSlider.value) < 0 || parseFloat(temperatureSlider.value) > 1) {
|
211 |
+
showNotification('Temperature must be between 0 and 1.', 'error');
|
212 |
+
return;
|
213 |
+
}
|
214 |
+
|
215 |
+
// Save configuration
|
216 |
+
try {
|
217 |
+
// API Settings
|
218 |
+
chatConfig.apiKey = apiKeyInput.value;
|
219 |
+
chatConfig.apiEndpoint = apiEndpointInput.value;
|
220 |
+
|
221 |
+
// Model Settings
|
222 |
+
chatConfig.model = modelSelect.value;
|
223 |
+
chatConfig.temperature = parseFloat(temperatureSlider.value);
|
224 |
+
chatConfig.maxTokens = parseInt(maxTokensSlider.value);
|
225 |
+
|
226 |
+
// Instructions
|
227 |
+
chatConfig.instructions = chatbotInstructions.value;
|
228 |
+
|
229 |
+
// Tone Settings
|
230 |
+
toneOptions.forEach(option => {
|
231 |
+
if (option.checked) {
|
232 |
+
chatConfig.toneStyle = option.value;
|
233 |
+
}
|
234 |
+
});
|
235 |
+
chatConfig.responseStyle = responseStyle.value;
|
236 |
+
chatConfig.customTone = customToneInstructions.value;
|
237 |
+
|
238 |
+
// Advanced Settings
|
239 |
+
chatConfig.memory = enableMemory.checked;
|
240 |
+
chatConfig.memoryContext = parseInt(memoryLimit.value);
|
241 |
+
chatConfig.streaming = enableStreaming.checked;
|
242 |
+
chatConfig.webSearch = enableWebSearch.checked;
|
243 |
+
chatConfig.widgetPosition = widgetPosition.value;
|
244 |
+
chatConfig.primaryColor = primaryColor.value;
|
245 |
+
chatConfig.autoOpen = autoOpen.checked;
|
246 |
+
|
247 |
+
// Save to localStorage
|
248 |
+
localStorage.setItem('chatConfig', JSON.stringify(chatConfig));
|
249 |
+
|
250 |
+
// Reset unsaved changes tracker
|
251 |
+
resetUnsavedChanges();
|
252 |
+
|
253 |
+
// Show success notification
|
254 |
+
showNotification('Changes saved successfully.', 'success');
|
255 |
+
|
256 |
+
// Broadcast configuration change event
|
257 |
+
window.dispatchEvent(new CustomEvent('chatConfigUpdated', { detail: chatConfig }));
|
258 |
+
} catch (error) {
|
259 |
+
console.error('Save Error:', error);
|
260 |
+
showNotification('Failed to save changes: ' + error.message, 'error');
|
261 |
+
}
|
262 |
+
}
|
263 |
+
|
264 |
+
// Test API connection with timeout
|
265 |
+
async function testApiConnection() {
|
266 |
+
const apiKey = apiKeyInput.value;
|
267 |
+
const apiEndpoint = apiEndpointInput.value;
|
268 |
+
|
269 |
+
if (!apiKey) {
|
270 |
+
showNotification('Please enter an API key.', 'error');
|
271 |
+
return;
|
272 |
+
}
|
273 |
+
|
274 |
+
showNotification('Testing API connection...', 'info');
|
275 |
+
|
276 |
+
try {
|
277 |
+
const controller = new AbortController();
|
278 |
+
const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
|
279 |
+
|
280 |
+
const response = await fetch(apiEndpoint, {
|
281 |
+
method: 'POST',
|
282 |
+
headers: {
|
283 |
+
'Content-Type': 'application/json',
|
284 |
+
'Authorization': `Bearer ${apiKey}`
|
285 |
+
},
|
286 |
+
body: JSON.stringify({
|
287 |
+
model: modelSelect.value,
|
288 |
+
messages: [
|
289 |
+
{
|
290 |
+
role: "system",
|
291 |
+
content: "You are a helpful assistant."
|
292 |
+
},
|
293 |
+
{
|
294 |
+
role: "user",
|
295 |
+
content: "Hello, this is a test message."
|
296 |
+
}
|
297 |
+
],
|
298 |
+
max_tokens: 10
|
299 |
+
}),
|
300 |
+
signal: controller.signal
|
301 |
+
});
|
302 |
+
|
303 |
+
clearTimeout(timeoutId);
|
304 |
+
|
305 |
+
if (response.ok) {
|
306 |
+
const data = await response.json();
|
307 |
+
if (data.choices && data.choices[0]?.message?.content) {
|
308 |
+
showNotification('API connection successful!', 'success');
|
309 |
+
} else {
|
310 |
+
throw new Error('Invalid API response format');
|
311 |
+
}
|
312 |
+
} else {
|
313 |
+
const error = await response.json();
|
314 |
+
throw new Error(error.error?.message || 'Unknown error');
|
315 |
+
}
|
316 |
+
} catch (error) {
|
317 |
+
if (error.name === 'AbortError') {
|
318 |
+
showNotification('API request timed out. Please check your connection.', 'error');
|
319 |
+
} else {
|
320 |
+
showNotification(`Connection error: ${error.message}`, 'error');
|
321 |
+
}
|
322 |
+
}
|
323 |
+
}
|
324 |
+
|
325 |
+
// Apply template with validation
|
326 |
+
function applyTemplate() {
|
327 |
+
const template = templateSelect.value;
|
328 |
+
if (!template) {
|
329 |
+
showNotification('Please select a template.', 'warning');
|
330 |
+
return;
|
331 |
+
}
|
332 |
+
|
333 |
+
if (hasUnsavedChanges()) {
|
334 |
+
if (!confirm('Applying a template will overwrite your current changes. Continue?')) {
|
335 |
+
return;
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
const selectedTemplate = templates[template];
|
340 |
+
if (!selectedTemplate) {
|
341 |
+
showNotification('Template not found.', 'error');
|
342 |
+
return;
|
343 |
+
}
|
344 |
+
|
345 |
+
try {
|
346 |
+
chatbotInstructions.value = selectedTemplate.instructions;
|
347 |
+
|
348 |
+
// Set tone
|
349 |
+
toneOptions.forEach(option => {
|
350 |
+
if (option.value === selectedTemplate.tone) {
|
351 |
+
option.checked = true;
|
352 |
+
}
|
353 |
+
});
|
354 |
+
|
355 |
+
showNotification(`Applied ${templateSelect.options[templateSelect.selectedIndex].text} template.`, 'success');
|
356 |
+
} catch (error) {
|
357 |
+
console.error('Template Error:', error);
|
358 |
+
showNotification('Failed to apply template: ' + error.message, 'error');
|
359 |
+
}
|
360 |
+
}
|
361 |
+
|
362 |
+
// Generate preview with error handling
|
363 |
+
async function generatePreview() {
|
364 |
+
try {
|
365 |
+
// Collect current settings
|
366 |
+
let instructions = chatbotInstructions.value;
|
367 |
+
let tone = '';
|
368 |
+
|
369 |
+
toneOptions.forEach(option => {
|
370 |
+
if (option.checked) {
|
371 |
+
tone = option.value;
|
372 |
+
}
|
373 |
+
});
|
374 |
+
|
375 |
+
// Add tone customization to instructions
|
376 |
+
let toneInstruction = '';
|
377 |
+
switch (tone) {
|
378 |
+
case 'friendly':
|
379 |
+
toneInstruction = 'Be warm, approachable, and conversational in your responses.';
|
380 |
+
break;
|
381 |
+
case 'professional':
|
382 |
+
toneInstruction = 'Maintain a professional, business-like tone while being helpful.';
|
383 |
+
break;
|
384 |
+
case 'casual':
|
385 |
+
toneInstruction = 'Keep your tone relaxed and casual, like chatting with a friend.';
|
386 |
+
break;
|
387 |
+
case 'formal':
|
388 |
+
toneInstruction = 'Use a formal, academic tone with precise language.';
|
389 |
+
break;
|
390 |
+
default:
|
391 |
+
throw new Error('Invalid tone selected');
|
392 |
+
}
|
393 |
+
|
394 |
+
// Response style
|
395 |
+
let styleInstruction = '';
|
396 |
+
switch (responseStyle.value) {
|
397 |
+
case 'concise':
|
398 |
+
styleInstruction = 'Keep your responses brief and to the point.';
|
399 |
+
break;
|
400 |
+
case 'detailed':
|
401 |
+
styleInstruction = 'Provide detailed, comprehensive responses.';
|
402 |
+
break;
|
403 |
+
case 'balanced':
|
404 |
+
styleInstruction = 'Balance brevity with thoroughness in your responses.';
|
405 |
+
break;
|
406 |
+
default:
|
407 |
+
throw new Error('Invalid response style selected');
|
408 |
+
}
|
409 |
+
|
410 |
+
// Custom tone instructions
|
411 |
+
let customInstructions = customToneInstructions.value;
|
412 |
+
|
413 |
+
// Combine all instructions
|
414 |
+
let fullInstructions = `${instructions}\n\n${toneInstruction}\n${styleInstruction}`;
|
415 |
+
if (customInstructions) {
|
416 |
+
fullInstructions += '\n\n' + customInstructions;
|
417 |
+
}
|
418 |
+
|
419 |
+
// Generate preview
|
420 |
+
let previewText = generatePreviewText(tone, responseStyle.value);
|
421 |
+
previewResponse.textContent = previewText;
|
422 |
+
showNotification('Preview generated.', 'info');
|
423 |
+
|
424 |
+
} catch (error) {
|
425 |
+
console.error('Preview Error:', error);
|
426 |
+
showNotification('Failed to generate preview: ' + error.message, 'error');
|
427 |
+
}
|
428 |
+
}
|
429 |
+
|
430 |
+
// Generate preview text
|
431 |
+
function generatePreviewText(tone, style) {
|
432 |
+
let baseText = '';
|
433 |
+
|
434 |
+
switch (tone) {
|
435 |
+
case 'friendly':
|
436 |
+
baseText = 'Hi there! I\'m DeepSeek, your friendly AI assistant. I\'m here to help you with any questions or tasks you have today. Just let me know what you need assistance with, and I\'ll do my best to help you out!';
|
437 |
+
break;
|
438 |
+
case 'professional':
|
439 |
+
baseText = 'Welcome. I\'m DeepSeek, your AI assistant. I\'m ready to provide you with accurate information and efficient assistance with your queries. Please let me know how I can be of service to you today.';
|
440 |
+
break;
|
441 |
+
case 'casual':
|
442 |
+
baseText = 'Hey! DeepSeek here. What\'s up? Got anything you want to chat about or need help with? I\'m all ears and ready to jump in whenever you are!';
|
443 |
+
break;
|
444 |
+
case 'formal':
|
445 |
+
baseText = 'Greetings. I am DeepSeek, an artificial intelligence assistant designed to provide you with information and assistance. I would be pleased to address any inquiries or requests you may have at this time.';
|
446 |
+
break;
|
447 |
+
default:
|
448 |
+
baseText = 'Hello, I\'m DeepSeek. How can I help you today?';
|
449 |
+
}
|
450 |
+
|
451 |
+
switch (style) {
|
452 |
+
case 'concise':
|
453 |
+
return baseText.split('.')[0] + '.';
|
454 |
+
case 'detailed':
|
455 |
+
return baseText + ' I can help with information retrieval, creative content, problem-solving, and many other tasks. My knowledge base includes a wide range of topics, though I have some limitations on real-time data and specialized expertise. Feel free to be specific with your requests so I can provide the most helpful response.';
|
456 |
+
case 'balanced':
|
457 |
+
default:
|
458 |
+
return baseText;
|
459 |
+
}
|
460 |
+
}
|
461 |
+
|
462 |
+
// Show notification with queue
|
463 |
+
const notificationQueue = [];
|
464 |
+
let isShowingNotification = false;
|
465 |
+
|
466 |
+
function showNotification(message, type = 'info') {
|
467 |
+
notificationQueue.push({ message, type });
|
468 |
+
if (!isShowingNotification) {
|
469 |
+
showNextNotification();
|
470 |
+
}
|
471 |
+
}
|
472 |
+
|
473 |
+
async function showNextNotification() {
|
474 |
+
if (notificationQueue.length === 0) {
|
475 |
+
isShowingNotification = false;
|
476 |
+
return;
|
477 |
+
}
|
478 |
+
|
479 |
+
isShowingNotification = true;
|
480 |
+
const { message, type } = notificationQueue.shift();
|
481 |
+
|
482 |
+
const notification = document.createElement('div');
|
483 |
+
notification.classList.add('notification', `notification-${type}`);
|
484 |
+
notification.textContent = message;
|
485 |
+
|
486 |
+
document.body.appendChild(notification);
|
487 |
+
|
488 |
+
await new Promise(resolve => setTimeout(resolve, 5000));
|
489 |
+
|
490 |
+
notification.classList.add('notification-hide');
|
491 |
+
await new Promise(resolve => setTimeout(resolve, 500));
|
492 |
+
|
493 |
+
notification.remove();
|
494 |
+
showNextNotification();
|
495 |
+
}
|
496 |
+
|
497 |
+
// Initialize
|
498 |
+
document.addEventListener('DOMContentLoaded', () => {
|
499 |
+
setupChangeTracking();
|
500 |
+
|
501 |
+
// Add event listeners
|
502 |
+
loginBtn.addEventListener('click', handleAsyncError(handleLogin));
|
503 |
+
logoutBtn.addEventListener('click', handleLogout);
|
504 |
+
saveBtn.addEventListener('click', handleAsyncError(saveConfig));
|
505 |
+
testApiBtn.addEventListener('click', handleAsyncError(testApiConnection));
|
506 |
+
applyTemplateBtn.addEventListener('click', handleAsyncError(applyTemplate));
|
507 |
+
generatePreviewBtn.addEventListener('click', handleAsyncError(generatePreview));
|
508 |
+
|
509 |
+
// Window beforeunload handler
|
510 |
+
window.addEventListener('beforeunload', (e) => {
|
511 |
+
if (hasUnsavedChanges()) {
|
512 |
+
e.preventDefault();
|
513 |
+
e.returnValue = '';
|
514 |
+
}
|
515 |
+
});
|
516 |
+
});
|
contact.html
ADDED
@@ -0,0 +1,130 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<meta name="description" content="Contact DeepSeek - Get in touch with our team">
|
7 |
+
<meta name="theme-color" content="#4285f4">
|
8 |
+
<title>Contact Us - DeepSeek</title>
|
9 |
+
<link rel="stylesheet" href="css/style.css">
|
10 |
+
<link rel="stylesheet" href="css/pages.css">
|
11 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
12 |
+
</head>
|
13 |
+
<body>
|
14 |
+
<header class="page-header">
|
15 |
+
<nav class="main-nav">
|
16 |
+
<div class="logo">
|
17 |
+
<img src="images/logo.png" alt="DeepSeek Logo" width="40" height="40">
|
18 |
+
<span>DeepSeek</span>
|
19 |
+
</div>
|
20 |
+
<ul class="nav-links">
|
21 |
+
<li><a href="index.html">Home</a></li>
|
22 |
+
<li><a href="about.html">About</a></li>
|
23 |
+
<li><a href="contact.html" class="active">Contact</a></li>
|
24 |
+
<li><a href="follow.html">Follow Us</a></li>
|
25 |
+
</ul>
|
26 |
+
</nav>
|
27 |
+
</header>
|
28 |
+
|
29 |
+
<main class="page-content">
|
30 |
+
<section class="contact-section">
|
31 |
+
<h1>Contact Us</h1>
|
32 |
+
<p class="section-desc">Have questions? We'd love to hear from you. Send us a message and we'll respond as soon as possible.</p>
|
33 |
+
|
34 |
+
<div class="contact-container">
|
35 |
+
<div class="contact-info">
|
36 |
+
<h2>Get in Touch</h2>
|
37 |
+
<div class="info-item">
|
38 |
+
<i class="fas fa-map-marker-alt"></i>
|
39 |
+
<div>
|
40 |
+
<h3>Address</h3>
|
41 |
+
<p>123 AI Street, Tech Valley<br>Silicon City, 12345</p>
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
<div class="info-item">
|
45 |
+
<i class="fas fa-phone"></i>
|
46 |
+
<div>
|
47 |
+
<h3>Phone</h3>
|
48 |
+
<p>+1 (555) 123-4567</p>
|
49 |
+
</div>
|
50 |
+
</div>
|
51 |
+
<div class="info-item">
|
52 |
+
<i class="fas fa-envelope"></i>
|
53 |
+
<div>
|
54 |
+
<h3>Email</h3>
|
55 |
+
<p>[email protected]</p>
|
56 |
+
</div>
|
57 |
+
</div>
|
58 |
+
<div class="info-item">
|
59 |
+
<i class="fas fa-clock"></i>
|
60 |
+
<div>
|
61 |
+
<h3>Working Hours</h3>
|
62 |
+
<p>Monday - Friday: 9:00 AM - 6:00 PM<br>Weekend: Closed</p>
|
63 |
+
</div>
|
64 |
+
</div>
|
65 |
+
</div>
|
66 |
+
|
67 |
+
<form class="contact-form" id="contactForm">
|
68 |
+
<h2>Send Message</h2>
|
69 |
+
<div class="form-group">
|
70 |
+
<label for="name">Your Name</label>
|
71 |
+
<input type="text" id="name" name="name" required>
|
72 |
+
</div>
|
73 |
+
<div class="form-group">
|
74 |
+
<label for="email">Your Email</label>
|
75 |
+
<input type="email" id="email" name="email" required>
|
76 |
+
</div>
|
77 |
+
<div class="form-group">
|
78 |
+
<label for="subject">Subject</label>
|
79 |
+
<input type="text" id="subject" name="subject" required>
|
80 |
+
</div>
|
81 |
+
<div class="form-group">
|
82 |
+
<label for="message">Message</label>
|
83 |
+
<textarea id="message" name="message" rows="5" required></textarea>
|
84 |
+
</div>
|
85 |
+
<button type="submit" class="submit-btn">Send Message</button>
|
86 |
+
</form>
|
87 |
+
</div>
|
88 |
+
</section>
|
89 |
+
</main>
|
90 |
+
|
91 |
+
<footer class="page-footer">
|
92 |
+
<div class="footer-content">
|
93 |
+
<div class="footer-section">
|
94 |
+
<h3>DeepSeek</h3>
|
95 |
+
<p>Advancing AI technology to help people communicate and solve problems more effectively.</p>
|
96 |
+
</div>
|
97 |
+
<div class="footer-section">
|
98 |
+
<h3>Quick Links</h3>
|
99 |
+
<ul>
|
100 |
+
<li><a href="index.html">Home</a></li>
|
101 |
+
<li><a href="about.html">About</a></li>
|
102 |
+
<li><a href="contact.html">Contact</a></li>
|
103 |
+
<li><a href="follow.html">Follow Us</a></li>
|
104 |
+
</ul>
|
105 |
+
</div>
|
106 |
+
<div class="footer-section">
|
107 |
+
<h3>Connect With Us</h3>
|
108 |
+
<div class="social-links">
|
109 |
+
<a href="#" aria-label="Facebook"><i class="fab fa-facebook"></i></a>
|
110 |
+
<a href="#" aria-label="Twitter"><i class="fab fa-twitter"></i></a>
|
111 |
+
<a href="#" aria-label="LinkedIn"><i class="fab fa-linkedin"></i></a>
|
112 |
+
<a href="#" aria-label="Instagram"><i class="fab fa-instagram"></i></a>
|
113 |
+
</div>
|
114 |
+
</div>
|
115 |
+
</div>
|
116 |
+
<div class="footer-bottom">
|
117 |
+
<p>© 2024 DeepSeek. All rights reserved.</p>
|
118 |
+
</div>
|
119 |
+
</footer>
|
120 |
+
|
121 |
+
<script>
|
122 |
+
document.getElementById('contactForm').addEventListener('submit', function(e) {
|
123 |
+
e.preventDefault();
|
124 |
+
// Add your form submission logic here
|
125 |
+
alert('Thank you for your message. We will get back to you soon!');
|
126 |
+
this.reset();
|
127 |
+
});
|
128 |
+
</script>
|
129 |
+
</body>
|
130 |
+
</html>
|
css/admin.css
ADDED
@@ -0,0 +1,489 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Admin Panel Theme Variables */
|
2 |
+
:root {
|
3 |
+
--admin-bg: #f4f6f8;
|
4 |
+
--sidebar-bg: #fff;
|
5 |
+
--card-bg: #fff;
|
6 |
+
--text-primary: #2c3e50;
|
7 |
+
--text-secondary: #7f8c8d;
|
8 |
+
--accent-color: #4285f4;
|
9 |
+
--border-color: #e1e4e8;
|
10 |
+
--hover-bg: #f8f9fa;
|
11 |
+
--shadow-sm: 0 2px 4px rgba(0,0,0,0.05);
|
12 |
+
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
|
13 |
+
--success-color: #27ae60;
|
14 |
+
--warning-color: #f39c12;
|
15 |
+
--danger-color: #e74c3c;
|
16 |
+
}
|
17 |
+
|
18 |
+
/* Dark Theme */
|
19 |
+
[data-theme="dark"] {
|
20 |
+
--admin-bg: #1a1a1a;
|
21 |
+
--sidebar-bg: #2d2d2d;
|
22 |
+
--card-bg: #2d2d2d;
|
23 |
+
--text-primary: #fff;
|
24 |
+
--text-secondary: #bdc3c7;
|
25 |
+
--border-color: #404040;
|
26 |
+
--hover-bg: #383838;
|
27 |
+
}
|
28 |
+
|
29 |
+
/* Reset and Base Styles */
|
30 |
+
* {
|
31 |
+
margin: 0;
|
32 |
+
padding: 0;
|
33 |
+
box-sizing: border-box;
|
34 |
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
35 |
+
}
|
36 |
+
|
37 |
+
body {
|
38 |
+
background-color: var(--admin-bg);
|
39 |
+
color: var(--text-primary);
|
40 |
+
line-height: 1.6;
|
41 |
+
}
|
42 |
+
|
43 |
+
/* Admin Container */
|
44 |
+
.admin-container {
|
45 |
+
display: flex;
|
46 |
+
min-height: 100vh;
|
47 |
+
}
|
48 |
+
|
49 |
+
/* Sidebar */
|
50 |
+
.sidebar {
|
51 |
+
width: 260px;
|
52 |
+
background-color: var(--sidebar-bg);
|
53 |
+
border-right: 1px solid var(--border-color);
|
54 |
+
display: flex;
|
55 |
+
flex-direction: column;
|
56 |
+
position: fixed;
|
57 |
+
height: 100vh;
|
58 |
+
box-shadow: var(--shadow-sm);
|
59 |
+
}
|
60 |
+
|
61 |
+
.sidebar-header {
|
62 |
+
padding: 20px;
|
63 |
+
border-bottom: 1px solid var(--border-color);
|
64 |
+
display: flex;
|
65 |
+
align-items: center;
|
66 |
+
gap: 12px;
|
67 |
+
}
|
68 |
+
|
69 |
+
.admin-logo {
|
70 |
+
height: 32px;
|
71 |
+
width: auto;
|
72 |
+
}
|
73 |
+
|
74 |
+
.sidebar-header h2 {
|
75 |
+
font-size: 18px;
|
76 |
+
font-weight: 600;
|
77 |
+
}
|
78 |
+
|
79 |
+
.sidebar-nav {
|
80 |
+
padding: 20px 0;
|
81 |
+
flex-grow: 1;
|
82 |
+
}
|
83 |
+
|
84 |
+
.nav-item {
|
85 |
+
display: flex;
|
86 |
+
align-items: center;
|
87 |
+
padding: 12px 20px;
|
88 |
+
color: var(--text-secondary);
|
89 |
+
text-decoration: none;
|
90 |
+
transition: all 0.2s ease;
|
91 |
+
gap: 12px;
|
92 |
+
}
|
93 |
+
|
94 |
+
.nav-item:hover {
|
95 |
+
background-color: var(--hover-bg);
|
96 |
+
color: var(--accent-color);
|
97 |
+
}
|
98 |
+
|
99 |
+
.nav-item.active {
|
100 |
+
background-color: rgba(66, 133, 244, 0.1);
|
101 |
+
color: var(--accent-color);
|
102 |
+
border-right: 3px solid var(--accent-color);
|
103 |
+
}
|
104 |
+
|
105 |
+
.nav-item i {
|
106 |
+
width: 20px;
|
107 |
+
text-align: center;
|
108 |
+
}
|
109 |
+
|
110 |
+
.sidebar-footer {
|
111 |
+
padding: 20px;
|
112 |
+
border-top: 1px solid var(--border-color);
|
113 |
+
}
|
114 |
+
|
115 |
+
.logout-btn {
|
116 |
+
display: flex;
|
117 |
+
align-items: center;
|
118 |
+
gap: 12px;
|
119 |
+
width: 100%;
|
120 |
+
padding: 12px;
|
121 |
+
border: none;
|
122 |
+
background: none;
|
123 |
+
color: var(--danger-color);
|
124 |
+
cursor: pointer;
|
125 |
+
transition: all 0.2s ease;
|
126 |
+
border-radius: 6px;
|
127 |
+
}
|
128 |
+
|
129 |
+
.logout-btn:hover {
|
130 |
+
background-color: var(--hover-bg);
|
131 |
+
}
|
132 |
+
|
133 |
+
/* Main Content */
|
134 |
+
.main-content {
|
135 |
+
flex: 1;
|
136 |
+
margin-left: 260px;
|
137 |
+
padding: 20px;
|
138 |
+
}
|
139 |
+
|
140 |
+
/* Top Bar */
|
141 |
+
.top-bar {
|
142 |
+
display: flex;
|
143 |
+
justify-content: space-between;
|
144 |
+
align-items: center;
|
145 |
+
padding: 20px;
|
146 |
+
background-color: var(--card-bg);
|
147 |
+
border-radius: 10px;
|
148 |
+
box-shadow: var(--shadow-sm);
|
149 |
+
margin-bottom: 24px;
|
150 |
+
}
|
151 |
+
|
152 |
+
.search-bar {
|
153 |
+
display: flex;
|
154 |
+
align-items: center;
|
155 |
+
gap: 12px;
|
156 |
+
background-color: var(--admin-bg);
|
157 |
+
padding: 8px 16px;
|
158 |
+
border-radius: 8px;
|
159 |
+
width: 300px;
|
160 |
+
}
|
161 |
+
|
162 |
+
.search-bar input {
|
163 |
+
border: none;
|
164 |
+
background: none;
|
165 |
+
outline: none;
|
166 |
+
color: var(--text-primary);
|
167 |
+
width: 100%;
|
168 |
+
}
|
169 |
+
|
170 |
+
.search-bar i {
|
171 |
+
color: var(--text-secondary);
|
172 |
+
}
|
173 |
+
|
174 |
+
.top-bar-actions {
|
175 |
+
display: flex;
|
176 |
+
align-items: center;
|
177 |
+
gap: 16px;
|
178 |
+
}
|
179 |
+
|
180 |
+
.theme-toggle {
|
181 |
+
background: none;
|
182 |
+
border: none;
|
183 |
+
color: var(--text-secondary);
|
184 |
+
cursor: pointer;
|
185 |
+
padding: 8px;
|
186 |
+
font-size: 20px;
|
187 |
+
transition: color 0.2s ease;
|
188 |
+
}
|
189 |
+
|
190 |
+
.theme-toggle:hover {
|
191 |
+
color: var(--text-primary);
|
192 |
+
}
|
193 |
+
|
194 |
+
.admin-profile {
|
195 |
+
display: flex;
|
196 |
+
align-items: center;
|
197 |
+
gap: 8px;
|
198 |
+
}
|
199 |
+
|
200 |
+
.admin-avatar {
|
201 |
+
width: 32px;
|
202 |
+
height: 32px;
|
203 |
+
border-radius: 50%;
|
204 |
+
}
|
205 |
+
|
206 |
+
/* Dashboard Stats */
|
207 |
+
.stats-grid {
|
208 |
+
display: grid;
|
209 |
+
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
210 |
+
gap: 24px;
|
211 |
+
margin-bottom: 24px;
|
212 |
+
}
|
213 |
+
|
214 |
+
.stat-card {
|
215 |
+
background-color: var(--card-bg);
|
216 |
+
padding: 24px;
|
217 |
+
border-radius: 10px;
|
218 |
+
box-shadow: var(--shadow-sm);
|
219 |
+
display: flex;
|
220 |
+
align-items: center;
|
221 |
+
gap: 20px;
|
222 |
+
}
|
223 |
+
|
224 |
+
.stat-icon {
|
225 |
+
width: 48px;
|
226 |
+
height: 48px;
|
227 |
+
border-radius: 12px;
|
228 |
+
background-color: rgba(66, 133, 244, 0.1);
|
229 |
+
color: var(--accent-color);
|
230 |
+
display: flex;
|
231 |
+
align-items: center;
|
232 |
+
justify-content: center;
|
233 |
+
font-size: 24px;
|
234 |
+
}
|
235 |
+
|
236 |
+
.stat-info h3 {
|
237 |
+
font-size: 14px;
|
238 |
+
color: var(--text-secondary);
|
239 |
+
margin-bottom: 4px;
|
240 |
+
}
|
241 |
+
|
242 |
+
.stat-info p {
|
243 |
+
font-size: 24px;
|
244 |
+
font-weight: 600;
|
245 |
+
color: var(--text-primary);
|
246 |
+
}
|
247 |
+
|
248 |
+
/* Charts Grid */
|
249 |
+
.charts-grid {
|
250 |
+
display: grid;
|
251 |
+
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
252 |
+
gap: 24px;
|
253 |
+
}
|
254 |
+
|
255 |
+
.chart-card {
|
256 |
+
background-color: var(--card-bg);
|
257 |
+
padding: 24px;
|
258 |
+
border-radius: 10px;
|
259 |
+
box-shadow: var(--shadow-sm);
|
260 |
+
}
|
261 |
+
|
262 |
+
.chart-card h3 {
|
263 |
+
margin-bottom: 20px;
|
264 |
+
color: var(--text-primary);
|
265 |
+
}
|
266 |
+
|
267 |
+
.chart-placeholder {
|
268 |
+
width: 100%;
|
269 |
+
height: 300px;
|
270 |
+
background-color: var(--hover-bg);
|
271 |
+
border-radius: 8px;
|
272 |
+
}
|
273 |
+
|
274 |
+
/* Settings */
|
275 |
+
.settings-grid {
|
276 |
+
display: grid;
|
277 |
+
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
|
278 |
+
gap: 24px;
|
279 |
+
}
|
280 |
+
|
281 |
+
.settings-card {
|
282 |
+
background-color: var(--card-bg);
|
283 |
+
padding: 24px;
|
284 |
+
border-radius: 10px;
|
285 |
+
box-shadow: var(--shadow-sm);
|
286 |
+
}
|
287 |
+
|
288 |
+
.settings-card h3 {
|
289 |
+
margin-bottom: 20px;
|
290 |
+
color: var(--text-primary);
|
291 |
+
}
|
292 |
+
|
293 |
+
.form-group {
|
294 |
+
margin-bottom: 20px;
|
295 |
+
}
|
296 |
+
|
297 |
+
.form-group label {
|
298 |
+
display: block;
|
299 |
+
margin-bottom: 8px;
|
300 |
+
color: var(--text-secondary);
|
301 |
+
}
|
302 |
+
|
303 |
+
.form-group input[type="text"],
|
304 |
+
.form-group input[type="password"],
|
305 |
+
.form-group input[type="url"],
|
306 |
+
.form-group input[type="number"] {
|
307 |
+
width: 100%;
|
308 |
+
padding: 10px;
|
309 |
+
border: 1px solid var(--border-color);
|
310 |
+
border-radius: 6px;
|
311 |
+
background-color: var(--admin-bg);
|
312 |
+
color: var(--text-primary);
|
313 |
+
}
|
314 |
+
|
315 |
+
.form-group input[type="range"] {
|
316 |
+
width: 100%;
|
317 |
+
margin-bottom: 8px;
|
318 |
+
}
|
319 |
+
|
320 |
+
.range-value {
|
321 |
+
color: var(--text-secondary);
|
322 |
+
font-size: 14px;
|
323 |
+
}
|
324 |
+
|
325 |
+
.btn-primary {
|
326 |
+
background-color: var(--accent-color);
|
327 |
+
color: white;
|
328 |
+
border: none;
|
329 |
+
padding: 12px 24px;
|
330 |
+
border-radius: 6px;
|
331 |
+
cursor: pointer;
|
332 |
+
transition: all 0.2s ease;
|
333 |
+
}
|
334 |
+
|
335 |
+
.btn-primary:hover {
|
336 |
+
opacity: 0.9;
|
337 |
+
}
|
338 |
+
|
339 |
+
/* Responsive Design */
|
340 |
+
@media (max-width: 768px) {
|
341 |
+
.sidebar {
|
342 |
+
width: 70px;
|
343 |
+
}
|
344 |
+
|
345 |
+
.sidebar-header h2,
|
346 |
+
.nav-item span,
|
347 |
+
.logout-btn span {
|
348 |
+
display: none;
|
349 |
+
}
|
350 |
+
|
351 |
+
.main-content {
|
352 |
+
margin-left: 70px;
|
353 |
+
}
|
354 |
+
|
355 |
+
.stats-grid {
|
356 |
+
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
357 |
+
}
|
358 |
+
|
359 |
+
.charts-grid,
|
360 |
+
.settings-grid {
|
361 |
+
grid-template-columns: 1fr;
|
362 |
+
}
|
363 |
+
}
|
364 |
+
|
365 |
+
/* Input with copy button */
|
366 |
+
.input-with-copy {
|
367 |
+
position: relative;
|
368 |
+
display: flex;
|
369 |
+
align-items: center;
|
370 |
+
}
|
371 |
+
|
372 |
+
.copy-btn {
|
373 |
+
position: absolute;
|
374 |
+
right: 12px;
|
375 |
+
background: none;
|
376 |
+
border: none;
|
377 |
+
color: var(--text-secondary);
|
378 |
+
cursor: pointer;
|
379 |
+
padding: 4px 8px;
|
380 |
+
transition: color 0.2s ease;
|
381 |
+
}
|
382 |
+
|
383 |
+
.copy-btn:hover {
|
384 |
+
color: var(--text-primary);
|
385 |
+
}
|
386 |
+
|
387 |
+
/* Select Input */
|
388 |
+
select {
|
389 |
+
width: 100%;
|
390 |
+
padding: 10px;
|
391 |
+
border: 1px solid var(--border-color);
|
392 |
+
border-radius: 6px;
|
393 |
+
background-color: var(--admin-bg);
|
394 |
+
color: var(--text-primary);
|
395 |
+
font-size: 14px;
|
396 |
+
cursor: pointer;
|
397 |
+
appearance: none;
|
398 |
+
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
|
399 |
+
background-repeat: no-repeat;
|
400 |
+
background-position: right 10px center;
|
401 |
+
background-size: 16px;
|
402 |
+
}
|
403 |
+
|
404 |
+
select:focus {
|
405 |
+
outline: none;
|
406 |
+
border-color: var(--accent-color);
|
407 |
+
box-shadow: 0 0 0 3px rgba(66, 133, 244, 0.1);
|
408 |
+
}
|
409 |
+
|
410 |
+
/* Range with value */
|
411 |
+
.range-with-value {
|
412 |
+
display: flex;
|
413 |
+
align-items: center;
|
414 |
+
gap: 12px;
|
415 |
+
}
|
416 |
+
|
417 |
+
.range-with-value input[type="range"] {
|
418 |
+
flex: 1;
|
419 |
+
}
|
420 |
+
|
421 |
+
.range-value {
|
422 |
+
min-width: 40px;
|
423 |
+
text-align: center;
|
424 |
+
padding: 2px 6px;
|
425 |
+
background-color: var(--hover-bg);
|
426 |
+
border-radius: 4px;
|
427 |
+
font-size: 14px;
|
428 |
+
}
|
429 |
+
|
430 |
+
/* Help text */
|
431 |
+
.help-text {
|
432 |
+
display: block;
|
433 |
+
color: var(--text-secondary);
|
434 |
+
font-size: 12px;
|
435 |
+
margin-top: 4px;
|
436 |
+
}
|
437 |
+
|
438 |
+
/* Checkbox label */
|
439 |
+
.checkbox-label {
|
440 |
+
display: flex;
|
441 |
+
align-items: center;
|
442 |
+
gap: 8px;
|
443 |
+
cursor: pointer;
|
444 |
+
}
|
445 |
+
|
446 |
+
.checkbox-label input[type="checkbox"] {
|
447 |
+
width: 16px;
|
448 |
+
height: 16px;
|
449 |
+
margin: 0;
|
450 |
+
}
|
451 |
+
|
452 |
+
/* Buttons */
|
453 |
+
.btn-secondary {
|
454 |
+
background-color: var(--hover-bg);
|
455 |
+
color: var(--text-primary);
|
456 |
+
border: 1px solid var(--border-color);
|
457 |
+
padding: 12px 24px;
|
458 |
+
border-radius: 6px;
|
459 |
+
cursor: pointer;
|
460 |
+
transition: all 0.2s ease;
|
461 |
+
display: inline-flex;
|
462 |
+
align-items: center;
|
463 |
+
gap: 8px;
|
464 |
+
margin-top: 12px;
|
465 |
+
}
|
466 |
+
|
467 |
+
.btn-secondary:hover {
|
468 |
+
background-color: var(--border-color);
|
469 |
+
}
|
470 |
+
|
471 |
+
.btn-secondary i {
|
472 |
+
font-size: 14px;
|
473 |
+
}
|
474 |
+
|
475 |
+
/* Form layout */
|
476 |
+
#modelSettingsForm {
|
477 |
+
display: flex;
|
478 |
+
flex-direction: column;
|
479 |
+
gap: 20px;
|
480 |
+
}
|
481 |
+
|
482 |
+
#modelSettingsForm .btn-primary {
|
483 |
+
margin-top: 12px;
|
484 |
+
}
|
485 |
+
|
486 |
+
/* Test Model Button */
|
487 |
+
#testModel {
|
488 |
+
width: 100%;
|
489 |
+
}
|
css/login.css
ADDED
@@ -0,0 +1,197 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Login Page Theme Variables */
|
2 |
+
:root {
|
3 |
+
--bg-color: #f4f6f8;
|
4 |
+
--card-bg: #fff;
|
5 |
+
--text-primary: #2c3e50;
|
6 |
+
--text-secondary: #7f8c8d;
|
7 |
+
--accent-color: #4285f4;
|
8 |
+
--border-color: #e1e4e8;
|
9 |
+
--error-color: #e74c3c;
|
10 |
+
--success-color: #27ae60;
|
11 |
+
--shadow-sm: 0 2px 4px rgba(0,0,0,0.05);
|
12 |
+
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
|
13 |
+
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
|
14 |
+
}
|
15 |
+
|
16 |
+
/* Reset and Base Styles */
|
17 |
+
* {
|
18 |
+
margin: 0;
|
19 |
+
padding: 0;
|
20 |
+
box-sizing: border-box;
|
21 |
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
22 |
+
}
|
23 |
+
|
24 |
+
body {
|
25 |
+
background-color: var(--bg-color);
|
26 |
+
min-height: 100vh;
|
27 |
+
display: flex;
|
28 |
+
align-items: center;
|
29 |
+
justify-content: center;
|
30 |
+
padding: 20px;
|
31 |
+
}
|
32 |
+
|
33 |
+
/* Login Container */
|
34 |
+
.login-container {
|
35 |
+
width: 100%;
|
36 |
+
max-width: 400px;
|
37 |
+
}
|
38 |
+
|
39 |
+
.login-card {
|
40 |
+
background-color: var(--card-bg);
|
41 |
+
border-radius: 12px;
|
42 |
+
box-shadow: var(--shadow-lg);
|
43 |
+
padding: 32px;
|
44 |
+
}
|
45 |
+
|
46 |
+
/* Login Header */
|
47 |
+
.login-header {
|
48 |
+
text-align: center;
|
49 |
+
margin-bottom: 32px;
|
50 |
+
}
|
51 |
+
|
52 |
+
.login-logo {
|
53 |
+
width: 120px;
|
54 |
+
height: auto;
|
55 |
+
margin-bottom: 16px;
|
56 |
+
}
|
57 |
+
|
58 |
+
.login-header h1 {
|
59 |
+
color: var(--text-primary);
|
60 |
+
font-size: 24px;
|
61 |
+
font-weight: 600;
|
62 |
+
}
|
63 |
+
|
64 |
+
/* Login Form */
|
65 |
+
.login-form {
|
66 |
+
margin-bottom: 24px;
|
67 |
+
}
|
68 |
+
|
69 |
+
.form-group {
|
70 |
+
margin-bottom: 20px;
|
71 |
+
}
|
72 |
+
|
73 |
+
.form-group label {
|
74 |
+
display: block;
|
75 |
+
color: var(--text-secondary);
|
76 |
+
margin-bottom: 8px;
|
77 |
+
font-size: 14px;
|
78 |
+
}
|
79 |
+
|
80 |
+
.form-group label i {
|
81 |
+
margin-right: 8px;
|
82 |
+
color: var(--accent-color);
|
83 |
+
}
|
84 |
+
|
85 |
+
.form-group input {
|
86 |
+
width: 100%;
|
87 |
+
padding: 12px;
|
88 |
+
border: 1px solid var(--border-color);
|
89 |
+
border-radius: 6px;
|
90 |
+
font-size: 16px;
|
91 |
+
transition: all 0.2s ease;
|
92 |
+
}
|
93 |
+
|
94 |
+
.form-group input:focus {
|
95 |
+
outline: none;
|
96 |
+
border-color: var(--accent-color);
|
97 |
+
box-shadow: 0 0 0 3px rgba(66, 133, 244, 0.1);
|
98 |
+
}
|
99 |
+
|
100 |
+
/* Password Input Group */
|
101 |
+
.password-input {
|
102 |
+
position: relative;
|
103 |
+
}
|
104 |
+
|
105 |
+
.toggle-password {
|
106 |
+
position: absolute;
|
107 |
+
right: 12px;
|
108 |
+
top: 50%;
|
109 |
+
transform: translateY(-50%);
|
110 |
+
background: none;
|
111 |
+
border: none;
|
112 |
+
color: var(--text-secondary);
|
113 |
+
cursor: pointer;
|
114 |
+
padding: 4px;
|
115 |
+
}
|
116 |
+
|
117 |
+
.toggle-password:hover {
|
118 |
+
color: var(--text-primary);
|
119 |
+
}
|
120 |
+
|
121 |
+
/* Error Message */
|
122 |
+
.error-message {
|
123 |
+
color: var(--error-color);
|
124 |
+
font-size: 14px;
|
125 |
+
margin-bottom: 16px;
|
126 |
+
min-height: 20px;
|
127 |
+
}
|
128 |
+
|
129 |
+
/* Login Button */
|
130 |
+
.login-btn {
|
131 |
+
width: 100%;
|
132 |
+
padding: 12px;
|
133 |
+
background-color: var(--accent-color);
|
134 |
+
color: white;
|
135 |
+
border: none;
|
136 |
+
border-radius: 6px;
|
137 |
+
font-size: 16px;
|
138 |
+
font-weight: 500;
|
139 |
+
cursor: pointer;
|
140 |
+
display: flex;
|
141 |
+
align-items: center;
|
142 |
+
justify-content: center;
|
143 |
+
gap: 8px;
|
144 |
+
transition: all 0.2s ease;
|
145 |
+
}
|
146 |
+
|
147 |
+
.login-btn:hover {
|
148 |
+
opacity: 0.9;
|
149 |
+
transform: translateY(-1px);
|
150 |
+
}
|
151 |
+
|
152 |
+
.login-btn:active {
|
153 |
+
transform: translateY(0);
|
154 |
+
}
|
155 |
+
|
156 |
+
/* Login Footer */
|
157 |
+
.login-footer {
|
158 |
+
text-align: center;
|
159 |
+
margin-top: 24px;
|
160 |
+
padding-top: 24px;
|
161 |
+
border-top: 1px solid var(--border-color);
|
162 |
+
}
|
163 |
+
|
164 |
+
.login-footer p {
|
165 |
+
color: var(--text-secondary);
|
166 |
+
font-size: 14px;
|
167 |
+
margin-bottom: 12px;
|
168 |
+
}
|
169 |
+
|
170 |
+
.back-link {
|
171 |
+
color: var(--accent-color);
|
172 |
+
text-decoration: none;
|
173 |
+
font-size: 14px;
|
174 |
+
display: inline-flex;
|
175 |
+
align-items: center;
|
176 |
+
gap: 4px;
|
177 |
+
transition: color 0.2s ease;
|
178 |
+
}
|
179 |
+
|
180 |
+
.back-link:hover {
|
181 |
+
color: var(--text-primary);
|
182 |
+
}
|
183 |
+
|
184 |
+
/* Responsive Design */
|
185 |
+
@media (max-width: 480px) {
|
186 |
+
.login-card {
|
187 |
+
padding: 24px;
|
188 |
+
}
|
189 |
+
|
190 |
+
.login-logo {
|
191 |
+
width: 100px;
|
192 |
+
}
|
193 |
+
|
194 |
+
.login-header h1 {
|
195 |
+
font-size: 20px;
|
196 |
+
}
|
197 |
+
}
|
css/pages.css
ADDED
@@ -0,0 +1,516 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Common Styles */
|
2 |
+
:root {
|
3 |
+
--primary-color: #4285f4;
|
4 |
+
--secondary-color: #34a853;
|
5 |
+
--accent-color: #ea4335;
|
6 |
+
--text-color: #333;
|
7 |
+
--light-gray: #f5f5f5;
|
8 |
+
--dark-gray: #666;
|
9 |
+
--white: #fff;
|
10 |
+
--shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
11 |
+
--transition: all 0.3s ease;
|
12 |
+
}
|
13 |
+
|
14 |
+
.page-header {
|
15 |
+
background: var(--white);
|
16 |
+
box-shadow: var(--shadow);
|
17 |
+
position: fixed;
|
18 |
+
width: 100%;
|
19 |
+
top: 0;
|
20 |
+
z-index: 1000;
|
21 |
+
}
|
22 |
+
|
23 |
+
.main-nav {
|
24 |
+
display: flex;
|
25 |
+
justify-content: space-between;
|
26 |
+
align-items: center;
|
27 |
+
padding: 1rem 2rem;
|
28 |
+
max-width: 1200px;
|
29 |
+
margin: 0 auto;
|
30 |
+
}
|
31 |
+
|
32 |
+
.logo {
|
33 |
+
display: flex;
|
34 |
+
align-items: center;
|
35 |
+
gap: 0.5rem;
|
36 |
+
font-size: 1.5rem;
|
37 |
+
font-weight: bold;
|
38 |
+
color: var(--primary-color);
|
39 |
+
}
|
40 |
+
|
41 |
+
.nav-links {
|
42 |
+
display: flex;
|
43 |
+
gap: 2rem;
|
44 |
+
list-style: none;
|
45 |
+
}
|
46 |
+
|
47 |
+
.nav-links a {
|
48 |
+
color: var(--text-color);
|
49 |
+
text-decoration: none;
|
50 |
+
font-weight: 500;
|
51 |
+
transition: var(--transition);
|
52 |
+
}
|
53 |
+
|
54 |
+
.nav-links a:hover,
|
55 |
+
.nav-links a.active {
|
56 |
+
color: var(--primary-color);
|
57 |
+
}
|
58 |
+
|
59 |
+
.page-content {
|
60 |
+
padding-top: 80px;
|
61 |
+
min-height: calc(100vh - 300px);
|
62 |
+
}
|
63 |
+
|
64 |
+
.hero-section {
|
65 |
+
text-align: center;
|
66 |
+
padding: 4rem 2rem;
|
67 |
+
background: linear-gradient(to right, #4285f4, #34a853);
|
68 |
+
color: var(--white);
|
69 |
+
}
|
70 |
+
|
71 |
+
.hero-section h1 {
|
72 |
+
font-size: 2.5rem;
|
73 |
+
margin-bottom: 1rem;
|
74 |
+
}
|
75 |
+
|
76 |
+
.section-desc {
|
77 |
+
font-size: 1.2rem;
|
78 |
+
max-width: 600px;
|
79 |
+
margin: 0 auto;
|
80 |
+
opacity: 0.9;
|
81 |
+
}
|
82 |
+
|
83 |
+
/* About Page Styles */
|
84 |
+
.about-section {
|
85 |
+
max-width: 1200px;
|
86 |
+
margin: 0 auto;
|
87 |
+
padding: 2rem;
|
88 |
+
}
|
89 |
+
|
90 |
+
.mission-vision {
|
91 |
+
display: grid;
|
92 |
+
grid-template-columns: repeat(2, 1fr);
|
93 |
+
gap: 2rem;
|
94 |
+
margin-bottom: 4rem;
|
95 |
+
}
|
96 |
+
|
97 |
+
.mission, .vision {
|
98 |
+
padding: 2rem;
|
99 |
+
background: var(--white);
|
100 |
+
border-radius: 8px;
|
101 |
+
box-shadow: var(--shadow);
|
102 |
+
}
|
103 |
+
|
104 |
+
.values-grid {
|
105 |
+
display: grid;
|
106 |
+
grid-template-columns: repeat(4, 1fr);
|
107 |
+
gap: 2rem;
|
108 |
+
margin-bottom: 4rem;
|
109 |
+
}
|
110 |
+
|
111 |
+
.value-item {
|
112 |
+
text-align: center;
|
113 |
+
padding: 2rem;
|
114 |
+
background: var(--white);
|
115 |
+
border-radius: 8px;
|
116 |
+
box-shadow: var(--shadow);
|
117 |
+
}
|
118 |
+
|
119 |
+
.value-item i {
|
120 |
+
font-size: 2rem;
|
121 |
+
color: var(--primary-color);
|
122 |
+
margin-bottom: 1rem;
|
123 |
+
}
|
124 |
+
|
125 |
+
.team-grid {
|
126 |
+
display: grid;
|
127 |
+
grid-template-columns: repeat(3, 1fr);
|
128 |
+
gap: 2rem;
|
129 |
+
margin-bottom: 4rem;
|
130 |
+
}
|
131 |
+
|
132 |
+
.team-member {
|
133 |
+
text-align: center;
|
134 |
+
padding: 2rem;
|
135 |
+
background: var(--white);
|
136 |
+
border-radius: 8px;
|
137 |
+
box-shadow: var(--shadow);
|
138 |
+
}
|
139 |
+
|
140 |
+
.member-photo {
|
141 |
+
width: 150px;
|
142 |
+
height: 150px;
|
143 |
+
border-radius: 50%;
|
144 |
+
margin-bottom: 1rem;
|
145 |
+
object-fit: cover;
|
146 |
+
}
|
147 |
+
|
148 |
+
.achievements-grid {
|
149 |
+
display: grid;
|
150 |
+
grid-template-columns: repeat(4, 1fr);
|
151 |
+
gap: 2rem;
|
152 |
+
}
|
153 |
+
|
154 |
+
.achievement-item {
|
155 |
+
text-align: center;
|
156 |
+
padding: 2rem;
|
157 |
+
background: var(--white);
|
158 |
+
border-radius: 8px;
|
159 |
+
box-shadow: var(--shadow);
|
160 |
+
}
|
161 |
+
|
162 |
+
.achievement-item .number {
|
163 |
+
font-size: 2.5rem;
|
164 |
+
font-weight: bold;
|
165 |
+
color: var(--primary-color);
|
166 |
+
}
|
167 |
+
|
168 |
+
/* Contact Page Styles */
|
169 |
+
.contact-section {
|
170 |
+
max-width: 1200px;
|
171 |
+
margin: 0 auto;
|
172 |
+
padding: 2rem;
|
173 |
+
display: grid;
|
174 |
+
grid-template-columns: 1fr 2fr;
|
175 |
+
gap: 2rem;
|
176 |
+
}
|
177 |
+
|
178 |
+
.contact-info {
|
179 |
+
background: var(--white);
|
180 |
+
padding: 2rem;
|
181 |
+
border-radius: 8px;
|
182 |
+
box-shadow: var(--shadow);
|
183 |
+
}
|
184 |
+
|
185 |
+
.contact-item {
|
186 |
+
display: flex;
|
187 |
+
align-items: center;
|
188 |
+
gap: 1rem;
|
189 |
+
margin-bottom: 1.5rem;
|
190 |
+
}
|
191 |
+
|
192 |
+
.contact-item i {
|
193 |
+
font-size: 1.5rem;
|
194 |
+
color: var(--primary-color);
|
195 |
+
}
|
196 |
+
|
197 |
+
.contact-form {
|
198 |
+
background: var(--white);
|
199 |
+
padding: 2rem;
|
200 |
+
border-radius: 8px;
|
201 |
+
box-shadow: var(--shadow);
|
202 |
+
}
|
203 |
+
|
204 |
+
.form-group {
|
205 |
+
margin-bottom: 1.5rem;
|
206 |
+
}
|
207 |
+
|
208 |
+
.form-group label {
|
209 |
+
display: block;
|
210 |
+
margin-bottom: 0.5rem;
|
211 |
+
color: var(--text-color);
|
212 |
+
}
|
213 |
+
|
214 |
+
.form-group input,
|
215 |
+
.form-group textarea {
|
216 |
+
width: 100%;
|
217 |
+
padding: 0.75rem;
|
218 |
+
border: 1px solid #ddd;
|
219 |
+
border-radius: 4px;
|
220 |
+
transition: var(--transition);
|
221 |
+
}
|
222 |
+
|
223 |
+
.form-group input:focus,
|
224 |
+
.form-group textarea:focus {
|
225 |
+
border-color: var(--primary-color);
|
226 |
+
outline: none;
|
227 |
+
}
|
228 |
+
|
229 |
+
.submit-button {
|
230 |
+
background: var(--primary-color);
|
231 |
+
color: var(--white);
|
232 |
+
padding: 0.75rem 1.5rem;
|
233 |
+
border: none;
|
234 |
+
border-radius: 4px;
|
235 |
+
cursor: pointer;
|
236 |
+
transition: var(--transition);
|
237 |
+
}
|
238 |
+
|
239 |
+
.submit-button:hover {
|
240 |
+
background: #3367d6;
|
241 |
+
}
|
242 |
+
|
243 |
+
/* Follow Us Page Styles */
|
244 |
+
.social-section {
|
245 |
+
max-width: 1200px;
|
246 |
+
margin: 0 auto;
|
247 |
+
padding: 2rem;
|
248 |
+
}
|
249 |
+
|
250 |
+
.social-grid {
|
251 |
+
display: grid;
|
252 |
+
grid-template-columns: repeat(4, 1fr);
|
253 |
+
gap: 2rem;
|
254 |
+
margin-bottom: 4rem;
|
255 |
+
}
|
256 |
+
|
257 |
+
.social-card {
|
258 |
+
text-align: center;
|
259 |
+
padding: 2rem;
|
260 |
+
background: var(--white);
|
261 |
+
border-radius: 8px;
|
262 |
+
box-shadow: var(--shadow);
|
263 |
+
transition: var(--transition);
|
264 |
+
}
|
265 |
+
|
266 |
+
.social-card:hover {
|
267 |
+
transform: translateY(-5px);
|
268 |
+
}
|
269 |
+
|
270 |
+
.social-card i {
|
271 |
+
font-size: 3rem;
|
272 |
+
margin-bottom: 1rem;
|
273 |
+
}
|
274 |
+
|
275 |
+
.social-card.facebook i { color: #1877f2; }
|
276 |
+
.social-card.twitter i { color: #1da1f2; }
|
277 |
+
.social-card.linkedin i { color: #0077b5; }
|
278 |
+
.social-card.instagram i { color: #e4405f; }
|
279 |
+
|
280 |
+
.social-button {
|
281 |
+
display: inline-flex;
|
282 |
+
align-items: center;
|
283 |
+
gap: 0.5rem;
|
284 |
+
background: var(--primary-color);
|
285 |
+
color: var(--white);
|
286 |
+
padding: 0.75rem 1.5rem;
|
287 |
+
border-radius: 4px;
|
288 |
+
text-decoration: none;
|
289 |
+
margin: 1rem 0;
|
290 |
+
transition: var(--transition);
|
291 |
+
}
|
292 |
+
|
293 |
+
.social-button:hover {
|
294 |
+
background: #3367d6;
|
295 |
+
}
|
296 |
+
|
297 |
+
.followers {
|
298 |
+
display: block;
|
299 |
+
color: var(--dark-gray);
|
300 |
+
font-size: 0.9rem;
|
301 |
+
margin-top: 0.5rem;
|
302 |
+
}
|
303 |
+
|
304 |
+
.community-section {
|
305 |
+
max-width: 1200px;
|
306 |
+
margin: 0 auto;
|
307 |
+
padding: 2rem;
|
308 |
+
text-align: center;
|
309 |
+
}
|
310 |
+
|
311 |
+
.community-grid {
|
312 |
+
display: grid;
|
313 |
+
grid-template-columns: repeat(3, 1fr);
|
314 |
+
gap: 2rem;
|
315 |
+
margin: 2rem 0;
|
316 |
+
}
|
317 |
+
|
318 |
+
.community-card {
|
319 |
+
padding: 2rem;
|
320 |
+
background: var(--white);
|
321 |
+
border-radius: 8px;
|
322 |
+
box-shadow: var(--shadow);
|
323 |
+
transition: var(--transition);
|
324 |
+
}
|
325 |
+
|
326 |
+
.community-card:hover {
|
327 |
+
transform: translateY(-5px);
|
328 |
+
}
|
329 |
+
|
330 |
+
.community-card i {
|
331 |
+
font-size: 2.5rem;
|
332 |
+
color: var(--primary-color);
|
333 |
+
margin-bottom: 1rem;
|
334 |
+
}
|
335 |
+
|
336 |
+
.community-button {
|
337 |
+
display: inline-block;
|
338 |
+
background: var(--light-gray);
|
339 |
+
color: var(--text-color);
|
340 |
+
padding: 0.75rem 1.5rem;
|
341 |
+
border-radius: 4px;
|
342 |
+
text-decoration: none;
|
343 |
+
margin-top: 1rem;
|
344 |
+
transition: var(--transition);
|
345 |
+
}
|
346 |
+
|
347 |
+
.community-button:hover {
|
348 |
+
background: #e0e0e0;
|
349 |
+
}
|
350 |
+
|
351 |
+
.newsletter-section {
|
352 |
+
background: var(--light-gray);
|
353 |
+
padding: 4rem 2rem;
|
354 |
+
text-align: center;
|
355 |
+
}
|
356 |
+
|
357 |
+
.newsletter-form {
|
358 |
+
max-width: 500px;
|
359 |
+
margin: 2rem auto 0;
|
360 |
+
}
|
361 |
+
|
362 |
+
.newsletter-form .form-group {
|
363 |
+
display: flex;
|
364 |
+
gap: 1rem;
|
365 |
+
}
|
366 |
+
|
367 |
+
.subscribe-button {
|
368 |
+
background: var(--primary-color);
|
369 |
+
color: var(--white);
|
370 |
+
padding: 0.75rem 1.5rem;
|
371 |
+
border: none;
|
372 |
+
border-radius: 4px;
|
373 |
+
cursor: pointer;
|
374 |
+
transition: var(--transition);
|
375 |
+
display: inline-flex;
|
376 |
+
align-items: center;
|
377 |
+
gap: 0.5rem;
|
378 |
+
}
|
379 |
+
|
380 |
+
.subscribe-button:hover {
|
381 |
+
background: #3367d6;
|
382 |
+
}
|
383 |
+
|
384 |
+
/* Footer Styles */
|
385 |
+
.page-footer {
|
386 |
+
background: var(--text-color);
|
387 |
+
color: var(--white);
|
388 |
+
padding: 4rem 2rem 2rem;
|
389 |
+
}
|
390 |
+
|
391 |
+
.footer-content {
|
392 |
+
max-width: 1200px;
|
393 |
+
margin: 0 auto;
|
394 |
+
display: grid;
|
395 |
+
grid-template-columns: 2fr 1fr 1fr;
|
396 |
+
gap: 2rem;
|
397 |
+
}
|
398 |
+
|
399 |
+
.footer-section h3 {
|
400 |
+
margin-bottom: 1rem;
|
401 |
+
}
|
402 |
+
|
403 |
+
.footer-section ul {
|
404 |
+
list-style: none;
|
405 |
+
padding: 0;
|
406 |
+
}
|
407 |
+
|
408 |
+
.footer-section ul li {
|
409 |
+
margin-bottom: 0.5rem;
|
410 |
+
}
|
411 |
+
|
412 |
+
.footer-section a {
|
413 |
+
color: var(--white);
|
414 |
+
text-decoration: none;
|
415 |
+
opacity: 0.8;
|
416 |
+
transition: var(--transition);
|
417 |
+
}
|
418 |
+
|
419 |
+
.footer-section a:hover {
|
420 |
+
opacity: 1;
|
421 |
+
}
|
422 |
+
|
423 |
+
.social-links {
|
424 |
+
display: flex;
|
425 |
+
gap: 1rem;
|
426 |
+
}
|
427 |
+
|
428 |
+
.social-links a {
|
429 |
+
font-size: 1.5rem;
|
430 |
+
}
|
431 |
+
|
432 |
+
.footer-bottom {
|
433 |
+
max-width: 1200px;
|
434 |
+
margin: 2rem auto 0;
|
435 |
+
padding-top: 2rem;
|
436 |
+
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
437 |
+
text-align: center;
|
438 |
+
opacity: 0.8;
|
439 |
+
}
|
440 |
+
|
441 |
+
/* Responsive Design */
|
442 |
+
@media (max-width: 1200px) {
|
443 |
+
.about-section,
|
444 |
+
.contact-section,
|
445 |
+
.social-section,
|
446 |
+
.community-section {
|
447 |
+
padding: 2rem 1rem;
|
448 |
+
}
|
449 |
+
|
450 |
+
.values-grid,
|
451 |
+
.achievements-grid {
|
452 |
+
grid-template-columns: repeat(2, 1fr);
|
453 |
+
}
|
454 |
+
}
|
455 |
+
|
456 |
+
@media (max-width: 992px) {
|
457 |
+
.mission-vision,
|
458 |
+
.team-grid,
|
459 |
+
.social-grid {
|
460 |
+
grid-template-columns: repeat(2, 1fr);
|
461 |
+
}
|
462 |
+
|
463 |
+
.contact-section {
|
464 |
+
grid-template-columns: 1fr;
|
465 |
+
}
|
466 |
+
|
467 |
+
.footer-content {
|
468 |
+
grid-template-columns: 1fr 1fr;
|
469 |
+
}
|
470 |
+
}
|
471 |
+
|
472 |
+
@media (max-width: 768px) {
|
473 |
+
.main-nav {
|
474 |
+
flex-direction: column;
|
475 |
+
padding: 1rem;
|
476 |
+
}
|
477 |
+
|
478 |
+
.nav-links {
|
479 |
+
margin-top: 1rem;
|
480 |
+
gap: 1rem;
|
481 |
+
}
|
482 |
+
|
483 |
+
.hero-section {
|
484 |
+
padding: 3rem 1rem;
|
485 |
+
}
|
486 |
+
|
487 |
+
.hero-section h1 {
|
488 |
+
font-size: 2rem;
|
489 |
+
}
|
490 |
+
|
491 |
+
.values-grid,
|
492 |
+
.team-grid,
|
493 |
+
.social-grid,
|
494 |
+
.community-grid {
|
495 |
+
grid-template-columns: 1fr;
|
496 |
+
}
|
497 |
+
|
498 |
+
.newsletter-form .form-group {
|
499 |
+
flex-direction: column;
|
500 |
+
}
|
501 |
+
}
|
502 |
+
|
503 |
+
@media (max-width: 576px) {
|
504 |
+
.mission-vision {
|
505 |
+
grid-template-columns: 1fr;
|
506 |
+
}
|
507 |
+
|
508 |
+
.footer-content {
|
509 |
+
grid-template-columns: 1fr;
|
510 |
+
text-align: center;
|
511 |
+
}
|
512 |
+
|
513 |
+
.social-links {
|
514 |
+
justify-content: center;
|
515 |
+
}
|
516 |
+
}
|
css/style.css
ADDED
@@ -0,0 +1,755 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
/* Reset and Base Styles */
|
2 |
+
* {
|
3 |
+
margin: 0;
|
4 |
+
padding: 0;
|
5 |
+
box-sizing: border-box;
|
6 |
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
7 |
+
}
|
8 |
+
|
9 |
+
body {
|
10 |
+
background-color: #fff;
|
11 |
+
color: #333;
|
12 |
+
line-height: 1.6;
|
13 |
+
}
|
14 |
+
|
15 |
+
/* Chat Container */
|
16 |
+
.chat-container {
|
17 |
+
max-width: 100%;
|
18 |
+
height: 100vh;
|
19 |
+
display: flex;
|
20 |
+
flex-direction: column;
|
21 |
+
background-color: #fff;
|
22 |
+
}
|
23 |
+
|
24 |
+
/* Status Bar */
|
25 |
+
.status-bar {
|
26 |
+
display: flex;
|
27 |
+
justify-content: space-between;
|
28 |
+
align-items: center;
|
29 |
+
padding: 4px 16px;
|
30 |
+
background-color: #fff;
|
31 |
+
font-size: 14px;
|
32 |
+
height: 24px;
|
33 |
+
}
|
34 |
+
|
35 |
+
.status-icons {
|
36 |
+
display: flex;
|
37 |
+
gap: 8px;
|
38 |
+
align-items: center;
|
39 |
+
}
|
40 |
+
|
41 |
+
.network {
|
42 |
+
font-size: 12px;
|
43 |
+
color: #666;
|
44 |
+
}
|
45 |
+
|
46 |
+
/* Chat Header */
|
47 |
+
.chat-header {
|
48 |
+
display: flex;
|
49 |
+
justify-content: space-between;
|
50 |
+
align-items: center;
|
51 |
+
padding: 16px;
|
52 |
+
background-color: #fff;
|
53 |
+
border-bottom: 1px solid #eee;
|
54 |
+
}
|
55 |
+
|
56 |
+
.chat-header h1 {
|
57 |
+
font-size: 18px;
|
58 |
+
font-weight: 600;
|
59 |
+
}
|
60 |
+
|
61 |
+
.menu-btn, .new-chat-btn {
|
62 |
+
background: none;
|
63 |
+
border: none;
|
64 |
+
font-size: 20px;
|
65 |
+
color: #666;
|
66 |
+
cursor: pointer;
|
67 |
+
padding: 8px;
|
68 |
+
}
|
69 |
+
|
70 |
+
/* Chat Messages */
|
71 |
+
.chat-messages {
|
72 |
+
flex: 1;
|
73 |
+
overflow-y: auto;
|
74 |
+
padding: 16px;
|
75 |
+
display: flex;
|
76 |
+
flex-direction: column;
|
77 |
+
align-items: center;
|
78 |
+
justify-content: center;
|
79 |
+
}
|
80 |
+
|
81 |
+
.welcome-message {
|
82 |
+
text-align: center;
|
83 |
+
max-width: 300px;
|
84 |
+
}
|
85 |
+
|
86 |
+
.welcome-logo {
|
87 |
+
width: 80px;
|
88 |
+
height: 80px;
|
89 |
+
margin-bottom: 16px;
|
90 |
+
border-radius: 50%;
|
91 |
+
object-fit: cover;
|
92 |
+
box-shadow: 0 2px 8px var(--shadow-color);
|
93 |
+
}
|
94 |
+
|
95 |
+
.welcome-message h2 {
|
96 |
+
font-size: 24px;
|
97 |
+
margin-bottom: 8px;
|
98 |
+
color: #333;
|
99 |
+
}
|
100 |
+
|
101 |
+
.welcome-message p {
|
102 |
+
color: #666;
|
103 |
+
font-size: 16px;
|
104 |
+
}
|
105 |
+
|
106 |
+
/* Chat Input */
|
107 |
+
.chat-input {
|
108 |
+
padding: 16px;
|
109 |
+
background-color: #f8f8f8;
|
110 |
+
border-top: 1px solid #eee;
|
111 |
+
}
|
112 |
+
|
113 |
+
.input-container {
|
114 |
+
background-color: #fff;
|
115 |
+
border-radius: 24px;
|
116 |
+
padding: 8px 16px;
|
117 |
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
118 |
+
}
|
119 |
+
|
120 |
+
#message-input {
|
121 |
+
width: 100%;
|
122 |
+
border: none;
|
123 |
+
outline: none;
|
124 |
+
font-size: 16px;
|
125 |
+
padding: 8px 0;
|
126 |
+
background: transparent;
|
127 |
+
}
|
128 |
+
|
129 |
+
.input-actions {
|
130 |
+
display: flex;
|
131 |
+
align-items: center;
|
132 |
+
justify-content: flex-end;
|
133 |
+
gap: 12px;
|
134 |
+
margin-top: 8px;
|
135 |
+
padding-top: 8px;
|
136 |
+
border-top: 1px solid #eee;
|
137 |
+
}
|
138 |
+
|
139 |
+
.more-btn, .send-btn {
|
140 |
+
background: none;
|
141 |
+
border: none;
|
142 |
+
padding: 8px;
|
143 |
+
color: #666;
|
144 |
+
cursor: pointer;
|
145 |
+
display: flex;
|
146 |
+
align-items: center;
|
147 |
+
justify-content: center;
|
148 |
+
font-size: 14px;
|
149 |
+
}
|
150 |
+
|
151 |
+
.send-btn {
|
152 |
+
background-color: #4285f4;
|
153 |
+
color: white;
|
154 |
+
border-radius: 50%;
|
155 |
+
width: 32px;
|
156 |
+
height: 32px;
|
157 |
+
}
|
158 |
+
|
159 |
+
.send-btn i {
|
160 |
+
font-size: 16px;
|
161 |
+
}
|
162 |
+
|
163 |
+
.more-btn {
|
164 |
+
color: #666;
|
165 |
+
transition: color 0.2s ease;
|
166 |
+
}
|
167 |
+
|
168 |
+
.more-btn:hover {
|
169 |
+
color: #333;
|
170 |
+
}
|
171 |
+
|
172 |
+
/* Message Bubbles */
|
173 |
+
.message {
|
174 |
+
margin: 16px;
|
175 |
+
max-width: 80%;
|
176 |
+
animation: fadeIn 0.3s ease;
|
177 |
+
}
|
178 |
+
|
179 |
+
/* User message (question) styling */
|
180 |
+
.question-bubble {
|
181 |
+
background-color: #e3f2fd;
|
182 |
+
color: #1a1a1a;
|
183 |
+
padding: 12px 20px;
|
184 |
+
border-radius: 20px;
|
185 |
+
margin-left: auto;
|
186 |
+
font-size: 15px;
|
187 |
+
line-height: 1.5;
|
188 |
+
}
|
189 |
+
|
190 |
+
/* Bot message (answer) styling */
|
191 |
+
.answer-container {
|
192 |
+
display: flex;
|
193 |
+
gap: 16px;
|
194 |
+
margin-right: auto;
|
195 |
+
width: 100%;
|
196 |
+
}
|
197 |
+
|
198 |
+
.bot-icon {
|
199 |
+
flex-shrink: 0;
|
200 |
+
width: 32px;
|
201 |
+
height: 32px;
|
202 |
+
border-radius: 50%;
|
203 |
+
overflow: hidden;
|
204 |
+
background-color: transparent;
|
205 |
+
display: flex;
|
206 |
+
align-items: center;
|
207 |
+
justify-content: center;
|
208 |
+
}
|
209 |
+
|
210 |
+
.bot-icon img {
|
211 |
+
width: 100%;
|
212 |
+
height: 100%;
|
213 |
+
object-fit: contain;
|
214 |
+
display: block;
|
215 |
+
}
|
216 |
+
|
217 |
+
.answer-content {
|
218 |
+
flex-grow: 1;
|
219 |
+
font-size: 15px;
|
220 |
+
line-height: 1.6;
|
221 |
+
color: #333;
|
222 |
+
}
|
223 |
+
|
224 |
+
.response-heading {
|
225 |
+
font-size: 24px;
|
226 |
+
font-weight: 600;
|
227 |
+
margin: 20px 0 15px;
|
228 |
+
color: #1a1a1a;
|
229 |
+
}
|
230 |
+
|
231 |
+
.definition {
|
232 |
+
margin: 15px 0;
|
233 |
+
}
|
234 |
+
|
235 |
+
.term {
|
236 |
+
font-weight: 500;
|
237 |
+
color: #1a1a1a;
|
238 |
+
}
|
239 |
+
|
240 |
+
.definition-text {
|
241 |
+
color: #444;
|
242 |
+
}
|
243 |
+
|
244 |
+
.numbered-list {
|
245 |
+
margin: 15px 0;
|
246 |
+
}
|
247 |
+
|
248 |
+
.list-item {
|
249 |
+
display: flex;
|
250 |
+
margin: 12px 0;
|
251 |
+
align-items: flex-start;
|
252 |
+
}
|
253 |
+
|
254 |
+
.number {
|
255 |
+
font-weight: 600;
|
256 |
+
margin-right: 8px;
|
257 |
+
color: #1a1a1a;
|
258 |
+
min-width: 25px;
|
259 |
+
}
|
260 |
+
|
261 |
+
.list-content {
|
262 |
+
flex: 1;
|
263 |
+
}
|
264 |
+
|
265 |
+
.list-term {
|
266 |
+
font-weight: 500;
|
267 |
+
color: #1a1a1a;
|
268 |
+
}
|
269 |
+
|
270 |
+
.list-definition {
|
271 |
+
color: #444;
|
272 |
+
}
|
273 |
+
|
274 |
+
.response-paragraph {
|
275 |
+
margin: 12px 0;
|
276 |
+
color: #333;
|
277 |
+
}
|
278 |
+
|
279 |
+
/* Animations */
|
280 |
+
@keyframes fadeIn {
|
281 |
+
from {
|
282 |
+
opacity: 0;
|
283 |
+
transform: translateY(10px);
|
284 |
+
}
|
285 |
+
to {
|
286 |
+
opacity: 1;
|
287 |
+
transform: translateY(0);
|
288 |
+
}
|
289 |
+
}
|
290 |
+
|
291 |
+
/* Dark theme adjustments */
|
292 |
+
[data-theme="dark"] .question-bubble {
|
293 |
+
background-color: #2c2c2c;
|
294 |
+
color: #ffffff;
|
295 |
+
}
|
296 |
+
|
297 |
+
[data-theme="dark"] .answer-content {
|
298 |
+
color: #e1e1e1;
|
299 |
+
}
|
300 |
+
|
301 |
+
[data-theme="dark"] .response-heading,
|
302 |
+
[data-theme="dark"] .term,
|
303 |
+
[data-theme="dark"] .number,
|
304 |
+
[data-theme="dark"] .list-term {
|
305 |
+
color: #e1e1e1;
|
306 |
+
}
|
307 |
+
|
308 |
+
[data-theme="dark"] .definition-text,
|
309 |
+
[data-theme="dark"] .list-definition,
|
310 |
+
[data-theme="dark"] .response-paragraph {
|
311 |
+
color: #b4b4b4;
|
312 |
+
}
|
313 |
+
|
314 |
+
/* Typing indicator adjustments */
|
315 |
+
.typing-indicator {
|
316 |
+
background: transparent !important;
|
317 |
+
margin-bottom: 8px;
|
318 |
+
}
|
319 |
+
|
320 |
+
.typing-indicator span {
|
321 |
+
background-color: var(--text-secondary);
|
322 |
+
}
|
323 |
+
|
324 |
+
/* Responsive Design */
|
325 |
+
@media (max-width: 768px) {
|
326 |
+
.chat-container {
|
327 |
+
height: 100vh;
|
328 |
+
}
|
329 |
+
|
330 |
+
.welcome-message {
|
331 |
+
padding: 0 16px;
|
332 |
+
}
|
333 |
+
|
334 |
+
.input-container {
|
335 |
+
margin-bottom: env(safe-area-inset-bottom, 0);
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
/* Error Message */
|
340 |
+
.error-message {
|
341 |
+
background-color: #ffebee;
|
342 |
+
color: #c62828;
|
343 |
+
border: 1px solid #ffcdd2;
|
344 |
+
padding: 12px 16px;
|
345 |
+
margin: 8px 0;
|
346 |
+
border-radius: 8px;
|
347 |
+
font-size: 14px;
|
348 |
+
text-align: center;
|
349 |
+
animation: shake 0.5s ease-in-out;
|
350 |
+
}
|
351 |
+
|
352 |
+
@keyframes shake {
|
353 |
+
0%, 100% { transform: translateX(0); }
|
354 |
+
25% { transform: translateX(-4px); }
|
355 |
+
75% { transform: translateX(4px); }
|
356 |
+
}
|
357 |
+
|
358 |
+
/* Menu Overlay Styles */
|
359 |
+
.menu-overlay {
|
360 |
+
position: fixed;
|
361 |
+
top: 0;
|
362 |
+
left: -100%;
|
363 |
+
width: 100%;
|
364 |
+
height: 100%;
|
365 |
+
background-color: rgba(0, 0, 0, 0.5);
|
366 |
+
z-index: 1000;
|
367 |
+
opacity: 0;
|
368 |
+
visibility: hidden;
|
369 |
+
transition: opacity 0.3s ease, visibility 0.3s ease;
|
370 |
+
}
|
371 |
+
|
372 |
+
.menu-overlay.active {
|
373 |
+
left: 0;
|
374 |
+
opacity: 1;
|
375 |
+
visibility: visible;
|
376 |
+
}
|
377 |
+
|
378 |
+
.menu-content {
|
379 |
+
position: absolute;
|
380 |
+
top: 0;
|
381 |
+
left: -300px;
|
382 |
+
width: 300px;
|
383 |
+
height: 100%;
|
384 |
+
background-color: #fff;
|
385 |
+
box-shadow: 2px 0 8px rgba(0, 0, 0, 0.1);
|
386 |
+
transition: left 0.3s ease-in-out;
|
387 |
+
display: flex;
|
388 |
+
flex-direction: column;
|
389 |
+
}
|
390 |
+
|
391 |
+
.menu-overlay.active .menu-content {
|
392 |
+
left: 0;
|
393 |
+
}
|
394 |
+
|
395 |
+
.menu-header {
|
396 |
+
padding: 20px;
|
397 |
+
display: flex;
|
398 |
+
align-items: center;
|
399 |
+
justify-content: space-between;
|
400 |
+
border-bottom: 1px solid #eee;
|
401 |
+
}
|
402 |
+
|
403 |
+
.menu-logo {
|
404 |
+
height: 40px;
|
405 |
+
width: 40px;
|
406 |
+
border-radius: 50%;
|
407 |
+
object-fit: cover;
|
408 |
+
}
|
409 |
+
|
410 |
+
.close-menu-btn {
|
411 |
+
background: none;
|
412 |
+
border: none;
|
413 |
+
font-size: 24px;
|
414 |
+
color: #666;
|
415 |
+
cursor: pointer;
|
416 |
+
padding: 8px;
|
417 |
+
transition: color 0.2s ease;
|
418 |
+
}
|
419 |
+
|
420 |
+
.close-menu-btn:hover {
|
421 |
+
color: #333;
|
422 |
+
}
|
423 |
+
|
424 |
+
.menu-nav {
|
425 |
+
padding: 20px 0;
|
426 |
+
flex-grow: 1;
|
427 |
+
}
|
428 |
+
|
429 |
+
.menu-item {
|
430 |
+
display: flex;
|
431 |
+
align-items: center;
|
432 |
+
padding: 15px 20px;
|
433 |
+
color: #333;
|
434 |
+
text-decoration: none;
|
435 |
+
transition: background-color 0.2s ease;
|
436 |
+
}
|
437 |
+
|
438 |
+
.menu-item:hover {
|
439 |
+
background-color: #f5f5f5;
|
440 |
+
}
|
441 |
+
|
442 |
+
.menu-item i {
|
443 |
+
width: 24px;
|
444 |
+
margin-right: 15px;
|
445 |
+
color: #4285f4;
|
446 |
+
}
|
447 |
+
|
448 |
+
.menu-item span {
|
449 |
+
font-size: 16px;
|
450 |
+
}
|
451 |
+
|
452 |
+
/* Recent Conversations Styles */
|
453 |
+
.recent-conversations {
|
454 |
+
padding: 16px 0;
|
455 |
+
}
|
456 |
+
|
457 |
+
.recent-conversations h3 {
|
458 |
+
font-size: 14px;
|
459 |
+
color: #666;
|
460 |
+
padding: 0 20px;
|
461 |
+
margin-bottom: 12px;
|
462 |
+
text-transform: uppercase;
|
463 |
+
letter-spacing: 0.5px;
|
464 |
+
}
|
465 |
+
|
466 |
+
.conversation-list {
|
467 |
+
margin-bottom: 8px;
|
468 |
+
}
|
469 |
+
|
470 |
+
.conversation-item {
|
471 |
+
display: flex;
|
472 |
+
align-items: center;
|
473 |
+
padding: 12px 20px;
|
474 |
+
color: #333;
|
475 |
+
text-decoration: none;
|
476 |
+
cursor: pointer;
|
477 |
+
transition: background-color 0.2s ease;
|
478 |
+
}
|
479 |
+
|
480 |
+
.conversation-item:hover {
|
481 |
+
background-color: #f5f5f5;
|
482 |
+
}
|
483 |
+
|
484 |
+
.conversation-item i {
|
485 |
+
width: 24px;
|
486 |
+
margin-right: 15px;
|
487 |
+
color: #4285f4;
|
488 |
+
}
|
489 |
+
|
490 |
+
.conversation-item span {
|
491 |
+
font-size: 15px;
|
492 |
+
white-space: nowrap;
|
493 |
+
overflow: hidden;
|
494 |
+
text-overflow: ellipsis;
|
495 |
+
}
|
496 |
+
|
497 |
+
.see-more-btn {
|
498 |
+
display: flex;
|
499 |
+
align-items: center;
|
500 |
+
width: 100%;
|
501 |
+
padding: 12px 20px;
|
502 |
+
background: none;
|
503 |
+
border: none;
|
504 |
+
color: #4285f4;
|
505 |
+
cursor: pointer;
|
506 |
+
font-size: 15px;
|
507 |
+
transition: background-color 0.2s ease;
|
508 |
+
}
|
509 |
+
|
510 |
+
.see-more-btn:hover {
|
511 |
+
background-color: #f5f5f5;
|
512 |
+
}
|
513 |
+
|
514 |
+
.see-more-btn i {
|
515 |
+
width: 24px;
|
516 |
+
margin-right: 15px;
|
517 |
+
}
|
518 |
+
|
519 |
+
.menu-divider {
|
520 |
+
height: 1px;
|
521 |
+
background-color: #eee;
|
522 |
+
margin: 8px 0;
|
523 |
+
}
|
524 |
+
|
525 |
+
/* Theme Variables */
|
526 |
+
:root {
|
527 |
+
--bg-color: #fff;
|
528 |
+
--text-color: #333;
|
529 |
+
--header-bg: #fff;
|
530 |
+
--input-bg: #f8f8f8;
|
531 |
+
--border-color: #eee;
|
532 |
+
--message-bg: #f1f3f4;
|
533 |
+
--message-text: #333;
|
534 |
+
--user-message-bg: #4285f4;
|
535 |
+
--user-message-text: #fff;
|
536 |
+
--hover-bg: #f5f5f5;
|
537 |
+
--icon-color: #666;
|
538 |
+
--secondary-text: #666;
|
539 |
+
--error-bg: #ffebee;
|
540 |
+
--error-border: #ffcdd2;
|
541 |
+
--error-text: #c62828;
|
542 |
+
--shadow-color: rgba(0, 0, 0, 0.1);
|
543 |
+
--overlay-bg: rgba(0, 0, 0, 0.5);
|
544 |
+
}
|
545 |
+
|
546 |
+
/* Dark Theme */
|
547 |
+
[data-theme="dark"] {
|
548 |
+
--bg-color: #1a1a1a;
|
549 |
+
--text-color: #fff;
|
550 |
+
--header-bg: #2d2d2d;
|
551 |
+
--input-bg: #2d2d2d;
|
552 |
+
--border-color: #404040;
|
553 |
+
--message-bg: #383838;
|
554 |
+
--message-text: #fff;
|
555 |
+
--user-message-bg: #4285f4;
|
556 |
+
--user-message-text: #fff;
|
557 |
+
--hover-bg: #404040;
|
558 |
+
--icon-color: #aaa;
|
559 |
+
--secondary-text: #aaa;
|
560 |
+
--error-bg: #421c1c;
|
561 |
+
--error-border: #692727;
|
562 |
+
--error-text: #ff8a8a;
|
563 |
+
--shadow-color: rgba(0, 0, 0, 0.3);
|
564 |
+
--overlay-bg: rgba(0, 0, 0, 0.7);
|
565 |
+
}
|
566 |
+
|
567 |
+
/* Apply Theme Variables */
|
568 |
+
body {
|
569 |
+
background-color: var(--bg-color);
|
570 |
+
color: var(--text-color);
|
571 |
+
}
|
572 |
+
|
573 |
+
.chat-header {
|
574 |
+
background-color: var(--header-bg);
|
575 |
+
border-bottom: 1px solid var(--border-color);
|
576 |
+
}
|
577 |
+
|
578 |
+
.chat-input {
|
579 |
+
background-color: var(--input-bg);
|
580 |
+
border-top: 1px solid var(--border-color);
|
581 |
+
}
|
582 |
+
|
583 |
+
.input-container {
|
584 |
+
background-color: var(--bg-color);
|
585 |
+
box-shadow: 0 2px 8px var(--shadow-color);
|
586 |
+
}
|
587 |
+
|
588 |
+
#message-input {
|
589 |
+
color: var(--text-color);
|
590 |
+
}
|
591 |
+
|
592 |
+
.bot-message {
|
593 |
+
background-color: var(--message-bg);
|
594 |
+
color: var(--message-text);
|
595 |
+
}
|
596 |
+
|
597 |
+
.menu-content {
|
598 |
+
background-color: var(--bg-color);
|
599 |
+
}
|
600 |
+
|
601 |
+
/* Header Actions */
|
602 |
+
.header-actions {
|
603 |
+
display: flex;
|
604 |
+
gap: 8px;
|
605 |
+
align-items: center;
|
606 |
+
}
|
607 |
+
|
608 |
+
.theme-toggle-btn {
|
609 |
+
background: none;
|
610 |
+
border: none;
|
611 |
+
font-size: 20px;
|
612 |
+
color: var(--icon-color);
|
613 |
+
cursor: pointer;
|
614 |
+
padding: 8px;
|
615 |
+
transition: color 0.2s ease;
|
616 |
+
}
|
617 |
+
|
618 |
+
.theme-toggle-btn:hover {
|
619 |
+
color: var(--text-color);
|
620 |
+
}
|
621 |
+
|
622 |
+
/* Update existing styles to use variables */
|
623 |
+
.menu-btn, .new-chat-btn {
|
624 |
+
color: var(--icon-color);
|
625 |
+
}
|
626 |
+
|
627 |
+
.menu-btn:hover, .new-chat-btn:hover {
|
628 |
+
color: var(--text-color);
|
629 |
+
}
|
630 |
+
|
631 |
+
.welcome-message h2 {
|
632 |
+
color: var(--text-color);
|
633 |
+
}
|
634 |
+
|
635 |
+
.welcome-message p {
|
636 |
+
color: var(--secondary-text);
|
637 |
+
}
|
638 |
+
|
639 |
+
.error-message {
|
640 |
+
background-color: var(--error-bg);
|
641 |
+
color: var(--error-text);
|
642 |
+
border-color: var(--error-border);
|
643 |
+
}
|
644 |
+
|
645 |
+
/* Conversation Overlay Styles */
|
646 |
+
.conversation-overlay {
|
647 |
+
position: fixed;
|
648 |
+
top: 0;
|
649 |
+
left: 0;
|
650 |
+
width: 100%;
|
651 |
+
height: 100%;
|
652 |
+
background-color: var(--overlay-bg);
|
653 |
+
z-index: 2000;
|
654 |
+
display: flex;
|
655 |
+
justify-content: center;
|
656 |
+
align-items: center;
|
657 |
+
animation: fadeIn 0.3s ease;
|
658 |
+
}
|
659 |
+
|
660 |
+
.conversation-overlay-content {
|
661 |
+
background-color: var(--bg-color);
|
662 |
+
width: 90%;
|
663 |
+
max-width: 600px;
|
664 |
+
max-height: 80vh;
|
665 |
+
border-radius: 12px;
|
666 |
+
box-shadow: 0 4px 24px var(--shadow-color);
|
667 |
+
overflow: hidden;
|
668 |
+
animation: slideIn 0.3s ease;
|
669 |
+
}
|
670 |
+
|
671 |
+
.overlay-header {
|
672 |
+
padding: 20px;
|
673 |
+
border-bottom: 1px solid var(--border-color);
|
674 |
+
display: flex;
|
675 |
+
justify-content: space-between;
|
676 |
+
align-items: center;
|
677 |
+
}
|
678 |
+
|
679 |
+
.overlay-header h2 {
|
680 |
+
font-size: 20px;
|
681 |
+
color: var(--text-color);
|
682 |
+
}
|
683 |
+
|
684 |
+
.close-overlay-btn {
|
685 |
+
background: none;
|
686 |
+
border: none;
|
687 |
+
color: var(--icon-color);
|
688 |
+
font-size: 24px;
|
689 |
+
cursor: pointer;
|
690 |
+
padding: 8px;
|
691 |
+
transition: color 0.2s ease;
|
692 |
+
}
|
693 |
+
|
694 |
+
.close-overlay-btn:hover {
|
695 |
+
color: var(--text-color);
|
696 |
+
}
|
697 |
+
|
698 |
+
.conversation-list-full {
|
699 |
+
overflow-y: auto;
|
700 |
+
max-height: calc(80vh - 70px);
|
701 |
+
padding: 12px 0;
|
702 |
+
}
|
703 |
+
|
704 |
+
/* Enhanced Conversation Item Styles */
|
705 |
+
.conversation-item {
|
706 |
+
display: flex;
|
707 |
+
align-items: center;
|
708 |
+
padding: 16px 20px;
|
709 |
+
transition: background-color 0.2s ease;
|
710 |
+
cursor: pointer;
|
711 |
+
border-bottom: 1px solid var(--border-color);
|
712 |
+
}
|
713 |
+
|
714 |
+
.conversation-item:last-child {
|
715 |
+
border-bottom: none;
|
716 |
+
}
|
717 |
+
|
718 |
+
.conversation-item:hover {
|
719 |
+
background-color: var(--hover-bg);
|
720 |
+
}
|
721 |
+
|
722 |
+
.conversation-details {
|
723 |
+
flex-grow: 1;
|
724 |
+
margin-left: 16px;
|
725 |
+
display: flex;
|
726 |
+
flex-direction: column;
|
727 |
+
gap: 4px;
|
728 |
+
}
|
729 |
+
|
730 |
+
.conversation-title {
|
731 |
+
font-size: 16px;
|
732 |
+
font-weight: 500;
|
733 |
+
color: var(--text-color);
|
734 |
+
}
|
735 |
+
|
736 |
+
.message-count {
|
737 |
+
font-size: 14px;
|
738 |
+
color: var(--secondary-text);
|
739 |
+
}
|
740 |
+
|
741 |
+
.conversation-date {
|
742 |
+
font-size: 12px;
|
743 |
+
color: var(--secondary-text);
|
744 |
+
}
|
745 |
+
|
746 |
+
@keyframes slideIn {
|
747 |
+
from {
|
748 |
+
opacity: 0;
|
749 |
+
transform: translateY(20px);
|
750 |
+
}
|
751 |
+
to {
|
752 |
+
opacity: 1;
|
753 |
+
transform: translateY(0);
|
754 |
+
}
|
755 |
+
}
|
follow.html
ADDED
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<meta name="description" content="Follow DeepSeek on social media and join our community">
|
7 |
+
<meta name="theme-color" content="#4285f4">
|
8 |
+
<title>Follow Us - DeepSeek</title>
|
9 |
+
<link rel="stylesheet" href="css/style.css">
|
10 |
+
<link rel="stylesheet" href="css/pages.css">
|
11 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
12 |
+
</head>
|
13 |
+
<body>
|
14 |
+
<header class="page-header">
|
15 |
+
<nav class="main-nav">
|
16 |
+
<div class="logo">
|
17 |
+
<img src="images/logo.png" alt="DeepSeek Logo" width="40" height="40">
|
18 |
+
<span>DeepSeek</span>
|
19 |
+
</div>
|
20 |
+
<ul class="nav-links">
|
21 |
+
<li><a href="index.html">Home</a></li>
|
22 |
+
<li><a href="about.html">About</a></li>
|
23 |
+
<li><a href="contact.html">Contact</a></li>
|
24 |
+
<li><a href="follow.html" class="active">Follow Us</a></li>
|
25 |
+
</ul>
|
26 |
+
</nav>
|
27 |
+
</header>
|
28 |
+
|
29 |
+
<main class="page-content">
|
30 |
+
<section class="hero-section">
|
31 |
+
<h1>Connect With Us</h1>
|
32 |
+
<p class="section-desc">Join our growing community and stay updated with the latest news and developments</p>
|
33 |
+
</section>
|
34 |
+
|
35 |
+
<section class="social-section">
|
36 |
+
<div class="social-grid">
|
37 |
+
<div class="social-card facebook">
|
38 |
+
<i class="fab fa-facebook"></i>
|
39 |
+
<h2>Facebook</h2>
|
40 |
+
<p>Join our Facebook community for daily updates and engaging discussions</p>
|
41 |
+
<a href="#" class="social-button" target="_blank" rel="noopener noreferrer">
|
42 |
+
Follow on Facebook
|
43 |
+
<i class="fas fa-external-link-alt"></i>
|
44 |
+
</a>
|
45 |
+
<span class="followers">50K+ Followers</span>
|
46 |
+
</div>
|
47 |
+
|
48 |
+
<div class="social-card twitter">
|
49 |
+
<i class="fab fa-twitter"></i>
|
50 |
+
<h2>Twitter</h2>
|
51 |
+
<p>Follow us on Twitter for real-time updates and tech insights</p>
|
52 |
+
<a href="#" class="social-button" target="_blank" rel="noopener noreferrer">
|
53 |
+
Follow on Twitter
|
54 |
+
<i class="fas fa-external-link-alt"></i>
|
55 |
+
</a>
|
56 |
+
<span class="followers">75K+ Followers</span>
|
57 |
+
</div>
|
58 |
+
|
59 |
+
<div class="social-card linkedin">
|
60 |
+
<i class="fab fa-linkedin"></i>
|
61 |
+
<h2>LinkedIn</h2>
|
62 |
+
<p>Connect with us professionally and stay updated with company news</p>
|
63 |
+
<a href="#" class="social-button" target="_blank" rel="noopener noreferrer">
|
64 |
+
Follow on LinkedIn
|
65 |
+
<i class="fas fa-external-link-alt"></i>
|
66 |
+
</a>
|
67 |
+
<span class="followers">30K+ Followers</span>
|
68 |
+
</div>
|
69 |
+
|
70 |
+
<div class="social-card instagram">
|
71 |
+
<i class="fab fa-instagram"></i>
|
72 |
+
<h2>Instagram</h2>
|
73 |
+
<p>Follow our Instagram for behind-the-scenes and company culture</p>
|
74 |
+
<a href="#" class="social-button" target="_blank" rel="noopener noreferrer">
|
75 |
+
Follow on Instagram
|
76 |
+
<i class="fas fa-external-link-alt"></i>
|
77 |
+
</a>
|
78 |
+
<span class="followers">40K+ Followers</span>
|
79 |
+
</div>
|
80 |
+
</div>
|
81 |
+
</section>
|
82 |
+
|
83 |
+
<section class="community-section">
|
84 |
+
<h2>Join Our Community</h2>
|
85 |
+
<div class="community-grid">
|
86 |
+
<div class="community-card">
|
87 |
+
<i class="fab fa-github"></i>
|
88 |
+
<h3>GitHub</h3>
|
89 |
+
<p>Contribute to our open-source projects and collaborate with developers</p>
|
90 |
+
<a href="#" class="community-button" target="_blank" rel="noopener noreferrer">
|
91 |
+
View Repository
|
92 |
+
</a>
|
93 |
+
</div>
|
94 |
+
|
95 |
+
<div class="community-card">
|
96 |
+
<i class="fab fa-discord"></i>
|
97 |
+
<h3>Discord</h3>
|
98 |
+
<p>Join our Discord server for real-time discussions and support</p>
|
99 |
+
<a href="#" class="community-button" target="_blank" rel="noopener noreferrer">
|
100 |
+
Join Server
|
101 |
+
</a>
|
102 |
+
</div>
|
103 |
+
|
104 |
+
<div class="community-card">
|
105 |
+
<i class="fab fa-medium"></i>
|
106 |
+
<h3>Blog</h3>
|
107 |
+
<p>Read our latest articles and technical insights on Medium</p>
|
108 |
+
<a href="#" class="community-button" target="_blank" rel="noopener noreferrer">
|
109 |
+
Read Blog
|
110 |
+
</a>
|
111 |
+
</div>
|
112 |
+
</div>
|
113 |
+
</section>
|
114 |
+
|
115 |
+
<section class="newsletter-section">
|
116 |
+
<h2>Subscribe to Our Newsletter</h2>
|
117 |
+
<p>Get the latest updates delivered directly to your inbox</p>
|
118 |
+
<form class="newsletter-form" id="newsletterForm">
|
119 |
+
<div class="form-group">
|
120 |
+
<input type="email" id="email" name="email" placeholder="Enter your email address" required>
|
121 |
+
<button type="submit" class="subscribe-button">
|
122 |
+
Subscribe
|
123 |
+
<i class="fas fa-paper-plane"></i>
|
124 |
+
</button>
|
125 |
+
</div>
|
126 |
+
</form>
|
127 |
+
</section>
|
128 |
+
</main>
|
129 |
+
|
130 |
+
<footer class="page-footer">
|
131 |
+
<div class="footer-content">
|
132 |
+
<div class="footer-section">
|
133 |
+
<h3>DeepSeek</h3>
|
134 |
+
<p>Advancing AI technology to help people communicate and solve problems more effectively.</p>
|
135 |
+
</div>
|
136 |
+
<div class="footer-section">
|
137 |
+
<h3>Quick Links</h3>
|
138 |
+
<ul>
|
139 |
+
<li><a href="index.html">Home</a></li>
|
140 |
+
<li><a href="about.html">About</a></li>
|
141 |
+
<li><a href="contact.html">Contact</a></li>
|
142 |
+
<li><a href="follow.html">Follow Us</a></li>
|
143 |
+
</ul>
|
144 |
+
</div>
|
145 |
+
<div class="footer-section">
|
146 |
+
<h3>Connect With Us</h3>
|
147 |
+
<div class="social-links">
|
148 |
+
<a href="#" aria-label="Facebook"><i class="fab fa-facebook"></i></a>
|
149 |
+
<a href="#" aria-label="Twitter"><i class="fab fa-twitter"></i></a>
|
150 |
+
<a href="#" aria-label="LinkedIn"><i class="fab fa-linkedin"></i></a>
|
151 |
+
<a href="#" aria-label="Instagram"><i class="fab fa-instagram"></i></a>
|
152 |
+
</div>
|
153 |
+
</div>
|
154 |
+
</div>
|
155 |
+
<div class="footer-bottom">
|
156 |
+
<p>© 2024 DeepSeek. All rights reserved.</p>
|
157 |
+
</div>
|
158 |
+
</footer>
|
159 |
+
|
160 |
+
<script>
|
161 |
+
document.getElementById('newsletterForm').addEventListener('submit', function(e) {
|
162 |
+
e.preventDefault();
|
163 |
+
const email = document.getElementById('email').value;
|
164 |
+
alert('Thank you for subscribing! We will send updates to ' + email);
|
165 |
+
this.reset();
|
166 |
+
});
|
167 |
+
</script>
|
168 |
+
</body>
|
169 |
+
</html>
|
images/bot-message-logo.png
ADDED
![]() |
Git LFS Details
|
images/menu-logo.png
ADDED
![]() |
Git LFS Details
|
images/welcome-logo.png
ADDED
![]() |
Git LFS Details
|
index.html
CHANGED
@@ -1,19 +1,92 @@
|
|
1 |
-
<!
|
2 |
-
<html>
|
3 |
-
|
4 |
-
|
5 |
-
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
</html>
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Muhafiz AI Chat</title>
|
7 |
+
<link rel="stylesheet" href="css/style.css">
|
8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
9 |
+
</head>
|
10 |
+
<body>
|
11 |
+
<!-- Side Menu Overlay -->
|
12 |
+
<div id="menuOverlay" class="menu-overlay">
|
13 |
+
<div class="menu-content">
|
14 |
+
<div class="menu-header">
|
15 |
+
<img src="images/menu-logo.png" alt="Muhafiz AI Logo" class="menu-logo">
|
16 |
+
<button id="closeMenuBtn" class="close-menu-btn">
|
17 |
+
<i class="fas fa-times"></i>
|
18 |
+
</button>
|
19 |
+
</div>
|
20 |
+
<nav class="menu-nav">
|
21 |
+
<!-- Recent Conversations Section -->
|
22 |
+
<div class="recent-conversations">
|
23 |
+
<h3>Recent Conversations</h3>
|
24 |
+
<div class="conversation-list" id="conversationList">
|
25 |
+
<!-- Conversations will be added here dynamically -->
|
26 |
+
</div>
|
27 |
+
<button class="see-more-btn" id="seeMoreBtn">
|
28 |
+
<i class="fas fa-chevron-down"></i>
|
29 |
+
<span>See More</span>
|
30 |
+
</button>
|
31 |
+
</div>
|
32 |
+
|
33 |
+
<!-- Divider -->
|
34 |
+
<div class="menu-divider"></div>
|
35 |
+
|
36 |
+
<!-- Navigation Links -->
|
37 |
+
<a href="about.html" class="menu-item">
|
38 |
+
<i class="fas fa-info-circle"></i>
|
39 |
+
<span>About Us</span>
|
40 |
+
</a>
|
41 |
+
<a href="contact.html" class="menu-item">
|
42 |
+
<i class="fas fa-envelope"></i>
|
43 |
+
<span>Contact Us</span>
|
44 |
+
</a>
|
45 |
+
<a href="follow.html" class="menu-item">
|
46 |
+
<i class="fas fa-share-alt"></i>
|
47 |
+
<span>Follow Us</span>
|
48 |
+
</a>
|
49 |
+
</nav>
|
50 |
+
</div>
|
51 |
+
</div>
|
52 |
+
|
53 |
+
<div class="chat-container">
|
54 |
+
<!-- Chat Header -->
|
55 |
+
<header class="chat-header">
|
56 |
+
<button class="menu-btn"><i class="fas fa-bars"></i></button>
|
57 |
+
<h1>New chat</h1>
|
58 |
+
<div class="header-actions">
|
59 |
+
<button class="theme-toggle-btn" id="themeToggleBtn" title="Toggle theme">
|
60 |
+
<i class="fas fa-moon"></i>
|
61 |
+
</button>
|
62 |
+
<button class="new-chat-btn" id="new-chat-btn"><i class="fas fa-plus"></i></button>
|
63 |
+
</div>
|
64 |
+
</header>
|
65 |
+
|
66 |
+
<!-- Chat Messages -->
|
67 |
+
<main class="chat-messages" id="chat-messages">
|
68 |
+
<div class="welcome-message">
|
69 |
+
<img src="images/welcome-logo.png" alt="Muhafiz AI Logo" class="welcome-logo">
|
70 |
+
<h2>Hi, I'm Muhafiz AI.</h2>
|
71 |
+
<p>How can I help you today?</p>
|
72 |
+
</div>
|
73 |
+
</main>
|
74 |
+
|
75 |
+
<!-- Chat Input -->
|
76 |
+
<footer class="chat-input">
|
77 |
+
<div class="input-container">
|
78 |
+
<input type="text" id="message-input" placeholder="Message Muhafiz AI">
|
79 |
+
<div class="input-actions">
|
80 |
+
<button class="more-btn" title="More options">
|
81 |
+
<i class="fas fa-plus"></i>
|
82 |
+
</button>
|
83 |
+
<button class="send-btn" id="send-btn" title="Send message">
|
84 |
+
<i class="fas fa-arrow-up"></i>
|
85 |
+
</button>
|
86 |
+
</div>
|
87 |
+
</div>
|
88 |
+
</footer>
|
89 |
+
</div>
|
90 |
+
<script src="js/script.js"></script>
|
91 |
+
</body>
|
92 |
</html>
|
js/admin.js
ADDED
@@ -0,0 +1,350 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// DOM Elements
|
2 |
+
const adminMenu = document.querySelector('.admin-menu');
|
3 |
+
const tabContents = document.querySelectorAll('.tab-content');
|
4 |
+
const logoutBtn = document.getElementById('logout-btn');
|
5 |
+
const sectionTitle = document.getElementById('section-title');
|
6 |
+
|
7 |
+
// OpenRouter API Configuration
|
8 |
+
let openRouterConfig = {
|
9 |
+
apiKey: localStorage.getItem('openRouterApiKey') || '',
|
10 |
+
siteUrl: localStorage.getItem('openRouterSiteUrl') || window.location.origin,
|
11 |
+
siteName: localStorage.getItem('openRouterSiteName') || 'Muhafiz AI Chat'
|
12 |
+
};
|
13 |
+
|
14 |
+
// Model Settings
|
15 |
+
let modelSettings = {
|
16 |
+
selectedModel: localStorage.getItem('selectedModel') || 'openai/gpt-3.5-turbo',
|
17 |
+
temperature: parseFloat(localStorage.getItem('temperature')) || 0.7,
|
18 |
+
maxTokens: parseInt(localStorage.getItem('maxTokens')) || 2048,
|
19 |
+
streamResponse: localStorage.getItem('streamResponse') === 'true'
|
20 |
+
};
|
21 |
+
|
22 |
+
// Initialize admin panel
|
23 |
+
function initAdminPanel() {
|
24 |
+
// Check authentication
|
25 |
+
if (localStorage.getItem('adminLoggedIn') !== 'true') {
|
26 |
+
window.location.href = 'login.html';
|
27 |
+
return;
|
28 |
+
}
|
29 |
+
|
30 |
+
// Add event listeners
|
31 |
+
adminMenu.addEventListener('click', handleMenuClick);
|
32 |
+
logoutBtn.addEventListener('click', handleLogout);
|
33 |
+
|
34 |
+
// Load saved settings
|
35 |
+
loadSettings();
|
36 |
+
|
37 |
+
// Set up form change tracking
|
38 |
+
setupChangeTracking();
|
39 |
+
}
|
40 |
+
|
41 |
+
// Handle menu item clicks
|
42 |
+
function handleMenuClick(e) {
|
43 |
+
const menuItem = e.target.closest('li');
|
44 |
+
if (!menuItem || menuItem.id === 'logout-btn') return;
|
45 |
+
|
46 |
+
// Update active menu item
|
47 |
+
document.querySelectorAll('.admin-menu li').forEach(item => {
|
48 |
+
item.classList.remove('active');
|
49 |
+
});
|
50 |
+
menuItem.classList.add('active');
|
51 |
+
|
52 |
+
// Show corresponding tab content
|
53 |
+
const tabId = menuItem.getAttribute('data-tab');
|
54 |
+
tabContents.forEach(tab => {
|
55 |
+
tab.classList.remove('active');
|
56 |
+
if (tab.id === tabId) {
|
57 |
+
tab.classList.add('active');
|
58 |
+
}
|
59 |
+
});
|
60 |
+
|
61 |
+
// Update section title
|
62 |
+
sectionTitle.textContent = menuItem.textContent.trim();
|
63 |
+
}
|
64 |
+
|
65 |
+
// Handle logout
|
66 |
+
function handleLogout() {
|
67 |
+
if (hasUnsavedChanges()) {
|
68 |
+
if (!confirm('You have unsaved changes. Are you sure you want to logout?')) {
|
69 |
+
return;
|
70 |
+
}
|
71 |
+
}
|
72 |
+
|
73 |
+
// Clear admin session
|
74 |
+
localStorage.removeItem('adminLoggedIn');
|
75 |
+
|
76 |
+
// Redirect to login page
|
77 |
+
window.location.href = 'login.html';
|
78 |
+
}
|
79 |
+
|
80 |
+
// Track unsaved changes
|
81 |
+
let hasUnsavedChanges = () => false;
|
82 |
+
|
83 |
+
// Set up change tracking
|
84 |
+
function setupChangeTracking() {
|
85 |
+
const formElements = document.querySelectorAll('input, select, textarea');
|
86 |
+
let initialValues = new Map();
|
87 |
+
|
88 |
+
formElements.forEach(element => {
|
89 |
+
initialValues.set(element, element.value);
|
90 |
+
|
91 |
+
element.addEventListener('change', () => {
|
92 |
+
const hasChanges = Array.from(formElements).some(el =>
|
93 |
+
initialValues.get(el) !== el.value
|
94 |
+
);
|
95 |
+
hasUnsavedChanges = () => hasChanges;
|
96 |
+
});
|
97 |
+
});
|
98 |
+
}
|
99 |
+
|
100 |
+
// Load saved settings
|
101 |
+
function loadSettings() {
|
102 |
+
const savedConfig = localStorage.getItem('chatConfig');
|
103 |
+
if (savedConfig) {
|
104 |
+
const config = JSON.parse(savedConfig);
|
105 |
+
// Apply saved settings to form elements
|
106 |
+
Object.entries(config).forEach(([key, value]) => {
|
107 |
+
const element = document.getElementById(key);
|
108 |
+
if (element) {
|
109 |
+
element.value = value;
|
110 |
+
}
|
111 |
+
});
|
112 |
+
}
|
113 |
+
}
|
114 |
+
|
115 |
+
// Save settings
|
116 |
+
function saveSettings() {
|
117 |
+
// OpenRouter API Configuration
|
118 |
+
openRouterConfig = {
|
119 |
+
apiKey: document.getElementById('openRouterApiKey').value,
|
120 |
+
siteUrl: document.getElementById('openRouterSiteUrl').value,
|
121 |
+
siteName: document.getElementById('openRouterSiteName').value
|
122 |
+
};
|
123 |
+
|
124 |
+
// Model Settings
|
125 |
+
modelSettings = {
|
126 |
+
selectedModel: document.getElementById('modelSelect').value,
|
127 |
+
temperature: parseFloat(document.getElementById('temperature').value),
|
128 |
+
maxTokens: parseInt(document.getElementById('maxTokens').value),
|
129 |
+
streamResponse: document.getElementById('streamResponse').checked
|
130 |
+
};
|
131 |
+
|
132 |
+
// Save to localStorage
|
133 |
+
Object.entries(openRouterConfig).forEach(([key, value]) => {
|
134 |
+
localStorage.setItem(`openRouter${key.charAt(0).toUpperCase() + key.slice(1)}`, value);
|
135 |
+
});
|
136 |
+
|
137 |
+
Object.entries(modelSettings).forEach(([key, value]) => {
|
138 |
+
localStorage.setItem(key, value);
|
139 |
+
});
|
140 |
+
|
141 |
+
showNotification('Settings saved successfully!', 'success');
|
142 |
+
}
|
143 |
+
|
144 |
+
// Show notification
|
145 |
+
function showNotification(message, type = 'info') {
|
146 |
+
const notification = document.createElement('div');
|
147 |
+
notification.classList.add('notification', `notification-${type}`);
|
148 |
+
notification.textContent = message;
|
149 |
+
|
150 |
+
document.body.appendChild(notification);
|
151 |
+
|
152 |
+
setTimeout(() => {
|
153 |
+
notification.classList.add('notification-hide');
|
154 |
+
setTimeout(() => notification.remove(), 300);
|
155 |
+
}, 3000);
|
156 |
+
}
|
157 |
+
|
158 |
+
// Initialize when DOM is loaded
|
159 |
+
document.addEventListener('DOMContentLoaded', initAdminPanel);
|
160 |
+
|
161 |
+
// Handle beforeunload
|
162 |
+
window.addEventListener('beforeunload', (e) => {
|
163 |
+
if (hasUnsavedChanges()) {
|
164 |
+
e.preventDefault();
|
165 |
+
e.returnValue = '';
|
166 |
+
}
|
167 |
+
});
|
168 |
+
|
169 |
+
// Initialize form values
|
170 |
+
function initializeFormValues() {
|
171 |
+
// OpenRouter API Configuration
|
172 |
+
document.getElementById('openRouterApiKey').value = openRouterConfig.apiKey;
|
173 |
+
document.getElementById('openRouterSiteUrl').value = openRouterConfig.siteUrl;
|
174 |
+
document.getElementById('openRouterSiteName').value = openRouterConfig.siteName;
|
175 |
+
|
176 |
+
// Model Settings
|
177 |
+
document.getElementById('modelSelect').value = modelSettings.selectedModel;
|
178 |
+
document.getElementById('temperature').value = modelSettings.temperature;
|
179 |
+
document.getElementById('temperatureValue').textContent = modelSettings.temperature;
|
180 |
+
document.getElementById('maxTokens').value = modelSettings.maxTokens;
|
181 |
+
document.getElementById('streamResponse').checked = modelSettings.streamResponse;
|
182 |
+
}
|
183 |
+
|
184 |
+
// Copy to clipboard function
|
185 |
+
function copyToClipboard(elementId) {
|
186 |
+
const element = document.getElementById(elementId);
|
187 |
+
navigator.clipboard.writeText(element.value).then(() => {
|
188 |
+
showNotification('Copied to clipboard!', 'success');
|
189 |
+
}).catch(err => {
|
190 |
+
showNotification('Failed to copy text', 'error');
|
191 |
+
});
|
192 |
+
}
|
193 |
+
|
194 |
+
// Test model function
|
195 |
+
async function testModel() {
|
196 |
+
const testButton = document.getElementById('testModel');
|
197 |
+
const originalText = testButton.textContent;
|
198 |
+
testButton.disabled = true;
|
199 |
+
testButton.textContent = 'Testing...';
|
200 |
+
|
201 |
+
try {
|
202 |
+
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
203 |
+
method: 'POST',
|
204 |
+
headers: {
|
205 |
+
'Authorization': `Bearer ${openRouterConfig.apiKey}`,
|
206 |
+
'HTTP-Referer': openRouterConfig.siteUrl,
|
207 |
+
'X-Title': openRouterConfig.siteName,
|
208 |
+
'Content-Type': 'application/json'
|
209 |
+
},
|
210 |
+
body: JSON.stringify({
|
211 |
+
model: modelSettings.selectedModel,
|
212 |
+
messages: [
|
213 |
+
{
|
214 |
+
role: 'user',
|
215 |
+
content: 'Say "Hello! I am working correctly!"'
|
216 |
+
}
|
217 |
+
],
|
218 |
+
temperature: modelSettings.temperature,
|
219 |
+
max_tokens: modelSettings.maxTokens,
|
220 |
+
stream: false
|
221 |
+
})
|
222 |
+
});
|
223 |
+
|
224 |
+
const data = await response.json();
|
225 |
+
|
226 |
+
if (!response.ok) {
|
227 |
+
console.error('OpenRouter API Error:', data);
|
228 |
+
throw new Error(data.error?.message || `HTTP error! status: ${response.status}`);
|
229 |
+
}
|
230 |
+
|
231 |
+
showNotification('Model test successful! Response: ' + data.choices[0].message.content, 'success');
|
232 |
+
} catch (error) {
|
233 |
+
console.error('Model test failed:', error);
|
234 |
+
showNotification('Model test failed: ' + error.message, 'error');
|
235 |
+
} finally {
|
236 |
+
testButton.disabled = false;
|
237 |
+
testButton.textContent = originalText;
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
// Update temperature value display
|
242 |
+
document.getElementById('temperature')?.addEventListener('input', (e) => {
|
243 |
+
document.getElementById('temperatureValue').textContent = e.target.value;
|
244 |
+
});
|
245 |
+
|
246 |
+
// Test API Response
|
247 |
+
async function testApiResponse() {
|
248 |
+
const testButton = document.getElementById('testApiBtn');
|
249 |
+
const testMessage = document.getElementById('testMessage');
|
250 |
+
const testResponse = document.getElementById('testResponse');
|
251 |
+
const testError = document.getElementById('testError');
|
252 |
+
const responseContainer = document.querySelector('.test-response-container');
|
253 |
+
|
254 |
+
// Validate inputs
|
255 |
+
if (!openRouterConfig.apiKey) {
|
256 |
+
showNotification('Please enter your API key first', 'error');
|
257 |
+
return;
|
258 |
+
}
|
259 |
+
|
260 |
+
// Update button state
|
261 |
+
testButton.classList.add('loading');
|
262 |
+
testButton.disabled = true;
|
263 |
+
const originalText = testButton.innerHTML;
|
264 |
+
testButton.innerHTML = '<i class="fas fa-spinner"></i> Testing...';
|
265 |
+
|
266 |
+
// Clear previous results
|
267 |
+
testResponse.textContent = '';
|
268 |
+
testError.textContent = '';
|
269 |
+
responseContainer.style.display = 'none';
|
270 |
+
|
271 |
+
try {
|
272 |
+
console.log('Testing API with configuration:', {
|
273 |
+
model: modelSettings.selectedModel,
|
274 |
+
siteUrl: openRouterConfig.siteUrl,
|
275 |
+
siteName: openRouterConfig.siteName
|
276 |
+
});
|
277 |
+
|
278 |
+
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
279 |
+
method: 'POST',
|
280 |
+
headers: {
|
281 |
+
'Authorization': `Bearer ${openRouterConfig.apiKey}`,
|
282 |
+
'HTTP-Referer': openRouterConfig.siteUrl,
|
283 |
+
'X-Title': openRouterConfig.siteName,
|
284 |
+
'Content-Type': 'application/json'
|
285 |
+
},
|
286 |
+
body: JSON.stringify({
|
287 |
+
model: modelSettings.selectedModel,
|
288 |
+
messages: [
|
289 |
+
{
|
290 |
+
role: 'user',
|
291 |
+
content: testMessage.value || 'Hello! Can you hear me?'
|
292 |
+
}
|
293 |
+
],
|
294 |
+
temperature: modelSettings.temperature,
|
295 |
+
max_tokens: modelSettings.maxTokens,
|
296 |
+
stream: false
|
297 |
+
})
|
298 |
+
});
|
299 |
+
|
300 |
+
const data = await response.json();
|
301 |
+
|
302 |
+
if (!response.ok) {
|
303 |
+
console.error('OpenRouter API Error:', data);
|
304 |
+
throw new Error(data.error?.message || `HTTP error! status: ${response.status}`);
|
305 |
+
}
|
306 |
+
|
307 |
+
// Display the full response for debugging
|
308 |
+
responseContainer.style.display = 'block';
|
309 |
+
testResponse.textContent = JSON.stringify(data, null, 2);
|
310 |
+
|
311 |
+
// Show success notification
|
312 |
+
showNotification('API test successful!', 'success');
|
313 |
+
|
314 |
+
} catch (error) {
|
315 |
+
console.error('API Test Error:', error);
|
316 |
+
responseContainer.style.display = 'block';
|
317 |
+
testError.textContent = `Error: ${error.message}`;
|
318 |
+
showNotification('API test failed. Check the error details below.', 'error');
|
319 |
+
} finally {
|
320 |
+
// Reset button state
|
321 |
+
testButton.classList.remove('loading');
|
322 |
+
testButton.disabled = false;
|
323 |
+
testButton.innerHTML = originalText;
|
324 |
+
}
|
325 |
+
}
|
326 |
+
|
327 |
+
// Initialize form values when DOM is loaded
|
328 |
+
document.addEventListener('DOMContentLoaded', () => {
|
329 |
+
initializeFormValues();
|
330 |
+
|
331 |
+
// Add event listeners for copy buttons
|
332 |
+
document.querySelectorAll('.copy-btn').forEach(button => {
|
333 |
+
button.addEventListener('click', (e) => {
|
334 |
+
const inputId = e.target.closest('.input-with-copy').querySelector('input').id;
|
335 |
+
copyToClipboard(inputId);
|
336 |
+
});
|
337 |
+
});
|
338 |
+
|
339 |
+
// Add event listener for test model button
|
340 |
+
document.getElementById('testModel')?.addEventListener('click', testModel);
|
341 |
+
|
342 |
+
// Add test API button handler
|
343 |
+
document.getElementById('testApiBtn')?.addEventListener('click', testApiResponse);
|
344 |
+
|
345 |
+
// Add form submit handler
|
346 |
+
document.getElementById('modelSettingsForm')?.addEventListener('submit', (e) => {
|
347 |
+
e.preventDefault();
|
348 |
+
saveSettings();
|
349 |
+
});
|
350 |
+
});
|
js/login.js
ADDED
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Constants
|
2 |
+
const MAX_LOGIN_ATTEMPTS = 5;
|
3 |
+
const LOCKOUT_TIME = 5 * 60 * 1000; // 5 minutes in milliseconds
|
4 |
+
|
5 |
+
// Get DOM elements
|
6 |
+
const loginForm = document.getElementById('loginForm');
|
7 |
+
const usernameInput = document.getElementById('username');
|
8 |
+
const passwordInput = document.getElementById('password');
|
9 |
+
const errorMessage = document.getElementById('errorMessage');
|
10 |
+
const togglePasswordBtn = document.querySelector('.toggle-password');
|
11 |
+
|
12 |
+
// Initialize login attempts
|
13 |
+
let loginAttempts = parseInt(localStorage.getItem('loginAttempts') || '0');
|
14 |
+
let lastAttemptTime = parseInt(localStorage.getItem('lastAttemptTime') || '0');
|
15 |
+
|
16 |
+
// Get redirect URL from query parameters
|
17 |
+
function getRedirectUrl() {
|
18 |
+
const params = new URLSearchParams(window.location.search);
|
19 |
+
return params.get('redirect') || 'admin.html';
|
20 |
+
}
|
21 |
+
|
22 |
+
// Check if user is already logged in
|
23 |
+
function checkLoginStatus() {
|
24 |
+
if (localStorage.getItem('adminLoggedIn') === 'true') {
|
25 |
+
window.location.href = getRedirectUrl();
|
26 |
+
}
|
27 |
+
}
|
28 |
+
|
29 |
+
// Check if user is locked out
|
30 |
+
function isLockedOut() {
|
31 |
+
if (loginAttempts >= MAX_LOGIN_ATTEMPTS) {
|
32 |
+
const timeSinceLastAttempt = Date.now() - lastAttemptTime;
|
33 |
+
if (timeSinceLastAttempt < LOCKOUT_TIME) {
|
34 |
+
const remainingTime = Math.ceil((LOCKOUT_TIME - timeSinceLastAttempt) / 1000 / 60);
|
35 |
+
errorMessage.textContent = `Too many failed attempts. Please try again in ${remainingTime} minutes.`;
|
36 |
+
return true;
|
37 |
+
} else {
|
38 |
+
// Reset attempts after lockout period
|
39 |
+
resetAttempts();
|
40 |
+
}
|
41 |
+
}
|
42 |
+
return false;
|
43 |
+
}
|
44 |
+
|
45 |
+
// Reset login attempts
|
46 |
+
function resetAttempts() {
|
47 |
+
loginAttempts = 0;
|
48 |
+
localStorage.setItem('loginAttempts', '0');
|
49 |
+
localStorage.removeItem('lastAttemptTime');
|
50 |
+
}
|
51 |
+
|
52 |
+
// Handle login form submission
|
53 |
+
loginForm.addEventListener('submit', async (e) => {
|
54 |
+
e.preventDefault();
|
55 |
+
|
56 |
+
// Clear previous error
|
57 |
+
errorMessage.textContent = '';
|
58 |
+
|
59 |
+
// Check for lockout
|
60 |
+
if (isLockedOut()) {
|
61 |
+
return;
|
62 |
+
}
|
63 |
+
|
64 |
+
const username = usernameInput.value.trim();
|
65 |
+
const password = passwordInput.value;
|
66 |
+
|
67 |
+
// Basic validation
|
68 |
+
if (!username || !password) {
|
69 |
+
errorMessage.textContent = 'Please enter both username and password';
|
70 |
+
return;
|
71 |
+
}
|
72 |
+
|
73 |
+
try {
|
74 |
+
// In a real application, this would be an API call to verify credentials
|
75 |
+
if (username === 'admin' && password === 'AdminMuhafiz') {
|
76 |
+
// Successful login
|
77 |
+
localStorage.setItem('adminLoggedIn', 'true');
|
78 |
+
resetAttempts();
|
79 |
+
|
80 |
+
// Redirect to the intended page
|
81 |
+
window.location.href = getRedirectUrl();
|
82 |
+
} else {
|
83 |
+
// Failed login
|
84 |
+
loginAttempts++;
|
85 |
+
lastAttemptTime = Date.now();
|
86 |
+
localStorage.setItem('loginAttempts', loginAttempts.toString());
|
87 |
+
localStorage.setItem('lastAttemptTime', lastAttemptTime.toString());
|
88 |
+
|
89 |
+
if (loginAttempts >= MAX_LOGIN_ATTEMPTS) {
|
90 |
+
errorMessage.textContent = 'Too many failed attempts. Please try again in 5 minutes.';
|
91 |
+
} else {
|
92 |
+
const remainingAttempts = MAX_LOGIN_ATTEMPTS - loginAttempts;
|
93 |
+
errorMessage.textContent = `Invalid username or password. ${remainingAttempts} attempts remaining.`;
|
94 |
+
}
|
95 |
+
}
|
96 |
+
} catch (error) {
|
97 |
+
errorMessage.textContent = 'An error occurred. Please try again.';
|
98 |
+
console.error('Login error:', error);
|
99 |
+
}
|
100 |
+
});
|
101 |
+
|
102 |
+
// Toggle password visibility
|
103 |
+
togglePasswordBtn.addEventListener('click', () => {
|
104 |
+
const type = passwordInput.type === 'password' ? 'text' : 'password';
|
105 |
+
passwordInput.type = type;
|
106 |
+
togglePasswordBtn.innerHTML = `<i class="fas fa-eye${type === 'password' ? '' : '-slash'}"></i>`;
|
107 |
+
});
|
108 |
+
|
109 |
+
// Check login status on page load
|
110 |
+
document.addEventListener('DOMContentLoaded', checkLoginStatus);
|
111 |
+
|
112 |
+
// Clear error message when user starts typing
|
113 |
+
usernameInput.addEventListener('input', () => errorMessage.textContent = '');
|
114 |
+
passwordInput.addEventListener('input', () => errorMessage.textContent = '');
|
js/script.js
ADDED
@@ -0,0 +1,656 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
// Chat Configuration
|
2 |
+
const DEFAULT_API_KEY = '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';
|
3 |
+
const DEFAULT_MODEL = 'qwen/qwen3-14b:free';
|
4 |
+
|
5 |
+
let chatConfig = {
|
6 |
+
apiKey: DEFAULT_API_KEY,
|
7 |
+
model: DEFAULT_MODEL,
|
8 |
+
siteUrl: window.location.origin,
|
9 |
+
siteName: 'Muhafiz AI Chat'
|
10 |
+
};
|
11 |
+
|
12 |
+
// Conversation history
|
13 |
+
let conversationHistory = [];
|
14 |
+
|
15 |
+
// DOM Elements
|
16 |
+
const messageInput = document.getElementById('message-input');
|
17 |
+
const sendButton = document.getElementById('send-btn');
|
18 |
+
const chatMessages = document.getElementById('chat-messages');
|
19 |
+
const moreButton = document.querySelector('.more-btn');
|
20 |
+
const newChatButton = document.getElementById('new-chat-btn');
|
21 |
+
const menuButton = document.querySelector('.menu-btn');
|
22 |
+
const menuOverlay = document.getElementById('menuOverlay');
|
23 |
+
const closeMenuButton = document.getElementById('closeMenuBtn');
|
24 |
+
const conversationList = document.getElementById('conversationList');
|
25 |
+
const seeMoreBtn = document.getElementById('seeMoreBtn');
|
26 |
+
const themeToggleBtn = document.getElementById('themeToggleBtn');
|
27 |
+
|
28 |
+
// Initialize chat
|
29 |
+
function initChat() {
|
30 |
+
// Load saved configuration and conversations
|
31 |
+
loadChatConfig();
|
32 |
+
loadConversations();
|
33 |
+
loadTheme();
|
34 |
+
|
35 |
+
// Add event listeners
|
36 |
+
messageInput.addEventListener('input', handleInput);
|
37 |
+
messageInput.addEventListener('keypress', handleKeyPress);
|
38 |
+
sendButton.addEventListener('click', handleSend);
|
39 |
+
moreButton.addEventListener('click', handleMore);
|
40 |
+
newChatButton.addEventListener('click', handleNewChat);
|
41 |
+
menuButton.addEventListener('click', handleMenuOpen);
|
42 |
+
closeMenuButton.addEventListener('click', handleMenuClose);
|
43 |
+
seeMoreBtn.addEventListener('click', handleSeeMore);
|
44 |
+
themeToggleBtn.addEventListener('click', handleThemeToggle);
|
45 |
+
menuOverlay.addEventListener('click', (e) => {
|
46 |
+
if (e.target === menuOverlay) {
|
47 |
+
handleMenuClose();
|
48 |
+
}
|
49 |
+
});
|
50 |
+
|
51 |
+
// Disable send button initially
|
52 |
+
sendButton.disabled = true;
|
53 |
+
sendButton.style.opacity = '0.5';
|
54 |
+
|
55 |
+
// Update status bar time
|
56 |
+
updateTime();
|
57 |
+
setInterval(updateTime, 60000);
|
58 |
+
}
|
59 |
+
|
60 |
+
// Load conversations from localStorage
|
61 |
+
function loadConversations() {
|
62 |
+
const savedConversations = localStorage.getItem('conversations');
|
63 |
+
if (savedConversations) {
|
64 |
+
conversationHistory = JSON.parse(savedConversations);
|
65 |
+
|
66 |
+
// If there are saved conversations, update the chat interface
|
67 |
+
if (conversationHistory.length > 0) {
|
68 |
+
const currentConversation = conversationHistory[0];
|
69 |
+
if (currentConversation.messages.length > 0) {
|
70 |
+
// Clear welcome message
|
71 |
+
while (chatMessages.firstChild) {
|
72 |
+
chatMessages.removeChild(chatMessages.firstChild);
|
73 |
+
}
|
74 |
+
|
75 |
+
// Load messages from the current conversation
|
76 |
+
currentConversation.messages.forEach(msg => {
|
77 |
+
addMessage(msg.content, msg.type);
|
78 |
+
});
|
79 |
+
}
|
80 |
+
}
|
81 |
+
}
|
82 |
+
updateConversationList();
|
83 |
+
}
|
84 |
+
|
85 |
+
// Save conversations to localStorage
|
86 |
+
function saveConversations() {
|
87 |
+
localStorage.setItem('conversations', JSON.stringify(conversationHistory));
|
88 |
+
}
|
89 |
+
|
90 |
+
// Update conversation list in menu
|
91 |
+
function updateConversationList() {
|
92 |
+
conversationList.innerHTML = '';
|
93 |
+
const recentConversations = conversationHistory.slice(0, 4);
|
94 |
+
|
95 |
+
if (recentConversations.length === 0) {
|
96 |
+
const emptyState = document.createElement('div');
|
97 |
+
emptyState.className = 'empty-conversations';
|
98 |
+
emptyState.textContent = 'No conversations yet';
|
99 |
+
conversationList.appendChild(emptyState);
|
100 |
+
return;
|
101 |
+
}
|
102 |
+
|
103 |
+
recentConversations.forEach(conv => {
|
104 |
+
const item = document.createElement('div');
|
105 |
+
item.className = 'conversation-item';
|
106 |
+
item.innerHTML = `
|
107 |
+
<i class="fas fa-comment"></i>
|
108 |
+
<span>${conv.title}</span>
|
109 |
+
<span class="message-count">${conv.messages.length} messages</span>
|
110 |
+
`;
|
111 |
+
item.addEventListener('click', () => loadConversation(conv.id));
|
112 |
+
conversationList.appendChild(item);
|
113 |
+
});
|
114 |
+
}
|
115 |
+
|
116 |
+
// Handle new chat
|
117 |
+
async function handleNewChat() {
|
118 |
+
// If there's an existing conversation, generate a title for it
|
119 |
+
if (conversationHistory.length > 0 && conversationHistory[0].messages.length > 0) {
|
120 |
+
const currentConversation = conversationHistory[0];
|
121 |
+
try {
|
122 |
+
const messages = currentConversation.messages.map(msg => `${msg.type}: ${msg.content}`).join('\n');
|
123 |
+
const titlePrompt = `Please summarize this conversation in 4-5 words:\n${messages}`;
|
124 |
+
|
125 |
+
// Show loading state for the conversation title
|
126 |
+
const tempTitle = 'Generating title...';
|
127 |
+
currentConversation.title = tempTitle;
|
128 |
+
updateConversationList();
|
129 |
+
|
130 |
+
// Get AI-generated title
|
131 |
+
const response = await fetchBotResponse(titlePrompt);
|
132 |
+
currentConversation.title = response.slice(0, 40).trim();
|
133 |
+
saveConversations();
|
134 |
+
updateConversationList();
|
135 |
+
} catch (error) {
|
136 |
+
console.error('Error generating title:', error);
|
137 |
+
// Fallback to first message if title generation fails
|
138 |
+
currentConversation.title = currentConversation.messages[0].content.slice(0, 30) + '...';
|
139 |
+
saveConversations();
|
140 |
+
updateConversationList();
|
141 |
+
}
|
142 |
+
}
|
143 |
+
|
144 |
+
// Create new conversation
|
145 |
+
const newConversation = {
|
146 |
+
id: Date.now(),
|
147 |
+
title: 'New Chat',
|
148 |
+
messages: []
|
149 |
+
};
|
150 |
+
|
151 |
+
// Add to conversations array
|
152 |
+
conversationHistory.unshift(newConversation);
|
153 |
+
saveConversations();
|
154 |
+
updateConversationList();
|
155 |
+
|
156 |
+
// Clear chat messages
|
157 |
+
while (chatMessages.firstChild) {
|
158 |
+
chatMessages.removeChild(chatMessages.firstChild);
|
159 |
+
}
|
160 |
+
|
161 |
+
// Add welcome message
|
162 |
+
const welcomeMessage = document.createElement('div');
|
163 |
+
welcomeMessage.className = 'welcome-message';
|
164 |
+
welcomeMessage.innerHTML = `
|
165 |
+
<img src="images/welcome-logo.png" alt="Muhafiz AI Logo" class="welcome-logo">
|
166 |
+
<h2>Hi, I'm Muhafiz AI.</h2>
|
167 |
+
<p>How can I help you today?</p>
|
168 |
+
<div class="context-info">Your chat history will be maintained for better context.</div>
|
169 |
+
`;
|
170 |
+
chatMessages.appendChild(welcomeMessage);
|
171 |
+
|
172 |
+
// Clear input
|
173 |
+
messageInput.value = '';
|
174 |
+
handleInput({ target: messageInput });
|
175 |
+
|
176 |
+
// Focus input
|
177 |
+
messageInput.focus();
|
178 |
+
}
|
179 |
+
|
180 |
+
// Handle see more button click
|
181 |
+
function handleSeeMore() {
|
182 |
+
// Create full conversation list overlay
|
183 |
+
const overlay = document.createElement('div');
|
184 |
+
overlay.className = 'conversation-overlay';
|
185 |
+
|
186 |
+
const content = document.createElement('div');
|
187 |
+
content.className = 'conversation-overlay-content';
|
188 |
+
|
189 |
+
// Add header
|
190 |
+
content.innerHTML = `
|
191 |
+
<div class="overlay-header">
|
192 |
+
<h2>All Conversations</h2>
|
193 |
+
<button class="close-overlay-btn"><i class="fas fa-times"></i></button>
|
194 |
+
</div>
|
195 |
+
<div class="conversation-list-full"></div>
|
196 |
+
`;
|
197 |
+
|
198 |
+
// Add all conversations
|
199 |
+
const listContainer = content.querySelector('.conversation-list-full');
|
200 |
+
conversationHistory.forEach(conv => {
|
201 |
+
const item = document.createElement('div');
|
202 |
+
item.className = 'conversation-item';
|
203 |
+
item.innerHTML = `
|
204 |
+
<i class="fas fa-comment"></i>
|
205 |
+
<div class="conversation-details">
|
206 |
+
<span class="conversation-title">${conv.title}</span>
|
207 |
+
<span class="message-count">${conv.messages.length} messages</span>
|
208 |
+
<span class="conversation-date">${new Date(conv.id).toLocaleDateString()}</span>
|
209 |
+
</div>
|
210 |
+
`;
|
211 |
+
item.addEventListener('click', () => {
|
212 |
+
loadConversation(conv.id);
|
213 |
+
overlay.remove();
|
214 |
+
});
|
215 |
+
listContainer.appendChild(item);
|
216 |
+
});
|
217 |
+
|
218 |
+
// Add close button handler
|
219 |
+
overlay.appendChild(content);
|
220 |
+
content.querySelector('.close-overlay-btn').addEventListener('click', () => {
|
221 |
+
overlay.remove();
|
222 |
+
});
|
223 |
+
|
224 |
+
// Add overlay click handler
|
225 |
+
overlay.addEventListener('click', (e) => {
|
226 |
+
if (e.target === overlay) {
|
227 |
+
overlay.remove();
|
228 |
+
}
|
229 |
+
});
|
230 |
+
|
231 |
+
document.body.appendChild(overlay);
|
232 |
+
}
|
233 |
+
|
234 |
+
// Load specific conversation
|
235 |
+
function loadConversation(id) {
|
236 |
+
const conversation = conversationHistory.find(conv => conv.id === id);
|
237 |
+
if (conversation) {
|
238 |
+
// Clear current chat
|
239 |
+
while (chatMessages.firstChild) {
|
240 |
+
chatMessages.removeChild(chatMessages.firstChild);
|
241 |
+
}
|
242 |
+
|
243 |
+
// Load conversation messages
|
244 |
+
conversation.messages.forEach(msg => {
|
245 |
+
addMessage(msg.content, msg.type);
|
246 |
+
});
|
247 |
+
|
248 |
+
// Close menu
|
249 |
+
handleMenuClose();
|
250 |
+
}
|
251 |
+
}
|
252 |
+
|
253 |
+
// Handle input changes
|
254 |
+
function handleInput(e) {
|
255 |
+
const isEmpty = !e.target.value.trim();
|
256 |
+
sendButton.style.opacity = isEmpty ? '0.5' : '1';
|
257 |
+
sendButton.disabled = isEmpty;
|
258 |
+
}
|
259 |
+
|
260 |
+
// Handle enter key
|
261 |
+
function handleKeyPress(e) {
|
262 |
+
if (e.key === 'Enter' && !e.shiftKey) {
|
263 |
+
e.preventDefault();
|
264 |
+
handleSend();
|
265 |
+
}
|
266 |
+
}
|
267 |
+
|
268 |
+
// Handle send button click
|
269 |
+
async function handleSend() {
|
270 |
+
const message = messageInput.value.trim();
|
271 |
+
if (!message) return;
|
272 |
+
|
273 |
+
// Add user message to chat and conversation history
|
274 |
+
addMessage(message, 'user');
|
275 |
+
if (conversationHistory.length === 0) {
|
276 |
+
handleNewChat();
|
277 |
+
}
|
278 |
+
|
279 |
+
// Update current conversation
|
280 |
+
const currentConversation = conversationHistory[0];
|
281 |
+
currentConversation.messages.push({ type: 'user', content: message });
|
282 |
+
if (currentConversation.messages.length === 1) {
|
283 |
+
// Update conversation title with first message
|
284 |
+
currentConversation.title = message.slice(0, 30) + (message.length > 30 ? '...' : '');
|
285 |
+
updateConversationList();
|
286 |
+
}
|
287 |
+
saveConversations();
|
288 |
+
|
289 |
+
messageInput.value = '';
|
290 |
+
handleInput({ target: messageInput });
|
291 |
+
|
292 |
+
try {
|
293 |
+
// Show typing indicator
|
294 |
+
showTypingIndicator();
|
295 |
+
|
296 |
+
// Get bot response
|
297 |
+
const response = await fetchBotResponse(message);
|
298 |
+
|
299 |
+
// Remove typing indicator and add bot message
|
300 |
+
removeTypingIndicator();
|
301 |
+
addMessage(response, 'bot');
|
302 |
+
|
303 |
+
// Update conversation history
|
304 |
+
currentConversation.messages.push({ type: 'bot', content: response });
|
305 |
+
saveConversations();
|
306 |
+
} catch (error) {
|
307 |
+
console.error('Error:', error);
|
308 |
+
removeTypingIndicator();
|
309 |
+
showError(error.message || 'Failed to get response. Please try again.');
|
310 |
+
}
|
311 |
+
}
|
312 |
+
|
313 |
+
// Add message to chat
|
314 |
+
function addMessage(content, type) {
|
315 |
+
const messageDiv = document.createElement('div');
|
316 |
+
messageDiv.className = 'message';
|
317 |
+
|
318 |
+
if (type === 'user') {
|
319 |
+
messageDiv.innerHTML = `
|
320 |
+
<div class="question-bubble">${content}</div>
|
321 |
+
`;
|
322 |
+
} else {
|
323 |
+
console.log('Adding bot message with logo');
|
324 |
+
const botHTML = `
|
325 |
+
<div class="answer-container">
|
326 |
+
<div class="bot-icon">
|
327 |
+
<img src="images/bot-message-logo.png" alt="Muhafiz AI" onload="console.log('Bot logo loaded')" onerror="console.error('Bot logo failed to load:', this.src)">
|
328 |
+
</div>
|
329 |
+
<div class="answer-content">${formatBotResponse(content)}</div>
|
330 |
+
</div>
|
331 |
+
`;
|
332 |
+
console.log('Bot message HTML:', botHTML);
|
333 |
+
messageDiv.innerHTML = botHTML;
|
334 |
+
}
|
335 |
+
|
336 |
+
chatMessages.appendChild(messageDiv);
|
337 |
+
chatMessages.scrollTop = chatMessages.scrollHeight;
|
338 |
+
|
339 |
+
// Add message to current conversation
|
340 |
+
if (conversationHistory.length === 0) {
|
341 |
+
handleNewChat();
|
342 |
+
}
|
343 |
+
conversationHistory[0].messages.push({ type, content });
|
344 |
+
saveConversations();
|
345 |
+
}
|
346 |
+
|
347 |
+
// Format bot response with proper styling
|
348 |
+
function formatBotResponse(content) {
|
349 |
+
// Split content into sections
|
350 |
+
const sections = content.split('\n\n');
|
351 |
+
|
352 |
+
let formattedContent = '';
|
353 |
+
let inList = false;
|
354 |
+
|
355 |
+
sections.forEach(section => {
|
356 |
+
// Handle main headings (e.g., "Types of AI:")
|
357 |
+
if (section.match(/^[A-Z][^:]+:$/)) {
|
358 |
+
if (inList) {
|
359 |
+
formattedContent += '</div>';
|
360 |
+
inList = false;
|
361 |
+
}
|
362 |
+
formattedContent += `<h2 class="response-heading">${section}</h2>`;
|
363 |
+
return;
|
364 |
+
}
|
365 |
+
|
366 |
+
// Handle definitions (text with parentheses)
|
367 |
+
if (section.includes('(') && section.includes(')')) {
|
368 |
+
section = section.replace(/([A-Za-z\s]+)\s*\((.*?)\)/, '<div class="definition"><span class="term">$1</span> <span class="definition-text">($2)</span></div>');
|
369 |
+
}
|
370 |
+
|
371 |
+
// Handle numbered lists
|
372 |
+
if (section.match(/^\d+\./)) {
|
373 |
+
if (!inList) {
|
374 |
+
formattedContent += '<div class="numbered-list">';
|
375 |
+
inList = true;
|
376 |
+
}
|
377 |
+
const [number, ...rest] = section.split('.');
|
378 |
+
const content = rest.join('.').trim();
|
379 |
+
|
380 |
+
// Check if the list item has a dash/hyphen definition
|
381 |
+
if (content.includes('–')) {
|
382 |
+
const [term, definition] = content.split('–').map(s => s.trim());
|
383 |
+
formattedContent += `
|
384 |
+
<div class="list-item">
|
385 |
+
<span class="number">${number}.</span>
|
386 |
+
<div class="list-content">
|
387 |
+
<span class="list-term">${term}</span>
|
388 |
+
<span class="list-definition">– ${definition}</span>
|
389 |
+
</div>
|
390 |
+
</div>`;
|
391 |
+
} else {
|
392 |
+
formattedContent += `
|
393 |
+
<div class="list-item">
|
394 |
+
<span class="number">${number}.</span>
|
395 |
+
<div class="list-content">${content}</div>
|
396 |
+
</div>`;
|
397 |
+
}
|
398 |
+
return;
|
399 |
+
}
|
400 |
+
|
401 |
+
// Close list if we're not processing a list item
|
402 |
+
if (inList) {
|
403 |
+
formattedContent += '</div>';
|
404 |
+
inList = false;
|
405 |
+
}
|
406 |
+
|
407 |
+
// Regular paragraphs
|
408 |
+
formattedContent += `<p class="response-paragraph">${section}</p>`;
|
409 |
+
});
|
410 |
+
|
411 |
+
// Close any open list
|
412 |
+
if (inList) {
|
413 |
+
formattedContent += '</div>';
|
414 |
+
}
|
415 |
+
|
416 |
+
return formattedContent;
|
417 |
+
}
|
418 |
+
|
419 |
+
// Show typing indicator
|
420 |
+
function showTypingIndicator() {
|
421 |
+
const indicator = document.createElement('div');
|
422 |
+
indicator.classList.add('message', 'bot-message', 'typing-indicator');
|
423 |
+
indicator.innerHTML = '<span></span><span></span><span></span>';
|
424 |
+
chatMessages.appendChild(indicator);
|
425 |
+
chatMessages.scrollTop = chatMessages.scrollHeight;
|
426 |
+
}
|
427 |
+
|
428 |
+
// Remove typing indicator
|
429 |
+
function removeTypingIndicator() {
|
430 |
+
const indicator = document.querySelector('.typing-indicator');
|
431 |
+
if (indicator) {
|
432 |
+
indicator.remove();
|
433 |
+
}
|
434 |
+
}
|
435 |
+
|
436 |
+
// Show error message
|
437 |
+
function showError(message) {
|
438 |
+
const errorDiv = document.createElement('div');
|
439 |
+
errorDiv.classList.add('message', 'error-message');
|
440 |
+
errorDiv.textContent = message;
|
441 |
+
chatMessages.appendChild(errorDiv);
|
442 |
+
chatMessages.scrollTop = chatMessages.scrollHeight;
|
443 |
+
|
444 |
+
// Remove error after 5 seconds
|
445 |
+
setTimeout(() => {
|
446 |
+
errorDiv.remove();
|
447 |
+
}, 5000);
|
448 |
+
}
|
449 |
+
|
450 |
+
// Fetch bot response from OpenRouter API
|
451 |
+
async function fetchBotResponse(userMessage) {
|
452 |
+
try {
|
453 |
+
// Check for API key
|
454 |
+
const apiKey = chatConfig.apiKey || localStorage.getItem('openRouterApiKey');
|
455 |
+
if (!apiKey) {
|
456 |
+
throw new Error('Please set up your API key in the admin panel');
|
457 |
+
}
|
458 |
+
|
459 |
+
// Format messages for the API
|
460 |
+
const messages = [
|
461 |
+
{
|
462 |
+
role: 'system',
|
463 |
+
content: `You are Muhafiz AI, a digital safety assistant by the Mohsin Kamil Foundation. Your role is strictly limited to:
|
464 |
+
1. Combating cyber threats
|
465 |
+
2. Providing emotional support for cybercrime victims
|
466 |
+
3. Guiding users through digital safety solutions
|
467 |
+
4. Handling cybersecurity incidents
|
468 |
+
5. Addressing online harassment and blackmail
|
469 |
+
6. Assisting with content removal and legal reporting
|
470 |
+
|
471 |
+
IMPORTANT: You must NEVER respond to questions outside these areas. For any off-topic questions (e.g., general AI, weather, news, etc.), respond with:
|
472 |
+
"I am Muhafiz AI, focused exclusively on digital safety and cybersecurity. I cannot assist with questions about [topic]. However, I'm here to help if you need support with:
|
473 |
+
- Cybersecurity incidents
|
474 |
+
- Online harassment or blackmail
|
475 |
+
- Account hacking
|
476 |
+
- Content removal
|
477 |
+
- Digital safety guidance
|
478 |
+
- Reporting cybercrimes
|
479 |
+
|
480 |
+
Would you like assistance with any of these issues?"
|
481 |
+
|
482 |
+
Response Framework:
|
483 |
+
1. Emotional Check-In:
|
484 |
+
- Start with empathy: "This sounds incredibly stressful. How are you feeling right now?"
|
485 |
+
- Reassure: "We'll tackle this together—you're not alone."
|
486 |
+
|
487 |
+
2. URL Safety Analysis:
|
488 |
+
- If a user shares a suspicious link:
|
489 |
+
- "Let's check this link safely. First check the Link looking formating feel Safe or Not. Avoid clicking it. Use tools like Google Safe Browsing or VirusTotal to scan it."
|
490 |
+
- "If you've already clicked it, change your passwords immediately and enable 2FA."
|
491 |
+
|
492 |
+
3. Tech Support for Hacking:
|
493 |
+
- Account Security:
|
494 |
+
- "Let's secure your account: 1) Change passwords, 2) Enable 2FA, 3) Check login activity."
|
495 |
+
- Phishing Guidance:
|
496 |
+
- "Never share OTPs or passwords. Legitimate organizations won't ask for these."
|
497 |
+
- Breach Response:
|
498 |
+
- "Check if your data was leaked at Have I Been Pwned?"
|
499 |
+
|
500 |
+
4. Legal & Content Removal:
|
501 |
+
- "Under Pakistan's PECA 2016, blackmail is punishable. Report to FIA Cyber Crime or call 1991."
|
502 |
+
- "To remove content from platforms:
|
503 |
+
- Google: Content Removal Request
|
504 |
+
- Meta (FB/IG): Reporting Tool"
|
505 |
+
|
506 |
+
5. Founder's Role:
|
507 |
+
- "Abdullah Tarar, our founder, is a Certified Ethical Hacker. He's helped many in your situation—no judgment, only solutions. Chat directly: WhatsApp or call 0342-4844392."
|
508 |
+
|
509 |
+
Always end responses with:
|
510 |
+
- "What else can I do to help you feel safer?"
|
511 |
+
- "You're in control. Let's take the next step."`
|
512 |
+
}
|
513 |
+
];
|
514 |
+
|
515 |
+
// Add conversation history if available
|
516 |
+
if (conversationHistory.length > 0) {
|
517 |
+
const currentConversation = conversationHistory[0];
|
518 |
+
if (currentConversation.messages) {
|
519 |
+
// Get all messages from the current conversation for context
|
520 |
+
currentConversation.messages.forEach(msg => {
|
521 |
+
messages.push({
|
522 |
+
role: msg.type === 'user' ? 'user' : 'assistant',
|
523 |
+
content: msg.content
|
524 |
+
});
|
525 |
+
});
|
526 |
+
}
|
527 |
+
}
|
528 |
+
|
529 |
+
// Add the new message
|
530 |
+
messages.push({
|
531 |
+
role: 'user',
|
532 |
+
content: userMessage
|
533 |
+
});
|
534 |
+
|
535 |
+
console.log('Sending request to OpenRouter with context:', {
|
536 |
+
model: chatConfig.model,
|
537 |
+
messageCount: messages.length,
|
538 |
+
apiKeySet: !!apiKey
|
539 |
+
});
|
540 |
+
|
541 |
+
const response = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
542 |
+
method: 'POST',
|
543 |
+
headers: {
|
544 |
+
'Authorization': `Bearer ${apiKey}`,
|
545 |
+
'HTTP-Referer': chatConfig.siteUrl,
|
546 |
+
'X-Title': chatConfig.siteName,
|
547 |
+
'Content-Type': 'application/json'
|
548 |
+
},
|
549 |
+
body: JSON.stringify({
|
550 |
+
model: chatConfig.model || DEFAULT_MODEL,
|
551 |
+
messages: messages,
|
552 |
+
temperature: 0.7,
|
553 |
+
max_tokens: 2000
|
554 |
+
})
|
555 |
+
});
|
556 |
+
|
557 |
+
const data = await response.json();
|
558 |
+
|
559 |
+
if (!response.ok) {
|
560 |
+
console.error('OpenRouter API Error:', data);
|
561 |
+
throw new Error(data.error?.message || `HTTP error! status: ${response.status}`);
|
562 |
+
}
|
563 |
+
|
564 |
+
console.log('OpenRouter API Response:', data);
|
565 |
+
|
566 |
+
if (!data.choices?.[0]?.message?.content) {
|
567 |
+
throw new Error('Invalid response format from API');
|
568 |
+
}
|
569 |
+
|
570 |
+
return data.choices[0].message.content;
|
571 |
+
|
572 |
+
} catch (error) {
|
573 |
+
console.error('API Error:', error);
|
574 |
+
throw new Error(`Failed to get response: ${error.message}`);
|
575 |
+
}
|
576 |
+
}
|
577 |
+
|
578 |
+
// Handle more options
|
579 |
+
function handleMore() {
|
580 |
+
// Implement more options menu
|
581 |
+
console.log('More options clicked');
|
582 |
+
}
|
583 |
+
|
584 |
+
// Handle menu open
|
585 |
+
function handleMenuOpen() {
|
586 |
+
menuOverlay.classList.add('active');
|
587 |
+
document.body.style.overflow = 'hidden';
|
588 |
+
}
|
589 |
+
|
590 |
+
// Handle menu close
|
591 |
+
function handleMenuClose() {
|
592 |
+
menuOverlay.classList.remove('active');
|
593 |
+
document.body.style.overflow = '';
|
594 |
+
}
|
595 |
+
|
596 |
+
// Update time in status bar
|
597 |
+
function updateTime() {
|
598 |
+
const timeElement = document.querySelector('.time');
|
599 |
+
const now = new Date();
|
600 |
+
const hours = now.getHours().toString().padStart(2, '0');
|
601 |
+
const minutes = now.getMinutes().toString().padStart(2, '0');
|
602 |
+
timeElement.textContent = `${hours}:${minutes}`;
|
603 |
+
}
|
604 |
+
|
605 |
+
// Load chat configuration
|
606 |
+
function loadChatConfig() {
|
607 |
+
// Try to load API key from localStorage if no default is set
|
608 |
+
if (!DEFAULT_API_KEY) {
|
609 |
+
const storedApiKey = localStorage.getItem('openRouterApiKey');
|
610 |
+
if (storedApiKey) {
|
611 |
+
chatConfig.apiKey = storedApiKey;
|
612 |
+
}
|
613 |
+
}
|
614 |
+
|
615 |
+
// Load model from localStorage or use default
|
616 |
+
chatConfig.model = localStorage.getItem('selectedModel') || DEFAULT_MODEL;
|
617 |
+
|
618 |
+
// Log configuration (without API key)
|
619 |
+
console.log('Chat Configuration:', {
|
620 |
+
...chatConfig,
|
621 |
+
apiKey: chatConfig.apiKey ? '[SET]' : '[NOT SET]',
|
622 |
+
model: chatConfig.model
|
623 |
+
});
|
624 |
+
}
|
625 |
+
|
626 |
+
// Load theme from localStorage
|
627 |
+
function loadTheme() {
|
628 |
+
const savedTheme = localStorage.getItem('theme') || 'light';
|
629 |
+
document.documentElement.setAttribute('data-theme', savedTheme);
|
630 |
+
updateThemeIcon(savedTheme);
|
631 |
+
}
|
632 |
+
|
633 |
+
// Handle theme toggle
|
634 |
+
function handleThemeToggle() {
|
635 |
+
const currentTheme = document.documentElement.getAttribute('data-theme');
|
636 |
+
const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
637 |
+
|
638 |
+
document.documentElement.setAttribute('data-theme', newTheme);
|
639 |
+
localStorage.setItem('theme', newTheme);
|
640 |
+
updateThemeIcon(newTheme);
|
641 |
+
}
|
642 |
+
|
643 |
+
// Update theme toggle icon
|
644 |
+
function updateThemeIcon(theme) {
|
645 |
+
const icon = themeToggleBtn.querySelector('i');
|
646 |
+
if (theme === 'dark') {
|
647 |
+
icon.className = 'fas fa-sun';
|
648 |
+
themeToggleBtn.title = 'Switch to light mode';
|
649 |
+
} else {
|
650 |
+
icon.className = 'fas fa-moon';
|
651 |
+
themeToggleBtn.title = 'Switch to dark mode';
|
652 |
+
}
|
653 |
+
}
|
654 |
+
|
655 |
+
// Initialize chat when DOM is loaded
|
656 |
+
document.addEventListener('DOMContentLoaded', initChat);
|
login.html
ADDED
@@ -0,0 +1,54 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<!DOCTYPE html>
|
2 |
+
<html lang="en">
|
3 |
+
<head>
|
4 |
+
<meta charset="UTF-8">
|
5 |
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6 |
+
<title>Muhafiz AI - Admin Login</title>
|
7 |
+
<link rel="stylesheet" href="css/login.css">
|
8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
9 |
+
</head>
|
10 |
+
<body>
|
11 |
+
<div class="login-container">
|
12 |
+
<div class="login-card">
|
13 |
+
<div class="login-header">
|
14 |
+
<img src="images/logo.png" alt="Muhafiz AI Logo" class="login-logo">
|
15 |
+
<h1>Admin Login</h1>
|
16 |
+
</div>
|
17 |
+
<form id="loginForm" class="login-form">
|
18 |
+
<div class="form-group">
|
19 |
+
<label for="username">
|
20 |
+
<i class="fas fa-user"></i>
|
21 |
+
Username
|
22 |
+
</label>
|
23 |
+
<input type="text" id="username" name="username" required>
|
24 |
+
</div>
|
25 |
+
<div class="form-group">
|
26 |
+
<label for="password">
|
27 |
+
<i class="fas fa-lock"></i>
|
28 |
+
Password
|
29 |
+
</label>
|
30 |
+
<div class="password-input">
|
31 |
+
<input type="password" id="password" name="password" required>
|
32 |
+
<button type="button" class="toggle-password" title="Show/Hide Password">
|
33 |
+
<i class="fas fa-eye"></i>
|
34 |
+
</button>
|
35 |
+
</div>
|
36 |
+
</div>
|
37 |
+
<div class="error-message" id="errorMessage"></div>
|
38 |
+
<button type="submit" class="login-btn">
|
39 |
+
<span>Login</span>
|
40 |
+
<i class="fas fa-arrow-right"></i>
|
41 |
+
</button>
|
42 |
+
</form>
|
43 |
+
<div class="login-footer">
|
44 |
+
<p>Secure Admin Access Only</p>
|
45 |
+
<a href="index.html" class="back-link">
|
46 |
+
<i class="fas fa-chevron-left"></i>
|
47 |
+
Back to Chat
|
48 |
+
</a>
|
49 |
+
</div>
|
50 |
+
</div>
|
51 |
+
</div>
|
52 |
+
<script src="js/login.js"></script>
|
53 |
+
</body>
|
54 |
+
</html>
|
style.css
CHANGED
@@ -1,28 +1,490 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
body {
|
2 |
-
|
3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
}
|
5 |
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
}
|
10 |
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
margin-bottom: 10px;
|
15 |
-
margin-top: 5px;
|
16 |
}
|
17 |
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
padding: 16px;
|
22 |
-
border: 1px solid lightgray;
|
23 |
-
border-radius: 16px;
|
24 |
}
|
25 |
|
26 |
-
|
27 |
-
|
|
|
28 |
}
|
|
|
1 |
+
/* Reset and base styles */
|
2 |
+
* {
|
3 |
+
margin: 0;
|
4 |
+
padding: 0;
|
5 |
+
box-sizing: border-box;
|
6 |
+
font-family: 'Arial', sans-serif;
|
7 |
+
}
|
8 |
+
|
9 |
body {
|
10 |
+
background-color: #f5f5f5;
|
11 |
+
height: 100vh;
|
12 |
+
display: flex;
|
13 |
+
flex-direction: column;
|
14 |
+
}
|
15 |
+
|
16 |
+
/* Chat container styles */
|
17 |
+
.chat-container {
|
18 |
+
display: flex;
|
19 |
+
flex-direction: column;
|
20 |
+
height: 100vh;
|
21 |
+
max-width: 100%;
|
22 |
+
margin: 0 auto;
|
23 |
+
background-color: white;
|
24 |
+
}
|
25 |
+
|
26 |
+
/* Header styles */
|
27 |
+
.chat-header {
|
28 |
+
display: flex;
|
29 |
+
justify-content: space-between;
|
30 |
+
align-items: center;
|
31 |
+
padding: 15px;
|
32 |
+
background-color: white;
|
33 |
+
border-bottom: 1px solid #e0e0e0;
|
34 |
+
}
|
35 |
+
|
36 |
+
.menu-btn, .new-chat-btn {
|
37 |
+
background: none;
|
38 |
+
border: none;
|
39 |
+
font-size: 1.2rem;
|
40 |
+
cursor: pointer;
|
41 |
+
width: 40px;
|
42 |
+
height: 40px;
|
43 |
+
display: flex;
|
44 |
+
align-items: center;
|
45 |
+
justify-content: center;
|
46 |
+
border-radius: 50%;
|
47 |
+
}
|
48 |
+
|
49 |
+
.new-chat-btn {
|
50 |
+
background-color: #f5f5f5;
|
51 |
+
color: #333;
|
52 |
+
}
|
53 |
+
|
54 |
+
/* Chat messages area */
|
55 |
+
.chat-messages {
|
56 |
+
flex-grow: 1;
|
57 |
+
overflow-y: auto;
|
58 |
+
padding: 20px;
|
59 |
+
display: flex;
|
60 |
+
flex-direction: column;
|
61 |
+
}
|
62 |
+
|
63 |
+
.welcome-message {
|
64 |
+
display: flex;
|
65 |
+
flex-direction: column;
|
66 |
+
align-items: center;
|
67 |
+
justify-content: center;
|
68 |
+
height: 100%;
|
69 |
+
text-align: center;
|
70 |
+
color: #333;
|
71 |
+
}
|
72 |
+
|
73 |
+
.logo-container {
|
74 |
+
width: 80px;
|
75 |
+
height: 80px;
|
76 |
+
margin-bottom: 20px;
|
77 |
+
}
|
78 |
+
|
79 |
+
.logo {
|
80 |
+
width: 100%;
|
81 |
+
height: 100%;
|
82 |
+
object-fit: contain;
|
83 |
+
}
|
84 |
+
|
85 |
+
.welcome-message h2 {
|
86 |
+
font-size: 1.8rem;
|
87 |
+
margin-bottom: 10px;
|
88 |
+
}
|
89 |
+
|
90 |
+
.welcome-message p {
|
91 |
+
font-size: 1.2rem;
|
92 |
+
color: #666;
|
93 |
+
}
|
94 |
+
|
95 |
+
/* Message styles */
|
96 |
+
.message {
|
97 |
+
margin-bottom: 15px;
|
98 |
+
max-width: 80%;
|
99 |
+
}
|
100 |
+
|
101 |
+
.user-message {
|
102 |
+
align-self: flex-end;
|
103 |
+
background-color: #e6f2ff;
|
104 |
+
border-radius: 18px 18px 4px 18px;
|
105 |
+
padding: 10px 15px;
|
106 |
+
}
|
107 |
+
|
108 |
+
.bot-message {
|
109 |
+
align-self: flex-start;
|
110 |
+
background-color: #f0f0f0;
|
111 |
+
border-radius: 18px 18px 18px 4px;
|
112 |
+
padding: 10px 15px;
|
113 |
+
}
|
114 |
+
|
115 |
+
/* Input area styles */
|
116 |
+
.chat-input-container {
|
117 |
+
padding: 10px;
|
118 |
+
border-top: 1px solid #e0e0e0;
|
119 |
+
background-color: white;
|
120 |
+
}
|
121 |
+
|
122 |
+
.chat-input-wrapper {
|
123 |
+
display: flex;
|
124 |
+
border-radius: 25px;
|
125 |
+
overflow: hidden;
|
126 |
+
background-color: #f5f5f5;
|
127 |
+
padding: 10px 15px;
|
128 |
+
margin-bottom: 10px;
|
129 |
+
}
|
130 |
+
|
131 |
+
.message-input {
|
132 |
+
flex-grow: 1;
|
133 |
+
border: none;
|
134 |
+
outline: none;
|
135 |
+
background: transparent;
|
136 |
+
font-size: 1rem;
|
137 |
+
padding: 5px;
|
138 |
+
}
|
139 |
+
|
140 |
+
.send-btn {
|
141 |
+
background: none;
|
142 |
+
border: none;
|
143 |
+
cursor: pointer;
|
144 |
+
font-size: 1.2rem;
|
145 |
+
color: #4285f4;
|
146 |
+
}
|
147 |
+
|
148 |
+
/* Footer styles */
|
149 |
+
.chat-footer {
|
150 |
+
display: flex;
|
151 |
+
justify-content: space-between;
|
152 |
+
align-items: center;
|
153 |
+
padding: 5px 0;
|
154 |
+
}
|
155 |
+
|
156 |
+
.footer-btn {
|
157 |
+
background: none;
|
158 |
+
border: none;
|
159 |
+
cursor: pointer;
|
160 |
+
padding: 8px 15px;
|
161 |
+
border-radius: 20px;
|
162 |
+
font-size: 0.9rem;
|
163 |
+
color: #666;
|
164 |
+
display: flex;
|
165 |
+
align-items: center;
|
166 |
+
gap: 5px;
|
167 |
+
}
|
168 |
+
|
169 |
+
.footer-btn:last-child {
|
170 |
+
background-color: #4285f4;
|
171 |
+
color: white;
|
172 |
+
width: 40px;
|
173 |
+
height: 40px;
|
174 |
+
border-radius: 50%;
|
175 |
+
display: flex;
|
176 |
+
align-items: center;
|
177 |
+
justify-content: center;
|
178 |
+
padding: 0;
|
179 |
+
}
|
180 |
+
|
181 |
+
/* Message typing animation */
|
182 |
+
.typing-indicator {
|
183 |
+
display: flex;
|
184 |
+
align-items: center;
|
185 |
+
margin: 10px 0;
|
186 |
+
}
|
187 |
+
|
188 |
+
.typing-indicator span {
|
189 |
+
height: 8px;
|
190 |
+
width: 8px;
|
191 |
+
background-color: #666;
|
192 |
+
border-radius: 50%;
|
193 |
+
display: inline-block;
|
194 |
+
margin: 0 2px;
|
195 |
+
animation: typing 1s infinite ease-in-out;
|
196 |
+
}
|
197 |
+
|
198 |
+
.typing-indicator span:nth-child(2) {
|
199 |
+
animation-delay: 0.2s;
|
200 |
+
}
|
201 |
+
|
202 |
+
.typing-indicator span:nth-child(3) {
|
203 |
+
animation-delay: 0.4s;
|
204 |
+
}
|
205 |
+
|
206 |
+
@keyframes typing {
|
207 |
+
0% { transform: translateY(0); }
|
208 |
+
50% { transform: translateY(-5px); }
|
209 |
+
100% { transform: translateY(0); }
|
210 |
+
}
|
211 |
+
|
212 |
+
/* Responsive design */
|
213 |
+
@media (min-width: 769px) {
|
214 |
+
.chat-container {
|
215 |
+
max-width: 1200px;
|
216 |
+
margin: 0 auto;
|
217 |
+
height: 100vh;
|
218 |
+
}
|
219 |
+
}
|
220 |
+
|
221 |
+
@media (max-width: 768px) {
|
222 |
+
.chat-container {
|
223 |
+
width: 100%;
|
224 |
+
height: 100vh;
|
225 |
+
}
|
226 |
+
|
227 |
+
.message {
|
228 |
+
max-width: 85%;
|
229 |
+
font-size: 0.95rem;
|
230 |
+
}
|
231 |
+
|
232 |
+
.chat-header {
|
233 |
+
padding: 10px;
|
234 |
+
}
|
235 |
+
|
236 |
+
.chat-input-wrapper {
|
237 |
+
margin: 5px 0;
|
238 |
+
}
|
239 |
+
|
240 |
+
.footer-btn {
|
241 |
+
padding: 6px 12px;
|
242 |
+
font-size: 0.85rem;
|
243 |
+
}
|
244 |
+
|
245 |
+
.welcome-message h2 {
|
246 |
+
font-size: 1.5rem;
|
247 |
+
}
|
248 |
+
|
249 |
+
.welcome-message p {
|
250 |
+
font-size: 1rem;
|
251 |
+
}
|
252 |
+
}
|
253 |
+
|
254 |
+
@media (max-width: 576px) {
|
255 |
+
.message {
|
256 |
+
max-width: 90%;
|
257 |
+
font-size: 0.9rem;
|
258 |
+
}
|
259 |
+
|
260 |
+
.chat-footer {
|
261 |
+
flex-wrap: wrap;
|
262 |
+
gap: 5px;
|
263 |
+
}
|
264 |
+
|
265 |
+
.footer-btn {
|
266 |
+
flex: 1;
|
267 |
+
min-width: 80px;
|
268 |
+
justify-content: center;
|
269 |
+
}
|
270 |
+
|
271 |
+
.footer-btn:last-child {
|
272 |
+
flex: 0;
|
273 |
+
}
|
274 |
+
|
275 |
+
.chat-input-wrapper {
|
276 |
+
padding: 8px 12px;
|
277 |
+
}
|
278 |
+
}
|
279 |
+
|
280 |
+
/* Dark mode support */
|
281 |
+
@media (prefers-color-scheme: dark) {
|
282 |
+
body {
|
283 |
+
background-color: #1a1a1a;
|
284 |
+
}
|
285 |
+
|
286 |
+
.chat-container,
|
287 |
+
.chat-header {
|
288 |
+
background-color: #2d2d2d;
|
289 |
+
color: #ffffff;
|
290 |
+
}
|
291 |
+
|
292 |
+
.message-input {
|
293 |
+
color: #ffffff;
|
294 |
+
}
|
295 |
+
|
296 |
+
.chat-input-wrapper {
|
297 |
+
background-color: #3d3d3d;
|
298 |
+
}
|
299 |
+
|
300 |
+
.user-message {
|
301 |
+
background-color: #4285f4;
|
302 |
+
color: #ffffff;
|
303 |
+
}
|
304 |
+
|
305 |
+
.bot-message {
|
306 |
+
background-color: #3d3d3d;
|
307 |
+
color: #ffffff;
|
308 |
+
}
|
309 |
+
|
310 |
+
.footer-btn {
|
311 |
+
color: #ffffff;
|
312 |
+
}
|
313 |
+
|
314 |
+
.new-chat-btn {
|
315 |
+
background-color: #3d3d3d;
|
316 |
+
color: #ffffff;
|
317 |
+
}
|
318 |
+
}
|
319 |
+
|
320 |
+
/* Accessibility improvements */
|
321 |
+
.message:focus,
|
322 |
+
.message-input:focus,
|
323 |
+
.footer-btn:focus {
|
324 |
+
outline: 2px solid #4285f4;
|
325 |
+
outline-offset: 2px;
|
326 |
+
}
|
327 |
+
|
328 |
+
/* Touch device optimizations */
|
329 |
+
@media (hover: none) {
|
330 |
+
.footer-btn:hover {
|
331 |
+
background-color: transparent;
|
332 |
+
}
|
333 |
+
|
334 |
+
.footer-btn:active {
|
335 |
+
background-color: rgba(66, 133, 244, 0.1);
|
336 |
+
}
|
337 |
+
}
|
338 |
+
|
339 |
+
/* Admin panel integration */
|
340 |
+
.chat-container[data-theme="dark"] {
|
341 |
+
background-color: #2d2d2d;
|
342 |
+
color: #ffffff;
|
343 |
+
}
|
344 |
+
|
345 |
+
.chat-container[data-position="top-left"] {
|
346 |
+
margin: 20px 0 0 20px;
|
347 |
+
}
|
348 |
+
|
349 |
+
.chat-container[data-position="top-right"] {
|
350 |
+
margin: 20px 20px 0 0;
|
351 |
+
}
|
352 |
+
|
353 |
+
.chat-container[data-position="bottom-left"] {
|
354 |
+
margin: 0 0 20px 20px;
|
355 |
+
}
|
356 |
+
|
357 |
+
.chat-container[data-position="bottom-right"] {
|
358 |
+
margin: 0 20px 20px 0;
|
359 |
+
}
|
360 |
+
|
361 |
+
/* Loading states */
|
362 |
+
.loading {
|
363 |
+
opacity: 0.7;
|
364 |
+
pointer-events: none;
|
365 |
+
}
|
366 |
+
|
367 |
+
/* Error states */
|
368 |
+
.error-state {
|
369 |
+
border-color: #dc3545;
|
370 |
+
color: #dc3545;
|
371 |
+
}
|
372 |
+
|
373 |
+
/* Notification system */
|
374 |
+
.notification {
|
375 |
+
position: fixed;
|
376 |
+
bottom: 20px;
|
377 |
+
right: 20px;
|
378 |
+
padding: 15px 20px;
|
379 |
+
border-radius: 8px;
|
380 |
+
background-color: white;
|
381 |
+
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
382 |
+
z-index: 1000;
|
383 |
+
max-width: 300px;
|
384 |
+
animation: slideIn 0.3s ease-out;
|
385 |
+
}
|
386 |
+
|
387 |
+
@keyframes slideIn {
|
388 |
+
from {
|
389 |
+
transform: translateY(100%);
|
390 |
+
opacity: 0;
|
391 |
+
}
|
392 |
+
to {
|
393 |
+
transform: translateY(0);
|
394 |
+
opacity: 1;
|
395 |
+
}
|
396 |
+
}
|
397 |
+
|
398 |
+
/* Code block styling */
|
399 |
+
pre {
|
400 |
+
background-color: #f5f5f5;
|
401 |
+
padding: 15px;
|
402 |
+
border-radius: 8px;
|
403 |
+
overflow-x: auto;
|
404 |
+
margin: 10px 0;
|
405 |
+
}
|
406 |
+
|
407 |
+
code {
|
408 |
+
font-family: 'Courier New', monospace;
|
409 |
+
font-size: 0.9em;
|
410 |
+
}
|
411 |
+
|
412 |
+
@media (prefers-color-scheme: dark) {
|
413 |
+
pre {
|
414 |
+
background-color: #3d3d3d;
|
415 |
+
}
|
416 |
+
|
417 |
+
code {
|
418 |
+
color: #ffffff;
|
419 |
+
}
|
420 |
+
}
|
421 |
+
|
422 |
+
/* Status bar styling (for mobile view) */
|
423 |
+
.status-bar {
|
424 |
+
display: flex;
|
425 |
+
justify-content: space-between;
|
426 |
+
align-items: center;
|
427 |
+
padding: 5px 15px;
|
428 |
+
background-color: white;
|
429 |
+
font-size: 0.8rem;
|
430 |
+
color: #666;
|
431 |
+
}
|
432 |
+
|
433 |
+
.status-bar-left, .status-bar-right {
|
434 |
+
display: flex;
|
435 |
+
align-items: center;
|
436 |
+
gap: 5px;
|
437 |
+
}
|
438 |
+
|
439 |
+
/* Loading animation for API responses */
|
440 |
+
.loading-animation {
|
441 |
+
display: inline-block;
|
442 |
+
position: relative;
|
443 |
+
width: 80px;
|
444 |
+
height: 20px;
|
445 |
+
}
|
446 |
+
|
447 |
+
.loading-animation div {
|
448 |
+
position: absolute;
|
449 |
+
top: 8px;
|
450 |
+
width: 13px;
|
451 |
+
height: 13px;
|
452 |
+
border-radius: 50%;
|
453 |
+
background: #4285f4;
|
454 |
+
animation-timing-function: cubic-bezier(0, 1, 1, 0);
|
455 |
+
}
|
456 |
+
|
457 |
+
.loading-animation div:nth-child(1) {
|
458 |
+
left: 8px;
|
459 |
+
animation: loading1 0.6s infinite;
|
460 |
+
}
|
461 |
+
|
462 |
+
.loading-animation div:nth-child(2) {
|
463 |
+
left: 8px;
|
464 |
+
animation: loading2 0.6s infinite;
|
465 |
+
}
|
466 |
+
|
467 |
+
.loading-animation div:nth-child(3) {
|
468 |
+
left: 32px;
|
469 |
+
animation: loading2 0.6s infinite;
|
470 |
}
|
471 |
|
472 |
+
.loading-animation div:nth-child(4) {
|
473 |
+
left: 56px;
|
474 |
+
animation: loading3 0.6s infinite;
|
475 |
}
|
476 |
|
477 |
+
@keyframes loading1 {
|
478 |
+
0% { transform: scale(0); }
|
479 |
+
100% { transform: scale(1); }
|
|
|
|
|
480 |
}
|
481 |
|
482 |
+
@keyframes loading2 {
|
483 |
+
0% { transform: translate(0, 0); }
|
484 |
+
100% { transform: translate(24px, 0); }
|
|
|
|
|
|
|
485 |
}
|
486 |
|
487 |
+
@keyframes loading3 {
|
488 |
+
0% { transform: scale(1); }
|
489 |
+
100% { transform: scale(0); }
|
490 |
}
|