Add, user modify
This commit is contained in:
@ -10,6 +10,7 @@ import PostCreate from "./pages/PostCreate";
|
||||
import PostEdit from "./pages/PostEdit";
|
||||
import PostCategory from "./pages/PostCategory";
|
||||
import Login from "./pages/Login";
|
||||
import Profile from "./pages/Profile";
|
||||
import { AuthProvider } from "./context/AuthContext";
|
||||
|
||||
function App() {
|
||||
@ -28,6 +29,7 @@ function App() {
|
||||
<Route path="/posts/:id/edit" element={<PostEdit />} />
|
||||
<Route path="/post/:category" element={<PostCategory />} />
|
||||
<Route path="/login" element={<Login />} />
|
||||
<Route path="/profile" element={<Profile />} />
|
||||
</Routes>
|
||||
</main>
|
||||
<Footer />
|
||||
|
@ -1,12 +1,11 @@
|
||||
import React from 'react';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { useAuth } from '../context/AuthContext'; // ✅ Context에서 로그인 상태 사용
|
||||
import { useAuth } from '../context/AuthContext';
|
||||
|
||||
const Navbar = () => {
|
||||
const navigate = useNavigate();
|
||||
const { isLoggedIn, logout } = useAuth();
|
||||
|
||||
// ✅ 'board' → 'posts'로 변경
|
||||
const menuItems = ['home', 'about', 'posts', 'paas', 'infra'];
|
||||
|
||||
return (
|
||||
@ -26,17 +25,27 @@ const Navbar = () => {
|
||||
</Link>
|
||||
))}
|
||||
|
||||
{isLoggedIn ? (
|
||||
<button
|
||||
onClick={() => {
|
||||
logout();
|
||||
navigate('/login');
|
||||
}}
|
||||
className="bg-gray-200 text-gray-700 px-4 py-2 rounded hover:bg-gray-300"
|
||||
>
|
||||
로그아웃
|
||||
</button>
|
||||
) : (
|
||||
{isLoggedIn && (
|
||||
<>
|
||||
<Link
|
||||
to="/profile"
|
||||
className="text-gray-600 hover:text-[#3B82F6]"
|
||||
>
|
||||
내 정보
|
||||
</Link>
|
||||
<button
|
||||
onClick={() => {
|
||||
logout();
|
||||
navigate('/login');
|
||||
}}
|
||||
className="bg-gray-200 text-gray-700 px-4 py-2 rounded hover:bg-gray-300"
|
||||
>
|
||||
로그아웃
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
|
||||
{!isLoggedIn && (
|
||||
<Link
|
||||
to="/login"
|
||||
className="bg-[#3B82F6] text-white px-4 py-2 rounded hover:bg-blue-700"
|
||||
|
@ -1,3 +1,4 @@
|
||||
// ./src/pages/Login.js
|
||||
import React, { useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import authApi from '../api/authApi';
|
||||
|
53
src/pages/Profile/EditForm.js
Normal file
53
src/pages/Profile/EditForm.js
Normal file
@ -0,0 +1,53 @@
|
||||
import React from 'react';
|
||||
|
||||
function EditForm({ form, onChange, onSubmit }) {
|
||||
return (
|
||||
<form onSubmit={onSubmit} className="bg-white p-8 rounded shadow-md w-full max-w-md mx-auto">
|
||||
<h2 className="text-2xl font-bold mb-6 text-center text-[#3B82F6]">회원정보 수정</h2>
|
||||
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">이름</label>
|
||||
<input
|
||||
name="name"
|
||||
value={form.name}
|
||||
onChange={onChange}
|
||||
className="w-full px-4 py-2 border border-gray-300 rounded"
|
||||
placeholder="이름을 입력하세요"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">이메일</label>
|
||||
<input
|
||||
name="email"
|
||||
type="email"
|
||||
value={form.email}
|
||||
onChange={onChange}
|
||||
className="w-full px-4 py-2 border border-gray-300 rounded"
|
||||
placeholder="이메일을 입력하세요"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">설명</label>
|
||||
<textarea
|
||||
name="desc"
|
||||
value={form.desc}
|
||||
onChange={onChange}
|
||||
rows="4"
|
||||
className="w-full px-4 py-2 border border-gray-300 rounded"
|
||||
placeholder="자기소개 또는 간단한 설명을 입력하세요"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<button
|
||||
type="submit"
|
||||
className="w-full bg-[#3B82F6] text-white py-2 rounded hover:bg-blue-700 transition"
|
||||
>
|
||||
수정
|
||||
</button>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
|
||||
export default EditForm;
|
58
src/pages/Profile/index.js
Normal file
58
src/pages/Profile/index.js
Normal file
@ -0,0 +1,58 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import EditForm from './EditForm';
|
||||
import authApi from '../../api/authApi';
|
||||
|
||||
function ProfilePage() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const [form, setForm] = useState({
|
||||
name: '',
|
||||
email: '',
|
||||
desc: '' // ✅ desc 상태 추가
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const token = localStorage.getItem('access');
|
||||
if (!token) {
|
||||
navigate('/login');
|
||||
return;
|
||||
}
|
||||
|
||||
const fetchUser = async () => {
|
||||
try {
|
||||
const res = await authApi.get('/api/auth/me/');
|
||||
const { name, email, desc } = res.data;
|
||||
setForm({ name, email, desc }); // ✅ desc 상태 반영
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
navigate('/login');
|
||||
}
|
||||
};
|
||||
|
||||
fetchUser();
|
||||
}, [navigate]);
|
||||
|
||||
const handleChange = (e) => {
|
||||
setForm({ ...form, [e.target.name]: e.target.value });
|
||||
};
|
||||
|
||||
const handleSubmit = async (e) => {
|
||||
e.preventDefault();
|
||||
try {
|
||||
await authApi.put('/api/auth/me/', form); // ✅ desc 포함해서 PUT
|
||||
alert('회원정보가 수정되었습니다.');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
alert('수정 실패');
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="container mt-5">
|
||||
<EditForm form={form} onChange={handleChange} onSubmit={handleSubmit} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProfilePage;
|
Reference in New Issue
Block a user