@@ -126,7 +126,7 @@ export default function Authenticated({ auth, children }) {
-
+
Data Absensi
diff --git a/resources/js/Pages/Absensi/FormModal.jsx b/resources/js/Pages/Absensi/FormModal.jsx
new file mode 100644
index 0000000..3f9dee8
--- /dev/null
+++ b/resources/js/Pages/Absensi/FormModal.jsx
@@ -0,0 +1,128 @@
+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 { getAll } from '@/Services/Karyawan'
+import { create } from '@/Services/Absensi'
+
+export default function FormModal({ modalState, periode, refresh }) {
+ const [loading, setLoading] = useState(false)
+ const { data, setData, reset } = useForm({
+ users: []
+ })
+
+ useEffect(() => {
+ getAll()
+ .then(items => setData({
+ users: items.filter(item => item.data.jabatan.id != "1").map(item => {
+ return {
+ id: item.id,
+ name: item.data.name,
+ nik: item.data.nik,
+ jenisKelamin: item.data.jenisKelamin,
+ jabatan: item.data.jabatan.nama,
+ jabatan_id: item.data.jabatan.id,
+ hadir: 0,
+ sakit: 0,
+ alfa: 0,
+ }
+ })
+ }))
+ },[modalState])
+
+ const onHandleChange = (item, event) => {
+ setData({
+ users: data.users.map(user => {
+ if (user.id == item.id) {
+ user[event.target.name] = event.target.value
+ }
+ return user
+ })
+ })
+ }
+
+ const submit = (e) => {
+ e.preventDefault()
+ setLoading(true)
+ create({
+ ...data,
+ periode: periode,
+ })
+ .then(() => {
+ reset()
+ modalState.toggle()
+ })
+ .finally(() => setLoading(false))
+ }
+
+ return (
+
+ Absensi Karyawan
+ Periode : {periode}
+
+
+
+ )
+}
\ No newline at end of file
diff --git a/resources/js/Pages/Absensi/Index.jsx b/resources/js/Pages/Absensi/Index.jsx
new file mode 100644
index 0000000..aee2f30
--- /dev/null
+++ b/resources/js/Pages/Absensi/Index.jsx
@@ -0,0 +1,132 @@
+import React, { useEffect, useState } from 'react';
+import Authenticated from '@/Layouts/Authenticated';
+import { Head, useForm } from '@inertiajs/inertia-react';
+import { useModalState } from '@/Hooks'
+import Button from '@/Components/Button';
+import FormModal from './FormModal';
+import { getByPeriode } from '@/Services/Absensi';
+import { toast } from 'react-toastify';
+
+export default function Karyawan(props) {
+ const formModal = useModalState(false)
+
+ const month = (new Date()).getMonth()
+ const year = (new Date()).getFullYear()
+ const months = [1,2,3,4,5,6,7,8,9,10,11,12]
+ const years = [+year-2, +year-1, year, +year+1, +year+2]
+
+ const {data, setData} = useForm({
+ month: month,
+ year: year
+ })
+
+ const onHandleChange = (event) => {
+ setData(
+ event.target.name,
+ event.target.type === 'checkbox'
+ ? event.target.checked
+ : event.target.value
+ )
+ }
+
+ const [absensi, setAbsensi] = useState({})
+ const onClickShow = () => {
+ setAbsensi({})
+ getByPeriode(`${data.month}_${data.year}`)
+ .then(items => {
+ if(items.length <= 0) {
+ toast.error("No data found")
+ return
+ }
+ setAbsensi(items[0])
+ })
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
Periode Data :
+
+
+
+
+
+
+
+
+
+
+
+
+ NIK
+ |
+
+ Nama
+ |
+
+ Jenis Kelamin
+ |
+
+ Jabatan
+ |
+ Hadir |
+ Sakit |
+ Alfa |
+
+
+
+ {absensi.data?.users?.map(item => (
+
+
+ {item.nik}
+ |
+
+ {item.name}
+ |
+
+ {item.jenisKelamin}
+ |
+
+ {item.jabatan}
+ |
+
+ {item.hadir}
+ |
+
+ {item.sakit}
+ |
+
+ {item.alfa}
+ |
+
+ ))}
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/resources/js/Pages/Jabatan/FormModal.jsx b/resources/js/Pages/Jabatan/FormModal.jsx
index e274372..92fed0f 100644
--- a/resources/js/Pages/Jabatan/FormModal.jsx
+++ b/resources/js/Pages/Jabatan/FormModal.jsx
@@ -10,9 +10,24 @@ export default function FormModal({ modalState, refresh }) {
const [loading, setLoading] = useState(false)
const { data, setData, reset } = useForm({
nama: '',
- tunjangan: 0
+ gajiPokok: 0,
+ tunjangan: 0,
+ feePenjualan: 0,
+ transport: 0,
+ uangMakan: 0,
+ bonus: 0,
+ total: 0
})
+ const total = +data.gajiPokok + +data.tunjangan + +data.feePenjualan + +data.transport + +data.uangMakan + +data.bonus
+
+ useEffect(() => {
+ setData({
+ ...data,
+ total: total
+ })
+ }, [total])
+
useEffect(() => {
if (modalState.isOpen === false) {
reset()
@@ -71,6 +86,18 @@ export default function FormModal({ modalState, refresh }) {
handleChange={onHandleChange}
/>
+
+
+
+
+
diff --git a/resources/js/Pages/Jabatan/Index.jsx b/resources/js/Pages/Jabatan/Index.jsx
index cd2ed30..f229774 100644
--- a/resources/js/Pages/Jabatan/Index.jsx
+++ b/resources/js/Pages/Jabatan/Index.jsx
@@ -6,6 +6,7 @@ import Button from '@/Components/Button';
import FormModal from './FormModal';
import { getAll, deleteById } from '@/Services/Jabatan';
import { toast } from 'react-toastify';
+import { formatIDR } from '@/Utils';
export default function Jabatan(props) {
const formModal = useModalState(false)
@@ -53,9 +54,27 @@ export default function Jabatan(props) {
Nama
|
+
+ Gaji Pokok
+ |
Tunjangan
|
+
+ Fee Penjualan
+ |
+
+ Tunjangan Transport
+ |
+
+ Uang Makan
+ |
+
+ Bonus
+ |
+
+ Total
+ |
|
@@ -66,7 +85,25 @@ export default function Jabatan(props) {
{item.data.nama}
- Rp. {item.data.tunjangan}
+ Rp. {formatIDR(item.data.gajiPokok)}
+ |
+
+ Rp. {formatIDR(item.data.tunjangan)}
+ |
+
+ Rp. {formatIDR(item.data.feePenjualan)}
+ |
+
+ Rp. {formatIDR(item.data.transport)}
+ |
+
+ Rp. {formatIDR(item.data.uangMakan)}
+ |
+
+ Rp. {formatIDR(item.data.bonus)}
+ |
+
+ Rp. {formatIDR(item.data.total)}
|
diff --git a/resources/js/Services/Absensi.js b/resources/js/Services/Absensi.js
new file mode 100644
index 0000000..1fca1c9
--- /dev/null
+++ b/resources/js/Services/Absensi.js
@@ -0,0 +1,57 @@
+import db from "@/firebase";
+import { collection, getDocs, doc, addDoc, deleteDoc, updateDoc, query, where } from "firebase/firestore";
+
+const COLLECTION = "absensi"
+
+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 getByPeriode(periode) {
+ const collect = query(collection(db, COLLECTION), where("periode", "==", periode))
+ const data = await getDocs(collect)
+ if (data.size <= 0) {
+ return []
+ }
+ 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,
+ getByPeriode
+}
\ No newline at end of file
diff --git a/resources/js/Utils/index.js b/resources/js/Utils/index.js
new file mode 100644
index 0000000..074f4a6
--- /dev/null
+++ b/resources/js/Utils/index.js
@@ -0,0 +1,4 @@
+export function formatIDR(amount) {
+ const idFormatter = new Intl.NumberFormat('id-ID')
+ return idFormatter.format(amount)
+}
\ No newline at end of file
diff --git a/routes/web.php b/routes/web.php
index fd7cfa4..d25d33f 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -31,5 +31,6 @@ Route::middleware([IsSessionAuth::class])->group(function () {
Route::get('/dashboard', [GeneralController::class, 'dashboard'])->name('dashboard');
Route::get('/jabatan', [GeneralController::class, 'jabatan'])->name('jabatan');
Route::get('/karyawan', [GeneralController::class, 'karyawan'])->name('karyawan');
+ Route::get('/absensi', [GeneralController::class, 'absensi'])->name('absensi');
Route::post('/logout', [AuthController::class, 'destroy'])->name('logout');
});
|