setting potongan gaji done
parent
3a30d72203
commit
4029cd099f
@ -0,0 +1,100 @@
|
|||||||
|
import React, { useEffect, useState } from 'react'
|
||||||
|
import { toast } from 'react-toastify'
|
||||||
|
import { Modal } from '@/Components/Modal'
|
||||||
|
import { useForm } from '@inertiajs/inertia-react'
|
||||||
|
import Button from '@/Components/Button'
|
||||||
|
import Input from '@/Components/Input'
|
||||||
|
import { create, update } from '@/Services/SettingPotonganGaji'
|
||||||
|
|
||||||
|
export default function FormModal({ modalState, refresh }) {
|
||||||
|
const [loading, setLoading] = useState(false)
|
||||||
|
const { data, setData, reset } = useForm({
|
||||||
|
jenis: 'alfa',
|
||||||
|
potongan: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (modalState.isOpen === false) {
|
||||||
|
reset()
|
||||||
|
modalState.setData(null)
|
||||||
|
}
|
||||||
|
if (modalState.data !== null) {
|
||||||
|
setData(modalState.data.data)
|
||||||
|
}
|
||||||
|
}, [modalState])
|
||||||
|
|
||||||
|
const onHandleChange = (event) => {
|
||||||
|
setData(
|
||||||
|
event.target.name,
|
||||||
|
event.target.type === 'checkbox'
|
||||||
|
? event.target.checked
|
||||||
|
: event.target.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const submit = (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
setLoading(true)
|
||||||
|
if (modalState.data !== null) {
|
||||||
|
update(data, modalState.data.id)
|
||||||
|
.finally(() => {
|
||||||
|
reset()
|
||||||
|
toast.success("berhasil update")
|
||||||
|
setLoading(false)
|
||||||
|
modalState.toggle()
|
||||||
|
refresh()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
create(data)
|
||||||
|
.then((id) => console.log(id))
|
||||||
|
.finally(() => {
|
||||||
|
reset()
|
||||||
|
toast.success("berhasil simpan")
|
||||||
|
setLoading(false)
|
||||||
|
modalState.toggle()
|
||||||
|
refresh()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal isOpen={modalState.isOpen} toggleModal={modalState.toggle}>
|
||||||
|
<div className="text-lg font-bold">Setting Potongan Gaji</div>
|
||||||
|
<label className="block text-sm mt-4">
|
||||||
|
<span className="text-gray-700 dark:text-gray-400">
|
||||||
|
Jenis Potongan
|
||||||
|
</span>
|
||||||
|
<select
|
||||||
|
className="border mt-1 border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
|
||||||
|
value={data.jenis}
|
||||||
|
name="jenis"
|
||||||
|
onChange={onHandleChange}
|
||||||
|
>
|
||||||
|
{["alfa", "sakit"].map((val, index) => (
|
||||||
|
<option
|
||||||
|
key={`val-${index}`}
|
||||||
|
value={val}
|
||||||
|
>
|
||||||
|
{val}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label className="block text-sm mt-4">
|
||||||
|
<span className="text-gray-700 dark:text-gray-400">
|
||||||
|
Jumlah Potongan
|
||||||
|
</span>
|
||||||
|
<Input
|
||||||
|
placeholder="081XXX"
|
||||||
|
name="potongan"
|
||||||
|
value={data.potongan}
|
||||||
|
handleChange={onHandleChange}
|
||||||
|
type="number"
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<Button className={'mt-4'} onClick={submit} disabled={loading} processing={loading}>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</Modal>
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,95 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import Authenticated from '@/Layouts/Authenticated';
|
||||||
|
import { Head } from '@inertiajs/inertia-react';
|
||||||
|
import { useModalState } from '@/Hooks'
|
||||||
|
import Button from '@/Components/Button';
|
||||||
|
import FormModal from './FormModal';
|
||||||
|
import { getAll } from '@/Services/SettingPotonganGaji';
|
||||||
|
import { toast } from 'react-toastify';
|
||||||
|
import { formatIDR } from '@/Utils';
|
||||||
|
|
||||||
|
export default function Karyawan(props) {
|
||||||
|
const formModal = useModalState(false)
|
||||||
|
|
||||||
|
const [items, setItems] = useState([])
|
||||||
|
|
||||||
|
const hanldeDeleteClick = (item) => {
|
||||||
|
const con = confirm("delete item?")
|
||||||
|
if (con) {
|
||||||
|
deleteById(item.id)
|
||||||
|
.then(() => toast.success('berhasil hapus'))
|
||||||
|
.finally(() => fetchData())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleEditClick = (item) => {
|
||||||
|
formModal.setData(item)
|
||||||
|
formModal.toggle()
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchData = () => {
|
||||||
|
getAll()
|
||||||
|
.then(items => {
|
||||||
|
console.log(items)
|
||||||
|
setItems(items)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchData()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Authenticated
|
||||||
|
auth={props.auth}
|
||||||
|
errors={props.errors}
|
||||||
|
>
|
||||||
|
<Head title="Potongan Gaji" />
|
||||||
|
|
||||||
|
<div className="py-0">
|
||||||
|
<div className="max-w-7xl sm:px-6">
|
||||||
|
<div className="bg-white overflow-hidden shadow-sm sm:rounded-lg">
|
||||||
|
<div className="p-6 bg-white border-b border-gray-200">
|
||||||
|
<div className='mb-5 text-3xl font-semibold'>
|
||||||
|
Setting Potongan Gaji
|
||||||
|
</div>
|
||||||
|
<Button onClick={formModal.toggle}>Tambah</Button>
|
||||||
|
<table className="w-full text-sm text-left text-gray-500 dark:text-gray-400 mt-5">
|
||||||
|
<thead className="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
|
||||||
|
<tr>
|
||||||
|
<th scope="col" className="py-3 px-6">
|
||||||
|
Jenis Potongan
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="py-3 px-6">
|
||||||
|
Jumlah Potongan
|
||||||
|
</th>
|
||||||
|
<th scope="col" className="py-3 px-6"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{items.map(item => (
|
||||||
|
<tr key={item.id} className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
|
||||||
|
<th scope="row" className="py-4 px-6 font-medium text-gray-900 whitespace-nowrap dark:text-white">
|
||||||
|
{item.data.jenis}
|
||||||
|
</th>
|
||||||
|
<td className="py-4 px-6">
|
||||||
|
Rp. {formatIDR(item.data.potongan)}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div className='flex space-x-1'>
|
||||||
|
<Button onClick={() => handleEditClick(item)}>Edit</Button>
|
||||||
|
<Button onClick={() => hanldeDeleteClick(item)}>Hapus</Button>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<FormModal modalState={formModal}refresh={fetchData}/>
|
||||||
|
</Authenticated>
|
||||||
|
);
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
import { useState } from "react";
|
||||||
|
import db from "@/firebase";
|
||||||
|
import { collection, getDocs, doc, addDoc, deleteDoc, updateDoc, query, where } from "firebase/firestore";
|
||||||
|
import { getAll as getKaryawan } from './Karyawan'
|
||||||
|
import { getAll as getJabatan } from './Jabatan'
|
||||||
|
|
||||||
|
async function getDataGaji() {
|
||||||
|
const [lists, setLists] = useState([])
|
||||||
|
const [jabatans, setJabatan] = useState([])
|
||||||
|
Promise.all([
|
||||||
|
() => getJabatan().then(items => setJabatan(items)),
|
||||||
|
() => getKaryawan().then(items => {
|
||||||
|
const employees = items.map(employee => {
|
||||||
|
const jab = jabatans.find(item => item.id == employee.data.jabatan.id)
|
||||||
|
// TODO: fetch potongan
|
||||||
|
return {
|
||||||
|
...employee,
|
||||||
|
gajiPokok: jab.gajiPokok,
|
||||||
|
tunjangan: jab.tunjangan,
|
||||||
|
feePenjualan: jab.feePenjualan,
|
||||||
|
transport: jab.transport,
|
||||||
|
uangMakan: jab.uangMakan,
|
||||||
|
bonus: jab.bonus,
|
||||||
|
total: jab.total
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
setLists(employees)
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
|
||||||
|
return lists
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
import db from "@/firebase";
|
||||||
|
import { collection, getDocs, doc, addDoc, deleteDoc, updateDoc } from "firebase/firestore";
|
||||||
|
|
||||||
|
const COLLECTION = "setting.potongan.gaji"
|
||||||
|
|
||||||
|
async function getAll() {
|
||||||
|
const collect = collection(db, COLLECTION)
|
||||||
|
const data = await getDocs(collect)
|
||||||
|
const lists = data.docs.map(doc => {
|
||||||
|
return {
|
||||||
|
data: doc.data(),
|
||||||
|
id: doc.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return lists
|
||||||
|
}
|
||||||
|
|
||||||
|
async function create(payload) {
|
||||||
|
const docRef = await addDoc(collection(db, COLLECTION), payload)
|
||||||
|
return docRef.id
|
||||||
|
}
|
||||||
|
|
||||||
|
async function update(payload, id){
|
||||||
|
const docRef = doc(db, COLLECTION, id)
|
||||||
|
const result = await updateDoc(docRef, payload);
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
async function deleteById(id) {
|
||||||
|
console.log(id)
|
||||||
|
const docRef = doc(db, COLLECTION, id)
|
||||||
|
const result = await deleteDoc(docRef);
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
getAll,
|
||||||
|
create,
|
||||||
|
update,
|
||||||
|
deleteById
|
||||||
|
}
|
Loading…
Reference in New Issue