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

[ Feature/dev 104 ] 구독관리 - 이메일 시간/요일 , 토글 구독 : mock api 연결 작업 #169

Merged
merged 30 commits into from
Sep 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
133b07d
Init : install react-switch
Happhee Sep 4, 2024
bf94aa5
fix : query name
Happhee Sep 4, 2024
bbd7436
feat : workbook unsubscription query
Happhee Sep 4, 2024
c625580
feat : workbook Email Day and Time query
Happhee Sep 4, 2024
cc2c272
feat : api routes email
Happhee Sep 4, 2024
5dc0bc9
feat : unsubscription workbook query
Happhee Sep 4, 2024
dc512bd
init : install switch component
Happhee Sep 4, 2024
42abe7a
feat : emailInfo with server and client
Happhee Sep 4, 2024
b4790e8
feat : workbook subscription info
Happhee Sep 4, 2024
9f80a80
style : header fix and scroll event
Happhee Sep 4, 2024
20a2e81
style : modify main wrapper style
Happhee Sep 4, 2024
1efe066
feat : subscription management model
Happhee Sep 4, 2024
8ccff05
feat : subscriptionEmail management component
Happhee Sep 4, 2024
8a769fc
feat : email time management dialog
Happhee Sep 4, 2024
b59fce4
feat : email day management component
Happhee Sep 4, 2024
3108642
style : modify lint and component style
Happhee Sep 4, 2024
368c433
feat : subscription management day info component
Happhee Sep 4, 2024
2471ea8
feat : subscription management item component
Happhee Sep 4, 2024
7ff39e5
feat : subscription management list component
Happhee Sep 4, 2024
f32de17
fix : add SubscriptionEmailManagement &SubscriptionManagementList in…
Happhee Sep 4, 2024
8312eb8
feat : subscription email and sub state in msw apiroutes
Happhee Sep 4, 2024
aadb332
feat : useModalWidth Control hooks
Happhee Sep 4, 2024
3063a43
fix : query name
Happhee Sep 4, 2024
8ba65f3
style : workbook card wrapper
Happhee Sep 4, 2024
ea41f7a
test : subscription manage ment model
Happhee Sep 5, 2024
a011400
test : email manage ment menu wit day and time
Happhee Sep 5, 2024
7f26df5
test : subscription management list
Happhee Sep 5, 2024
951c5b4
fix : change to method patch
Happhee Sep 5, 2024
fd94c86
fix : api routes
Happhee Sep 5, 2024
6255093
fix : import subscribeWorkbookQueryOptions metthod
Happhee Sep 5, 2024
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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.1.0",
"@radix-ui/react-tabs": "^1.1.0",
"@radix-ui/react-toast": "^1.1.5",
"@tanstack/react-query": "^5.40.0",
Expand Down
58 changes: 56 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import TopButton from "@common/components/TopButton";
import { Separator } from "@shared/components/ui/separator";

import ArticleCardsWrapper from "@main/components/ArticleCardsWrapper";
import MainHeader from "@main/components/MainHeader";
import WorkbookCardsWrapper from "@main/components/WorkbookCardsWrapper";
import { Separator } from "@shared/components/ui/separator";

import TopButton from "@common/components/TopButton";

export default function MainPage() {
return (
<main className="flex h-auto w-full flex-col">
<main className="relative flex h-auto w-full flex-col overflow-y-auto">
<MainHeader />
<WorkbookCardsWrapper />
<Separator className="h-[20px] bg-background1" />
Expand Down
6 changes: 4 additions & 2 deletions src/common/hooks/useSusbscribeWorkbook.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { toast } from "@shared/components/ui/use-toast";
import { SUBSCRIBE_USER_ACTIONS } from "@subscription/constants/subscribe";
import { subscribeWorkbookOptions } from "@subscription/remotes/postSubscriptionQueryOptions";
import { subscribeWorkbookQueryOptions } from "@subscription/remotes/postSubscriptionQueryOptions";
import { useMutation } from "@tanstack/react-query";

export default function useSusbscribeWorkbook() {
const { mutate: subscribeWorkbook } = useMutation(subscribeWorkbookOptions());
const { mutate: subscribeWorkbook } = useMutation(
subscribeWorkbookQueryOptions(),
);
const postSubscribeWorkbook = ({
workbookId,
handleSucess,
Expand Down
5 changes: 3 additions & 2 deletions src/main/components/DropDownMenuItemList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,16 @@ export function DropDownMenuItemList() {

const MENU_ITEM_LIST = isLogin ? AUTH_LINK : UNAUTH_LINK;
const lastIdx = MENU_ITEM_LIST.length - 1;

return (
<ul className="absolute left-0 top-[66px] z-20 h-screen w-full bg-white">
<ul className="fixed left-0 top-[66px] z-10 h-screen w-full overflow-y-auto bg-white">
{MENU_ITEM_LIST.map(({ title, component }, idx) => (
<li
key={`link-to-${idx}`}
className={cn(
"flex flex-col justify-center",
"sub2-bold min-h-[66px] w-full px-[20px] py-[10px]",
title === "구독 토글 리스트" && "p-0",
title === "구독 관리 제목" && "p-0",
lastIdx !== idx && "border-b-[0.5px] border-text-gray3",
)}
>
Expand Down
3 changes: 2 additions & 1 deletion src/main/components/DropdownMenuWrapper/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { XIcon } from "lucide-react";
import HamburgerMenu from "public/assets/icon/hamburgerMenu.svg";

import { DropDownMenuItemList } from "../DropDownMenuItemList";
import HamburgerMenu from "public/assets/icon/hamburgerMenu.svg";
interface DropdownMenuWrapperProps {
toggleMenu: boolean;
handleToggleMenu: () => void;
Expand Down
85 changes: 85 additions & 0 deletions src/main/components/EmailDayManagementDialog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import React, { useState } from "react";

import { useMutation } from "@tanstack/react-query";

import { Button } from "@shared/components/ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@shared/components/ui/dialog";
import useModalWidthControl from "@shared/hooks/useModalWidthControl";
import { cn } from "@shared/utils/cn";

import { SUBSCRIPTION_EMAIL_CLIENT_INFO } from "@main/constants/emailInfo";
import { SubscriptionManagementModel } from "@main/models/SubscriptionManagementModel";
import { patchWorkbookEmailDayMutationOptions } from "@main/remotes/patchWorkbookEmailDayMutationOptions";
import { SubscriptionEmailClientInfo } from "@main/types/emailInfo";

export default function EmailDayManagementDialog({
day,
}: Pick<SubscriptionEmailClientInfo, "day">) {
const [currentDay, setCurrentDay] = useState(day);
useModalWidthControl();

const { mutate: patchWorkbookEmailDay } = useMutation({
...patchWorkbookEmailDayMutationOptions(),
});

const onClickUpdateWorkbookEmailDay = () => {
patchWorkbookEmailDay({
date: SubscriptionManagementModel.getDayPostInfo({ day: currentDay }),
});
};

return (
<Dialog>
<DialogTrigger className="sub2-medium rounded-lg bg-text-gray3 px-2 py-1">
{SUBSCRIPTION_EMAIL_CLIENT_INFO.DAY[currentDay]}
</DialogTrigger>
<DialogContent className="z-50 w-full max-w-[380px] rounded bg-white">
<DialogHeader>
<DialogTitle className="h3-bold mb-[35px]">
이메일을 받고 싶은 요일을
<br /> 선택해주세요.
</DialogTitle>
<DialogDescription className="flex justify-between">
{Object.keys(SUBSCRIPTION_EMAIL_CLIENT_INFO.DAY).map((key) => {
const currentKey =
key as keyof typeof SUBSCRIPTION_EMAIL_CLIENT_INFO.DAY;
const value = SUBSCRIPTION_EMAIL_CLIENT_INFO.DAY[currentKey];
return (
<Button
className={cn(
"body3-medium bg-white text-text-gray2",
"min-w-[150px] p-[12px]",
"rounded-[10px] border-[1px] border-text-gray2",
"hover:bg-main hover:text-white",
key === currentDay && "bg-main text-white",
)}
key={`email-day-${key}`}
onClick={() => setCurrentDay(currentKey)}
>
{value}
</Button>
);
})}
</DialogDescription>
</DialogHeader>
<DialogFooter>
<DialogClose
className="body3-medium mt-[34px] bg-black py-[12px] text-white"
onClick={onClickUpdateWorkbookEmailDay}
>
완료
</DialogClose>
</DialogFooter>
</DialogContent>
</Dialog>
);
}
103 changes: 103 additions & 0 deletions src/main/components/EmailManagementMenu/EmailManagementMenu.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import { useMutation, useQuery } from "@tanstack/react-query";

import { beforeEach, describe, expect, it } from "vitest";

import QueryClientProviders from "@shared/components/queryClientProvider";
import { createQueryProviderWrapper } from "@shared/constants/createQueryProvider";

import { getSubscriptionWorkbooksQueryOptions } from "@main/remotes/getSubscriptionWorkbooksQueryOptions";
import { patchWorkbookEmailDayMutationOptions } from "@main/remotes/patchWorkbookEmailDayMutationOptions";
import { patchWorkbookEmailTimeMutationOptions } from "@main/remotes/patchWorkbookEmailTimeMutationOptions";

import SubscriptionEmailManagement from ".";
import { render, renderHook, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

describe("이메일 관련 구독 관리 컴포넌트 테스트", () => {
const renderWithClient = () => {
return render(
<QueryClientProviders>
<SubscriptionEmailManagement />
</QueryClientProviders>,
);
};

beforeEach(async () => {
renderWithClient();
const { result } = renderHook(
() =>
useQuery({
...getSubscriptionWorkbooksQueryOptions(),
}),
{ wrapper: createQueryProviderWrapper() },
);
await waitFor(async () => result.current.isLoading);
await waitFor(async () => result.current.isSuccess);
});

it("이메일 시간 변경하기 테스트", async () => {
const { result } = renderHook(
() =>
useMutation({
...patchWorkbookEmailTimeMutationOptions(),
}),
{ wrapper: createQueryProviderWrapper() },
);

const user = userEvent.setup();
const emialTimeButton = screen.getByRole("button", { name: "오전 9시" });

await user.click(emialTimeButton);
const popupHeading = screen.getByRole("heading", {
level: 2,
});

expect(popupHeading).toHaveTextContent("아침에 이메일을 받고 싶은 시간을");

const tenTimeButton = screen.getByRole("button", { name: "10시" });
await user.click(tenTimeButton);

const closeButton = screen.getByRole("button", { name: "완료" });
await user.click(closeButton);

result.current.mutate({ time: "10:00" });
await waitFor(() => expect(result.current.isSuccess).toBeTruthy());

expect(screen.getByRole("button", { name: "오전 10시" }));
});

it("이메일 요일 변경하기 테스트", async () => {
const { result } = renderHook(
() =>
useMutation({
...patchWorkbookEmailDayMutationOptions(),
}),
{ wrapper: createQueryProviderWrapper() },
);

const user = userEvent.setup();
const emialDayButton = screen.getByRole("button", {
name: "매일 받을래요",
});

await user.click(emialDayButton);
const popupHeading = screen.getByRole("heading", {
level: 2,
});

expect(popupHeading).toHaveTextContent("이메일을 받고 싶은 요일을");

const notWeekButton = screen.getByRole("button", {
name: "주말에는 안 받을래요",
});
await user.click(notWeekButton);

const closeButton = screen.getByRole("button", { name: "완료" });
await user.click(closeButton);

result.current.mutate({ date: "0011111" });
await waitFor(() => expect(result.current.isSuccess).toBeTruthy());

Check failure on line 99 in src/main/components/EmailManagementMenu/EmailManagementMenu.test.tsx

View workflow job for this annotation

GitHub Actions / test

src/main/components/EmailManagementMenu/EmailManagementMenu.test.tsx > 이메일 관련 구독 관리 컴포넌트 테스트 > 이메일 요일 변경하기 테스트

AssertionError: expected false to be truthy Ignored nodes: comments, script, style <html> <head /> <body style="" > <div> <section class="flex flex-col" > <article class="flex h-[66px] items-center justify-between py-[10px]" > <p class="sub2-medium" > 이메일 받는 시간 </p> <button aria-controls="radix-:r6:" aria-expanded="false" aria-haspopup="dialog" class="sub2-medium rounded-lg bg-text-gray3 px-2 py-1" data-state="closed" type="button" > 오전 9 시 </button> </article> <article class="flex h-[66px] items-center justify-between py-[10px]" > <p class="sub2-medium" > 이메일 받는 요일 </p> <button aria-controls="radix-:r9:" aria-expanded="false" aria-haspopup="dialog" class="sub2-medium rounded-lg bg-text-gray3 px-2 py-1" data-state="closed" type="button" > 주말에는 안 받을래요 </button> </article> </section> </div> <div /> <div /> </body> </html> ❯ src/main/components/EmailManagementMenu/EmailManagementMenu.test.tsx:99:58 ❯ runWithExpensiveErrorDiagnosticsDisabled node_modules/.pnpm/@testing-library[email protected]/node_modules/@testing-library/dom/dist/config.js:47:12 ❯ checkCallback node_modules/.pnpm/@testing-library[email protected]/node_modules/@testing-library/dom/dist/wait-for.js:124:77 ❯ Timeout.checkRealTimersCallback node_modules/.pnpm/@testing-library[email protected]/node_modules/@testing-library/dom/dist/wait-for.js:118:16

expect(screen.getByRole("button", { name: "주말에는 안 받을래요" }));
});
});
38 changes: 38 additions & 0 deletions src/main/components/EmailManagementMenu/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from "react";

import { useQuery } from "@tanstack/react-query";

import { SubscriptionManagementModel } from "@main/models/SubscriptionManagementModel";
import { getSubscriptionWorkbooksQueryOptions } from "@main/remotes/getSubscriptionWorkbooksQueryOptions";

import EmailDayManagementDialog from "../EmailDayManagementDialog";
import EmailTimeManagementDialog from "../EmailTimeManagementDialog";

export default function SubscriptionEmailManagement() {
const { data } = useQuery({
...getSubscriptionWorkbooksQueryOptions(),
select: ({ data }) => {
const subscriptionManagementModel = new SubscriptionManagementModel({
initSubscriptionManagementServerList: data.data.workbooks,
});
return subscriptionManagementModel.SubscriptionEmailManagementClientInfo;
},
});

return (
<section className="flex flex-col">
{data && (
<>
<article className="flex h-[66px] items-center justify-between py-[10px]">
<p className="sub2-medium">이메일 받는 시간</p>
<EmailTimeManagementDialog {...data} />
</article>
<article className="flex h-[66px] items-center justify-between py-[10px]">
<p className="sub2-medium">이메일 받는 요일</p>
<EmailDayManagementDialog {...data} />
</article>
</>
)}
</section>
);
}
Loading
Loading