Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions src/components/dashboard/modal/DashboardInviteModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Input from '@/components/common/input/Input';
import FormModal from '@/components/common/modal/FormModal';
import { INVITE } from '@/constants/modalName';
import { useModal } from '@/hooks/useModal';
import { validateEmail } from '@/utils/validation';
import { validateEmail, validateInvitation } from '@/utils/validation';

interface DashboardInviteModalProps {
inviteeEmail: string;
Expand All @@ -13,6 +13,7 @@ interface DashboardInviteModalProps {
setErrorMsg: React.Dispatch<React.SetStateAction<string>>;
apiErrorMsg: string;
onSubmit: () => Promise<void>;
dashboardId: string;
}

export default function DashboardInviteModal({
Expand All @@ -22,6 +23,7 @@ export default function DashboardInviteModal({
setErrorMsg,
apiErrorMsg,
onSubmit,
dashboardId,
}: DashboardInviteModalProps) {
const { handleModalClose } = useModal(INVITE);

Expand All @@ -34,18 +36,24 @@ export default function DashboardInviteModal({

const handleChange = (value: string) => {
setInviteeEmail(value);

if (errorMsg) {
setErrorMsg('');
}
};

const handleBlur = () => {
if (validateInvitation(inviteeEmail + dashboardId)) {
setErrorMsg(() => validateInvitation(inviteeEmail + dashboardId));
return;
}
const message = validateEmail(inviteeEmail);
setErrorMsg(message);
};

const disabled = inviteeEmail.trim() === '' || validateEmail(inviteeEmail) !== '';
const disabled =
inviteeEmail.trim() === ''
|| validateEmail(inviteeEmail) !== ''
|| validateInvitation(inviteeEmail + dashboardId) !== '';

return (
<FormModal closeBtn modalName={INVITE}>
Expand Down
38 changes: 16 additions & 22 deletions src/components/editpage/InvitesEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,14 @@ export default function InvitesEdit() {
const cancelMutation = useMutation<unknown, DeleteInvitationParams>({
mutationFn: ({ dashboardId: id, invitationId }) =>
deleteInvitationdata(Number(id), invitationId),
onSuccess: () => {
onSuccess: (_, value: DeleteInvitationParams) => {
const invitation = invitations.find(
(inv) => inv.id.toString() === value.invitationId.toString()
);
if (invitation) {
const inviteeEmail = invitation?.invitee?.email;
localStorage.removeItem(inviteeEmail + dashboardId);
}
setDeleteMessage('초대 취소가 완료되었습니다.');
openCancelModal();
refetch();
Expand All @@ -85,27 +92,13 @@ export default function InvitesEdit() {
}, [inviteData?.totalCount]);

const isNextDisabled = currentPage >= calculatedTotalPages;
const invitations: Invitation[] = useMemo(() => inviteData?.invitations || [], [inviteData]);

const numericDashboardId: number | null = useMemo(() => {
if (dashboardId) {
const numId = Number(dashboardId);
if (!isNaN(numId)) {
return numId;
}
}
return null;
}, [dashboardId]);

if (!dashboardId) {
if (!inviteData) {
return null;
}
const invitations: Invitation[] = inviteData?.invitations;

if (numericDashboardId === null) {
return <div>유효하지 않은 대시보드 ID입니다.</div>;
}

if (!inviteData) {
if (!dashboardId) {
return null;
}

Expand All @@ -124,7 +117,7 @@ export default function InvitesEdit() {
}

try {
const resData = await inviteDashboard(dashboardId, { email: inviteeEmail });
const resData = await inviteDashboard(dashboardId.toString(), { email: inviteeEmail });

setCompletedInviteeUser(resData.invitee.nickname);
openBaseModal();
Expand Down Expand Up @@ -157,18 +150,18 @@ export default function InvitesEdit() {
type='InvitesItem'
email={invitation.invitee.email}
id={invitation.id}
onCancel={() => handleCancel(numericDashboardId, invitation.id)}>
onCancel={() => handleCancel(+dashboardId, invitation.id)}>
<DashboardItem.Content
type='InvitesItem'
email={invitation.invitee.email}
id={invitation.id}
onCancel={() => handleCancel(numericDashboardId, invitation.id)}
onCancel={() => handleCancel(+dashboardId, invitation.id)}
/>
<DashboardItem.Action
type='InvitesItem'
email={invitation.invitee.email}
id={invitation.id}
onCancel={() => handleCancel(numericDashboardId, invitation.id)}
onCancel={() => handleCancel(+dashboardId, invitation.id)}
/>
</DashboardItem>
));
Expand Down Expand Up @@ -227,6 +220,7 @@ export default function InvitesEdit() {
setErrorMsg={setInputErrorMsg}
onSubmit={handleInviteSubmit}
apiErrorMsg={apiErrorMsg}
dashboardId={dashboardId}
/>
)}

Expand Down
2 changes: 2 additions & 0 deletions src/constants/invitation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/**초대된 이메일 **/
export const REQUESTED_EMAIL = 'requestedEmail';
4 changes: 3 additions & 1 deletion src/pages/DetailLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import { useState } from 'react';
import { Outlet, useParams } from 'react-router';
import BaseModalFrame from '@/components/common/modal/BaseModalFrame';
import DashboardInviteModal from '@/components/dashboard/modal/DashboardInviteModal';
import { REQUESTED_EMAIL } from '@/constants/invitation';
import { INVITE } from '@/constants/modalName';
import useBaseModal from '@/hooks/useBaseModal';
import { useModal } from '@/hooks/useModal';
import { inviteDashboard } from '@/lib/apis/Invitations';

export default function DetailLayout() {
const { dashboardId } = useParams();
const {
Expand All @@ -34,6 +34,7 @@ export default function DetailLayout() {
setCompletedInviteeUser(resData.invitee.nickname);
openBaseModal();
closeInviteModal();
localStorage.setItem(inviteeEmail + dashboardId, REQUESTED_EMAIL);
} catch (err) {
if (axios.isAxiosError(err)) {
setApiErrorMsg(err.response?.data?.message ?? '오류가 발생했습니다.');
Expand All @@ -52,6 +53,7 @@ export default function DetailLayout() {
setErrorMsg={setInputErrorMsg}
onSubmit={handleInviteSubmit}
apiErrorMsg={apiErrorMsg}
dashboardId={dashboardId}
/>
)}
{baseModalIsOpen && (
Expand Down
7 changes: 6 additions & 1 deletion src/utils/validation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { EMAIL_REGEX, PASSWORD_MIN_LEN, NICKNAME_MAX_LEN } from '@/constants/authRegex';

import { REQUESTED_EMAIL } from '@/constants/invitation';
export const validateEmail = (value: string) => {
return EMAIL_REGEX.test(value) ? '' : '이메일 형식으로 작성해 주세요.';
};
Expand All @@ -18,9 +18,14 @@ export const validateNickname = (value: string) => {
return value.length <= NICKNAME_MAX_LEN ? '' : `${NICKNAME_MAX_LEN}자 이하로 작성해주세요.`;
};

export const validateInvitation = (value: string) => {
return localStorage.getItem(value) === REQUESTED_EMAIL ? '이미 요청한 이메일입니다.' : '';
};

export const validators: Record<string, (v: string) => string> = {
email: validateEmail,
password: validatePassword,
newPassword: validateNewPassword,
nickname: validateNickname,
invitation: validateInvitation,
};