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

Jateen_Shopping_Application_Sample_Project #103

Open
wants to merge 1 commit 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,4 @@ dmypy.json

# Pyre type checker
.pyre/
node_modules
29 changes: 29 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 33 additions & 9 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,40 @@
import React from 'react';
import 'bootstrap/dist/css/bootstrap.min.css'; 
import 'bootstrap/dist/css/bootstrap.min.css';


import { AppProvider } from './context/AppContext';
import CartValue from './components/CartValue';
import ExpenseList from './components/ExpenseList';
import ItemSelected from './components/ItemSelected';
import Location from './components/Location';

function App() {
return (
<div className="App">
</div>
);
}

export default App;
const App = () => {
return (
<AppProvider>
<div className='container'>
<h1 className='mt-3'>Shopping App</h1>
<div className='row mt-3'>
<div className='col-sm'>
<CartValue />
</div>
<div className='col-sm'>
<Location />
</div>
</div>
<h3 className='mt-3'>Shopping Cart</h3>
<div className='row '>
<div className='col-sm'>
<ExpenseList />
</div>
</div>
<h3 className='mt-3'>Add Items</h3>
<div className='row mt-3'>
<div className='col-sm'>
<ItemSelected/>
</div>
</div>
</div>
</AppProvider>
);
};
export default App;
12 changes: 11 additions & 1 deletion src/components/CartValue.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@ import React, { useContext } from 'react';
import { AppContext } from '../context/AppContext';

const CartValue = () => {
const { expenses, Location } = useContext(AppContext);
const totalExpenses = expenses.reduce((total, item) => {
return (total += (item.unitprice * item.quantity));
}, 0);

return (
<div className='alert alert-primary'>
<span>Cart Value: {Location}{totalExpenses}</span>
</div>
);
};

export default CartValue;
export default CartValue;
25 changes: 24 additions & 1 deletion src/components/ExpenseItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,29 @@ import { AppContext } from '../context/AppContext';
import { FaTimesCircle } from 'react-icons/fa';

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

const handleDeleteItem = () => {
const item = {
name: props.name,
};

dispatch({
type: 'DELETE_ITEM',
payload: item,
});
};


return (
<tr>
<td>{props.name}</td>
<td>{props.quantity}</td>
<td>{Location}{parseInt(props.unitprice)}</td>
<td>{Location}{parseInt(props.quantity)*parseInt(props.unitprice)}</td>
<td><FaTimesCircle size='2.2em' color="red" onClick={handleDeleteItem}></FaTimesCircle></td>
</tr>
);
};

export default ExpenseItem;
export default ExpenseItem;
23 changes: 22 additions & 1 deletion src/components/ExpenseList.js
Original file line number Diff line number Diff line change
@@ -1,7 +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">Items</th>
<th scope="col">Quantity</th>
<th scope="col">Unit Price</th>
<th scope="col">Items Price</th>
<th scope="col">Remove</th>
</tr>
</thead>
<tbody>
{expenses.map((expense) => (
<ExpenseItem id={expense.id} key={expense.id} name={expense.name} quantity={expense.quantity} unitprice={expense.unitprice} />
))}
</tbody>
</table>
);
};

export default ExpenseList;
export default ExpenseList;
72 changes: 71 additions & 1 deletion src/components/ItemSelected.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,76 @@ import React, { useContext, useState } from 'react';
import { AppContext } from '../context/AppContext';

const ItemSelected = (props) => {
const { dispatch} = useContext(AppContext);

const [name, setName] = useState('');
const [quantity, setQuantity] = useState('');
const [action, setAction] = useState('');


const submitEvent = () => {

const item = {
name: name,
quantity: parseInt(quantity),
};

if(action === "Reduce") {
dispatch({
type: 'RED_QUANTITY',
payload: item,
});
} else {
dispatch({
type: 'ADD_QUANTITY',
payload: item,
});
}
};

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">Items</label>
</div>
<select className="custom-select" id="inputGroupSelect01" onChange={(event) => setName(event.target.value)}>
<option defaultValue>Choose...</option>
<option value="Shirt" name="Shirt"> Shirt</option>
<option value="Dress" name="Dress">Dress</option>
<option value="Jeans" name="Jeans">Jeans</option>
<option value="Dinner set" name="Dinner set">Dinner set</option>
<option value="Bags" name="Bags">Bags</option>
</select>

<div className="input-group-prepend" style={{ marginLeft: '2rem' }}>
<label className="input-group-text" htmlFor="inputGroupSelect02">Quantity</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>
<span className="eco" style={{ marginLeft: '2rem', marginRight: '8px'}}></span>

<input
required='required'
type='number'
id='cost'
value={quantity}
style={{size: 10}}
onChange={(event) => setQuantity(event.target.value)}>
</input>

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

</div>
);
};

export default ItemSelected;
export default ItemSelected;
21 changes: 21 additions & 0 deletions src/components/Location.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,27 @@ import React, { useContext } from 'react';
import { AppContext } from '../context/AppContext';

const Location = () => {
const {dispatch } = useContext(AppContext);

const changeLocation = (val)=>{
dispatch({
type: 'CHG_LOCATION',
payload: val,
})
}


return (
<div className='alert alert-secondary'> Location {
<select name="Location" id="Location" onChange={event=>changeLocation(event.target.value)}>
<option value="£">Uk(£)</option>
<option value="₹">India(₹)</option>
<option value="€">Europe(€)</option>
<option value="CAD">Canada(CAD)</option>
</select>
}
</div>
);
};

export default Location;
101 changes: 100 additions & 1 deletion src/context/AppContext.js
Original file line number Diff line number Diff line change
@@ -1 +1,100 @@
import React, { createContext, useReducer } from 'react';
import React, { createContext, useReducer } from 'react';

// 5. The reducer - this is used to update the state, based on the action
export const AppReducer = (state, action) => {
let new_expenses = [];
switch (action.type) {
case 'ADD_QUANTITY':
let updatedqty = false;
state.expenses.map((expense)=>{
if(expense.name === action.payload.name) {
expense.quantity = expense.quantity + action.payload.quantity;
updatedqty = true;
}
new_expenses.push(expense);
return true;
})
state.expenses = new_expenses;
action.type = "DONE";
return {
...state,
};

case 'RED_QUANTITY':
state.expenses.map((expense)=>{
if(expense.name === action.payload.name) {
expense.quantity = expense.quantity - action.payload.quantity;
}
expense.quantity = expense.quantity < 0 ? 0: expense.quantity;
new_expenses.push(expense);
return true;
})
state.expenses = new_expenses;
action.type = "DONE";
return {
...state,
};
case 'DELETE_ITEM':
state.expenses.map((expense)=>{
if(expense.name === action.payload.name) {
expense.quantity = 0;
}
new_expenses.push(expense);
return true;
})
state.expenses = new_expenses;
action.type = "DONE";
return {
...state,
};
case 'CHG_LOCATION':
action.type = "DONE";
state.Location = action.payload;
return {
...state
}

default:
return state;
}
};

// 1. Sets the initial state when the app loads
const initialState = {
expenses: [
{ id: "Shirt", name: 'Shirt', quantity: 0, unitprice: 500 },
{ id: "Jeans", name: 'Jeans', quantity: 0, unitprice: 300 },
{ id: "Dress", name: 'Dress', quantity: 0, unitprice: 400 },
{ id: "Dinner set", name: 'Dinner set', quantity: 0, unitprice: 600 },
{ id: "Bags", name: 'Bags', quantity: 0, unitprice: 200 },
],
Location: '£'
};

// 2. Creates the context this is the thing our components import and use to get the state
export const AppContext = createContext();

// 3. Provider component - wraps the components we want to give access to the state
// Accepts the children, which are the nested(wrapped) components
export const AppProvider = (props) => {
// 4. Sets up the app state. takes a reducer, and an initial state
const [state, dispatch] = useReducer(AppReducer, initialState);

const totalExpenses = state.expenses.reduce((total, item) => {
return (total = total + (item.unitprice*item.quantity));
}, 0);
state.CartValue = totalExpenses;

return (
<AppContext.Provider
value={{
expenses: state.expenses,
CartValue: state.CartValue,
dispatch,
Location: state.Location
}}
>
{props.children}
</AppContext.Provider>
);
};