diff --git a/src/views/CompletePage/apis.ts b/src/views/CompletePage/apis.ts new file mode 100644 index 00000000..360f06cb --- /dev/null +++ b/src/views/CompletePage/apis.ts @@ -0,0 +1,7 @@ +import tokenInstance from '@apis/tokenInstance'; + +export const postSatisfaction = (satisfaction: number) => { + return tokenInstance.post('/recruiting-applicant/satisfaction', { + satisfaction, + }); +}; diff --git a/src/views/CompletePage/components/Survey.tsx b/src/views/CompletePage/components/Survey.tsx new file mode 100644 index 00000000..4e960eb8 --- /dev/null +++ b/src/views/CompletePage/components/Survey.tsx @@ -0,0 +1,50 @@ +import { useState } from 'react'; + +import useMutateSatisfaction from '../hooks/useMutateSatisfaction'; +import { pointBoxVar, pointContainerVar, surveyBox, thanksTextVar } from '../style.css'; + +const Survey = () => { + const [point, setPoint] = useState(-1); + + const handleSatisfaction = () => { + setTimeout(() => { + setPoint('CHANGED'); + }, 200); + setTimeout(() => { + setPoint(-1); + }, 2200); + }; + + const { mutate } = useMutateSatisfaction({ onSuccess: handleSatisfaction }); + + const handleClickPoint = (i: number) => { + if (point === 'CHANGED') return; + mutate({ satisfaction: i }); + setPoint(i); + }; + + return ( +
+ {`지원서 이용 만족도를 0-10점 중에 선택해주세요.\n의견을 주시면 프로덕트 개선에 도움이 됩니다.`} +
+ 소중한 의견 감사합니다 :) +
    + {Array.from({ length: 11 }, (_, i) => i).map((v) => ( +
  • handleClickPoint(v)}> + {v} +
  • + ))} +
+
+
+ ); +}; + +export default Survey; diff --git a/src/views/CompletePage/hooks/useMutateSatisfaction.ts b/src/views/CompletePage/hooks/useMutateSatisfaction.ts new file mode 100644 index 00000000..ab0aa08a --- /dev/null +++ b/src/views/CompletePage/hooks/useMutateSatisfaction.ts @@ -0,0 +1,22 @@ +import { useMutation } from '@tanstack/react-query'; +import { AxiosError, AxiosResponse } from 'axios'; + +import { ErrorResponse } from '@type/errorResponse'; + +import { postSatisfaction } from '../apis'; +import { PostSatisfactionRequest, PostSatisfactionResponse } from '../types'; + +const useMutateSatisfaction = ({ onSuccess }: { onSuccess?: () => void }) => { + const { mutate } = useMutation< + AxiosResponse, + AxiosError, + PostSatisfactionRequest + >({ + mutationFn: ({ satisfaction }) => postSatisfaction(satisfaction), + onSuccess, + }); + + return { mutate }; +}; + +export default useMutateSatisfaction; diff --git a/src/views/CompletePage/index.tsx b/src/views/CompletePage/index.tsx index 6309a771..97043f2c 100644 --- a/src/views/CompletePage/index.tsx +++ b/src/views/CompletePage/index.tsx @@ -5,6 +5,7 @@ import Button from '@components/Button'; import Callout from '@components/Callout'; import { RecruitingInfoContext } from '@store/recruitingInfoContext'; +import Survey from './components/Survey'; import IconCheckmark from './icons/IconCheckmark'; import { container, icon, mainText, subText } from './style.css'; @@ -28,9 +29,10 @@ const CompletePage = () => {

이메일로 지원 접수 완료 알림이 발송되었습니다.

{`이메일 도착 시점에 차이가 있을 수 있습니다.\n이메일이 오지 않으면 스팸 메일함을 확인해주세요.`} + ); }; diff --git a/src/views/CompletePage/style.css.ts b/src/views/CompletePage/style.css.ts index e6446cc6..1dfe7d58 100644 --- a/src/views/CompletePage/style.css.ts +++ b/src/views/CompletePage/style.css.ts @@ -1,4 +1,4 @@ -import { style } from '@vanilla-extract/css'; +import { style, styleVariants } from '@vanilla-extract/css'; import { calc } from '@vanilla-extract/css-utils'; import { theme } from 'styles/theme.css'; @@ -8,7 +8,7 @@ export const container = style({ flexDirection: 'column', alignItems: 'center', justifyContent: 'center', - width: 466, + width: 550, height: calc.subtract('100vh', '74px'), minHeight: 700, @@ -23,7 +23,7 @@ export const icon = style({ display: 'flex', alignItems: 'center', justifyContent: 'center', - marginBottom: '32px', + marginBottom: 20, width: 66, height: 66, borderRadius: '50%', @@ -31,7 +31,7 @@ export const icon = style({ }); export const mainText = style({ - marginBottom: 24, + marginBottom: 8, color: theme.color.baseText, textAlign: 'center', whiteSpace: 'pre-line', @@ -39,8 +39,113 @@ export const mainText = style({ }); export const subText = style({ - marginBottom: 50, + marginBottom: 30, color: theme.color.baseText, textAlign: 'center', ...theme.font.BODY_1_18_M, }); + +export const surveyBox = style({ + display: 'flex', + flexDirection: 'column', + justifyContent: 'center', + alignItems: 'center', + gap: 12, + width: 466, + padding: '22px 0px', + marginTop: 35, + color: theme.color.lightestText, + ...theme.font.BODY_2_16_M, + border: `1px solid ${theme.color.border}`, + borderRadius: 15, +}); + +export const pointContainer = style({ + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + display: 'flex', + gap: 4, + transition: 'all 0.3s ease', +}); + +export const pointContainerVar = styleVariants({ + in: [ + pointContainer, + { + opacity: 1, + }, + ], + out: [ + pointContainer, + { + opacity: 0, + }, + ], +}); + +const pointBox = style({ + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + width: 28, + height: 36, + borderRadius: 6, + transition: 'all 0.3s ease', + cursor: 'pointer', +}); + +export const pointBoxVar = styleVariants({ + default: [ + pointBox, + { + backgroundColor: theme.color.subBackground, + color: theme.color.baseText, + }, + ], + selected: [ + pointBox, + { + backgroundColor: theme.color.primary, + color: theme.color.white, + }, + ], + changed: [ + pointBox, + { + cursor: 'default', + }, + ], +}); + +export const thanksText = style({ + position: 'absolute', + top: 0, + left: 0, + width: '100%', + height: '100%', + paddingTop: 5, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + ...theme.font.TITLE_6_16_SB, + color: theme.color.lighterText, + transition: 'all 0.3s ease', +}); + +export const thanksTextVar = styleVariants({ + in: [ + thanksText, + { + opacity: 1, + }, + ], + out: [ + thanksText, + { + opacity: 0, + }, + ], +}); diff --git a/src/views/CompletePage/types.ts b/src/views/CompletePage/types.ts new file mode 100644 index 00000000..d1a0959f --- /dev/null +++ b/src/views/CompletePage/types.ts @@ -0,0 +1,8 @@ +export interface PostSatisfactionRequest { + satisfaction: number; +} + +export interface PostSatisfactionResponse { + err: boolean; + userMessage: string; +}