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

[Feat] CompletePage 사용자 만족도 조사 추가 #343

Merged
merged 10 commits into from
Aug 5, 2024
7 changes: 7 additions & 0 deletions src/views/CompletePage/apis.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import tokenInstance from '@apis/tokenInstance';

export const postSatisfaction = (satisfaction: number) => {
return tokenInstance.post('/recruiting-applicant/satisfaction', {
satisfaction,
});
};
50 changes: 50 additions & 0 deletions src/views/CompletePage/components/Survey.tsx
Original file line number Diff line number Diff line change
@@ -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<number | 'CHANGED'>(-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 (
<div className={surveyBox}>
<span
style={{
textAlign: 'center',
whiteSpace: 'pre-line',
}}>{`지원서 이용 만족도를 0-10점 중에 선택해주세요.\n의견을 주시면 프로덕트 개선에 도움이 됩니다.`}</span>
<div style={{ position: 'relative', width: 348, height: 36 }}>
<span className={thanksTextVar[point === 'CHANGED' ? 'in' : 'out']}>소중한 의견 감사합니다 :&#41;</span>
<ul className={pointContainerVar[point !== 'CHANGED' ? 'in' : 'out']}>
{Array.from({ length: 11 }, (_, i) => i).map((v) => (
<li
key={v}
className={pointBoxVar[point === 'CHANGED' ? 'changed' : v === point ? 'selected' : 'default']}
onClick={() => handleClickPoint(v)}>
<span style={{ paddingTop: 5 }}>{v}</span>
</li>
))}
</ul>
</div>
</div>
);
};

export default Survey;
22 changes: 22 additions & 0 deletions src/views/CompletePage/hooks/useMutateSatisfaction.ts
Original file line number Diff line number Diff line change
@@ -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<PostSatisfactionResponse, PostSatisfactionRequest>,
AxiosError<ErrorResponse, PostSatisfactionRequest>,
PostSatisfactionRequest
>({
mutationFn: ({ satisfaction }) => postSatisfaction(satisfaction),
onSuccess,
});

return { mutate };
};

export default useMutateSatisfaction;
4 changes: 3 additions & 1 deletion src/views/CompletePage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -28,9 +29,10 @@ const CompletePage = () => {
<p className={subText}>이메일로 지원 접수 완료 알림이 발송되었습니다.</p>
<Callout
style={{
marginBottom: 50,
marginBottom: 35,
}}>{`이메일 도착 시점에 차이가 있을 수 있습니다.\n이메일이 오지 않으면 스팸 메일함을 확인해주세요.`}</Callout>
<Button onClick={handleClickMyPage}>마이페이지로 이동하기</Button>
<Survey />
</section>
);
};
Expand Down
115 changes: 110 additions & 5 deletions src/views/CompletePage/style.css.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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,

Expand All @@ -23,24 +23,129 @@ export const icon = style({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
marginBottom: '32px',
marginBottom: 20,
width: 66,
height: 66,
borderRadius: '50%',
background: theme.color.primaryLinear,
});

export const mainText = style({
marginBottom: 24,
marginBottom: 8,
color: theme.color.baseText,
textAlign: 'center',
whiteSpace: 'pre-line',
...theme.font.HEADING_2_32_B,
});

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,
},
],
});
8 changes: 8 additions & 0 deletions src/views/CompletePage/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export interface PostSatisfactionRequest {
satisfaction: number;
}

export interface PostSatisfactionResponse {
err: boolean;
userMessage: string;
}