refactor(FE): Refactor dropdown and export button components

This commit is contained in:
rstubryan
2026-02-13 09:53:33 +07:00
parent 3a676723e4
commit d312da4c66
5 changed files with 216 additions and 161 deletions
@@ -25,8 +25,6 @@ import {
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
import Button from '@/components/Button'; import Button from '@/components/Button';
import Dropdown from '@/components/Dropdown'; import Dropdown from '@/components/Dropdown';
import MenuItem from '@/components/menu/MenuItem';
import Menu from '@/components/menu/Menu';
import Modal, { useModal } from '@/components/Modal'; import Modal, { useModal } from '@/components/Modal';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
import { useFormik } from 'formik'; import { useFormik } from 'formik';
@@ -387,13 +385,13 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
color='none' color='none'
onClick={handleFilterModalOpen} onClick={handleFilterModalOpen}
className={cn( className={cn(
'px-3 py-2.5', 'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
'rounded-lg! font-semibold text-sm gap-1.5', {
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft', 'border-primary-gradient text-primary': hasFilters,
hasFilters && 'border-primary-gradient text-primary' }
)} )}
> >
<Icon icon='heroicons:funnel' width={18} height={18} /> <Icon icon='heroicons:funnel' width={20} height={20} />
Filter Filter
{hasFilters && ( {hasFilters && (
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'> <span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
@@ -403,42 +401,55 @@ const CustomerPaymentTab = ({ tabId }: CustomerPaymentTabProps) => {
</Button> </Button>
<Dropdown <Dropdown
align='end'
direction='bottom'
className={{
content:
'mt-1 rounded-xl border border-base-content/5 shadow-sm overflow-hidden',
}}
trigger={ trigger={
<Button <Button
variant='outline' variant='outline'
color='none' color='none'
isLoading={isAnyExportLoading} isLoading={isAnyExportLoading}
className={cn( className='px-3 py-2.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
'px-3 py-2.5',
'rounded-lg font-semibold text-sm gap-1.5',
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft'
)}
> >
<Icon icon='heroicons:cloud-arrow-down' width={20} height={20} /> <div className='flex flex-row items-center gap-1.5'>
Export <Icon
<div className='w-6.5 h-5 flex items-center justify-center border-l border-base-content/10'> icon='heroicons:cloud-arrow-down'
<Icon width={14} height={14} icon='heroicons:chevron-down' /> width={20}
height={20}
/>
<span>Export</span>
<div className='w-px self-stretch bg-base-content/10' />
<Icon icon='heroicons:chevron-down' width={14} height={14} />
</div> </div>
</Button> </Button>
} }
align='end'
className={{
content:
'mt-1 p-0 w-full shadow-button-soft border border-base-content/10 rounded-lg',
}}
> >
<Menu className='p-0 w-full'> <Button
<MenuItem variant='ghost'
className='text-sm p-3' color='none'
title='Excel' onClick={handleExportExcel}
onClick={handleExportExcel} isLoading={isExcelExportLoading}
/> className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
<MenuItem >
className='text-sm p-3' <Icon icon='heroicons:table-cells' width={20} height={20} />
title='PDF' Export to Excel
onClick={handleExportPdf} </Button>
/> <Button
</Menu> variant='ghost'
color='none'
onClick={handleExportPdf}
isLoading={isPdfExportLoading}
className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
>
<Icon icon='heroicons:document' width={20} height={20} />
Export to PDF
</Button>
</Dropdown> </Dropdown>
</div> </div>
); );
@@ -3,8 +3,6 @@ import Card from '@/components/Card';
import Dropdown from '@/components/Dropdown'; import Dropdown from '@/components/Dropdown';
import DateInput from '@/components/input/DateInput'; import DateInput from '@/components/input/DateInput';
import { OptionType, useSelect } from '@/components/input/SelectInput'; import { OptionType, useSelect } from '@/components/input/SelectInput';
import Menu from '@/components/menu/Menu';
import MenuItem from '@/components/menu/MenuItem';
import Modal, { useModal } from '@/components/Modal'; import Modal, { useModal } from '@/components/Modal';
import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table'; import Table, { TABLE_DEFAULT_STYLING } from '@/components/Table';
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
@@ -277,7 +275,7 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => {
useEffect(() => { useEffect(() => {
setTabActions( setTabActions(
tabId, tabId,
<div className='flex flex-row gap-3 '> <div className='flex flex-row gap-3'>
<ButtonFilter <ButtonFilter
values={formik.values} values={formik.values}
onClick={handleFilterModalOpen} onClick={handleFilterModalOpen}
@@ -286,42 +284,55 @@ const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => {
/> />
<Dropdown <Dropdown
align='end'
direction='bottom'
className={{
content:
'mt-1 rounded-xl border border-base-content/5 shadow-sm overflow-hidden',
}}
trigger={ trigger={
<Button <Button
variant='outline' variant='outline'
color='none' color='none'
isLoading={isAnyExportLoading} isLoading={isAnyExportLoading}
className={cn( className='px-3 py-2.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
'px-3 py-2.5',
'rounded-lg font-semibold text-sm gap-1.5',
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft'
)}
> >
<Icon icon='heroicons:cloud-arrow-down' width={20} height={20} /> <div className='flex flex-row items-center gap-1.5'>
Export <Icon
<div className='w-6.5 h-5 flex items-center justify-center border-l border-base-content/10'> icon='heroicons:cloud-arrow-down'
<Icon width={14} height={14} icon='heroicons:chevron-down' /> width={20}
height={20}
/>
<span>Export</span>
<div className='w-px self-stretch bg-base-content/10' />
<Icon icon='heroicons:chevron-down' width={14} height={14} />
</div> </div>
</Button> </Button>
} }
align='end'
className={{
content:
'mt-1 p-0 w-full shadow-button-soft border border-base-content/10 rounded-lg',
}}
> >
<Menu className='p-0 w-full'> <Button
<MenuItem variant='ghost'
className='text-sm p-3' color='none'
title='Excel' onClick={handleExportExcel}
onClick={handleExportExcel} isLoading={isExcelExportLoading}
/> className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
<MenuItem >
className='text-sm p-3' <Icon icon='heroicons:table-cells' width={20} height={20} />
title='PDF' Export to Excel
onClick={handleExportPdf} </Button>
/> <Button
</Menu> variant='ghost'
color='none'
onClick={handleExportPdf}
isLoading={isPdfExportLoading}
className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
>
<Icon icon='heroicons:document' width={20} height={20} />
Export to PDF
</Button>
</Dropdown> </Dropdown>
</div> </div>
); );
@@ -3,8 +3,6 @@ import Card from '@/components/Card';
import Dropdown from '@/components/Dropdown'; import Dropdown from '@/components/Dropdown';
import DateInput from '@/components/input/DateInput'; import DateInput from '@/components/input/DateInput';
import { useSelect } from '@/components/input/SelectInput'; import { useSelect } from '@/components/input/SelectInput';
import Menu from '@/components/menu/Menu';
import MenuItem from '@/components/menu/MenuItem';
import Modal, { useModal } from '@/components/Modal'; import Modal, { useModal } from '@/components/Modal';
import Table from '@/components/Table'; import Table from '@/components/Table';
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
@@ -498,13 +496,13 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
color='none' color='none'
onClick={handleFilterModalOpen} onClick={handleFilterModalOpen}
className={cn( className={cn(
'px-3 py-2.5', 'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
'rounded-lg! font-semibold text-sm gap-1.5', {
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft', 'border-primary-gradient text-primary': hasFilters,
hasFilters && 'border-primary-gradient text-primary' }
)} )}
> >
<Icon icon='heroicons:funnel' width={18} height={18} /> <Icon icon='heroicons:funnel' width={20} height={20} />
Filter Filter
{hasFilters && ( {hasFilters && (
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'> <span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
@@ -514,42 +512,55 @@ const PurchasesPerSupplierTab = ({ tabId }: PurchasesPerSupplierTabProps) => {
</Button> </Button>
<Dropdown <Dropdown
align='end'
direction='bottom'
className={{
content:
'mt-1 rounded-xl border border-base-content/5 shadow-sm overflow-hidden',
}}
trigger={ trigger={
<Button <Button
variant='outline' variant='outline'
color='none' color='none'
isLoading={isAnyExportLoading} isLoading={isAnyExportLoading}
className={cn( className='px-3 py-2.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
'px-3 py-2.5',
'rounded-lg font-semibold text-sm gap-1.5',
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft'
)}
> >
<Icon icon='heroicons:cloud-arrow-down' width={20} height={20} /> <div className='flex flex-row items-center gap-1.5'>
Export <Icon
<div className='w-6.5 h-5 flex items-center justify-center border-l border-base-content/10'> icon='heroicons:cloud-arrow-down'
<Icon width={14} height={14} icon='heroicons:chevron-down' /> width={20}
height={20}
/>
<span>Export</span>
<div className='w-px self-stretch bg-base-content/10' />
<Icon icon='heroicons:chevron-down' width={14} height={14} />
</div> </div>
</Button> </Button>
} }
align='end'
className={{
content:
'mt-1 p-0 w-full shadow-button-soft border border-base-content/10 rounded-lg',
}}
> >
<Menu className='p-0 w-full'> <Button
<MenuItem variant='ghost'
className='text-sm p-3' color='none'
title='Excel' onClick={handleExportExcel}
onClick={handleExportExcel} isLoading={isExcelExportLoading}
/> className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
<MenuItem >
className='text-sm p-3' <Icon icon='heroicons:table-cells' width={20} height={20} />
title='PDF' Export to Excel
onClick={handleExportPdf} </Button>
/> <Button
</Menu> variant='ghost'
color='none'
onClick={handleExportPdf}
isLoading={isPdfExportLoading}
className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
>
<Icon icon='heroicons:document' width={20} height={20} />
Export to PDF
</Button>
</Dropdown> </Dropdown>
</div> </div>
); );
@@ -18,8 +18,6 @@ import {
import { isResponseSuccess } from '@/lib/api-helper'; import { isResponseSuccess } from '@/lib/api-helper';
import Button from '@/components/Button'; import Button from '@/components/Button';
import Dropdown from '@/components/Dropdown'; import Dropdown from '@/components/Dropdown';
import MenuItem from '@/components/menu/MenuItem';
import Menu from '@/components/menu/Menu';
import { generateHppPerKandangPDF } from '@/components/pages/report/marketing/export/HppPerkandangExportPDF'; import { generateHppPerKandangPDF } from '@/components/pages/report/marketing/export/HppPerkandangExportPDF';
import { generateHppPerKandangExcel } from '@/components/pages/report/marketing/export/HppPerkandangExportXLSX'; import { generateHppPerKandangExcel } from '@/components/pages/report/marketing/export/HppPerkandangExportXLSX';
import toast from 'react-hot-toast'; import toast from 'react-hot-toast';
@@ -499,13 +497,13 @@ const HppPerKandangTab = ({ tabId }: HppPerKandangTabProps) => {
color='none' color='none'
onClick={handleFilterModalOpen} onClick={handleFilterModalOpen}
className={cn( className={cn(
'px-3 py-2.5', 'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
'rounded-lg! font-semibold text-sm gap-1.5', {
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft', 'border-primary-gradient text-primary': hasFilters,
hasFilters && 'border-primary-gradient text-primary' }
)} )}
> >
<Icon icon='heroicons:funnel' width={18} height={18} /> <Icon icon='heroicons:funnel' width={20} height={20} />
Filter Filter
{hasFilters && ( {hasFilters && (
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'> <span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
@@ -515,42 +513,55 @@ const HppPerKandangTab = ({ tabId }: HppPerKandangTabProps) => {
</Button> </Button>
<Dropdown <Dropdown
align='end'
direction='bottom'
className={{
content:
'mt-1 rounded-xl border border-base-content/5 shadow-sm overflow-hidden',
}}
trigger={ trigger={
<Button <Button
variant='outline' variant='outline'
color='none' color='none'
isLoading={isAnyExportLoading} isLoading={isAnyExportLoading}
className={cn( className='px-3 py-2.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
'px-3 py-2.5',
'rounded-lg font-semibold text-sm gap-1.5',
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft'
)}
> >
<Icon icon='heroicons:cloud-arrow-down' width={20} height={20} /> <div className='flex flex-row items-center gap-1.5'>
Export <Icon
<div className='w-6.5 h-5 flex items-center justify-center border-l border-base-content/10'> icon='heroicons:cloud-arrow-down'
<Icon width={14} height={14} icon='heroicons:chevron-down' /> width={20}
height={20}
/>
<span>Export</span>
<div className='w-px self-stretch bg-base-content/10' />
<Icon icon='heroicons:chevron-down' width={14} height={14} />
</div> </div>
</Button> </Button>
} }
align='end'
className={{
content:
'mt-1 p-0 w-full shadow-button-soft border border-base-content/10 rounded-lg',
}}
> >
<Menu className='p-0 w-full'> <Button
<MenuItem variant='ghost'
className='text-sm p-3' color='none'
title='Excel' onClick={handleExportExcel}
onClick={handleExportExcel} isLoading={isExcelExportLoading}
/> className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
<MenuItem >
className='text-sm p-3' <Icon icon='heroicons:table-cells' width={20} height={20} />
title='PDF' Export to Excel
onClick={handleExportPDF} </Button>
/> <Button
</Menu> variant='ghost'
color='none'
onClick={handleExportPDF}
isLoading={isPdfExportLoading}
className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
>
<Icon icon='heroicons:document' width={20} height={20} />
Export to PDF
</Button>
</Dropdown> </Dropdown>
</div> </div>
); );
@@ -9,8 +9,6 @@ import { Icon } from '@iconify/react';
import Button from '@/components/Button'; import Button from '@/components/Button';
import Dropdown from '@/components/dropdown/Dropdown'; import Dropdown from '@/components/dropdown/Dropdown';
import SelectInput, { useSelect } from '@/components/input/SelectInput'; import SelectInput, { useSelect } from '@/components/input/SelectInput';
import Menu from '@/components/menu/Menu';
import MenuItem from '@/components/menu/MenuItem';
import ProductionResultProjectFlockKandangTable from '@/components/pages/report/production-result/ProductionResultProjectFlockKandangTable'; import ProductionResultProjectFlockKandangTable from '@/components/pages/report/production-result/ProductionResultProjectFlockKandangTable';
import { useFormik } from 'formik'; import { useFormik } from 'formik';
import { import {
@@ -546,13 +544,13 @@ const ProductionResultContent = ({ tabId }: ProductionResultTabProps) => {
color='none' color='none'
onClick={() => filterModal.openModal()} onClick={() => filterModal.openModal()}
className={cn( className={cn(
'px-3 py-2.5', 'px-3 py-2.5 gap-1.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft transition-all',
'rounded-lg! font-semibold text-sm gap-1.5', {
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft', 'border-primary-gradient text-primary': hasFilters,
hasFilters && 'border-primary-gradient text-primary' }
)} )}
> >
<Icon icon='heroicons:funnel' width={18} height={18} /> <Icon icon='heroicons:funnel' width={20} height={20} />
Filter Filter
{hasFilters && ( {hasFilters && (
<span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'> <span className='w-5 h-5 text-white bg-[#FF3535] rounded-lg border border-base-300 flex items-center justify-center text-xs'>
@@ -562,42 +560,55 @@ const ProductionResultContent = ({ tabId }: ProductionResultTabProps) => {
</Button> </Button>
<Dropdown <Dropdown
align='end'
direction='bottom'
className={{
content:
'mt-1 rounded-xl border border-base-content/5 shadow-sm overflow-hidden',
}}
trigger={ trigger={
<Button <Button
variant='outline' variant='outline'
color='none' color='none'
isLoading={isAnyExportLoading} isLoading={isAnyExportLoading}
className={cn( className='px-3 py-2.5 text-sm text-base-content/50 border border-base-content/10 rounded-xl shadow-button-soft'
'px-3 py-2.5',
'rounded-lg font-semibold text-sm gap-1.5',
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft'
)}
> >
<Icon icon='heroicons:cloud-arrow-down' width={20} height={20} /> <div className='flex flex-row items-center gap-1.5'>
Export <Icon
<div className='w-6.5 h-5 flex items-center justify-center border-l border-base-content/10'> icon='heroicons:cloud-arrow-down'
<Icon width={14} height={14} icon='heroicons:chevron-down' /> width={20}
height={20}
/>
<span>Export</span>
<div className='w-px self-stretch bg-base-content/10' />
<Icon icon='heroicons:chevron-down' width={14} height={14} />
</div> </div>
</Button> </Button>
} }
align='end'
className={{
content:
'mt-1 p-0 w-full shadow-button-soft border border-base-content/10 rounded-lg',
}}
> >
<Menu className='p-0 w-full'> <Button
<MenuItem variant='ghost'
className='text-sm p-3' color='none'
title='Excel' onClick={exportToExcelHandler}
onClick={exportToExcelHandler} isLoading={isExcelExportLoading}
/> className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
<MenuItem >
className='text-sm p-3' <Icon icon='heroicons:table-cells' width={20} height={20} />
title='PDF' Export to Excel
onClick={exportToPdfHandler} </Button>
/> <Button
</Menu> variant='ghost'
color='none'
onClick={exportToPdfHandler}
isLoading={isPdfExportLoading}
className='w-full p-3 justify-start text-sm text-base-content/50 font-semibold text-nowrap'
>
<Icon icon='heroicons:document' width={20} height={20} />
Export to PDF
</Button>
</Dropdown> </Dropdown>
</div> </div>
); );