summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/App.jsx24
-rw-r--r--src/Entry.jsx36
-rw-r--r--src/Result.jsx44
-rw-r--r--src/SalaryInput.jsx11
4 files changed, 99 insertions, 16 deletions
diff --git a/src/App.jsx b/src/App.jsx
index da2bbc7..8a487e0 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -4,9 +4,11 @@ import Entry from "./Entry.jsx";
import {Button, Container, Typography} from "@mui/material";
import dayjs from "dayjs";
import SalaryInput from "./SalaryInput.jsx";
+import Result from "./Result.jsx";
function App() {
+ const [baseSalary, setBaseSalary] = useState(0);
const [listEntry, setListEntry] = useState(
[
{id: 0, date: dayjs(), start: dayjs(), finish: dayjs()},
@@ -24,6 +26,20 @@ function App() {
return lastEntry.id;
}
+ const handleEntryChange = (entry, updatedAttr) => {
+ const updatedEntryList = listEntry.map((entryOnList) => {
+ if (entryOnList.id === entry.id) {
+ return {...entryOnList, [updatedAttr]: entry[updatedAttr]}
+ }
+ return entryOnList;
+ });
+ setListEntry(updatedEntryList);
+ }
+
+ const handleBaseSalaryChange = (baseSalaryInput) => {
+ setBaseSalary(baseSalaryInput);
+ }
+
const addToList = () => {
const newEntry = {
id: getLastId() + 1,
@@ -43,19 +59,22 @@ function App() {
return (
<Container>
<Typography variant='h3' align='center'>Overtime Calculator</Typography>
- <Typography variant='overline' display='block' align='center'>🤑🤑 Sudahkah anda lembur hari ini? 🤑🤑</Typography>
+ <Typography variant='overline' display='block' align='center'>🤑🤑 Sudahkah anda lembur hari ini?
+ 🤑🤑</Typography>
<ul>
<li style={{listStyle: 'none', margin: '20px 0'}}>
- <SalaryInput/>
+ <SalaryInput handleBaseSalaryChange={handleBaseSalaryChange}/>
</li>
{listEntry.map((entry) => {
return (
<div key={entry.id} style={{display: 'flex', gap: '10px', marginBottom: '10px'}}>
<li style={{listStyle: 'none'}} key={entry.id}>
<Entry
+ propId={entry.id}
propDate={entry.date}
propStart={entry.start}
propFinish={entry.finish}
+ handleEntryChange={handleEntryChange}
/>
</li>
<Button
@@ -75,6 +94,7 @@ function App() {
)
})}
</ul>
+ <Result listEntry={listEntry} baseSalary={baseSalary}/>
</Container>
)
}
diff --git a/src/Entry.jsx b/src/Entry.jsx
index e554050..c486680 100644
--- a/src/Entry.jsx
+++ b/src/Entry.jsx
@@ -4,7 +4,7 @@ import {AdapterDayjs} from '@mui/x-date-pickers/AdapterDayjs';
import 'dayjs/locale/id';
-function Entry({propDate, propStart, propFinish}) {
+function Entry({propId, propDate, propStart, propFinish, handleEntryChange}) {
const [date, setDate] = useState(propDate);
const [start, setStart] = useState(propStart);
const [finish, setFinish] = useState(propFinish);
@@ -12,15 +12,31 @@ function Entry({propDate, propStart, propFinish}) {
return (
<LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale='id'>
<div style={{display: 'flex', gap: '5px'}}>
- <DatePicker label="Tanggal Lembur" value={date}
- onAccept={(newDate) => setDate(newDate)}/>
- <TimePicker label="Mulai" ampm={false} value={start} maxTime={finish} onAccept={(newStart) => {
- setStart(newStart)
- }}/>
- <TimePicker label="Selesai" ampm={false} value={finish} minTime={start} onAccept={(newFinish) => {
- setFinish(newFinish);
- console.log(newFinish)
- }}/>
+ <DatePicker label="Tanggal Lembur"
+ value={date}
+ onAccept={(newDate) => {
+ setDate(newDate);
+ handleEntryChange({id: propId, date: newDate}, 'date')
+ }}
+ />
+ <TimePicker label="Mulai"
+ ampm={false}
+ value={start}
+ maxTime={finish}
+ onAccept={(newStart) => {
+ setStart(newStart);
+ handleEntryChange({id: propId, start: newStart}, 'start')
+ }}
+ />
+ <TimePicker label="Selesai"
+ ampm={false}
+ value={finish}
+ minTime={start}
+ onAccept={(newFinish) => {
+ setFinish(newFinish);
+ handleEntryChange({id: propId, finish: newFinish}, 'finish')
+ }}
+ />
</div>
</LocalizationProvider>
)
diff --git a/src/Result.jsx b/src/Result.jsx
new file mode 100644
index 0000000..0ea4810
--- /dev/null
+++ b/src/Result.jsx
@@ -0,0 +1,44 @@
+import {useEffect, useState} from "react";
+import entry from "./Entry.jsx";
+
+function Result({listEntry, baseSalary}) {
+ const [totalOvertimePay, setTotalOvertimePay] = useState(0);
+
+ useEffect(() => {
+ setTotalOvertimePay(getOvertimePayTotal(listEntry, baseSalary));
+ }, [listEntry, baseSalary]);
+
+ return (
+ <div>
+ Totalnye: Rp{totalOvertimePay}
+ {listEntry.map((entry) => {
+ return (
+ <div key={entry.id}>
+ <p>{entry.date.format('DD MMMM YYYY')} dapetnya Rp{calculatePerDay(entry, baseSalary)}</p>
+ </div>
+ )
+ })}
+ </div>
+ )
+}
+
+function calculatePerDay(entry, baseSalary) {
+ const hourlyPay = baseSalary / 173;
+ const timeDiff = entry.finish.diff(entry.start, 'hour', true);
+ let multiplier = 1.5; // Jam pertama
+ if (timeDiff > 1) {
+ multiplier += (timeDiff - 1) * 2; // Jam jam berikutnya
+ }
+
+ return multiplier * hourlyPay;
+}
+
+function getOvertimePayTotal(listEntry, baseSalary) {
+ let total = 0;
+ listEntry.forEach((entry) => {
+ total += calculatePerDay(entry, baseSalary)
+ });
+ return total;
+}
+
+export default Result; \ No newline at end of file
diff --git a/src/SalaryInput.jsx b/src/SalaryInput.jsx
index f04c68f..753d457 100644
--- a/src/SalaryInput.jsx
+++ b/src/SalaryInput.jsx
@@ -2,8 +2,8 @@ import { useState } from "react";
import TextField from "@mui/material/TextField";
import { NumericFormat } from "react-number-format";
-function SalaryInput() {
- const [displayValue, setDisplayValue] = useState('');
+function SalaryInput({handleBaseSalaryChange}) {
+ const [baseSalary, setBaseSalary] = useState('');
return (
<NumericFormat
customInput={ TextField }
@@ -11,8 +11,11 @@ function SalaryInput() {
variant="outlined"
valueIsNumericString={true}
thousandSeparator={true}
- value={displayValue}
- onValueChange={(value, sourceInfo) => {setDisplayValue(value.value)}}
+ value={baseSalary}
+ onValueChange={(value, sourceInfo) => {
+ setBaseSalary(value.value);
+ handleBaseSalaryChange(value.value);
+ }}
InputProps={{
startAdornment: <span>Rp</span>
}}