Skip to content

Commit

Permalink
Merge branch 'main' into UI-design
Browse files Browse the repository at this point in the history
  • Loading branch information
Pushpa472 authored Nov 9, 2024
2 parents e51c05e + 73147e2 commit 377a325
Show file tree
Hide file tree
Showing 16 changed files with 642 additions and 12 deletions.
5 changes: 5 additions & 0 deletions server/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
MONGO_URI=mongodb://localhost:27017/finveda
PORT=5000
EMAIL_ID=
PASS_KEY=
ADMIN_EMAIL_ID=
6 changes: 6 additions & 0 deletions server/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
./node_modules
.env
package-lock.json
uploads
./uploads
22 changes: 22 additions & 0 deletions server/app.js
Original file line number Diff line number Diff line change
@@ -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}`);
});
28 changes: 28 additions & 0 deletions server/controllers/contactController.js
Original file line number Diff line number Diff line change
@@ -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');
}
34 changes: 34 additions & 0 deletions server/model/contact.js
Original file line number Diff line number Diff line change
@@ -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;
24 changes: 24 additions & 0 deletions server/package.json
Original file line number Diff line number Diff line change
@@ -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": ""
}
8 changes: 8 additions & 0 deletions server/routes/contactRoutes.js
Original file line number Diff line number Diff line change
@@ -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;
15 changes: 15 additions & 0 deletions server/utils/db.js
Original file line number Diff line number Diff line change
@@ -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;
71 changes: 71 additions & 0 deletions server/utils/sendMail.js
Original file line number Diff line number Diff line change
@@ -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: `<div style="background: #e3f2fd; color: #333; padding: 20px; font-family: Arial, sans-serif;">
<div style="font-size: 1.5rem; text-align: center; margin-bottom: 20px; color: #0288d1;">
GLASSYUI Contact Form Submission
</div>
<table style="width: 60%; border-collapse: collapse; margin: 0 auto; background: white; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);">
<thead>
<tr>
<th style="border: 1px solid #ddd; padding: 10px; text-align:center; background-color: #0288d1; color: white;">
Field
</th>
<th style="border: 1px solid #ddd; padding: 10px; text-align:center; background-color: #0288d1; color: white;">
Value
</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border: 1px solid #ddd; padding: 10px; text-align:center;">Name</td>
<td style="border: 1px solid #ddd; padding: 10px; text-align:center;">${userdata.fullName}</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 10px; text-align:center;">Phone</td>
<td style="border: 1px solid #ddd; padding: 10px; text-align:center;">${userdata.phoneNumber}</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 10px; text-align:center;">Email</td>
<td style="border: 1px solid #ddd; padding: 10px; text-align:center;">${userdata.email}</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 10px; text-align:center;">Message</td>
<td style="border: 1px solid #ddd; padding: 10px; text-align:center;">${userdata.message}</td>
</tr>
<tr>
<td style="border: 1px solid #ddd; padding: 10px; text-align:center;">Submitted At</td>
<td style="border: 1px solid #ddd; padding: 10px; text-align:center;">${new Date().toLocaleString()}</td>
</tr>
</tbody>
</table>
</div>`, // html body
});
}

main().catch(console.error);
};

// Export as a named export
export { sendMailToAdmin };
20 changes: 14 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -74,6 +77,7 @@ const App: React.FC = () => {
return (
<Router>
<Header />
<AiChatbot />
{/* <ThemeToggle /> */}
<ScrollProgressBar /> {/* Add the ScrollProgressBar component here */}
<Routes>
Expand Down Expand Up @@ -112,14 +116,18 @@ const App: React.FC = () => {
<Route path='/spinner' element={<SpinnerDetailsPage />} />
<Route path='/product-details' element={<ProductCardDetailsPage />} />
<Route path='/gallery-details' element={<GalleryDetailsPage />} />
<Route path='*' element={<NotFoundPage />} />
<Route path='/contact' element={<ContactUs />} />
<Route path='/termsOfUse' element={<TermsOfUse />} />
<Route path='*' element={<NotFoundPage />} />
</Routes>
{/* <ConditionalFooter /> */}
</Router>
);
};
// const ConditionalFooter: React.FC = () => {
// const location = useLocation();
// return location.pathname === '/' ? <Footer /> : null;
// };

const ConditionalFooter: React.FC = () => {
const location = useLocation();
return location.pathname === '/' ? null : <Footer />;
};

export default App;
33 changes: 33 additions & 0 deletions src/components/AIChatbot.tsx
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 1 addition & 1 deletion src/components/BackToTop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const BackToTopButton: React.FC = () => {
{isVisible && (
<button
onClick={scrollToTop}
className='z-50 fixed bottom-12 right-8 bg-indigo-500 hover:bg-purple-500 transition-all text-white px-4 py-2 rounded-md shadow-lg transition-opacity duration-300'
className='z-50 fixed bottom-12 right-24 bg-indigo-500 hover:bg-purple-500 transition-all text-white px-4 py-2 rounded-md shadow-lg transition-opacity duration-300'
>
</button>
Expand Down
Loading

0 comments on commit 377a325

Please sign in to comment.