diff --git a/README.md b/README.md index 58beeacc..74e6a8d1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,17 @@ +# Web App Details +1. Helps user login using their name +2. Login redirects to the products page, currently we are using dummy data from dummyjson.com and with a limit of 100, moving forward we can add more data to this list. +3. User can add items to the cart by clicking on the add item button. +4. User can search items through typing text in the search bar or giving input through narration by clicking on the mic icon and saying the product name. This filters the data for the user. +5. After adding, they will see a pop up mentioning added item to the cart and the cart symbol will update with current item in the cart. +6. User can see all the items in the cart, their quantity and total cost of the cart and per item. +7. They can share this cart with someone by clicking on share cart button and entering the email id. + +# Future Improvements:- +1. Improving UI +2. Adding more levels of security and a well maintained backend system, as current data is being stored in sessionstorage due to given scope of the project. +3. Having a customized emailing template and a custom email sending function rather than using EmailJs. + # Getting Started with Create React App This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). diff --git a/package-lock.json b/package-lock.json index 89f4e0cd..ad45b665 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,8 +16,10 @@ "@testing-library/jest-dom": "5.16.5", "@testing-library/react": "13.4.0", "@testing-library/user-event": "13.5.0", + "emailjs-com": "^3.2.0", "react": "18.2.0", "react-dom": "18.2.0", + "react-router-dom": "^6.16.0", "react-scripts": "5.0.1", "web-vitals": "2.1.4" } @@ -4530,6 +4532,14 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@remix-run/router": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.9.0.tgz", + "integrity": "sha512-bV63itrKBC0zdT27qYm6SDZHlkXwFL1xMBuhkn+X7l0+IIhNaH5wuuvZKp6eKhCD4KFhujhfhCT1YxXW6esUIA==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/@rollup/plugin-babel": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", @@ -8086,6 +8096,15 @@ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.523.tgz", "integrity": "sha512-9AreocSUWnzNtvLcbpng6N+GkXnCcBR80IQkxRC9Dfdyg4gaWNUPBujAHUpKkiUkoSoR9UlhA4zD/IgBklmhzg==" }, + "node_modules/emailjs-com": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/emailjs-com/-/emailjs-com-3.2.0.tgz", + "integrity": "sha512-Prbz3E1usiAwGjMNYRv6EsJ5c373cX7/AGnZQwOfrpNJrygQJ15+E9OOq4pU8yC977Z5xMetRfc3WmDX6RcjAA==", + "deprecated": "The SDK name changed to @emailjs/browser", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/emittery": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz", @@ -17275,6 +17294,36 @@ "node": ">=0.10.0" } }, + "node_modules/react-router": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.16.0.tgz", + "integrity": "sha512-VT4Mmc4jj5YyjpOi5jOf0I+TYzGpvzERy4ckNSvSh2RArv8LLoCxlsZ2D+tc7zgjxcY34oTz2hZaeX5RVprKqA==", + "dependencies": { + "@remix-run/router": "1.9.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.16.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.16.0.tgz", + "integrity": "sha512-aTfBLv3mk/gaKLxgRDUPbPw+s4Y/O+ma3rEN1u8EgEpLpPe6gNjIsWt9rxushMHHMb7mSwxRGdGlGdvmFsyPIg==", + "dependencies": { + "@remix-run/router": "1.9.0", + "react-router": "6.16.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, "node_modules/react-scripts": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-5.0.1.tgz", diff --git a/package.json b/package.json index ca2a9136..14e7cd32 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,10 @@ "@testing-library/jest-dom": "5.16.5", "@testing-library/react": "13.4.0", "@testing-library/user-event": "13.5.0", + "emailjs-com": "^3.2.0", "react": "18.2.0", "react-dom": "18.2.0", + "react-router-dom": "^6.16.0", "react-scripts": "5.0.1", "web-vitals": "2.1.4" }, diff --git a/similarity.js b/similarity.js new file mode 100644 index 00000000..b12fed7b --- /dev/null +++ b/similarity.js @@ -0,0 +1,36 @@ +const stringSimilarity = require('string-similarity'); + +// Sample passage +const passage = ` +Mens Casual Premium Slim Fit T-Shirts Slim-fitting style, +contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable +and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual +fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket. +Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday +`; + +// Function to search for similar text +function searchSimilarText(query, passage, numResults = 3) { + const sentences = passage.split('\n').filter((sentence) => sentence.trim() !== ''); + + // Calculate the similarity between the query and each sentence + const similarities = sentences.map((sentence) => ({ + sentence, + similarity: stringSimilarity.compareTwoStrings(query, sentence), + })); + + // Sort by similarity and return the top results + similarities.sort((a, b) => b.similarity - a.similarity); + + return similarities.slice(0, numResults); +} + +// Example usage +const query = 'Slim Fit TShirt'; +const results = searchSimilarText(query, passage); + +console.log('Query:', query); +console.log('Similar Text:'); +results.forEach((result) => { + console.log(`Sentence: ${result.sentence}, Similarity: ${result.similarity}`); +}); diff --git a/src/App.js b/src/App.js index 96d24665..6c5ed295 100644 --- a/src/App.js +++ b/src/App.js @@ -1,98 +1,121 @@ import React, { useEffect, useState } from 'react' - -import CssBaseline from '@mui/material/CssBaseline' - import { - createTheme, - ThemeProvider, - responsiveFontSizes, -} from '@mui/material/styles' - -import Stack from '@mui/material/Stack' - -import Content from './components/Content' -import Loading from './components/Loading' - - -let theme = createTheme({ - palette: { - primary: { - main: '#de6720', - }, - secondary: { - main: '#0077ea', - }, - }, - components: { - MuiCssBaseline: { - styleOverrides: { - html: { - WebkitFontSmoothing: 'auto', - }, - body: { - background: '#fefefe', - overflow: 'hidden', - padding: '5px', - width: '450px', - color: '#333', - }, - }, - }, - MuiLinearProgress: { - styleOverrides: { - root: { - backgroundColor: 'rgba(222, 103, 32, 0.25)', - }, - bar: { - backgroundColor: 'rgba(222, 103, 32, 1)', - }, - }, - }, - }, -}) -theme = responsiveFontSizes(theme) - - -const App = () => { - - const [loading, setLoading] = useState(false) - - useEffect(() => { - - // show a loading indicator - setLoading(true) - - setTimeout(() => { - - // hide loading indicator - setLoading(false) - }, 1000) // 1 second - - // hide loading indicator - return () => { - setLoading(false) - } - }, []) - - const renderLoading = () => { - if ( !loading ) { return } - return - } - - const renderContent = () => { - if ( loading ) { return } - return - } - + BrowserRouter as Router, + Routes, + Route, + Link +} from "react-router-dom"; +// import CssBaseline from '@mui/material/CssBaseline' + +// import { +// createTheme, +// ThemeProvider, +// responsiveFontSizes, +// } from '@mui/material/styles' + +// import Stack from '@mui/material/Stack' + +// import Content from './components/Content' +// import Loading from './components/Loading' +import Login from './components/login' +import Dashboard from './components/Dashboard'; +import MyComponent from './components/fetch'; +import Cart from './components/Cart'; +// import Appmail from './components/sendEmail'; +// let theme = createTheme({ +// palette: { +// primary: { +// main: '#de6720', +// }, +// secondary: { +// main: '#0077ea', +// }, +// }, +// components: { +// MuiCssBaseline: { +// styleOverrides: { +// html: { +// WebkitFontSmoothing: 'auto', +// }, +// body: { +// background: '#fefefe', +// overflow: 'hidden', +// padding: '5px', +// width: '450px', +// color: '#333', +// }, +// }, +// }, +// MuiLinearProgress: { +// styleOverrides: { +// root: { +// backgroundColor: 'rgba(222, 103, 32, 0.25)', +// }, +// bar: { +// backgroundColor: 'rgba(222, 103, 32, 1)', +// }, +// }, +// }, +// }, +// }) +// theme = responsiveFontSizes(theme) + + +// const App = () => { + +// const [loading, setLoading] = useState(false) + +// useEffect(() => { + +// // show a loading indicator +// setLoading(true) + +// setTimeout(() => { + +// // hide loading indicator +// setLoading(false) +// }, 1000) // 1 second + +// // hide loading indicator +// return () => { +// setLoading(false) +// } +// }, []) + +// const renderLoading = () => { +// if ( !loading ) { return } +// return +// } + +// const renderContent = () => { +// if ( loading ) { return } +// return +// } + +// return ( +// +// +// +// {/* {renderLoading()} +// {renderContent()} */} + +// +// +// ) +// } +function App() { return ( - - - - {renderLoading()} - {renderContent()} - - - ) + + + }/> + }/> + }/> + }/> + {/* }/> */} + + + ); } + export default App diff --git a/src/components/Cards.js b/src/components/Cards.js new file mode 100644 index 00000000..3a43bbf4 --- /dev/null +++ b/src/components/Cards.js @@ -0,0 +1,109 @@ +import React, { useState, useEffect } from 'react'; +import { + Typography, + Grid, + Card, + CardContent, + CardMedia, + Button, +} from '@mui/material'; +import Snackbar from '@mui/material/Snackbar'; +import MuiAlert from '@mui/material/Alert'; + +function ProductCard(projectsData) { + const [open, setOpen] = useState(false); + const [cartCount, setCartCount] = useState(0); + + useEffect(() => { + // Load cart count from session storage when the component mounts + const data = sessionStorage.getItem('userdata'); + if (data) { + const userData = JSON.parse(data); + const itemCount = userData.cart.count; + setCartCount(itemCount); + } + }, []); + + const handleClick = (index) => { + const data = sessionStorage.getItem('userdata'); + const username = sessionStorage.username; + const userData = JSON.parse(data); + + userData.cart.count = parseInt(userData.cart.count) + 1; + userData.cart.items.push(projectsData.projectsData.products[index]); + sessionStorage.setItem('userdata', JSON.stringify(userData)); + + setCartCount(userData.cart.count); + setOpen(true); + }; + + const handleClose = (event, reason) => { + if (reason === 'clickaway') { + return; + } + setOpen(false); + }; + + return ( +
+ + + {projectsData.projectsData.products.map((project, index) => ( + + + + + + {project.brand} : {project.title} + + + {project.description.substring(0, 80)}.. + + ${project.price} + + + + Added Item to Cart + + + + + + ))} + +
+ ); +} + +export default ProductCard; diff --git a/src/components/Cart.js b/src/components/Cart.js new file mode 100644 index 00000000..ca8ccf45 --- /dev/null +++ b/src/components/Cart.js @@ -0,0 +1,162 @@ +import React, { useState, useEffect } from 'react'; +import { + Container, + Typography, + Paper, + Table, + TableBody, + TableCell, + TableContainer, + TableHead, + TableRow, + Button, + IconButton, + AppBar, + Toolbar, + Badge, +} from '@mui/material'; +import DeleteIcon from '@mui/icons-material/Delete'; +import EmailInputModal from './EmailModal'; +import MuiAlert from '@mui/material/Alert'; +import Snackbar from '@mui/material/Snackbar'; +import HomeIcon from '@mui/icons-material/Home'; +import { useNavigate } from 'react-router-dom'; +import sendmail from './sendEmail'; +import createEmailContent from './createContent'; +const Cart = () => { + const [apiData, setApiData] = useState(null); + const [modalOpen, setModalOpen] = useState(false); + const [recipientEmail, setRecipientEmail] = useState(''); + const [message, setMessage] = useState(''); + const [open, setOpen] = useState(false); + const username = sessionStorage.username; + useEffect(() => { + const username = sessionStorage.username; + var data = sessionStorage.getItem(username); + if (data) { + const userData = JSON.parse(data); + setApiData(userData); + } + }, []); + const getTotalPrice = () => { + var total = 0 + Object.entries(apiData['items']).forEach(([key, value]) => { + total += (value.quantity * value.price); + }); + return total; + }; + const handleMail = () => { + setModalOpen(true); + }; + const handleClose = (event, reason) => { + if (reason === 'clickaway') { + return; + } + setOpen(false); + }; + const sendEmail = (recipientEmail) => { + // Customize this function to send the email using your email service or API + // Example: You can make an HTTP request to your backend to send the email + // or use a client library for sending emails. + // Ensure you have configured your email service properly. + console.log(`Sending email to: ${recipientEmail}`); + setOpen(true); + var content = createEmailContent(apiData['items']) + // ... (send email logic) + sendmail(username,recipientEmail, content); + // Close the modal and show a confirmation message + setModalOpen(false); + setMessage('Email sent successfully'); + }; + const navigate = useNavigate(); + const gohome=()=>{ + + navigate('/dashboard'); + } + return ( + apiData ? +
+ + + + Welcome {username} !!! + + + + + + + + + + + Shopping Cart + + {apiData['count'] === 0 ? ( + + Your cart is empty. + + ) : ( + + + + + Product + Quantity + Price + Total + + + + + {Object.entries(apiData['items']).map(([key, item]) =>( + + +
+ {item.brand} + {item.brand} - {item.title} +
+
+ {item.quantity} + ${item.price} + ${item.price * item.quantity} + {/* {item} */} + + + + + +
+ ))} +
+
+
+ )} + {apiData['count'] === 0 ? ( +
): ( +
+
+ + Total: ${getTotalPrice()} + +
+
+ +
+
+ )} + setModalOpen(false)} + onConfirm={sendEmail} + /> + + Email Sent successfully +
+
:
+ ); +}; + +export default Cart; diff --git a/src/components/Dashboard.js b/src/components/Dashboard.js new file mode 100644 index 00000000..64061182 --- /dev/null +++ b/src/components/Dashboard.js @@ -0,0 +1,230 @@ +import React, { useState, useEffect } from 'react'; +import { + AppBar, + Toolbar, + Typography, + Container, + IconButton, + Badge, + Button, + TextField, + InputAdornment, + Grid, + Card, + CardContent, + CardMedia, +} from '@mui/material'; +import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; +import SearchIcon from '@mui/icons-material/Search'; +import MicIcon from '@mui/icons-material/Mic'; +import Snackbar from '@mui/material/Snackbar'; +import MuiAlert from '@mui/material/Alert'; +import { useNavigate } from 'react-router-dom'; +function Dashboard() { + + const username = sessionStorage.username; + var data = sessionStorage.getItem(username); + data = JSON.parse(data) + var [itemscart,setItem] = useState(data['count']); + const [apiData, setApiData] = useState(null); + const [filteredProducts, setFilteredProducts] = useState([]); + + + useEffect(() => { + const apiUrl = 'https://dummyjson.com/products?limit=100'; + const data = sessionStorage.getItem(username); + if (data) { + const userData = JSON.parse(data); + const itemCount = userData.count; + setCartCount(itemCount); + } + fetch(apiUrl) + .then((response) => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then((data) => { + setApiData(data); + setFilteredProducts(data.products); + }) + .catch((error) => { + console.error('Error fetching data:', error); + }); + }, []); + + const [open, setOpen] = useState(false); + const [cartCount, setCartCount] = useState(0); + + const handleSearch = () => { + // Filter products based on the search query + const query = searchText.toLowerCase(); + const filtered = apiData.products.filter((product) => + product.title.toLowerCase().includes(query) || + product.brand.toLowerCase().includes(query) || + product.description.toLowerCase().includes(query) + ); + setFilteredProducts(filtered); + }; + const handleClick = (index) => { + const username = sessionStorage.username; + const data = sessionStorage.getItem(username); + const userData = JSON.parse(data); + userData.count = parseInt(userData.count) + 1; + if(index in userData['items']){ + userData['items'][index]['quantity']+=1; + } + else{ + userData['items'][index] = apiData.products[index]; + userData['items'][index]['quantity'] = 1; + } + sessionStorage.setItem(username, JSON.stringify(userData)); + + setCartCount(userData.count); + setOpen(true); + }; + + const handleClose = (event, reason) => { + if (reason === 'clickaway') { + return; + } + setOpen(false); + }; + +// console.log(apiData) + + const [searchText, setSearchText] = useState(''); + const [isListening, setIsListening] = useState(false); + + const recognition = new window.webkitSpeechRecognition(); // Create a speech recognition instance + + recognition.onstart = () => { + setIsListening(true); + }; + + recognition.onend = () => { + setIsListening(false); + }; + + recognition.onresult = (event) => { + const transcript = event.results[0][0].transcript; + setSearchText(transcript); + console.log('Transcribed Text:', transcript); // Log the transcribed text to the console + }; + + recognition.onerror = (event) => { + console.error('Speech recognition error:', event.error); + }; + + const handleSearchChange = (event) => { + setSearchText(event.target.value); + }; + + const handleVoiceInput = () => { + if (!isListening) { + recognition.start(); // Start listening when the microphone button is clicked + } else { + recognition.stop(); // Stop listening when the button is clicked again + } + }; + const navigate = useNavigate(); + const handleCart = () => { + navigate('/cart'); + } + return ( +
+ + + + Welcome {username} !!! + + + + + + + + + +
+ + + {isListening ? : } + + + ), + }} sx={{mr:1}} + /> + +
+ {apiData ? ( + + {filteredProducts.map((project, index) => ( + + + + + + {project.brand} : {project.title} + + + {project.description} + + ${project.price} +
+ + + + Added Item to Cart + + +
+
+
+ ))} +
+ ) : <>} +
+
+ ); +} + +export default Dashboard; diff --git a/src/components/EmailModal.js b/src/components/EmailModal.js new file mode 100644 index 00000000..0ce4f32d --- /dev/null +++ b/src/components/EmailModal.js @@ -0,0 +1,43 @@ +import React, { useState } from 'react'; +import { + Dialog, + DialogTitle, + DialogContent, + TextField, + DialogActions, + Button, +} from '@mui/material'; + +const EmailInputModal = ({ open, onClose, onConfirm }) => { + const [email, setEmail] = useState(''); + + const handleConfirm = () => { + onConfirm(email); + onClose(); + }; + + return ( + + Enter Recipient's Email + + setEmail(e.target.value)} + /> + + + + + + + ); +}; + +export default EmailInputModal; diff --git a/src/components/UserContext.js b/src/components/UserContext.js new file mode 100644 index 00000000..92ab45be --- /dev/null +++ b/src/components/UserContext.js @@ -0,0 +1,17 @@ +import { createContext, useContext, useState } from 'react'; + +const UserContext = createContext(); + +export function UserProvider({ children }) { + const [username, setUsername] = useState(''); + + return ( + + {children} + + ); +} + +export function useUser() { + return useContext(UserContext); +} \ No newline at end of file diff --git a/src/components/createContent.js b/src/components/createContent.js new file mode 100644 index 00000000..5847f880 --- /dev/null +++ b/src/components/createContent.js @@ -0,0 +1,36 @@ +const createEmailContent = (apiData) => { + // const { items } = apiData; // Extract items from apiData + + // Calculate the total price + const totalPrice = Object.values(apiData).reduce( + (total, item) => total + item.quantity * item.price, + 0 + ); + + // Create the email content + const emailContent = ` +
+

Your Shopping Cart

+
    + ${Object.values(apiData) + .map( + (item) => ` +
  • + ${item.brand} - ${item.title} +
    + Quantity: ${item.quantity} +
    + Price per item: $${item.price} +
  • + ` + ) + .join('')} +
+

Total Price: $${totalPrice.toFixed(2)}

+
`; + + return emailContent; + }; + + export default createEmailContent; + \ No newline at end of file diff --git a/src/components/emailjs.config.js b/src/components/emailjs.config.js new file mode 100644 index 00000000..ae9dbd48 --- /dev/null +++ b/src/components/emailjs.config.js @@ -0,0 +1,7 @@ +const emailjsConfig = { + serviceId: 'service_pgevijq', + templateId: 'template_1evo1fi', + userId: 'Qu1oyo0hG11swVjHW', + }; + + export default emailjsConfig; \ No newline at end of file diff --git a/src/components/fetch.js b/src/components/fetch.js new file mode 100644 index 00000000..4182ac06 --- /dev/null +++ b/src/components/fetch.js @@ -0,0 +1,41 @@ +import React, { useState, useEffect } from 'react'; + +function MyComponent() { + // Step 3: Initialize state variable to store API response + const [apiData, setApiData] = useState(null); + + // Step 4: Make the fetch request when the component mounts + useEffect(() => { + // Define the API URL + const apiUrl = 'https://dummyjson.com/products'; + + // Make the fetch request + fetch(apiUrl) + .then((response) => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then((data) => { + // Step 5: Update state variable with fetched data + setApiData(data); + }) + .catch((error) => { + console.error('Error fetching data:', error); + }); + }, []); // The empty dependency array ensures this effect runs only once + + return ( +
+

API Data:

+ {apiData ? ( +
{JSON.stringify(apiData, null, 2)}
+ ) : ( +

Loading...

+ )} +
+ ); +} + +export default MyComponent; diff --git a/src/components/login.js b/src/components/login.js new file mode 100644 index 00000000..12a50a3c --- /dev/null +++ b/src/components/login.js @@ -0,0 +1,89 @@ +import React, { useState } from 'react'; +import { + Paper, + TextField, + Button, + Typography, + Avatar, +} from '@mui/material'; +import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; +import { useNavigate } from 'react-router-dom'; +const useStyles = { + root: { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + height: '100vh', + backgroundImage: 'url(https://www.ninahendrick.com/wp-content/uploads/Small-Pantry-Organization-9.jpg)', // Replace with your image URL + backgroundSize: 'cover', // Adjust background size as needed + backgroundPosition: 'center', // Adjust background position as needed + }, + paper: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + padding: '16px', + width: '400px', + backgroundColor: 'rgba(255, 255, 255, 1)', // Add a semi-transparent background color + }, + avatar: { + backgroundColor: 'primary', + marginBottom: '8px', + }, + form: { + width: '100%', + marginTop: '8px', + }, + submitButton: { + marginTop: '16px', + }, +}; + +function Login() { + const [username, setUsername] = useState(''); + const navigate = useNavigate(); + + const handleLogin = () => { + console.log(`Logged in as ${username}`); + if(!sessionStorage.getItem(username)){ + sessionStorage.setItem(username,JSON.stringify({'items':{},'count':0})); + } + sessionStorage.setItem('username',username); + navigate('/dashboard'); + }; + + return ( +
+ + + + + + Log In + +
+ setUsername(e.target.value)} + required + /> + + +
+
+ ); +} + +export default Login; diff --git a/src/components/responsive.js b/src/components/responsive.js new file mode 100644 index 00000000..8d4092dd --- /dev/null +++ b/src/components/responsive.js @@ -0,0 +1,16 @@ +import { css } from "styled-components"; + +export const mobile = (props) => { + return css` + @media only screen and (max-width: 480px) { + ${props} + } + `; +}; +export const tablet = (props) => { + return css` + @media only screen and (max-width: 780px) { + ${props} + } + `; +}; \ No newline at end of file diff --git a/src/components/sendEmail.js b/src/components/sendEmail.js new file mode 100644 index 00000000..0ba790dc --- /dev/null +++ b/src/components/sendEmail.js @@ -0,0 +1,69 @@ +import emailjs from 'emailjs-com'; +import emailjsConfig from './emailjs.config'; // Import your configuration + +const sendmail = (name,email,content) => { + const templateParams = { + to_email: email, + from_name:name, + message: content, + 'Content-Type': 'text/html' + }; + + emailjs + .send( + emailjsConfig.serviceId, + emailjsConfig.templateId, + templateParams, + emailjsConfig.userId + ) + .then( + (response) => { + console.log('Email sent successfully:', response); + // Handle success, e.g., show a confirmation message to the user + }, + (error) => { + console.error('Email sending failed:', error); + // Handle error, e.g., display an error message to the user + } + ); + return 200; +}; +export default sendmail; +// import React from 'react'; +// import emailjs from 'emailjs-com'; +// import emailjsConfig from './emailjs.config'; // Import your configuration + +// const sendEmail = () => { +// const templateParams = { +// to_email: 'rajeevdh@usc.edu', +// message: 'This is the email content.', +// }; + +// emailjs +// .send( +// emailjsConfig.serviceId, +// emailjsConfig.templateId, +// templateParams, +// emailjsConfig.userId +// ) +// .then( +// (response) => { +// console.log('Email sent successfully:', response); +// // Handle success, e.g., show a confirmation message to the user +// }, +// (error) => { +// console.error('Email sending failed:', error); +// // Handle error, e.g., display an error message to the user +// } +// ); +// }; + +// function Appmail() { +// return ( +//
+// +//
+// ); +// } + +// export default Appmail;