Skip to content

Commit

Permalink
Merge pull request #57 from eunji-0623/dev
Browse files Browse the repository at this point in the history
dev -> master
  • Loading branch information
eunji-0623 authored Jun 16, 2024
2 parents 0597f4c + b807782 commit f58d7fa
Show file tree
Hide file tree
Showing 13 changed files with 70 additions and 40 deletions.
17 changes: 10 additions & 7 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ module.exports = {
'import/no-absolute-path': 'off',

// jsx-a11y label-has-associated-control 규칙 설정
"jsx-a11y/label-has-associated-control": [ 2, {
"some": [ "nesting", "id" ]
}],
}
}
]
}
'jsx-a11y/label-has-associated-control': [
2,
{
some: ['nesting', 'id'],
},
],
},
},
],
};
Binary file added public/img/Avatar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ function AppLayout() {
<Route path="/dashboard/:id/edit" element={<DashboardEdit />} />
<Route path="/dashboard/:id" element={<DashboardForId />} />
<Route path="/mypage" element={<MyPage />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} />
<Route path="*" element={<NotFound />} />
</Routes>
);
Expand All @@ -32,8 +34,6 @@ function App() {
<BrowserRouter>
<Routes>
<Route index element={<Home />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<SignUp />} />
<Route
path="/*"
element={(
Expand Down
4 changes: 3 additions & 1 deletion src/api/users/apiUsers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,13 @@ export async function apiEditMyInfo(

// 프로필 이미지 업로드 api
export async function apiUploadImage(
body: FormData, // FormData로 받아오도록
body: FormData,
): Promise<EditImageResponse> {
const token = localStorage.getItem('Token'); // 저장된 토큰을 가져옴
const res = await instance.post<EditImageResponse>('/users/me/image', body, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: `Bearer ${token}`, // 토큰 사용
},
});
return handleResponse(res);
Expand Down
16 changes: 9 additions & 7 deletions src/components/UserProfileImg/UserProfileImg.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import styles from './UserProfileImg.module.scss';
import DefaultImg from '/img/Avatar.png';
/*
유저의 프로필 이미지 컴포넌트입니다.
프로필 이미지를 설정하지 않은 유저는 프로필 이미지가 없으므로,
Expand Down Expand Up @@ -34,23 +35,24 @@ function UserProfileImg({
}

// 대시보드 멤버들 표현에 사용되는 프로필 이미지
interface MembersProfileImgprops {
profileImageUrl : string | null;
}

export function MembersProfileImg({
isImg,
profileImageUrl,
nickname,
}: UserProfileImgProps) {
}: MembersProfileImgprops) {
return (
<div
className={styles.MembersProfileImg}
style={{
backgroundColor: profileImageUrl || '#fff',
}}
>
{isImg ? (
{profileImageUrl ? (
<img src={profileImageUrl} alt="프로필 이미지" className={styles.Img} />
) : (
<div className={styles.FirstName}>{nickname?.[0].toUpperCase()}</div>
<img src={DefaultImg} alt="프로필 기본 이미지" className={styles.Img} />
)}
</div>
);
Expand All @@ -65,10 +67,10 @@ interface UserProfileImgSvgProps {
profileImageUrl: string | undefined;
}

export function UserProfileImgSvg({ profileImageUrl }: UserProfileImgSvgProps) {
export function UserProfileImgSvg({ profileImageUrl = DefaultImg }: UserProfileImgSvgProps) {
return (
<img
src={profileImageUrl}
src={profileImageUrl || DefaultImg}
alt="프로필 이미지"
className={styles.UserProfileImgSvg}
/>
Expand Down
27 changes: 15 additions & 12 deletions src/contexts/UserContext.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import {
createContext,
useState,
useEffect,
ReactNode,
useMemo,
createContext, useState, useEffect, ReactNode, useMemo,
} from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import { apiInquireMyInfo } from '../api/apiModule';
import DefaultImg from '/img/Avatar.png'; // 이미지를 import

/*
현재 로그인된 유저의 정보를 가져오는 Context입니다.
Expand All @@ -28,6 +25,8 @@ export interface UserInfo {
interface UserContextProps {
userInfo: UserInfo | null;
setUserInfo: (info: UserInfo | null) => void;
userProfile: string;
setUserProfile: (url: string) => void;
}

interface UserProviderProps {
Expand All @@ -40,6 +39,7 @@ export const UserContext = createContext<UserContextProps | null>(null);
// UserProvider 컴포넌트
export function UserProvider({ children }: UserProviderProps) {
const [userInfo, setUserInfo] = useState<UserInfo | null>(null);
const [userProfile, setUserProfile] = useState<string>(DefaultImg); // DefaultImg를 초기값으로 설정
const navigate = useNavigate();
const location = useLocation();

Expand All @@ -63,6 +63,11 @@ export function UserProvider({ children }: UserProviderProps) {
try {
const info = await apiInquireMyInfo();
setUserInfo(info);
if (info.profileImageUrl === null) {
setUserProfile(DefaultImg);
} else {
setUserProfile(info.profileImageUrl);
}
} catch (error) {
navigate('/login');
}
Expand All @@ -73,13 +78,11 @@ export function UserProvider({ children }: UserProviderProps) {
}, [location.pathname, userInfo, navigate]);

const value = useMemo(
() => ({ userInfo, setUserInfo }),
[userInfo],
() => ({
userInfo, setUserInfo, userProfile, setUserProfile,
}), // userProfile과 setUserProfile 추가
[userInfo, userProfile],
);

return (
<UserContext.Provider value={value}>
{children}
</UserContext.Provider>
);
return <UserContext.Provider value={value}>{children}</UserContext.Provider>;
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,6 @@ function Members({ dashboardId }: { dashboardId: number | undefined }) {
{members.slice(0, maxMembersToShow).map((member) => (
<MembersProfileImg
key={member.id}
isImg={member.profileImageUrl !== null}
nickname={member.nickname}
profileImageUrl={member.profileImageUrl}
/>
))}
Expand Down
4 changes: 4 additions & 0 deletions src/pages/login-signup/components/utils/useLoginFrom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface LoginFormInputs {
password: string;
passwordCheck: string;
}

function useLoginForm() {
// Input value 값 상태 관리
const [values, setValues] = useState<LoginFormInputs>({
Expand All @@ -37,6 +38,7 @@ function useLoginForm() {
setIsModalOpen(false);
};

// 로그인 버튼 클릭 시 실행
const handleSubmit = async (e: { preventDefault: () => void }) => {
e.preventDefault();
setLoading(true); // 로그인 시도 중에는 버튼 비활성화
Expand All @@ -48,6 +50,8 @@ function useLoginForm() {
const response = await apiLoginRequest({ email, password });
setUser(response.user ?? null);
navigate('/mydashboard'); // 로그인 성공 시 mydashboard 페이지로 이동

// 페이지 새로고침
window.location.reload();
} catch (error) {
setIsModalOpen(true); // 로그인 실패 시 모달 창 띄우기
Expand Down
18 changes: 13 additions & 5 deletions src/pages/login-signup/components/utils/useSignUpForm.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState } from 'react';
import { useState, useContext } from 'react';
import { useNavigate } from 'react-router-dom';
import { UserContext } from '../../../../contexts/UserContext';
import { apiSignUp } from '../../../../api/apiModule';
import defaultProfileImgMaker from '../../../../utils/defaultProfileImgMaker';

// 회원가입 폼 제출 기능을 수행하는 함수입니다.
// useNavigate를 사용하여 폼 제출 시 다른 페이지로 이동하도록 구현했습니다.
Expand Down Expand Up @@ -43,9 +43,20 @@ function useSignUpForm() {
// 변경 성공 시 모달을 닫으면 자동으로 로그인 페이지로 이동
const closeSuccessModalAndReload = () => {
setIsModalOpen(false);
setValues({
email: '',
nickname: '',
password: '',
passwordCheck: '',
}); // 폼 값을 초기화
navigate('/login'); // 회원가입 성공 시 로그인 페이지로 이동
};

const userContext = useContext(UserContext);
if (!userContext) {
throw new Error('반드시 DashboardProvider 안에서 사용해야 합니다.');
}

// 회원가입 폼 제출
const handleSubmit = async (e: { preventDefault: () => void }) => {
e.preventDefault();
Expand All @@ -56,9 +67,6 @@ function useSignUpForm() {

try {
await apiSignUp({ email, nickname, password }); // 회원가입 API 호출

defaultProfileImgMaker({ name: nickname }); // 프로필 이미지 생성

setIsModalOpen(true); // 성공 시 모달 창 띄우기
} catch (error) {
setIsErrorModalOpen(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
@use '/src/styles/media.scss' as *;

.container {
width: 1024px;
width: auto;
max-width: 1024px;
}

.dashboardList {
Expand Down
2 changes: 1 addition & 1 deletion src/pages/myDashboard/index.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
overflow-x: auto;

@include mobile {
margin: 40px;
margin-left: 8px;
}
}
}
11 changes: 10 additions & 1 deletion src/pages/mypage/utils/useProfileChange.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useContext, useState, useEffect } from 'react';
import { UserContext } from '../../../contexts/UserContext';
import { apiEditMyInfo, apiUploadImage } from '../../../api/apiModule';
import defaultProfileImg from '../../../../public/img/test_img.png';
import defaultProfileImg from '../../../../public/img/Avatar.png';

// 닉네임과 프로필을 변경하는 함수입니다.
// 닉네임은 기존 값을 먼저 보여주며, 변경하고 변경 버튼을 누르면 닉네임이 변경됩니다.
Expand Down Expand Up @@ -66,6 +66,15 @@ function useProfileChange() {
const file = e.target.files[0];
setProfileImage(file);

// 파일 형식 검사
const validImageTypes = ['image/jpeg', 'image/png', 'image/svg+xml'];
if (!validImageTypes.includes(file.type)) {
// alert('Unsupported file type. Only JPEG, PNG, and SVG are allowed.');
return;
}

setProfileImage(file);

// URL.createObjectURL을 사용하여 새로운 이미지 URL 생성
const imageUrl = URL.createObjectURL(file);
setProfileImageUrl(imageUrl);
Expand Down
2 changes: 1 addition & 1 deletion src/utils/defaultProfileImgMaker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export function RandomColorPicker() {
// 현재 프로젝트에서 사용할 수 있도록 만든 프로필 이미지 생성기입니다.
// 이름(전체), size(필수 아님)을 prop으로 받습니다.
// 약 0.6kb정도의 svg 이미지 url이 나옵니다.
function defaultProfileImgMaker({ name, size = 50 }: SvgMakerProps) {
function defaultProfileImgMaker({ name, size = 38 }: SvgMakerProps) {
// 이름 첫글자
const initial = name.charAt(0).toUpperCase();

Expand Down

0 comments on commit f58d7fa

Please sign in to comment.