Bread is an organizational tool where users can form events with each-other and log expenses that are to be split up by others in the event. Centered around an event created by you a friend, Bread can keep track of expenses throughout the night - so you can focus on enjoying your time!
Live Link
- User account creation and authentication
- User can create an event and add party members (friends).
- Expenses are logged/added on by the User as the event progresses.
- When the event is over, the expense is divided equally through a built-in expenses calculator.
- Includes a tip calculator for quick calculation after dinner
- Integrated with an SMS messaging API called Twilio so that users can remind other users in an event how much they owe/are owed.
Implemented logic behind adding expenses by event id.
// routes/expenses.js
router.get("/:id/total", (req, res) => {
Expense.find( {event_id : {$in : req.params.id}})
.then(expense => {
const total = [];
expense.forEach(expense => {
total.unshift(expense.amount)
})
sum = 0;
total.forEach(decimal => {
sum += JSON.parse(decimal)
})
res.json(sum);
})
});
Implemented a search bar so user's can add friends to an event. This was done by creating a search form that would send the search term bounds
to the backend. We then filtered the results using a regex expression to find usernames that match the parameters of the bounds.
// routes/api/searches.js
router.get('/search', (req, res) => {
if(req.query.bounds) {
User
.find({ username: { $regex: `${req.query.bounds}`, $options: "gi" } })
.then(users => res.json(users))
.catch(err => res.status(400).json(err));
} else {
// grab all users from db
User
.find()
.then(users => res.json(users))
.catch(err => res.status(400).json(err));
}
});
Then, we would send back the filtered users and place them in a specific slice of state under state.entities.users.search
so that we could specifically manipulate what usernames users see in the search results bar vs other parts of the webapp that might contain user information unrelated to that of the search. For example, you can see this in action in the above gif where added users stay even when the search bounds change. Below is our action that first updates our filter state and then fetches the searched users from the database.
// filter_acitons.js
import { fetchUsersFromSearch } from './user_actions';
export const UPDATE_FILTER = 'UPDATE_FILTER';
export const changeFilter = (filter, value) => ({
type: UPDATE_FILTER,
filter,
value
});
export const updateFilter = (filter, value) => (dispatch, getState) => {
dispatch(changeFilter(filter, value));
return fetchUsersFromSearch(getState().ui.filters)(dispatch);
};
Our super simplified tip calculator allows for users to quickly and easily update what they ordered for dinner and know their unique total once tip is added. By creating a slice of the state that will hold the values of tip, users are able to update their preffered tip percentage and our function will return the appropriate calcualted value.
With just a a few lines of code we were able to provide an incredibly useful tool to Bread users attempting to split their bills. Check out a quick snippet below:
let tip = Math.round((this.state.totalCost * (this.state.tip / 100)) * 100) / 100;
let totalCostWithTip = 0
if (tip) {
totalCostWithTip = parseInt(this.state.totalCost) + tip;
}
- Mongoose(MongoDB)
- Express
- Node.JS
- React / Redux
- CSS / HTML