Skip to content

Commit 98452a7

Browse files
authored
Merge pull request #35 from the-collab-lab/rt-code-cleanup
Rt code cleanup
2 parents 422f1b3 + 7bddd57 commit 98452a7

File tree

8 files changed

+30
-119
lines changed

8 files changed

+30
-119
lines changed

noun-home-icon-3574480.svg

Lines changed: 1 addition & 0 deletions
Loading

src/App.jsx

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,17 @@ import { useAuth, useShoppingListData, useShoppingLists } from './api';
77
import { useStateWithStorage } from './utils';
88

99
export function App() {
10-
/**
11-
* This custom hook takes the path of a shopping list
12-
* in our database and syncs it with localStorage for later use.
13-
* Check ./utils/hooks.js for its implementation.
14-
*
15-
* We'll later use `setListPath` when we allow a user
16-
* to create and switch between lists.
17-
*/
1810
const [listPath, setListPath] = useStateWithStorage(
1911
'tcl-shopping-list-path',
2012
null,
2113
);
2214

23-
/**
24-
* This custom hook holds info about the current signed in user.
25-
* Check ./api/useAuth.jsx for its implementation.
26-
*/
2715
const { user } = useAuth();
2816
const userId = user?.uid;
2917
const userEmail = user?.email;
3018

31-
/**
32-
* This custom hook takes a user ID and email and fetches
33-
* the shopping lists that the user has access to.
34-
* Check ./api/firestore.js for its implementation.
35-
*/
3619
const lists = useShoppingLists(userId, userEmail);
37-
/**
38-
* This custom hook takes our token and fetches the data for our list.
39-
* Check ./api/firestore.js for its implementation.
40-
*/
20+
4121
const data = useShoppingListData(listPath);
4222

4323
return (

src/api/firebase.js

Lines changed: 15 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,17 @@ import { calculateEstimate } from '@the-collab-lab/shopping-list-utils';
2222
* @returns
2323
*/
2424
export function useShoppingLists(userId, userEmail) {
25-
// Start with an empty array for our data.
2625
const initialState = [];
2726
const [data, setData] = useState(initialState);
2827

2928
useEffect(() => {
30-
// If we don't have a userId or userEmail (the user isn't signed in),
31-
// we can't get the user's lists.
3229
if (!userId || !userEmail) return;
33-
34-
// When we get a userEmail, we use it to subscribe to real-time updates
3530
const userDocRef = doc(db, 'users', userEmail);
3631

3732
onSnapshot(userDocRef, (docSnap) => {
3833
if (docSnap.exists()) {
3934
const listRefs = docSnap.data().sharedLists;
4035
const newData = listRefs.map((listRef) => {
41-
// We keep the list's id and path so we can use them later.
4236
return { name: listRef.id, path: listRef.path };
4337
});
4438
setData(newData);
@@ -56,36 +50,25 @@ export function useShoppingLists(userId, userEmail) {
5650
* @see https://firebase.google.com/docs/firestore/query-data/listen
5751
*/
5852
export function useShoppingListData(listPath) {
59-
// Start with an empty array for our data.
6053
/** @type {import('firebase/firestore').DocumentData[]} */
6154
const initialState = [];
6255
const [data, setData] = useState(initialState);
6356

6457
useEffect(() => {
6558
if (!listPath) return;
6659

67-
// When we get a listPath, we use it to subscribe to real-time updates
68-
// from Firestore.
6960
return onSnapshot(collection(db, listPath, 'items'), (snapshot) => {
70-
// The snapshot is a real-time update. We iterate over the documents in it
71-
// to get the data.
7261
const nextData = snapshot.docs.map((docSnapshot) => {
73-
// Extract the document's data from the snapshot.
7462
const item = docSnapshot.data();
7563

76-
// The document's id is not in the data,
77-
// but it is very useful, so we add it to the data ourselves.
7864
item.id = docSnapshot.id;
7965

8066
return item;
8167
});
8268

83-
// Update our React state with the new data.
8469
setData(nextData);
8570
});
8671
}, [listPath]);
87-
88-
// Return the data so it can be used by our React components.
8972
return data;
9073
}
9174

@@ -94,16 +77,11 @@ export function useShoppingListData(listPath) {
9477
* @param {Object} user The user object from Firebase Auth.
9578
*/
9679
export async function addUserToDatabase(user) {
97-
// Check if the user already exists in the database.
9880
const userDoc = await getDoc(doc(db, 'users', user.email));
99-
// If the user already exists, we don't need to do anything.
81+
10082
if (userDoc.exists()) {
10183
return;
10284
} else {
103-
// If the user doesn't exist, add them to the database.
104-
// We'll use the user's email as the document id
105-
// because it's more likely that the user will know their email
106-
// than their uid.
10785
await setDoc(doc(db, 'users', user.email), {
10886
email: user.email,
10987
name: user.displayName,
@@ -138,18 +116,16 @@ export async function createList(userId, userEmail, listName) {
138116
* @param {string} recipientEmail The email of the user to share the list with.
139117
*/
140118
export async function shareList(listPath, currentUserId, recipientEmail) {
141-
// Check if current user is owner.
142119
if (!listPath.includes(currentUserId)) {
143120
throw new Error('You do not have permission to share this list');
144121
}
145-
// Get the document for the recipient user.
122+
146123
const usersCollectionRef = collection(db, 'users');
147124
const recipientDoc = await getDoc(doc(usersCollectionRef, recipientEmail));
148-
// If the recipient user doesn't exist, we can't share the list.
125+
149126
if (!recipientDoc.exists()) {
150127
throw new Error('The user with the provided email does not exist');
151128
}
152-
// Add the list to the recipient user's sharedLists array.
153129
const listDocumentRef = doc(db, listPath);
154130
const userDocumentRef = doc(db, 'users', recipientEmail);
155131
await updateDoc(userDocumentRef, {
@@ -167,13 +143,10 @@ export async function shareList(listPath, currentUserId, recipientEmail) {
167143
*/
168144
export async function addItem(listPath, { itemName, daysUntilNextPurchase }) {
169145
const listCollectionRef = await collection(db, listPath, 'items');
170-
// TODO: Replace this call to console.log with the appropriate
171-
// Firebase function, so this information is sent to your database!
146+
172147
try {
173148
await addDoc(listCollectionRef, {
174149
dateCreated: new Date(),
175-
// NOTE: This is null because the item has just been created.
176-
// We'll use updateItem to put a Date here when the item is purchased!
177150
dateLastPurchased: null,
178151
dateNextPurchased: getFutureDate(daysUntilNextPurchase),
179152
name: itemName,
@@ -185,14 +158,7 @@ export async function addItem(listPath, { itemName, daysUntilNextPurchase }) {
185158
}
186159

187160
export async function updateItem(listPath, itemId, { totalPurchases }) {
188-
/**
189-
* TODO: Fill this out so that it uses the correct Firestore function
190-
* to update an existing item. You'll need to figure out what arguments
191-
* this function must accept!
192-
*/
193-
194161
try {
195-
// Get a reference to the specific item document in Firestore
196162
const itemRef = doc(db, listPath, 'items', itemId);
197163
const docSnap = await getDoc(itemRef);
198164
const data = docSnap.data();
@@ -221,11 +187,6 @@ export async function updateItem(listPath, itemId, { totalPurchases }) {
221187
}
222188

223189
export async function deleteItem(listPath, itemId) {
224-
/**
225-
* TODO: Fill this out so that it uses the correct Firestore function
226-
* to delete an existing item. You'll need to figure out what arguments
227-
* this function must accept!
228-
*/
229190
try {
230191
const itemRef = doc(db, listPath, 'items', itemId);
231192
await deleteDoc(itemRef);
@@ -239,12 +200,17 @@ export async function deleteItem(listPath, itemId) {
239200
* Sorts the items in the list according to category using urgencyIndex and inactiveIndex to determine what category an item belongs.
240201
* @param {string} data The path to the data object to sort.
241202
*/
203+
242204
export async function comparePurchaseUrgency(data) {
243205
const now = new Date();
206+
const inactivityPeriod = 60;
207+
const dayOfPurchase = 0;
208+
const soon = 7;
209+
const kindOfSoon = 30;
244210

245211
data.map((item) => {
246212
const urgencyIndex = Math.ceil(
247-
getDaysBetweenDates(now, item.dateNextPurchased.toDate()), //takes the difference between the current date and the date the item is next purchased
213+
getDaysBetweenDates(now, item.dateNextPurchased.toDate()),
248214
);
249215

250216
const lastPurchase = item.dateLastPurchased
@@ -255,26 +221,20 @@ export async function comparePurchaseUrgency(data) {
255221
item.inactiveIndex = inactiveItem;
256222
item.urgencyIndex = urgencyIndex;
257223

258-
if (inactiveItem > 60) {
224+
if (inactiveItem > inactivityPeriod) {
259225
item.category = 'inactive';
260-
} else if (urgencyIndex < 0) {
226+
} else if (urgencyIndex < dayOfPurchase) {
261227
item.category = 'Overdue';
262-
} else if (urgencyIndex <= 7) {
228+
} else if (urgencyIndex <= soon) {
263229
item.category = 'soon';
264-
} else if (urgencyIndex < 30) {
230+
} else if (urgencyIndex < kindOfSoon) {
265231
item.category = 'kind of soon';
266232
} else {
267233
item.category = 'Not soon';
268234
}
269235
return item;
270236
});
271-
/**
272-
* Function to implement custom sort based on inacrtivity, then on urgencyIndex and name
273-
* 1- if urgency of a is inactive and b is not inactive, sort b ontop the top of a
274-
* 2- if urgency of a is not inactive and b is inactive, sort a ontop of b
275-
* 3- if urgency is the same, sort based on UrgencyIndex
276-
* 4- if urgencyIndex is the same, sort based on name
277-
*/
237+
278238
data.sort((a, b) => {
279239
if (a.category === 'inactive' && b.category !== 'inactive') {
280240
return 1;

src/api/useAuth.jsx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ import { auth } from './config.js';
33
import { GoogleAuthProvider, signInWithPopup } from 'firebase/auth';
44
import { addUserToDatabase } from './firebase.js';
55

6-
/**
7-
* A button that signs the user in using Google OAuth. When clicked,
8-
* the button redirects the user to the Google OAuth sign-in page.
9-
* After the user signs in, they are redirected back to the app.
10-
*/
116
export const SignInButton = () => (
127
<button
138
type="button"
@@ -17,9 +12,6 @@ export const SignInButton = () => (
1712
</button>
1813
);
1914

20-
/**
21-
* A button that signs the user out of the app using Firebase Auth.
22-
*/
2315
export const SignOutButton = () => (
2416
<button type="button" onClick={() => auth.signOut()}>
2517
Sign Out

src/components/ListItem.jsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@ import './ListItem.css';
44
export function ListItem({ name, dateLastPurchased, onCheck, onDelete }) {
55
const [isChecked, setIsChecked] = useState(false);
66

7-
// Update `isChecked` based on the `dateLastPurchased` value
87
useEffect(() => {
98
const checkStatus = () => {
109
if (dateLastPurchased) {
1110
const purchaseDate = dateLastPurchased.toDate();
1211
const timeSinceLastPurchase = new Date() - purchaseDate;
1312
const hasBeenPurchasedRecently =
14-
timeSinceLastPurchase < 24 * 60 * 60 * 1000; // 24 hours
13+
timeSinceLastPurchase < 24 * 60 * 60 * 1000;
1514
setIsChecked(hasBeenPurchasedRecently);
1615
} else {
1716
setIsChecked(false);
@@ -26,7 +25,7 @@ export function ListItem({ name, dateLastPurchased, onCheck, onDelete }) {
2625
onDelete();
2726
}
2827
};
29-
28+
3029
return (
3130
<li className="ListItem">
3231
<label>

src/views/Layout.jsx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,6 @@ import { Outlet, NavLink, Link } from 'react-router-dom';
22
import './Layout.css';
33
import { SignInButton, SignOutButton, useAuth } from '../api/useAuth';
44

5-
/**
6-
* TODO: The links defined in this file don't work!
7-
*
8-
* Instead of anchor element, they should use a component
9-
* from `react-router-dom` to navigate to the routes
10-
* defined in `App.jsx`.
11-
*/
12-
135
export function Layout() {
146
const { user } = useAuth();
157
return (

src/views/List.jsx

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,12 @@ export function List({ data, listPath, lists }) {
1313
const [searchItem, setSearchItem] = useState('');
1414
const [errorMsg, setErrorMsg] = useState('');
1515

16-
const [items, setItems] = useState([]); //to store the sorted items for display
17-
18-
//Code segment to sort items using the compareUrgency function from firebase.js
16+
const [items, setItems] = useState([]);
1917
useEffect(() => {
2018
const fetchItems = async () => {
21-
try {
22-
const sortedItems = await comparePurchaseUrgency(data);
23-
setItems(sortedItems);
24-
} catch (error) {
25-
console.log(error);
26-
}
19+
const sortedItems = await comparePurchaseUrgency(data);
20+
setItems(sortedItems);
2721
};
28-
2922
fetchItems();
3023
}, [data]);
3124

@@ -99,6 +92,7 @@ export function List({ data, listPath, lists }) {
9992
id="search-item-in-list"
10093
value={searchItem}
10194
placeholder="Search item..."
95+
aria-label="Search for items"
10296
/>
10397
{searchItem && (
10498
<button type="button" onClick={clearSearch}>
@@ -107,7 +101,7 @@ export function List({ data, listPath, lists }) {
107101
)}
108102
</div>
109103
</form>
110-
{searchItem && (
104+
{searchItem ? (
111105
<ul>
112106
{filterItems.map((item) => (
113107
<ListItem
@@ -120,11 +114,7 @@ export function List({ data, listPath, lists }) {
120114
/>
121115
))}
122116
</ul>
123-
)}
124-
125-
{errorMsg && <p>{errorMsg}</p>}
126-
127-
{
117+
) : (
128118
<ul>
129119
{Object.keys(groupedItems).map((category) => (
130120
<li key={category}>
@@ -145,7 +135,9 @@ export function List({ data, listPath, lists }) {
145135
</li>
146136
))}
147137
</ul>
148-
}
138+
)}
139+
140+
{errorMsg && <p>{errorMsg}</p>}
149141
</>
150142
)}
151143
</>

src/views/ManageList.jsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ export function ManageList({ listPath, userId, data }) {
88
nextPurchase: 0,
99
});
1010
const [messageItem, setMessageItem] = useState('');
11-
1211
const [formAddUser, setFormAddUser] = useState('');
1312
const [messageUser, setMessageUser] = useState('');
1413

@@ -31,25 +30,21 @@ export function ManageList({ listPath, userId, data }) {
3130
return;
3231
}
3332
try {
34-
//Function to normalize the item name and convert to lowercase goes here
3533
const normalizedName = (name) => {
3634
return name
3735
.toLowerCase()
38-
.replace(/[^\w\s]|_/g, '') // for punctuation
39-
.replace(/\s+/g, ''); // for spaces
36+
.replace(/[^\w\s]|_/g, '')
37+
.replace(/\s+/g, '');
4038
};
4139

42-
// check if the item already exists
4340
const itemExists = data.some(
4441
(item) => normalizedName(item.name) === normalizedName(name),
4542
);
4643

47-
// if the item already exists, show an error message
4844
if (itemExists) {
4945
setMessageItem(`${normalizedName(name)} is already in the list`);
5046
return;
5147
}
52-
// if the item does not exist, add it to the list
5348
await addItem(listPath, {
5449
itemName: name,
5550
daysUntilNextPurchase: nextPurchase,

0 commit comments

Comments
 (0)