mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-23 06:45:46 +00:00
fix(FE): adjust ui debt supplier pixel perfect figma
This commit is contained in:
@@ -123,6 +123,10 @@ const Card = ({
|
|||||||
return cn(baseClasses, 'p-6', className?.body);
|
return cn(baseClasses, 'p-6', className?.body);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getCollapsibleClasses = () => {
|
||||||
|
return cn('', className?.collapsible);
|
||||||
|
};
|
||||||
|
|
||||||
const getTitleClasses = () => {
|
const getTitleClasses = () => {
|
||||||
const sizeClasses = {
|
const sizeClasses = {
|
||||||
sm: 'text-lg',
|
sm: 'text-lg',
|
||||||
@@ -213,6 +217,7 @@ const Card = ({
|
|||||||
titleClassName='w-full cursor-pointer'
|
titleClassName='w-full cursor-pointer'
|
||||||
contentClassName='p-0'
|
contentClassName='p-0'
|
||||||
fullWidth={true}
|
fullWidth={true}
|
||||||
|
className={getCollapsibleClasses()}
|
||||||
>
|
>
|
||||||
{cardContent}
|
{cardContent}
|
||||||
</Collapse>
|
</Collapse>
|
||||||
|
|||||||
+23
-12
@@ -25,8 +25,10 @@ export interface TabsProps
|
|||||||
wrapper?: string;
|
wrapper?: string;
|
||||||
tab?: string;
|
tab?: string;
|
||||||
content?: string;
|
content?: string;
|
||||||
|
tabHeaderWrapper?: string;
|
||||||
};
|
};
|
||||||
onTabChange?: (tabId: string) => void;
|
onTabChange?: (tabId: string) => void;
|
||||||
|
sideContent?: ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Tabs = ({
|
const Tabs = ({
|
||||||
@@ -38,6 +40,7 @@ const Tabs = ({
|
|||||||
activeTabId: controlledActiveId,
|
activeTabId: controlledActiveId,
|
||||||
className,
|
className,
|
||||||
onTabChange,
|
onTabChange,
|
||||||
|
sideContent,
|
||||||
...props
|
...props
|
||||||
}: TabsProps) => {
|
}: TabsProps) => {
|
||||||
// State internal hanya dipakai kalau `activeTabId` (controlled) tidak diset
|
// State internal hanya dipakai kalau `activeTabId` (controlled) tidak diset
|
||||||
@@ -59,6 +62,7 @@ const Tabs = ({
|
|||||||
wrapper: wrapperClassName,
|
wrapper: wrapperClassName,
|
||||||
tab: tabClassName,
|
tab: tabClassName,
|
||||||
content: contentClassName,
|
content: contentClassName,
|
||||||
|
tabHeaderWrapper: tabHeaderWrapperClassName,
|
||||||
} = typeof className === 'object'
|
} = typeof className === 'object'
|
||||||
? className
|
? className
|
||||||
: { wrapper: className, tab: undefined };
|
: { wrapper: className, tab: undefined };
|
||||||
@@ -102,6 +106,10 @@ const Tabs = ({
|
|||||||
tabClassName
|
tabClassName
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const getSideContentClasses = () => {
|
||||||
|
return cn('flex flex-row', tabHeaderWrapperClassName);
|
||||||
|
};
|
||||||
|
|
||||||
const activeContent = tabs.find((tab) => tab.id === activeTabId)?.content;
|
const activeContent = tabs.find((tab) => tab.id === activeTabId)?.content;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -112,18 +120,21 @@ const Tabs = ({
|
|||||||
typeof className === 'string' ? className : containerClassName
|
typeof className === 'string' ? className : containerClassName
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div role='tablist' className={getTabsClasses()}>
|
<div className={getSideContentClasses()}>
|
||||||
{tabs.map(({ id, label, disabled }) => (
|
<div role='tablist' className={getTabsClasses()}>
|
||||||
<button
|
{tabs.map(({ id, label, disabled }) => (
|
||||||
key={id}
|
<button
|
||||||
role='tab'
|
key={id}
|
||||||
className={getTabClasses(id === activeTabId, disabled)}
|
role='tab'
|
||||||
onClick={() => !disabled && handleTabChange(id)}
|
className={getTabClasses(id === activeTabId, disabled)}
|
||||||
disabled={disabled}
|
onClick={() => !disabled && handleTabChange(id)}
|
||||||
>
|
disabled={disabled}
|
||||||
{label}
|
>
|
||||||
</button>
|
{label}
|
||||||
))}
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
{sideContent && sideContent}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{activeContent && (
|
{activeContent && (
|
||||||
|
|||||||
@@ -19,11 +19,11 @@ const ButtonFilter = ({ values, onClick, ...props }: ButtonFilterProps) => {
|
|||||||
variant='outline'
|
variant='outline'
|
||||||
color='none'
|
color='none'
|
||||||
className={cn(
|
className={cn(
|
||||||
'padding-[12px] rounded-[8px] max-h-[40px] font-semibold text-[14px] gap-[6px]',
|
'rounded-lg max-h-10 font-semibold text-sm gap-1.5',
|
||||||
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft',
|
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft',
|
||||||
getFilledFormikValuesCount(values) > 0
|
getFilledFormikValuesCount(values) > 0
|
||||||
? 'border-primary-gradient !rounded-[8px]'
|
? 'border-primary-gradient text-primary rounded-lg!'
|
||||||
: '!rounded-[8px]',
|
: 'rounded-lg',
|
||||||
props.className
|
props.className
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -37,7 +37,7 @@ const ButtonFilter = ({ values, onClick, ...props }: ButtonFilterProps) => {
|
|||||||
/>
|
/>
|
||||||
Filter
|
Filter
|
||||||
{getFilledFormikValuesCount(values) > 0 && (
|
{getFilledFormikValuesCount(values) > 0 && (
|
||||||
<span className='w-[20px] h-[20px] text-white bg-[#FF3535] rounded-[8px] border-[1px] 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'>
|
||||||
{getFilledFormikValuesCount(values)}
|
{getFilledFormikValuesCount(values)}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ const DashboardProduction = () => {
|
|||||||
variant='outline'
|
variant='outline'
|
||||||
color='none'
|
color='none'
|
||||||
className={cn(
|
className={cn(
|
||||||
'p-2 rounded-lg font-semibold text-sm gap-1.5',
|
'rounded-lg font-semibold text-sm gap-1.5',
|
||||||
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft'
|
'text-sm text-base-content/50 border border-base-content/10 shadow-button-soft'
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,28 +1,43 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
|
import { useState } from 'react';
|
||||||
import Tabs from '@/components/Tabs';
|
import Tabs from '@/components/Tabs';
|
||||||
import CustomerPaymentTab from '@/components/pages/report/finance/tab/CustomerPaymentTab';
|
import CustomerPaymentTab from '@/components/pages/report/finance/tab/CustomerPaymentTab';
|
||||||
import DebtSupplierTab from '@/components/pages/report/finance/tab/DebtSupplierTab';
|
import DebtSupplierTab from '@/components/pages/report/finance/tab/DebtSupplierTab';
|
||||||
|
import { useFinanceTabStore } from '@/stores/finance-tab/finance-tab.store';
|
||||||
|
|
||||||
const FinanceTabs = () => {
|
const FinanceTabs = () => {
|
||||||
|
const [activeTabId, setActiveTabId] = useState<string>('1');
|
||||||
|
const tabActions = useFinanceTabStore((state) => state.tabActions);
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
id: '1',
|
id: '1',
|
||||||
label: 'Rekapitulasi Hutang Ke Supplier',
|
label: 'Rekapitulasi Hutang Ke Supplier',
|
||||||
|
content: <DebtSupplierTab tabId={'1'} />,
|
||||||
content: <DebtSupplierTab />,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: '2',
|
id: '2',
|
||||||
label: 'Kontrol Pembayaran Customer',
|
label: 'Kontrol Pembayaran Customer',
|
||||||
|
|
||||||
content: <CustomerPaymentTab />,
|
content: <CustomerPaymentTab />,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className='w-full p-4'>
|
<section className='w-full'>
|
||||||
<Tabs tabs={tabs} variant='lifted' />
|
<Tabs
|
||||||
|
tabs={tabs}
|
||||||
|
variant='boxed'
|
||||||
|
activeTabId={activeTabId}
|
||||||
|
onTabChange={setActiveTabId}
|
||||||
|
className={{
|
||||||
|
tabHeaderWrapper:
|
||||||
|
'justify-between items-center p-3 border-b border-base-content/10',
|
||||||
|
tab: 'w-fit',
|
||||||
|
content: 'p-0 m-0',
|
||||||
|
}}
|
||||||
|
sideContent={tabActions[activeTabId] || null}
|
||||||
|
/>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import { generateDebtSupplierExcel } from '@/components/pages/report/finance/exp
|
|||||||
import { generateDebtSupplierPDF } from '@/components/pages/report/finance/export/DebtSupllierExportPDF';
|
import { generateDebtSupplierPDF } from '@/components/pages/report/finance/export/DebtSupllierExportPDF';
|
||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import { ColumnDef } from '@tanstack/react-table';
|
import { ColumnDef } from '@tanstack/react-table';
|
||||||
import { useCallback, useMemo, useState } from 'react';
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||||
import toast from 'react-hot-toast';
|
import toast from 'react-hot-toast';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
import { DebtSupplierApi } from '@/services/api/report/debt-supplier';
|
import { DebtSupplierApi } from '@/services/api/report/debt-supplier';
|
||||||
@@ -37,6 +37,7 @@ import { Color } from '@/types/theme';
|
|||||||
import { Supplier } from '@/types/api/master-data/supplier';
|
import { Supplier } from '@/types/api/master-data/supplier';
|
||||||
import SelectInputCheckbox from '@/components/input/SelectInputCheckbox';
|
import SelectInputCheckbox from '@/components/input/SelectInputCheckbox';
|
||||||
import SelectInputRadio from '@/components/input/SelectInputRadio';
|
import SelectInputRadio from '@/components/input/SelectInputRadio';
|
||||||
|
import { useFinanceTabStore } from '@/stores/finance-tab/finance-tab.store';
|
||||||
|
|
||||||
const dueStatus: Record<string, Color> = {
|
const dueStatus: Record<string, Color> = {
|
||||||
'Sudah Jatuh Tempo': 'error',
|
'Sudah Jatuh Tempo': 'error',
|
||||||
@@ -75,7 +76,11 @@ const getPillBadge = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const DebtSupplierTab = () => {
|
interface DebtSupplierTabProps {
|
||||||
|
tabId: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DebtSupplierTab = ({ tabId }: DebtSupplierTabProps) => {
|
||||||
// ===== STATE MANAGEMENT =====
|
// ===== STATE MANAGEMENT =====
|
||||||
const [isPdfExportLoading, setIsPdfExportLoading] = useState(false);
|
const [isPdfExportLoading, setIsPdfExportLoading] = useState(false);
|
||||||
const [isExcelExportLoading, setIsExcelExportLoading] = useState(false);
|
const [isExcelExportLoading, setIsExcelExportLoading] = useState(false);
|
||||||
@@ -271,6 +276,77 @@ const DebtSupplierTab = () => {
|
|||||||
}
|
}
|
||||||
}, [debtSupplierExport]);
|
}, [debtSupplierExport]);
|
||||||
|
|
||||||
|
// ===== REGISTER TAB ACTIONS TO STORE =====
|
||||||
|
const setTabActions = useFinanceTabStore((state) => state.setTabActions);
|
||||||
|
const clearTabActions = useFinanceTabStore((state) => state.clearTabActions);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTabActions(
|
||||||
|
tabId,
|
||||||
|
<div className='flex flex-row gap-3 '>
|
||||||
|
<ButtonFilter
|
||||||
|
values={formik.values}
|
||||||
|
onClick={handleFilterModalOpen}
|
||||||
|
variant='outline'
|
||||||
|
className='px-3 py-2.5'
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Dropdown
|
||||||
|
trigger={
|
||||||
|
<Button
|
||||||
|
variant='outline'
|
||||||
|
color='none'
|
||||||
|
isLoading={isAnyExportLoading}
|
||||||
|
className={cn(
|
||||||
|
'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} />
|
||||||
|
Export
|
||||||
|
<div className='w-6.5 h-5 flex items-center justify-center border-l border-base-content/10'>
|
||||||
|
<Icon width={14} height={14} icon='heroicons:chevron-down' />
|
||||||
|
</div>
|
||||||
|
</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'>
|
||||||
|
<MenuItem
|
||||||
|
className='text-sm p-3'
|
||||||
|
title='Excel'
|
||||||
|
onClick={handleExportExcel}
|
||||||
|
/>
|
||||||
|
<MenuItem
|
||||||
|
className='text-sm p-3'
|
||||||
|
title='PDF'
|
||||||
|
onClick={handleExportPdf}
|
||||||
|
/>
|
||||||
|
</Menu>
|
||||||
|
</Dropdown>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}, [
|
||||||
|
tabId,
|
||||||
|
formik.values,
|
||||||
|
isAnyExportLoading,
|
||||||
|
handleExportExcel,
|
||||||
|
handleExportPdf,
|
||||||
|
setTabActions,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Cleanup on unmount
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
clearTabActions(tabId);
|
||||||
|
};
|
||||||
|
}, [tabId, clearTabActions]);
|
||||||
|
|
||||||
const getTableColumns = (supplier: DebtSupplier): ColumnDef<DebtRow>[] => [
|
const getTableColumns = (supplier: DebtSupplier): ColumnDef<DebtRow>[] => [
|
||||||
{
|
{
|
||||||
id: 'no',
|
id: 'no',
|
||||||
@@ -478,41 +554,9 @@ const DebtSupplierTab = () => {
|
|||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className='w-full p-0 sm:p-4 flex flex-col gap-4'>
|
<div className='w-full p-0 sm:p-3 flex flex-col gap-3'>
|
||||||
<Card
|
|
||||||
subtitle='Laporan > Rekapitulasi Hutang ke Supplier'
|
|
||||||
className={{ wrapper: 'w-full', body: 'p-1!' }}
|
|
||||||
>
|
|
||||||
<div className='mb-4 flex justify-end gap-2 [&_button]:px-4'>
|
|
||||||
<ButtonFilter
|
|
||||||
values={formik.values}
|
|
||||||
onClick={handleFilterModalOpen}
|
|
||||||
variant='outline'
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Dropdown
|
|
||||||
trigger={
|
|
||||||
<Button variant='outline' isLoading={isAnyExportLoading}>
|
|
||||||
<Icon
|
|
||||||
icon='heroicons:cloud-arrow-down'
|
|
||||||
width={18}
|
|
||||||
height={18}
|
|
||||||
/>
|
|
||||||
Export
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
align='end'
|
|
||||||
>
|
|
||||||
<Menu>
|
|
||||||
<MenuItem title='Excel' onClick={handleExportExcel} />
|
|
||||||
<MenuItem title='PDF' onClick={handleExportPdf} />
|
|
||||||
</Menu>
|
|
||||||
</Dropdown>
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{!isSubmitted ? (
|
{!isSubmitted ? (
|
||||||
<div className='mt-6 text-center text-gray-500'>
|
<div className='mt-6 text-center text-base-content/50'>
|
||||||
Silakan klik tombol Filter untuk mengatur filter dan menampilkan
|
Silakan klik tombol Filter untuk mengatur filter dan menampilkan
|
||||||
data.
|
data.
|
||||||
</div>
|
</div>
|
||||||
@@ -521,7 +565,7 @@ const DebtSupplierTab = () => {
|
|||||||
<span className='loading loading-spinner loading-xl' />
|
<span className='loading loading-spinner loading-xl' />
|
||||||
</div>
|
</div>
|
||||||
) : data.length === 0 ? (
|
) : data.length === 0 ? (
|
||||||
<div className='mt-6 text-center text-gray-500'>
|
<div className='mt-6 text-center text-base-content/50'>
|
||||||
Tidak ada data yang dapat ditampilkan...
|
Tidak ada data yang dapat ditampilkan...
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
@@ -531,10 +575,11 @@ const DebtSupplierTab = () => {
|
|||||||
key={supplierReport.supplier.id}
|
key={supplierReport.supplier.id}
|
||||||
title={supplierReport.supplier.name}
|
title={supplierReport.supplier.name}
|
||||||
className={{
|
className={{
|
||||||
wrapper: 'w-full !rounded-lg',
|
wrapper: 'w-full rounded-lg border-none',
|
||||||
body: 'p-0 rounded-lg',
|
body: 'p-0',
|
||||||
title:
|
title:
|
||||||
'ps-2 pt-1 pb-1 font-normal text-md bg-primary text-white',
|
'px-2 py-1.5 font-normal text-sm bg-primary text-white',
|
||||||
|
collapsible: 'rounded-lg',
|
||||||
}}
|
}}
|
||||||
variant='bordered'
|
variant='bordered'
|
||||||
collapsible={true}
|
collapsible={true}
|
||||||
@@ -551,8 +596,9 @@ const DebtSupplierTab = () => {
|
|||||||
pageSize={supplierReport.rows.length + 1}
|
pageSize={supplierReport.rows.length + 1}
|
||||||
renderFooter={supplierReport.rows.length > 0}
|
renderFooter={supplierReport.rows.length > 0}
|
||||||
className={{
|
className={{
|
||||||
containerClassName: 'w-full',
|
containerClassName: 'w-full mb-0',
|
||||||
tableWrapperClassName: 'overflow-x-auto',
|
tableWrapperClassName:
|
||||||
|
'overflow-x-auto rounded-tr-none rounded-tl-none',
|
||||||
headerColumnClassName: cn(
|
headerColumnClassName: cn(
|
||||||
TABLE_DEFAULT_STYLING.headerColumnClassName,
|
TABLE_DEFAULT_STYLING.headerColumnClassName,
|
||||||
'whitespace-nowrap'
|
'whitespace-nowrap'
|
||||||
@@ -617,33 +663,34 @@ const DebtSupplierTab = () => {
|
|||||||
ref={filterModal.ref}
|
ref={filterModal.ref}
|
||||||
className={{
|
className={{
|
||||||
modal: 'p-0',
|
modal: 'p-0',
|
||||||
modalBox: 'p-0 rounded-2xl xl:max-w-4/12 max-w-sm',
|
modalBox: 'p-0 rounded-[0.875rem] xl:max-w-4/12 max-w-sm',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<form
|
<form onSubmit={formik.handleSubmit} onReset={formik.handleReset}>
|
||||||
className='space-y-6'
|
|
||||||
onSubmit={formik.handleSubmit}
|
|
||||||
onReset={formik.handleReset}
|
|
||||||
>
|
|
||||||
{/* Modal Header */}
|
{/* Modal Header */}
|
||||||
<div className='flex items-center justify-between gap-2 py-3 border-b border-gray-300 px-4'>
|
<div className='flex items-center justify-between gap-2 border-b border-base-content/10 p-4'>
|
||||||
<div className='flex items-center gap-2 text-primary'>
|
<div className='flex items-center gap-2 text-primary'>
|
||||||
<Icon icon='heroicons:funnel' width={20} height={20} />
|
<Icon icon='heroicons:funnel' width={20} height={20} />
|
||||||
<h3 className='font-semibold'>Filter Data</h3>
|
<h3 className='font-medium text-sm'>Filter Data</h3>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
variant='link'
|
variant='link'
|
||||||
|
type='button'
|
||||||
onClick={filterModal.closeModal}
|
onClick={filterModal.closeModal}
|
||||||
className='text-gray-500 hover:text-gray-700 transition-colors cursor-pointer'
|
className='text-base-content/50 hover:text-base-content transition-colors cursor-pointer'
|
||||||
>
|
>
|
||||||
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
<Icon icon='heroicons:x-mark' width={20} height={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div className='space-y-4 px-4'>
|
|
||||||
<div className='grid grid-cols-1 sm:grid-cols-2 sm:gap-4'>
|
{/* Modal Body */}
|
||||||
<div>
|
<div className='p-4 flex flex-col gap-1.5'>
|
||||||
|
<div>
|
||||||
|
<label className='block text-xs font-semibold text-base-content py-2'>
|
||||||
|
Tanggal
|
||||||
|
</label>
|
||||||
|
<div className='flex flex-row gap-1.5 items-center justify-between'>
|
||||||
<DateInput
|
<DateInput
|
||||||
label='Tanggal'
|
|
||||||
name='startDate'
|
name='startDate'
|
||||||
value={formik.values.startDate || ''}
|
value={formik.values.startDate || ''}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -655,11 +702,8 @@ const DebtSupplierTab = () => {
|
|||||||
}
|
}
|
||||||
errorMessage={formik.errors.startDate}
|
errorMessage={formik.errors.startDate}
|
||||||
/>
|
/>
|
||||||
</div>
|
<hr className='w-full max-w-3 h-px border-base-content/10'></hr>
|
||||||
|
|
||||||
<div className='mt-auto'>
|
|
||||||
<DateInput
|
<DateInput
|
||||||
label=' '
|
|
||||||
name='endDate'
|
name='endDate'
|
||||||
value={formik.values.endDate || ''}
|
value={formik.values.endDate || ''}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
@@ -730,15 +774,19 @@ const DebtSupplierTab = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Action Buttons */}
|
{/* Action Buttons */}
|
||||||
<div className='flex justify-between gap-4 py-4 mt-8 border-t border-gray-300 bg-gray-100'>
|
<div className='flex justify-between items-center gap-4 p-4 border-t border-gray-300 bg-gray-100'>
|
||||||
<Button
|
<Button
|
||||||
variant='soft'
|
variant='soft'
|
||||||
className='ms-4 min-w-36 rounded-lg'
|
color='none'
|
||||||
|
className='rounded-lg text-base-content/65 bg-transparent border-none hover:bg-base-content/10 hover:text-base-content/65 transition-colors px-3 py-2'
|
||||||
type='reset'
|
type='reset'
|
||||||
>
|
>
|
||||||
Reset Filter
|
Reset Filter
|
||||||
</Button>
|
</Button>
|
||||||
<Button className='me-4 min-w-36 rounded-lg' type='submit'>
|
<Button
|
||||||
|
className='min-w-40 text-sm rounded-lg py-3 text-white'
|
||||||
|
type='submit'
|
||||||
|
>
|
||||||
Apply Filter
|
Apply Filter
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import { ReactNode } from 'react';
|
||||||
|
import { create } from 'zustand';
|
||||||
|
import { devtools } from 'zustand/middleware';
|
||||||
|
|
||||||
|
export type FinanceTabActionsSlice = {
|
||||||
|
// State - actions per tab ID
|
||||||
|
tabActions: Record<string, ReactNode>;
|
||||||
|
|
||||||
|
// Actions
|
||||||
|
setTabActions: (tabId: string, actions: ReactNode) => void;
|
||||||
|
clearTabActions: (tabId: string) => void;
|
||||||
|
clearAllTabActions: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFinanceTabStore = create<FinanceTabActionsSlice>()(
|
||||||
|
devtools(
|
||||||
|
(set) => ({
|
||||||
|
tabActions: {},
|
||||||
|
|
||||||
|
setTabActions: (tabId, actions) =>
|
||||||
|
set(
|
||||||
|
(state) => ({
|
||||||
|
tabActions: {
|
||||||
|
...state.tabActions,
|
||||||
|
[tabId]: actions,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
false,
|
||||||
|
'setTabActions'
|
||||||
|
),
|
||||||
|
|
||||||
|
clearTabActions: (tabId) =>
|
||||||
|
set(
|
||||||
|
(state) => {
|
||||||
|
const { [tabId]: _, ...rest } = state.tabActions;
|
||||||
|
return { tabActions: rest };
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
'clearTabActions'
|
||||||
|
),
|
||||||
|
|
||||||
|
clearAllTabActions: () =>
|
||||||
|
set({ tabActions: {} }, false, 'clearAllTabActions'),
|
||||||
|
}),
|
||||||
|
{
|
||||||
|
name: 'FinanceTabStore',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
Reference in New Issue
Block a user