-
Notifications
You must be signed in to change notification settings - Fork 1
Feat(onboarding): 온보딩 회원가입 api 연결 #86
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
Changes from all commits
78b0308
1e6bc1a
19b0081
205b66f
7dd8a8c
9ddf810
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,8 +6,10 @@ import AlarmStep from './step/AlarmStep'; | |
| import MacStep from './step/MacStep'; | ||
| import FinalStep from './step/FinalStep'; | ||
| import { cva } from 'class-variance-authority'; | ||
| import { usePostSignUp } from '@shared/apis/queries'; | ||
| const stepProgress = [{ progress: 30 }, { progress: 60 }, { progress: 100 }]; | ||
|
|
||
| import { AlarmsType } from '@constants/alarms'; | ||
| import { normalizeTime } from '@pages/onBoarding/utils/formatRemindTime'; | ||
| const variants = { | ||
| slideIn: (direction: number) => ({ | ||
| x: direction > 0 ? 200 : -200, | ||
|
|
@@ -36,6 +38,8 @@ const MainCard = () => { | |
| const [direction, setDirection] = useState(0); | ||
| const [alarmSelected, setAlarmSelected] = useState<1 | 2 | 3>(1); | ||
| const [isMac, setIsMac] = useState(false); | ||
| // api 구간 | ||
| const {mutate:postSignData} = usePostSignUp(); | ||
|
|
||
| useEffect(() => { | ||
| const ua = navigator.userAgent.toLowerCase(); | ||
|
|
@@ -62,15 +66,33 @@ const MainCard = () => { | |
| } | ||
| }; | ||
|
|
||
| const [remindTime, setRemindTime] = useState('09:00'); | ||
| const nextStep = () => { | ||
| console.log(step) | ||
| if (step === 3) { | ||
| // 이거 이후에 api 붙일 자리 표시임! console.log('선택된 알람:', AlarmsType[alarmSelected - 1].time); | ||
| // 이거 이후에 api 붙일 자리 표시임! | ||
|
|
||
| } | ||
| if (step < 5) { | ||
| setDirection(1); | ||
| setStep((prev) => prev + 1); | ||
| } else if (step === 5) { | ||
| window.location.href = '/'; | ||
| const raw = AlarmsType[alarmSelected - 1].time; | ||
| setRemindTime(normalizeTime(raw)); | ||
|
|
||
| postSignData({ | ||
| "email": "tesdfdfsst@gmail.com", | ||
| "remindDefault": remindTime, | ||
| "fcmToken": "adlfdjlajlkadfsjlkfdsdfsdfsdfsdfsa" | ||
| }, | ||
|
Comment on lines
+83
to
+87
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. key에 string으로 저렇게 작성해도 잘 동작하나요??
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵네! 첫 회원가입 로직이라서, |
||
| { | ||
| onSuccess:()=>{ | ||
| window.location.href = '/'; | ||
| } | ||
| } | ||
| ) | ||
|
|
||
|
|
||
| } | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,26 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export function normalizeTime(input: string): string { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let hours = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| let minutes = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const ampmMatch = input.match(/(AM|PM)\s?(\d{1,2}):(\d{1,2})/i); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (ampmMatch) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [, ampm, h, m] = ampmMatch; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hours = parseInt(h, 10); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| minutes = parseInt(m, 10); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (ampm.toUpperCase() === "PM" && hours < 12) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hours += 12; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (ampm.toUpperCase() === "AM" && hours === 12) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hours = 0; // 12 AM → 00시 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [h, m] = input.split(":"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hours = parseInt(h, 10); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| minutes = parseInt(m, 10); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const hh = String(hours).padStart(2, "0"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const mm = String(minutes).padStart(2, "0"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return `${hh}:${mm}`; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+26
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion 한글(오전/오후) 포맷 미지원으로 NaN:NaN 발생 가능 현재 아래처럼 다국어 포맷을 안전하게 처리하는 방향을 제안합니다. -export function normalizeTime(input: string): string {
- let hours = 0;
- let minutes = 0;
-
- const ampmMatch = input.match(/(AM|PM)\s?(\d{1,2}):(\d{1,2})/i);
- if (ampmMatch) {
- const [, ampm, h, m] = ampmMatch;
- hours = parseInt(h, 10);
- minutes = parseInt(m, 10);
-
- if (ampm.toUpperCase() === "PM" && hours < 12) {
- hours += 12;
- }
- if (ampm.toUpperCase() === "AM" && hours === 12) {
- hours = 0; // 12 AM → 00시
- }
- } else {
- const [h, m] = input.split(":");
- hours = parseInt(h, 10);
- minutes = parseInt(m, 10);
- }
-
- const hh = String(hours).padStart(2, "0");
- const mm = String(minutes).padStart(2, "0");
- return `${hh}:${mm}`;
-}
+export function normalizeTime(input: string): string {
+ const fallback = '09:00';
+ if (!input || typeof input !== 'string') return fallback;
+ const s = input.trim();
+
+ // 1) AM/PM 앞: "AM 9:05", "PM 12:00"
+ const ampmFront = s.match(/^(AM|PM)\s*(\d{1,2})(?::(\d{1,2}))?$/i);
+ // 2) AM/PM 뒤: "9:05 AM", "12 PM"
+ const ampmBack = s.match(/^(\d{1,2})(?::(\d{1,2}))?\s*(AM|PM)$/i);
+ // 3) 한글: "오전 9시", "오후 8시", "오전 9시 5분"
+ const kor = s.match(/^(오전|오후)\s*(\d{1,2})\s*시(?:\s*(\d{1,2})\s*분)?$/);
+ // 4) 24시간: "09:00", "9:5"
+ const h24 = s.match(/^(\d{1,2})(?::(\d{1,2}))$/);
+
+ let hours: number | null = null;
+ let minutes: number | null = null;
+ let meridiem: 'AM' | 'PM' | null = null;
+
+ if (ampmFront) {
+ const [, ampm, h, m] = ampmFront;
+ hours = parseInt(h!, 10);
+ minutes = m ? parseInt(m, 10) : 0;
+ meridiem = ampm.toUpperCase() as 'AM' | 'PM';
+ } else if (ampmBack) {
+ const [, h, m, ampm] = ampmBack;
+ hours = parseInt(h!, 10);
+ minutes = m ? parseInt(m, 10) : 0;
+ meridiem = ampm.toUpperCase() as 'AM' | 'PM';
+ } else if (kor) {
+ const [, ap, h, m] = kor;
+ hours = parseInt(h!, 10);
+ minutes = m ? parseInt(m, 10) : 0;
+ meridiem = ap === '오후' ? 'PM' : 'AM';
+ } else if (h24) {
+ const [, h, m] = h24;
+ hours = parseInt(h!, 10);
+ minutes = parseInt(m!, 10);
+ }
+
+ if (hours === null || minutes === null || Number.isNaN(hours) || Number.isNaN(minutes)) {
+ return fallback;
+ }
+
+ if (meridiem) {
+ if (meridiem === 'PM' && hours < 12) hours += 12;
+ if (meridiem === 'AM' && hours === 12) hours = 0;
+ }
+
+ if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) return fallback;
+
+ const hh = String(hours).padStart(2, '0');
+ const mm = String(minutes).padStart(2, '0');
+ return `${hh}:${mm}`;
+}추가로 간단한 유닛 테스트(예: '오전 9시'→'09:00', '오후 8시'→'20:00', 'AM 9:05'→'09:05', 빈 문자열→'09:00')도 부탁드립니다. 원하시면 테스트 템플릿을 바로 드리겠습니다. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,5 @@ | ||
| import { useMutation, useQuery, UseQueryResult } from '@tanstack/react-query'; | ||
| import { getDashboardCategories, postCategory } from '@shared/apis/axios'; | ||
| import { getDashboardCategories, postCategory, postSignUp, postSignUpRequest } from '@shared/apis/axios'; | ||
| import { AxiosError } from 'axios'; | ||
| import { DashboardCategoriesResponse, AcornsResponse } from '@shared/types/api'; | ||
| import { getAcorns } from './axios'; | ||
|
|
@@ -26,3 +26,21 @@ export const useGetArcons = (): UseQueryResult<AcornsResponse, AxiosError> => { | |
| queryFn: () => getAcorns(), | ||
| }); | ||
| }; | ||
|
|
||
| export const usePostSignUp = () => { | ||
| return useMutation({ | ||
| mutationFn: (data: postSignUpRequest) => postSignUp(data), | ||
| onSuccess: (data) => { | ||
|
Comment on lines
+30
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion useMutation 제네릭 지정으로 응답 스키마 고정 및 안전성 확보 현재 추가 타입(파일 상단 임의 위치): type SignUpResponse = { token: string };선택 라인 변경: -export const usePostSignUp = () => {
- return useMutation({
- mutationFn: (data: postSignUpRequest) => postSignUp(data),
- onSuccess: (data) => {
+export const usePostSignUp = () => {
+ return useMutation<SignUpResponse, AxiosError, postSignUpRequest>({
+ mutationFn: (payload) => postSignUp(payload),
+ onSuccess: (resp) => {🤖 Prompt for AI Agents |
||
| const newToken = data?.data?.token || data?.token; | ||
|
|
||
| if (newToken) { | ||
| localStorage.setItem("token", newToken); | ||
| } | ||
|
|
||
| console.log("회원가입 성공:", data); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 불필요한 콘솔은 이후에 제거! |
||
| }, | ||
| onError: (error) => { | ||
| console.error("회원가입 실패:", error); | ||
| }, | ||
| }); | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
중복 제출 방지: 로딩 상태 처리 및 버튼 비활성화
useMutation의isPending을 사용해 전송 중 중복 클릭을 막아주세요.적용 제안(diff 1/2):
적용 제안(diff 2/2 — 파일 하단 버튼, 외부 범위 변경):
📝 Committable suggestion
🤖 Prompt for AI Agents