Skip to content
Merged
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
1 change: 0 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"plugins": ["prettier"],
"rules": {
"prettier/prettier": ["error"],
"no-unused-vars": "warn",
"@typescript-eslint/no-unused-vars": "warn"
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 λ‘˜μ΄ 같이 있으면 μΆ©λŒλ‚˜μ„œ κ²½κ³  밑쀄이 μ΄μƒν•˜κ²Œ λœ¨λ”λΌκ³ μš”
저희 μ–΄μ°¨ν”Ό typescript만 μ‚¬μš©ν•˜λ‹ˆκΉŒ μœ„μ—κ±΄ μ§€μ› μŠ΅λ‹ˆλ‹€.

}
}
14 changes: 0 additions & 14 deletions src/app/mypage/components/Button.module.css

This file was deleted.

18 changes: 0 additions & 18 deletions src/app/mypage/components/Button.tsx

This file was deleted.

27 changes: 17 additions & 10 deletions src/app/mypage/components/FileInput.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
import { useEffect } from 'react';
import { ChangeEvent, useState } from 'react';
import Image from 'next/image';
import { UseFormSetValue } from 'react-hook-form';
import { FormValues } from './ProfileForm';
import styles from './FileInput.module.css';

interface FileInputProps {
name: 'imgFile';
setValue: UseFormSetValue<FormValues>;
id: string;
name: 'image';
setValue: (name: 'image', value: File | null) => void;
url?: string | null;
}

export default function FileInput({ name, setValue }: FileInputProps) {
const [preview, setPreview] = useState('');
export default function FileInput({ name, setValue, url, id }: FileInputProps) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

μš”κΈ°μ„œ name은 항상 'image' λ¬Έμžμ—΄ κ³ μ •κ°’ λ§žμ„κΉŒμš”?
그럼 νŒŒλΌλ―Έν„°λ‘œ μ•ˆλ°›μ•„λ„ λ˜λŠ”..λŠλ‚ŒμΌκΉŒμš”..?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

λ„€ image file input μš©λ„λ‘œλ§Œ μ‚¬μš©ν•  κ±° κ°™μ•„μ„œ 'image' κ³ μ •μž…λ‹ˆλ‹€.
νŒŒλΌλ―Έν„°λŠ” 없어도 λ˜κ² λ„€μš” πŸ‘€

const [preview, setPreview] = useState<string | null>(null);

const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
const file = event.target.files?.[0];
if (file) {
setPreview(URL.createObjectURL(file));
setValue('image', file);
setValue(name, file);
}
};

useEffect(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use client μ΅œμƒμœ„μ— μ„ μ–Έ μ•ˆν•΄μ€˜λ„ λ™μž‘ν•˜λ‚˜λ³΄κ΅°μš”?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

λΆ€λͺ¨μ»΄ν¬λ„ŒνŠΈκ°€ 'use client' 둜 λ˜μ–΄μžˆμœΌλ©΄ ν•„μš” μ—†κΈ΄ ν•œλ°...
곡용으둜 λΉΌλ €λ©΄ κ³ λ €ν•΄λ³Ό μ‚¬ν•­μ΄λ„€μš”..!

if (url) {
setPreview(url);
}
}, [url]);

return (
<>
<label className={styles.label} htmlFor={name}>
<label className={styles.label} htmlFor={id}>
{preview ? (
<Image src={preview} alt="미리보기" fill />
) : (
Expand All @@ -34,9 +41,9 @@ export default function FileInput({ name, setValue }: FileInputProps) {
<input
className={styles.input}
type="file"
accept="image/png, image/jpeg"
id={id}
name={name}
id={name}
accept="image/png, image/jpeg"
onChange={handleChange}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
}

.button {
line-height: 24px;
margin-top: 24px;
padding: 15px 113.5px;
}
Expand Down
1 change: 1 addition & 0 deletions src/app/mypage/components/Input.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
}

.input:read-only {
color: var(--gray-400);
outline: none;
}

Expand Down
28 changes: 17 additions & 11 deletions src/app/mypage/components/PasswordForm.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use client';

import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import Input from './Input';
import Button from './Button';
import styles from './PasswordForm.module.css';
import Button from '@/components/Button';
import { ERROR_MESSAGES } from '../constants/message';
import styles from './Form.module.css';
import { updatePassword } from '../lib/authHelper';

interface FormValues {
export interface PasswordFormValues {
currentPassword: string;
newPassword: string;
newPasswordConfirmation: string;
Expand All @@ -16,14 +16,18 @@ export default function PasswordForm() {
const {
register,
handleSubmit,
formState: { errors, isValid },
formState: { errors },
watch,
trigger,
} = useForm<FormValues>({ mode: 'onChange' });
setError,
reset,
} = useForm<PasswordFormValues>({ mode: 'onChange' });

const customIsValid = Object.keys(errors).length === 0;
const watchedPassword = watch('newPassword');

const onSubmit = () => {};
const onSubmit = async (data: PasswordFormValues) =>
updatePassword(data, reset, setError);

useEffect(() => {
if (watchedPassword) {
Expand All @@ -40,6 +44,8 @@ export default function PasswordForm() {
name="currentPassword"
label="ν˜„μž¬ λΉ„λ°€λ²ˆν˜Έ"
placeholder="λΉ„λ°€λ²ˆν˜Έ μž…λ ₯"
register={register('currentPassword')}
error={errors.currentPassword}
/>
<Input
className={styles.input}
Expand All @@ -50,7 +56,7 @@ export default function PasswordForm() {
register={register('newPassword', {
minLength: {
value: 8,
message: 'λΉ„λ°€λ²ˆν˜Έλ₯Ό 8자 이상 μž…λ ₯ν•΄μ£Όμ„Έμš”.',
message: ERROR_MESSAGES.PASSWORD_TOO_SHORT,
},
})}
error={errors.newPassword}
Expand All @@ -63,12 +69,12 @@ export default function PasswordForm() {
register={register('newPasswordConfirmation', {
validate: {
matchesPassword: (value) =>
value === watchedPassword || 'λΉ„λ°€λ²ˆν˜Έκ°€ μΌμΉ˜ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.',
value === watchedPassword || ERROR_MESSAGES.PASSWORDS_MATCH,
},
})}
error={errors.newPasswordConfirmation}
/>
<Button className={styles.button} type="submit" disabled={!isValid}>
<Button className={styles.button} type="submit" disabled={!customIsValid}>
λ³€κ²½
</Button>
</form>
Expand Down
28 changes: 0 additions & 28 deletions src/app/mypage/components/ProfileForm.module.css

This file was deleted.

49 changes: 37 additions & 12 deletions src/app/mypage/components/ProfileForm.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,54 @@
'use client';

import { useEffect } from 'react';
import { useForm } from 'react-hook-form';
import Button from './Button';
import Input from './Input';
import styles from './ProfileForm.module.css';
import useAuth from '../hooks/useAuth';
import FileInput from './FileInput';
import Input from './Input';
import Button from '@/components/Button';
import { updateProfile } from '../lib/authHelper';
import styles from './Form.module.css';

export interface FormValues {
image: File;
export interface ProfileFormValues {
image: File | null;
email: string;
nickname: string;
}

export default function ProfileForm() {
const { handleSubmit, setValue } = useForm<FormValues>();
const { user } = useAuth();
const {
register,
handleSubmit,
formState: { errors },
setValue,
reset,
} = useForm<ProfileFormValues>();

const onSubmit = () => {};
const customIsValid = Object.keys(errors).length === 0;

const onSubmit = async (data: ProfileFormValues) => updateProfile(data);

useEffect(() => {
if (user) {
const { email, nickname } = user;
reset({ email, nickname });
}
}, [reset, user]);

return (
<form className={styles.form} onSubmit={handleSubmit(onSubmit)}>
<h2>ν”„λ‘œν•„</h2>
<FileInput name="imgFile" setValue={setValue} />
<FileInput
id="image"
name="image"
setValue={setValue}
url={user?.profileImageUrl}
/>
<Input
className={styles.input}
type="text"
name="email"
label="이메일"
placeholder="test@email.com"
register={register('email')}
readOnly
/>
<Input
Expand All @@ -35,8 +57,11 @@ export default function ProfileForm() {
name="nickname"
label="λ‹‰λ„€μž„"
placeholder="λ‹‰λ„€μž„ μž…λ ₯"
register={register('nickname')}
/>
<Button className={styles.button}>μ €μž₯</Button>
<Button className={styles.button} type="submit" disabled={!customIsValid}>
μ €μž₯
</Button>
</form>
);
}
6 changes: 6 additions & 0 deletions src/app/mypage/constants/message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const ERROR_MESSAGES = {
CURRENT_PASSWORD_INCORRECT: 'ν˜„μž¬ λΉ„λ°€λ²ˆν˜Έκ°€ ν‹€λ ΈμŠ΅λ‹ˆλ‹€.',
PASSWORDS_MATCH: 'λΉ„λ°€λ²ˆν˜Έκ°€ μΌμΉ˜ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.',
SAME_AS_OLD_PASSWORD: 'κΈ°μ‘΄ λΉ„λ°€λ²ˆν˜Έμ™€ λ™μΌν•©λ‹ˆλ‹€.',
PASSWORD_TOO_SHORT: 'λΉ„λ°€λ²ˆν˜Έλ₯Ό 8자 이상 μž…λ ₯ν•΄μ£Όμ„Έμš”.',
};
43 changes: 43 additions & 0 deletions src/app/mypage/hooks/useAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import useAuthStore from '../store/authStore';
import axios from '../lib/axios';

const useAuth = () => {
const { user, accessToken, setUser, setAccessToken } = useAuthStore();
const isAuthenticated = !!accessToken;

const getMe = async () => {
try {
const response = await axios.get('/users/me');
setUser(response.data);
} catch (error) {
throw error;
}
};

const login = async () => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이건 개발 μž„μ‹œμš©μΈκ±ΈκΉŒμš”?!

try {
const response = await axios.post('/auth/login', {
email: '[email protected]',
password: '12341234',
});
setAccessToken(response.data.accessToken);
} catch (error) {
throw error;
}
};

const logout = async () => {
setAccessToken(null);
};

return {
user,
accessToken,
isAuthenticated,
getMe,
login,
logout,
};
};

export default useAuth;
Loading