From b5ac52130ce41e40e6751982735c4500031bedc9 Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 19 Sep 2023 16:28:24 -0700 Subject: [PATCH 1/2] Login and Shopping Pages done --- src/App.js | 8 ++- src/pages/login.js | 40 ++++++++++++ src/pages/shopping-list.js | 126 +++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+), 2 deletions(-) create mode 100644 src/pages/login.js create mode 100644 src/pages/shopping-list.js diff --git a/src/App.js b/src/App.js index 96d24665..f5044715 100644 --- a/src/App.js +++ b/src/App.js @@ -12,6 +12,8 @@ import Stack from '@mui/material/Stack' import Content from './components/Content' import Loading from './components/Loading' +import Login from './pages/login' +import ShoppingListApp from './pages/shopping-list' let theme = createTheme({ @@ -86,11 +88,13 @@ const App = () => { return ( - + {/* {renderLoading()} {renderContent()} - + */} + {/* */} + ) } diff --git a/src/pages/login.js b/src/pages/login.js new file mode 100644 index 00000000..c71dde23 --- /dev/null +++ b/src/pages/login.js @@ -0,0 +1,40 @@ +import React, { useState } from 'react'; +import { TextField, Button, Container, Typography } from '@mui/material'; + +const Login = () => { + const [name, setName] = useState(''); + + const handleLogin = () => { + // Add login logic here + }; + + return ( + + + Login + +
+ setName(e.target.value)} + /> + + + +
+ ); +}; + +export default Login; \ No newline at end of file diff --git a/src/pages/shopping-list.js b/src/pages/shopping-list.js new file mode 100644 index 00000000..0c3924ae --- /dev/null +++ b/src/pages/shopping-list.js @@ -0,0 +1,126 @@ +import React, { useState } from 'react'; +import { + Container, + Typography, + TextField, + Button, + List, + ListItem, + ListItemText, + ListItemSecondaryAction, + IconButton, +} from '@mui/material'; +import { AddCircle, Delete } from '@mui/icons-material'; + +const ShoppingListApp = () => { + const [storeItems, setStoreItems] = useState([ + { id: 1, name: 'Apples', price: 1.99 }, + { id: 2, name: 'Bananas', price: 0.99 }, + { id: 3, name: 'Milk', price: 2.49 }, + // Add more store items as needed + ]); + const [userItems, setUserItems] = useState([]); + const [newItem, setNewItem] = useState(''); + + const addItemToUserList = (item) => { + setUserItems([...userItems, item]); + }; + + const removeItemFromUserList = (index) => { + const updatedItems = [...userItems]; + updatedItems.splice(index, 1); + setUserItems(updatedItems); + }; + + return ( + + + Shopping List + + + {/* Store Catalog */} + + Store Catalog + + + {storeItems.map((item) => ( + + + + + + + ))} + + + {/* User's Shopping List */} + + Your Shopping List + + setNewItem(e.target.value)} + onKeyPress={(e) => { + if (e.key === 'Enter') { + addItemToUserList({ name: newItem, price: 0 }); + setNewItem(''); + } + }} + /> + + + {userItems.map((item, index) => ( + + + + removeItemFromUserList(index)} + > + + + + + ))} + + + + + + + ); +}; + +export default ShoppingListApp; \ No newline at end of file From 22b465a48dfc18d1fbb09ef72a2d5907b42f45ad Mon Sep 17 00:00:00 2001 From: Bhargav Date: Tue, 26 Sep 2023 02:08:30 -0700 Subject: [PATCH 2/2] initial commit --- package-lock.json | 39 ++++++++ package.json | 1 + src/App.js | 12 ++- src/components/SpeechRecognition.js | 125 ++++++++++++++++++++++++ src/index.js | 3 + src/pages/login.js | 4 + src/pages/shopping-list.js | 144 +++++++++++++++++++++++++++- 7 files changed, 323 insertions(+), 5 deletions(-) create mode 100644 src/components/SpeechRecognition.js diff --git a/package-lock.json b/package-lock.json index 89f4e0cd..6f963d34 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@testing-library/user-event": "13.5.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 +4531,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", @@ -17275,6 +17284,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..90494dce 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@testing-library/user-event": "13.5.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/src/App.js b/src/App.js index f5044715..398bef51 100644 --- a/src/App.js +++ b/src/App.js @@ -15,6 +15,9 @@ import Loading from './components/Loading' import Login from './pages/login' import ShoppingListApp from './pages/shopping-list' +import { BrowserRouter as Router, Route, Routes, BrowserRouter } from 'react-router-dom'; + + let theme = createTheme({ palette: { @@ -87,6 +90,7 @@ const App = () => { } return ( + // {/* @@ -94,7 +98,13 @@ const App = () => { {renderContent()} */} {/* */} - + {/* */} + + } /> + } /> + {/* */} + + {/* */} ) } diff --git a/src/components/SpeechRecognition.js b/src/components/SpeechRecognition.js new file mode 100644 index 00000000..0d5ae50c --- /dev/null +++ b/src/components/SpeechRecognition.js @@ -0,0 +1,125 @@ +import React, { useEffect, useState } from 'react'; + +const SpeechRecognitionComponent = ({originalList, addItems}) => { + const [transcript, setTranscript] = useState(''); + const [transcripts, setTranscripts] = useState([]); + const [ isRecording, setIsRecording] = useState(false); + const [recognition, setRecognition] = useState(null); + + // Function to calculate Levenshtein distance between two strings +function getLevenshteinDistance(a, b) { + if (a.length === 0) return b.length; + if (b.length === 0) return a.length; + + const matrix = []; + for (let i = 0; i <= b.length; i++) { + matrix[i] = [i]; + } + + for (let j = 0; j <= a.length; j++) { + matrix[0][j] = j; + } + + for (let i = 1; i <= b.length; i++) { + for (let j = 1; j <= a.length; j++) { + const cost = a[j - 1] === b[i - 1] ? 0 : 1; + matrix[i][j] = Math.min( + matrix[i - 1][j] + 1, + matrix[i][j - 1] + 1, + matrix[i - 1][j - 1] + cost + ); + } + } + + return matrix[b.length][a.length]; + } + + + + const createFinalList = (recognizedList) => { + // Set a threshold for similarity + const similarityThreshold = 2; // Adjust as needed + + // Create a final list of similar items + const finalList = []; + for (const recognizedItem of recognizedList) { + for (const originalItem of originalList) { + const distance = getLevenshteinDistance(recognizedItem.toLowerCase(), originalItem.toLowerCase()); + if (distance <= similarityThreshold) { + finalList.push(originalItem); + break; // Move to the next recognized item + } + } + } + + addItems(finalList) + } + + useEffect(() => { + // Check for browser support + if ('SpeechRecognition' in window || 'webkitSpeechRecognition' in window) { + const recognitionInstance = + window.SpeechRecognition || window.webkitSpeechRecognition; + const recognitionObj = new recognitionInstance(); + + recognitionObj.lang = 'en-US'; // Set the language you want to recognize + + recognitionObj.onresult = (event) => { + const result = event.results[0][0].transcript; + setTranscript(result); + setTranscripts((prevTranscripts) => [ + ...prevTranscripts, + ...result.split(' '), // Split recognized phrase into words + ]); + console.log("DD") + createFinalList(result.split(' ')) + }; + + recognitionObj.onend = () => { + if (isRecording) { + // If recording is still active, restart recognition + recognitionObj.start(); + } + }; + + setRecognition(recognitionObj); + } else { + console.error('Speech recognition not supported in this browser'); + } + }, [isRecording]); + + const startRecording = () => { + if (recognition) { + setIsRecording(true); + setTranscript(''); + setTranscripts([]); + recognition.start(); + } + }; + + const stopRecording = () => { + if (recognition) { + setIsRecording(false); + recognition.stop(); + } + }; + + return ( +
+ + + {/*

Transcripts: {transcripts.join(', ')}

+

Current Transcript: {transcript}

*/} +
+ ); +}; + +export default SpeechRecognitionComponent; \ No newline at end of file diff --git a/src/index.js b/src/index.js index d563c0fb..112f6789 100644 --- a/src/index.js +++ b/src/index.js @@ -3,11 +3,14 @@ import ReactDOM from 'react-dom/client'; import './index.css'; import App from './App'; import reportWebVitals from './reportWebVitals'; +import { BrowserRouter } from 'react-router-dom'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( + + ); diff --git a/src/pages/login.js b/src/pages/login.js index c71dde23..742cdfbf 100644 --- a/src/pages/login.js +++ b/src/pages/login.js @@ -1,11 +1,15 @@ import React, { useState } from 'react'; import { TextField, Button, Container, Typography } from '@mui/material'; +import { useNavigate } from 'react-router-dom'; const Login = () => { const [name, setName] = useState(''); + const navigate = useNavigate(); const handleLogin = () => { // Add login logic here + navigate("/shopping-list"); + }; return ( diff --git a/src/pages/shopping-list.js b/src/pages/shopping-list.js index 0c3924ae..927b40ad 100644 --- a/src/pages/shopping-list.js +++ b/src/pages/shopping-list.js @@ -11,12 +11,15 @@ import { IconButton, } from '@mui/material'; import { AddCircle, Delete } from '@mui/icons-material'; +import SpeechRecognitionComponent from '../components/SpeechRecognition'; const ShoppingListApp = () => { const [storeItems, setStoreItems] = useState([ { id: 1, name: 'Apples', price: 1.99 }, { id: 2, name: 'Bananas', price: 0.99 }, { id: 3, name: 'Milk', price: 2.49 }, + { id: 3, name: 'Oranges', price: 2.49 }, + { id: 3, name: 'Cucumber', price: 2.49 }, // Add more store items as needed ]); const [userItems, setUserItems] = useState([]); @@ -32,6 +35,136 @@ const ShoppingListApp = () => { setUserItems(updatedItems); }; + const printItems = () => { + + var products = [ + { name: "Product 1", price: "$10.00" }, + { name: "Product 2", price: "$20.00" }, + { name: "Product 3", price: "$15.00" }, + { name: "Product 4", price: "$25.00" }, + ]; + + + const tableToPrint = document.createElement('table') + tableToPrint.createTBody() + tableToPrint.style.borderCollapse = "collapse"; + tableToPrint.style.width = "50%"; + tableToPrint.style.margin = "0 auto"; + tableToPrint.style.border = "1px solid #ddd"; + tableToPrint.style.outline = "1px solid #ddd"; + + var thead = tableToPrint.createTHead(); + var headerRow = thead.insertRow(); + var th1 = document.createElement("th"); + th1.textContent = "Name"; + th1.style.border = "1px solid #ddd"; // Add a border to the header cells + th1.style.outline = "1px solid #ddd"; // Add an outline to the header cells + var th2 = document.createElement("th"); + th2.textContent = "Price"; + th2.style.border = "1px solid #ddd"; // Add a border to the header cells + th2.style.outline = "1px solid #ddd"; // Add an outline to the header cells + headerRow.appendChild(th1); + headerRow.appendChild(th2); + + var tableBody = tableToPrint.getElementsByTagName('tbody')[0] + + // Loop through the products and add rows to the table + for (var i = 0; i < products.length; i++) { + var row = tableBody.insertRow(i); + row.style.border = "1px solid #ddd"; // Add a border to the row + row.style.outline = "1px solid #ddd"; + + var cell1 = row.insertCell(0); + cell1.textContent = products[i].name; + cell1.style.border = "1px solid #ddd"; + cell1.style.outline = "1px solid #ddd"; + cell1.style.textAlign = "center"; + + var cell2 = row.insertCell(1); + cell1.innerHTML = products[i].name; + cell2.innerHTML = products[i].price; + + + cell2.textContent = products[i].price; + cell2.style.border = "1px solid #ddd"; + cell2.style.outline = "1px solid #ddd"; + cell2.style.textAlign = "center"; + } + + let newWin= window.open(""); + newWin.document.write(tableToPrint.outerHTML); + newWin.print(); + newWin.close(); + } + + const sendEmail = ( subject, body ) => { + // Encode the subject and body to ensure special characters are properly handled + const encodedSubject = encodeURIComponent(`Hi, I'm sharing my shopping list with you!`); + + var products = [ + { name: "Product 1", price: "$10.00" }, + { name: "Product 2", price: "$20.00" }, + { name: "Product 3", price: "$15.00" }, + { name: "Product 4", price: "$25.00" }, + ]; + + + const tableToPrint = document.createElement('table') + tableToPrint.createTBody() + tableToPrint.style.borderCollapse = "collapse"; + tableToPrint.style.width = "50%"; + tableToPrint.style.margin = "0 auto"; + tableToPrint.style.border = "1px solid #ddd"; + tableToPrint.style.outline = "1px solid #ddd"; + + var thead = tableToPrint.createTHead(); + var headerRow = thead.insertRow(); + var th1 = document.createElement("th"); + th1.textContent = "Name"; + th1.style.border = "1px solid #ddd"; // Add a border to the header cells + th1.style.outline = "1px solid #ddd"; // Add an outline to the header cells + var th2 = document.createElement("th"); + th2.textContent = "Price"; + th2.style.border = "1px solid #ddd"; // Add a border to the header cells + th2.style.outline = "1px solid #ddd"; // Add an outline to the header cells + headerRow.appendChild(th1); + headerRow.appendChild(th2); + + var tableBody = tableToPrint.getElementsByTagName('tbody')[0] + + // Loop through the products and add rows to the table + for (var i = 0; i < products.length; i++) { + var row = tableBody.insertRow(i); + row.style.border = "1px solid #ddd"; // Add a border to the row + row.style.outline = "1px solid #ddd"; + + var cell1 = row.insertCell(0); + cell1.textContent = products[i].name; + cell1.style.border = "1px solid #ddd"; + cell1.style.outline = "1px solid #ddd"; + cell1.style.textAlign = "center"; + + var cell2 = row.insertCell(1); + cell1.innerHTML = products[i].name; + cell2.innerHTML = products[i].price; + + + cell2.textContent = products[i].price; + cell2.style.border = "1px solid #ddd"; + cell2.style.outline = "1px solid #ddd"; + cell2.style.textAlign = "center"; + } + + let htmlBod = document.createElement('html') + + const encodedBody = encodeURIComponent(tableToPrint.outerHTML); + + // Create the mailto URL with subject and body + const mailtoUrl = `mailto:?subject=${encodedSubject}&body=${encodedBody}`; + window.location.href = mailtoUrl; + }; + + return ( @@ -93,6 +226,9 @@ const ShoppingListApp = () => { > Add + {return item.name})} addItems = {(items) => { + setUserItems([...userItems, ...items.map(i => {return {name: i, price: 0}})]) + }} /> {userItems.map((item, index) => ( @@ -110,15 +246,15 @@ const ShoppingListApp = () => { ))} - - - + */} ); };