setCategories((prev) => ({ ...prev, bitcoinPrediction: !prev.bitcoinPrediction }))}
+ {/* 제목 영역 */}
+
+
알림 서비스 구독
+
+ 투자에 도움이 될만한 정보들을 로그인 없이 메일로 받아보세요.
+
+
+ {/* 키워드 영역 */}
+
+
+ 관심키워드
+ * 관심키워드 설정은 최대 3개입니다.
+
+
+ {keywordList.map((keyword, index) => (
+ handleAddkeyword({ index, keyword })}
+ onChange={(e) =>
+ handleChangekeyword({
+ index,
+ keyword: (e.target as HTMLInputElement).value,
+ })
+ }
+ onKeyUp={(e) => {
+ if (e.key === "Enter") {
+ handleAddkeyword({ index, keyword });
+ }
+ }}
+ onBlur={() => handleAddkeyword({ index, keyword })}
+ key={index}
+ closable={true}
+ inputable={keyword.inputable}
+ maxLength={10}
+ />
+ ))}
+
+
+ {/* 이메일 인증 영역 */}
+
+
+
+
+
-
+
+
+
+ setVerifyEmailNum(e.target.value)}
+ disabled={!verifySendCheck}
/>
+
-
-
-
+
-
- {/* 이메일 입력 및 인증 */}
-
- 이메일 인증
-
-
-
-
- {verifySendCheck ? "발송됨" : "인증 요청"}
-
+ {/* 이메일 동의 및 구독 영역 */}
+
+
+ {verifyCheckBox.map((item) => {
+ return (
+
handleChecked(item)}
+ >
+ {item.checked ? (
+

+ ) : (
+

+ )}
+
{item.label}
+
+ );
+ })}
+
+
+
+ );
+};
- {verifySendCheck && (
-
- setVerifyEmailNum(e.target.value)}
- maxLength={6}
- css={css`
- flex: 1;
- padding: 1rem;
- border: 1px solid ${DESIGN_SYSTEM_COLOR.GRAY_300};
- border-radius: 0.8rem;
- font-size: 1.4rem;
- `}
- disabled={verifyEmailNumCheck}
- />
-
- {verifyEmailNumCheck ? "인증 완료" : "인증하기"}
-
-
- )}
-
+const keywordWrapper = {
+ container: css`
+ flex-direction: column;
+ row-gap: 12px;
+ display: flex;
+ background-color: var(--gray-5);
+ border-radius: 8px;
+ padding: 16px;
+ margin-top: 24px;
+ `,
+ descriptionContainer: css`
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ column-gap: 8px;
-
-
-
-
-
-
- );
+const emailWrapper = {
+ container: css`
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ margin-top: 32px;
+ row-gap: 12px;
+ `,
+ titleContainer: css`
+ display: flex;
+ flex-direction: row;
+
+ & > span {
+ font-size: 14px;
+ font-weight: 400;
+ color: var(--text-body1);
+ }
+
+ > #circle {
+ margin-top: 5px;
+ background-color: var(--red-50);
+ width: 3px;
+ height: 3px;
+ border-radius: 100%;
+ }
+ `,
+ emailFormContainer: css`
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ column-gap: 12px;
+ `,
+ certificationContainer: css`
+ display: flex;
+ flex-direction: column;
+ width: 100%;
+ row-gap: 8px;
+
+ span {
+ font-size: 12px;
+ }
+ `,
+ certificationWrapper: css`
+ position: relative;
+ width: 100%;
+ display: flex;
+ align-items: center;
+
+ > button {
+ position: absolute;
+ right: 0;
+ font-size: 15px;
+ color: var(--blue-50);
+ background-color: transparent;
+ border: none;
+ margin-right: 16px;
+
+ &:disabled {
+ color: var(--text-disabled);
+ }
+
+ &:focus {
+ outline: none;
+ }
+ }
+ `,
+ messageWrapper: ({ verifyDescription }: { verifyDescription: string }) => css`
+ display: flex;
+ flex-direction: column;
+ text-align: left;
+ ${verifyDescription === "error" && "color: var(--red-50);"}
+ ${verifyDescription === "success" && "color: var(--blue-50);"}
+ `,
+};
+
+const footerWrapper = {
+ container: css`
+ width: 100%;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-top: 32px;
+ row-gap: 12px;
+ `,
+ checkbox__container: css`
+ display: flex;
+ column-gap: 24px;
+ cursor: pointer;
+ `,
+ checkbox__wrapper: css`
+ display: flex;
+ align-items: center;
+ color: var(--text-body1);
+ `,
};
diff --git a/src/hooks/api/subscribe/useApiSendSubscribe.ts b/src/hooks/api/subscribe/useApiSendSubscribe.ts
index 1e9de47..296fc63 100644
--- a/src/hooks/api/subscribe/useApiSendSubscribe.ts
+++ b/src/hooks/api/subscribe/useApiSendSubscribe.ts
@@ -2,12 +2,15 @@ import { api } from "@/api";
interface sendSubscribeEmail {
email: string;
+ keywords: string[];
}
-export const sendSubscribeEmail = ({ email }: sendSubscribeEmail) => {
+
+// TODO: 이메일 구독 요청 API 훅 구조로 변경하기
+export const sendSubscribeEmail = ({ email, keywords }: sendSubscribeEmail) => {
const res = api.post(`/user-service/api/v1/subscribers/subscribe`, {
- email: email,
+ email,
+ keywords,
});
return res;
};
-
diff --git a/src/style/variable.scss b/src/style/variable.scss
index dccbb25..c14f5ef 100644
--- a/src/style/variable.scss
+++ b/src/style/variable.scss
@@ -17,7 +17,7 @@
--text-body1: #2d2d2d;
--text-body2: #555555;
--text-caption: #8e8e8e;
- --text-disabled: #8e8e8e;
+ --text-disabled: #c6c6c6;
// line color token
--border-black: #1d1d1d;
diff --git a/src/types/modal.ts b/src/types/modal.ts
index 6b4983e..b611baa 100644
--- a/src/types/modal.ts
+++ b/src/types/modal.ts
@@ -1,7 +1,7 @@
export type ModalType = {
isOpen: boolean;
isVisibleBtn?: boolean;
- title: string;
+ title?: string;
content: JSX.Element | string;
callBack?: () => void;
};
diff --git a/src/utils/dateUtil.ts b/src/utils/dateUtil.ts
new file mode 100644
index 0000000..ff78a27
--- /dev/null
+++ b/src/utils/dateUtil.ts
@@ -0,0 +1,7 @@
+export default {
+ formatTime: (seconds: number): string => {
+ const minutes = Math.floor(seconds / 60);
+ const remainingSeconds = seconds % 60;
+ return `${minutes.toString().padStart(2, "0")}:${remainingSeconds.toString().padStart(2, "0")}`;
+ },
+};