-
Notifications
You must be signed in to change notification settings - Fork 3
[feature] 동아리 지원서 답변 화면 구현 및 관련 컴포넌트 개발 #490
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
cc6ba8a
d67ad89
f706635
f5e3e70
abec624
e2d98ae
009068f
df0a87c
23b288c
0209ba5
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 |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| import { useState } from 'react'; | ||
| import { AnswerItem } from '@/types/application'; | ||
|
|
||
| export const useAnswers = () => { | ||
| const [answers, setAnswers] = useState<AnswerItem[]>([]); | ||
|
|
||
| const updateSingleAnswer = (id: number, value: string) => { | ||
| setAnswers((prev) => [ | ||
| ...prev.filter((a) => a.id !== id), | ||
| { id, answer: value }, | ||
| ]); | ||
| }; | ||
|
|
||
| const updateMultiAnswer = (id: number, values: string[]) => { | ||
| setAnswers((prev) => [ | ||
| ...prev.filter((a) => a.id !== id), | ||
| ...values.map((v) => ({ id, answer: v })), | ||
| ]); | ||
| }; | ||
|
|
||
| const onAnswerChange = (id: number, value: string | string[]) => { | ||
| if (Array.isArray(value)) { | ||
| updateMultiAnswer(id, value); | ||
| } else { | ||
| updateSingleAnswer(id, value); | ||
| } | ||
| }; | ||
|
|
||
| const getAnswersById = (id: number) => | ||
| answers.filter((a) => a.id === id).map((a) => a.answer); | ||
|
|
||
| return { onAnswerChange, getAnswersById }; | ||
oesnuj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| }; | ||
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import styled from 'styled-components'; | ||
|
|
||
| export const FormTitle = styled.h1` | ||
| font-size: 2.5rem; | ||
| font-weight: 700; | ||
| border: none; | ||
| outline: none; | ||
| margin-top: 20px; | ||
| margin-bottom: 46px; | ||
| `; | ||
|
|
||
| export const ButtonWrapper = styled.div` | ||
| display: flex; | ||
| justify-content: flex-end; | ||
| `; | ||
|
|
||
| export const submitButton = styled.button` | ||
| padding: 10px 56px; | ||
| background-color: #ff5414; | ||
| border-radius: 10px; | ||
| border: none; | ||
| color: #fff; | ||
| font-size: 1.25rem; | ||
| font-weight: 600; | ||
| letter-spacing: -0.4px; | ||
| transition: background-color 0.2s; | ||
| margin: 50px 0; | ||
|
|
||
| &:hover { | ||
| background-color: #ffad8e; | ||
| animation: pulse 0.4s ease-in-out; | ||
| } | ||
|
|
||
| &:active { | ||
| transform: scale(0.95); | ||
| } | ||
| `; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| import { mockData } from '@/mocks/data/mockData'; | ||
| import { PageContainer } from '@/styles/PageContainer.styles'; | ||
| import * as Styled from './AnswerApplicationForm.styles'; | ||
| import Header from '@/components/common/Header/Header'; | ||
| import { useParams } from 'react-router-dom'; | ||
| import { useGetClubDetail } from '@/hooks/queries/club/useGetClubDetail'; | ||
| import ClubProfile from '@/pages/ClubDetailPage/components/ClubProfile/ClubProfile'; | ||
| import { useAnswers } from '@/hooks/useAnswers'; | ||
| import QuestionAnswerer from '@/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer'; | ||
|
|
||
| const AnswerApplicationForm = () => { | ||
| //const { clubId } = useParams<{ clubId: string }>(); | ||
| const clubId = '67e54ae51cfd27718dd40bec'; // 하드코딩된 club ID | ||
oesnuj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const { data: clubDetail, error } = useGetClubDetail(clubId || ''); | ||
| const { onAnswerChange, getAnswersById } = useAnswers(); | ||
| if (!clubDetail) { | ||
| return null; | ||
| } | ||
oesnuj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| if (error) { | ||
| return <div>에러가 발생했습니다.</div>; | ||
| } | ||
|
|
||
| return ( | ||
| <> | ||
| <Header /> | ||
| <PageContainer style={{ paddingTop: '172px' }}> | ||
| <ClubProfile | ||
| name={clubDetail.name} | ||
| logo={clubDetail.logo} | ||
| division={clubDetail.division} | ||
| category={clubDetail.category} | ||
| tags={clubDetail.tags} | ||
| /> | ||
| <Styled.FormTitle>{mockData.form_title}</Styled.FormTitle> | ||
| {mockData.questions.map((q) => ( | ||
| <QuestionAnswerer | ||
| key={q.id} | ||
| question={q} | ||
| selectedAnswers={getAnswersById(q.id)} | ||
| onChange={onAnswerChange} | ||
| /> | ||
| ))} | ||
| <Styled.ButtonWrapper> | ||
| <Styled.submitButton>제출하기</Styled.submitButton> | ||
oesnuj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| </Styled.ButtonWrapper> | ||
| </PageContainer> | ||
| </> | ||
| ); | ||
| }; | ||
|
|
||
| export default AnswerApplicationForm; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| import { Question } from '@/types/application'; | ||
| import ShortText from '@/pages/AdminPage/application/fields/ShortText'; | ||
| import LongText from '@/pages/AdminPage/application/fields/LongText'; | ||
|
Check warning on line 3 in frontend/src/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer.tsx
|
||
| import Choice from '@/pages/AdminPage/application/fields/Choice'; | ||
|
|
||
| interface QuestionAnswererProps { | ||
| question: Question; | ||
| selectedAnswers: string[]; | ||
| onChange: (id: number, value: string | string[]) => void; | ||
| } | ||
|
|
||
| const QuestionAnswerer = ({ | ||
|
Check warning on line 12 in frontend/src/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer.tsx
|
||
| question, | ||
| selectedAnswers, | ||
| onChange, | ||
| }: QuestionAnswererProps) => { | ||
| const baseProps = { | ||
|
Check warning on line 17 in frontend/src/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer.tsx
|
||
| id: question.id, | ||
| title: question.title, | ||
| description: question.description, | ||
| required: question.options.required, | ||
| mode: 'answer' as const, | ||
| }; | ||
|
|
||
| switch (question.type) { | ||
| case 'NAME': | ||
| case 'EMAIL': | ||
| case 'PHONE_NUMBER': | ||
| case 'SHORT_TEXT': | ||
| return ( | ||
|
Check warning on line 30 in frontend/src/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer.tsx
|
||
| <ShortText | ||
| {...baseProps} | ||
| answer={selectedAnswers[0] ?? ''} | ||
| onAnswerChange={(value) => onChange(question.id, value)} | ||
|
Check warning on line 34 in frontend/src/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer.tsx
|
||
| /> | ||
| ); | ||
|
|
||
| case 'LONG_TEXT': | ||
| return ( | ||
|
Check warning on line 39 in frontend/src/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer.tsx
|
||
| <LongText | ||
| {...baseProps} | ||
| answer={selectedAnswers[0] ?? ''} | ||
| onAnswerChange={(value) => onChange(question.id, value)} | ||
|
Check warning on line 43 in frontend/src/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer.tsx
|
||
| /> | ||
| ); | ||
|
|
||
| case 'CHOICE': | ||
| case 'MULTI_CHOICE': | ||
| return ( | ||
|
Check warning on line 49 in frontend/src/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer.tsx
|
||
| <></> | ||
| // <Choice | ||
| // {...baseProps} | ||
| // items={question.items} | ||
| // isMulti={question.type === 'MULTI_CHOICE'} | ||
| // answer={selectedAnswers} | ||
| // onAnswerChange={(value) => onChange(question.id, value)} | ||
| // /> | ||
oesnuj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ); | ||
oesnuj marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| default: | ||
| return <div>지원하지 않는 질문 유형입니다: {question.type}</div>; | ||
|
Check warning on line 61 in frontend/src/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer.tsx
|
||
| } | ||
| }; | ||
|
|
||
| export default QuestionAnswerer; | ||
|
Check warning on line 65 in frontend/src/pages/AdminPage/application/components/QuestionAnswerer/QuestionAnswerer.tsx
|
||
Uh oh!
There was an error while loading. Please reload this page.