From 9eba5ffeca12a2e58c25df8be24baa24bedca5f3 Mon Sep 17 00:00:00 2001 From: randy-ar Date: Tue, 2 Dec 2025 12:37:03 +0700 Subject: [PATCH] feat(FE): create floation actions button --- src/app/production/project-flock/layout.tsx | 4 +- src/components/FloatingActionsButton.tsx | 127 ++++++++++++++++++ .../project-flock/ProjectFlockTable.tsx | 56 +++++++- 3 files changed, 184 insertions(+), 3 deletions(-) create mode 100644 src/components/FloatingActionsButton.tsx diff --git a/src/app/production/project-flock/layout.tsx b/src/app/production/project-flock/layout.tsx index bc50b862..fbfc5eb4 100644 --- a/src/app/production/project-flock/layout.tsx +++ b/src/app/production/project-flock/layout.tsx @@ -36,7 +36,7 @@ export default function ProjectFlockLayout({ return ( <> {/* List page always rendered */} -
+
!isOpen && router.push('/production/project-flock')} /> @@ -48,7 +48,7 @@ export default function ProjectFlockLayout({ setOpen={(v) => { if (!v) router.push('/production/project-flock'); }} - closeOnBackdropClick={false} + closeOnBackdropClick={isDetail ? true : false} onBackdropClick={handleBackdropClick} variant='right' sidebarContent={isOpen &&
{children}
} diff --git a/src/components/FloatingActionsButton.tsx b/src/components/FloatingActionsButton.tsx new file mode 100644 index 00000000..8be8669f --- /dev/null +++ b/src/components/FloatingActionsButton.tsx @@ -0,0 +1,127 @@ +'use client'; + +import { cn } from '@/lib/helper'; +import { Icon } from '@iconify/react'; + +type FloatingActionsButtonProps = { + actions: { + action: 'DETAIL' | 'EDIT' | 'DELETE'; + icon: string; + label?: string; + onClick?: () => void; + hidden?: boolean; + }[]; + approvals: { + action: 'APPROVED' | 'REJECTED'; + icon: string; + label?: string; + onClick?: () => void; + }[]; + selectedRowIds: number[]; + onClose: () => void; +}; + +const FloatingActionsButton = ({ + actions, + approvals, + selectedRowIds, + onClose, +}: FloatingActionsButtonProps) => { + // Jika tidak ada baris yang dipilih, jangan tampilkan FAB + const positionStyles = + selectedRowIds.length > 0 ? 'bottom-[10%]' : 'bottom-[-100%]'; + + // Helper untuk menentukan gaya warna tombol approval + const getApprovalColor = (action: 'APPROVED' | 'REJECTED') => { + if (action === 'APPROVED') return 'success'; + if (action === 'REJECTED') return 'error'; + return 'primary'; + }; + + const getActionColor = (action: 'DETAIL' | 'EDIT' | 'DELETE') => { + if (action === 'DETAIL') return 'white'; + if (action === 'EDIT') return 'warning'; + if (action === 'DELETE') return 'error'; + return 'primary'; + }; + + return ( + // Container utama FAB +
+
+ {/* === BARIS ATAS: Status Seleksi dan Actions (Termasuk Close) === */} +
+

+ {selectedRowIds.length} Selected +

+ +
+
+ {/* Render Aksi dari props.actions */} + {actions + .filter((action) => !action.hidden) + .map((action, index) => { + return ( + + ); + })} + +
+ + {/* Tombol Close */} + +
+
+
+ + {/* === BARIS BAWAH: Approval Buttons (Approve/Reject) === */} +
+ {approvals.map((approval, index) => ( + + ))} +
+
+
+ ); +}; + +export default FloatingActionsButton; diff --git a/src/components/pages/production/project-flock/ProjectFlockTable.tsx b/src/components/pages/production/project-flock/ProjectFlockTable.tsx index bdbfbe18..51ef2ab6 100644 --- a/src/components/pages/production/project-flock/ProjectFlockTable.tsx +++ b/src/components/pages/production/project-flock/ProjectFlockTable.tsx @@ -1,6 +1,7 @@ 'use client'; import Button from '@/components/Button'; +import FloatingActionsButton from '@/components/FloatingActionsButton'; import CheckboxInput from '@/components/input/CheckboxInput'; import DebouncedTextInput from '@/components/input/DebouncedTextInput'; import SelectInput, { OptionType } from '@/components/input/SelectInput'; @@ -20,6 +21,7 @@ import { Kandang } from '@/types/api/master-data/kandang'; import { ProjectFlock } from '@/types/api/production/project-flock'; import { Icon } from '@iconify/react'; import { CellContext, SortingState } from '@tanstack/react-table'; +import { useRouter } from 'next/navigation'; import { ChangeEventHandler, useEffect, useState } from 'react'; import toast from 'react-hot-toast'; import useSWR from 'swr'; @@ -119,6 +121,7 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => { periodFilter: 'period', }, }); + const router = useRouter(); // State const [rowSelection, setRowSelection] = useState>({}); @@ -262,7 +265,7 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => { return ( <> -
+
@@ -577,6 +580,57 @@ const ProjectFlockTable = ({ refresh }: { refresh?: () => void }) => {
+ { + toast.error(`Konfirmasi hapus ${selectedRowIds.length} data.`); + }, + }, + ]} + approvals={[ + { + icon: 'material-symbols:check', + label: 'Approve', + action: 'APPROVED', + onClick: () => { + setApprovalAction('APPROVED'); + confirmModal.openModal(); + setRowSelection({}); + }, + }, + { + icon: 'mdi:times', + label: 'Reject', + action: 'REJECTED', + onClick: () => { + setApprovalAction('REJECTED'); + confirmModal.openModal(); + setRowSelection({}); + }, + }, + ]} + selectedRowIds={selectedRowIds} + onClose={() => { + setRowSelection({}); + }} + /> +