diff --git a/src/pages/input-page/auth/components/Agreement.jsx b/src/pages/input-page/auth/components/Agreement.jsx index b63aac4..08af65f 100644 --- a/src/pages/input-page/auth/components/Agreement.jsx +++ b/src/pages/input-page/auth/components/Agreement.jsx @@ -29,14 +29,14 @@ const AGREEMENT_ITEMS = [ }, { id: "thirdParty", - type: "선택", + type: "필수", label: "개인정보 제3자 제공에 동의합니다.", modalTitle: "Pertineo 개인정보 제3자 제공 동의서", url: "https://d2qlxukzyb0szn.cloudfront.net/terms-of-service/v1/third-party-data-sharing.html", }, ]; -const REQUIRED_IDS = ["terms", "privacy", "policy"]; +const REQUIRED_IDS = ["terms", "privacy", "policy", "thirdParty"]; const AGREEMENT_CHECKED_KEY = "agreementChecked"; function Agreement({ isEmailVerified = false, email = "" }) { diff --git a/src/pages/input-page/company/layouts/CompanySection.jsx b/src/pages/input-page/company/layouts/CompanySection.jsx index 915eebc..f35a2e3 100644 --- a/src/pages/input-page/company/layouts/CompanySection.jsx +++ b/src/pages/input-page/company/layouts/CompanySection.jsx @@ -3,7 +3,10 @@ import { useNavigate } from "react-router-dom"; import EntrySection from "../components/EntrySection"; import Button from "../../components/Button"; import TempSaveModal from "../../components/TempSaveModal"; -import { useFetchCompanies, useFetchPositions } from "api/setupApi"; +import { + useFetchCompanies, + // useFetchPositions +} from "api/setupApi"; function CompanySection() { const navigate = useNavigate(); @@ -11,10 +14,10 @@ function CompanySection() { // API 자동완성 데이터 const { data: companiesData } = useFetchCompanies(); - const { data: positionsData } = useFetchPositions(); + // const { data: positionsData } = useFetchPositions(); const companiesList = useMemo(() => companiesData?.data?.list ?? [], [companiesData]); - const positionsList = useMemo(() => positionsData?.data?.list ?? [], [positionsData]); + // const positionsList = useMemo(() => positionsData?.data?.list ?? [], [positionsData]); // 1. 상태 정의 const [companyName, setCompanyName] = useState(() => sessionStorage.getItem('company_companyName') || ''); @@ -48,7 +51,6 @@ function CompanySection() { caption="지원 회사명" value={companyName} onChange={setCompanyName} - placeholder="pertineo" width={530} required={true} autocompleteResults={companyResults} @@ -58,11 +60,10 @@ function CompanySection() { caption="지원 직무" value={jobTitle} onChange={setJobTitle} - placeholder="소프트웨어 엔지니어" width={530} required={true} - autocompleteResults={positionsList} - selectOnly={true} + // autocompleteResults={positionsList} + // selectOnly={true} /> @@ -70,7 +71,6 @@ function CompanySection() { caption="지원 공고 사이트 URL" value={noticeUrl} onChange={setNoticeUrl} - placeholder="https://pertineo.khu.ac.kr/" width={1080} /> diff --git a/src/pages/input-page/resume/layouts/ResumeSection.jsx b/src/pages/input-page/resume/layouts/ResumeSection.jsx index b447d9e..449faac 100644 --- a/src/pages/input-page/resume/layouts/ResumeSection.jsx +++ b/src/pages/input-page/resume/layouts/ResumeSection.jsx @@ -144,6 +144,49 @@ function ResumeSection() { ); }; + // GPA 범위 검증 함수 + const validateGPA = (gpa) => { + if (!gpa) return null; + const gpaNum = parseFloat(gpa); + if (isNaN(gpaNum)) return "범위가 벗어났습니다"; + if (gpaNum < 0.0 || gpaNum > 4.3) return "범위가 벗어났습니다"; + return null; + }; + + // 각 education 행의 GPA 에러 상태 + const educationGPAErrors = education.map((row) => validateGPA(row.gpa)); + + // Education 변경 핸들러 (GPA 필터링 포함) + const handleEducationChange = (newEducation) => { + const filteredEducation = newEducation.map((row) => { + let gpa = row.gpa; + + // 숫자와 첫 번째 점 이외의 모든 것 제거 + let numericPart = ''; + let hasDot = false; + + for (let char of gpa) { + if (char === '.' && !hasDot) { + numericPart += '.'; + hasDot = true; + } else if (/[0-9]/.test(char)) { + numericPart += char; + } + } + + // 점으로 시작하는 경우만 제거 (끝나는 경우는 허용) + if (numericPart.startsWith('.')) { + numericPart = numericPart.slice(1); + } + + return { + ...row, + gpa: numericPart + }; + }); + setEducation(filteredEducation); + }; + // 행별 자동완성 결과 동적 계산 const eduAutocomplete = useMemo(() => { return education.map((row) => ({ @@ -168,10 +211,17 @@ function ResumeSection() { // 학력사항(required)의 필수 필드가 모두 입력된 경우에만 다음 버튼 활성화 const canProceed = education.every( - (row) => - row.university?.trim() !== "" && - row.major?.trim() !== "" && - row.gpa?.trim() !== "", + (row) => { + const gpa = parseFloat(row.gpa); + return ( + row.university?.trim() !== "" && + row.major?.trim() !== "" && + row.gpa?.trim() !== "" && + !isNaN(gpa) && + gpa >= 0.0 && + gpa <= 4.3 + ); + } ); return ( @@ -183,7 +233,7 @@ function ResumeSection() { + + {/* GPA 에러 메시지 */} + {educationGPAErrors.some((err) => err !== null) && ( +
+ {educationGPAErrors.map((error, idx) => + error ? ( +
+ {error} +
+ ) : null + )} +
+ )} {/* 경력사항 */} [{ id: 0, question: "", content: "" }];