Skip to content

Commit

Permalink
Merge pull request #3754 from CAFECA-IO/feature/ledger_link_view_vouc…
Browse files Browse the repository at this point in the history
…hers

Return to the Ledger from the Page Viewing Vouchers
  • Loading branch information
Luphia authored Dec 25, 2024
2 parents f495a24 + efcf0e4 commit 5ac89c0
Show file tree
Hide file tree
Showing 5 changed files with 221 additions and 171 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "iSunFA",
"version": "0.8.5+231",
"version": "0.8.5+232",
"private": false,
"scripts": {
"dev": "next dev",
Expand Down
249 changes: 138 additions & 111 deletions src/components/ledger/ledger_item.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import React, { useState } from 'react';
import React from 'react';
import CalendarIcon from '@/components/calendar_icon/calendar_icon';
import { numberWithCommas } from '@/lib/utils/common';
import { FaUpload, FaDownload } from 'react-icons/fa';
import { FiRepeat } from 'react-icons/fi';
import { checkboxStyle } from '@/constants/display';
import { EventType, VoucherType } from '@/constants/account';
import Link from 'next/link';

Expand All @@ -24,128 +23,156 @@ export interface ILedgerBeta {

interface ILedgerItemProps {
ledger: ILedgerBeta; // Info: (20241118 - Anna) 傳入單個 ledger 作為 prop
selectedDateRange: { startTimeStamp: number; endTimeStamp: number };
selectedStartAccountNo: string;
selectedEndAccountNo: string;
selectedReportType: string;
}

const LedgerItem = React.memo(({ ledger }: ILedgerItemProps) => {
const { voucherDate, voucherNumber, voucherType, particulars, voucherId } = ledger;
const LedgerItem = React.memo(
({
ledger,
selectedDateRange,
selectedStartAccountNo,
selectedEndAccountNo,
selectedReportType,
}: ILedgerItemProps) => {
const { voucherDate, voucherNumber, voucherType, particulars, voucherId } = ledger;

const [isChecked, setIsChecked] = useState(false);
const displayedDate = (
<div className="flex h-full items-center justify-center py-4">
<CalendarIcon timestamp={voucherDate} unRead={false} />
</div>
);

const displayedCheckbox = (
<div className="relative top-20px px-8px print:hidden">
<input
type="checkbox"
className={checkboxStyle}
checked={isChecked}
onChange={() => setIsChecked(!isChecked)}
/>
</div>
);
const displayedVoucherNo =
voucherType === VoucherType.RECEIVE ? (
<div className="relative mx-auto flex w-fit items-center gap-4px rounded-full bg-badge-surface-soft-error px-8px py-4px">
<FaDownload size={14} className="text-surface-state-error-dark" />
<Link
// Info: (20241225 - Anna) from=ledger 為了返回時能回到分類帳頁面
href={{
pathname: `/users/accounting/${voucherId}`, // Info: (20241225 - Anna) 傳票詳細頁面路徑
query: {
from: 'ledger',
startDate: selectedDateRange.startTimeStamp,
endDate: selectedDateRange.endTimeStamp,
startAccountNo: selectedStartAccountNo,
endAccountNo: selectedEndAccountNo,
labelType: selectedReportType,
},
}}
className="table-row font-medium hover:cursor-pointer hover:bg-surface-brand-primary-10"
>
<p className="text-sm text-text-state-error-solid">{voucherNumber}</p>
</Link>
</div>
) : voucherType === VoucherType.EXPENSE ? (
<div className="relative mx-auto flex w-fit items-center gap-4px rounded-full bg-badge-surface-soft-success px-8px py-4px">
<FaUpload size={14} className="text-surface-state-success-dark" />
<Link
href={{
pathname: `/users/accounting/${voucherId}`,
query: {
from: 'ledger',
startDate: selectedDateRange.startTimeStamp,
endDate: selectedDateRange.endTimeStamp,
startAccountNo: selectedStartAccountNo,
endAccountNo: selectedEndAccountNo,
labelType: selectedReportType,
},
}}
className="table-row font-medium hover:cursor-pointer hover:bg-surface-brand-primary-10"
>
<p className="text-sm text-text-state-success-solid">{voucherNumber}</p>
</Link>
</div>
) : (
<div className="relative mx-auto flex w-fit items-center gap-4px rounded-full bg-badge-surface-soft-secondary px-8px py-4px">
<FiRepeat size={14} className="text-surface-brand-secondary" />
<Link
href={{
pathname: `/users/accounting/${voucherId}`,
query: {
from: 'ledger',
startDate: selectedDateRange.startTimeStamp,
endDate: selectedDateRange.endTimeStamp,
startAccountNo: selectedStartAccountNo,
endAccountNo: selectedEndAccountNo,
labelType: selectedReportType,
},
}}
className="table-row font-medium hover:cursor-pointer hover:bg-surface-brand-primary-10"
>
<p className="text-sm text-badge-text-secondary-solid">{voucherNumber}</p>
</Link>
</div>
);

const displayedDate = (
<div className="flex h-full items-center justify-center py-4">
<CalendarIcon timestamp={voucherDate} unRead={false} />
</div>
);
const displayedNote = (
<p className="flex h-full items-center justify-start px-1 font-normal text-text-neutral-tertiary">
{particulars}
</p>
);

const displayedVoucherNo =
voucherType === VoucherType.RECEIVE ? (
<div className="relative mx-auto flex w-fit items-center gap-4px rounded-full bg-badge-surface-soft-error px-8px py-4px">
<FaDownload size={14} className="text-surface-state-error-dark" />
<Link
href={`/users/accounting/${voucherId}`}
className="table-row font-medium hover:cursor-pointer hover:bg-surface-brand-primary-10"
>
<p className="text-sm text-text-state-error-solid">{voucherNumber}</p>
</Link>
const displayedAccountingCode = (
<div className="flex h-full items-center justify-center font-normal text-neutral-600">
<p className="m-0 flex items-center">{ledger.no}</p>
</div>
) : voucherType === VoucherType.EXPENSE ? (
<div className="relative mx-auto flex w-fit items-center gap-4px rounded-full bg-badge-surface-soft-success px-8px py-4px">
<FaUpload size={14} className="text-surface-state-success-dark" />
<Link
href={`/users/accounting/${voucherId}`}
className="table-row font-medium hover:cursor-pointer hover:bg-surface-brand-primary-10"
>
<p className="text-sm text-text-state-success-solid">{voucherNumber}</p>
</Link>
</div>
) : (
<div className="relative mx-auto flex w-fit items-center gap-4px rounded-full bg-badge-surface-soft-secondary px-8px py-4px">
<FiRepeat size={14} className="text-surface-brand-secondary" />
<Link
href={`/users/accounting/${voucherId}`}
className="table-row font-medium hover:cursor-pointer hover:bg-surface-brand-primary-10"
>
<p className="text-sm text-badge-text-secondary-solid">{voucherNumber}</p>
</Link>
);
const displayedAccountingName = (
<div className="flex h-full items-center justify-center font-normal text-neutral-600">
<p className="m-0 flex items-center">{ledger.accountingTitle}</p>
</div>
);

const displayedNote = (
<p className="flex h-full items-center justify-start px-1 font-normal text-text-neutral-tertiary">
{particulars}
</p>
);

const displayedAccountingCode = (
<div className="flex h-full items-center justify-center font-normal text-neutral-600">
<p className="m-0 flex items-center">{ledger.no}</p>
</div>
);
const displayedAccountingName = (
<div className="flex h-full items-center justify-center font-normal text-neutral-600">
<p className="m-0 flex items-center">{ledger.accountingTitle}</p>
</div>
);

// Info: (20241118 - Anna) 使用傳入的 creditAmount、debitAmount、balance,而非 ledgerItemsData 的遍歷
const displayedCredit = (
<div className="flex h-full items-center justify-end font-normal text-text-neutral-tertiary">
<p className="m-0 flex items-center text-text-neutral-primary">
{numberWithCommas(ledger.creditAmount)}
</p>
</div>
);
// Info: (20241118 - Anna) 使用傳入的 creditAmount、debitAmount、balance,而非 ledgerItemsData 的遍歷
const displayedCredit = (
<div className="flex h-full items-center justify-end font-normal text-text-neutral-tertiary">
<p className="m-0 flex items-center text-text-neutral-primary">
{numberWithCommas(ledger.creditAmount)}
</p>
</div>
);

const displayedDebit = (
<div className="flex h-full items-center justify-end font-normal text-text-neutral-tertiary">
<p className="text-text-neutral-primary">{numberWithCommas(ledger.debitAmount)}</p>
</div>
);
const displayedDebit = (
<div className="flex h-full items-center justify-end font-normal text-text-neutral-tertiary">
<p className="text-text-neutral-primary">{numberWithCommas(ledger.debitAmount)}</p>
</div>
);

const displayedBalance = (
<div className="flex h-full items-center justify-end font-normal text-text-neutral-tertiary">
<p className="align-middle text-text-neutral-primary">{numberWithCommas(ledger.balance)}</p>
</div>
);
const displayedBalance = (
<div className="flex h-full items-center justify-end font-normal text-text-neutral-tertiary">
<p className="align-middle text-text-neutral-primary">{numberWithCommas(ledger.balance)}</p>
</div>
);

return (
<div
className="table-row font-medium hover:cursor-pointer hover:bg-surface-brand-primary-10"
// Info: (20241206 - Anna) 避免行內換頁
style={{ pageBreakInside: 'avoid' }}
>
{/* Info: (20240920 - Julian) Select */}
<div className={`table-cell text-center`}>{displayedCheckbox}</div>
{/* Info: (20240920 - Julian) Issued Date */}
<div className="table-cell text-center">{displayedDate}</div>
{/* Info: (20241004 - Anna) Accounting */}
<div className="table-cell text-center align-middle">{displayedAccountingCode}</div>
<div className="table-cell text-center align-middle print:hidden">
{displayedAccountingName}
return (
<div
className="table-row font-medium hover:cursor-pointer hover:bg-surface-brand-primary-10"
// Info: (20241206 - Anna) 避免行內換頁
style={{ pageBreakInside: 'avoid' }}
>
{/* Info: (20240920 - Julian) Issued Date */}
<div className="table-cell text-center">{displayedDate}</div>
{/* Info: (20241004 - Anna) Accounting */}
<div className="table-cell text-center align-middle">{displayedAccountingCode}</div>
<div className="table-cell text-center align-middle print:hidden">
{displayedAccountingName}
</div>
{/* Info: (20240920 - Julian) Voucher No */}
<div className="table-cell py-8px text-right align-middle">{displayedVoucherNo}</div>
{/* Info: (20240920 - Julian) Note */}
<div className="table-cell py-8px text-right align-middle">{displayedNote}</div>
{/* Info: (202401101 - Anna) Debit */}
<div className="table-cell py-8px pr-2 text-right align-middle">{displayedDebit}</div>
{/* Info: (202401101 - Anna) Credit */}
<div className="table-cell py-8px pr-2 text-right align-middle">{displayedCredit}</div>
{/* Info: (20241004 - Anna) Balance */}
<div className="table-cell py-8px pr-2 text-right align-middle">{displayedBalance}</div>
</div>
{/* Info: (20240920 - Julian) Voucher No */}
<div className="table-cell py-8px text-right align-middle">{displayedVoucherNo}</div>
{/* Info: (20240920 - Julian) Note */}
<div className="table-cell py-8px text-right align-middle">{displayedNote}</div>
{/* Info: (202401101 - Anna) Debit */}
<div className="table-cell py-8px pr-2 text-right align-middle">{displayedDebit}</div>
{/* Info: (202401101 - Anna) Credit */}
<div className="table-cell py-8px pr-2 text-right align-middle">{displayedCredit}</div>
{/* Info: (20241004 - Anna) Balance */}
<div className="table-cell py-8px pr-2 text-right align-middle">{displayedBalance}</div>
</div>
);
});
);
}
);

export default LedgerItem;
54 changes: 12 additions & 42 deletions src/components/ledger/ledger_list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import React, { useState, useRef } from 'react';
import { useTranslation } from 'next-i18next';
import LedgerItem from '@/components/ledger/ledger_item';
import Pagination from '@/components/pagination/pagination';
import SortingButton from '@/components/voucher/sorting_button';
import { checkboxStyle } from '@/constants/display';
import { SortOrder } from '@/constants/sort';
import PrintButton from '@/components/button/print_button';
import DownloadButton from '@/components/button/download_button';
import { ILedgerPayload } from '@/interfaces/ledger';
Expand All @@ -18,13 +15,17 @@ interface LedgerListProps {
loading: boolean; // Info: (20241118 - Anna) 接收父组件傳遞的loading狀態
selectedDateRange: { startTimeStamp: number; endTimeStamp: number }; // Info: (20241218 - Anna) 從父組件傳來的日期範圍
labelType: string; // Info: (20241218 - Anna) 從父組件傳來的 labelType
selectedStartAccountNo: string;
selectedEndAccountNo: string;
}

const LedgerList: React.FunctionComponent<LedgerListProps> = ({
ledgerData,
loading,
selectedDateRange,
labelType,
selectedStartAccountNo,
selectedEndAccountNo,
}) => {
const { selectedCompany } = useUserCtx();
const companyId = selectedCompany?.id;
Expand All @@ -38,36 +39,10 @@ const LedgerList: React.FunctionComponent<LedgerListProps> = ({
// Info: (20241118 - Anna) 確保 ledgerItemsData 是一個有效的陣列
const ledgerItemsData = Array.isArray(ledgerData?.items?.data) ? ledgerData.items.data : [];

// Info: (20240920 - Julian) 排序狀態
const [dateSort, setDateSort] = useState<null | SortOrder>(null);
const [creditSort, setCreditSort] = useState<null | SortOrder>(null);
const [debitSort, setDebitSort] = useState<null | SortOrder>(null);

// Info: (20240920 - Julian) css string
const tableCellStyles = 'text-center align-middle';
const sideBorderStyles = 'border-r border-b border-stroke-neutral-quaternary';

// Info: (20240920 - Julian) 日期排序按鈕
const displayedDate = SortingButton({
string: t('journal:VOUCHER.VOUCHER_DATE'),
sortOrder: dateSort,
setSortOrder: setDateSort,
});

// Info: (20240920 - Julian) credit 排序按鈕
const displayedCredit = SortingButton({
string: t('journal:JOURNAL.CREDIT'),
sortOrder: creditSort,
setSortOrder: setCreditSort,
});

// Info: (20240920 - Julian) debit 排序按鈕
const displayedDebit = SortingButton({
string: t('journal:JOURNAL.DEBIT'),
sortOrder: debitSort,
setSortOrder: setDebitSort,
});

const handlePrint = useReactToPrint({
contentRef: printRef, // Info: (20241203 - Anna) 指定需要打印的內容 Ref
documentTitle: `分類帳`,
Expand Down Expand Up @@ -177,7 +152,11 @@ const LedgerList: React.FunctionComponent<LedgerListProps> = ({
balance,
// Info: (20241224 - Anna) 將字串轉換為整數
voucherId: typeof voucherId === 'string' ? parseInt(voucherId, 10) : voucherId,
}} // Info: (20241118 - Anna) 確保每個欄位有預設值
}}
selectedDateRange={selectedDateRange}
selectedStartAccountNo={selectedStartAccountNo}
selectedEndAccountNo={selectedEndAccountNo}
selectedReportType={labelType}
/>
);
});
Expand All @@ -191,19 +170,10 @@ const LedgerList: React.FunctionComponent<LedgerListProps> = ({
{/* Info: (20240920 - Julian) ---------------- Table Header ---------------- */}
<div className="table-header-group border-b bg-surface-neutral-surface-lv1 text-sm text-text-neutral-tertiary">
<div className="table-row h-60px">
<div
className={`table-cell border-stroke-neutral-quaternary ${tableCellStyles} border-b`}
>
<div className="flex items-center justify-center print:hidden">
<div className="relative">
<input type="checkbox" className={checkboxStyle} />
</div>
</div>
</div>
<div
className={`table-cell ${tableCellStyles} ${sideBorderStyles} whitespace-nowrap print:bg-neutral-50`}
>
{displayedDate}
{t('journal:VOUCHER.VOUCHER_DATE')}
</div>
<div
className={`table-cell ${tableCellStyles} ${sideBorderStyles} whitespace-nowrap print:bg-neutral-50`}
Expand All @@ -228,13 +198,13 @@ const LedgerList: React.FunctionComponent<LedgerListProps> = ({
<div
className={`table-cell ${tableCellStyles} ${sideBorderStyles} print:bg-neutral-50`}
>
{displayedDebit}
{t('journal:JOURNAL.DEBIT')}
</div>

<div
className={`table-cell ${tableCellStyles} ${sideBorderStyles} print:bg-neutral-50`}
>
{displayedCredit}
{t('journal:JOURNAL.CREDIT')}
</div>

<div
Expand Down
Loading

0 comments on commit 5ac89c0

Please sign in to comment.