Skip to content
Open
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
┣ 📦components <br/>
┃ ┣ 📜[Component1].jsx <br/>
┃ ┗ 📜[Component2].jsx <br/>
┣ 📜App.jsx <br/>
┣ 📜App.tsx <br/>
┣ 📜App.css <br/>
┣ 📜main.jsx <br/>
┣ 📜main.tsx <br/>

## 커밋 컨벤션

Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
31 changes: 23 additions & 8 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@
},
"devDependencies": {
"@eslint/js": "^9.30.1",
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@types/react": "^19.1.9",
"@types/react-dom": "^19.1.7",
"@vitejs/plugin-react": "^4.6.0",
"eslint": "^9.30.1",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.3.0",
"typescript": "^5.8.3",
"vite": "^7.0.4"
}
}
17 changes: 0 additions & 17 deletions src/App.jsx

This file was deleted.

40 changes: 40 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React, {useEffect, useState} from "react";
import "./App.css";
import SignIn from './components/SignInModal';
import SignUp from './components/SignUpModal';

function App() {
const [signIn, setSignIn] = useState<boolean>(false);
const [signUp, setSignUp] = useState<boolean>(false);
const mainStyle: React.CSSProperties = {
display: "flex",
gap: "2rem",
}
useEffect(() => {
const isModalOpen: boolean = signIn || signUp;
if (isModalOpen) document.body.style.overflow = "hidden";
else document.body.style.overflow = "";
return () => {
document.body.style.overflow = "";
}
}, [signIn, signUp])

const openSignInModal = () => {
setSignIn(true);
setSignUp(false);
}
const openSignUpModal = () => {
setSignUp(true);
setSignIn(false);
}
return (
<main style={mainStyle}>
<button onClick={openSignInModal}>Sign in</button>
<button onClick={openSignUpModal}>Sign up</button>
{signIn && <SignIn setSignIn={setSignIn} />}
{signUp && <SignUp setSignUp={setSignUp} />}
</main>
);
}

export default App;
37 changes: 37 additions & 0 deletions src/components/ModalContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';

const inputStyle: React.CSSProperties = {
width: "100%",
height: "2rem",
}
interface ModalContainerProps {
width: string | number,
height: string | number,
children?: React.ReactNode,
}
const ModalContainer: React.FC<ModalContainerProps> = ({width, height, children}: ModalContainerProps) => {
const modalStyle: React.CSSProperties = {
width: width,
height: height,
position: 'fixed',
left: '50%',
top: '50%',
transform: 'translate(-50%, -50%)',
zIndex: 2,
backgroundColor: 'white',
border: '1px solid #777',
borderRadius: '2rem',
padding: '2rem',
display: 'flex',
flexDirection: 'column',
gap: '1rem',
}
return (
<div style={modalStyle}>
{children}
</div>
)
}

export default ModalContainer
export { inputStyle }
38 changes: 38 additions & 0 deletions src/components/SignInModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React, {useRef, useState} from 'react';
import ModalContainer, { inputStyle } from "./ModalContainer";

interface SignInModalProps {
setSignIn: React.Dispatch<React.SetStateAction<boolean>>;
}
const SignInModal: React.FC<SignInModalProps> = ({setSignIn}: SignInModalProps) => {
const idRef = useRef<HTMLInputElement>(null);
const passwordRef = useRef<HTMLInputElement>(null);
const [errorMsg, setErrorMsg] = useState<string | null>(null);
const check = () => {
if(idRef.current?.value.length as number <= 0) {
idRef.current?.focus();
setErrorMsg("id를 입력해주세요.");
return;
}
else if(passwordRef.current?.value.length as number <= 0) {
passwordRef.current?.focus();
setErrorMsg("password를 입력해주세요.");
return;
}
alert("SignIn 성공");
setSignIn(false);
}
return (
<ModalContainer width={"20rem"} height={"14rem"}>
<input type="text" name="ID" style={inputStyle} ref={idRef} />
<input type="password" name="PASSWORD" style={inputStyle} ref={passwordRef} />
<p>{errorMsg}</p>
<div>
<button onClick={check}>SignIn</button>
<button onClick={()=>setSignIn(false)}>Close</button>
</div>
</ModalContainer>
)
}

export default SignInModal;
45 changes: 45 additions & 0 deletions src/components/SignUpModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import React, {useRef, useState} from 'react';
import ModalContainer, { inputStyle } from "./ModalContainer";

interface SignUpModalProps {
setSignUp: React.Dispatch<React.SetStateAction<boolean>>;
}
const SignUpModal: React.FC<SignUpModalProps> = ({setSignUp}: SignUpModalProps) => {
const nameRef = useRef<HTMLInputElement>(null);
const idRef = useRef<HTMLInputElement>(null);
const passwordRef = useRef<HTMLInputElement>(null);
const [errorMsg, setErrorMsg] = useState<string | null>(null);
const check = () => {
if(nameRef.current?.value.length as number <= 0) {
nameRef.current?.focus();
setErrorMsg("name를 입력해주세요.");
return;
}
if(idRef.current?.value.length as number <= 0) {
idRef.current?.focus();
setErrorMsg("id를 입력해주세요.");
return;
}
else if(passwordRef.current?.value.length as number <= 0) {
passwordRef.current?.focus();
setErrorMsg("password를 입력해주세요.");
return;
}
alert("SignUp 성공");
setSignUp(false);
}
return (
<ModalContainer width={"20rem"} height={"14rem"}>
<input type="text" name="NAME" style={inputStyle} ref={nameRef} />
<input type="text" name="ID" style={inputStyle} ref={idRef} />
<input type="password" name="PASSWORD" style={inputStyle} ref={passwordRef} />
<p>{errorMsg}</p>
<div>
<button onClick={check}>SignUp</button>
<button onClick={()=>setSignUp(false)}>Close</button>
</div>
</ModalContainer>
)
}

export default SignUpModal;
10 changes: 0 additions & 10 deletions src/main.jsx

This file was deleted.

5 changes: 5 additions & 0 deletions src/main.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'

createRoot(document.getElementById('root')).render(<App />)
1 change: 0 additions & 1 deletion vite.config.js → vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
})