diff --git a/server/.env.example b/server/.env.example
new file mode 100644
index 0000000..ae680ee
--- /dev/null
+++ b/server/.env.example
@@ -0,0 +1,5 @@
+MONGO_URI=mongodb://localhost:27017/finveda
+PORT=5000
+EMAIL_ID=
+PASS_KEY=
+ADMIN_EMAIL_ID=
\ No newline at end of file
diff --git a/server/.gitignore b/server/.gitignore
new file mode 100644
index 0000000..aff6b1d
--- /dev/null
+++ b/server/.gitignore
@@ -0,0 +1,6 @@
+node_modules
+./node_modules
+.env
+package-lock.json
+uploads
+./uploads
\ No newline at end of file
diff --git a/server/app.js b/server/app.js
new file mode 100644
index 0000000..9b2ee27
--- /dev/null
+++ b/server/app.js
@@ -0,0 +1,22 @@
+import express from 'express';
+import dotenv from 'dotenv';
+import connectDB from './utils/db.js';
+import cors from 'cors';
+import contactRoutes from './routes/contactRoutes.js';
+
+dotenv.config();
+const app = express();
+connectDB();
+
+app.use(express.json());
+
+// to avoid cross-origin error
+app.use(cors());
+
+// Serve static files from the uploads directory
+app.use('/api/contact', contactRoutes);
+
+const PORT = process.env.PORT || 5000;
+app.listen(PORT, () => {
+ console.log(`Server running on port ${PORT}`);
+});
diff --git a/server/controllers/contactController.js b/server/controllers/contactController.js
new file mode 100644
index 0000000..2076e67
--- /dev/null
+++ b/server/controllers/contactController.js
@@ -0,0 +1,28 @@
+import Contact from '../model/contact.js';
+import { sendMailToAdmin } from '../utils/sendMail.js';
+
+export async function saveContact(req, res) {
+ try {
+ const { fullName, phoneNumber, email, message } = req.body;
+
+ if (!fullName || !phoneNumber || !email || !message) {
+ return res.status(400).json({ message: 'All fields are required.' });
+ }
+
+ const newContact = new Contact({ fullName, phoneNumber, email, message });
+ sendMailToAdmin(newContact);
+
+ await newContact.save();
+
+ res
+ .status(201)
+ .json({ message: 'Contact form submitted successfully!', newContact });
+ } catch (error) {
+ console.error('Error saving contact form:', error);
+ res.status(500).json({ message: 'Failed to submit contact form.', error });
+ }
+}
+
+export async function getContact(req, res) {
+ res.send('hello contact');
+}
diff --git a/server/model/contact.js b/server/model/contact.js
new file mode 100644
index 0000000..9cb2189
--- /dev/null
+++ b/server/model/contact.js
@@ -0,0 +1,34 @@
+import mongoose from 'mongoose';
+
+const contactSchema = new mongoose.Schema({
+ fullName: {
+ type: String,
+ required: true,
+ trim: true,
+ },
+ phoneNumber: {
+ type: String,
+ required: true,
+ trim: true,
+ match: [/^\d{10}$/, 'Please enter a valid 10-digit phone number'],
+ },
+ email: {
+ type: String,
+ required: true,
+ trim: true,
+ match: [/^\S+@\S+\.\S+$/, 'Please enter a valid email address'],
+ },
+ message: {
+ type: String,
+ required: true,
+ trim: true,
+ },
+ createdAt: {
+ type: Date,
+ default: Date.now,
+ },
+});
+
+const Contact = mongoose.model('Contact', contactSchema);
+
+export default Contact;
diff --git a/server/package.json b/server/package.json
new file mode 100644
index 0000000..813bb3b
--- /dev/null
+++ b/server/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "server",
+ "version": "1.0.0",
+ "main": "app.js",
+ "type": "module",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "finveda"
+ ],
+ "author": "",
+ "license": "ISC",
+ "dependencies": {
+ "cors": "^2.8.5",
+ "dotenv": "^16.4.5",
+ "express": "^4.21.1",
+ "mongoose": "^8.8.0",
+ "multer": "^1.4.5-lts.1",
+ "nodemailer": "^6.9.16",
+ "nodemon": "^3.1.7"
+ },
+ "description": ""
+}
diff --git a/server/routes/contactRoutes.js b/server/routes/contactRoutes.js
new file mode 100644
index 0000000..3140aad
--- /dev/null
+++ b/server/routes/contactRoutes.js
@@ -0,0 +1,8 @@
+import express from 'express';
+const router = express.Router();
+import { getContact, saveContact } from '../controllers/contactController.js';
+
+router.post('/saveContact', saveContact);
+router.get('/saveContact', getContact);
+
+export default router;
diff --git a/server/utils/db.js b/server/utils/db.js
new file mode 100644
index 0000000..c951c34
--- /dev/null
+++ b/server/utils/db.js
@@ -0,0 +1,15 @@
+import mongoose from 'mongoose';
+import dotenv from 'dotenv';
+dotenv.config();
+
+const connectDB = async () => {
+ try {
+ await mongoose.connect(process.env.MONGO_URI);
+ console.log('MongoDB Connected');
+ } catch (error) {
+ console.error('Database connection error:', error);
+ process.exit(1);
+ }
+};
+
+export default connectDB;
diff --git a/server/utils/sendMail.js b/server/utils/sendMail.js
new file mode 100644
index 0000000..3b5c100
--- /dev/null
+++ b/server/utils/sendMail.js
@@ -0,0 +1,71 @@
+import nodemailer from 'nodemailer';
+import 'dotenv/config';
+
+const sendMailToAdmin = userdata => {
+ const transporter = nodemailer.createTransport({
+ service: 'gmail',
+ host: 'smtp.gmail.com',
+ port: 587,
+ secure: false, // Use `true` for port 465, `false` for all other ports
+ auth: {
+ user: process.env.EMAIL_ID, // Email ID to send the mail
+ pass: process.env.PASS_KEY, // Passkey
+ },
+ });
+
+ async function main() {
+ await transporter.sendMail({
+ from: {
+ name: `GLASSYUI Contact Form - ${new Date().toLocaleString()}`,
+ address: process.env.EMAIL_ID,
+ }, // sender address
+ to: process.env.ADMIN_EMAIL_ID, // list of receivers
+ subject: 'New Contact Form Submission from GLASSYUI ✔', // Subject line
+ text: 'GLASSYUI Contact Form Submission', // plain text body
+ html: `
+
+ GLASSYUI Contact Form Submission
+
+
+
+
+
+ Field
+
+
+ Value
+
+
+
+
+
+ Name
+ ${userdata.fullName}
+
+
+ Phone
+ ${userdata.phoneNumber}
+
+
+ Email
+ ${userdata.email}
+
+
+ Message
+ ${userdata.message}
+
+
+ Submitted At
+ ${new Date().toLocaleString()}
+
+
+
+
`, // html body
+ });
+ }
+
+ main().catch(console.error);
+};
+
+// Export as a named export
+export { sendMailToAdmin };
diff --git a/src/App.tsx b/src/App.tsx
index 67b6847..aff2a75 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -43,7 +43,10 @@ import Statistic from './components/StatisticDetails';
import GalleryDetailsPage from './components/GalleryDetailsPage';
import SpinnerDetailsPage from './components/SpinnerDetailsPage';
import ProductCardDetailsPage from './components/ProductCardDetailsPage';
-
+ import ContactUs from './components/ContactUs';
+ import AiChatbot from './components/AIChatbot';
+ import { TermsOfUse } from './components/TermsOfUse';
+
const ThemeToggle: React.FC = () => {
const [theme, setTheme] = useState(localStorage.getItem('theme') || 'light');
@@ -74,6 +77,7 @@ const App: React.FC = () => {
return (
+
{/* */}
{/* Add the ScrollProgressBar component here */}
@@ -112,14 +116,18 @@ const App: React.FC = () => {
} />
} />
} />
- } />
+ } />
+ } />
+ } />
{/* */}
);
};
-// const ConditionalFooter: React.FC = () => {
-// const location = useLocation();
-// return location.pathname === '/' ? : null;
-// };
+
+const ConditionalFooter: React.FC = () => {
+ const location = useLocation();
+ return location.pathname === '/' ? null : ;
+};
+
export default App;
diff --git a/src/components/AIChatbot.tsx b/src/components/AIChatbot.tsx
new file mode 100644
index 0000000..3dcacbc
--- /dev/null
+++ b/src/components/AIChatbot.tsx
@@ -0,0 +1,33 @@
+import React, { useEffect } from 'react';
+
+const AiChatbot: React.FC = () => {
+ useEffect(() => {
+ const script = document.createElement('script');
+ script.src = 'https://www.chatbase.co/embed.min.js';
+ script.defer = true;
+ script.async = true;
+ script.setAttribute('chatbotId', 'NwunJFmeijfG8mzeXqdPw');
+ script.setAttribute('domain', 'www.chatbase.co');
+
+ const chatbotConfig = document.createElement('script');
+ chatbotConfig.innerHTML = `
+ window.embeddedChatbotConfig = {
+ chatbotId: "NwunJFmeijfG8mzeXqdPw",
+ domain: "www.chatbase.co"
+ };
+ `;
+
+ document.body.appendChild(chatbotConfig);
+ document.body.appendChild(script);
+
+ // Clean up the scripts on component unmount
+ return () => {
+ document.body.removeChild(chatbotConfig);
+ document.body.removeChild(script);
+ };
+ }, []);
+
+ return null; // No visual elements needed in this component
+};
+
+export default AiChatbot;
diff --git a/src/components/BackToTop.tsx b/src/components/BackToTop.tsx
index b8ad91a..6b4228d 100644
--- a/src/components/BackToTop.tsx
+++ b/src/components/BackToTop.tsx
@@ -34,7 +34,7 @@ const BackToTopButton: React.FC = () => {
{isVisible && (
↑
diff --git a/src/components/ContactUs.tsx b/src/components/ContactUs.tsx
new file mode 100644
index 0000000..772344b
--- /dev/null
+++ b/src/components/ContactUs.tsx
@@ -0,0 +1,203 @@
+import React, { ChangeEvent, FormEvent } from 'react';
+import { useState } from 'react';
+
+const ContactUs = () => {
+ interface FormData {
+ fullName: string;
+ phoneNumber: string;
+ email: string;
+ message: string;
+ }
+
+ const [formData, setFormData] = useState({
+ fullName: '',
+ phoneNumber: '',
+ email: '',
+ message: '',
+ });
+
+ const handleChange = (
+ e: ChangeEvent,
+ ) => {
+ setFormData({ ...formData, [e.target.name]: e.target.value });
+ };
+
+ const handleSubmit = async (e: FormEvent) => {
+ e.preventDefault();
+
+ try {
+ const response = await fetch(
+ 'http://localhost:5000/api/contact/saveContact',
+ {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(formData),
+ },
+ );
+
+ if (!response.ok) {
+ throw new Error('Something went wrong!');
+ }
+
+ alert('Message Sent Successfully!');
+ setFormData({ fullName: '', phoneNumber: '', email: '', message: '' });
+ } catch (error) {
+ console.error(error);
+ alert('Failed to send message. Please try again later.');
+ }
+ };
+
+ return (
+
+ {/* Left-side Information with glassmorphism effect */}
+
+
+
+ Welcome to GlassyUI-Components!
+
+
+ This open-source library features stunning React components designed
+ with a captivating glassmorphism effect, perfect for giving your web
+ applications a modern and sleek design.
+
+
+
+ Email: contact@glassyui.com
+
+
+ Phone: +123-456-7890
+
+
+ Website: www.glassyui.com
+
+
+
+
✨ Features
+
+ Glassmorphism-themed React components
+ Customizable styles with SCSS
+ Beginner-friendly and easy to contribute
+ Modular and reusable components
+
+
+
+
+
+ {/* Form Section */}
+
+
+ );
+};
+
+export default ContactUs;
diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx
index 46c9455..35c8db7 100644
--- a/src/components/Footer.tsx
+++ b/src/components/Footer.tsx
@@ -1,8 +1,35 @@
-import React from 'react';
+import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import GoogleTranslate from './GoogleTranslator';
-
+import { FormEvent } from 'react';
const Footer: React.FC = () => {
+ const [name, setName] = useState('');
+ const [email, setEmail] = useState('');
+
+ const handleSubmit = async (e: FormEvent) => {
+ e.preventDefault();
+ console.log(name + ' ' + email);
+ // try {
+ // const response = await fetch("http://localhost:5000/api/newsletter/subscribe", {
+ // method: "POST",
+ // headers: {
+ // "Content-Type": "application/json",
+ // },
+ // body: JSON.stringify({ name, email }),
+ // });
+
+ // if (response.ok) {
+ // alert("Subscription successful!");
+ // setName("");
+ // setEmail("");
+ // } else {
+ // alert("Failed to subscribe.");
+ // }
+ // } catch (error) {
+ // alert("An error occurred. Please try again.");
+ // }
+ };
+
return (
<>
@@ -24,6 +51,9 @@ const Footer: React.FC = () => {
About
+
+ Terms Of Use
+
@@ -35,12 +65,10 @@ const Footer: React.FC = () => {
.glass-footer {
backdrop-filter: blur(10px) saturate(180%);
-webkit-backdrop-filter: blur(10px) saturate(180%);
- background-color: rgba(43, 48, 60, 0.7);
+ background-color: rgb(12, 17, 29);
width: 100vw;
padding: 40px 20px;
- border-radius: 15px;
text-align: center;
- margin-top: 50px;
display: flex;
flex-direction: column;
align-items: center;
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index 1d8c213..1b14dd0 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -63,6 +63,16 @@ const Header: React.FC = () => {
About Us
+
+ (e.currentTarget.style.color = '#fde047')}
+ onMouseLeave={e => (e.currentTarget.style.color = 'white')}
+ >
+ Contact Us
+
+
{
+ return (
+ <>
+
+
+
+
+ Glass UI
+ {' '}
+ Terms of Use
+
+
+ {/* Acceptance of Terms */}
+
+
+ 1. Acceptance of Terms
+
+
+ By accessing or using GlassyUI-Components, you agree to abide by
+ these Terms. If you disagree with any part of these terms, please
+ refrain from using this library.
+
+
+
+ {/* User Obligations */}
+
+
+ 2. User Obligations
+
+
+ Users must use the components responsibly, providing proper
+ attribution as required. Redistribution without modification is
+ prohibited.
+
+
+
+ {/* Intellectual Property */}
+
+
+ 3. Intellectual Property Rights
+
+
+ GlassyUI-Components and its designs are the intellectual property
+ of the creators and contributors.
+
+
+
+ {/* Limitation of Liability */}
+
+
+ 4. Limitation of Liability
+
+
+ We are not liable for any damages arising from the use or misuse
+ of GlassyUI-Components.
+
+
+
+ {/* Termination */}
+
+
+ 5. Termination
+
+
+ We reserve the right to terminate access to GlassyUI-Components
+ for users who violate these Terms.
+
+
+
+ {/* Modification of Terms */}
+
+
+ 6. Modification of Terms
+
+
+ We reserve the right to modify these Terms at any time. Changes
+ will be announced through our GitHub repository or other official
+ channels.
+
+
+
+ {/* Privacy Policy */}
+
+
+ 7. Privacy Policy
+
+
+ We respect your privacy. Any data collected is handled according
+ to our Privacy Policy, accessible through our main website.
+
+
+
+ {/* Third-Party Links */}
+
+
+ 8. Third-Party Links
+
+
+ Our library may contain links to third-party websites or services.
+ We are not responsible for the content, policies, or practices of
+ these external sites.
+
+
+
+ {/* User-Generated Content */}
+
+
+ 9. User-Generated Content
+
+
+ Any contributions or modifications made to GlassyUI-Components are
+ welcome but must align with our community guidelines and
+ open-source policies.
+
+
+
+ {/* Governing Law */}
+
+
+ 10. Governing Law
+
+
+ These Terms are governed by and construed in accordance with the
+ applicable intellectual property laws and open-source policies.
+
+
+
+
+
+ >
+ );
+};