jveebs 3 years ago
commit cb53190b25

@ -0,0 +1,65 @@
import React, { useContext, useState } from 'react';
import { AppContext } from '../context/AppContext';
import { v4 as uuidv4 } from 'uuid';
const AddExpenseForm = (props) => {
const { dispatch } = useContext(AppContext);
const [name, setName] = useState('');
const [cost, setCost] = useState('');
const onSubmit = (event) => {
event.preventDefault();
const expense = {
id: uuidv4(),
name,
cost: parseInt(cost),
};
dispatch({
type: 'ADD_EXPENSE',
payload: expense,
});
setName('');
setCost('');
};
return (
<form onSubmit={onSubmit}>
<div class='row'>
<div class='col-sm col-lg-4'>
<label for='name'>Name</label>
<input
required='required'
type='text'
class='form-control'
id='name'
value={name}
onChange={(event) => setName(event.target.value)}
/>
</div>
<div class='col-sm col-lg-4'>
<label for='cost'>Cost</label>
<input
required='required'
type='number'
class='form-control'
id='cost'
value={cost}
onChange={(event) => setCost(event.target.value)}
/>
</div>
</div>
<div class='row mt-3'>
<div class='col-sm'>
<button type='submit' class='btn btn-primary'>
Save
</button>
</div>
</div>
</form>
);
};
export default AddExpenseForm;

@ -1,58 +0,0 @@
.add_bill_widget {
background-color: rgb(223, 245, 229);
max-height: 50%;
}
.widget_header {
margin: 0px;
margin-bottom: 20px;
}
input {
max-width: 50%;
}
button {
margin-left: 20%;
margin-right: auto;
}
.buttons{
}
/* Style The Dropdown Button */
.dropbtn {
cursor: pointer;
}
/* The container <div> - needed to position the dropdown content */
.dropdown {
position: relative;
display: inline-block;
}
/* Dropdown Content (Hidden by Default) */
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
min-width: 160px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
z-index: 1;
}
/* Links inside the dropdown */
.dropdown-content a {
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
}
/* Change color of dropdown links on hover */
.dropdown-content a:hover {background-color: #f1f1f1}
/* Show the dropdown menu on hover */
.dropdown:hover .dropdown-content {
display: block;
}
/* Change the background color of the dropdown button when the dropdown content is shown */
.dropdown:hover .dropbtn {
background-color: #3e8e41;
}

@ -1,29 +0,0 @@
import React from 'react'
import './AddNewBill.css'
export default function AddNewBill() {
return (
<>
<div class="add_bill_widget">
<h4 class="widget_header">Add New Bill</h4>
<input type="number"></input>
<div class="buttons">
<div class="dropdown">
<button class="dropbtn">Categories</button>
<div class="dropdown-content">
<p>Bills</p>
<p>Groceries</p>
<p>Rent</p>
<p>Leisure</p>
<p>Gas</p>
</div>
</div>
<button>Add Bill</button>
</div>
</div>
</>
)
}

@ -1,23 +0,0 @@
.current_balance_widget {
background-color: rgb(223, 245, 229);
}
.widget_header {
}
img {
float: left;
height: 40px;
margin-left: 5%;
}
.current_balance_widget h1 {
float: left;
margin: 0;
margin-left: 10%;
}
.current_balance_widget h6 {
color: green;
float: left;
margin: 0;
margin-left: 33%;
}

@ -1,17 +0,0 @@
import React from 'react'
import './CurrentBalance.css'
import logo from '../assets/widget_logos/current_balance_logo.png';
export default function CurrentBalance() {
return (
<>
<div class="current_balance_widget">
<h4 class="widget_header">Current Balance</h4>
<img src={logo} />
<h1>$1238.56</h1>
<h6>+ $179.97 (17%) last month</h6>
</div>
</>
)
}

@ -0,0 +1,26 @@
import React, { useState } from 'react';
const EditBudget = (props) => {
const [value, setValue] = useState(props.budget);
return (
<>
<input
required='required'
type='number'
class='form-control mr-3'
id='name'
value={value}
onChange={(event) => setValue(event.target.value)}
/>
<button
type='button'
class='btn btn-primary'
onClick={() => props.handleSaveClick(value)}
>
Save
</button>
</>
);
};
export default EditBudget;

@ -0,0 +1,24 @@
import React, { useContext } from 'react';
import { AppContext } from '../context/AppContext';
const ExpenseItem = (props) => {
const { dispatch } = useContext(AppContext);
const handleDeleteExpense = () => {
dispatch({
type: 'DELETE_EXPENSE',
payload: props.id,
});
};
return (
<li class='list-group-item d-flex justify-content-between align-items-center'>
{props.name}
<div>
<span class='text-primary badge badge-primary badge-pill mr-3'>${props.cost}</span>
</div>
</li>
);
};
export default ExpenseItem;

@ -0,0 +1,42 @@
import React, { useContext, useState, useEffect } from 'react';
import ExpenseItem from './ExpenseItem';
import { AppContext } from '../context/AppContext';
const ExpenseList = () => {
const { expenses } = useContext(AppContext);
const [filteredExpenses, setfilteredExpenses] = useState(expenses || []);
useEffect(() => {
setfilteredExpenses(expenses);
}, [expenses]);
const handleChange = (event) => {
const searchResults = expenses.filter((filteredExpense) =>
filteredExpense.name.toLowerCase().includes(event.target.value)
);
setfilteredExpenses(searchResults);
};
return (
<>
<input
type='text'
class='form-control mb-2 mr-sm-2'
placeholder='Type to search...'
onChange={handleChange}
/>
<ul class='list-group mt-3 mb-3'>
{filteredExpenses.map((expense) => (
<ExpenseItem
id={expense.id}
name={expense.name}
cost={expense.cost}
/>
))}
</ul>
</>
);
};
export default ExpenseList;

@ -0,0 +1,18 @@
import React, { useContext } from 'react';
import { AppContext } from '../context/AppContext';
const ExpenseTotal = () => {
const { expenses } = useContext(AppContext);
const total = expenses.reduce((total, item) => {
return (total += item.cost);
}, 0);
return (
<div class='alert alert-secondary p-4'>
<span>This Month's Expenses: ${total}</span>
</div>
);
};
export default ExpenseTotal;

@ -1,20 +0,0 @@
.expenses_widget {
background-color: rgb(223, 245, 229);
}
.widget_header {
}
img {
height: 40px;
}
.expenses_widget h1 {
float: left;
margin: 0;
margin-left: 10%;
}
.expenses_widget h6 {
color: red;
float: right;
margin: 0;
}

@ -1,17 +0,0 @@
import React from 'react'
import './Expenses.css'
import logo from '../assets/widget_logos/expenses_logo.png';
export default function Expenses() {
return (
<>
<div class="expenses_widget">
<h4 class="widget_header">This Month's Expenses</h4>
<img src={logo} />
<h1>$456.78</h1>
<h6>+ $359.97 (26%) last month (17%)</h6>
</div>
</>
)
}

@ -1,20 +0,0 @@
.income_widget {
background-color: rgb(223, 245, 229);
}
.widget_header {
}
img {
height: 40px;
}
.income_widget h1 {
float: left;
margin: 0;
margin-left: 10%;
}
.income_widget h6 {
color: green;
margin: 0;
float: right;
}

@ -1,17 +0,0 @@
import React from 'react'
import './Income.css'
import logo from '../assets/widget_logos/income_logo.png';
export default function Income() {
return (
<>
<div class="income_widget">
<h4 class="widget_header">This Month's Income</h4>
<img src={logo} />
<h1>$1,525.00</h1>
<h6>+ $1,037.51 (42%) last month</h6>
</div>
</>
)
}

@ -1,15 +0,0 @@
.transactions_widget {
background-color: rgb(223, 245, 229);
}
.transaction_table {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 30px 30px 30px 30px;
box-sizing: border-box;
}
.transaction_table p {
margin: 0;
float: left;
}

@ -1,30 +0,0 @@
import React from 'react'
import './RecentTransaction.css'
export default function RecentTransactions() {
return (
<>
<div class="transactions_widget">
<h4 class="widget_header">Recent Transactions</h4>
<div class="transaction_table">
<p>Bill</p>
<p>$35.00</p>
<p>2/15/23</p>
<p>Food</p>
<p>$29.95</p>
<p>2/11/23</p>
<p>Wage</p>
<p>$723.40</p>
<p>2/10/23</p>
<p>Pet</p>
<p>$56.98</p>
<p>2/5/23</p>
<p>Leisure</p>
<p>$60.04</p>
<p>2/03/23</p>
</div>
</div>
</>
)
}

@ -0,0 +1,20 @@
import React, { useContext } from 'react';
import { AppContext } from '../context/AppContext';
const RemainingBudget = () => {
const { expenses, budget } = useContext(AppContext);
const totalExpenses = expenses.reduce((total, item) => {
return (total += item.cost);
}, 0);
const alertType = totalExpenses > budget ? 'alert-danger' : 'alert-success';
return (
<div class={`alert p-4 ${alertType}`}>
<span>Budget Remaining: ${budget - totalExpenses}</span>
</div>
);
};
export default RemainingBudget;

@ -1,7 +1,3 @@
.sidebar {
padding: 0 12px;
}
.sidebar-header {
display: flex;
align-items: center;

@ -12,7 +12,7 @@ import './SideNav.css'
export default function SideNav() {
return(
<Sidebar className='sidebar' backgroundColor='transparent'>
<Sidebar backgroundColor='transparent'>
<div className='sidebar-header'>
<div className='sidebar-avatar'>
<Avatar />

@ -0,0 +1,14 @@
import React from 'react';
const ViewBudget = (props) => {
return (
<>
<span>Current Balance: ${props.budget}</span>
<button type='button' class='btn btn-primary' onClick={props.handleEditClick}>
Edit
</button>
</>
);
};
export default ViewBudget;

@ -1,23 +0,0 @@
.budget_widget {
background-color: rgb(223, 245, 229);
}
.widget_header {
}
img {
float: left;
height: 40px;
margin-left: 5%;
}
.budget_widget h1 {
float: left;
margin: 0;
margin-left: 10%;
}
.budget_widget h6 {
color: green;
float: left;
margin: 0;
margin-left: 37%;
}

@ -1,17 +1,33 @@
import React from 'react'
import './budget.css'
import logo from '../assets/widget_logos/budget_logo.png';
import React, { useState, useContext } from 'react';
import ViewBudget from './ViewBudget';
import EditBudget from './EditBudget';
import { AppContext } from '../context/AppContext';
export default function Budget() {
return (
<>
<div class="budget_widget">
<h4 class="widget_header">Budget Remaining</h4>
<img src={logo} />
<h1>$456.78</h1>
<h6>Still on budget</h6>
</div>
</>
const Budget = () => {
const { budget, dispatch } = useContext(AppContext);
const [isEditing, setIsEditing] = useState(false);
)
}
const handleEditClick = () => {
setIsEditing(true);
};
const handleSaveClick = (value) => {
dispatch({
type: 'SET_BUDGET',
payload: value,
});
setIsEditing(false);
};
return (
<div class='alert alert-secondary p-3 d-flex align-items-center justify-content-between'>
{isEditing ? (
<EditBudget handleSaveClick={handleSaveClick} budget={budget} />
) : (
<ViewBudget handleEditClick={handleEditClick} budget={budget} />
)}
</div>
);
};
export default Budget;

@ -0,0 +1,56 @@
import React, { createContext, useReducer } from 'react';
import { v4 as uuidv4 } from 'uuid';
export const AppReducer = (state, action) => {
switch (action.type) {
case 'ADD_EXPENSE':
return {
...state,
expenses: [...state.expenses, action.payload],
};
case 'DELETE_EXPENSE':
return {
...state,
expenses: state.expenses.filter(
(expense) => expense.id !== action.payload
),
};
case 'SET_BUDGET':
return {
...state,
budget: action.payload,
};
default:
return state;
}
};
const initialState = {
budget: 2000,
expenses: [
{ id: uuidv4(), name: 'Groceries', cost: 50 },
{ id: uuidv4(), name: 'Leisure', cost: 300 },
{ id: uuidv4(), name: 'Pet', cost: 70 },
{ id: uuidv4(), name: 'Gas', cost: 40 },
{ id: uuidv4(), name: 'Rent', cost: 500 },
],
};
export const AppContext = createContext();
export const AppProvider = (props) => {
const [state, dispatch] = useReducer(AppReducer, initialState);
return (
<AppContext.Provider
value={{
expenses: state.expenses,
budget: state.budget,
dispatch,
}}
>
{props.children}
</AppContext.Provider>
);
};

@ -1,19 +1,42 @@
import AddNewBill from '../components/AddNewBill'
import CurrentBalance from '../components/CurrentBalance'
import Expenses from '../components/Expenses'
import Income from '../components/Income'
import Budget from '../components/budget'
import RecentTransactions from '../components/RecentTransactions'
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css';
export default function Dashboard() {
return (
<>
<CurrentBalance />
<Budget />
<Expenses />
<Income />
<RecentTransactions />
<AddNewBill />
</>
)
import { AppProvider } from '../context/AppContext';
import Budget from '../components/Budget';
import ExpenseTotal from '../components/ExpenseTotal';
import ExpenseList from '../components/ExpenseList';
import AddExpenseForm from '../components/AddExpenseForm';
import RemainingBudget from '../components/Remaining';
export default function Dashboard() {
return (
<AppProvider>
<div className='container'>
<h1 className='mt-3'>My Budget Planner</h1>
<div className='row mt-3'>
<div className='col-sm'>
<Budget />
</div>
<div className='col-sm'>
<RemainingBudget />
</div>
<div className='col-sm'>
<ExpenseTotal />
</div>
</div>
<h3 className='mt-3'>Expenses</h3>
<div className='row '>
<div className='col-sm'>
<ExpenseList />
</div>
</div>
<h3 className='mt-3'>Add Expense</h3>
<div className='row mt-3'>
<div className='col-sm'>
<AddExpenseForm />
</div>
</div>
</div>
</AppProvider>
);
}

@ -24,12 +24,12 @@ code {
border-radius: 20px;
padding: 20px 30px;
width: 100vw;
display: grid;
/*display: grid; COMMENTED OUT BY CHRIS FOR PUSH ON WIDGETS, not sure if need for welcome page or not, do not need anymore for widgets
grid-template-columns: repeat(4, 1fr);
grid-template-rows: 125px 250px 100px 100px;
gap: 10px;
padding: 10px;
box-sizing: border-box;
box-sizing: border-box; */
}
.page-display div {

Loading…
Cancel
Save