Skip to content

Commit

Permalink
feat: add voucher partial component
Browse files Browse the repository at this point in the history
  • Loading branch information
TzuHanLiang committed Sep 26, 2024
1 parent baee0c1 commit aa6b6ba
Show file tree
Hide file tree
Showing 19 changed files with 743 additions and 58 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.2+11",
"version": "0.8.2+12",
"private": false,
"scripts": {
"dev": "next dev",
Expand Down
103 changes: 103 additions & 0 deletions public/elements/siri.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions src/components/ai_analyzer/ai_analyzer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import Image from 'next/image';

interface AIAnalyzerProps {}

const AIAnalyzer: React.FC<AIAnalyzerProps> = () => {
return (
<div className="mt-4 flex items-center justify-between overflow-hidden rounded-md bg-surface-brand-primary-moderate px-4 py-2">
<div className="relative h-20 w-20">
<Image
src="/elements/siri.svg"
alt="AI"
width={180}
height={190}
className="absolute left-1/2 top-14 max-w-180px -translate-x-1/2 -translate-y-1/2 object-cover"
/>
</div>
<p className="text-lg font-medium">
Please select the certificates for AI to generate the voucher for you
</p>
</div>
);
};

export default AIAnalyzer;
28 changes: 8 additions & 20 deletions src/components/certificate/certificate_edit_modal.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -74,20 +74,8 @@ const CertificateEditModal: React.FC<CertificateEditModalProps> = ({
if (!isOpen) return null;

return (
<div
className="fixed inset-0 z-70 flex items-center justify-center bg-black/50"
onClick={onClose}
>
<div className="relative flex max-h-450px w-90vw max-w-800px flex-col rounded-sm bg-surface-neutral-surface-lv2 p-20px md:max-h-90vh">
{/* Info: (20240924 - tzuhan) 關閉按鈕 */}
<button
type="button"
className="absolute right-4 top-4 text-checkbox-text-primary"
onClick={onClose}
>
<RxCross1 size={32} />
</button>

<Modal isOpen={isOpen} onClose={onClose}>
<>
{/* Info: (20240924 - tzuhan) 模態框標題 */}
<h2 className="mb-4 flex justify-center gap-2 text-xl font-semibold">
{certificate.invoiceName}
Expand Down Expand Up @@ -324,8 +312,8 @@ const CertificateEditModal: React.FC<CertificateEditModalProps> = ({
</div>
</div>
</div>
</div>
</div>
</>
</Modal>
);
};

Expand Down
2 changes: 1 addition & 1 deletion src/components/certificate/certificate_grid.tsx
Original file line number Diff line number Diff line change
@@ -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) 項目列表
Expand Down
66 changes: 66 additions & 0 deletions src/components/certificate/certificate_selection.tsx
Original file line number Diff line number Diff line change
@@ -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<CertificateSelectionProps> = ({
selectedCertificates,
setOpenModal,
}: CertificateSelectionProps) => {
return (
<div className="my-8 w-full flex-col items-center">
<div className="flex h-56 w-full flex-col items-start justify-start rounded-md border border-stroke-neutral-quaternary px-8 pt-6 shadow-inset-lg">
<div className="flex space-x-4 overflow-x-auto">
{selectedCertificates.map((certificate) => (
<div key={certificate.id} className="flex flex-col items-center">
<Image src={certificate.thumbnailUrl} alt="AI" width={80} height={80} />
<p className="text-sm font-semibold">{certificate.invoiceName}</p>
</div>
))}
<div>
<button
type="button"
className="mx-4 my-2 flex h-140px w-80px items-center justify-center rounded-xs border border-dashed border-stroke-neutral-tertiary p-2 text-white"
onClick={() => setOpenModal(true)}
>
<FaPlus size={24} className="text-stroke-neutral-tertiary" />
</button>
</div>
</div>
</div>
<div className="mt-2 w-full text-center">
<p className="text-text-neutral-tertiary">
Uploaded {selectedCertificates.length} certificates
</p>
<div className="mt-2 flex items-center justify-center space-x-2">
<Button
type="button"
onClick={() => {}}
variant="secondaryOutline"
disabled={selectedCertificates.length === 0}
className="h-40px w-40px p-0"
>
<AiOutlineLeft size={16} />
</Button>
<Button
type="button"
onClick={() => {}}
variant="secondaryOutline"
disabled={selectedCertificates.length === 0}
className="h-40px w-40px p-0"
>
<AiOutlineRight size={16} />
</Button>
</div>
</div>
</div>
);
};

export default CertificateSelection;
112 changes: 112 additions & 0 deletions src/components/certificate/certificate_selector_modal.tsx
Original file line number Diff line number Diff line change
@@ -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<CertificateSelectorModalProps> = ({
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 (
<div className="fixed inset-0 z-70 flex items-center justify-center bg-black/50">
<div className="relative flex max-h-450px w-90vw max-w-800px flex-col rounded-sm bg-surface-neutral-surface-lv2 p-20px md:max-h-90vh">
{/* Info: (20240924 - tzuhan) 關閉按鈕 */}
<button
type="button"
className="absolute right-4 top-4 text-checkbox-text-primary"
onClick={onClose}
>
<RxCross1 size={32} />
</button>
{/* Info: (20240924 - tzuhan) 模態框標題 */}
<h2 className="flex justify-center gap-2 text-xl font-semibold">Select Certificates</h2>
<p className="flex justify-center text-card-text-secondary">
Choosing the certificates you want to attach with the voucher
</p>
<FilterSection
apiName={APIName.CERTIFICATE_LIST}
onApiResponse={handleApiResponse}
types={['All', 'Invoice', 'Receipt']}
/>
<div className="px-4">
<div className="flex items-center justify-between">
<div className="font-medium text-text-neutral-secondary">
(Select {selectedCertificates.length}/{certificates.length})
</div>
<button
type="button"
className="text-link-text-primary hover:underline"
onClick={handleSelectAll}
>
Select All
</button>
</div>
</div>
<SelectionPannl
certificates={certificates}
handleSelect={handleSelect}
openUploaderModal={openUploaderModal}
/>
<div className="flex items-center justify-end gap-2">
<Button
id="upload-image-button"
type="button"
variant="secondaryOutline"
className="gap-x-4px px-4 py-2"
onClick={onClose}
>
Cancel
</Button>
<Button
id="upload-image-button"
type="button"
variant="tertiary"
className="gap-x-4px px-4 py-2"
onClick={handleComfirm}
>
Confirm
</Button>
</div>
</div>
</div>
);
};

export default CertificateSelectorModal;
Loading

0 comments on commit aa6b6ba

Please sign in to comment.