diff --git a/src/App.jsx b/src/App.jsx index 62f2095..cdd5299 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,6 +1,6 @@ import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'; import { Suspense } from 'react'; -import { Home, Layout, ManageList, Team } from './views'; +import { Home, Layout, AddItem, Team } from './views'; import { Loading } from './components/Loading'; import { ProtectedRoute } from './components/ProtectedRoute'; import { useAuth, useShoppingListData, useShoppingLists } from './api'; @@ -59,10 +59,10 @@ export function App() { } /> - + } /> diff --git a/src/views/AddItem.jsx b/src/views/AddItem.jsx new file mode 100644 index 0000000..2a0b23f --- /dev/null +++ b/src/views/AddItem.jsx @@ -0,0 +1,148 @@ +import { ToastContainer } from 'react-toastify'; +import { useState, useMemo } from 'react'; +import { addItem } from '../api/firebase'; +import { FaPlusSquare } from 'react-icons/fa'; +import { IconButton } from '../components/IconButton'; +import { notify } from '../utils/notifications'; + +export function AddItem({ listPath, data }) { + const [itemName, setItemName] = useState(''); + const [daysUntilNextPurchase, setDaysUntilNextPurchase] = useState(7); + + const messages = { + added: 'Your item was successfully added!', + failed: + "Your item wasn't added! There was an error saving the item. Please try again.", + empty: 'Please enter an item to add to your list.', + duplicate: 'Item already exists!', + }; + + const extractedListName = listPath.match(/(?<=\/).*$/)[0]; + + const normalizeString = (str) => + str.toLowerCase().replace(/[^a-z0-9-]+/g, ''); + + const normalizedData = useMemo( + () => data.map((item) => normalizeString(item.name)), + [data], + ); + const handleSubmit = async (event) => { + event.preventDefault(); + + const normalizedItemName = normalizeString(itemName.trim()); + + if (!normalizedItemName) { + notify(messages['empty'], 'warning'); + return; + } + + const itemMatch = normalizedData.includes(normalizedItemName); + + if (itemMatch) { + notify(messages['duplicate'], 'warning'); + return; + } + + try { + await addItem(listPath, { + itemName: normalizedItemName, + daysUntilNextPurchase, + }); + setItemName(''); + setDaysUntilNextPurchase(7); + notify(messages['added'], 'success'); + } catch (error) { + console.error('Error adding item:', error); + notify(messages['failed'], 'error'); + } + }; + + return ( +
+ +

+ Manage Your Shopping List for{' '} + {extractedListName} +

+
+
+ + setItemName(e.target.value)} + placeholder="Add an item name" + className="border border-gray-300 rounded-lg p-2 w-full focus:ring focus:ring-blue-300 focus:outline-none transition duration-150 ease-in-out hover:shadow-md" + /> +
+
+ + How soon will you need to buy this item again? + +
+
+ +
+ +
+ +
+ +
+ +
+
+
+
+ +
+
+

+
+ ); +} diff --git a/src/views/CreateList.jsx b/src/views/CreateList.jsx index 8a8cb5f..359008e 100644 --- a/src/views/CreateList.jsx +++ b/src/views/CreateList.jsx @@ -9,11 +9,11 @@ export function CreateList({ isCreateListModalOpen, setIsCreateListModalOpen, user, + setListPath, }) { const userId = user?.uid; const userEmail = user?.email; - const [listPath, setListPath] = useState(''); const [listName, setListName] = useState(''); const handleChange = (event) => { @@ -25,8 +25,9 @@ export function CreateList({ if (listName) { try { const newListPath = await createList(userId, userEmail, listName); - notify('List is sucessfully created', 'success'); setListPath(newListPath); + setIsCreateListModalOpen(false); + notify(`${listName} is sucessfully created`, 'success'); } catch { notify('There was an error adding your list', 'error'); } @@ -58,7 +59,7 @@ export function CreateList({ setIsCreateListModalOpen(false)} - className="inline-flex justify-center rounded-md bg-[#184E77] px-4 py-[.75rem] text-lg font-medium text-white shadow-sm ring-1 ring-gray-300 hover:bg-[#1E6091] transition duration-200 ease-in-out" // Increased button padding and font size + className="inline-flex justify-center rounded-md bg-btnPrimary px-4 py-[.75rem] text-lg font-medium text-white shadow-sm ring-1 ring-gray-300 hover:bg-btnPrimary transition duration-200 ease-in-out" // Increased button padding and font size label="Cancel" IconComponent={FaTimes} /> diff --git a/src/views/Disclosure.jsx b/src/views/Disclosure.jsx index 3ae2639..4e7940f 100644 --- a/src/views/Disclosure.jsx +++ b/src/views/Disclosure.jsx @@ -17,7 +17,7 @@ export function Disclosure({ listpath, setListPath, }) { - const [isOpen, setIsOpen] = useState(false); + const [isOpen, setIsOpen] = useState(listpath === currentListPath); useEffect(() => { if (currentListPath !== listpath) { diff --git a/src/views/Home.jsx b/src/views/Home.jsx index 3b2e77a..1a7d583 100644 --- a/src/views/Home.jsx +++ b/src/views/Home.jsx @@ -34,6 +34,7 @@ export function Home({ data, lists, listPath, setListPath, user }) { isCreateListModalOpen={isCreateListModalOpen} setIsCreateListModalOpen={setIsCreateListModalOpen} user={user} + setListPath={setListPath} /> )}
diff --git a/src/views/Layout.jsx b/src/views/Layout.jsx index 0b52e4a..5fafc1c 100644 --- a/src/views/Layout.jsx +++ b/src/views/Layout.jsx @@ -53,7 +53,7 @@ export function Layout() { IconComponent={FaCartPlus} //className label="Add Item" - to="/manage-list" + to="/add-item" /> - str.toLowerCase().replace(/[^a-z0-9-]+/g, ''); - - const normalizedData = useMemo( - () => data.map((item) => normalizeString(item.name)), - [data], - ); - const handleSubmit = async (event) => { - event.preventDefault(); - - const normalizedItemName = normalizeString(itemName.trim()); - - if (!normalizedItemName) { - notify(messages['empty'], 'warning'); - return; - } - - const itemMatch = normalizedData.includes(normalizedItemName); - - if (itemMatch) { - notify(messages['duplicate'], 'warning'); - return; - } - - try { - await addItem(listPath, { - itemName: normalizedItemName, - daysUntilNextPurchase, - }); - setItemName(''); - setDaysUntilNextPurchase(7); - notify(messages['added'], 'success'); - } catch (error) { - console.error('Error adding item:', error); - notify(messages['failed'], 'error'); - } - }; - - return ( -
- -

Manage Your Shopping List for {extractedListName}

-
- - setItemName(e.target.value)} - /> - -
- How soon will you need to buy this item again? - {' '} -
- {' '} -
- -
-
- -

-
- ); -} diff --git a/src/views/index.js b/src/views/index.js index b2ff773..a928cb8 100644 --- a/src/views/index.js +++ b/src/views/index.js @@ -1,4 +1,4 @@ -export * from './ManageList'; +export * from './AddItem'; export * from './Home'; export * from './Layout'; export * from './LandingPage'; diff --git a/tailwind.config.js b/tailwind.config.js index 384b66a..7932183 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -10,6 +10,10 @@ export default { txtPrimary: '#184E77', // Primary color Text txtSecondary: '#34A0A4', // Secondary color Text }, + backgroundImage: { + 'radio-gradient': + 'linear-gradient(to top, #34A0A4, #168AAD, #1A759F, #1E6091, #184E77)', + }, }, }, plugins: [],