Sample Project 1
App.js
import { useState } from 'react';
import classnames from 'classnames';
import shoppingIcon from './assets/shopping-icon.svg'
import plusIcon from './assets/plus-icon.svg'
import minusIcon from './assets/minus-icon.svg'
import './App.css';
function App() {
const [value, setValue] = useState('');
const [todos, setTodos] = useState([
{title: 'Nasi Goreng', count: 1},
{title: 'Baso', count: 1},
{title: 'Mie Ayam', count: 1}
]);
const handleSubmit = (e) => {
e.preventDefault()
if(!(value)) {
alert('No blank list!')
return;
}
const addedTodos = [...todos, {
title: value,
count: 1
}]
setTodos(addedTodos)
setValue('')
}
// console.log(value);
// console.log(todos);
const handleAdditionCount = (index) => {
const newTodos = [...todos]
newTodos[index].count = newTodos[index].count + 1
setTodos(newTodos);
}
const handleSubstractionCount = (index) => {
const newTodos = [...todos]
if(newTodos[index].count > 0) {
// Selama jumlah count nya masih di atas 0
// Bisa lakuin pengurangan
newTodos[index].count = newTodos[index].count - 1
} else {
// Kalo udah 0 dan masih dikurangin juga
// Hapus array value dengan index yang sesuai
newTodos.splice(index, 1)
}
setTodos(newTodos)
}
const getTotalCounts = () => {
const totalCounts = todos.reduce((total, num) => {
return total + num.count
}, 0)
return totalCounts
}
return (
<>
<nav className='nav'>
<img className='nav-icon' src={shoppingIcon} alt="shopping-icon" />
<h1 className='nav-title'>Shopping List</h1>
</nav>
<section className='container'>
<form className='form' onSubmit={handleSubmit}>
<input
onChange={(e) => {setValue(e.target.value)}}
value={value}
className='input'
type='text'
placeholder="List"
/>
<button className='add-button' type='submit'>Add</button>
</form>
<div className='info'>
<div className='info-total'>
<p>
{`Total List: ${todos.length}`}
</p>
</div>
<div className='info-total'>
<p>
{`Total Count: ${getTotalCounts()}`}
</p>
</div>
<button onClick={() => setTodos([])} className='delete-all-button'>
Delete All List
</button>
</div>
{todos.length > 0 ? (
<div className="todos">
{todos.map((todo, index, arr) => {
return (
<div key={index} className={`todo ${!(arr.length === index + 1) && 'todo-divider'}`}>
{todo.title}
<div className='todo-icon-wrapper'>
<div className='todo-count'>{todo.count}</div>
<button onClick={() => handleSubstractionCount(index)} className='todo-action-button'>
<img src={minusIcon} alt="minus icon" />
</button>
<button onClick={() => handleAdditionCount(index)} className='todo-action-button'>
<img src={plusIcon} alt="plus icon" />
</button>
</div>
</div>
)
})}
</div>
) : (
<div>Kosong</div>
)}
</section>
</>
);
}
export default App;
App.css
.nav {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
background-color: var(--main-background-color);
padding: 0 16px;
height: 55px;
}
.nav-icon{
height: 24px;
width: 24px;
}
.nav-title{
color: var(--secondary-font-color);
font-size: 24px;
font-weight: bold;
}
.container {
display: flex;
flex-direction: column;
height: calc(100vh- 55vh);
max-width: 480px;
padding: 16px;
margin: 0 auto;
background-color: var(--main-container-color);
}
.form{
display: flex;
}
.input{
flex: 1;
margin-right: 8px;
box-shadow: var(--main-box-shadow);
border: none;
border-radius: 6px;
padding: 10px;
color: var(--main-font-color);
font-size: 16px;
font-weight: 600;
}
.add-button{
border: none;
border-radius: 6px;
color: var(--secondary-font-color);
font-size: 16px;
font-weight: bold;
text-transform: uppercase;
width: 80px;
background-color: var(--main-background-color);
box-shadow: var(--main-box-shadow);
}
.todos {
box-shadow: var(--main-box-shadow);
overflow-x: hidden;
overflow-y: auto;
border-radius: 8px;
max-height: 640px;
}
.todo{
display: flex;
justify-content: space-between;
align-items: center;
height: 60px;
padding: 12px 16px;
background-color: var(--main-background-color-light);
color: var(--main-font-color);
font-size: 16px;
font-weight: 600;
}
.todo-count{
display: flex;
justify-content: center;
align-items: center;
height: 32px;
padding: 24px;
border-radius: 4px;
color: var(--label-font-color);
background-color: var(--secondary-font-color);
box-shadow: var(--main-box-shadow-inset);
}
.todo-icon-wrapper{
display: flex;
align-items: center;
justify-content: space-between;
align-items: center;
width: 120px;
}
.todo-action-button{
border: none;
background-color: unset;
padding: unset;
height: 24px;
width: 24px;
}
.todo-divider{
border-bottom: 1px solid var(--main-border-color);
}
.info {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
padding: 16px 0;
}
.info-total{
display: flex;
justify-content: center;
align-items: center;
color: var(--main-font-color);
font-size: 12px;
}
.info-total > p {
font-weight: bold;
}
.delete-all-button {
background-color: unset;
border: none;
padding: unset;
color: var(--danger-font-color);
font-size: 12px;
font-weight: bold;
}
Last updated
Was this helpful?