diff --git a/components/Cards/index.tsx b/components/Cards/index.tsx deleted file mode 100644 index eacd7411c..000000000 --- a/components/Cards/index.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { useFetch } from '@/hooks/useFetch'; -import { formatDate, generateTimeText } from '@/hooks/date'; -import styles from '@/components/Cards/index.module.css'; -import Image from 'next/image'; -import { SyntheticEvent } from 'react'; - -export interface Link { - id: string; - url: string; - imageSource?: string; - title: string; - createdAt: Date; - description: string; -} - -interface FolderData { - folder: { - links: Link[]; - }; -} - -const AddThumbnail = (e: SyntheticEvent) => { - e.currentTarget.src = '/thumbnail.svg'; -}; - -function Cards({ url }: { url: string }) { - // props를 비구조화 할당하여 사용 - const CardData = useFetch(url); - - return ( -
- {CardData ? ( - CardData.folder.links.map((link: Link) => ( - -
-
- {link.imageSource ? ( - {link.title} - ) : ( - thumbnail_img - )} -
-
-
-

- {generateTimeText(link.createdAt)} -

-
-
-

{link.description}

-
-
- {formatDate(link.createdAt)} -
-
-
-
- )) - ) : ( -
저장된 링크가 없습니다
- )} -
- ); -} - -export default Cards; diff --git a/components/Cardsfolder/index.module.css b/components/FolderCards/index.module.css similarity index 96% rename from components/Cardsfolder/index.module.css rename to components/FolderCards/index.module.css index 5e6643fd7..f48d1d790 100644 --- a/components/Cardsfolder/index.module.css +++ b/components/FolderCards/index.module.css @@ -6,6 +6,10 @@ border-radius: 10px; } +.card :hover { + background-color: var(--gray10); +} + .card_txt_div_body { margin: 0.8rem 0; font-size: 1.2rem; @@ -100,8 +104,7 @@ text-align: center; padding: 0.7rem 0; } - -.isHovering { +.options:hover { background-color: var(--gray10); } diff --git a/components/Cardsfolder/index.tsx b/components/FolderCards/index.tsx similarity index 64% rename from components/Cardsfolder/index.tsx rename to components/FolderCards/index.tsx index 66ce25a65..2f22f4621 100644 --- a/components/Cardsfolder/index.tsx +++ b/components/FolderCards/index.tsx @@ -1,27 +1,28 @@ import { useFetch } from '@/hooks/useFetch'; -import { formatDate, generateTimeText } from '../../hooks/date'; +import { formatDate, generateTimeText } from '../../utils/date'; import thumbnail from '@/public/thumbnail.svg'; -import styles from '@/components/Cardsfolder/index.module.css'; +import styles from '@/components/FolderCards/index.module.css'; import starticon from '@/public/staricon.svg'; import moreoptionicon from '@/public/moreoptionicon.svg'; import { useState } from 'react'; import ModalFolder from '@/components/modal/ModalFolder'; import ModalDelete from '@/components/modal/ModalDelete'; import Image from 'next/image'; +import Link from 'next/link'; interface Link { id: string; url: string; - image_source?: string; // 이미지 소스는 옵셔널 + image_source?: string; + thumbnail?: string; title: string; created_at: Date; description: string; } -function Cardsfolder({ url }: { url: string }) { - // props를 비구조화 할당하여 사용 - const cardData = useFetch<{ data: Link[] }>(url); - const [hoverStates, setHoverStates] = useState([]); +function FolderCards({ url }: { url: string }) { + const card = useFetch<{ data: Link[] }>(url); + const cardData = card?.data; const [isModalOpen, setIsModalOpen] = useState(false); const [isModalDeleteOpen, setIsModalDeleteOpen] = useState(false); const [popoverStates, setPopoverStates] = useState<{ @@ -30,22 +31,6 @@ function Cardsfolder({ url }: { url: string }) { const [selectedCardDescription, setSelectedCardDescription] = useState(''); - const handleMouseOver = (index: number) => { - setHoverStates((prevStates) => { - const updatedStates = [...prevStates]; - updatedStates[index] = true; - return updatedStates; - }); - }; - - const handleMouseOut = (index: number) => { - setHoverStates((prevStates) => { - const updatedStates = [...prevStates]; - updatedStates[index] = false; - return updatedStates; - }); - }; - const handleCloseModal = () => { setIsModalOpen(false); }; @@ -56,6 +41,7 @@ function Cardsfolder({ url }: { url: string }) { const handleClickButton = () => { setIsModalOpen((prev) => !prev); + setIsModalDeleteOpen(false); }; const handleDeleteClickButton = (linkDescription: string) => { @@ -71,46 +57,25 @@ function Cardsfolder({ url }: { url: string }) { setSelectedCardDescription(linkDescription); }; - const handleFavoriteButtonClick = ( - e: React.MouseEvent - ) => { - e.stopPropagation(); - }; - - if (!cardData) { - return null; - } - return (
- {cardData.data.length ? ( - cardData.data.map((link, index) => ( -
handleMouseOver(index)} - onMouseOut={() => handleMouseOut(index)} - > - + {!cardData ? ( +
+

저장된 링크가 없습니다

+
+ ) : ( + cardData.map((link) => ( +
+
- {link.image_source ? ( - {link.title} - ) : ( - {link.title} - )} + {link.title}
@@ -128,7 +93,7 @@ function Cardsfolder({ url }: { url: string }) {
-
+
)} -
)) - ) : ( -
-

저장된 링크가 없습니다

-
)} {isModalOpen && ( (BASE_URL_FOLDER); - // styled-components를 사용하여 스타일링된 컴포넌트 생성 - const Container = styled.div` - display: flex; - justify-content: center; - align-items: center; - width: 100%; - height: 24.4rem; - padding: 2rem 0 6rem; - background-color: var(--light-blue); - `; - return ( - +
{folderData && (
- 프로필{folderData.folder.name}
)} - +
); } diff --git a/components/Foldermenu/foldermenu.module.css b/components/Foldermenu/foldermenu.module.css new file mode 100644 index 000000000..d630765a2 --- /dev/null +++ b/components/Foldermenu/foldermenu.module.css @@ -0,0 +1,23 @@ +.folderListContainer { + display: flex; + justify-content: start; + gap: 0.8rem; + position: relative; + flex-wrap: wrap; +} + +.folderMenuContainer { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: 2.4rem; + height: 3.2rem; + margin-bottom: 2.4rem; +} + +.imageContainer { + display: flex; + justify-content: center; + gap: 1.2rem; + height: 1.8rem; +} diff --git a/components/Foldermenu/index.tsx b/components/Foldermenu/index.tsx index 82709fc83..7fb467edb 100644 --- a/components/Foldermenu/index.tsx +++ b/components/Foldermenu/index.tsx @@ -1,21 +1,24 @@ import { useFetch } from '../../hooks/useFetch'; -import styled from 'styled-components'; import styles from './index.module.css'; import addfolderIcon from '@/public/addfolder.svg'; import deleteicon from '@/public/deleteicon.svg'; import changenameicon from '@/public/changenameicon.svg'; import shareicon from '@/public/shareicon.svg'; import { useState } from 'react'; -import Cardsfolder from '@/components/Cardsfolder'; +import FolderCards from '@/components/FolderCards'; import ModalFolder from '@/components/modal/ModalFolder'; import ModalShare from '@/components/modal/ModalShare'; import ModalDelete from '@/components/modal/ModalDelete'; import SearchableBar from '@/components/SearchableBar'; import Image from 'next/image'; - -const BASE_FOLDER_ID = 'all'; - -interface Link { +import S from './foldermenu.module.css'; +import { + BASE_URL_FOLDER, + BASE_URL_ALL_FOLDER, + BASE_FOLDER_ID, +} from '@/constant/folder-constant'; + +interface Card { id: string; url: string; title: string; @@ -30,75 +33,36 @@ interface FolderResponse { data: Folder[]; } -const BASE_URL_FOLDER = 'https://bootcamp-api.codeit.kr/api/users/1/folders'; -const BASE_URL_ALL_FOLDER = 'https://bootcamp-api.codeit.kr/api/users/1/links'; - -const FolderListContainer = styled.div` - display: flex; - justify-content: start; - gap: 0.8rem; - position: relative; - flex-wrap: wrap; -`; - -const FolderMenuContainer = styled.div` - display: flex; - justify-content: space-between; - align-items: center; - margin-top: 2.4rem; - height: 3.2rem; - margin-bottom: 2.4rem; -`; - -const ImageContainer = styled.div` - display: flex; - justify-content: center; - gap: 1.2rem; - height: 1.8rem; -`; - function Foldermenu() { - const folderData = useFetch(BASE_URL_FOLDER); + const folder = useFetch(BASE_URL_FOLDER); + const folderNames = folder?.data; const [activeButton, setActiveButton] = useState('전체'); const [url, setUrl] = useState(BASE_URL_ALL_FOLDER); - const [isModalOpen, setIsModalOpen] = useState(false); - const [isModalShareOpen, setIsModalShareOpen] = useState(false); - const [isModalRenameOpen, setIsModalRenameOpen] = useState(false); - const [isModalDeleteOpen, setIsModalDeleteOpen] = useState(false); const [currentFolderId, setCurrentFolderId] = useState( BASE_FOLDER_ID ); - const [filteredLinks, setFilteredLinks] = useState([]); - - function handleCloseModal() { - setIsModalOpen(false); - } - function handleClickButton() { - setIsModalOpen(true); - } - - function handleCloseShareModal() { - setIsModalShareOpen(false); - } - function handleClickShareButton() { - setIsModalShareOpen(true); - } - - function handleCloseRenameModal() { - setIsModalRenameOpen(false); - } - function handleClickRenameButton() { - setIsModalRenameOpen(true); - } - - function handleCloseDeleteModal() { - setIsModalDeleteOpen(false); - } - function handleClickDeleteButton() { - setIsModalDeleteOpen(true); - } + const [filteredLinks, setFilteredLinks] = useState([]); + const [modalState, setModalState] = useState({ + addFolder: false, + shareFolder: false, + renameFolder: false, + deleteFolder: false, + }); + + const handleModalOpen = (modalType: string) => { + setModalState((prevState) => ({ + ...prevState, + [modalType]: true, + })); + }; - const handleSearch = (filteredLinks: Link[]) => { + const handleModalClose = (modalType: string) => { + setModalState((prevState) => ({ + ...prevState, + [modalType]: false, + })); + }; + const handleSearch = (filteredLinks: Card[]) => { setFilteredLinks(filteredLinks); }; @@ -119,7 +83,7 @@ function Foldermenu() {
- +
- {folderData?.data && - folderData?.data.map((folderdata) => ( + {folderNames && + folderNames.map((foldername) => ( ))} - -
+
- +

{activeButton}

{activeButton === '전체' && ( - - - - - +
)} -
- +
+ - {isModalOpen && ( + {modalState.addFolder && ( handleModalClose('addFolder')} buttonName={'추가하기'} - isModalOpen={isModalOpen} + isModalOpen={modalState.addFolder} /> )} - {isModalShareOpen && ( + {modalState.shareFolder && ( handleModalClose('shareFolder')} + isModalOpen={modalState.shareFolder} currentFolderId={currentFolderId} /> )} - {isModalRenameOpen && ( + {modalState.renameFolder && ( handleModalClose('renameFolder')} buttonName={'변경하기'} - isModalOpen={isModalRenameOpen} + isModalOpen={modalState.renameFolder} /> )} - {isModalDeleteOpen && ( + {modalState.deleteFolder && ( handleModalClose('deleteFolder')} + isModalOpen={modalState.deleteFolder} /> )} diff --git a/components/Footer/index.tsx b/components/Footer/index.tsx index 2b38b30c1..7e6bc7097 100644 --- a/components/Footer/index.tsx +++ b/components/Footer/index.tsx @@ -1,54 +1,7 @@ -import facebook from '@/public/facebook.svg'; -import twitter from '@/public/twitter.svg'; -import youtube from '@/public/youtube.svg'; -import instagram from '@/public/instagram.svg'; +import { snsLists } from '@/constant/footer-constant'; import styles from '@/components/Footer/index.module.css'; import Image from 'next/image'; -interface SnsList { - id: string; - link: string; - img: string; - height: string; - width: string; - alt: string; -} - -const snsLists: SnsList[] = [ - { - id: '페이스북', - link: 'https://facebook.com/', - img: facebook, - height: '20', - width: '20', - alt: '페이스북 아이콘', - }, - { - id: '트위터', - link: 'https://twitter.com/', - img: twitter, - height: '20', - width: '20', - alt: '트위터 아이콘', - }, - { - id: '유튜브', - link: 'https://youtube.com/', - img: youtube, - height: '20', - width: '20', - alt: '유튜브 아이콘', - }, - { - id: '인스타그램', - link: 'https://instagram.com/', - img: instagram, - height: '20', - width: '20', - alt: '인스타그램 아이콘', - }, -]; - function Footer() { return (
diff --git a/components/IdInput/index.module.css b/components/IdInput/index.module.css index 4df68bcd2..fc8cc0fcd 100644 --- a/components/IdInput/index.module.css +++ b/components/IdInput/index.module.css @@ -17,7 +17,7 @@ color: var(--text-content-gray); } -.focused { +.input__form:focus { border: 1px solid var(--primary); } diff --git a/components/IdInput/index.tsx b/components/IdInput/index.tsx index 88e3e1b02..3904739b4 100644 --- a/components/IdInput/index.tsx +++ b/components/IdInput/index.tsx @@ -1,25 +1,26 @@ -import { useState } from 'react'; +import { ChangeEvent, useState } from 'react'; import styles from '@/components/IdInput/index.module.css'; -function IdInput({ placeholder = '내용을 입력하세요' }) { - const [value, setValue] = useState(''); - const [isError, setIsError] = useState(false); - const [ErrorMsg, setErrorMsg] = useState(''); - const [isFocused, setIsFocused] = useState(false); - - const handleFocus = () => { - setIsFocused(true); - }; +export interface InputProps { + value: string; + onChange: (value: string) => void; + placeholder: string; + isError: boolean; + ErrorMsg: string; + onBlur: () => void; +} - const handleBlur = () => { - setIsFocused(false); - if (value == '') { - setIsError(true); - setErrorMsg('내용을 입력하세요.'); - } else { - setIsError(false); - setErrorMsg(''); - } +function IdInput({ + value, + onChange, + placeholder, + isError, + ErrorMsg, + onBlur, +}: InputProps) { + const handleChange = (e: ChangeEvent) => { + const newValue = e.target.value; + onChange(newValue); }; return ( @@ -30,12 +31,9 @@ function IdInput({ placeholder = '내용을 입력하세요' }) { placeholder={placeholder} alt="아이디 인풋 폼" value={value} - onChange={(e) => setValue(e.target.value)} - onFocus={handleFocus} - onBlur={handleBlur} - className={`${styles.input__form} ${ - isFocused ? styles.focused : '' - } ${isError ? styles.error : ''}`} + onChange={handleChange} + onBlur={onBlur} + className={`${styles.input__form} ${isError ? styles.error : ''}`} />
{isError &&

{ErrorMsg}

} diff --git a/components/Navigation/index.module.css b/components/Navigation/index.module.css index fb0cc6ee7..af501dad6 100644 --- a/components/Navigation/index.module.css +++ b/components/Navigation/index.module.css @@ -3,7 +3,7 @@ justify-content: center; position: sticky; top: 0; - z-index: 1; + z-index: 99; width: 100%; background-color: var(--light-blue); } diff --git a/components/Navigation/index.tsx b/components/Navigation/index.tsx index 3ef59c9a1..9cb5fa8a6 100644 --- a/components/Navigation/index.tsx +++ b/components/Navigation/index.tsx @@ -3,6 +3,7 @@ import styles from './index.module.css'; import { useFetch } from '@/hooks/useFetch'; import Image from 'next/image'; import Link from 'next/link'; +import { BASE_URL_USER } from '@/constant/navigation-constant'; interface UserProfile { data: { @@ -11,8 +12,6 @@ interface UserProfile { }[]; } -const BASE_URL_USER = 'https://bootcamp-api.codeit.kr/api/users/1'; - function Navigation() { const userProfile = useFetch(BASE_URL_USER); @@ -28,7 +27,9 @@ function Navigation() { {userProfile ? (
- 유저 프로필사진(''); - const [isEyeOn, setIsEyeOn] = useState(false); - const [isError, setIsError] = useState(false); - const [ErrorMsg, setErrorMsg] = useState(''); - const [isFocused, setIsFocused] = useState(false); +function PasswordInput({ + value, + onChange, + placeholder, + isError, + ErrorMsg, + onBlur, +}: InputProps) { + const [isEyeOn, setIsEyeOn] = useState(false); const toggleEyeButton = () => { setIsEyeOn(!isEyeOn); }; - const handleFocus = () => { - setIsFocused(true); - }; - - const handleBlur = () => { - setIsFocused(false); - if (value == '') { - setIsError(true); - setErrorMsg('내용을 입력하세요.'); - } else { - setIsError(false); - setErrorMsg(''); - } + const handleChange = (e: ChangeEvent) => { + const newValue = e.target.value; + onChange(newValue); }; return ( <>
setValue(e.target.value)} - onFocus={handleFocus} - onBlur={handleBlur} - className={`${styles.input__form} ${ - isFocused ? styles.focused : '' - } ${isError ? styles.error : ''}`} + onChange={handleChange} + onBlur={onBlur} + className={`${styles.input__form} ${isError ? styles.error : ''}`} /> + + + +
+ + ); } diff --git a/pages/shared/index.module.css b/pages/shared/index.module.css new file mode 100644 index 000000000..6f6e9fe02 --- /dev/null +++ b/pages/shared/index.module.css @@ -0,0 +1,21 @@ +.pageDisplay { + display: flex; + row-gap: 4rem; + padding: 4rem 0 10rem; + flex-direction: column; + margin: 0 auto; + width: 106rem; + + @media (max-width: 1199px) { + margin-left: min(3.2rem) max(auto); + margin-right: min(3.2rem) max(auto); + } + + @media (max-width: 1123px) { + width: 70.4rem; + + @media (max-width: 767px) { + width: 32.5rem; + } + } +} diff --git a/pages/shared/index.tsx b/pages/shared/index.tsx index 6d509b00d..4a01673dd 100644 --- a/pages/shared/index.tsx +++ b/pages/shared/index.tsx @@ -1,45 +1,22 @@ import FolderData from '@/components/Folderdata'; import Navigation from '@/components/Navigation'; import SearchBar from '@/components/SearchBar'; -import Cards from '@/components/Cards'; -import styled from 'styled-components'; +import ShareCards from '@/components/ShareCards'; +import styles from './index.module.css'; import Footer from '@/components/Footer'; - -const BASE_URL_FOLDER_SAMPLE = - 'https://bootcamp-api.codeit.kr/api/sample/folder'; +import { BASE_URL_FOLDER_SAMPLE } from '@/constant/shared-constant'; /*테블릿 1124 이상 모바일 최소여백 32 테블릿 768~1199 모바일 375 ~767 */ -const PageDisplay = styled.div` - display: flex; - row-gap: 4rem; - padding: 4rem 0 10rem; - flex-direction: column; - margin: 0 auto; - width: 106rem; - - @media (max-width: 1199px) { - margin-left: min(3.2rem) max(auto); - margin-right: min(3.2rem) max(auto); - } - - @media (max-width: 1123px) { - width: 70.4rem; - - @media (max-width: 767px) { - width: 32.5rem; - } - } -`; function SharedPage() { return ( <> - +
- - + +
); diff --git a/pages/signin/index.module.css b/pages/signin/index.module.css index e26b5e787..71909c8f9 100644 --- a/pages/signin/index.module.css +++ b/pages/signin/index.module.css @@ -4,7 +4,7 @@ align-items: center; padding: 238px 0 253px; background-color: var(--light-blue); - height: 100%; + height: 100vh; @media (max-width: 1200px) { padding: 200px 0 291px; diff --git a/pages/signin/index.tsx b/pages/signin/index.tsx index ad16fb59b..38467b738 100644 --- a/pages/signin/index.tsx +++ b/pages/signin/index.tsx @@ -6,8 +6,65 @@ import S from './index.module.css'; import Link from 'next/link'; import googleIcon from '@/public/googlesns.svg'; import kakaoIcon from '@/public/kakaosns.svg'; +import { SIGN_IN_BASE_URL } from '../../constant/signin-constant'; +import { useRouter } from 'next/router'; +import useSignInId from '@/hooks/useSignInId'; +import useSignInPwd from '@/hooks/useSignInPwd'; +import { useEffect } from 'react'; export default function SignInPage() { + const router = useRouter(); + useEffect(() => { + const accessToken = localStorage.getItem('accessToken'); + if (accessToken) { + router.push('/folder'); + } + }, []); + const { + email, + isIdError, + idErrorMsg, + handleEmailChange, + handleIdBlur, + handleIdErrorOnSubmit, + } = useSignInId(); + + const { + password, + isPwdError, + pwdErrorMsg, + handlePasswordChange, + handlePwdBlur, + handlePWdErrorOnSubmit, + } = useSignInPwd(); + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + + try { + const response = await fetch(SIGN_IN_BASE_URL, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ email, password }), + }); + + if (!response.ok) { + throw new Error('로그인에 실패했습니다.'); + } + const data = await response.json(); + const { accessToken, refreshToken } = data; + localStorage.setItem('accessToken', accessToken); + localStorage.setItem('refreshToken', refreshToken); + + router.push('/folder'); + } catch (error) { + console.error('Error:', error); + handleIdErrorOnSubmit(); + handlePWdErrorOnSubmit(); + } + } return ( <>
@@ -24,24 +81,42 @@ export default function SignInPage() {

-
- - -
-
- - -
- +
+
+ + +
+
+ + +
+ +

소셜 로그인

- - +
diff --git a/pages/signup/index.module.css b/pages/signup/index.module.css index 26c1d2f0e..774a1c9d5 100644 --- a/pages/signup/index.module.css +++ b/pages/signup/index.module.css @@ -4,7 +4,7 @@ align-items: center; padding: 238px 0 253px; background-color: var(--light-blue); - height: 100%; + height: 100vh; @media (max-width: 1200px) { padding: 200px 0 291px; diff --git a/pages/signup/index.tsx b/pages/signup/index.tsx index fa7049927..5850ad5c0 100644 --- a/pages/signup/index.tsx +++ b/pages/signup/index.tsx @@ -6,8 +6,78 @@ import S from './index.module.css'; import Link from 'next/link'; import googleIcon from '@/public/googlesns.svg'; import kakaoIcon from '@/public/kakaosns.svg'; +import useSignUpId from '@/hooks/useSignUpId'; +import useSignUpPwd from '@/hooks/useSignUpPwd'; +import useSignUpPwdCheck from '@/hooks/useSignUpPwdCheck'; +import { useRouter } from 'next/router'; +import { SIGN_UP_BASE_URL } from '@/constant/signup-constant'; +import { useEffect } from 'react'; export default function SignUpPage() { + const router = useRouter(); + useEffect(() => { + const accessToken = localStorage.getItem('accessToken'); + if (accessToken) { + router.push('/folder'); + } + }, []); + + const { + email, + isIdError, + idErrorMsg, + handleEmailChange, + handleIdBlur, + handleIdErrorOnSubmit, + } = useSignUpId(); + + const { + password, + isPwdError, + pwdErrorMsg, + handlePasswordChange, + handlePwdBlur, + handlePWdErrorOnSubmit, + } = useSignUpPwd(); + + const { + passwordCheck, + isPwdCheckError, + pwdCheckErrorMsg, + handlePasswordCheckChange, + handlePwdCheckBlur, + handlePWdCheckErrorOnSubmit, + } = useSignUpPwdCheck({ password }); + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + + try { + const response = await fetch(SIGN_UP_BASE_URL, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ email, password }), + }); + + if (!response.ok) { + throw new Error('로그인에 실패했습니다.'); + } + const data = await response.json(); + const { accessToken, refreshToken } = data; + localStorage.setItem('accessToken', accessToken); + localStorage.setItem('refreshToken', refreshToken); + + router.push('/folder'); + } catch (error) { + console.error('Error:', error); + handleIdErrorOnSubmit(); + handlePWdErrorOnSubmit(); + handlePWdCheckErrorOnSubmit; + } + } + return ( <>
@@ -24,32 +94,51 @@ export default function SignUpPage() {

-
- - -
-
- - -
-
- - -
- +
+
+ + +
+
+ + +
+
+ + +
+ +

다른 방식으로 가입하기

- - +
diff --git a/pages/test/index.tsx b/pages/test/index.tsx deleted file mode 100644 index 42133398b..000000000 --- a/pages/test/index.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import IdInput from '@/components/IdInput'; -import PasswordInput from '@/components/PasswordInput'; - -function Test() { - return ( - <> - ; - - - ); -} - -export default Test; diff --git a/hooks/date.ts b/utils/date.ts similarity index 100% rename from hooks/date.ts rename to utils/date.ts diff --git a/utils/emailRegrex.js b/utils/emailRegrex.js new file mode 100644 index 000000000..53c5ea4cf --- /dev/null +++ b/utils/emailRegrex.js @@ -0,0 +1,6 @@ +const emailRegrex = /^[A-Za-z0-9_\.\-]+@[A-Za-z0-9\-]+\.[A-za-z0-9\-]+/; + +//이메일 검사 +export default function validateEmail(email) { + return new RegExp(emailRegrex).test(email); +}