Skip to content

Commit

Permalink
Merge pull request #105 from SystemConsultantGroup/feat/42-Connect
Browse files Browse the repository at this point in the history
[Feat] 회원가입 페이지 구현 완료
  • Loading branch information
moony1204 authored Nov 7, 2024
2 parents 47fba3f + 9773cea commit b5139b9
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 70 deletions.
11 changes: 7 additions & 4 deletions src/components/common/CheckBox/CheckBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ import styles from "./CheckBox.module.css";

interface CheckBoxProps {
label: string;
checked?: boolean;
onChange?: (checked: boolean) => void;
}

export const CheckBox: React.FC<CheckBoxProps> = ({ label }) => {
const [checked, setChecked] = useState(false);
export const CheckBox: React.FC<CheckBoxProps> = ({ label, checked = false, onChange }) => {
const [isChecked, setChecked] = useState(checked);

const handleClick = () => {
setChecked(!checked);
setChecked(!isChecked);
onChange?.(!isChecked);
};

return (
<div className={styles.checkboxContainer} onClick={handleClick}>
<MantineCheckbox
checked={checked}
checked={isChecked}
onChange={handleClick}
size="sm"
radius={"sm"}
Expand Down
22 changes: 16 additions & 6 deletions src/components/common/RegisterForm/registerForm.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
flex-direction: column;
justify-content: center;
align-items: center;
padding: 20px;
padding: 50px;
gap: 30px;
position: relative;
background: var(--color-surfaceContainerLowest);
Expand All @@ -15,18 +15,28 @@
word-wrap: break-word;
}

.form {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 10px;
padding: 20px;
/* Add gap between form elements */
}

.registerBox label {
margin-bottom: 10px;
}

.text {
width: 300px;
width: 400px;
height: 12%;
}

.logo {
margin-bottom: 0px;
width: 150px;
width: 180px;
height: auto;
}

Expand Down Expand Up @@ -57,7 +67,7 @@
}

.logo {
width: 110px;
width: 160px;
}

.text {
Expand All @@ -73,7 +83,7 @@
}

.logo {
width: 90px;
width: 110px;
}

.text {
Expand All @@ -89,7 +99,7 @@
}

.logo {
width: 75px;
width: 90px;
}

.text {
Expand Down
252 changes: 192 additions & 60 deletions src/components/common/RegisterForm/registerForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,85 +4,217 @@ import { Dropdown } from "@/components/common/Dropdown/Dropdown";
import { CheckBox } from "@/components/common/CheckBox/CheckBox";
import { PrimaryButton } from "@/components/common/Buttons/PrimaryButton/PrimaryButton";
import classes from "./registerForm.module.css";
// refresh token 안됨 !! 왜지 ??
//import { getServerSideToken } from "@/components/common/Auth/getServerSideToken";
import { useAuth } from "@/components/common/Auth/AuthProvider";
import { CommonAxios } from "@/utils/CommonAxios/CommonAxios";

const MEMBER_TYPES = ["학생", "교수/교직원", "기업관계자", "외부인"];

const SIGNUP_SOURCES = ["학과 게시판", "s-top 홍보자료", "학과 카톡방", "지인 소개", "기타"];
export function RegisterForm() {
const [formData, setFormData] = useState({
name: "",
phoneNumber: "",
userType: "",
email: "",
signUpSource: "",
studentInfo: { department: "", studentNumber: "" },
division: null,
position: null,
});

const [selectedMemberType, setSelectedMemberType] = useState<string | null>(null);
const [selectedDepartment, setSelectedDepartment] = useState<string | null>(null);
//const [selectedSignupSource, setSelectedSignupSource] = useState<String | null>(null);

const [acceptedTerms, setAcceptedTerms] = useState(false);
const [acceptedPrivacy, setAcceptedPrivacy] = useState(false);

const { token } = useAuth();

const handleTermsChange = () => {
setAcceptedTerms(!acceptedTerms);
};

const handlePrivacyChange = () => {
setAcceptedPrivacy(!acceptedPrivacy);
};

const handleChange = (field: string, value: any) => {
setFormData((prevState) => ({
...prevState,
[field]: value,
}));
};

const handleMemberTypeChange = (type: string) => {
setSelectedMemberType(type);
setSelectedDepartment(null); // Reset department when member type changes
setFormData((prevState) => ({
...prevState,
userType:
type === "학생"
? "STUDENT"
: type === "교수/교직원"
? "FACULTY"
: type === "기업관계자"
? "COMPANY_REP"
: "EXTERNAL",
}));
setSelectedDepartment(null);
};

const handleDepartmentChange = (department: string) => {
setSelectedDepartment(department);
setFormData((prevState) => ({
...prevState,
studentInfo: { ...prevState.studentInfo, department },
}));
};

const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();

if (!acceptedTerms || !acceptedPrivacy) {
alert("서비스 이용약관과 개인정보 처리 방침에 동의해주세요");
return;
}

try {
//const { accessToken, refreshToken } = await getServerSideToken()

const config = {
headers: { Authorization: `Bearer ${token}` },
withCredentials: true,
};

const response = await CommonAxios.post(
"http://localhost:8000/auth/register",
formData,
config
);

console.log("Registration Successful: ", response.data);
} catch (error) {
console.error("Error registering: ", error);
}
};

return (
<div className={classes.registerBox}>
<img src="/images/S-TopLogo.png" alt="Logo" className={classes.logo} />

<h1>회원 정보 입력</h1>

<TextInput className={classes.text} label="이름" placeholder="이름을 입력하세요" required />
<TextInput
className={classes.text}
label="휴대전화"
placeholder="휴대전화 번호를 입력하세요"
required
/>

<Dropdown
options={MEMBER_TYPES}
placeholder="회원 유형을 선택하세요"
selectedOption={selectedMemberType}
onOptionClick={handleMemberTypeChange}
/>

{selectedMemberType === "학생" && (
<>
<form onSubmit={handleSubmit} className={classes.form}>
<img src="/images/S-TopLogo.png" alt="Logo" className={classes.logo} />

<h1>회원 정보 입력</h1>

<TextInput
className={classes.text}
label="이름"
placeholder="이름을 입력하세요"
required
onChange={(e) => handleChange("name", e.target.value)}
/>
<TextInput
className={classes.text}
label="휴대전화"
placeholder="휴대전화 번호를 입력하세요"
required
onChange={(e) => handleChange("phoneNumber", e.target.value)}
/>
<TextInput
className={classes.text}
label="이메일"
placeholder="이메일 주소를 입력하세요"
required
onChange={(e) => handleChange("email", e.target.value)}
/>
<br />
<Dropdown
options={MEMBER_TYPES}
placeholder="회원 유형을 선택하세요"
selectedOption={selectedMemberType}
onOptionClick={handleMemberTypeChange}
/>

{selectedMemberType === "학생" && (
<>
<Dropdown
options={[
"컴퓨터공학과",
"소프트웨어학과",
"글로벌 융합학부",
"지능형 소프트웨어학과",
"기타",
]}
placeholder="학과를 선택하세요"
selectedOption={selectedDepartment}
onOptionClick={handleDepartmentChange}
/>
<br />
<TextInput
className={classes.text}
label="학번"
placeholder="학번을 입력하세요"
onChange={(e) =>
setFormData((prevState) => ({
...prevState,
studentInfo: { ...prevState.studentInfo, studentNumber: e.target.value },
}))
}
/>

<Dropdown
options={SIGNUP_SOURCES}
placeholder="가입 경로를 선택하세요"
selectedOption={formData.signUpSource}
onOptionClick={(value) => handleChange("signUpSource", value)}
/>
</>
)}

{(selectedMemberType === "교수/교직원" || selectedMemberType === "기업관계자") && (
<>
<TextInput
className={classes.text}
label="소속"
placeholder="소속을 입력하세요"
onChange={(e) => handleChange("division", e.target.value)}
/>
<TextInput
className={classes.text}
label="직책"
placeholder="직책을 입력하세요"
onChange={(e) => handleChange("position", e.target.value)}
/>
<br />
<Dropdown
options={SIGNUP_SOURCES}
placeholder="가입 경로를 선택하세요"
selectedOption={formData.signUpSource}
onOptionClick={(value) => handleChange("signUpSource", value)}
/>
</>
)}

{selectedMemberType === "외부인" && (
<Dropdown
options={[
"컴퓨터공학과",
"소프트웨어학과",
"글로벌 융합학부",
"지능형 소프트웨어학과",
"기타",
]}
placeholder="학과를 선택하세요"
selectedOption={selectedDepartment}
onOptionClick={handleDepartmentChange}
options={SIGNUP_SOURCES}
placeholder="가입 경로를 선택하세요"
selectedOption={formData.signUpSource}
onOptionClick={(value) => handleChange("signUpSource", value)}
/>
<TextInput className={classes.text} label="학번" placeholder="학번을 입력하세요" />
<TextInput
className={classes.text}
label="가입경로"
placeholder="가입경로를 입력하세요"
/>
</>
)}

{(selectedMemberType === "교수/교직원" || selectedMemberType === "기업관계자") && (
<>
<TextInput className={classes.text} label="소속" placeholder="소속을 입력하세요" />
<TextInput className={classes.text} label="직책" placeholder="직책을 입력하세요" />
<TextInput
className={classes.text}
label="가입경로"
placeholder="가입경로를 입력하세요"
/>
</>
)}

{selectedMemberType === "외부인" && (
<TextInput className={classes.text} label="가입경로" placeholder="가입경로를 입력하세요" />
)}
)}

<CheckBox label="서비스이용약관 (필수)" />
<CheckBox label="개인정보처리방침 (필수)" />
<PrimaryButton>회원가입</PrimaryButton>
<br />
<div onClick={handleTermsChange}>
<CheckBox label="서비스이용약관 (필수)" />
</div>
<div onClick={handlePrivacyChange}>
<CheckBox label="개인정보처리방침 (필수)" />
</div>
<br />
<br />
<PrimaryButton type="submit">회원가입</PrimaryButton>
</form>
</div>
);
}
3 changes: 3 additions & 0 deletions src/components/common/SearchInput/SearchInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ export function SearchInput({
placeholder,
iconSize = 16,
onChange,
value,
...props
}: InputProps & {
placeholder?: string;
iconSize?: number;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
value?: string;
}) {
return (
<>
Expand All @@ -22,6 +24,7 @@ export function SearchInput({
placeholder={placeholder}
leftSection={<IconSearch size={iconSize} />}
onChange={onChange}
value={value}
{...props}
/>
</>
Expand Down

0 comments on commit b5139b9

Please sign in to comment.