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

[Refactor/FE] 회원가입 페이지를 리팩토링한다. #53

Merged
merged 7 commits into from
Nov 16, 2023
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
183 changes: 101 additions & 82 deletions src/components/Accounts/SignupComponents.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,16 @@ import InputImage from "../Input/InputImage.jsx";
import InputTextContainer from "../Input/InputTextContainer.jsx";
import Button from "../Button/Button.jsx";
import DropdownFilter from "../Dropdown/DropdownFilter.jsx";
import { useState } from "react";
import { userSignup } from "../../librarys/api/signup.js";
import { useReducer, useState } from "react";
import {
intialUserRegisterState,
userRegisterReducer,
} from "../../reducer/user-register.js";
import { getByPath } from "../../librarys/util.js";
import { createAccount } from "../../librarys/api/user.js";
import { useDispatch } from "react-redux";
import { getMyInfo, login } from "../../redux/userSlice.js";
import { useNavigate } from "react-router-dom";

const Grid = styled.div`
margin: 48px 70px;
Expand All @@ -22,139 +30,150 @@ const RegisterButton = styled(Button)`
justify-self: center;
`;

const Signup = () => {
// 소속 병원 드롭다운 내용
const hospitalItems = [
{ key: "춘천성심병원", value: "춘천성심병원" },
{ key: "동탄성심병원", value: "동탄성심병원" },
{ key: "강남성심병원", value: "강남성심병원" },
{ key: "한강성심병원", value: "한강성심병원" },
{ key: "강동성심병원", value: "강동성심병원" },
{ key: "한림성심병원", value: "한림성심병원" },
];

const handleSelectHospital = (hospital) => {
console.log("Selected Hospital: ", hospital.key);
setFormData({ ...formData, hospital: hospital.key });
};

// 역할 버튼 상태 로직
const [selectedRole, setSelectedRole] = useState(null);

const handleSelectRole = (role) => {
setSelectedRole(role);
const staffRole = role === "doctor" ? "ROLE_DOCTOR" : "ROLE_THERAPIST";
setFormData({ ...formData, staffRole: staffRole });
};
// 소속 병원 드롭다운 내용
const hospitals = [
"춘천성심병원",
"동탄성심병원",
"강남성심병원",
"한강성심병원",
"강동성심병원",
"한림성심병원",
].map((item) => ({ key: item, value: item }));

//이미지 업로드 api 연결
const handleImageSelect = (file) => {
const formDataCopy = { ...formData };
formDataCopy.file = file;
setFormData(formDataCopy);
};
const Signup = () => {
const [state, dispatch] = useReducer(
userRegisterReducer,
intialUserRegisterState,
);
const reduxDispatch = useDispatch();
const navigate = useNavigate();

const [formData, setFormData] = useState({
mid: "",
password: "",
name: "",
hospital: "",
department: "",
email: "",
phone: "",
staffRole: "",
// fileName: '',
});
const { id, password, name, hospital, department, email, phone, role } =
state;

const handleSubmit = async (e) => {
e.preventDefault();
function setData(key, path) {
return (value) => {
if (path) {
value = getByPath(value, path);
}

// const dataToSubmit = new FormData();
// Object.keys(formData).forEach(key => {
// if (key !== 'file') {
// dataToSubmit.append(key, formData[key]);
// }
// });
dispatch({
type: "field",
payload: {
key,
value,
},
});
};
}

// if (formData.file) {
// dataToSubmit.append('file', formData.file);
// }
async function clickRegisterButton() {
if (id === "" || id.length < 3) {
alert("아이디는 4글자 이상으로 입력해주세요.");
return;
}
if (password === "" || password.length < 3) {
alert("비밀번호는 4글자 이상으로 입력해주세요.");
return;
}
if (name === "") {
alert("이름을 입력하세요.");
return;
}
if (hospital === "") {
alert("소속 병원을 입력하세요.");
return;
}
if (department === "") {
alert("소속 부서를 입력하세요.");
return;
}
if (email === "") {
alert("이메일을 입력하세요.");
return;
}
if (phone === "") {
alert("핸드폰 번호를 입력하세요.");
return;
}
console.log(state);

try {
const response = await userSignup(formData);
console.log(response);
await createAccount(state);
} catch (error) {
console.error(error);
alert("회원가입에 실패했습니다.");
return;
}
};

const handleInputChange = (id) => {
return (e) => {
setFormData({ ...formData, [id]: e.target.value });
};
};
alert(name + "님의 회원가입이 완료되었습니다!");
const tokenResponse = await reduxDispatch(login({ id, password }));
await reduxDispatch(getMyInfo(tokenResponse.payload));

navigate("/");
}

return (
<BlockContainer>
<TitleText text="회원가입" />
<Grid>
<RoleButton
role="doctor"
isSelected={selectedRole === "doctor"}
onSelectRole={() => handleSelectRole("doctor")}
isSelected={role === "ROLE_DOCTOR"}
onSelectRole={() => setData("role")("ROLE_DOCTOR")}
/>
<RoleButton
role="therapist"
isSelected={selectedRole === "therapist"}
onSelectRole={() => handleSelectRole("therapist")}
isSelected={role === "ROLE_THERAPIST"}
onSelectRole={() => setData("role")("ROLE_THERAPIST")}
/>
<DropdownFilter
label="소속 병원명 *"
items={hospitalItems}
onSelect={handleSelectHospital}
items={hospitals}
onSelect={setData("hospital", "value")}
/>
<InputImage
onImageSelect={handleImageSelect}
onUpload={setData("image")}
style={{ gridRowEnd: "span 2" }}
/>
<InputTextContainer
label="전공 분야 *"
name="department"
value={formData.department}
onChange={handleInputChange("department")}
value={department}
onChange={setData("department", "target.value")}
/>
<InputTextContainer
label="성함 *"
name="name"
value={formData.name}
onChange={handleInputChange("name")}
value={name}
onChange={setData("name", "target.value")}
/>
<InputTextContainer
label="연락처 *"
name="phone"
value={formData.phone}
onChange={handleInputChange("phone")}
value={phone}
onChange={setData("phone", "target.value")}
/>
<InputTextContainer
label="이메일 *"
name="email"
value={formData.email}
onChange={handleInputChange("email")}
value={email}
onChange={setData("email", "target.value")}
style={{ gridColumnEnd: "span 2" }}
/>
<InputTextContainer
label="아이디 *"
name="mid"
value={formData.mid}
onChange={handleInputChange("mid")}
value={id}
onChange={setData("id", "target.value")}
/>
<InputTextContainer
label="비밀번호 *"
name="password"
value={formData.password}
onChange={handleInputChange("password")}
value={password}
onChange={setData("password", "target.value")}
/>
<RegisterButton onClick={handleSubmit}>회원가입</RegisterButton>
<RegisterButton onClick={clickRegisterButton}>회원가입</RegisterButton>
</Grid>
</BlockContainer>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/Common/DnDList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const DnDList = ({ id, data, dropping, dragging, removable }) => {

DnDList.propTypes = {
id: PropTypes.string.isRequired,
data: PropTypes.arrayOf(PropTypes.array).isRequired,
data: PropTypes.arrayOf(PropTypes.object).isRequired,
dropping: PropTypes.bool,
dragging: PropTypes.bool,
removable: PropTypes.bool,
Expand Down
2 changes: 1 addition & 1 deletion src/components/Input/InputArea.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function InputArea({ value, onInput, disabled, className }) {
return (
<Item
type="text"
value={value}
defaultValue={value}
onChange={onInput}
disabled={disabled}
className={displayClassName}
Expand Down
47 changes: 31 additions & 16 deletions src/components/Input/InputImage.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useMemo, useState } from "react";
import { useMemo, useRef, useState } from "react";
import styled from "styled-components";
import PropTypes from "prop-types";
import { createImage } from "../../librarys/api/image.js";

const UploadBox = styled.div`
width: 154px;
Expand Down Expand Up @@ -29,25 +31,34 @@ const ImagePreview = styled.img`
object-fit: contain;
`;

const InputImage = ({ onImageSelect, ...props }) => {
const InputImage = ({ onUpload, ...props }) => {
const [preview, setPreview] = useState(null);
const [selectedFile, setSelectedFile] = useState(null);
const ref = useRef(null);

const handleImageChange = (e) => {
const handleInputChange = (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setPreview(reader.result);
setSelectedFile(file);
onImageSelect(file);
};
reader.readAsDataURL(file);

if (!file) {
return;
}

const reader = new FileReader();
reader.onloadend = () => {
handleUpload(reader.result, file);
};
reader.readAsDataURL(file);
};

const triggerFileInput = () => {
document.getElementById("imageInput").click();
const handleUpload = async (image, file) => {
setPreview(image);
const response = await createImage(file);
onUpload(response.link);
};

const handleClick = () => {
if (ref) {
ref.current.click();
}
};

const content = useMemo(() => {
Expand All @@ -59,11 +70,15 @@ const InputImage = ({ onImageSelect, ...props }) => {
}, [preview]);

return (
<UploadBox {...props} onClick={triggerFileInput}>
<UploadBox {...props} onClick={handleClick}>
{content}
<HiddenInput type="file" onChange={handleImageChange} id="imageInput" />
<HiddenInput ref={ref} type="file" onChange={handleInputChange} />
</UploadBox>
);
};

InputImage.propTypes = {
onUpload: PropTypes.func,
};

export default InputImage;
9 changes: 7 additions & 2 deletions src/components/Input/InputText.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ const Item = styled.input`

function InputText({ value, onChange, className }) {
return (
<Item type="text" value={value} onChange={onChange} className={className} />
<Item
type="text"
defaultValue={value}
onChange={onChange}
className={className}
/>
);
}

Expand All @@ -27,4 +32,4 @@ InputText.propTypes = {
className: PropTypes.string,
};

export default InputText;
export default InputText;
Loading