Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/pages/input-page/auth/components/Agreement.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "" }) {
Expand Down
16 changes: 8 additions & 8 deletions src/pages/input-page/company/layouts/CompanySection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,21 @@ 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();
const [showTempSaveModal, setShowTempSaveModal] = useState(false);

// 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') || '');
Expand Down Expand Up @@ -48,7 +51,6 @@ function CompanySection() {
caption="지원 회사명"
value={companyName}
onChange={setCompanyName}
placeholder="pertineo"
width={530}
required={true}
autocompleteResults={companyResults}
Expand All @@ -58,19 +60,17 @@ function CompanySection() {
caption="지원 직무"
value={jobTitle}
onChange={setJobTitle}
placeholder="소프트웨어 엔지니어"
width={530}
required={true}
autocompleteResults={positionsList}
selectOnly={true}
// autocompleteResults={positionsList}
// selectOnly={true}
/>
</div>

<EntrySection
caption="지원 공고 사이트 URL"
value={noticeUrl}
onChange={setNoticeUrl}
placeholder="https://pertineo.khu.ac.kr/"
width={1080}
/>

Expand Down
73 changes: 68 additions & 5 deletions src/pages/input-page/resume/layouts/ResumeSection.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) => ({
Expand All @@ -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 (
Expand All @@ -183,7 +233,7 @@ function ResumeSection() {
<EntryGroupSection
caption="학력사항"
items={education}
onChange={setEducation}
onChange={handleEducationChange}
required={true}
newItem={{ university: "경희대학교", major: "", gpa: "", minor: "" }}
placeholders={{
Expand All @@ -194,6 +244,19 @@ function ResumeSection() {
}}
autocompleteResults={eduAutocomplete}
/>

{/* GPA 에러 메시지 */}
{educationGPAErrors.some((err) => err !== null) && (
<div className="w-full min-[894px]:max-w-[1080px]">
{educationGPAErrors.map((error, idx) =>
error ? (
<div key={idx} className="text-[#E74C3C] text-[14px] font-normal mt-[8px]">
{error}
</div>
) : null
)}
</div>
)}

{/* 경력사항 */}
<EntryGroupSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import TempSaveModal from "../../components/TempSaveModal";
import { useCreateAnalysis } from "hooks/useCreateAnalysis";
import { useAnalysisStore } from "stores/analysisStore";

const MAX_CARDS = 5;
const MAX_CARDS = 10;
const SESSION_KEY = "selfIntroCards";

const defaultCards = () => [{ id: 0, question: "", content: "" }];
Expand Down
Loading