Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project submit #465

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,6 @@ dmypy.json

# Pyre type checker
.pyre/

# Node node_modules
node_modules/
49 changes: 41 additions & 8 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ import 'bootstrap/dist/css/bootstrap.min.css';
import Budget from './components/Budget';

// Add code to import the other components here under
import Remaining from './components/Remaining';
import ExpenseTotal from './components/ExpenseTotal';
import ExpenseList from './components/ExpenseList';
import AllocationForm from './components/AllocationForm';


import { AppProvider } from './context/AppContext';
import Currency from './components/Currency';
const App = () => {
return (
<AppProvider>
Expand All @@ -18,27 +23,55 @@ const App = () => {
    {
/* Add Budget component here */
}
<div className='col-sm'>
<Budget />
</div>

    {
/* Add Remaining component here*/
}
<div className='col-sm'>
<Remaining />
</div>

    {
/* Add ExpenseTotal component here */
}

    {
/* Add ExpenseList component here */
}
<div className='col-sm'>
<ExpenseTotal />
</div>

    {
/* Add ExpenseItem component here */
/* Add Currency component here */
}
<div className='col-sm'>
<Currency />
</div>


    {
/* Add AllocationForm component here under */
}
</div>
    {
/* Add ExpenseList component here */
}
<h3 className='mt-3'>Allocation</h3>
<div className='row '>
<div className='col-sm'>
<ExpenseList />
</div>
</div>

    {
/* Add ExpenseItem component here */
}

    {
/* Add AllocationForm component here under */
}
<h3 className='mt-3'>Change allocation</h3>
<div className='row mt-3'>
<div className='col-sm'>
<AllocationForm/>
</div>
</div>
</div>
</AppProvider>
Expand Down
83 changes: 83 additions & 0 deletions src/components/AllocationForm.js
Original file line number Diff line number Diff line change
@@ -1 +1,84 @@
import React, { useContext, useState } from 'react';
import { AppContext } from '../context/AppContext';

const AllocationForm = (props) => {
const { dispatch, remaining, currency } = useContext(AppContext);

const [name, setName] = useState('');
const [cost, setCost] = useState('');
const [action, setAction] = useState('');

const submitEvent = () => {

if(cost > remaining) {
alert("The value cannot exceed remaining funds £"+remaining);
setCost("");
return;
}

const expense = {
name: name,
cost: parseInt(cost),
};
if(action === "Reduce") {
dispatch({
type: 'RED_EXPENSE',
payload: expense,
});
} else {
dispatch({
type: 'ADD_EXPENSE',
payload: expense,
});
}
};

return (
<div>
<div className='row'>

<div className="input-group mb-3" style={{ marginLeft: '2rem' }}>
<div className="input-group-prepend">
<label className="input-group-text" htmlFor="inputGroupSelect01">Department</label>
</div>
<select className="custom-select" id="inputGroupSelect01" onChange={(event) => setName(event.target.value)}>
<option defaultValue>Choose...</option>
<option value="Marketing" name="marketing"> Marketing</option>
<option value="Sales" name="sales">Sales</option>
<option value="Finance" name="finance">Finance</option>
<option value="HR" name="hr">HR</option>
<option value="IT" name="it">IT</option>
<option value="Admin" name="admin">Admin</option>
</select>

<div className="input-group-prepend" style={{ marginLeft: '2rem' }}>
<label className="input-group-text" htmlFor="inputGroupSelect02">Allocation</label>
</div>
<select className="custom-select" id="inputGroupSelect02" onChange={(event) => setAction(event.target.value)}>
<option defaultValue value="Add" name="Add">Add</option>
<option value="Reduce" name="Reduce">Reduce</option>
</select>

<div className="input-group-prepend" style={{ marginLeft: '2rem' }}>
<label className="input-group-text" htmlFor="inputGroupSelect02">{currency}</label>
</div>
<input
required='required'
type='number'
id='cost'
value={cost}
style={{ size: 10}}
onChange={(event) => setCost(event.target.value)}>
</input>

<button className="btn btn-primary" onClick={submitEvent} style={{ marginLeft: '2rem' }}>
Save
</button>
</div>
</div>

</div>
);
};

export default AllocationForm;
17 changes: 17 additions & 0 deletions src/components/Budget.js
Original file line number Diff line number Diff line change
@@ -1 +1,18 @@
import React, { useContext } from 'react';
import { AppContext } from '../context/AppContext';

const Budget = () => {
const { budget, dispatch, currency } = useContext(AppContext);

const handleBudgetChange = (event) => {
dispatch({ type: 'SET_BUDGET', payload: parseInt(event.target.value) })
}

return (
<div className='alert alert-secondary'>
<span>Budget: {currency}</span>
<input type="number" step="10" value={budget} onChange={handleBudgetChange} style={{width: 'fit-content'}}></input>
</div>
);
};
export default Budget;
47 changes: 47 additions & 0 deletions src/components/Currency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import React, { useContext, useState } from 'react';
import { AppContext } from '../context/AppContext';

const Currency = () => {
const [currencyName, setCurrencyName] = useState('GBP');
const { dispatch } = useContext(AppContext);

const getCurrencySymbol = (locale, currency) => {
return (0).toLocaleString(
locale,
{
style: 'currency',
currency: currency,
minimumFractionDigits: 0,
maximumFractionDigits: 0
}
).replace(/\d/g, '').trim()
}

const handleCurrency = (event) => {
let locale = 'en-GB';
if (event.target.value === 'USD') {
locale = 'en-US';
}
if (event.target.value === 'INR') {
locale = 'en-IN';
}
if (event.target.value === 'EUR') {
locale = 'fr-FR';
}
dispatch({ type: 'CHG_CURRENCY', payload: getCurrencySymbol(locale ,event.target.value) })
setCurrencyName(event.target.value)
}

return (
<div className='alert alert-warning'>
<span>Currency{' '}</span>
<select defaultValue={currencyName} onChange={handleCurrency} style={{width: 'fit-content', color: 'inherit', backgroundColor: 'inherit', border: 'none'}}>
<option value={'USD'}>{getCurrencySymbol('en-US' ,'USD')} Dollar</option>
<option value={'GBP'}>{getCurrencySymbol('en-GB' ,'GBP')} Pound</option>
<option value={'EUR'}>{getCurrencySymbol('en-US' ,'EUR')} Euro</option>
<option value={'INR'}>{getCurrencySymbol('en-IN' ,'INR')} Ruppee</option>
</select>
</div>
);
};
export default Currency;
51 changes: 51 additions & 0 deletions src/components/ExpenseItem.js
Original file line number Diff line number Diff line change
@@ -1 +1,52 @@
import React, { useContext } from 'react';
import { TiDelete } from 'react-icons/ti';
import { AppContext } from '../context/AppContext';

const ExpenseItem = (props) => {
const { dispatch, currency } = useContext(AppContext);

const handleDeleteExpense = () => {
dispatch({
type: 'DELETE_EXPENSE',
payload: props.id,
});
};

const increaseAllocation = (name) => {
const expense = {
name: name,
cost: 10,
};

dispatch({
type: 'ADD_EXPENSE',
payload: expense
});

}

const decreaseAllocation = (name) => {
const expense = {
name: name,
cost: 10,
};

dispatch({
type: 'RED_EXPENSE',
payload: expense
});

}

return (
<tr>
<td>{props.name}</td>
<td>{currency}{props.cost}</td>
<td><button style={{ backgroundColor: 'green', color:'white', fontSize: '1.5rem', fontWeight: 'bold', width: '40px', height: '40px', border:'none', borderRadius: '100%', lineHeight: '1', padding: '1px'}} onClick={event=> increaseAllocation(props.name)}>+</button></td>
<td><button style={{ backgroundColor: 'red', color:'white', fontSize: '1.5rem', fontWeight: 'bold', width: '40px', height: '40px', border:'none', borderRadius: '100%', lineHeight: '1', padding: '1px'}} onClick={event=> decreaseAllocation(props.name)}>-</button></td>
<td><TiDelete size='1.5em' onClick={handleDeleteExpense}></TiDelete></td>
</tr>
);
};

export default ExpenseItem;
27 changes: 27 additions & 0 deletions src/components/ExpenseList.js
Original file line number Diff line number Diff line change
@@ -1 +1,28 @@
import React, { useContext } from 'react';
import ExpenseItem from './ExpenseItem';
import { AppContext } from '../context/AppContext';

const ExpenseList = () => {
const { expenses } = useContext(AppContext);

return (
<table className='table'>
<thead className="thead-light">
<tr>
<th scope="col">Department</th>
<th scope="col">Allocated Budget</th>
<th scope="col">Increase by 10</th>
<th scope="col">Decrease by 10</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
{expenses.map((expense) => (
<ExpenseItem id={expense.id} key={expense.id} name={expense.name} cost={expense.cost} />
))}
</tbody>
</table>
);
};

export default ExpenseList;
15 changes: 14 additions & 1 deletion src/components/ExpenseTotal.js
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@

import React, { useContext } from 'react';
import { AppContext } from '../context/AppContext';
const ExpenseTotal = () => {
const { expenses, currency } = useContext(AppContext);
const totalExpenses = expenses.reduce((total, item) => {
return (total += item.cost);
}, 0);
return (
<div className='alert alert-primary'>
<span>Spent so far: {currency}{totalExpenses}</span>
</div>
);
};
export default ExpenseTotal;
16 changes: 15 additions & 1 deletion src/components/Remaining.js
Original file line number Diff line number Diff line change
@@ -1 +1,15 @@

import React, { useContext } from 'react';
import { AppContext } from '../context/AppContext';
const Remaining = () => {
const { expenses, budget, currency } = useContext(AppContext);
const totalExpenses = expenses.reduce((total, item) => {
return (total = total + item.cost);
}, 0);
const alertType = totalExpenses > budget ? 'alert-danger' : 'alert-success';
return (
<div className={`alert ${alertType}`}>
<span>Remaining: {currency}{budget - totalExpenses}</span>
</div>
);
};
export default Remaining;
10 changes: 10 additions & 0 deletions src/context/AppContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,18 @@ export const AppReducer = (state, action) => {
};
case 'SET_BUDGET':
action.type = "DONE";

const totalExpenses = state.expenses.reduce((total, item) => {
return (total += item.cost);
}, 0);

if (action.payload < totalExpenses) {
alert('You cannot reduce the budget value lower then the spending');
return;
}
state.budget = action.payload;


return {
...state,
};
Expand Down
Loading