Showing
7 changed files
with
620 additions
and
37 deletions
| ... | @@ -5,6 +5,7 @@ const Profile = require('../../models/profile'); | ... | @@ -5,6 +5,7 @@ const Profile = require('../../models/profile'); |
| 5 | const DoctorInfo = require('../../models/doctorInfo'); | 5 | const DoctorInfo = require('../../models/doctorInfo'); |
| 6 | const Joi = require('joi'); | 6 | const Joi = require('joi'); |
| 7 | const jwt = require('jsonwebtoken'); | 7 | const jwt = require('jsonwebtoken'); |
| 8 | +const axios = require('axios'); | ||
| 8 | 9 | ||
| 9 | 10 | ||
| 10 | exports.register = async(ctx) => { | 11 | exports.register = async(ctx) => { |
| ... | @@ -66,6 +67,29 @@ exports.register = async(ctx) => { | ... | @@ -66,6 +67,29 @@ exports.register = async(ctx) => { |
| 66 | 67 | ||
| 67 | }; | 68 | }; |
| 68 | 69 | ||
| 70 | +exports.searchHospital = async ctx => { | ||
| 71 | + const { | ||
| 72 | + hospitalNm, | ||
| 73 | + page, | ||
| 74 | + } = ctx.query; | ||
| 75 | + | ||
| 76 | + const pageSlice = 5; | ||
| 77 | + | ||
| 78 | + const url = 'http://apis.data.go.kr/B551182/hospInfoService1/getHospBasisList1'; | ||
| 79 | + let queryParams = '?' + encodeURIComponent('ServiceKey') + '=' + process.env.SERVICE_KEY; | ||
| 80 | + queryParams += '&' + encodeURIComponent('pageNo') + '=' + encodeURIComponent(page); | ||
| 81 | + queryParams += '&' + encodeURIComponent('numOfRows') + '=' + encodeURIComponent(pageSlice); | ||
| 82 | + queryParams += '&' + encodeURIComponent('yadmNm') + '=' + encodeURIComponent(hospitalNm); | ||
| 83 | + | ||
| 84 | + const result = await axios.get(url + queryParams); | ||
| 85 | + | ||
| 86 | + ctx.status = 200; | ||
| 87 | + ctx.body = { | ||
| 88 | + totalPage : Math.ceil(result.data.response.body.totalCount / pageSlice), | ||
| 89 | + hospitalList : result.data.response.body.items.item, | ||
| 90 | + }; | ||
| 91 | +}; | ||
| 92 | + | ||
| 69 | exports.doctorRegister = async ctx => { | 93 | exports.doctorRegister = async ctx => { |
| 70 | const { | 94 | const { |
| 71 | userId, | 95 | userId, | ... | ... |
| ... | @@ -12,6 +12,14 @@ const auth = new Router() | ... | @@ -12,6 +12,14 @@ const auth = new Router() |
| 12 | auth.post('/register', authCtrl.register) | 12 | auth.post('/register', authCtrl.register) |
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | + * 병원 검색 | ||
| 16 | + * url : http://localhost:4000/api/auth/hospital | ||
| 17 | + * request parameter : hospitalNm | ||
| 18 | + * return : xml type data | ||
| 19 | + */ | ||
| 20 | +auth.get('/hospital', authCtrl.searchHospital); | ||
| 21 | + | ||
| 22 | +/** | ||
| 15 | * 회원가입 (email type) : 의사 회원가입 | 23 | * 회원가입 (email type) : 의사 회원가입 |
| 16 | * url : http://localhost:4000/api/auth/register/doctor | 24 | * url : http://localhost:4000/api/auth/register/doctor |
| 17 | * request parameter : userId, password, passwordCheck, doctorInfo | 25 | * request parameter : userId, password, passwordCheck, doctorInfo | ... | ... |
| ... | @@ -11,6 +11,7 @@ exports.updateMedicineInfo = async() => { | ... | @@ -11,6 +11,7 @@ exports.updateMedicineInfo = async() => { |
| 11 | //queryUrl을 return하는 함수 : 한 페이지에 100개의 item씩 요청할 수 있다. | 11 | //queryUrl을 return하는 함수 : 한 페이지에 100개의 item씩 요청할 수 있다. |
| 12 | const getQueryURL = (i) => { | 12 | const getQueryURL = (i) => { |
| 13 | const url = 'http://apis.data.go.kr/1471000/DrbEasyDrugInfoService/getDrbEasyDrugList'; | 13 | const url = 'http://apis.data.go.kr/1471000/DrbEasyDrugInfoService/getDrbEasyDrugList'; |
| 14 | + // eslint-disable-next-line no-undef | ||
| 14 | const queryParams = '?' + encodeURIComponent('ServiceKey') + '=' + process.env.SERVICE_KEY; | 15 | const queryParams = '?' + encodeURIComponent('ServiceKey') + '=' + process.env.SERVICE_KEY; |
| 15 | const pageNum = '&' + encodeURIComponent('pageNo') + '=' + encodeURIComponent(i); | 16 | const pageNum = '&' + encodeURIComponent('pageNo') + '=' + encodeURIComponent(i); |
| 16 | const numOfItem = '&' + encodeURIComponent('numOfRows') + '=' + encodeURIComponent(100); | 17 | const numOfItem = '&' + encodeURIComponent('numOfRows') + '=' + encodeURIComponent(100); |
| ... | @@ -24,6 +25,7 @@ const getItemsList = async(queryUrl) => { | ... | @@ -24,6 +25,7 @@ const getItemsList = async(queryUrl) => { |
| 24 | let i = 1, getItem = null, items = null; | 25 | let i = 1, getItem = null, items = null; |
| 25 | const result = []; | 26 | const result = []; |
| 26 | 27 | ||
| 28 | + // eslint-disable-next-line no-constant-condition | ||
| 27 | while(true) { | 29 | while(true) { |
| 28 | getItem = await axios.get(queryUrl(i)); | 30 | getItem = await axios.get(queryUrl(i)); |
| 29 | items = getItem.data.body.items; | 31 | items = getItem.data.body.items; | ... | ... |
| ... | @@ -5,6 +5,15 @@ export default { | ... | @@ -5,6 +5,15 @@ export default { |
| 5 | return client.post('/auth/register', Data); | 5 | return client.post('/auth/register', Data); |
| 6 | }, | 6 | }, |
| 7 | 7 | ||
| 8 | + searchHospital : (hospitalNm : string, page : number) => { | ||
| 9 | + return client.get('/auth/hospital', { | ||
| 10 | + params : { | ||
| 11 | + hospitalNm, | ||
| 12 | + page, | ||
| 13 | + }, | ||
| 14 | + }); | ||
| 15 | + }, | ||
| 16 | + | ||
| 8 | registerDoctor : (Data : any) => { | 17 | registerDoctor : (Data : any) => { |
| 9 | return client.post('/auth/register/doctor', Data); | 18 | return client.post('/auth/register/doctor', Data); |
| 10 | }, | 19 | }, | ... | ... |
| 1 | import React, { useState, useEffect } from "react"; | 1 | import React, { useState, useEffect } from "react"; |
| 2 | import { RouteComponentProps } from 'react-router-dom'; | 2 | import { RouteComponentProps } from 'react-router-dom'; |
| 3 | 3 | ||
| 4 | -import { useRecoilValue } from "recoil"; | 4 | +import { useRecoilValue, useRecoilState } from "recoil"; |
| 5 | import * as recoilUtil from '../../util/recoilUtil'; | 5 | import * as recoilUtil from '../../util/recoilUtil'; |
| 6 | 6 | ||
| 7 | import validator from 'validator'; | 7 | import validator from 'validator'; |
| ... | @@ -11,7 +11,6 @@ import Header from '../../components/Header'; | ... | @@ -11,7 +11,6 @@ import Header from '../../components/Header'; |
| 11 | import RegisterPresenter from "./RegisterPresenter"; | 11 | import RegisterPresenter from "./RegisterPresenter"; |
| 12 | 12 | ||
| 13 | import { authApi } from '../../api'; | 13 | import { authApi } from '../../api'; |
| 14 | -import { resourceLimits } from "worker_threads"; | ||
| 15 | 14 | ||
| 16 | 15 | ||
| 17 | // eslint-disable-next-line @typescript-eslint/no-empty-interface | 16 | // eslint-disable-next-line @typescript-eslint/no-empty-interface |
| ... | @@ -20,6 +19,7 @@ interface RegisterProps extends RouteComponentProps {} | ... | @@ -20,6 +19,7 @@ interface RegisterProps extends RouteComponentProps {} |
| 20 | const RegisterContainer = (props : RegisterProps) => { | 19 | const RegisterContainer = (props : RegisterProps) => { |
| 21 | 20 | ||
| 22 | const token = useRecoilValue(recoilUtil.token); | 21 | const token = useRecoilValue(recoilUtil.token); |
| 22 | + const [loading, setLoading] = useRecoilState(recoilUtil.loading); | ||
| 23 | 23 | ||
| 24 | const [registerForm, setRegisterForm] = useState<any>({ | 24 | const [registerForm, setRegisterForm] = useState<any>({ |
| 25 | userId : '', | 25 | userId : '', |
| ... | @@ -38,6 +38,12 @@ const RegisterContainer = (props : RegisterProps) => { | ... | @@ -38,6 +38,12 @@ const RegisterContainer = (props : RegisterProps) => { |
| 38 | const [page, setPage] = useState<number>(1); | 38 | const [page, setPage] = useState<number>(1); |
| 39 | const [error, setError] = useState<string | null>(null); | 39 | const [error, setError] = useState<string | null>(null); |
| 40 | 40 | ||
| 41 | + const [searchHospital, setSearchHospital] = useState<boolean>(false); | ||
| 42 | + const [hospitalNm, setHospitalNm] = useState<string>(''); | ||
| 43 | + const [hospitalSearchPage, setHospitalSearchPage] = useState<number>(1); | ||
| 44 | + const [hospitalSearchPageList, setHospitalSearchPageList] = useState<number[]>([1]); | ||
| 45 | + const [hospitalList, setHospitalList] = useState<any[]>([]); | ||
| 46 | + const [selectHospital, setSelectHospital] = useState<any>(null); | ||
| 41 | 47 | ||
| 42 | 48 | ||
| 43 | const fetchData = async() => { | 49 | const fetchData = async() => { |
| ... | @@ -126,23 +132,7 @@ const RegisterContainer = (props : RegisterProps) => { | ... | @@ -126,23 +132,7 @@ const RegisterContainer = (props : RegisterProps) => { |
| 126 | }; | 132 | }; |
| 127 | 133 | ||
| 128 | const onSetHospitalNm = (e : React.ChangeEvent<HTMLInputElement>) => { | 134 | const onSetHospitalNm = (e : React.ChangeEvent<HTMLInputElement>) => { |
| 129 | - setRegisterForm({ | 135 | + setHospitalNm(e.target.value); |
| 130 | - ...registerForm, | ||
| 131 | - info : { | ||
| 132 | - ...registerForm.info, | ||
| 133 | - hospitalNm : e.target.value, | ||
| 134 | - }, | ||
| 135 | - }); | ||
| 136 | - }; | ||
| 137 | - | ||
| 138 | - const onSetHospitalAddr = (e : React.ChangeEvent<HTMLInputElement>) => { | ||
| 139 | - setRegisterForm({ | ||
| 140 | - ...registerForm, | ||
| 141 | - info : { | ||
| 142 | - ...registerForm.info, | ||
| 143 | - hospitalAddr : e.target.value, | ||
| 144 | - }, | ||
| 145 | - }); | ||
| 146 | }; | 136 | }; |
| 147 | 137 | ||
| 148 | const onSetContact = (e : React.ChangeEvent<HTMLInputElement>) => { | 138 | const onSetContact = (e : React.ChangeEvent<HTMLInputElement>) => { |
| ... | @@ -175,6 +165,49 @@ const RegisterContainer = (props : RegisterProps) => { | ... | @@ -175,6 +165,49 @@ const RegisterContainer = (props : RegisterProps) => { |
| 175 | }); | 165 | }); |
| 176 | }; | 166 | }; |
| 177 | 167 | ||
| 168 | + const onSearchHospital = async () => { | ||
| 169 | + try { | ||
| 170 | + setLoading(true); | ||
| 171 | + setSearchHospital(true); | ||
| 172 | + const result = await authApi.searchHospital(hospitalNm, hospitalSearchPage); | ||
| 173 | + if(result.statusText === 'OK') { | ||
| 174 | + setLoading(false); | ||
| 175 | + setHospitalSearchPageList(new Array(result.data.totalPage).fill(null).map((item : null, index : number) => index + 1)); | ||
| 176 | + setHospitalList(result.data.hospitalList.length ? result.data.hospitalList : [result.data.hospitalList]); | ||
| 177 | + } | ||
| 178 | + } catch(e : any) { | ||
| 179 | + setLoading(false); | ||
| 180 | + Alert.onError('알 수 없는 에러로 검색에 실패했습니다.', () => null); | ||
| 181 | + } | ||
| 182 | + }; | ||
| 183 | + | ||
| 184 | + const onSetSearchPrevPage = () => { | ||
| 185 | + //set Prev Page | ||
| 186 | + const pageSlice = 5; | ||
| 187 | + if(hospitalSearchPage > pageSlice) { | ||
| 188 | + setHospitalSearchPage(Math.floor((hospitalSearchPage - 1) / pageSlice) * pageSlice); | ||
| 189 | + } | ||
| 190 | + }; | ||
| 191 | + | ||
| 192 | + const onSetSearchNextPage = () => { | ||
| 193 | + //set Next Page | ||
| 194 | + const pageSlice = 5; | ||
| 195 | + if(hospitalSearchPage <= Math.floor((hospitalSearchPageList.length - 1) / pageSlice) * pageSlice) { | ||
| 196 | + setHospitalSearchPage(Math.ceil(hospitalSearchPage / pageSlice) * pageSlice + 1); | ||
| 197 | + } | ||
| 198 | + }; | ||
| 199 | + | ||
| 200 | + const onCancelSearchHospital = () => { | ||
| 201 | + Alert.onCheck('병원 등록이 취소됩니다. 계속하시겠습니까?', () => { | ||
| 202 | + setSearchHospital(false); | ||
| 203 | + setHospitalNm(''); | ||
| 204 | + setHospitalSearchPage(1); | ||
| 205 | + setHospitalSearchPageList([1]); | ||
| 206 | + setHospitalList([]); | ||
| 207 | + setSelectHospital(null); | ||
| 208 | + }, () => null); | ||
| 209 | + }; | ||
| 210 | + | ||
| 178 | const onSubmitButton = () => { | 211 | const onSubmitButton = () => { |
| 179 | if(error) { | 212 | if(error) { |
| 180 | Alert.onError(error, () => null); | 213 | Alert.onError(error, () => null); |
| ... | @@ -192,20 +225,54 @@ const RegisterContainer = (props : RegisterProps) => { | ... | @@ -192,20 +225,54 @@ const RegisterContainer = (props : RegisterProps) => { |
| 192 | if(result.data === 'Created') { | 225 | if(result.data === 'Created') { |
| 193 | Alert.onSuccess('회원가입 성공, 관리자의 승인을 대기하세요.', () => props.history.push('/login')); | 226 | Alert.onSuccess('회원가입 성공, 관리자의 승인을 대기하세요.', () => props.history.push('/login')); |
| 194 | } | 227 | } |
| 195 | - } catch(e) { | 228 | + } catch(e : any) { |
| 196 | Alert.onError(e.response.data.error, () => null); | 229 | Alert.onError(e.response.data.error, () => null); |
| 197 | } | 230 | } |
| 198 | }; | 231 | }; |
| 199 | 232 | ||
| 233 | + if(selectHospital) { | ||
| 200 | Alert.onCheck('입력하신 정보로 회원가입을 진행하시겠습니까?', onRegisterDoctor, () => null); | 234 | Alert.onCheck('입력하신 정보로 회원가입을 진행하시겠습니까?', onRegisterDoctor, () => null); |
| 235 | + } else { | ||
| 236 | + Alert.onError('검색 버튼을 눌러 병원을 선택해주세요.', () => null); | ||
| 237 | + } | ||
| 238 | + | ||
| 201 | } | 239 | } |
| 202 | 240 | ||
| 203 | }; | 241 | }; |
| 204 | 242 | ||
| 243 | + | ||
| 244 | + | ||
| 205 | useEffect(() => { | 245 | useEffect(() => { |
| 206 | validateRegisterForm(); | 246 | validateRegisterForm(); |
| 207 | }, [registerForm, page]); | 247 | }, [registerForm, page]); |
| 208 | 248 | ||
| 249 | + useEffect(() => { | ||
| 250 | + if(selectHospital) { | ||
| 251 | + setHospitalNm(selectHospital.yadmNm); | ||
| 252 | + setRegisterForm({ | ||
| 253 | + ...registerForm, | ||
| 254 | + info : { | ||
| 255 | + ...registerForm.info, | ||
| 256 | + hospitalNm : selectHospital.yadmNm, | ||
| 257 | + hospitalAddr : selectHospital.addr, | ||
| 258 | + }, | ||
| 259 | + }); | ||
| 260 | + } else { | ||
| 261 | + setHospitalNm(''); | ||
| 262 | + setRegisterForm({ | ||
| 263 | + ...registerForm, | ||
| 264 | + info : { | ||
| 265 | + ...registerForm.info, | ||
| 266 | + hospitalNm : '', | ||
| 267 | + hospitalAddr : '', | ||
| 268 | + }, | ||
| 269 | + }); | ||
| 270 | + } | ||
| 271 | + }, [selectHospital]); | ||
| 272 | + | ||
| 273 | + useEffect(() => { | ||
| 274 | + if(searchHospital) onSearchHospital(); | ||
| 275 | + }, [hospitalSearchPage]); | ||
| 209 | 276 | ||
| 210 | useEffect(() => { | 277 | useEffect(() => { |
| 211 | fetchData(); | 278 | fetchData(); |
| ... | @@ -228,12 +295,27 @@ const RegisterContainer = (props : RegisterProps) => { | ... | @@ -228,12 +295,27 @@ const RegisterContainer = (props : RegisterProps) => { |
| 228 | onSetPassword = {onSetPassword} | 295 | onSetPassword = {onSetPassword} |
| 229 | onSetPasswordCheck = {onSetPasswordCheck} | 296 | onSetPasswordCheck = {onSetPasswordCheck} |
| 230 | onSetDoctorLicense = {onSetDoctorLicense} | 297 | onSetDoctorLicense = {onSetDoctorLicense} |
| 298 | + hospitalNm = {hospitalNm} | ||
| 299 | + setHospitalNm = {setHospitalNm} | ||
| 231 | onSetHospitalNm = {onSetHospitalNm} | 300 | onSetHospitalNm = {onSetHospitalNm} |
| 232 | - onSetHospitalAddr = {onSetHospitalAddr} | ||
| 233 | onSetContact = {onSetContact} | 301 | onSetContact = {onSetContact} |
| 234 | onSetDoctorType = {onSetDoctorType} | 302 | onSetDoctorType = {onSetDoctorType} |
| 235 | onSetDoctorNm = {onSetDoctorNm} | 303 | onSetDoctorNm = {onSetDoctorNm} |
| 236 | onSubmitButton = {onSubmitButton} | 304 | onSubmitButton = {onSubmitButton} |
| 305 | + | ||
| 306 | + searchHospital = {searchHospital} | ||
| 307 | + setSearchHospital = {setSearchHospital} | ||
| 308 | + onSearchHospital = {onSearchHospital} | ||
| 309 | + hospitalSearchPage = {hospitalSearchPage} | ||
| 310 | + setHospitalSearchPage = {setHospitalSearchPage} | ||
| 311 | + hospitalSearchPageList = {hospitalSearchPageList} | ||
| 312 | + onSetSearchPrevPage = {onSetSearchPrevPage} | ||
| 313 | + onSetSearchNextPage = {onSetSearchNextPage} | ||
| 314 | + onCancelSearchHospital = {onCancelSearchHospital} | ||
| 315 | + | ||
| 316 | + hospitalList = {hospitalList} | ||
| 317 | + selectHospital = {selectHospital} | ||
| 318 | + setSelectHospital = {setSelectHospital} | ||
| 237 | /> | 319 | /> |
| 238 | </> | 320 | </> |
| 239 | ) | 321 | ) | ... | ... |
| ... | @@ -3,6 +3,11 @@ import React from 'react'; | ... | @@ -3,6 +3,11 @@ import React from 'react'; |
| 3 | import * as styled from './RegisterStyled'; | 3 | import * as styled from './RegisterStyled'; |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | +const lensImg = '/static/img/lens.png'; | ||
| 7 | +const closeButton = '/static/img/close.png'; | ||
| 8 | +const check = '/static/img/check.png'; | ||
| 9 | +const uncheck = '/static/img/uncheck.png' | ||
| 10 | + | ||
| 6 | interface RegisterProps { | 11 | interface RegisterProps { |
| 7 | registerForm : { | 12 | registerForm : { |
| 8 | userId : string; | 13 | userId : string; |
| ... | @@ -27,18 +32,131 @@ interface RegisterProps { | ... | @@ -27,18 +32,131 @@ interface RegisterProps { |
| 27 | onSetPassword : React.ChangeEventHandler<HTMLInputElement>; | 32 | onSetPassword : React.ChangeEventHandler<HTMLInputElement>; |
| 28 | onSetPasswordCheck : React.ChangeEventHandler<HTMLInputElement>; | 33 | onSetPasswordCheck : React.ChangeEventHandler<HTMLInputElement>; |
| 29 | onSetDoctorLicense : React.ChangeEventHandler<HTMLInputElement>; | 34 | onSetDoctorLicense : React.ChangeEventHandler<HTMLInputElement>; |
| 35 | + hospitalNm : string; | ||
| 36 | + setHospitalNm : (arg0 : string) => void; | ||
| 30 | onSetHospitalNm : React.ChangeEventHandler<HTMLInputElement>; | 37 | onSetHospitalNm : React.ChangeEventHandler<HTMLInputElement>; |
| 31 | - onSetHospitalAddr : React.ChangeEventHandler<HTMLInputElement>; | 38 | + // onSetHospitalAddr : React.ChangeEventHandler<HTMLInputElement>; |
| 32 | onSetContact : React.ChangeEventHandler<HTMLInputElement>; | 39 | onSetContact : React.ChangeEventHandler<HTMLInputElement>; |
| 33 | onSetDoctorType : React.ChangeEventHandler<HTMLInputElement>; | 40 | onSetDoctorType : React.ChangeEventHandler<HTMLInputElement>; |
| 34 | onSetDoctorNm : React.ChangeEventHandler<HTMLInputElement>; | 41 | onSetDoctorNm : React.ChangeEventHandler<HTMLInputElement>; |
| 35 | onSubmitButton : () => void; | 42 | onSubmitButton : () => void; |
| 36 | 43 | ||
| 44 | + searchHospital : boolean; | ||
| 45 | + setSearchHospital : (arg0 : boolean) => void; | ||
| 46 | + onSearchHospital : () => void; | ||
| 47 | + | ||
| 48 | + hospitalSearchPage : number; | ||
| 49 | + setHospitalSearchPage : (arg0 : number) => void; | ||
| 50 | + hospitalSearchPageList : number[]; | ||
| 51 | + onSetSearchPrevPage : () => void; | ||
| 52 | + onSetSearchNextPage : () => void; | ||
| 53 | + onCancelSearchHospital : () => void; | ||
| 54 | + | ||
| 55 | + hospitalList : any[]; | ||
| 56 | + selectHospital : any; | ||
| 57 | + setSelectHospital : (arg0 : any) => void; | ||
| 37 | } | 58 | } |
| 38 | 59 | ||
| 39 | const RegisterPresenter = (props : RegisterProps) => { | 60 | const RegisterPresenter = (props : RegisterProps) => { |
| 40 | return ( | 61 | return ( |
| 41 | <styled.Container> | 62 | <styled.Container> |
| 63 | + { | ||
| 64 | + props.searchHospital ? | ||
| 65 | + <styled.ModalContainer> | ||
| 66 | + <styled.ModalClsButtonWrapper> | ||
| 67 | + <styled.ModalClsButton | ||
| 68 | + onClick = {props.onCancelSearchHospital} | ||
| 69 | + > | ||
| 70 | + <styled.ModalClsButtonImg src = {closeButton}/> | ||
| 71 | + <styled.ModalClsButtonText>닫기</styled.ModalClsButtonText> | ||
| 72 | + </styled.ModalClsButton> | ||
| 73 | + </styled.ModalClsButtonWrapper> | ||
| 74 | + <styled.ModalContentWrapper> | ||
| 75 | + <styled.ModalContent> | ||
| 76 | + <styled.SearchTitle> | ||
| 77 | + {`"${props.hospitalNm}"에 대한 검색 결과`} | ||
| 78 | + </styled.SearchTitle> | ||
| 79 | + <styled.HospitalListWrapper> | ||
| 80 | + <styled.HospitalListInfo> | ||
| 81 | + <styled.HospitalListInfoEach isLast = {false}>이름</styled.HospitalListInfoEach> | ||
| 82 | + <styled.HospitalListInfoEach isLast = {false}>주소</styled.HospitalListInfoEach> | ||
| 83 | + <styled.HospitalListInfoEach isLast = {true}>선택</styled.HospitalListInfoEach> | ||
| 84 | + </styled.HospitalListInfo> | ||
| 85 | + { | ||
| 86 | + props.hospitalList.map((hospital : any) => { | ||
| 87 | + return ( | ||
| 88 | + <styled.HospitalListEach | ||
| 89 | + key = {hospital.addr} | ||
| 90 | + > | ||
| 91 | + <styled.HospitalListEachInfo isLast = {false}> | ||
| 92 | + {hospital.yadmNm} | ||
| 93 | + </styled.HospitalListEachInfo> | ||
| 94 | + <styled.HospitalListEachInfo isLast = {false}> | ||
| 95 | + {hospital.addr} | ||
| 96 | + </styled.HospitalListEachInfo> | ||
| 97 | + <styled.HospitalListEachInfo isLast = {true}> | ||
| 98 | + <styled.CheckButton | ||
| 99 | + onClick = {() => props.setSelectHospital(hospital)} | ||
| 100 | + > | ||
| 101 | + <styled.CheckButtonImg src = { | ||
| 102 | + props.selectHospital && props.selectHospital.addr === hospital.addr ? | ||
| 103 | + check : uncheck | ||
| 104 | + }/> | ||
| 105 | + </styled.CheckButton> | ||
| 106 | + </styled.HospitalListEachInfo> | ||
| 107 | + </styled.HospitalListEach> | ||
| 108 | + ) | ||
| 109 | + }) | ||
| 110 | + } | ||
| 111 | + </styled.HospitalListWrapper> | ||
| 112 | + <styled.PageWrapper> | ||
| 113 | + <styled.PageButton | ||
| 114 | + isSelect = {false} | ||
| 115 | + onClick = {props.onSetSearchPrevPage} | ||
| 116 | + > | ||
| 117 | + prev | ||
| 118 | + </styled.PageButton> | ||
| 119 | + { | ||
| 120 | + props.hospitalSearchPageList.slice(Math.floor((props.hospitalSearchPage - 1) / 5) * 5, Math.floor((props.hospitalSearchPage - 1) / 5) * 5 + 5) | ||
| 121 | + .map((page : number) => { | ||
| 122 | + return ( | ||
| 123 | + <styled.PageButton | ||
| 124 | + key = {page} | ||
| 125 | + isSelect = {props.hospitalSearchPage === page} | ||
| 126 | + onClick = {() => props.setHospitalSearchPage(page)} | ||
| 127 | + > | ||
| 128 | + {page} | ||
| 129 | + </styled.PageButton> | ||
| 130 | + ) | ||
| 131 | + }) | ||
| 132 | + } | ||
| 133 | + <styled.PageButton | ||
| 134 | + isSelect = {false} | ||
| 135 | + onClick = {props.onSetSearchNextPage} | ||
| 136 | + > | ||
| 137 | + next | ||
| 138 | + </styled.PageButton> | ||
| 139 | + </styled.PageWrapper> | ||
| 140 | + <styled.ModalButtonWrapper> | ||
| 141 | + <styled.ModalButton | ||
| 142 | + isCloseButton = {false} | ||
| 143 | + onClick = {() => props.setSearchHospital(false)} | ||
| 144 | + > | ||
| 145 | + 확인 | ||
| 146 | + </styled.ModalButton> | ||
| 147 | + <styled.ModalButton | ||
| 148 | + isCloseButton = {true} | ||
| 149 | + onClick = {props.onCancelSearchHospital} | ||
| 150 | + > | ||
| 151 | + 취소 | ||
| 152 | + </styled.ModalButton> | ||
| 153 | + </styled.ModalButtonWrapper> | ||
| 154 | + </styled.ModalContent> | ||
| 155 | + </styled.ModalContentWrapper> | ||
| 156 | + <styled.ModalClsButtonWrapper /> | ||
| 157 | + </styled.ModalContainer> | ||
| 158 | + :null | ||
| 159 | + } | ||
| 42 | <styled.RegisterWrapper> | 160 | <styled.RegisterWrapper> |
| 43 | <styled.RegisterBackButtonWrapper> | 161 | <styled.RegisterBackButtonWrapper> |
| 44 | <styled.RegisterBackButton | 162 | <styled.RegisterBackButton |
| ... | @@ -118,27 +236,33 @@ const RegisterPresenter = (props : RegisterProps) => { | ... | @@ -118,27 +236,33 @@ const RegisterPresenter = (props : RegisterProps) => { |
| 118 | props.page === 3 ? | 236 | props.page === 3 ? |
| 119 | <> | 237 | <> |
| 120 | <styled.RegisterInputWrapper> | 238 | <styled.RegisterInputWrapper> |
| 121 | - <styled.RegisterInputText>전문 분야</styled.RegisterInputText> | 239 | + <styled.RegisterInputText>병원</styled.RegisterInputText> |
| 122 | - <styled.RegisterInput | 240 | + <styled.RegisterInputWrapperForSearch> |
| 123 | - placeholder = "Doctor's Type" | ||
| 124 | - value = {props.registerForm.info.doctorType} | ||
| 125 | - onChange = {props.onSetDoctorType} | ||
| 126 | - /> | ||
| 127 | - </styled.RegisterInputWrapper> | ||
| 128 | - <styled.RegisterInputWrapper> | ||
| 129 | - <styled.RegisterInputText>병원 이름</styled.RegisterInputText> | ||
| 130 | <styled.RegisterInput | 241 | <styled.RegisterInput |
| 131 | placeholder = 'Hospital' | 242 | placeholder = 'Hospital' |
| 132 | - value = {props.registerForm.info.hospitalNm} | 243 | + value = {props.hospitalNm} |
| 133 | onChange = {props.onSetHospitalNm} | 244 | onChange = {props.onSetHospitalNm} |
| 134 | /> | 245 | /> |
| 246 | + <styled.RegisterInputSearchButton | ||
| 247 | + onClick = {props.onSearchHospital} | ||
| 248 | + > | ||
| 249 | + <styled.RegisterInputSearchButtonImg src = {lensImg}/> | ||
| 250 | + </styled.RegisterInputSearchButton> | ||
| 251 | + </styled.RegisterInputWrapperForSearch> | ||
| 135 | </styled.RegisterInputWrapper> | 252 | </styled.RegisterInputWrapper> |
| 136 | <styled.RegisterInputWrapper> | 253 | <styled.RegisterInputWrapper> |
| 137 | - <styled.RegisterInputText>병원 주소</styled.RegisterInputText> | 254 | + <styled.RegisterInputText>주소</styled.RegisterInputText> |
| 138 | <styled.RegisterInput | 255 | <styled.RegisterInput |
| 139 | placeholder = 'Address' | 256 | placeholder = 'Address' |
| 140 | value = {props.registerForm.info.hospitalAddr} | 257 | value = {props.registerForm.info.hospitalAddr} |
| 141 | - onChange = {props.onSetHospitalAddr} | 258 | + /> |
| 259 | + </styled.RegisterInputWrapper> | ||
| 260 | + <styled.RegisterInputWrapper> | ||
| 261 | + <styled.RegisterInputText>전문 분야</styled.RegisterInputText> | ||
| 262 | + <styled.RegisterInput | ||
| 263 | + placeholder = "Doctor's Type" | ||
| 264 | + value = {props.registerForm.info.doctorType} | ||
| 265 | + onChange = {props.onSetDoctorType} | ||
| 142 | /> | 266 | /> |
| 143 | </styled.RegisterInputWrapper> | 267 | </styled.RegisterInputWrapper> |
| 144 | </> : null | 268 | </> : null | ... | ... |
| 1 | -import styled from 'styled-components'; | 1 | +import styled, { keyframes } from 'styled-components'; |
| 2 | + | ||
| 3 | + | ||
| 4 | +const ModalOn = keyframes ` | ||
| 5 | + 0% { | ||
| 6 | + background-color : rgba(52, 52, 52, .0); | ||
| 7 | + } | ||
| 8 | + 20% { | ||
| 9 | + background-color : rgba(52, 52, 52, .2); | ||
| 10 | + } | ||
| 11 | + 40% { | ||
| 12 | + background-color : rgba(52, 52, 52, .4); | ||
| 13 | + } | ||
| 14 | + 60% { | ||
| 15 | + background-color : rgba(52, 52, 52, .5); | ||
| 16 | + } | ||
| 17 | + 80% { | ||
| 18 | + background-color : rgba(52, 52, 52, .6); | ||
| 19 | + } | ||
| 20 | + 100% { | ||
| 21 | + background-color : rgba(52, 52, 52, .7); | ||
| 22 | + } | ||
| 23 | + | ||
| 24 | +`; | ||
| 2 | 25 | ||
| 3 | 26 | ||
| 4 | export const Container = styled.div ` | 27 | export const Container = styled.div ` |
| ... | @@ -10,6 +33,274 @@ export const Container = styled.div ` | ... | @@ -10,6 +33,274 @@ export const Container = styled.div ` |
| 10 | align-items : center; | 33 | align-items : center; |
| 11 | `; | 34 | `; |
| 12 | 35 | ||
| 36 | +export const ModalContainer = styled.div ` | ||
| 37 | + height : 100%; | ||
| 38 | + width : 100%; | ||
| 39 | + z-index : 99; | ||
| 40 | + position : absolute; | ||
| 41 | + | ||
| 42 | + display : flex; | ||
| 43 | + flex-direction : column; | ||
| 44 | + | ||
| 45 | + animation : ${ModalOn} .5s; | ||
| 46 | + | ||
| 47 | + background-color : rgba(52, 52, 52, .7); | ||
| 48 | + | ||
| 49 | +`; | ||
| 50 | + | ||
| 51 | +export const ModalClsButtonWrapper = styled.div ` | ||
| 52 | + flex : 1; | ||
| 53 | + | ||
| 54 | + display : flex; | ||
| 55 | + | ||
| 56 | + justify-content : flex-end; | ||
| 57 | + align-items : center; | ||
| 58 | + padding : 0 20px; | ||
| 59 | + | ||
| 60 | + border : none; | ||
| 61 | + background-color : transprent; | ||
| 62 | +`; | ||
| 63 | + | ||
| 64 | +export const ModalClsButton = styled.button ` | ||
| 65 | + border : none; | ||
| 66 | + background-color : transparent; | ||
| 67 | + | ||
| 68 | + cursor : pointer; | ||
| 69 | + | ||
| 70 | + color : #fff; | ||
| 71 | + | ||
| 72 | + display : flex; | ||
| 73 | + flex-direction : row; | ||
| 74 | + | ||
| 75 | + justify-content : center; | ||
| 76 | + align-items : center; | ||
| 77 | + | ||
| 78 | + transition : .25s all; | ||
| 79 | + &:hover { | ||
| 80 | + opacity : .5; | ||
| 81 | + } | ||
| 82 | +`; | ||
| 83 | + | ||
| 84 | +export const ModalClsButtonImg = styled.img ` | ||
| 85 | + height : 20px; | ||
| 86 | + width : 20px; | ||
| 87 | + | ||
| 88 | + margin : 0 10px 0 0; | ||
| 89 | +`; | ||
| 90 | + | ||
| 91 | +export const ModalClsButtonText = styled.div ` | ||
| 92 | + font-size : 18px; | ||
| 93 | + font-weight : 700; | ||
| 94 | +`; | ||
| 95 | + | ||
| 96 | +export const ModalContentWrapper = styled.div ` | ||
| 97 | + flex : 8; | ||
| 98 | + | ||
| 99 | + display : flex; | ||
| 100 | + flex-direction : column; | ||
| 101 | + | ||
| 102 | + justify-content : center; | ||
| 103 | + align-items : center; | ||
| 104 | + | ||
| 105 | + border : none; | ||
| 106 | +`; | ||
| 107 | + | ||
| 108 | +export const ModalContent = styled.div ` | ||
| 109 | + width : 600px; | ||
| 110 | + height : 400px; | ||
| 111 | + | ||
| 112 | + background-color : #fff; | ||
| 113 | + border : 1.2px solid #337DFF; | ||
| 114 | + border-radius : 5px; | ||
| 115 | + | ||
| 116 | + display : flex; | ||
| 117 | + flex-direction : column; | ||
| 118 | + | ||
| 119 | + justify-content : center; | ||
| 120 | + align-items : center; | ||
| 121 | +`; | ||
| 122 | + | ||
| 123 | +export const SearchTitle = styled.div ` | ||
| 124 | + font-weight : 600; | ||
| 125 | + font-size : 20; | ||
| 126 | + | ||
| 127 | + color : #337DFF; | ||
| 128 | + | ||
| 129 | +`; | ||
| 130 | + | ||
| 131 | +export const HospitalListWrapper = styled.div ` | ||
| 132 | + margin : 20px 0; | ||
| 133 | + | ||
| 134 | + height : 200px; | ||
| 135 | + width : 80%; | ||
| 136 | + | ||
| 137 | + border : 1px solid #337DFF; | ||
| 138 | + | ||
| 139 | + display : flex; | ||
| 140 | + flex-direction : column; | ||
| 141 | +`; | ||
| 142 | + | ||
| 143 | +export const HospitalListInfo = styled.div ` | ||
| 144 | + | ||
| 145 | + height : 20px; | ||
| 146 | + width : 100%; | ||
| 147 | + | ||
| 148 | + border : none; | ||
| 149 | + border-bottom : 1px solid #ddd; | ||
| 150 | + | ||
| 151 | + display : flex; | ||
| 152 | + flex-direction : row; | ||
| 153 | +`; | ||
| 154 | + | ||
| 155 | +export const HospitalListInfoEach = styled.div<{isLast : boolean}> ` | ||
| 156 | + flex : ${props => props.isLast ? '1' : '3'}; | ||
| 157 | + | ||
| 158 | + display : flex; | ||
| 159 | + align-items : center; | ||
| 160 | + justify-content : center; | ||
| 161 | + | ||
| 162 | + font-size : 14px; | ||
| 163 | + font-weight : 500; | ||
| 164 | + | ||
| 165 | + color : #343434; | ||
| 166 | + | ||
| 167 | + border : none; | ||
| 168 | + border-right : ${props => props.isLast ? 'none' : '1px solid #ddd'}; | ||
| 169 | + | ||
| 170 | + padding : 3px 5px; | ||
| 171 | +`; | ||
| 172 | + | ||
| 173 | +export const HospitalListEach = styled.div ` | ||
| 174 | + min-height : 35px; | ||
| 175 | + max-height : 35px; | ||
| 176 | + width : 100%; | ||
| 177 | + | ||
| 178 | + display : flex; | ||
| 179 | + flex-direction : row; | ||
| 180 | + | ||
| 181 | + border : none; | ||
| 182 | + border-bottom : 1px solid #ddd; | ||
| 183 | +`; | ||
| 184 | + | ||
| 185 | +export const HospitalListEachInfo = styled.div<{isLast : boolean}> ` | ||
| 186 | + flex : ${props => props.isLast ? '1' : '3'}; | ||
| 187 | + | ||
| 188 | + display : flex; | ||
| 189 | + | ||
| 190 | + font-size : 12px; | ||
| 191 | + font-weight : 500; | ||
| 192 | + | ||
| 193 | + justify-content : center; | ||
| 194 | + align-items : center; | ||
| 195 | + | ||
| 196 | + border : none; | ||
| 197 | + border-right : ${props => props.isLast ? 'none' : '1px solid #ddd'}; | ||
| 198 | + | ||
| 199 | + padding : 3px 5px; | ||
| 200 | +`; | ||
| 201 | + | ||
| 202 | +export const CheckButton = styled.button ` | ||
| 203 | + border : none; | ||
| 204 | + background-color : transparent; | ||
| 205 | + | ||
| 206 | + height : 15px; | ||
| 207 | + width : 15px; | ||
| 208 | + | ||
| 209 | + display : flex; | ||
| 210 | + flex-direction : row; | ||
| 211 | + justify-content : center; | ||
| 212 | + | ||
| 213 | + cursor : pointer; | ||
| 214 | + transition : .25s all; | ||
| 215 | + | ||
| 216 | + &:hover { | ||
| 217 | + opacity : .5; | ||
| 218 | + } | ||
| 219 | +`; | ||
| 220 | + | ||
| 221 | +export const CheckButtonImg = styled.img ` | ||
| 222 | + height : 15px; | ||
| 223 | + width : 15px; | ||
| 224 | +`; | ||
| 225 | + | ||
| 226 | +export const PageWrapper = styled.div ` | ||
| 227 | + width : 50%; | ||
| 228 | + display : flex; | ||
| 229 | + flex-direction : row; | ||
| 230 | + | ||
| 231 | + justify-content : center; | ||
| 232 | + align-items : center; | ||
| 233 | + | ||
| 234 | + gap : 2%; | ||
| 235 | +`; | ||
| 236 | + | ||
| 237 | +export const PageButton = styled.button<{isSelect : boolean}> ` | ||
| 238 | + height : 18px; | ||
| 239 | + width : 18px; | ||
| 240 | + | ||
| 241 | + display : flex; | ||
| 242 | + align-items : center; | ||
| 243 | + justify-content : center; | ||
| 244 | + | ||
| 245 | + border : none; | ||
| 246 | + border-radius : 4px; | ||
| 247 | + background-color : ${props => props.isSelect ? '#337DFF' : 'transparent'}; | ||
| 248 | + color : ${props => props.isSelect ? '#fff' : '#343434'}; | ||
| 249 | + | ||
| 250 | + font-size : 12px; | ||
| 251 | + font-weight : 600; | ||
| 252 | + | ||
| 253 | + cursor : pointer; | ||
| 254 | + | ||
| 255 | + transition : .25s all; | ||
| 256 | + | ||
| 257 | + &:hover { | ||
| 258 | + opacity : .7; | ||
| 259 | + } | ||
| 260 | +`; | ||
| 261 | + | ||
| 262 | +export const PageArrowImg = styled.img ` | ||
| 263 | + height : 15px; | ||
| 264 | + width : 15px; | ||
| 265 | +`; | ||
| 266 | + | ||
| 267 | +export const ModalButtonWrapper = styled.div ` | ||
| 268 | + margin : 20px 0 0 0; | ||
| 269 | + width : 50%; | ||
| 270 | + | ||
| 271 | + display : flex; | ||
| 272 | + flex-direction : row; | ||
| 273 | + | ||
| 274 | + justify-content : center; | ||
| 275 | + align-items : center; | ||
| 276 | + | ||
| 277 | + border : none; | ||
| 278 | + | ||
| 279 | + gap : 10%; | ||
| 280 | +`; | ||
| 281 | + | ||
| 282 | +export const ModalButton = styled.div<{isCloseButton : boolean}> ` | ||
| 283 | + padding : 2.5% 10%; | ||
| 284 | + cursor : pointer; | ||
| 285 | + | ||
| 286 | + border : 1px solid ${props => props.isCloseButton ? '#343434' : '#337DFF'}; | ||
| 287 | + background-color : ${props => props.isCloseButton ? 'transparent' : '#337DFF'}; | ||
| 288 | + | ||
| 289 | + border-radius : 5px; | ||
| 290 | + | ||
| 291 | + color : ${props => props.isCloseButton ? '#343434' : '#fff'}; | ||
| 292 | + font-weight : 600; | ||
| 293 | + font-size : 16px; | ||
| 294 | + | ||
| 295 | + transition : .25s all; | ||
| 296 | + | ||
| 297 | + &:hover { | ||
| 298 | + opacity : .7; | ||
| 299 | + } | ||
| 300 | + | ||
| 301 | +` | ||
| 302 | + | ||
| 303 | + | ||
| 13 | export const RegisterWrapper = styled.div ` | 304 | export const RegisterWrapper = styled.div ` |
| 14 | width : 35%; | 305 | width : 35%; |
| 15 | border : none; | 306 | border : none; |
| ... | @@ -24,10 +315,9 @@ export const RegisterWrapper = styled.div ` | ... | @@ -24,10 +315,9 @@ export const RegisterWrapper = styled.div ` |
| 24 | padding : 30px 3px; | 315 | padding : 30px 3px; |
| 25 | 316 | ||
| 26 | box-shadow: 0px 0px 10px #a0a0a0; | 317 | box-shadow: 0px 0px 10px #a0a0a0; |
| 27 | - | ||
| 28 | - | ||
| 29 | `; | 318 | `; |
| 30 | 319 | ||
| 320 | + | ||
| 31 | export const RegisterBackButtonWrapper = styled.div ` | 321 | export const RegisterBackButtonWrapper = styled.div ` |
| 32 | width : 100%; | 322 | width : 100%; |
| 33 | border : none; | 323 | border : none; |
| ... | @@ -97,6 +387,18 @@ export const RegisterInputText = styled.div ` | ... | @@ -97,6 +387,18 @@ export const RegisterInputText = styled.div ` |
| 97 | 387 | ||
| 98 | `; | 388 | `; |
| 99 | 389 | ||
| 390 | +export const RegisterInputWrapperForSearch = styled.div ` | ||
| 391 | + display : flex; | ||
| 392 | + flex-direction : row; | ||
| 393 | + | ||
| 394 | + justify-content : center; | ||
| 395 | + | ||
| 396 | + width : 100%; | ||
| 397 | + | ||
| 398 | + border : none; | ||
| 399 | + background-color : transparent; | ||
| 400 | +`; | ||
| 401 | + | ||
| 100 | export const RegisterInput = styled.input ` | 402 | export const RegisterInput = styled.input ` |
| 101 | width : 80%; | 403 | width : 80%; |
| 102 | padding : 5px 10px; | 404 | padding : 5px 10px; |
| ... | @@ -111,6 +413,38 @@ export const RegisterInput = styled.input ` | ... | @@ -111,6 +413,38 @@ export const RegisterInput = styled.input ` |
| 111 | } | 413 | } |
| 112 | `; | 414 | `; |
| 113 | 415 | ||
| 416 | +export const RegisterInputSearchButton = styled.button ` | ||
| 417 | + position : absolute; | ||
| 418 | + | ||
| 419 | + height : 25px; | ||
| 420 | + width : 25px; | ||
| 421 | + | ||
| 422 | + align-self : end; | ||
| 423 | + | ||
| 424 | + margin : 0 0 1px 24%; | ||
| 425 | + | ||
| 426 | + background-color : transparent; | ||
| 427 | + border : none; | ||
| 428 | + | ||
| 429 | + transition : .25s all; | ||
| 430 | + &:hover { | ||
| 431 | + opacity : .5; | ||
| 432 | + } | ||
| 433 | + | ||
| 434 | + display : flex; | ||
| 435 | + flex-direction : row; | ||
| 436 | + | ||
| 437 | + justify-content : center; | ||
| 438 | + align-items : center; | ||
| 439 | + | ||
| 440 | + cursor : pointer; | ||
| 441 | +`; | ||
| 442 | + | ||
| 443 | +export const RegisterInputSearchButtonImg = styled.img ` | ||
| 444 | + height : 20px; | ||
| 445 | + width : 20px; | ||
| 446 | +`; | ||
| 447 | + | ||
| 114 | export const RegisterButtonWrapper = styled.div ` | 448 | export const RegisterButtonWrapper = styled.div ` |
| 115 | margin : 20px 0 0 0; | 449 | margin : 20px 0 0 0; |
| 116 | 450 | ... | ... |
-
Please register or login to post a comment