diff --git a/front/.gitignore b/front/.gitignore
index 4d29575..9f0d8d9 100644
--- a/front/.gitignore
+++ b/front/.gitignore
@@ -4,7 +4,7 @@
/node_modules
/.pnp
.pnp.js
-
+.env
# testing
/coverage
diff --git a/front/package.json b/front/package.json
index fd17a01..a9be182 100644
--- a/front/package.json
+++ b/front/package.json
@@ -14,6 +14,7 @@
"@types/react-dom": "^18.3.1",
"axios": "^1.7.8",
"class-variance-authority": "^0.7.0",
+ "dotenv": "^16.4.5",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^7.0.1",
diff --git a/front/src/Controller/fetch.signup.ts b/front/src/Controller/fetch.signup.ts
new file mode 100644
index 0000000..d2867b1
--- /dev/null
+++ b/front/src/Controller/fetch.signup.ts
@@ -0,0 +1,47 @@
+import supabaseInstance from '../Model/fetch.supabase.instance';
+
+interface SignUpParams {
+ email: string;
+ password: string;
+ admin: boolean;
+ job?: string; // Optional: name은 필수가 아닐 수 있음
+ nickname?: string;
+}
+
+const fetchSignUp = async ({ email, password, admin, job, nickname }: SignUpParams) => {
+ try {
+ const { data, error } = await supabaseInstance.auth.signUp({
+ email,
+ password,
+ options: {
+ data: {
+ // 사용자 정의 메타데이터로 전달
+ admin,
+ job,
+ nickname,
+ },
+ },
+ });
+
+ // 구조할당으로 responseMessage를 보내는 이유는 이 구조로 호출하는 쪽에서 명확하게 responseMessage와 data를 구분해서 사용할 수 있게 하기 위함이다. 즉, 반환 값은 객체이기 때문이다.
+ // 추가적으로 fetchSignup은 promise를 반환했다.
+
+ if (error) {
+ // error
+ console.error('SignUp Error:', error);
+ const errorMessage = error.message || 'Signup failed. Please try again.';
+ return { responseMessage: errorMessage, data: undefined };
+ }
+ // 성공적인 경우
+ const successMessage = 'Signup successful! Check your email for confirmation.';
+ return { responseMessage: successMessage, data };
+
+ // 예외가 발생할 경우
+ } catch (error: any) {
+ console.error('SignUp Error:', error);
+ const catchMessage = error.message || 'An unexpected error occurred. Please try again.';
+ return { responseMessage: catchMessage, data: undefined };
+ }
+};
+
+export default fetchSignUp;
diff --git a/front/src/Model/fetch.instance.ts b/front/src/Model/fetch.instance.ts
new file mode 100644
index 0000000..2486454
--- /dev/null
+++ b/front/src/Model/fetch.instance.ts
@@ -0,0 +1,12 @@
+import axios from 'axios';
+
+const axiosInstance = axios.create({
+ baseURL: 'https://fsrotjrwllkimiidizgk.supabase.co', // Supabase 프로젝트 URL
+ headers: {
+ apikey:
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZzcm90anJ3bGxraW1paWRpemdrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzMwMjgzMTQsImV4cCI6MjA0ODYwNDMxNH0.uiFog4O3BbOZhBC1z0LRFTtEE4p4z3PK5VQ5wKrRHzg', // Supabase API Key
+ 'Content-Type': 'application/json',
+ },
+});
+
+export default axiosInstance;
diff --git a/front/src/Model/fetch.supabase.instance.ts b/front/src/Model/fetch.supabase.instance.ts
new file mode 100644
index 0000000..d67cc61
--- /dev/null
+++ b/front/src/Model/fetch.supabase.instance.ts
@@ -0,0 +1,8 @@
+import { createClient } from '@supabase/supabase-js';
+
+const supabaseInstance = createClient(
+ 'https://bsrffkqymaqhwwqziqee.supabase.co',
+ 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImJzcmZma3F5bWFxaHd3cXppcWVlIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzMxMTc5NzMsImV4cCI6MjA0ODY5Mzk3M30.1UKuqvG0Ls3WxLvNkAHRASWyv8Y8coIJKe0M9tZ8flA',
+);
+
+export default supabaseInstance;
diff --git a/front/src/Page/Signup.tsx b/front/src/Page/Signup.tsx
index f11d989..83195aa 100644
--- a/front/src/Page/Signup.tsx
+++ b/front/src/Page/Signup.tsx
@@ -1,80 +1,77 @@
import React, { useState } from 'react';
-import { createClient } from '@supabase/supabase-js';
+import fetchSignUp from '../Controller/fetch.signup';
-const supabase = createClient(
- 'https://fsrotjrwllkimiidizgk.supabase.co',
- 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImZzcm90anJ3bGxraW1paWRpemdrIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MzMwMjgzMTQsImV4cCI6MjA0ODYwNDMxNH0.uiFog4O3BbOZhBC1z0LRFTtEE4p4z3PK5VQ5wKrRHzg',
-);
-
-const Signup: React.FC = () => {
+const Login = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
- const [name, setName] = useState('');
+ const [admin, setAdmin] = useState(false);
+ const [job, setJob] = useState('');
+ const [nickname, setNickName] = useState('');
const [responseMessage, setResponseMessage] = useState('');
const handleSignUp = async () => {
- try {
- const { data, error } = await supabase.auth.signUp({
- email,
- password,
- options: {
- data: {
- name, // 사용자 정의 메타데이터로 전달
- },
- },
- });
-
- if (error) {
- throw error;
- }
-
- setResponseMessage('Signup successful! Check your email for confirmation.');
- } catch (error: any) {
- setResponseMessage(error.message || 'Signup failed. Please try again.');
- }
+ const { responseMessage } = await fetchSignUp({
+ email,
+ password,
+ admin,
+ job,
+ nickname,
+ });
+ setResponseMessage(responseMessage);
};
return (
-
-
Sign Up
+
+
Sign Up
+ {/* Nickname */}
setName(e.target.value)}
- style={{ display: 'block', width: '100%', marginBottom: '10px', padding: '8px' }}
+ placeholder='nickname'
+ value={nickname}
+ onChange={(e) => setNickName(e.target.value)}
+ className='block w-full p-2 mb-3 border border-gray-300 rounded'
/>
+ {/* Job */}
+
+ {/* Email */}
setEmail(e.target.value)}
- style={{ display: 'block', width: '100%', marginBottom: '10px', padding: '8px' }}
+ className='block w-full p-2 mb-3 border border-gray-300 rounded'
/>
+ {/* Password */}
setPassword(e.target.value)}
- style={{ display: 'block', width: '100%', marginBottom: '10px', padding: '8px' }}
+ className='block w-full p-2 mb-3 border border-gray-300 rounded'
/>
+ {/* Sign Up Button */}
- {responseMessage &&
{responseMessage}
}
+ {responseMessage &&
{responseMessage}
}
);
};
-export default Signup;
+export default Login;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9f0757c..6a25ea2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -43,6 +43,9 @@ importers:
class-variance-authority:
specifier: ^0.7.0
version: 0.7.1
+ dotenv:
+ specifier: ^16.4.5
+ version: 16.4.5
react:
specifier: ^18.3.1
version: 18.3.1
@@ -1932,8 +1935,8 @@ packages:
caniuse-api@3.0.0:
resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==}
- caniuse-lite@1.0.30001684:
- resolution: {integrity: sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==}
+ caniuse-lite@1.0.30001685:
+ resolution: {integrity: sha512-e/kJN1EMyHQzgcMEEgoo+YTCO1NGCmIYHk5Qk8jT6AazWemS5QFKJ5ShCJlH3GZrNIdZofcNCEwZqbMjjKzmnA==}
case-sensitive-paths-webpack-plugin@2.4.0:
resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==}
@@ -2421,6 +2424,10 @@ packages:
resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==}
engines: {node: '>=10'}
+ dotenv@16.4.5:
+ resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
+ engines: {node: '>=12'}
+
duplexer@0.1.2:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
@@ -3054,8 +3061,8 @@ packages:
has-property-descriptors@1.0.2:
resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==}
- has-proto@1.0.3:
- resolution: {integrity: sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==}
+ has-proto@1.1.0:
+ resolution: {integrity: sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==}
engines: {node: '>= 0.4'}
has-symbols@1.0.3:
@@ -3305,8 +3312,8 @@ packages:
resolution: {integrity: sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==}
engines: {node: '>= 0.4'}
- is-number-object@1.0.7:
- resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==}
+ is-number-object@1.1.0:
+ resolution: {integrity: sha512-KVSZV0Dunv9DTPkhXwcZ3Q+tUc9TsaE1ZwX5J2WMvsSGS6Md8TFPun5uwh0yRdrNerI6vf/tbJxqSx4c1ZI1Lw==}
engines: {node: '>= 0.4'}
is-number@7.0.0:
@@ -3348,8 +3355,8 @@ packages:
resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
engines: {node: '>=8'}
- is-string@1.0.7:
- resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==}
+ is-string@1.1.0:
+ resolution: {integrity: sha512-PlfzajuF9vSo5wErv3MJAKD/nqf9ngAs1NFQYm16nUYFO2IzxJ2hcm+IOCg+EEopdykNNUhVq5cz35cAUxU8+g==}
engines: {node: '>= 0.4'}
is-symbol@1.0.4:
@@ -7762,7 +7769,7 @@ snapshots:
es-abstract: 1.23.5
es-object-atoms: 1.0.0
get-intrinsic: 1.2.4
- is-string: 1.0.7
+ is-string: 1.1.0
array-union@2.1.0: {}
@@ -7806,7 +7813,7 @@ snapshots:
es-array-method-boxes-properly: 1.0.0
es-errors: 1.3.0
es-object-atoms: 1.0.0
- is-string: 1.0.7
+ is-string: 1.1.0
array.prototype.tosorted@1.1.4:
dependencies:
@@ -7840,7 +7847,7 @@ snapshots:
autoprefixer@10.4.20(postcss@8.4.49):
dependencies:
browserslist: 4.24.2
- caniuse-lite: 1.0.30001684
+ caniuse-lite: 1.0.30001685
fraction.js: 4.3.7
normalize-range: 0.1.2
picocolors: 1.1.1
@@ -8045,7 +8052,7 @@ snapshots:
browserslist@4.24.2:
dependencies:
- caniuse-lite: 1.0.30001684
+ caniuse-lite: 1.0.30001685
electron-to-chromium: 1.5.67
node-releases: 2.0.18
update-browserslist-db: 1.1.1(browserslist@4.24.2)
@@ -8084,11 +8091,11 @@ snapshots:
caniuse-api@3.0.0:
dependencies:
browserslist: 4.24.2
- caniuse-lite: 1.0.30001684
+ caniuse-lite: 1.0.30001685
lodash.memoize: 4.1.2
lodash.uniq: 4.5.0
- caniuse-lite@1.0.30001684: {}
+ caniuse-lite@1.0.30001685: {}
case-sensitive-paths-webpack-plugin@2.4.0: {}
@@ -8573,6 +8580,8 @@ snapshots:
dotenv@10.0.0: {}
+ dotenv@16.4.5: {}
+
duplexer@0.1.2: {}
eastasianwidth@0.2.0: {}
@@ -8634,7 +8643,7 @@ snapshots:
globalthis: 1.0.4
gopd: 1.1.0
has-property-descriptors: 1.0.2
- has-proto: 1.0.3
+ has-proto: 1.1.0
has-symbols: 1.0.3
hasown: 2.0.2
internal-slot: 1.0.7
@@ -8644,7 +8653,7 @@ snapshots:
is-negative-zero: 2.0.3
is-regex: 1.2.0
is-shared-array-buffer: 1.0.3
- is-string: 1.0.7
+ is-string: 1.1.0
is-typed-array: 1.1.13
is-weakref: 1.0.2
object-inspect: 1.13.3
@@ -8679,7 +8688,7 @@ snapshots:
is-arguments: 1.1.1
is-map: 2.0.3
is-set: 2.0.3
- is-string: 1.0.7
+ is-string: 1.1.0
isarray: 2.0.5
stop-iteration-iterator: 1.0.0
@@ -8695,7 +8704,7 @@ snapshots:
globalthis: 1.0.4
gopd: 1.1.0
has-property-descriptors: 1.0.2
- has-proto: 1.0.3
+ has-proto: 1.1.0
has-symbols: 1.0.3
internal-slot: 1.0.7
iterator.prototype: 1.1.3
@@ -9296,7 +9305,7 @@ snapshots:
dependencies:
es-errors: 1.3.0
function-bind: 1.1.2
- has-proto: 1.0.3
+ has-proto: 1.1.0
has-symbols: 1.0.3
hasown: 2.0.2
@@ -9400,7 +9409,9 @@ snapshots:
dependencies:
es-define-property: 1.0.0
- has-proto@1.0.3: {}
+ has-proto@1.1.0:
+ dependencies:
+ call-bind: 1.0.7
has-symbols@1.0.3: {}
@@ -9644,8 +9655,9 @@ snapshots:
is-negative-zero@2.0.3: {}
- is-number-object@1.0.7:
+ is-number-object@1.1.0:
dependencies:
+ call-bind: 1.0.7
has-tostringtag: 1.0.2
is-number@7.0.0: {}
@@ -9675,8 +9687,9 @@ snapshots:
is-stream@2.0.1: {}
- is-string@1.0.7:
+ is-string@1.1.0:
dependencies:
+ call-bind: 1.0.7
has-tostringtag: 1.0.2
is-symbol@1.0.4:
@@ -12099,7 +12112,7 @@ snapshots:
call-bind: 1.0.7
for-each: 0.3.3
gopd: 1.1.0
- has-proto: 1.0.3
+ has-proto: 1.1.0
is-typed-array: 1.1.13
typed-array-byte-offset@1.0.3:
@@ -12108,7 +12121,7 @@ snapshots:
call-bind: 1.0.7
for-each: 0.3.3
gopd: 1.1.0
- has-proto: 1.0.3
+ has-proto: 1.1.0
is-typed-array: 1.1.13
reflect.getprototypeof: 1.0.7
@@ -12366,8 +12379,8 @@ snapshots:
dependencies:
is-bigint: 1.0.4
is-boolean-object: 1.1.2
- is-number-object: 1.0.7
- is-string: 1.0.7
+ is-number-object: 1.1.0
+ is-string: 1.1.0
is-symbol: 1.0.4
which-builtin-type@1.2.0: