간편 로그인하기
-
-
diff --git a/src/pages/signup/signupScript.js b/src/pages/signup/signupScript.js
deleted file mode 100644
index 3ee9a6822..000000000
--- a/src/pages/signup/signupScript.js
+++ /dev/null
@@ -1,172 +0,0 @@
-document.addEventListener('DOMContentLoaded', () => {
- let isValidEmail = false;
- let isValidNickname = false;
- let isValidPassword = false;
- let isValidPasswordConfirmation = false;
-
- const inputEmail = document.getElementById('email');
- const inputNickname = document.getElementById('nickname');
- const inputPassword = document.getElementById('password');
- const inputPasswordConfirmation = document.getElementById(
- 'password-confirmation'
- );
- const btnTogglePasswordVisibleList = document.querySelectorAll(
- '.btn-password-visible'
- );
- const btnSignup = document.getElementById('btn-signup');
- const messageErrorEmail = document.getElementById('message-error-email');
- const messageErrorNickname = document.getElementById(
- 'message-error-nickname'
- );
- const messageErrorPassword = document.getElementById(
- 'message-error-password'
- );
- const messageErrorPasswordConfirmation = document.getElementById(
- 'message-error-password-confirmation'
- );
-
- const validateEmail = () => {
- const emailValue = inputEmail.value.trim();
- if (!emailValue) {
- showError(inputEmail, messageErrorEmail, '이메일을 입력해주세요.');
- isValidEmail = false;
- } else if (!checkEmailRegex(emailValue)) {
- showError(inputEmail, messageErrorEmail, '잘못된 이메일 형식입니다.');
- isValidEmail = false;
- } else {
- clearError(inputEmail, messageErrorEmail);
- isValidEmail = true;
- }
- updatebtnSignup();
- };
-
- const validateNickname = () => {
- const nicknameValue = inputNickname.value.trim();
- if (!nicknameValue) {
- showError(inputNickname, messageErrorNickname, '닉네임을 입력해주세요.');
- isValidNickname = false;
- } else {
- clearError(inputNickname, messageErrorNickname);
- isValidNickname = true;
- }
- updatebtnSignup();
- };
-
- const validatePassword = () => {
- const passwordValue = inputPassword.value.trim();
- if (!passwordValue) {
- showError(
- inputPassword,
- messageErrorPassword,
- '비밀번호를 입력해주세요.'
- );
- isValidPassword = false;
- } else if (passwordValue.length < 8) {
- showError(
- inputPassword,
- messageErrorPassword,
- '비밀번호를 8자 이상 입력해주세요'
- );
- isValidPassword = false;
- } else {
- clearError(inputPassword, messageErrorPassword);
- isValidPassword = true;
- }
- validatePasswordConfirmation();
- updatebtnSignup();
- };
-
- const validatePasswordConfirmation = () => {
- const passwordConfirmationValue = inputPasswordConfirmation.value.trim();
- const passwordValue = inputPassword.value.trim();
- if (!passwordConfirmationValue) {
- showError(
- inputPasswordConfirmation,
- messageErrorPasswordConfirmation,
- '비밀번호를 입력해주세요.'
- );
- } else if (passwordConfirmationValue !== passwordValue) {
- showError(
- inputPasswordConfirmation,
- messageErrorPasswordConfirmation,
- '비밀번호가 일치하지 않습니다.'
- );
- isValidPasswordConfirmation = false;
- } else {
- clearError(inputPasswordConfirmation, messageErrorPasswordConfirmation);
- isValidPasswordConfirmation = true;
- }
- updatebtnSignup();
- };
-
- const togglePasswordVisible = (e) => {
- e.preventDefault();
- const visibleBtn = e.currentTarget;
- const targetInput = visibleBtn.parentElement.querySelector('input');
- const visibleImg = visibleBtn.querySelector('.img-password-visible');
- if (targetInput.type === 'password') {
- targetInput.type = 'text';
- visibleImg.src = '/images/icons/eye-visible.svg';
- visibleImg.alt = '비밀번호 표시';
- } else {
- targetInput.type = 'password';
- visibleImg.src = '/images/icons/eye-invisible.svg';
- visibleImg.alt = '비밀번호 숨김';
- }
- };
-
- const updatebtnSignup = () => {
- if (
- isValidPassword &&
- isValidEmail &&
- isValidNickname &&
- isValidPasswordConfirmation
- ) {
- btnSignup.disabled = false;
- } else {
- btnSignup.disabled = true;
- }
- };
-
- const handleSubmit = (e) => {
- e.preventDefault();
- if (btnSignup.disabled) return;
- window.location.href = '/signin';
- };
-
- const checkEmailRegex = (email) => {
- const emailRegex = new RegExp('[a-z0-9]+@[a-z]+\\.[a-z]{2,3}');
- return emailRegex.test(email);
- };
-
- const showError = (input, errorMessageElement, message) => {
- input.classList.add('error');
- errorMessageElement.textContent = message;
- errorMessageElement.style.display = 'block';
- };
-
- const clearError = (input, errorMessageElement) => {
- input.classList.remove('error');
- errorMessageElement.textContent = '';
- errorMessageElement.style.display = 'none';
- };
-
- inputEmail.addEventListener('focusout', validateEmail);
- inputEmail.addEventListener('input', validateEmail);
- inputNickname.addEventListener('focusout', validateNickname);
- inputNickname.addEventListener('input', validateNickname);
- inputPassword.addEventListener('focusout', validatePassword);
- inputPassword.addEventListener('input', validatePassword);
- inputPasswordConfirmation.addEventListener(
- 'focusout',
- validatePasswordConfirmation
- );
- inputPasswordConfirmation.addEventListener(
- 'input',
- validatePasswordConfirmation
- );
- btnSignup.addEventListener('click', handleSubmit);
- btnTogglePasswordVisibleList.forEach((button) => {
- button.addEventListener('click', togglePasswordVisible);
- });
-});
diff --git a/src/pages/signup/signupScript.ts b/src/pages/signup/signupScript.ts
new file mode 100644
index 000000000..dd8ccd093
--- /dev/null
+++ b/src/pages/signup/signupScript.ts
@@ -0,0 +1,202 @@
+document.addEventListener('DOMContentLoaded', () => {
+ let isValidEmail = false;
+ let isValidNickname = false;
+ let isValidPassword = false;
+ let isValidPasswordConfirmation = false;
+
+ const inputEmail = document.getElementById('email');
+ const inputNickname = document.getElementById('nickname');
+ const inputPassword = document.getElementById('password');
+ const inputPasswordConfirmation = document.getElementById(
+ 'password-confirmation'
+ );
+ const btnTogglePasswordVisibleList = document.querySelectorAll(
+ '.btn-password-visible'
+ );
+ const btnSignup = document.getElementById('btn-signup');
+ const messageErrorEmail = document.getElementById('message-error-email');
+ const messageErrorNickname = document.getElementById(
+ 'message-error-nickname'
+ );
+ const messageErrorPassword = document.getElementById(
+ 'message-error-password'
+ );
+ const messageErrorPasswordConfirmation = document.getElementById(
+ 'message-error-password-confirmation'
+ );
+
+ const validateEmail = () => {
+ const inputEmailEl = inputEmail as HTMLInputElement;
+ const messageErrorEmailEl = messageErrorEmail as HTMLElement;
+ const emailValue = inputEmailEl.value.trim();
+ if (!emailValue) {
+ showError(inputEmailEl, messageErrorEmailEl, '이메일을 입력해주세요.');
+ isValidEmail = false;
+ } else if (!checkEmailRegex(emailValue)) {
+ showError(inputEmailEl, messageErrorEmailEl, '잘못된 이메일 형식입니다.');
+ isValidEmail = false;
+ } else {
+ clearError(inputEmailEl, messageErrorEmailEl);
+ isValidEmail = true;
+ }
+ updatebtnSignup();
+ };
+
+ const validateNickname = () => {
+ const nicknameEl = inputNickname as HTMLInputElement;
+ const messageErrorNicknameEl = messageErrorNickname as HTMLElement;
+ const nicknameValue = nicknameEl.value.trim();
+ if (!nicknameValue) {
+ showError(nicknameEl, messageErrorNicknameEl, '닉네임을 입력해주세요.');
+ isValidNickname = false;
+ } else {
+ clearError(nicknameEl, messageErrorNicknameEl);
+ isValidNickname = true;
+ }
+ updatebtnSignup();
+ };
+
+ const validatePassword = () => {
+ const passwordEl = inputPassword as HTMLInputElement;
+ const messageErrorPasswordEl = messageErrorPassword as HTMLElement;
+ const passwordValue = passwordEl.value.trim();
+ if (!passwordValue) {
+ showError(passwordEl, messageErrorPasswordEl, '비밀번호를 입력해주세요.');
+ isValidPassword = false;
+ } else if (passwordValue.length < 8) {
+ showError(
+ passwordEl,
+ messageErrorPasswordEl,
+ '비밀번호를 8자 이상 입력해주세요'
+ );
+ isValidPassword = false;
+ } else {
+ clearError(passwordEl, messageErrorPasswordEl);
+ isValidPassword = true;
+ }
+ validatePasswordConfirmation();
+ updatebtnSignup();
+ };
+
+ const validatePasswordConfirmation = () => {
+ const passwordConfirmationValue = (
+ inputPasswordConfirmation as HTMLInputElement
+ ).value.trim();
+ const passwordValue = (inputPassword as HTMLInputElement).value.trim();
+ if (!passwordConfirmationValue) {
+ showError(
+ inputPasswordConfirmation as HTMLInputElement,
+ messageErrorPasswordConfirmation as HTMLElement,
+ '비밀번호를 입력해주세요.'
+ );
+ } else if (passwordConfirmationValue !== passwordValue) {
+ showError(
+ inputPasswordConfirmation as HTMLInputElement,
+ messageErrorPasswordConfirmation as HTMLElement,
+ '비밀번호가 일치하지 않습니다.'
+ );
+ isValidPasswordConfirmation = false;
+ } else {
+ clearError(
+ inputPasswordConfirmation as HTMLInputElement,
+ messageErrorPasswordConfirmation as HTMLElement
+ );
+ isValidPasswordConfirmation = true;
+ }
+ updatebtnSignup();
+ };
+
+ const togglePasswordVisible = (
+ e: React.MouseEvent
+ ) => {
+ e.preventDefault();
+ const visibleBtn = e.currentTarget;
+ const targetInput = visibleBtn.parentElement?.querySelector('input');
+ const visibleImg: HTMLImageElement | null = visibleBtn.querySelector(
+ '.img-password-visible'
+ );
+ if (targetInput?.type === 'password') {
+ targetInput.type = 'text';
+ if (visibleImg) {
+ visibleImg.src = '/images/icons/eye-visible.svg';
+ visibleImg.alt = '비밀번호 표시';
+ }
+ } else {
+ if (targetInput && visibleImg) {
+ targetInput.type = 'password';
+ visibleImg.src = '/images/icons/eye-invisible.svg';
+ visibleImg.alt = '비밀번호 숨김';
+ }
+ }
+ };
+
+ const updatebtnSignup = () => {
+ const btnSignupEl = btnSignup as HTMLButtonElement;
+ if (
+ isValidPassword &&
+ isValidEmail &&
+ isValidNickname &&
+ isValidPasswordConfirmation
+ ) {
+ btnSignupEl.disabled = false;
+ } else {
+ btnSignupEl.disabled = true;
+ }
+ };
+
+ const handleSubmit = (e: React.MouseEvent) => {
+ e.preventDefault();
+ const btnSignupEl = btnSignup as HTMLButtonElement;
+ if (btnSignupEl.disabled) return;
+ window.location.href = '/signin';
+ };
+
+ const checkEmailRegex = (email: string) => {
+ const emailRegex = new RegExp('[a-z0-9]+@[a-z]+\\.[a-z]{2,3}');
+ return emailRegex.test(email);
+ };
+
+ const showError = (
+ input: HTMLInputElement,
+ errorMessageElement: HTMLElement,
+ message: string
+ ) => {
+ input.classList.add('error');
+ errorMessageElement.textContent = message;
+ errorMessageElement.style.display = 'block';
+ };
+
+ const clearError = (
+ input: HTMLInputElement,
+ errorMessageElement: HTMLElement
+ ) => {
+ input.classList.remove('error');
+ errorMessageElement.textContent = '';
+ errorMessageElement.style.display = 'none';
+ };
+
+ inputEmail?.addEventListener('focusout', validateEmail);
+ inputEmail?.addEventListener('input', validateEmail);
+ inputNickname?.addEventListener('focusout', validateNickname);
+ inputNickname?.addEventListener('input', validateNickname);
+ inputPassword?.addEventListener('focusout', validatePassword);
+ inputPassword?.addEventListener('input', validatePassword);
+ inputPasswordConfirmation?.addEventListener(
+ 'focusout',
+ validatePasswordConfirmation
+ );
+ inputPasswordConfirmation?.addEventListener(
+ 'input',
+ validatePasswordConfirmation
+ );
+ btnSignup?.addEventListener(
+ 'click',
+ handleSubmit as unknown as EventListener
+ );
+ btnTogglePasswordVisibleList.forEach((button) => {
+ button.addEventListener(
+ 'click',
+ togglePasswordVisible as unknown as EventListener
+ );
+ });
+});
diff --git a/src/utils/items.js b/src/utils/items.ts
similarity index 100%
rename from src/utils/items.js
rename to src/utils/items.ts
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
new file mode 100644
index 000000000..11f02fe2a
--- /dev/null
+++ b/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 000000000..9d379a3c4
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "esModuleInterop": true,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noFallthroughCasesInSwitch": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx"
+ },
+ "include": ["src"]
+}
diff --git a/visualwind.wrapper.tsx b/visualwind.wrapper.tsx
new file mode 100644
index 000000000..4f83d902c
--- /dev/null
+++ b/visualwind.wrapper.tsx
@@ -0,0 +1,35 @@
+import React from 'react';
+
+/**
+* 1. Add GLOBAL CSS files here. Typical candidates are added automatically :
+*/
+import './src/styles/global.css';
+
+/**
+ * 2. You can also add global providers here.
+ * You don't have to do this from the beginning, as simple dumb components will be rendered just okay without this.
+ * Come back here when you need to add global providers.
+ * Examples are given as comments.
+ * Refer to htts://www.visualwind.dev/configuration for further details.
+ */
+export default function Wrapper({ children: YOUR_COMPONENT }: React.PropsWithChildren): React.ReactElement {
+ return (
+ <>
+ {/* Place global providers here, common providers are given below, for example:*/}
+ {/* */}
+ {/* */}
+ {/* */}
+ {YOUR_COMPONENT}
+ {/* */}
+ {/* */}
+ {/* */}
+ >
+ );
+}
+
+/**
+ * 3. Now settings are done, you can:
+ * - save this file,
+ * - open your COMPONENT file again,
+ * - hit the arrow icon on the top right corner to render to start.
+ */
\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
new file mode 100644
index 000000000..e13144fd8
--- /dev/null
+++ b/vite.config.ts
@@ -0,0 +1,8 @@
+import { defineConfig } from 'vite';
+import react from '@vitejs/plugin-react';
+import svgr from 'vite-plugin-svgr';
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react(), svgr({ include: '**/*.svg' })],
+});