Skip to content

Commit

Permalink
Merge branch 'develop' into feature/beta_login_i18n
Browse files Browse the repository at this point in the history
  • Loading branch information
TzuHanLiang committed Aug 15, 2024
2 parents ec737bb + 571038f commit 813f4b3
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 48 deletions.
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "iSunFA",
"version": "0.8.0+7",
"version": "0.8.0+9",
"private": false,
"scripts": {
"dev": "next dev",
Expand Down Expand Up @@ -53,7 +53,8 @@
"react-usestateref": "^1.0.8",
"sharp": "^0.33.3",
"tailwind-merge": "^2.2.2",
"ts-node": "^10.9.2"
"ts-node": "^10.9.2",
"uuid": "^10.0.0"
},
"devDependencies": {
"@babel/eslint-plugin": "^7.23.5",
Expand All @@ -67,6 +68,7 @@
"@types/nodemailer": "^6.4.15",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^6.16.0",
"@typescript-eslint/parser": "^6.16.0",
"autoprefixer": "^10.4.16",
Expand Down
53 changes: 41 additions & 12 deletions src/components/journal_upload_area/journal_upload_area.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { v4 as uuidv4 } from 'uuid';
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'next-i18next';
import Image from 'next/image';
import APIHandler from '@/lib/utils/api_handler';
import { APIName } from '@/constants/api_connection';
import { IAccountResultStatus } from '@/interfaces/accounting_account';
// import { IAccountResultStatus } from '@/interfaces/accounting_account';
import { useUserCtx } from '@/contexts/user_context';
import { useGlobalCtx } from '@/contexts/global_context';
import { useAccountingCtx } from '@/contexts/accounting_context';
import { ProgressStatus } from '@/constants/account';
import { MessageType } from '@/interfaces/message_modal';
import { ToastType } from '@/interfaces/toastify';
import { getTimestampNow } from '@/lib/utils/common';
import { transformBytesToFileSizeString } from '@/lib/utils/common';
import { IOCR } from '@/interfaces/ocr';

interface FileInfo {
file: File;
Expand All @@ -21,15 +23,17 @@ interface FileInfo {
const JournalUploadArea = () => {
const { t } = useTranslation('common');
const { selectedCompany } = useUserCtx();
const { setInvoiceIdHandler, addOCRHandler } = useAccountingCtx();
const { setInvoiceIdHandler, addPendingOCRHandler, deletePendingOCRHandler, addOCRHandler } =
useAccountingCtx();
const { messageModalDataHandler, messageModalVisibilityHandler, toastHandler } = useGlobalCtx();

const {
trigger: uploadInvoice,
data: results,
success: uploadSuccess,
code: uploadCode,
} = APIHandler<IAccountResultStatus[]>(APIName.OCR_UPLOAD);
} = APIHandler<IOCR[]>(APIName.OCR_UPLOAD);
// IAccountResultStatus[]

// Info: (20240711 - Julian) 上傳的檔案
const [uploadFile, setUploadFile] = useState<FileInfo | null>(null);
Expand All @@ -44,10 +48,11 @@ const JournalUploadArea = () => {
const { files } = event.target;
if (files && files.length > 0) {
const file = files[0];
const fileSize = transformBytesToFileSizeString(file.size);
setUploadFile({
file,
name: file.name,
size: file.size.toString(),
size: fileSize,
});
}
};
Expand All @@ -65,10 +70,11 @@ const JournalUploadArea = () => {
event.preventDefault();
const droppedFile = event.dataTransfer.files[0];
if (droppedFile) {
const fileSize = transformBytesToFileSizeString(droppedFile.size);
setUploadFile({
file: droppedFile,
name: droppedFile.name,
size: droppedFile.size.toString(),
size: fileSize,
});
setIsDragOver(false);
}
Expand All @@ -77,11 +83,19 @@ const JournalUploadArea = () => {
useEffect(() => {
if (uploadFile && selectedCompany) {
const formData = new FormData();
const uuid = uuidv4();
formData.append('image', uploadFile.file);
// TODO: in dev (20240815 - Shirley) 加上 imageSize, imageName, uploadIdentifier
formData.append('imageSize', uploadFile.size);
formData.append('imageName', uploadFile.name);
formData.append('uploadIdentifier', uuid);
// eslint-disable-next-line no-console
// console.log('formData', formData);

// Info: (20240711 - Julian) 點擊上傳後才升起 flag
// setIsShowSuccessModal(true);
addOCRHandler(`${getTimestampNow()}`, uploadFile.name, uploadFile.size);
// addOCRHandler(`${getTimestampNow()}`, uploadFile.name, uploadFile.size, uuid);
addPendingOCRHandler(uploadFile.name, uploadFile.size, uuid);

uploadInvoice({ params: { companyId: selectedCompany.id }, body: formData });
}
Expand All @@ -90,7 +104,7 @@ const JournalUploadArea = () => {
useEffect(() => {
if (uploadSuccess && results) {
results.forEach((result) => {
const { resultId } = result;
// const { resultId } = result;
/* Info: (20240805 - Anna) 將狀態的翻譯key值存到變數 */
const translatedStatus = t(
`PROGRESS_STATUS.${result.status.toUpperCase().replace(/_/g, '_')}`
Expand All @@ -107,10 +121,25 @@ const JournalUploadArea = () => {
closeable: true,
type: ToastType.SUCCESS,
});
setInvoiceIdHandler(resultId);
// if (uploadFile) {
// addOCRHandler(resultId, uploadFile.name, uploadFile.size);
// }
setInvoiceIdHandler(result.aichResultId);
// setInvoiceIdHandler(resultId);
// TODO: in dev (20240815 - Shirley) 加上
// eslint-disable-next-line no-console
console.log('result in JournalUploadArea', result);
if (
result?.uploadIdentifier &&
result?.aichResultId &&
result?.imageName &&
result?.imageSize
) {
addOCRHandler(
result.aichResultId,
result.imageName,
result.imageSize,
result.uploadIdentifier
);
deletePendingOCRHandler(result?.uploadIdentifier);
}
// messageModalDataHandler({
// // title: 'Upload Successful',
// title: t('JOURNAL.UPLOAD_SUCCESSFUL'),
Expand Down
32 changes: 28 additions & 4 deletions src/components/step_one_tab/step_one_tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,19 @@ const StepOneTab = () => {
const { t } = useTranslation('common');
const { cameraScannerVisibilityHandler, toastHandler } = useGlobalCtx();
const { selectedCompany } = useUserCtx();
const { OCRList, OCRListStatus, updateOCRListHandler, selectOCRHandler, deleteOCRHandler } =
useAccountingCtx();
const {
OCRList,
OCRListStatus,
updateOCRListHandler,
selectOCRHandler,
deleteOCRHandler,
pendingOCRList,
} = useAccountingCtx();
// Info: (20240809 - Shirley) disabled for now , 分頁功能在 alpha release 還沒實作
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [currentFilePage, setCurrentFilePage] = useState<number>(1);
const [fileList, setFileList] = useState<IOCR[]>(OCRList);
// const [pendingFileList, setPendingFileList] = useState<IOCR[]>(pendingOCRList);
// Info: (20240809 - Shirley) disabled for now , 分頁功能在 alpha release 還沒實作
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [totalPages, setTotalPages] = useState<number>(1);
Expand Down Expand Up @@ -83,6 +90,9 @@ const StepOneTab = () => {
}
};

// eslint-disable-next-line no-console
console.log('in StepOneTab, fileList', fileList, 'pendingOCRList', pendingOCRList);

useEffect(() => {
setTotalPages(Math.ceil(fileList.length / 5));
}, [fileList]);
Expand Down Expand Up @@ -154,6 +164,16 @@ const StepOneTab = () => {
};

const displayedFileList = fileList.map((data) => (
<UploadedFileItem
key={data.id}
itemData={data}
pauseHandler={fileItemPauseHandler}
deleteHandler={fileItemDeleteHandler}
clickHandler={handleOCRClick}
/>
));

const displayedPendingFileList = pendingOCRList.map((data) => (
<UploadedFileItem
key={data.id}
itemData={data}
Expand All @@ -165,7 +185,7 @@ const StepOneTab = () => {
));

const uploadedFileSection =
fileList.length > 0 ? (
fileList.length > 0 || pendingOCRList.length > 0 ? (
<>
<div className="my-5 flex items-center gap-4">
<hr className="block flex-1 border-lightGray4 md:hidden" />
Expand All @@ -182,7 +202,11 @@ const StepOneTab = () => {
</div>
{/* Info: (20240523 - Julian) Uploaded File List */}
<div className="mb-50px flex flex-col items-center gap-y-50px">
<div className="flex w-full flex-col items-center gap-y-12px">{displayedFileList}</div>
<div className="flex w-full flex-col items-center gap-y-12px">
{displayedFileList}
{displayedPendingFileList}
</div>

{/* Info: (20240523 - Julian) Pagination */}
{/* Info: (20240809 - Shirley) disabled for now , 分頁功能在 alpha release 還沒實作 */}
{/* {totalPages > 1 && (
Expand Down
14 changes: 10 additions & 4 deletions src/components/uploaded_file_item/uploaded_file_item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ const UploadedFileItem = ({
clickHandler(itemData);
};

// Info: (20240527 - Julian) 若檔名過長,則擷取前 3 個和後 4 個(副檔名)字元,中間以 ... 代替
// Info: (20240527 - Julian) 若檔名過長,則擷取前 5 個和後 4 個(副檔名)字元,中間以 ... 代替
const truncatedFileName =
imageName.length > 20 ? `${imageName.slice(0, 3)}...${imageName.slice(-4)}` : imageName;
imageName.length > 20 ? `${imageName.slice(0, 5)}...${imageName.slice(-4)}` : imageName;

const displayedPauseButton =
status === ProgressStatus.PAUSED ? <FiPlay size={20} /> : <FiPauseCircle size={20} />;
Expand All @@ -81,8 +81,14 @@ const UploadedFileItem = ({
<Skeleton width={56} height={56} /> {/* Info: 掃描動畫 (20240814 - Shirley) */}
<Skeleton width={64} height={64} /> {/* Info: 文件縮略圖 (20240814 - Shirley) */}
<div className="flex shrink grow flex-col items-start">
<Skeleton width={100} height={24} /> {/* Info: 文件名 (20240814 - Shirley) */}
<Skeleton width={50} height={16} /> {/* Info: 文件大小 (20240814 - Shirley) */}
<h3
className={`text-base font-semibold leading-normal tracking-tight text-file-uploading-text-primary`}
>
{truncatedFileName}
</h3>
<p className="text-xs font-normal leading-tight tracking-tight text-file-uploading-text-disable">
{imageSize}
</p>
</div>
<div className="absolute right-0 z-10 flex items-center gap-10px">
<Skeleton width={20} height={20} /> {/* Info: 狀態圖標 (20240814 - Shirley) */}
Expand Down
54 changes: 52 additions & 2 deletions src/contexts/accounting_context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,15 @@ interface IAccountingContext {
OCRList: IOCR[];
OCRListStatus: { listSuccess: boolean | undefined; listCode: string | undefined };
updateOCRListHandler: (companyId: number | undefined, update: boolean) => void;
addOCRHandler: (aichId: string, imageName: string, imageSize: string) => void;
addOCRHandler: (
aichId: string,
imageName: string,
imageSize: string,
uploadIdentifier: string
) => void;
deleteOCRHandler: (aichId: string) => void;
addPendingOCRHandler: (imageName: string, imageSize: string, uploadIdentifier: string) => void;
deletePendingOCRHandler: (uploadIdentifier: string) => void;
accountList: IAccount[];
getAccountListHandler: (
companyId: number,
Expand Down Expand Up @@ -114,6 +121,7 @@ interface IAccountingContext {
generateAccountTitle: (account: IAccount | null) => string;

deleteOwnAccountTitle: (companyId: number, id: number) => void;
pendingOCRList: IOCR[];
}

const initialAccountingContext: IAccountingContext = {
Expand All @@ -127,6 +135,8 @@ const initialAccountingContext: IAccountingContext = {
updateOCRListHandler: () => {},
addOCRHandler: () => {},
deleteOCRHandler: () => {},
addPendingOCRHandler: () => {},
deletePendingOCRHandler: () => {},
accountList: [],
getAccountListHandler: () => {},
getAIStatusHandler: () => {},
Expand Down Expand Up @@ -159,6 +169,7 @@ const initialAccountingContext: IAccountingContext = {
generateAccountTitle: () => 'Account Title',

deleteOwnAccountTitle: () => {},
pendingOCRList: [],
};

export const AccountingContext = createContext<IAccountingContext>(initialAccountingContext);
Expand Down Expand Up @@ -212,6 +223,9 @@ export const AccountingProvider = ({ children }: IAccountingProvider) => {
const [intervalId, setIntervalId] = useState<NodeJS.Timeout | null>(null);
const [inputDescription, setInputDescription] = useState<string>('');

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [pendingOCRList, setPendingOCRList] = useState<IOCR[]>([]);

const getAccountListHandler = (
companyId: number,
type?: string,
Expand Down Expand Up @@ -297,7 +311,12 @@ export const AccountingProvider = ({ children }: IAccountingProvider) => {
});
};

const addOCRHandler = (aichId: string, imageName: string, imageSize: string) => {
const addOCRHandler = (
aichId: string,
imageName: string,
imageSize: string,
uploadIdentifier: string
) => {
const now = getTimestampNow();
const pendingOCR: IOCR = {
id: now,
Expand All @@ -308,13 +327,39 @@ export const AccountingProvider = ({ children }: IAccountingProvider) => {
progress: 0,
status: ProgressStatus.WAITING_FOR_UPLOAD,
createdAt: 0,
uploadIdentifier,
};
setOCRList((prev) => {
const rs = [...prev, pendingOCR];
return rs;
});
};

const addPendingOCRHandler = (imageName: string, imageSize: string, uploadIdentifier: string) => {
const ocr: IOCR = {
id: getTimestampNow(),
aichResultId: getTimestampNow().toString(),
imageName,
imageUrl: '',
progress: 0,
status: ProgressStatus.WAITING_FOR_UPLOAD,
imageSize,
createdAt: 0,
uploadIdentifier,
};
setPendingOCRList((prev) => {
const rs = [...prev, ocr];
return rs;
});
};

const deletePendingOCRHandler = (uploadIdentifier: string) => {
setPendingOCRList((prev) => {
const rs = prev.filter((ocr) => ocr.uploadIdentifier !== uploadIdentifier);
return rs;
});
};

useEffect(() => {
if (accountSuccess && accountTitleList) {
setAccountList(accountTitleList.data);
Expand Down Expand Up @@ -598,6 +643,8 @@ export const AccountingProvider = ({ children }: IAccountingProvider) => {
updateOCRListHandler,
addOCRHandler,
deleteOCRHandler,
addPendingOCRHandler,
deletePendingOCRHandler,
accountList,
getAccountListHandler,
getAIStatusHandler,
Expand Down Expand Up @@ -628,6 +675,8 @@ export const AccountingProvider = ({ children }: IAccountingProvider) => {
deleteOwnAccountTitle,
inputDescription,
inputDescriptionHandler,

pendingOCRList,
}),
[
OCRList,
Expand All @@ -652,6 +701,7 @@ export const AccountingProvider = ({ children }: IAccountingProvider) => {
selectedJournal,
selectJournalHandler,
inputDescription,
pendingOCRList,
]
);

Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/accounting_account.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { AccountType, EquityType, ProgressStatus } from '@/constants/account';
import { Account } from '@prisma/client';
import { ReportSheetType } from '@/constants/report';
import { IPaginatedData } from './pagination';
import { IPaginatedData } from '@/interfaces/pagination';

export interface IAccount {
id: number;
Expand Down
Loading

0 comments on commit 813f4b3

Please sign in to comment.