Skip to content

Commit

Permalink
update PreviewModal & user context
Browse files Browse the repository at this point in the history
  • Loading branch information
godmmt committed Oct 9, 2024
1 parent 244ca88 commit 0f1491b
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 68 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+37",
"version": "0.8.2+38",
"private": false,
"scripts": {
"dev": "next dev",
Expand Down
61 changes: 43 additions & 18 deletions src/components/beta/select_role/introduction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,26 @@ import React from 'react';
import Image from 'next/image';
import { FiEye, FiArrowRight } from 'react-icons/fi';
import { RoleId } from '@/constants/role';
import { useUserCtx } from '@/contexts/user_context';

interface IntroductionProps {
role: React.SetStateAction<string>;
showingRole: React.SetStateAction<RoleId | null>;
togglePreviewModal: () => void;
}
interface ButtonsProps {
showingRole: RoleId;
togglePreviewModal: () => void;
}
interface BookkeeperIntroductionProps {
showingRole: RoleId;
togglePreviewModal: () => void;
}
interface EducationalTrialVersionIntroductionProps {
showingRole: RoleId;
togglePreviewModal: () => void;
}

const DefaultIntroduction = () => {
const DefaultIntroduction: React.FC = () => {
return (
<section className="h-600px bg-bg_select_role bg-contain bg-right-top bg-no-repeat">
<div className="flex flex-col gap-40px pl-60px pt-60px">
Expand All @@ -26,25 +40,23 @@ const DefaultIntroduction = () => {
);
};

const Buttons = () => {
const handlePreview = () => {
// Deprecated: (20241007 - Liz)
// eslint-disable-next-line no-console
console.log('Preview');
};
const Buttons: React.FC<ButtonsProps> = ({ togglePreviewModal, showingRole }) => {
const { selectRole } = useUserCtx();

const handleStart = () => {
// Deprecated: (20241007 - Liz)
// eslint-disable-next-line no-console
console.log('Start');
console.log('showingRole:', showingRole, '儲存 showingRole 到 userCtx');

selectRole(showingRole);
};

return (
<div className="flex gap-40px">
<button
type="button"
className="flex items-center gap-8px rounded-xs border border-button-stroke-secondary px-32px py-14px text-lg font-medium text-button-text-secondary hover:border-button-stroke-primary-hover hover:text-button-text-primary-hover disabled:border-button-stroke-disable disabled:text-button-text-disable"
onClick={handlePreview}
onClick={togglePreviewModal}
>
<p>Preview</p>
<FiEye size={24} />
Expand All @@ -62,7 +74,10 @@ const Buttons = () => {
);
};

const BookkeeperIntroduction = () => {
const BookkeeperIntroduction: React.FC<BookkeeperIntroductionProps> = ({
showingRole,
togglePreviewModal,
}) => {
return (
<section className="h-600px bg-bg_bookkeeper bg-contain bg-right-top bg-no-repeat">
<div className="flex flex-col gap-40px pl-60px pt-60px">
Expand All @@ -82,13 +97,16 @@ const BookkeeperIntroduction = () => {
<p>General Ledger, Voucher Issuance, Preparation of Financial and Tax Reports</p>
</div>

<Buttons />
<Buttons showingRole={showingRole} togglePreviewModal={togglePreviewModal} />
</div>
</section>
);
};

const EducationalTrialVersionIntroduction = () => {
const EducationalTrialVersionIntroduction: React.FC<EducationalTrialVersionIntroductionProps> = ({
showingRole,
togglePreviewModal,
}) => {
return (
<section className="h-600px bg-bg_educational_trial_version bg-contain bg-right-top bg-no-repeat">
<div className="flex flex-col gap-40px pl-60px pt-60px">
Expand All @@ -113,18 +131,25 @@ const EducationalTrialVersionIntroduction = () => {
<p>General Ledger, Voucher Issuance</p>
</div>

<Buttons />
<Buttons showingRole={showingRole} togglePreviewModal={togglePreviewModal} />
</div>
</section>
);
};

const Introduction = ({ role }: IntroductionProps) => {
const Introduction: React.FC<IntroductionProps> = ({ showingRole, togglePreviewModal }) => {
return (
<>
{!role && <DefaultIntroduction />}
{role === RoleId.BOOKKEEPER && <BookkeeperIntroduction />}
{role === RoleId.EDUCATIONAL_TRIAL_VERSION && <EducationalTrialVersionIntroduction />}
{!showingRole && <DefaultIntroduction />}
{showingRole === RoleId.BOOKKEEPER && (
<BookkeeperIntroduction showingRole={showingRole} togglePreviewModal={togglePreviewModal} />
)}
{showingRole === RoleId.EDUCATIONAL_TRIAL_VERSION && (
<EducationalTrialVersionIntroduction
showingRole={showingRole}
togglePreviewModal={togglePreviewModal}
/>
)}
</>
);
};
Expand Down
31 changes: 21 additions & 10 deletions src/components/beta/select_role/preview_modal.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,25 @@
import Image from 'next/image';
import { useState } from 'react';
import { IoCloseOutline, IoEllipse } from 'react-icons/io5';

interface PreviewModalProps {
togglePreviewModal: () => void;
}

const PreviewModal = ({ togglePreviewModal }: PreviewModalProps) => {
// ToDo: (20241009 - Liz) 根據 videoIndex 顯示不同影片
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [videoIndex, setVideoIndex] = useState<number>(0);
const videoIds = ['video1', 'video2', 'video3', 'video4', 'video5'];

return (
<div className="fixed inset-0 z-10 flex items-center justify-center bg-black/50">
<div className="flex w-700px flex-col gap-40px rounded-lg bg-white p-40px">
<section className="flex items-center justify-between">
<h1 className="grow text-center text-xl font-bold text-text-neutral-primary">
Role Function Preview
</h1>
<button type="button" onClick={togglePreviewModal} className="">
<button type="button" onClick={togglePreviewModal}>
<IoCloseOutline size={24} />
</button>
</section>
Expand All @@ -28,15 +34,20 @@ const PreviewModal = ({ togglePreviewModal }: PreviewModalProps) => {
></Image>
</section>

{/* // Info: (20241008 - Liz) 切換影片控制鈕 */}
<section className="flex">
<button type="button" className="text-carousel-surface-active">
<IoEllipse size={8} />
</button>
<IoEllipse size={8} />
<IoEllipse size={8} />
<IoEllipse size={8} />
<IoEllipse size={8} />
{/* // Info: (20241008 - Liz) 切換影片控制按鈕 */}
<section className="flex justify-center gap-8px p-16px">
{videoIds.map((id, index) => (
<button
key={id}
type="button"
onClick={() => setVideoIndex(index)}
className={
videoIndex === index ? 'text-carousel-surface-active' : 'text-carousel-surface-mute'
}
>
<IoEllipse size={10} />
</button>
))}
</section>
</div>
</div>
Expand Down
24 changes: 12 additions & 12 deletions src/components/beta/select_role/role_card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import Image from 'next/image';
import { RoleId } from '@/constants/role';

interface RoleCardProps {
role: React.SetStateAction<string>;
setRole: React.Dispatch<React.SetStateAction<string>>;
showingRole: React.SetStateAction<RoleId | null>;
setShowingRole: React.Dispatch<React.SetStateAction<RoleId | null>>;
}

interface CardProps {
Expand All @@ -13,8 +13,8 @@ interface CardProps {
title: string;
imageSrc: string;
altText: string;
role: React.SetStateAction<string>;
setRole: React.Dispatch<React.SetStateAction<string>>;
showingRole: React.SetStateAction<RoleId | null>;
setShowingRole: React.Dispatch<React.SetStateAction<RoleId | null>>;
}

// Info: (20241007 - Liz) 每個角色卡片的資訊
Expand Down Expand Up @@ -55,15 +55,15 @@ const Card: React.FC<CardProps> = ({
title,
imageSrc,
altText,
role,
setRole,
showingRole,
setShowingRole,
}) => {
const isRoleSelected = role === roleId;
const isRoleSelected = showingRole === roleId;

return (
<button
type="button"
onClick={() => setRole(roleId)}
onClick={() => setShowingRole(roleId)}
disabled={isRoleDisabled}
className={`relative flex h-120px w-240px skew-x-20 items-center rounded-sm text-text-neutral-primary shadow-Dropshadow_XS disabled:opacity-50 desktop:w-360px ${isRoleSelected ? 'border-2 border-stroke-brand-primary bg-surface-brand-primary-30' : 'bg-surface-neutral-surface-lv2 hover:bg-surface-brand-primary-10'} ${isRoleDisabled && 'pointer-events-none'}`}
>
Expand All @@ -77,13 +77,13 @@ const Card: React.FC<CardProps> = ({
alt={altText}
width={48}
height={48}
className={`absolute -left-50px -top-30px w-160px -skew-x-20 rounded-full ${role === roleId ? 'border-4 border-stroke-brand-primary' : ''}`}
className={`absolute -left-50px -top-30px w-160px -skew-x-20 rounded-full ${showingRole === roleId ? 'border-4 border-stroke-brand-primary' : ''}`}
/>
</button>
);
};

const RoleCard = ({ role, setRole }: RoleCardProps) => {
const RoleCard = ({ showingRole, setShowingRole }: RoleCardProps) => {
return (
<div className="flex gap-80px">
{cards.map((card) => (
Expand All @@ -94,8 +94,8 @@ const RoleCard = ({ role, setRole }: RoleCardProps) => {
title={card.title}
imageSrc={card.imageSrc}
altText={card.altText}
role={role}
setRole={setRole}
showingRole={showingRole}
setShowingRole={setShowingRole}
/>
))}
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/constants/role.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Info: (20241007 - Liz) 每個角色卡片的角色 id
// Info: (20241007 - Liz) 角色 id (與後端的角色 id 不同,未來後端會提供 role name)
export enum RoleId {
BOOKKEEPER = 'bookkeeper',
EDUCATIONAL_TRIAL_VERSION = 'educational_trial_version',
Expand Down
46 changes: 28 additions & 18 deletions src/contexts/user_context.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ interface UserContextType {
isAgreeTermsOfService: boolean;
isAgreePrivacyPolicy: boolean;
isSignInError: boolean;
role: string | null;
selectRole: (roleId: string) => void;
selectedCompany: ICompany | null;
selectCompany: (company: ICompany | null, isPublic?: boolean) => Promise<void>;
successSelectCompany: boolean | undefined;
Expand Down Expand Up @@ -56,6 +58,8 @@ export const UserContext = createContext<UserContextType>({
isAgreeTermsOfService: false,
isAgreePrivacyPolicy: false,
isSignInError: false,
role: null,
selectRole: () => {},
selectedCompany: null,
selectCompany: async () => {},
successSelectCompany: undefined,
Expand All @@ -80,6 +84,7 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => {
const [, setCredential, credentialRef] = useStateRef<string | null>(null);
const [userAuth, setUserAuth, userAuthRef] = useStateRef<IUser | null>(null);
const [, setUsername, usernameRef] = useStateRef<string | null>(null);
const [, setRole, roleRef] = useStateRef<string | null>(null);
const [, setSelectedCompany, selectedCompanyRef] = useStateRef<ICompany | null>(null);
const [, setSuccessSelectCompany, successSelectCompanyRef] = useStateRef<boolean | undefined>(
undefined
Expand Down Expand Up @@ -118,6 +123,7 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => {
setCredential(null);
setIsSignIn(false);
setIsSignInError(false);
setRole(null);
setSelectedCompany(null);
setSuccessSelectCompany(undefined);
localStorage.removeItem('userId');
Expand Down Expand Up @@ -272,10 +278,9 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => {
setIsAgreePrivacyPolicy(hasAgreedToPrivacy);
};

// Deprecated: (20241004 - Liz) 之後統一刪除
// Info: (20241001 - Liz) 此函數處理公司資訊:
// 如果公司資料存在且不為空,它會設定選定的公司 (setSelectedCompany),並標記成功選擇公司。
// 若公司資料不存在,會將公司資訊設為空,並檢查路由是否位於 users 路徑中。如果符合條件且不在 SELECT_COMPANY 頁面,它會呼叫 redirectToSelectCompanyPage 函數進行重新導向
// 若公司資料不存在,會將公司資訊設為空,並標記為未選擇公司
const processCompanyInfo = (company: ICompany) => {
if (company && Object.keys(company).length > 0) {
// Deprecated: (20241008 - Liz)
Expand All @@ -295,23 +300,17 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => {
setSelectedCompany(null);

return false;

// const isInUsersRoute =
// router.pathname.includes('users') && !router.pathname.includes(ISUNFA_ROUTE.SELECT_COMPANY);

// if (isInUsersRoute) {
// goToSelectRolePage();
// }
}
};

// ToDo: (20241004 - Liz) 之後會新增一個函數來處理「使用者的角色資訊」

// Info: (20241001 - Liz) 此函數處理使用者資訊:
// 如果使用者資料存在且有效,會設定使用者認證、名稱,並標記為已登入。
// 它還會將使用者的 userId 和過期時間儲存在 localStorage。
// 最後,它會呼叫 updateUserAgreements 函數更新使用者的協議狀態。
// 如果使用者資料不存在,則會清除狀態,並導向登入頁面。
// 如果使用者資料存在且有效,會設定使用者認證、名稱,並標記為已登入,
// 它還會將使用者的 userId 和過期時間儲存在 localStorage 中,
// 接著它會呼叫 updateUserAgreements 函數更新使用者的協議狀態,
// 最後回傳 true。
// 如果使用者資料不存在,會回傳 false。
const processUserInfo = (user: IUser) => {
if (user && Object.keys(user).length > 0) {
setUserAuth(user);
Expand All @@ -330,12 +329,15 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => {

return true;
} else {
// clearStates();
// redirectToLoginPage();
// clearStates(); // Deprecated: (20241009 - Liz)
// redirectToLoginPage(); // Deprecated: (20241009 - Liz)
return false;
}
};

// Info: (20241009 - Liz) 此函數是在處理使用者和公司資訊,並根據處理結果來決定下一步的操作:
// 它會呼叫 processUserInfo 和 processCompanyInfo 分別處理使用者和公司資訊。
// 依據處理結果,它會執行不同的自動導向邏輯。
const handleUserAndCompanyProcessing = (user: IUser, company: ICompany) => {
const isProcessedInfo = processUserInfo(user);
const isProcessedCompany = processCompanyInfo(company);
Expand All @@ -359,9 +361,9 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => {
};

// Info: (20241001 - Liz) 此函數使用 useCallback 封裝,用來非同步取得使用者和公司狀態資訊。
// 它首先檢查是否需要取得使用者資料 (isProfileFetchNeeded),如果不需要,則直接返回
// 當資料獲取中,它會設定載入狀態 (setIsAuthLoading) 並清除公司選擇狀態。
// 當 API 回傳成功且有資料時,它會呼叫 processUserInfo 和 processCompanyInfo 分別處理使用者和公司資訊。
// 它首先檢查是否需要取得使用者資料 (isProfileFetchNeeded),如果不需要,則直接結束
// 當資料獲取中,它會設定載入狀態 (setIsAuthLoading)
// 當 API 回傳成功且有資料時,它會呼叫 handleUserAndCompanyProcessing 分別處理使用者和公司資訊。
// 如果獲取資料失敗,它會執行未登入的處理邏輯: 清除狀態、導向登入頁面、設定登入錯誤狀態、設定錯誤代碼。
// 最後,它會將載入狀態設為完成。
const getStatusInfo = useCallback(async () => {
Expand Down Expand Up @@ -462,6 +464,11 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => {
}
};

// ToDo: (20241009 - Liz) 選擇角色的功能
const selectRole = (roleId: string) => {
setRole(roleId);
};

// Info: (20240513 - Julian) 選擇公司的功能
const selectCompany = async (company: ICompany | null, isPublic = false) => {
setSelectedCompany(null);
Expand Down Expand Up @@ -556,6 +563,8 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => {
isAgreeTermsOfService: isAgreeTermsOfServiceRef.current,
isAgreePrivacyPolicy: isAgreePrivacyPolicyRef.current,
isSignInError: isSignInErrorRef.current,
role: roleRef.current,
selectRole,
selectedCompany: selectedCompanyRef.current,
selectCompany,
successSelectCompany: successSelectCompanyRef.current,
Expand All @@ -570,6 +579,7 @@ export const UserProvider = ({ children }: { children: React.ReactNode }) => {
}),
[
credentialRef.current,
roleRef.current,
selectedCompanyRef.current,
successSelectCompanyRef.current,
errorCodeRef.current,
Expand Down
Loading

0 comments on commit 0f1491b

Please sign in to comment.