Skip to content

Commit 4920011

Browse files
Merge pull request #59 from the-collab-lab/st-managelist
Issue #21: Implement TailwindCSS for ManageList page, refactor naming to AddItem page and modal close for Create List.
2 parents dc23352 + 1bbe3db commit 4920011

File tree

9 files changed

+164
-126
lines changed

9 files changed

+164
-126
lines changed

src/App.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
22
import { Suspense } from 'react';
3-
import { Home, Layout, ManageList, Team } from './views';
3+
import { Home, Layout, AddItem, Team } from './views';
44
import { Loading } from './components/Loading';
55
import { ProtectedRoute } from './components/ProtectedRoute';
66
import { useAuth, useShoppingListData, useShoppingLists } from './api';
@@ -59,10 +59,10 @@ export function App() {
5959
}
6060
/>
6161
<Route
62-
path="manage-list"
62+
path="add-item"
6363
element={
6464
<ProtectedRoute>
65-
<ManageList listPath={listPath} user={user} data={data} />
65+
<AddItem listPath={listPath} user={user} data={data} />
6666
</ProtectedRoute>
6767
}
6868
/>

src/views/AddItem.jsx

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import { ToastContainer } from 'react-toastify';
2+
import { useState, useMemo } from 'react';
3+
import { addItem } from '../api/firebase';
4+
import { FaPlusSquare } from 'react-icons/fa';
5+
import { IconButton } from '../components/IconButton';
6+
import { notify } from '../utils/notifications';
7+
8+
export function AddItem({ listPath, data }) {
9+
const [itemName, setItemName] = useState('');
10+
const [daysUntilNextPurchase, setDaysUntilNextPurchase] = useState(7);
11+
12+
const messages = {
13+
added: 'Your item was successfully added!',
14+
failed:
15+
"Your item wasn't added! There was an error saving the item. Please try again.",
16+
empty: 'Please enter an item to add to your list.',
17+
duplicate: 'Item already exists!',
18+
};
19+
20+
const extractedListName = listPath.match(/(?<=\/).*$/)[0];
21+
22+
const normalizeString = (str) =>
23+
str.toLowerCase().replace(/[^a-z0-9-]+/g, '');
24+
25+
const normalizedData = useMemo(
26+
() => data.map((item) => normalizeString(item.name)),
27+
[data],
28+
);
29+
const handleSubmit = async (event) => {
30+
event.preventDefault();
31+
32+
const normalizedItemName = normalizeString(itemName.trim());
33+
34+
if (!normalizedItemName) {
35+
notify(messages['empty'], 'warning');
36+
return;
37+
}
38+
39+
const itemMatch = normalizedData.includes(normalizedItemName);
40+
41+
if (itemMatch) {
42+
notify(messages['duplicate'], 'warning');
43+
return;
44+
}
45+
46+
try {
47+
await addItem(listPath, {
48+
itemName: normalizedItemName,
49+
daysUntilNextPurchase,
50+
});
51+
setItemName('');
52+
setDaysUntilNextPurchase(7);
53+
notify(messages['added'], 'success');
54+
} catch (error) {
55+
console.error('Error adding item:', error);
56+
notify(messages['failed'], 'error');
57+
}
58+
};
59+
60+
return (
61+
<div className="container p-6 rounded-lg shadow-md">
62+
<ToastContainer />
63+
<h1 className="text-4xl text-txtPrimary font-semibold my-6 text-center">
64+
Manage Your Shopping List for{' '}
65+
<span className="text-txtSecondary font-bold">{extractedListName}</span>
66+
</h1>
67+
<form onSubmit={handleSubmit} className="space-y-6">
68+
<div className="flex flex-col mb-4 items-center">
69+
<label
70+
htmlFor="itemName"
71+
className="text-3xl text-txtPrimary font-semibold"
72+
>
73+
Please enter an item name
74+
</label>
75+
<input
76+
type="text"
77+
id="itemName"
78+
value={itemName}
79+
onChange={(e) => setItemName(e.target.value)}
80+
placeholder="Add an item name"
81+
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"
82+
/>
83+
</div>
84+
<fieldset className="border border-gray-200 p-8 m-6 rounded-lg shadow-md">
85+
<legend className="text-3xl text-txtPrimary mb-4 font-semibold">
86+
How soon will you need to buy this item again?
87+
</legend>
88+
<div className="grid grid-cols-1 md:grid-cols-3 gap-10 justify-items-center items-center">
89+
<div className="border border-gray-300 p-2 bg-radio-gradient w-[20rem] rounded-lg transition-transform duration-300 hover:scale-105 hover:shadow-lg">
90+
<label className="flex items-center justify-center cursor-pointer w-full mb-4 mt-4">
91+
<input
92+
type="radio"
93+
value={7}
94+
checked={daysUntilNextPurchase === 7}
95+
onChange={() => setDaysUntilNextPurchase(7)}
96+
className="mr-4 text-txtPrimary"
97+
/>
98+
<span className="text-2xl font-medium text-white ">
99+
Soon (7 days)
100+
</span>
101+
</label>
102+
</div>
103+
104+
<div className="border border-gray-300 p-2 bg-radio-gradient w-[20rem] rounded-lg transition-transform duration-300 hover:scale-105 hover:shadow-lg">
105+
<label className="flex items-center justify-center cursor-pointer max-w-sm mb-4 mt-4">
106+
<input
107+
type="radio"
108+
value={14}
109+
checked={daysUntilNextPurchase === 14}
110+
onChange={() => setDaysUntilNextPurchase(14)}
111+
className="mr-6"
112+
/>
113+
<span className="text-2xl font-medium text-white ">
114+
Kind of soon (14 days)
115+
</span>
116+
</label>
117+
</div>
118+
119+
<div className="border border-gray-300 p-2 bg-radio-gradient w-[20rem] rounded-lg transition-transform duration-300 hover:scale-105 hover:shadow-lg">
120+
<label className="flex items-center justify-center cursor-pointer max-w-md mb-4 mt-4">
121+
<input
122+
type="radio"
123+
value={30}
124+
checked={daysUntilNextPurchase === 30}
125+
onChange={() => setDaysUntilNextPurchase(30)}
126+
className="mr-3"
127+
/>
128+
<span className="text-2xl font-medium text-white ">
129+
Not soon (30 days)
130+
</span>
131+
</label>
132+
</div>
133+
</div>
134+
</fieldset>
135+
<div className="flex justify-center">
136+
<IconButton
137+
aria-label="Add item to your list"
138+
as="button"
139+
label="Add an item"
140+
IconComponent={FaPlusSquare}
141+
className="mt-1 block w-1/8 rounded-md border border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 sm:text-lg py-3 px-4"
142+
/>
143+
</div>
144+
</form>
145+
<br></br>
146+
</div>
147+
);
148+
}

src/views/CreateList.jsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ export function CreateList({
99
isCreateListModalOpen,
1010
setIsCreateListModalOpen,
1111
user,
12+
setListPath,
1213
}) {
1314
const userId = user?.uid;
1415
const userEmail = user?.email;
1516

16-
const [listPath, setListPath] = useState('');
1717
const [listName, setListName] = useState('');
1818

1919
const handleChange = (event) => {
@@ -25,8 +25,9 @@ export function CreateList({
2525
if (listName) {
2626
try {
2727
const newListPath = await createList(userId, userEmail, listName);
28-
notify('List is sucessfully created', 'success');
2928
setListPath(newListPath);
29+
setIsCreateListModalOpen(false);
30+
notify(`${listName} is sucessfully created`, 'success');
3031
} catch {
3132
notify('There was an error adding your list', 'error');
3233
}
@@ -58,7 +59,7 @@ export function CreateList({
5859
<IconButton
5960
aria-label="Add a list"
6061
as="button"
61-
className="inline-flex justify-center rounded-md bg-[#184E77] px-4 py-[.75rem] text-lg font-medium text-white shadow-sm hover:bg-[#1E6091] transition duration-200 ease-in-out mr-10"
62+
className="inline-flex justify-center rounded-md bg-btnPrimary px-4 py-[.75rem] text-lg font-medium text-white shadow-sm hover:bg-btnPrimary transition duration-200 ease-in-out mr-10"
6263
label="Add"
6364
IconComponent={FaPlusSquare}
6465
type="submit"
@@ -67,7 +68,7 @@ export function CreateList({
6768
aria-label="Cancel adding"
6869
as="button"
6970
onClick={() => setIsCreateListModalOpen(false)}
70-
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
71+
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
7172
label="Cancel"
7273
IconComponent={FaTimes}
7374
/>

src/views/Disclosure.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export function Disclosure({
1717
listpath,
1818
setListPath,
1919
}) {
20-
const [isOpen, setIsOpen] = useState(false);
20+
const [isOpen, setIsOpen] = useState(listpath === currentListPath);
2121

2222
useEffect(() => {
2323
if (currentListPath !== listpath) {

src/views/Home.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ export function Home({ data, lists, listPath, setListPath, user }) {
3434
isCreateListModalOpen={isCreateListModalOpen}
3535
setIsCreateListModalOpen={setIsCreateListModalOpen}
3636
user={user}
37+
setListPath={setListPath}
3738
/>
3839
)}
3940
<div className="flex justify-center items-center">

src/views/Layout.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function Layout() {
5353
IconComponent={FaCartPlus}
5454
//className
5555
label="Add Item"
56-
to="/manage-list"
56+
to="/add-item"
5757
/>
5858
<IconButton
5959
aria-label="Sign Out"

src/views/ManageList.jsx

Lines changed: 0 additions & 116 deletions
This file was deleted.

src/views/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
export * from './ManageList';
1+
export * from './AddItem';
22
export * from './Home';
33
export * from './Layout';
44
export * from './LandingPage';

tailwind.config.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ export default {
1010
txtPrimary: '#184E77', // Primary color Text
1111
txtSecondary: '#34A0A4', // Secondary color Text
1212
},
13+
backgroundImage: {
14+
'radio-gradient':
15+
'linear-gradient(to top, #34A0A4, #168AAD, #1A759F, #1E6091, #184E77)',
16+
},
1317
},
1418
},
1519
plugins: [],

0 commit comments

Comments
 (0)