Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: 초대링크를 통한 가입시 storeId 받아올 수 있게 로직 변경 #98

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
27 changes: 27 additions & 0 deletions src/apis/dynamodb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { InviteSchedule } from "@/data/inviteSchedule";
import axios from "axios";

export interface InviteResponse {
id: string;
inviteData: InviteDataType;
}
interface InviteDataType {
storeId: string;
position: string;
schedule: InviteSchedule;
createdAt: string;
}

async function getInviteData(inviteDataId: string) {
const { data } = await axios.get<InviteResponse>(
`/api/dynamoDB?id=${inviteDataId}`,
);
return data;
}

async function postInviteData(body: InviteResponse) {
const { data } = await axios.post("/api/dynamoDB", body);
return data;
}

export { getInviteData, postInviteData };
29 changes: 29 additions & 0 deletions src/hooks/query/dynamodb.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { InviteResponse, getInviteData, postInviteData } from "@/apis/dynamodb";
import { myAtom } from "@/data/global";
import { copyLink } from "@/libs/copy";
import { useMutation, useQuery } from "@tanstack/react-query";
import { useAtom } from "jotai";

function useGetInviteData() {
const [my] = useAtom(myAtom);
const inviteId = localStorage.getItem("inviteDataId");
const { data, isSuccess } = useQuery({
queryKey: ["getInviteData"],
queryFn: () => getInviteData(inviteId as string),
enabled: !(my?.id === undefined || my?.id === null || inviteId === null),
});

return { data, isSuccess };
}

function usePostInviteData(inviteId: string) {
const { mutate, isSuccess } = useMutation({
mutationKey: ["getInviteData"],
mutationFn: (body: InviteResponse) => postInviteData(body),
onSuccess: () => copyLink(inviteId),
});

return { mutate, isSuccess };
}

export { useGetInviteData, usePostInviteData };
37 changes: 34 additions & 3 deletions src/hooks/query/relation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import {
import { storeIdAtom } from "@/data/global";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { useAtom } from "jotai";
import { useRouter } from "next/router";
import { InviteSchedule } from "@/data/inviteSchedule";
import { usePostPlanList } from "./plan";
import { useGetMyQueryKey } from "./my";

interface UsePostRelationProps {
storeId: string;
Expand All @@ -35,12 +39,12 @@ function useGetRelationList() {
}

function usePostRelation() {
const { mutate, isSuccess } = useMutation({
const { mutateAsync } = useMutation({
mutationKey: ["postRelationMutate"],
mutationFn: ({ storeId, memberId, body }: UsePostRelationProps) =>
mutationFn: async ({ storeId, memberId, body }: UsePostRelationProps) =>
postRelation(storeId, memberId, body),
});
return { mutate, isSuccess };
return { mutateAsync };
}

function usePostRelationAdmin() {
Expand All @@ -64,9 +68,36 @@ function usePostRelationAdmin() {
return { mutate };
}

function useStaffJoin() {
const { mutateAsync: postRelationMutate } = usePostRelation();
const { mutate: postPlanListMutate } = usePostPlanList();
const queryClient = useQueryClient();
const router = useRouter();

const { mutate } = useMutation({
mutationKey: ["StaffJoin"],
mutationFn: async ({
storeId,
memberId,
body,
inviteSchedule,
}: UsePostRelationProps & { inviteSchedule: InviteSchedule }) => {
await postRelationMutate({ storeId, memberId, body });
postPlanListMutate({ storeId, memberId, inviteSchedule });
Comment on lines +72 to +86
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mutateAsync라는게 있었네요.. 이걸 알았으면 더 빨리 되었을것 같습니다.
postPlanListMutate도 await 걸 수 있을거 같아요

},
onSuccess: async () => {
await queryClient.invalidateQueries({ queryKey: [useGetMyQueryKey] });
localStorage.removeItem("inviteDataId");
router.push("/main");
},
});
return { mutate };
}

export {
useGetRelation,
useGetRelationList,
usePostRelation,
usePostRelationAdmin,
useStaffJoin,
};
20 changes: 12 additions & 8 deletions src/libs/copy.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
export default function copy(
text: string,
onSuccess?: () => void,
onError?: (err: Error) => void,
) {
const copy = (text: string, onSuccess?: () => void) => {
if (navigator.clipboard) {
// (크롬 66버전 이상일때만 사용 가능)
navigator.clipboard.writeText(text).then(onSuccess).catch(onError);
navigator.clipboard
.writeText(text)
.then(onSuccess)
.catch(error => console.log("링크를 복사하는데 실패했습니다: ", error));
} else {
if (!document.queryCommandSupported("copy")) {
onError && onError(new Error("복사하기가 지원되지 않는 브라우저입니다."));
console.log("복사하기가 지원되지 않는 브라우저입니다.");
return;
}
const textarea = document.createElement("textarea");
Expand All @@ -26,4 +25,9 @@ export default function copy(
document.body.removeChild(textarea);
onSuccess && onSuccess();
}
}
};

export const copyLink = (inviteId: string, onSuccess?: () => void) => {
const link = `${window.location.origin}/?id=${inviteId}`;
copy(link, onSuccess);
};
74 changes: 28 additions & 46 deletions src/pages/oauth/redirect.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,42 @@
import { PostRelationBody } from "@/apis/relation";
import { myAtom } from "@/data/global";
import { usePostPlanList } from "@/hooks/query/plan";
import { usePostRelation } from "@/hooks/query/relation";
import { InviteResponse, InviteDataType } from "@/screen/manage/ShareLink";
import axios from "axios";
import { useGetInviteData } from "@/hooks/query/dynamodb";
import { useStaffJoin } from "@/hooks/query/relation";
import { useAtom } from "jotai";
import { useRouter } from "next/router";
import { useEffect } from "react";

export default function Redirect() {
const { push } = useRouter();
const router = useRouter();

const [my] = useAtom(myAtom);
const { mutate: postRelationMutate } = usePostRelation();
const { mutate: postPlanListMutate } = usePostPlanList();

async function getInviteData(inviteDataId: string) {
const response = await axios.get<InviteResponse>(
`/api/dynamoDB?id=${inviteDataId}`,
);
return response.data;
}
const createNewEmployee = (inviteData: InviteDataType, memberId: string) => {
const body: PostRelationBody = {
role: "STAFF",
position: inviteData.position,
};
postRelationMutate(
{ storeId: inviteData.storeId, memberId: my?.id as string, body },
{
onSuccess: () =>
postPlanListMutate({
storeId: inviteData.storeId,
memberId,
inviteSchedule: inviteData.schedule,
}),
onError: () => console.log("fail"),
},
);
};
const { data: inviteResponse, isSuccess } = useGetInviteData();
const { mutate: staffJoinMutate } = useStaffJoin();

useEffect(() => {
if (my?.id === undefined || my?.id === null) return;
if (localStorage.getItem("inviteDataId") !== null) {
const inviteDataId = String(localStorage.getItem("inviteDataId"));
getInviteData(inviteDataId)
.then(data => {
createNewEmployee(data.inviteData, my?.id);
localStorage.removeItem("inviteDataId");
push("/main");
})
.catch(() => {
push("/main");
});
const inviteId = localStorage.getItem("inviteDataId");
if (inviteId !== null) {
// 1. 직원초대링크를 통해 들어온 새 직원
if (isSuccess && inviteResponse) {
const body: PostRelationBody = {
role: "STAFF",
position: inviteResponse.inviteData.position,
};
const inviteRequestBody = {
storeId: inviteResponse.inviteData.storeId,
memberId: my?.id as string,
body,
inviteSchedule: inviteResponse.inviteData.schedule,
};
staffJoinMutate(inviteRequestBody);
}
} else if (my?.relationList.length === 0) {
push("/signup");
// 2. 회원가입
router.push("/signup");
} else {
push("/main");
// 3. 기존회원 로그인
router.push("/main");
}
}, [my]);
}, [isSuccess]);
}
79 changes: 32 additions & 47 deletions src/screen/manage/ShareLink.tsx
Original file line number Diff line number Diff line change
@@ -1,74 +1,60 @@
import { storeIdAtom } from "@/data/global";
import {
InviteSchedule,
inviteScheduleAtom,
selectedPositionAtom,
} from "@/data/inviteSchedule";
import copy from "@/libs/copy";
import { usePostInviteData } from "@/hooks/query/dynamodb";
import { copyLink } from "@/libs/copy";
import { createRandomString } from "@/libs/createRandomId";
import FlexBox from "@modules/layout/FlexBox";
import axios from "axios";
import dayjs from "dayjs";
import { useAtom } from "jotai";
import Image from "next/image";
import { useEffect, useState } from "react";

export interface InviteResponse {
id: string;
inviteData: InviteDataType;
}

interface InviteDataType {
storeId: string;
position: string;
schedule: InviteSchedule;
createdAt: string;
}

function ShareLink() {
const [inviteId, setInviteId] = useState<string>("");
const [linkCopied, setLinkCopied] = useState(false);
const [showToastMsg, setShowToastMsg] = useState<boolean>(false);
const [inviteSchedule] = useAtom(inviteScheduleAtom);
const [selectedPosition] = useAtom(selectedPositionAtom);
const [storeId] = useAtom(storeIdAtom);

const { mutate, isSuccess } = usePostInviteData(inviteId);

if (!inviteId) setInviteId(createRandomString(8));

const handleCopyLink = () => {
const link = `${window.location.origin}/?id=${inviteId}`;
copy(
link,
() => {
setLinkCopied(true);
},
err => {
console.log("링크를 복사하는데 실패했습니다: ", err);
},
);
copyLink(inviteId, () => setLinkCopied(true));
};

const sendInviteToDB = async () => {
const inviteData: InviteDataType = {
storeId,
position: selectedPosition,
schedule: inviteSchedule,
createdAt: dayjs().format("YYYY-MM-DD HH:mm:ss"),
};
const data = {
id: inviteId,
inviteData,
};
try {
await axios.post("/api/dynamoDB", data);
handleCopyLink();
} catch (error) {
alert("초대링크 생성에 실패했습니다.");
useEffect(() => {
let timer: NodeJS.Timeout | undefined;
if (isSuccess || linkCopied) {
setShowToastMsg(true);
timer = setTimeout(() => {
setShowToastMsg(false);
}, 2000);
}
};
return () => {
if (timer) clearTimeout(timer);
};
}, [isSuccess, linkCopied]);

useEffect(() => {
sendInviteToDB();
}, []);
if (inviteId.length > 0) {
const inviteData = {
id: inviteId,
inviteData: {
storeId,
position: selectedPosition,
schedule: inviteSchedule,
createdAt: dayjs().format("YYYY-MM-DD HH:mm:ss"),
},
};
mutate(inviteData);
}
}, [inviteId]);

return (
<>
Expand All @@ -91,15 +77,15 @@ function ShareLink() {
<div className="B1-medium text-Gray5 mt-4">
링크복사가 안되었나요?
</div>
<button onClick={() => handleCopyLink()} type="button">
<button onClick={handleCopyLink} type="button">
<FlexBox direction="row">
<div className="B4-regular text-Gray4 underline">링크 복사</div>
<div className="B4-regular text-Gray4">하기</div>
</FlexBox>
</button>
</FlexBox>
</FlexBox>
{linkCopied && (
{showToastMsg && (
<div className="w-full B5-regular px-4 py-4 mb-4 bg-[#2D2D2D] text-white">
<p className="mb-4">링크가 자동으로 복사되었습니다.</p>
</div>
Expand All @@ -109,4 +95,3 @@ function ShareLink() {
}

export default ShareLink;
export type { InviteDataType };
Loading