From baee0c17723a64ec49dd4468a9dd7169b1397435 Mon Sep 17 00:00:00 2001 From: TzuHanLiang Date: Thu, 26 Sep 2024 10:10:45 +0800 Subject: [PATCH 1/5] feat: update UI --- package.json | 2 +- src/components/certificate/certificate.tsx | 3 + .../certificate/certificate_grid.tsx | 33 +++++---- .../selection_tool_bar/selection_tool_bar.tsx | 71 ++++++++++++------- ...d_certificate.tsx => certificate_list.tsx} | 23 ++++-- 5 files changed, 87 insertions(+), 45 deletions(-) rename src/pages/users/accounting/{upload_certificate.tsx => certificate_list.tsx} (93%) diff --git a/package.json b/package.json index 26ad95f6..f86f2fad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iSunFA", - "version": "0.8.2+10", + "version": "0.8.2+11", "private": false, "scripts": { "dev": "next dev", diff --git a/src/components/certificate/certificate.tsx b/src/components/certificate/certificate.tsx index 95ac26fb..350ffe1d 100644 --- a/src/components/certificate/certificate.tsx +++ b/src/components/certificate/certificate.tsx @@ -7,6 +7,7 @@ import CertificateGrid from './certificate_grid'; interface CertificateProps { data: ICertificateUI[]; // Info: (20240923 - tzuhan) 項目列表 viewType: VIEW_TYPES; // Info: (20240923 - tzuhan) 顯示模式 + activeTab: number; // Info: (20240926 - tzuhan) 活躍的 Tab activeSelection: boolean; // Info: (20240923 - tzuhan) 是否處於選擇狀態 handleSelect: (ids: number[], isSelected: boolean) => void; isSelectedAll: boolean; @@ -20,6 +21,7 @@ interface CertificateProps { const Certificate: React.FC = ({ data, viewType, + activeTab, activeSelection, handleSelect, isSelectedAll, @@ -46,6 +48,7 @@ const Certificate: React.FC = ({ {viewType === VIEW_TYPES.GRID && ( void; onRemove: (id: number) => void; onDownload: (id: number) => void; @@ -14,24 +16,29 @@ interface CertificateGridProps { const CertificateGrid: React.FC = ({ data, activeSelection, + activeTab, handleSelect, onRemove, onDownload, onEdit, }) => { return ( -
- {data.map((certificate) => ( - - ))} -
+ <> +
+ {data.map((certificate) => ( + + ))} +
+ {/* Info: (20240926- tzuhan) Floating Upload Popup */} + {activeTab === 0 && } + ); }; diff --git a/src/components/selection_tool_bar/selection_tool_bar.tsx b/src/components/selection_tool_bar/selection_tool_bar.tsx index 81c3006c..71954cd7 100644 --- a/src/components/selection_tool_bar/selection_tool_bar.tsx +++ b/src/components/selection_tool_bar/selection_tool_bar.tsx @@ -1,11 +1,15 @@ import { ICertificateUI } from '@/interfaces/certificate'; import React from 'react'; +import { FaPlus } from 'react-icons/fa6'; import { FiDownload, FiTrash2 } from 'react-icons/fi'; interface SelectionToolbarProps { active: boolean; // Info: (20240920 - tzuhan) 是否打開 + isSelectable: boolean; // Info: (20240920 - tzuhan) 是否可選擇 onActiveChange: (active: boolean) => void; // Info: (20240920 - tzuhan) 當打開狀態變更時的回調函數 items: ICertificateUI[]; // Info: (20240920 - tzuhan) 項目列表 + itemType: string; + subtitle: string; selectedCount: number; // Info: (20240920 - tzuhan) 選中的項目數量 totalCount: number; // Info: (20240920 - tzuhan) 總項目數量 handleSelect: (ids: number[], isSelected: boolean) => void; @@ -18,8 +22,11 @@ interface SelectionToolbarProps { const SelectionToolbar: React.FC = ({ active, + isSelectable, onActiveChange, items, + itemType, + subtitle, selectedCount, totalCount, handleSelect, @@ -65,38 +72,41 @@ const SelectionToolbar: React.FC = ({ {/* Info: (20240920 - tzuhan) 中間操作按鈕 */}
- {operations.includes('DELETE') && ( - - )} {operations.includes('ADD_VOUCHER') && ( )} {operations.includes('ADD_ASSET') && ( + )} + {operations.includes('DELETE') && ( + )} @@ -105,9 +115,6 @@ const SelectionToolbar: React.FC = ({ - @@ -115,14 +122,28 @@ const SelectionToolbar: React.FC = ({
) : ( -
- +
+ {/* Info: (20240920 - tzuhan) 左側選擇計數顯示 */} +
{subtitle}
+
+ + {isSelectable && ( + + )} +
)}
diff --git a/src/pages/users/accounting/upload_certificate.tsx b/src/pages/users/accounting/certificate_list.tsx similarity index 93% rename from src/pages/users/accounting/upload_certificate.tsx rename to src/pages/users/accounting/certificate_list.tsx index eb7292a9..38bd2542 100644 --- a/src/pages/users/accounting/upload_certificate.tsx +++ b/src/pages/users/accounting/certificate_list.tsx @@ -7,7 +7,6 @@ import Header from '@/components/upload_certificate/header'; import UploadArea from '@/components/upload_certificate/upload_area'; import Tabs from '@/components/tabs/tabs'; import FilterSection from '@/components/filter_section/filter_section'; -import FloatingUploadPopup from '@/components/upload_certificate/floating_upload_popup'; import { APIName } from '@/constants/api_connection'; import SelectionToolbar from '@/components/selection_tool_bar/selection_tool_bar'; import { ICertificate, ICertificateUI, OPERATIONS, VIEW_TYPES } from '@/interfaces/certificate'; @@ -20,6 +19,10 @@ const UploadCertificatePage: React.FC = () => { 0: {}, 1: {}, }); + const [sumPrice, setSumPrice] = useState<{ [tab: number]: number }>({ + 0: 0, + 1: 0, + }); const [activeSelection, setActiveSelection] = React.useState(false); const [viewType, setViewType] = useState(VIEW_TYPES.LIST); const [editingId, setEditingId] = useState(null); @@ -29,6 +32,10 @@ const UploadCertificatePage: React.FC = () => { }); const handleApiResponse = useCallback((resData: ICertificate[]) => { + const sumInvoiceTotalPrice = { + 0: 0, + 1: 0, + }; const certificates = resData.reduce( (acc, item) => { if (!item.voucherNo) { @@ -40,6 +47,7 @@ const UploadCertificatePage: React.FC = () => { actions: [OPERATIONS.DOWNLOAD, OPERATIONS.REMOVE], }, }; + sumInvoiceTotalPrice[0] += item.totalPrice; } else { acc[1] = { ...acc[1], @@ -49,12 +57,14 @@ const UploadCertificatePage: React.FC = () => { actions: [OPERATIONS.DOWNLOAD], }, }; + sumInvoiceTotalPrice[1] += item.totalPrice; } return acc; }, {} as { [tab: number]: { [id: number]: ICertificateUI } } ); setData(certificates); // Info: (20240919 - tzuhan) 假設 API 回應中有 data 屬性 + setSumPrice(sumInvoiceTotalPrice); }, []); const handleSelect = useCallback( @@ -197,7 +207,7 @@ const UploadCertificatePage: React.FC = () => { {/* Info: (20240919 - tzuhan) Tabs */} setActiveTab(index)} counts={[Object.keys(data[0]).length, Object.keys(data[1]).length]} @@ -221,12 +231,15 @@ const UploadCertificatePage: React.FC = () => { { { /> - - {/* Info: (20240919 - tzuhan) Floating Upload Popup */} - ); From aa6b6bae74a5c8b9a72600e98c5db2d58eff7d62 Mon Sep 17 00:00:00 2001 From: TzuHanLiang Date: Thu, 26 Sep 2024 16:22:55 +0800 Subject: [PATCH 2/5] feat: add voucher partial component --- package.json | 2 +- public/elements/siri.svg | 103 ++++++++++++++ src/components/ai_analyzer/ai_analyzer.tsx | 24 ++++ .../certificate/certificate_edit_modal.tsx | 28 ++-- .../certificate/certificate_grid.tsx | 2 +- .../certificate/certificate_selection.tsx | 66 +++++++++ .../certificate_selector_modal.tsx | 112 +++++++++++++++ .../certificate_uoloader_modal.tsx | 128 ++++++++++++++++++ .../certificate/circular_progress_bar.tsx | 51 +++++++ .../certificate/selection_pannel.tsx | 43 ++++++ .../filter_section/filter_section.tsx | 8 +- .../floating_upload_popup.tsx | 9 +- src/components/modal/modal.tsx | 34 +++++ .../selection_tool_bar/selection_tool_bar.tsx | 42 +++--- .../upload_area.tsx | 0 .../upload_certificate/upload_file_item.tsx | 26 +++- src/pages/add_voucher.tsx | 115 ++++++++++++++++ .../users/accounting/certificate_list.tsx | 2 +- tailwind.config.ts | 6 + 19 files changed, 743 insertions(+), 58 deletions(-) create mode 100644 public/elements/siri.svg create mode 100644 src/components/ai_analyzer/ai_analyzer.tsx create mode 100644 src/components/certificate/certificate_selection.tsx create mode 100644 src/components/certificate/certificate_selector_modal.tsx create mode 100644 src/components/certificate/certificate_uoloader_modal.tsx create mode 100644 src/components/certificate/circular_progress_bar.tsx create mode 100644 src/components/certificate/selection_pannel.tsx rename src/components/{upload_certificate => floating_upload_popup}/floating_upload_popup.tsx (91%) create mode 100644 src/components/modal/modal.tsx rename src/components/{upload_certificate => upload_area}/upload_area.tsx (100%) create mode 100644 src/pages/add_voucher.tsx diff --git a/package.json b/package.json index f86f2fad..1ceab190 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iSunFA", - "version": "0.8.2+11", + "version": "0.8.2+12", "private": false, "scripts": { "dev": "next dev", diff --git a/public/elements/siri.svg b/public/elements/siri.svg new file mode 100644 index 00000000..d1f2816b --- /dev/null +++ b/public/elements/siri.svg @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/components/ai_analyzer/ai_analyzer.tsx b/src/components/ai_analyzer/ai_analyzer.tsx new file mode 100644 index 00000000..84f4e77d --- /dev/null +++ b/src/components/ai_analyzer/ai_analyzer.tsx @@ -0,0 +1,24 @@ +import Image from 'next/image'; + +interface AIAnalyzerProps {} + +const AIAnalyzer: React.FC = () => { + return ( +
+
+ AI +
+

+ Please select the certificates for AI to generate the voucher for you +

+
+ ); +}; + +export default AIAnalyzer; diff --git a/src/components/certificate/certificate_edit_modal.tsx b/src/components/certificate/certificate_edit_modal.tsx index 8910b9d1..b094a081 100644 --- a/src/components/certificate/certificate_edit_modal.tsx +++ b/src/components/certificate/certificate_edit_modal.tsx @@ -1,13 +1,13 @@ -import { CERTIFICATE_TYPES, ICertificateUI, INVOICE_TYPES } from '@/interfaces/certificate'; import Image from 'next/image'; import React, { useState } from 'react'; -import NumericInput from '@/components/numeric_input/numeric_input'; -import { RxCross1 } from 'react-icons/rx'; -import useOuterClick from '@/lib/hooks/use_outer_click'; import { useTranslation } from 'react-i18next'; import { IoIosArrowDown } from 'react-icons/io'; +import useOuterClick from '@/lib/hooks/use_outer_click'; +import NumericInput from '@/components/numeric_input/numeric_input'; import Toggle from '@/components/toggle/toggle'; +import Modal from '@/components/modal/modal'; import { Button } from '@/components/button/button'; +import { CERTIFICATE_TYPES, ICertificateUI, INVOICE_TYPES } from '@/interfaces/certificate'; interface CertificateEditModalProps { isOpen: boolean; @@ -74,20 +74,8 @@ const CertificateEditModal: React.FC = ({ if (!isOpen) return null; return ( -
-
- {/* Info: (20240924 - tzuhan) 關閉按鈕 */} - - + + <> {/* Info: (20240924 - tzuhan) 模態框標題 */}

{certificate.invoiceName} @@ -324,8 +312,8 @@ const CertificateEditModal: React.FC = ({

- - + + ); }; diff --git a/src/components/certificate/certificate_grid.tsx b/src/components/certificate/certificate_grid.tsx index 270740cc..c883b56c 100644 --- a/src/components/certificate/certificate_grid.tsx +++ b/src/components/certificate/certificate_grid.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { ICertificateUI } from '@/interfaces/certificate'; import CertificateThumbnail from '@/components/certificate/certificate_thumbnail'; -import FloatingUploadPopup from '@/components/upload_certificate/floating_upload_popup'; +import FloatingUploadPopup from '@/components/floating_upload_popup/floating_upload_popup'; interface CertificateGridProps { data: ICertificateUI[]; // Info: (20240923 - tzuhan) 項目列表 diff --git a/src/components/certificate/certificate_selection.tsx b/src/components/certificate/certificate_selection.tsx new file mode 100644 index 00000000..8bdcda72 --- /dev/null +++ b/src/components/certificate/certificate_selection.tsx @@ -0,0 +1,66 @@ +import Image from 'next/image'; +import { Button } from '@/components/button/button'; +import { AiOutlineLeft, AiOutlineRight } from 'react-icons/ai'; +import { FaPlus } from 'react-icons/fa6'; +import { ICertificate } from '@/interfaces/certificate'; + +interface CertificateSelectionProps { + selectedCertificates: ICertificate[]; + setOpenModal: (open: boolean) => void; +} + +const CertificateSelection: React.FC = ({ + selectedCertificates, + setOpenModal, +}: CertificateSelectionProps) => { + return ( +
+
+
+ {selectedCertificates.map((certificate) => ( +
+ AI +

{certificate.invoiceName}

+
+ ))} +
+ +
+
+
+
+

+ Uploaded {selectedCertificates.length} certificates +

+
+ + +
+
+
+ ); +}; + +export default CertificateSelection; diff --git a/src/components/certificate/certificate_selector_modal.tsx b/src/components/certificate/certificate_selector_modal.tsx new file mode 100644 index 00000000..e4552136 --- /dev/null +++ b/src/components/certificate/certificate_selector_modal.tsx @@ -0,0 +1,112 @@ +import React from 'react'; + +import FilterSection from '@/components/filter_section/filter_section'; +import { ICertificate, ICertificateUI } from '@/interfaces/certificate'; +import { APIName } from '@/constants/api_connection'; +import SelectionPannl from '@/components/certificate/selection_pannel'; +import { Button } from '@/components/button/button'; +import { RxCross1 } from 'react-icons/rx'; + +interface CertificateSelectorModalProps { + isOpen: boolean; + onClose: () => void; // Info: (20240924 - tzuhan) 關閉模態框的回調函數 + selectedCertificates: ICertificateUI[]; // Info: (20240926 - tzuhan) 已選擇的證書 + handleSelect: (ids: number[], isSelected: boolean) => void; // Info: (20240926 - tzuhan) 保存數據的回調函數 + certificates: ICertificateUI[]; // Info: (20240926 - tzuhan) 證書列表 + handleApiResponse: (data: ICertificate[]) => void; // Info: (20240926 - tzuhan) 處理 API 回應的回調函數 + openUploaderModal: () => void; // Info: (20240926 - tzuhan) 打開上傳模態框的回調函數 +} + +const CertificateSelectorModal: React.FC = ({ + isOpen, + onClose, + handleSelect, + selectedCertificates, + handleApiResponse, + certificates, + openUploaderModal, +}) => { + // Info: (20240924 - tzuhan) 不顯示模態框時返回 null + if (!isOpen) return null; + + const handleSelectAll = () => { + handleSelect( + certificates.map((item) => item.id), + true + ); + }; + + const handleComfirm = () => { + handleSelect( + selectedCertificates.map((item) => item.id), + true + ); + onClose(); + }; + + return ( +
+
+ {/* Info: (20240924 - tzuhan) 關閉按鈕 */} + + {/* Info: (20240924 - tzuhan) 模態框標題 */} +

Select Certificates

+

+ Choosing the certificates you want to attach with the voucher +

+ +
+
+
+ (Select {selectedCertificates.length}/{certificates.length}) +
+ +
+
+ +
+ + +
+
+
+ ); +}; + +export default CertificateSelectorModal; diff --git a/src/components/certificate/certificate_uoloader_modal.tsx b/src/components/certificate/certificate_uoloader_modal.tsx new file mode 100644 index 00000000..0fb453eb --- /dev/null +++ b/src/components/certificate/certificate_uoloader_modal.tsx @@ -0,0 +1,128 @@ +import React, { useState } from 'react'; + +import { Button } from '@/components/button/button'; +import { RxCross1 } from 'react-icons/rx'; +import UploadArea from '@/components/upload_area/upload_area'; +import { ProgressStatus } from '@/constants/account'; +import UploadFileItem, { UploadFile } from '@/components/upload_certificate/upload_file_item'; +import { GoArrowLeft } from 'react-icons/go'; +import CircularProgressBar from '@/components/certificate/circular_progress_bar'; + +interface CertificateUploaderModalProps { + isOpen: boolean; + onClose: () => void; // Info: (20240924 - tzuhan) 關閉模態框的回調函數 + onBack: () => void; // Info: (20240926 - tzuhan) 返回上一步的回調函數 +} + +const CertificateUploaderModal: React.FC = ({ + isOpen, + onClose, + onBack, +}) => { + const [files, setFiles] = useState([ + { name: 'preline-ui.xls', size: 7, progress: 20, status: ProgressStatus.IN_PROGRESS }, + { name: 'preline-ui.xls', size: 7, progress: 50, status: ProgressStatus.IN_PROGRESS }, + { name: 'preline-ui.xls', size: 7, progress: 80, status: ProgressStatus.IN_PROGRESS }, + ]); + + const updateFileStatus = (prevFiles: UploadFile[], index: number) => + prevFiles.map((file, i) => { + return i === index + ? { + ...file, + status: + file.status === ProgressStatus.PAUSED + ? ProgressStatus.IN_PROGRESS + : ProgressStatus.PAUSED, + } + : file; + }); + + const togglePause = (index: number) => { + setFiles((prevFiles) => updateFileStatus(prevFiles, index)); + }; + + // Info: (20240919 - tzuhan) 刪除上傳文件 + const deleteFile = (index: number) => { + setFiles((prevFiles) => prevFiles.filter((_, i) => i !== index)); + }; + + // Info: (20240924 - tzuhan) 不顯示模態框時返回 null + if (!isOpen) return null; + return ( +
+
+ {/* Info: (20240924 - tzuhan) 關閉按鈕 */} + + + {/* Info: (20240924 - tzuhan) 模態框標題 */} +

Upload Certificates

+

+ Upload the certificates you want to attach with the voucher +

+ +
+
+ {files.length > 0 ? ( + files.map((file, index) => ( + togglePause(index)} + onDelete={() => deleteFile(index)} + withoutImage + withoutBorder + /> + )) + ) : ( +
No files uploading
+ )} +
+
+
+ +
+
+ + +
+
+
+ ); +}; + +export default CertificateUploaderModal; diff --git a/src/components/certificate/circular_progress_bar.tsx b/src/components/certificate/circular_progress_bar.tsx new file mode 100644 index 00000000..608a930d --- /dev/null +++ b/src/components/certificate/circular_progress_bar.tsx @@ -0,0 +1,51 @@ +import React from 'react'; + +interface CircularProgressBarProps { + size: number; // 圓形直徑 + progress: number; // 進度百分比 + strokeWidth: number; // 線條寬度 + remainingText: string; // 顯示的剩餘文字 +} + +const CircularProgressBar: React.FC = ({ + size, + progress, + strokeWidth, + remainingText, +}) => { + // 圓的周長 + const radius = (size - strokeWidth) / 2; + const circumference = radius * 2 * Math.PI; + + // 根據進度計算 dashoffset + const dashOffset = circumference - (progress / 100) * circumference; + + return ( +
+ + + + + {remainingText} +
+ ); +}; + +export default CircularProgressBar; diff --git a/src/components/certificate/selection_pannel.tsx b/src/components/certificate/selection_pannel.tsx new file mode 100644 index 00000000..45716a5d --- /dev/null +++ b/src/components/certificate/selection_pannel.tsx @@ -0,0 +1,43 @@ +import { ICertificateUI } from '@/interfaces/certificate'; +import Image from 'next/image'; +import { FaPlus } from 'react-icons/fa6'; + +interface SelectionPannlProps { + certificates: ICertificateUI[]; + handleSelect: (ids: number[], isSelected: boolean) => void; + openUploaderModal: () => void; +} + +const SelectionPannl: React.FC = ({ + certificates, + handleSelect, + openUploaderModal, +}: SelectionPannlProps) => { + return ( +
+
+
+ +
+ {certificates.map((certificate) => ( +
+ AI +

{certificate.invoiceName}

+
+ ))} +
+
+ ); +}; + +export default SelectionPannl; diff --git a/src/components/filter_section/filter_section.tsx b/src/components/filter_section/filter_section.tsx index 6bf9d4d3..117b1833 100644 --- a/src/components/filter_section/filter_section.tsx +++ b/src/components/filter_section/filter_section.tsx @@ -17,8 +17,8 @@ interface FilterSectionProps { sortingOptions?: string[]; sortingByDate?: boolean; onApiResponse?: (data: ICertificate[]) => void; // Info: (20240919 - tzuhan) 回傳 API 回應資料 - viewType: VIEW_TYPES; - viewToggleHandler: (viewType: VIEW_TYPES) => void; + viewType?: VIEW_TYPES; + viewToggleHandler?: (viewType: VIEW_TYPES) => void; } const FilterSection: React.FC = ({ @@ -143,7 +143,9 @@ const FilterSection: React.FC = ({ {/* Info: (20240919 - tzuhan) 顯示風格切換 */} - + {viewType && viewToggleHandler && ( + + )} {/* Info: (20240919 - tzuhan) 排序選項 */} {sortingByDate ? ( diff --git a/src/components/upload_certificate/floating_upload_popup.tsx b/src/components/floating_upload_popup/floating_upload_popup.tsx similarity index 91% rename from src/components/upload_certificate/floating_upload_popup.tsx rename to src/components/floating_upload_popup/floating_upload_popup.tsx index c348c257..7a772852 100644 --- a/src/components/upload_certificate/floating_upload_popup.tsx +++ b/src/components/floating_upload_popup/floating_upload_popup.tsx @@ -1,15 +1,8 @@ import React, { useState } from 'react'; -import UploadFileItem from '@/components/upload_certificate/upload_file_item'; +import UploadFileItem, { UploadFile } from '@/components/upload_certificate/upload_file_item'; import { ProgressStatus } from '@/constants/account'; import Image from 'next/image'; -interface UploadFile { - name: string; - size: number; // Info: (20240919 - tzuhan) 文件大小(KB) - progress: number; // Info: (20240919 - tzuhan) 上傳進度(0-100) - status: ProgressStatus; // Info: (20240919 - tzuhan) 是否暫停 -} - const FloatingUploadPopup: React.FC = () => { const [files, setFiles] = useState([ { name: 'preline-ui.xls', size: 7, progress: 20, status: ProgressStatus.IN_PROGRESS }, diff --git a/src/components/modal/modal.tsx b/src/components/modal/modal.tsx new file mode 100644 index 00000000..b575c170 --- /dev/null +++ b/src/components/modal/modal.tsx @@ -0,0 +1,34 @@ +import React, { ReactElement } from 'react'; +import { RxCross1 } from 'react-icons/rx'; + +interface ModalProps { + isOpen: boolean; + onClose: () => void; // Info: (20240924 - tzuhan) 關閉模態框的回調函數 + children: ReactElement; +} + +const Modal: React.FC = ({ isOpen, onClose, children }) => { + // Info: (20240924 - tzuhan) 不顯示模態框時返回 null + if (!isOpen) return null; + + return ( +
+
+ {/* Info: (20240924 - tzuhan) 關閉按鈕 */} + + {children} +
+
+ ); +}; + +export default Modal; diff --git a/src/components/selection_tool_bar/selection_tool_bar.tsx b/src/components/selection_tool_bar/selection_tool_bar.tsx index 71954cd7..57cd67fe 100644 --- a/src/components/selection_tool_bar/selection_tool_bar.tsx +++ b/src/components/selection_tool_bar/selection_tool_bar.tsx @@ -8,16 +8,16 @@ interface SelectionToolbarProps { isSelectable: boolean; // Info: (20240920 - tzuhan) 是否可選擇 onActiveChange: (active: boolean) => void; // Info: (20240920 - tzuhan) 當打開狀態變更時的回調函數 items: ICertificateUI[]; // Info: (20240920 - tzuhan) 項目列表 - itemType: string; - subtitle: string; + itemType?: string; + subtitle?: string; selectedCount: number; // Info: (20240920 - tzuhan) 選中的項目數量 totalCount: number; // Info: (20240920 - tzuhan) 總項目數量 handleSelect: (ids: number[], isSelected: boolean) => void; operations?: ('ADD_VOUCHER' | 'ADD_ASSET' | 'DELETE')[]; // Info: (20240920 - tzuhan) 操作列表 - onAddVoucher: () => void; // Info: (20240920 - tzuhan) 添加新的憑證的回調函數 - onAddAsset: () => void; // Info: (20240920 - tzuhan) 添加新資產的回調函數 - onDelete: () => void; // Info: (20240920 - tzuhan) 添加刪除的回調函數 - onDownload: () => void; // Info: (20240923 - tzuhan) 添加下載的回調函數 + onAddVoucher?: () => void; // Info: (20240920 - tzuhan) 添加新的憑證的回調函數 + onAddAsset?: () => void; // Info: (20240920 - tzuhan) 添加新資產的回調函數 + onDelete?: () => void; // Info: (20240920 - tzuhan) 添加刪除的回調函數 + onDownload?: () => void; // Info: (20240923 - tzuhan) 添加下載的回調函數 } const SelectionToolbar: React.FC = ({ @@ -66,21 +66,23 @@ const SelectionToolbar: React.FC = ({ {active ? (
{/* Info: (20240920 - tzuhan) 左側選擇計數顯示 */} -
+
(Select {selectedCount}/{totalCount})
{/* Info: (20240920 - tzuhan) 中間操作按鈕 */}
- - {operations.includes('ADD_VOUCHER') && ( + {onDownload && ( + + )} + {operations.includes('ADD_VOUCHER') && onAddVoucher && ( )} - {operations.includes('ADD_ASSET') && ( + {operations.includes('ADD_ASSET') && onAddAsset && ( )} - {operations.includes('DELETE') && ( + {operations.includes('DELETE') && onDelete && (