Skip to content

Commit

Permalink
Issue #9 - Marking item as purchased (#28)
Browse files Browse the repository at this point in the history
* add checkbox to ListItem

* updated isPurchased handling

* Passed through listPath, added updateDoc to firebase function, debugging list item

* passed listPath to ListItem, added useEffect to update isPurchased, changed updateItem function in firebase

* Refactored to remove try/catch in updateItem function

* used setTimeout to uncheck boxes for items that were purchased more than a day ago

* debugged checkbox

* Changed to useMemo, updated timeout to use milliseconds in a day

* Changed to useMemo, updated timeout to use milliseconds in a day

* Decrement in the db when user unchecks before 24hrs is up, moved async purchaseItem function into changeHandler and removed useEffect

* Revert "Decrement in the db when user unchecks before 24hrs is up, moved async purchaseItem function into changeHandler and removed useEffect"

This reverts commit d5688d8.

* Decrement in the db when user unchecks before 24hrs is up, moved async purchaseItem function into changeHandler and removed useEffect

* removed unnecessary comments, added in intentional comments

* Switched changeHandler to function expression

* Added updateTimer function to calculate remaining time, updated useEffeect to use remaining time in setTimeout

* Updated setTimeout if statement

* Update src/components/ListItem.jsx

Co-authored-by: Raynaldo Sutisna <[email protected]>

* refactored to prevent timer running when purchasedOneDayAgo is false

---------

Co-authored-by: Devina Gillis <[email protected]>
Co-authored-by: Devina Gillis <[email protected]>
Co-authored-by: Raynaldo Sutisna <[email protected]>
  • Loading branch information
4 people authored Mar 3, 2024
1 parent bb10418 commit 166fd84
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 10 deletions.
14 changes: 8 additions & 6 deletions src/api/firebase.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
doc,
onSnapshot,
updateDoc,
increment,
} from 'firebase/firestore';
import { useEffect, useState } from 'react';
import { db } from './config';
Expand Down Expand Up @@ -186,12 +187,13 @@ export async function addItem(listPath, { itemName, daysUntilNextPurchase }) {
return newItem;
}

export async function updateItem() {
/**
* TODO: Fill this out so that it uses the correct Firestore function
* to update an existing item. You'll need to figure out what arguments
* this function must accept!
*/
export async function updateItem(listPath, itemID, isChecked) {
const listRef = doc(db, listPath, 'items', itemID);

await updateDoc(listRef, {
dateLastPurchased: isChecked ? new Date() : null,
totalPurchases: isChecked ? increment(1) : increment(-1),
});
}

export async function deleteItem() {
Expand Down
69 changes: 67 additions & 2 deletions src/components/ListItem.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,70 @@
import './ListItem.css';
import { updateItem } from '../api/firebase.js';
import { useState, useEffect, useMemo } from 'react';
import { ONE_DAY_IN_MILLISECONDS } from '../utils/dates.js';

export function ListItem({ name }) {
return <li className="ListItem">{name}</li>;
export function ListItem({ listPath, item }) {
/* Returns a boolean that is passed into isChecked useState
On render, box is checked if purchased less than a day ago */

const purchasedOneDayAgo = useMemo(() => {
if (item.dateLastPurchased === null) {
return false;
}

const timeDiff = Date.now() - item.dateLastPurchased.seconds * 1000;
return timeDiff <= ONE_DAY_IN_MILLISECONDS;
}, [item.dateLastPurchased]);

const [isChecked, setIsChecked] = useState(purchasedOneDayAgo);
const changeHandler = (e) => {
setIsChecked(!isChecked);
async function purchaseItem() {
try {
await updateItem(listPath, item.id, !isChecked);
} catch (error) {
alert(error.message);
}
}
purchaseItem();
};

//Calculate time remaining if purchase was less than 24 hours ago
const updateTimer = () => {
if (item.dateLastPurchased) {
const timeElapsed = Date.now() - item.dateLastPurchased.seconds * 1000;
if (timeElapsed < ONE_DAY_IN_MILLISECONDS) {
return ONE_DAY_IN_MILLISECONDS - timeElapsed;
} else {
return 0;
}
}
};

//sets a timer to uncheck an item 24 hours after it's purchased
useEffect(() => {
if (purchasedOneDayAgo) {
let timeRemaining = updateTimer();

const timer = setTimeout(() => {
setIsChecked(false);
}, timeRemaining);
return () => clearTimeout(timer);
}
}, [isChecked, purchasedOneDayAgo]);

return (
<li className="ListItem">
<label htmlFor={item.name}>
{item.name}
<input
type="checkbox"
id={item.name}
name="purchased"
onChange={changeHandler}
checked={isChecked}
/>
</label>
</li>
);
}
2 changes: 1 addition & 1 deletion src/utils/dates.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const ONE_DAY_IN_MILLISECONDS = 86400000;
export const ONE_DAY_IN_MILLISECONDS = 86400000;

/**
* Get a new JavaScript Date that is `offset` days in the future.
Expand Down
4 changes: 3 additions & 1 deletion src/views/List.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import { ListItem } from '../components';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';


export function List({ data, listPath }) {

const [searchTerm, setSearchTerm] = useState('');

const navigate = useNavigate();
Expand Down Expand Up @@ -62,7 +64,7 @@ export function List({ data, listPath }) {
) : null}
<ul>
{filteredData.map((item) => {
return <ListItem key={item.id} name={item.name} />;
return <ListItem key={item.id} item={item} listPath={listPath} />;
})}
</ul>
</>
Expand Down

0 comments on commit 166fd84

Please sign in to comment.