Skip to content

Commit

Permalink
conversion and modals
Browse files Browse the repository at this point in the history
  • Loading branch information
allen-liaoo committed May 3, 2024
1 parent d9b6cc9 commit 26cd9ee
Show file tree
Hide file tree
Showing 29 changed files with 772 additions and 539 deletions.
39 changes: 35 additions & 4 deletions api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,7 +225,7 @@ app.http('getFoods', {
const userId = token.userId;
const name = token.userDetails;
const client = await mongoClient.connect(process.env.AZURE_MONGO_DB);
const foods = await client.db("LetMeCookDB").collection("foods").find({userId: userId}).project({name: 1, quantity: 1, image: 1, expirationDate: 1}).toArray();
const foods = await client.db("LetMeCookDB").collection("foods").find({userId: userId}).project({name: 1, quantity: 1, image: 1, expirationDate: 1, unit: 1, timestamp: 1}).toArray();
// const userInfo = await client.db("LetMeCookDB").collection("users").findOne({name: name, userId: userId});
// const foods = userInfo.foods;
client.close();
Expand Down Expand Up @@ -379,8 +379,10 @@ app.http("insertFood", {
const timeElapsed = Date.now();
const today = new Date(timeElapsed);
const expirationDate = today.toLocaleDateString();
const timestamp = new Date(Date.now());
const unit = "";
// const expirationDate = null;
const payload = {userId, apiId, name, image, quantity, expirationDate};
const payload = {userId, apiId, name, image, quantity, expirationDate, timestamp, unit};
// context.log("payload= " + JSON.stringify(payload));
const client = await mongoClient.connect(process.env.AZURE_MONGO_DB);
const result = await client.db("LetMeCookDB").collection("foods").insertOne(payload);
Expand Down Expand Up @@ -530,7 +532,8 @@ app.http('checkUser', {
if (!res) {
const foods = [];
const recipes = [];
const payload = { name, userId, foods, recipes };
const recipeQueue = [];
const payload = { name, userId, foods, recipes, recipeQueue };
res = await client.db("LetMeCookDB").collection("users").insertOne(payload);
client.close();
// context.log("user was created!");
Expand Down Expand Up @@ -593,10 +596,11 @@ app.http('editFood', {
const name = body.name;
const quantity = ((body.quantity >= 0) ? body.quantity : 0);
const expirationDate = body.expirationDate;
const unit = body.unit;
const client = await mongoClient.connect(process.env.AZURE_MONGO_DB);
const result = await client.db("LetMeCookDB").collection("foods")
.updateOne({_id: new ObjectId(_id), userId: userId},
{$set: {name: name, quantity: quantity, expirationDate: expirationDate}});
{$set: {name: name, quantity: quantity, expirationDate: expirationDate, unit: unit}});
client.close();
if (result.matchedCount > 0) {
return {
Expand Down Expand Up @@ -1082,6 +1086,33 @@ app.http('lowestFoods', {
},
});

app.http('getFoodsByTimestamp', {
methods: ['GET'],
authLevel: 'anonymous',
route: 'foods/timestamp',
handler: async (request, context) => {
const auth_header = request.headers.get('X-MS-CLIENT-PRINCIPAL');
let token = null;
if (auth_header) {
token = Buffer.from(auth_header, "base64");
token = JSON.parse(token.toString());
// context.log("token= " + JSON.stringify(token));
const userId = token.userId;
const client = await mongoClient.connect(process.env.AZURE_MONGO_DB);
const foods = client.db("LetMeCookDB").collection("foods").find({userId: userId}, { $orderby: {timestamp: -1} }).toArray();
client.close();
return {
status: 201,
jsonBody: {foods: foods}
}
}
return {
status: 405,
jsonBody: {error: "Unable to authorize user to obtain foods by timestamp"}
}
},
});

app.http('searchUserRecipes', {
methods: ['GET'],
authLevel: 'anonymous',
Expand Down
12 changes: 6 additions & 6 deletions src/components/EditButton.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styles from '../css/Buttons.module.css';
export default function EditButton({...props}){
return <div>
<button className={styles.editButton} {...props}> Edit </button>
</div>
}
// import styles from '../css/Buttons.module.css';
// export default function EditButton({...props}){
// return <div>
// <button className={styles.editButton} {...props}> Edit </button>
// </div>
// }
234 changes: 234 additions & 0 deletions src/components/FoodItem.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
import 'bootstrap/dist/css/bootstrap.min.css';
import styles from "../css/QueueItem.module.css";
import Layout from "../css/ItemPageLayout.module.css";
import Card from 'react-bootstrap/Card';
import ListGroup from 'react-bootstrap/ListGroup';
import { ReactComponent as UploadImage } from '../assets/upload.svg'
import { ReactComponent as EditSVG } from '../assets/edit.svg'
import { ReactComponent as DeleteSVG } from '../assets/delete.svg'
import { useState, useEffect } from 'react';
import SaveButton from './SaveButton'
import RemoveButton from './RemoveButton'

export default function FoodItem({ food }) {
const [editMode, setEditMode] = useState(0);
const [name,setName] = useState(food.name ?? "")
const [image, setImage] = useState(food.image ?? "")
const [newImageFile, setNewImageFile] = useState(null)
const [quantity, setQuantity] = useState(food.quantity ?? 0)
const [unit, setUnit] = useState(food.unit ?? "")
const [expirationDate, setExpirationDate] = useState(food.expirationDate ?? "")
const [setofclasses, setSetofClasses] = useState(styles.wholeCard +" "+Layout.centerrow)
const [getinfo,setGetinfo] = useState(true);
const [isNoQuantity,setIsNoQuantity] = useState(false);
const [isExpired,setIsExpired] = useState(false);
const [imgFiles] = useState([]);
useEffect(() => {
(async () => {
if(getinfo){
const res = await fetch("/api/food/"+food._id, { method: "GET" })
if (!res.ok) {
console.log(res)
window.alert("Error getting food on edit food page!")
return
}
const resJson = await res.json()
const newFood = resJson.food
console.log("updating");
console.log(newFood);
setName(newFood.name)
setImage(newFood.image)
setQuantity(newFood.quantity)
setUnit(newFood.units)
setExpirationDate(newFood.expirationDate)
setExpirationDateAndQuantity(food);
}})()
}, [editMode, getinfo]);

async function editFood() {
const res = await fetch('/api/food/edit/'+food._id, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
name: name,
quantity: quantity,
expirationDate: expirationDate,
unit: unit
})
})
console.log('Editing Food', res)
if (!res.ok) {
window.alert("Failed editing food!")
return
}

if (newImageFile != null) {
const formData = new FormData()
formData.append('image', newImageFile)
const res = await fetch('/api/food/edit/image/'+food._id, {
method: "POST",
// headers: {
// "Content-Type": "multipart/form-data"
// }, // dont specify content type so it is set with boundary
body: formData
})
console.log('Changing image of food', res)
if (!res.ok) {
window.alert("Failed to change image of food!")
return
}
}

//navigate('/food/' + id)
setEditMode(false)
}

function setExpirationDateAndQuantity(food) {
const curTime = getCurTime();
if (!food.expirationDate || food.expirationDate === "NA" || food.expirationDate < curTime) {
console.log("Adding expired flag");
setIsNoQuantity(true);
}
if (!food.quantity || food.quantity === "NA" || food.quantity <= 0) {
console.log("Adding noQuantity flag");
setIsExpired(true);
}
}

async function removeFood() {
const res = await fetch('/api/food/delete/'+food._id, { method: "POST" })
console.log('Deleting Food', res)
if (!res.ok) {
window.alert("Failed deleting food!")
return
}
//navigate('/foods')
setSetofClasses(styles.wholeCard +" "+Layout.centerrow+" "+Layout.hidden)
setGetinfo(false)
setEditMode(false)
console.log(editMode)
}

// Gets String of current date in yyyy-mm-dd format
function getCurTime() {
const curDate = new Date();
var curYear = String(curDate.getFullYear());
var curMonth = String(curDate.getMonth() + 1); // 0-indexed
var curDay = String(curDate.getDate());
if (curDay.length < 2) {
curDay = "0" + curDay;
}
if (curMonth.length < 2) {
curMonth = "0" + curMonth;
}
var curTime = curYear + "-" + curMonth + "-" + curDay;
return curTime;
}

async function uploadImage(e) {
if (e.target.files.length <= 0) return
const file = e.target.files.item(0);
console.log("Image selected", file)
if (file.size > 10000000) { // 10,000,000 bytes = 10 mb
console.alert("Image file is too large (> 10mb)!")
return
}
setNewImageFile(file)
}

if(editMode){
return(
<div className={setofclasses}>

<Card className={styles.customCard}>
<Card.Body className={styles.cardBody}>
<div className={styles.innerBodyContainer}>
<label htmlFor="file-input" className={styles.imgcontainer}>

{image?
<Card.Img className={styles.cardImg} src={image}/>
: <div className={styles.cardImgHolder} ></div> }

<UploadImage className={styles.uploadSvg}/>
</label>
{/* Upload image */}
<input id="file-input" type="file" accept="image/*" capture="environment"
value={imgFiles}
onChange={uploadImage} className={styles.hidden}/>

<div className={styles.cardTextContainer}>
{/* Change text */}
<input className={styles.inputTitle}
value={name} onInput={(e)=>setName(e.target.value)}
maxLength="50" />
</div>

</div>
</Card.Body>
<ListGroup variant="flush">
<ListGroup.Item className={`list-group-flush`}>
<div className={Layout.text}>Quantity: &ensp;
<input type="text"
value={quantity} onChange={(e)=>setQuantity(e.target.value)}
min="0"/>
</div>
</ListGroup.Item>

<ListGroup.Item className="list-group-flush">
<div className={Layout.text}>Unit: &ensp;
<input type="text"
value={unit} onChange={(e)=>setUnit(e.target.value)} />
</div>
</ListGroup.Item>

<ListGroup.Item className={`list-group-flush`}>
<div className={`Layout.text`}>Expiration Date: &ensp;
<input type="date" value={expirationDate} onChange={(e)=>setExpirationDate(e.target.value)}/>
</div>
</ListGroup.Item>
<ListGroup.Item className="list-group-flush">
<div className = {Layout.centerrow}>
<RemoveButton onClick={removeFood}/>
<SaveButton onClick={editFood}/>
</div>
</ListGroup.Item>
</ListGroup>
</Card>
</div>)
} else {
return (
<div className={setofclasses}>
<Card className={styles.customCard}>
<Card.Body>
<div className={styles.innerBodyContainer}>
<Card.Img className={styles.cardImg} src={image}/>
<div className={styles.cardTextContainer}>
<Card.Text className={styles.cardText}>{name}</Card.Text>
</div>
<button className={styles.iconContainer+" "+styles.editButton} value="" onClick={(e)=>setEditMode(true)}>
<EditSVG />
</button>
</div>
</Card.Body>

<ListGroup variant="flush">

<ListGroup.Item className={`${isNoQuantity ? Layout.noQuantity : ''} ${Layout.text} list-group-flush`}>
Quantiny: { quantity ? quantity : "NA"}
</ListGroup.Item>

<ListGroup.Item className={Layout.text+" "+"list-group-flush"}>
Unit: { unit ? unit : "NA"}
</ListGroup.Item>

<ListGroup.Item className={`${isExpired ? Layout.expired : ''} ${Layout.text} list-group-flush`}>
Expiration Date: { expirationDate ? expirationDate : "NA"}
</ListGroup.Item>
</ListGroup>

</Card>
</div>)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ function LinkFood({ ingredient, hidePopup }) {

function linkIngredient(foodId) {
ingredient.foodId = foodId
hidePopup()
hidePopup(ingredient)
}

return (
<Modal show="true" animation={false} onHide={hidePopup}>
<Modal show="true" animation={false} onHide={()=>hidePopup(ingredient)}>
<Modal.Header closeButton>
<Modal.Title>Link {ingredient.name}</Modal.Title>
<Modal.Title>Searching pantry for "{ingredient ? ingredient.name : ''}"</Modal.Title>
</Modal.Header>
<Modal.Body>
{ results && results.length !== 0 ?
Expand All @@ -41,7 +41,7 @@ function LinkFood({ ingredient, hidePopup }) {
<div key={i} onClick={()=>linkIngredient(e._id)}>
<SearchResult name={ e.name } image ={e.image}></SearchResult>
</div>
) : <></> }
) : <>{'\"' + ingredient.name + '\" not in pantry'}</> }
</Modal.Body>
{/* <Modal.Footer>
<button>
Expand Down
Loading

0 comments on commit 26cd9ee

Please sign in to comment.