From b5c188815329607a45881881f346aa82e6497318 Mon Sep 17 00:00:00 2001 From: Iqbal Rizqi Kurniawan Date: Fri, 24 Oct 2025 10:52:03 +0700 Subject: [PATCH] Enhance DetailJadwalShift and ListJadwalShift components with improved employee fetching, form handling, and UI updates --- .../component/DetailJadwalShift.jsx | 271 ++++---- .../jadwalShift/component/ListJadwalShift.jsx | 655 ++++++++++++------ 2 files changed, 579 insertions(+), 347 deletions(-) diff --git a/src/pages/jadwalShift/component/DetailJadwalShift.jsx b/src/pages/jadwalShift/component/DetailJadwalShift.jsx index 4f77120..83d705f 100644 --- a/src/pages/jadwalShift/component/DetailJadwalShift.jsx +++ b/src/pages/jadwalShift/component/DetailJadwalShift.jsx @@ -1,172 +1,173 @@ import React, { useEffect, useState } from 'react'; import { Modal, - Input, Typography, Button, ConfigProvider, - Row, - Col + Form, + Select, + Spin, + Input } from 'antd'; -import { NotifOk } from '../../../components/Global/ToastNotif'; +import { NotifOk, NotifAlert } from '../../../components/Global/ToastNotif'; +import { updateJadwalShift, createJadwalShift } from '../../../api/jadwal-shift.jsx'; const { Text } = Typography; +const { Option } = Select; const DetailJadwalShift = (props) => { + const [form] = Form.useForm(); const [confirmLoading, setConfirmLoading] = useState(false); + const [employees, setEmployees] = useState([]); + const [loadingEmployees, setLoadingEmployees] = useState(false); - const defaultData = { - id: '', - nama_shift: '', - jam_masuk: '', - jam_pulang: '', - username: '', - nama_employee: '', - whatsapp: '' - }; - - const [FormData, setFormData] = useState(defaultData); + const isReadOnly = props.actionMode === 'preview'; const handleCancel = () => { - props.setSelectedData(null); props.setActionMode('list'); }; + const fetchEmployees = async () => { + setLoadingEmployees(true); + try { + // Data dummy untuk dropdown karyawan + const dummyEmployees = [ + { employee_id: '101', nama_employee: 'Andi Pratama' }, + { employee_id: '102', nama_employee: 'Budi Santoso' }, + { employee_id: '103', nama_employee: 'Citra Lestari' }, + { employee_id: '104', nama_employee: 'Dewi Anggraini' }, + { employee_id: '105', nama_employee: 'Eko Wahyudi' }, + { employee_id: '106', nama_employee: 'Fitriani' }, + ]; + setEmployees(dummyEmployees); + } catch (error) { + NotifAlert({ icon: 'error', title: 'Gagal', message: 'Gagal memuat daftar karyawan.' }); + } finally { + setLoadingEmployees(false); + } + }; + const handleSave = async () => { - setConfirmLoading(true); - // This is a dummy save function for slicing purposes - setTimeout(() => { + try { + const values = await form.validateFields(); + let payload; + let responseMessage; + + setConfirmLoading(true); + if (props.actionMode === 'edit') { + payload = { ...props.selectedData, ...values }; + // await updateJadwalShift(payload.schedule_id, payload); + console.log("Updating schedule with payload:", payload); + responseMessage = 'Jadwal berhasil diperbarui.'; + } else { // 'add' mode + payload = { + employee_id: values.employee_id, + shift_name: props.selectedData.shift_name, + schedule_date: new Date().toISOString().split('T')[0], // Example date + }; + // await createJadwalShift(payload); + console.log("Creating schedule with payload:", payload); + responseMessage = 'User berhasil ditambahkan ke jadwal.'; + } + await new Promise(resolve => setTimeout(resolve, 500)); // Simulasi API call + + NotifOk({ icon: 'success', title: 'Berhasil', message: responseMessage }); + props.setActionMode('list'); // Menutup modal dan memicu refresh di parent + } catch (error) { + const message = error.response?.data?.message || 'Gagal memperbarui jadwal.'; + NotifAlert({ icon: 'error', title: 'Gagal', message }); + } finally { setConfirmLoading(false); - NotifOk({ - icon: 'success', - title: 'Berhasil', - message: 'Data dummy berhasil disimpan.', - }); - props.setActionMode('list'); - }, 1000); + } }; useEffect(() => { - if (props.selectedData) { - setFormData(props.selectedData); - } else { - setFormData(defaultData); + // Hanya jalankan jika modal untuk 'edit' atau 'preview' terbuka + if (props.showModal) { + fetchEmployees(); + if (props.actionMode === 'edit' || props.actionMode === 'preview') { + form.setFieldsValue({ + employee_id: props.selectedData.employee_id, + shift_name: props.selectedData.shift_name, + }); + } else if (props.actionMode === 'add') { + form.setFieldsValue({ + shift_name: props.selectedData.shift_name, + employee_id: null, // Reset employee selection + }); + } } - }, [props.showModal, props.selectedData]); - - // Dummy handler for slicing - const handleInputChange = (e) => { - const { name, value } = e.target; - setFormData({ ...FormData, [name]: value }); - }; + }, [props.actionMode, props.showModal, props.selectedData, form]); return ( - - - - - {!props.readOnly && ( - - )} - + + {!isReadOnly && ( + + )} , ]} > - {FormData && ( -
- - - Nama Karyawan - - - - Username - - - - Nama Shift - - - - Whatsapp - - - - Jam Masuk - - - - Jam Pulang - - - -
- )} + +
+ {props.actionMode === 'add' ? ( + <> + + + + + + + + ) : ( + <> + + + + + + + + )} +
+
); }; diff --git a/src/pages/jadwalShift/component/ListJadwalShift.jsx b/src/pages/jadwalShift/component/ListJadwalShift.jsx index 631c3c9..57c11f3 100644 --- a/src/pages/jadwalShift/component/ListJadwalShift.jsx +++ b/src/pages/jadwalShift/component/ListJadwalShift.jsx @@ -1,153 +1,146 @@ import React, { memo, useState, useEffect } from 'react'; -import { Space, Tag, ConfigProvider, Button, Row, Col, Card, Input } from 'antd'; +import { Space, ConfigProvider, Button, Row, Col, Card, Input, Typography, Spin, Divider, Checkbox, Select } from 'antd'; import { PlusOutlined, + SearchOutlined, + EyeOutlined, EditOutlined, DeleteOutlined, - EyeOutlined, - SearchOutlined, } from '@ant-design/icons'; -import { NotifAlert, NotifConfirmDialog } from '../../../components/Global/ToastNotif'; +import { NotifAlert, NotifOk, NotifConfirmDialog } from '../../../components/Global/ToastNotif'; import { useNavigate } from 'react-router-dom'; -import TableList from '../../../components/Global/TableList'; -import { getAllJadwalShift, deleteJadwalShift } from '../../../api/jadwal-shift'; +import { getAllJadwalShift, deleteJadwalShift, updateJadwalShift } from '../../../api/jadwal-shift.jsx'; -const columns = (showPreviewModal, showEditModal, showDeleteDialog) => [ - { - title: 'Tanggal Jadwal', - dataIndex: 'schedule_date', - key: 'schedule_date', - render: (date) => date ? new Date(date).toLocaleDateString('id-ID') : '-', - }, - { - title: 'Nama Shift', - dataIndex: 'shift_name', - key: 'shift_name', - render: (text) => text || '-', - }, - { - title: 'Jam Masuk', - dataIndex: 'start_time', - key: 'start_time', - render: (time) => time || '-', - }, - { - title: 'Jam Pulang', - dataIndex: 'end_time', - key: 'end_time', - render: (time) => time || '-', - }, - { - title: 'Status', - dataIndex: 'is_active', - key: 'is_active', - render: (isActive) => ( - - {isActive ? 'Aktif' : 'Tidak Aktif'} - - ), - }, - { - title: 'Aksi', - key: 'aksi', - align: 'center', - render: (_, record) => ( - - + + + + + + ) : ( + <> + + - Search - - } - size="large" - /> - - - - - + + + + { + const value = e.target.value; + setSearchValue(value); + if (value === '') { + handleSearchClear(); + } + }} + onSearch={handleSearch} + allowClear + enterButton={ + - - - + /> + + + )} - - - + + +
+ {(Object.keys(groupedSchedules).length === 0 && !loading) ? ( + Tidak ada data jadwal untuk ditampilkan. + ) : ( + Object.keys(groupedSchedules).map(shiftName => ( // Iterate through each shift (PAGI, SIANG, MALAM) +
{/* Container for each shift section */} + + + + SHIFT {shiftName} ({groupedSchedules[shiftName].users.length} Karyawan) + + + {editingShift === shiftName ? ( + + + + + + + + ) : ( + + + + + + + + + )} + + + {/* Horizontal scrollable container for employee cards */} +
+ {groupedSchedules[shiftName].users.length > 0 ? ( + groupedSchedules[shiftName].users.map(user => ( + + {isEditMode && editingShift === null && ( // Checkbox for global delete mode only + handleSelectSchedule(user.schedule_id, e.target.checked)} + onClick={(e) => e.stopPropagation()} // Prevent card click + /> + )} + {editingShift === shiftName || (isEditMode && editingShift === null) ? ( // Global or Shift-specific Edit Mode + // EDIT MODE VIEW +
+ + + + + handleSelectSchedule(user.schedule_id, e.target.checked)} + /> +
+ ) : ( + // NORMAL VIEW +
+
+ {user.nama_employee} + {user.whatsapp} +
+
+ + Terakhir diperbarui
+ {formatRelativeTimestamp(groupedSchedules[shiftName].lastUpdate.timestamp)}
+ oleh {groupedSchedules[shiftName].lastUpdate.user} +
+ +
+
+ )} +
+ )) + ) : ( + Tidak ada karyawan yang dijadwalkan untuk shift ini. + )} +
+
+ )) + )} +
+
); }); -export default ListJadwalShift; \ No newline at end of file +export default ListJadwalShift;