From 357591a79137eaa7a4f9bbe136809c6c9824ecb7 Mon Sep 17 00:00:00 2001 From: Eunseo Sim <55528304+simeunseo@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:07:00 +0900 Subject: [PATCH 01/18] =?UTF-8?q?feat:=20Provider=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=95=88=EC=A0=95=EC=84=B1=20=EA=B0=95=ED=99=94=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=ED=83=80=EC=9E=85=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/entity/user.entity.ts | 3 ++- apps/api/src/user/dto/createLocalUser.dto.ts | 4 +++- apps/api/src/user/dto/createSocialUser.dto.ts | 4 +++- apps/api/src/user/dto/userProfileDto.ts | 3 ++- apps/api/src/user/dto/userProfileOfMeDto.ts | 3 ++- apps/api/src/user/user.controller.ts | 2 +- apps/api/src/user/user.service.ts | 4 ++-- apps/web/src/api/user.ts | 8 ++++++++ packages/types/src/index.ts | 1 + packages/types/src/user/index.ts | 2 ++ packages/types/src/user/provider.ts | 7 +++++++ packages/types/src/user/userProfileOfMe.ts | 11 +++++++++++ 12 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 apps/web/src/api/user.ts create mode 100644 packages/types/src/user/index.ts create mode 100644 packages/types/src/user/provider.ts create mode 100644 packages/types/src/user/userProfileOfMe.ts diff --git a/apps/api/src/entity/user.entity.ts b/apps/api/src/entity/user.entity.ts index 43cf31e0..c58c56a7 100644 --- a/apps/api/src/entity/user.entity.ts +++ b/apps/api/src/entity/user.entity.ts @@ -6,6 +6,7 @@ import { PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; +import { Provider } from '@repo/types'; import { Applicant } from './applicant.entity'; import { Ticle } from './ticle.entity'; @@ -34,7 +35,7 @@ export class User { profileImageUrl: string; @Column({ type: 'varchar', default: 'local' }) - provider: string; + provider: Provider; @Column({ type: 'varchar', name: 'social_id', nullable: true }) socialId: string; diff --git a/apps/api/src/user/dto/createLocalUser.dto.ts b/apps/api/src/user/dto/createLocalUser.dto.ts index 7460d4eb..fbe976a7 100644 --- a/apps/api/src/user/dto/createLocalUser.dto.ts +++ b/apps/api/src/user/dto/createLocalUser.dto.ts @@ -1,8 +1,10 @@ +import { Provider } from '@repo/types'; + export class CreateLocalUserDto { username: string; password: string; email: string; - provider: string; + provider: Provider; nickname?: string; introduce?: string; profileImageUrl?: string; diff --git a/apps/api/src/user/dto/createSocialUser.dto.ts b/apps/api/src/user/dto/createSocialUser.dto.ts index 5a22f6b7..481a1228 100644 --- a/apps/api/src/user/dto/createSocialUser.dto.ts +++ b/apps/api/src/user/dto/createSocialUser.dto.ts @@ -1,6 +1,8 @@ +import { Provider } from '@repo/types'; + export class CreateSocialUserDto { email: string; - provider: string; + provider: Provider; socialId: string; nickname?: string; introduce?: string; diff --git a/apps/api/src/user/dto/userProfileDto.ts b/apps/api/src/user/dto/userProfileDto.ts index 75eaaf64..6ed78c2b 100644 --- a/apps/api/src/user/dto/userProfileDto.ts +++ b/apps/api/src/user/dto/userProfileDto.ts @@ -1,4 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; +import { Provider } from '@repo/types'; export class UserProfileDto { @ApiProperty({ @@ -23,7 +24,7 @@ export class UserProfileDto { example: 'github', description: '유저 소셜 로그인 프로바이더', }) - provider: string; + provider: Provider; @ApiProperty({ example: ['개발자를 위한 피그마', '야, 너도 부캠할 수 있어'], diff --git a/apps/api/src/user/dto/userProfileOfMeDto.ts b/apps/api/src/user/dto/userProfileOfMeDto.ts index 320e23f4..b32b1f1d 100644 --- a/apps/api/src/user/dto/userProfileOfMeDto.ts +++ b/apps/api/src/user/dto/userProfileOfMeDto.ts @@ -1,4 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; +import { Provider } from '@repo/types'; export class UserProfileOfMeDto { @ApiProperty({ @@ -23,5 +24,5 @@ export class UserProfileOfMeDto { example: 'github', description: '유저 소셜 로그인 프로바이더', }) - provider: string; + provider: Provider; } diff --git a/apps/api/src/user/user.controller.ts b/apps/api/src/user/user.controller.ts index da8b3dbe..299e6f5b 100644 --- a/apps/api/src/user/user.controller.ts +++ b/apps/api/src/user/user.controller.ts @@ -1,4 +1,4 @@ -import { Controller, Get, Param, Patch, UseGuards } from '@nestjs/common'; +import { Controller, Get, Param, UseGuards } from '@nestjs/common'; import { JwtAuthGuard } from '@/auth/jwt/jwt-auth.guard'; import { GetUserId } from '@/common/decorator/get-userId.decorator'; diff --git a/apps/api/src/user/user.service.ts b/apps/api/src/user/user.service.ts index 5fea9db3..3562055b 100644 --- a/apps/api/src/user/user.service.ts +++ b/apps/api/src/user/user.service.ts @@ -2,7 +2,7 @@ import { ConflictException, Injectable, NotFoundException } from '@nestjs/common import { InjectRepository } from '@nestjs/typeorm'; import * as bcrypt from 'bcrypt'; import { Repository } from 'typeorm'; -import { ErrorMessage } from '@repo/types'; +import { ErrorMessage, Provider } from '@repo/types'; import { User } from '@/entity/user.entity'; @@ -57,7 +57,7 @@ export class UserService { return user; } - async findUserBySocialIdAndProvider(socialId: string, provider: string): Promise { + async findUserBySocialIdAndProvider(socialId: string, provider: Provider): Promise { const user = await this.userRepository.findOne({ where: { socialId, provider }, }); diff --git a/apps/web/src/api/user.ts b/apps/web/src/api/user.ts new file mode 100644 index 00000000..33021cb0 --- /dev/null +++ b/apps/web/src/api/user.ts @@ -0,0 +1,8 @@ +export const getDashboardTicleList = async (params: GetDashboardListQueryType) => { + return request({ + method: 'GET', + url: '/dashboard', + params, + schema: DashboardListResponseSchema, + }); +}; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index f1c3c0d0..228e700f 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -1,3 +1,4 @@ export * from './dashboard'; export * from './ticle'; +export * from './user'; export * from './errorMessages'; diff --git a/packages/types/src/user/index.ts b/packages/types/src/user/index.ts new file mode 100644 index 00000000..548461c4 --- /dev/null +++ b/packages/types/src/user/index.ts @@ -0,0 +1,2 @@ +export * from './provider'; +export * from './userProfileOfMe'; diff --git a/packages/types/src/user/provider.ts b/packages/types/src/user/provider.ts new file mode 100644 index 00000000..52975b3c --- /dev/null +++ b/packages/types/src/user/provider.ts @@ -0,0 +1,7 @@ +export const Provider = { + github: 'github', + google: 'google', + guest: 'guest', +} as const; + +export type Provider = (typeof Provider)[keyof typeof Provider]; diff --git a/packages/types/src/user/userProfileOfMe.ts b/packages/types/src/user/userProfileOfMe.ts new file mode 100644 index 00000000..02e20742 --- /dev/null +++ b/packages/types/src/user/userProfileOfMe.ts @@ -0,0 +1,11 @@ +import { z } from 'zod'; +import { Provider } from './provider'; + +export const UserProfileOfMeSchema = z.object({ + id: z.number(), + nickname: z.string(), + profileImageUrl: z.string().url(), + provider: z.enum([Provider.github, Provider.google, Provider.guest]), +}); + +export type UserProfileOfMeResponse = z.infer; From a95b1c52cc1c0ac04cee5a653f4607e36dd6a482 Mon Sep 17 00:00:00 2001 From: Eunseo Sim <55528304+simeunseo@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:32:43 +0900 Subject: [PATCH 02/18] =?UTF-8?q?feat:=20provider=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/auth/auth.service.ts | 5 +++-- apps/api/src/auth/github/github.strategy.ts | 5 +++-- apps/api/src/auth/google/google.strategy.ts | 5 +++-- apps/web/src/hooks/api/user.ts | 17 +++++++++++++++++ packages/types/src/user/index.ts | 1 + packages/types/src/user/provider.ts | 1 + packages/types/src/user/userProfile.ts | 12 ++++++++++++ 7 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 apps/web/src/hooks/api/user.ts create mode 100644 packages/types/src/user/userProfile.ts diff --git a/apps/api/src/auth/auth.service.ts b/apps/api/src/auth/auth.service.ts index 30baed98..2ecfe0d0 100644 --- a/apps/api/src/auth/auth.service.ts +++ b/apps/api/src/auth/auth.service.ts @@ -1,6 +1,7 @@ import { Injectable, UnauthorizedException } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; import * as bcrypt from 'bcrypt'; +import { Provider } from '@repo/types'; import { CreateSocialUserDto } from '@/user/dto/createSocialUser.dto'; import { UserService } from '@/user/user.service'; @@ -15,7 +16,7 @@ export class AuthService { ) {} async signupLocal(signupRequestDto: LocalSignupRequestDto) { - return this.userService.createLocalUser({ provider: 'local', ...signupRequestDto }); + return this.userService.createLocalUser({ provider: Provider.local, ...signupRequestDto }); } async validateLocalLogin(username: string, inputPassword: string) { @@ -45,7 +46,7 @@ export class AuthService { }; const user = await this.userService.findUserByUsername(guestUser.username); if (!user) { - return this.userService.createLocalUser({ provider: 'guest', ...guestUser }); + return this.userService.createLocalUser({ provider: Provider.guest, ...guestUser }); } return user; } diff --git a/apps/api/src/auth/github/github.strategy.ts b/apps/api/src/auth/github/github.strategy.ts index cf8c4502..6fdf01c6 100644 --- a/apps/api/src/auth/github/github.strategy.ts +++ b/apps/api/src/auth/github/github.strategy.ts @@ -2,11 +2,12 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; import { Profile, Strategy } from 'passport-github2'; +import { Provider } from '@repo/types'; import { AuthService } from '../auth.service'; @Injectable() -export class GitHubStrategy extends PassportStrategy(Strategy, 'github') { +export class GitHubStrategy extends PassportStrategy(Strategy, Provider.github) { constructor( private configService: ConfigService, private authService: AuthService @@ -23,7 +24,7 @@ export class GitHubStrategy extends PassportStrategy(Strategy, 'github') { const { id, username, emails, photos } = profile; const user = { - provider: 'github', + provider: Provider.github, socialId: id, nickname: username, email: emails[0].value, diff --git a/apps/api/src/auth/google/google.strategy.ts b/apps/api/src/auth/google/google.strategy.ts index 0d32ed2f..a4dd0aa3 100644 --- a/apps/api/src/auth/google/google.strategy.ts +++ b/apps/api/src/auth/google/google.strategy.ts @@ -2,11 +2,12 @@ import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; import { PassportStrategy } from '@nestjs/passport'; import { Profile, Strategy } from 'passport-google-oauth20'; +import { Provider } from '@repo/types'; import { AuthService } from '../auth.service'; @Injectable() -export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { +export class GoogleStrategy extends PassportStrategy(Strategy, Provider.google) { constructor( private configService: ConfigService, private authService: AuthService @@ -23,7 +24,7 @@ export class GoogleStrategy extends PassportStrategy(Strategy, 'google') { const { id, displayName, emails, photos } = profile; const user = { - provider: 'google', + provider: Provider.google, socialId: id, nickname: displayName, email: emails[0].value, diff --git a/apps/web/src/hooks/api/user.ts b/apps/web/src/hooks/api/user.ts new file mode 100644 index 00000000..a9de67ab --- /dev/null +++ b/apps/web/src/hooks/api/user.ts @@ -0,0 +1,17 @@ +import { useQuery } from '@tanstack/react-query'; + +import { getUserProfileByUserId, getUserProfileOfMe } from '@/api/user'; + +export const useUserProfileOfMe = () => { + return useQuery({ + queryKey: ['userProfileOfMe'], + queryFn: getUserProfileOfMe, + }); +}; + +export const useUserProfile = (userId: number) => { + return useQuery({ + queryKey: ['userProfile', userId], + queryFn: () => getUserProfileByUserId(userId), + }); +}; diff --git a/packages/types/src/user/index.ts b/packages/types/src/user/index.ts index 548461c4..76e10fc4 100644 --- a/packages/types/src/user/index.ts +++ b/packages/types/src/user/index.ts @@ -1,2 +1,3 @@ export * from './provider'; export * from './userProfileOfMe'; +export * from './userProfile'; diff --git a/packages/types/src/user/provider.ts b/packages/types/src/user/provider.ts index 52975b3c..02c472a8 100644 --- a/packages/types/src/user/provider.ts +++ b/packages/types/src/user/provider.ts @@ -2,6 +2,7 @@ export const Provider = { github: 'github', google: 'google', guest: 'guest', + local: 'local', } as const; export type Provider = (typeof Provider)[keyof typeof Provider]; diff --git a/packages/types/src/user/userProfile.ts b/packages/types/src/user/userProfile.ts new file mode 100644 index 00000000..ac9d33ba --- /dev/null +++ b/packages/types/src/user/userProfile.ts @@ -0,0 +1,12 @@ +import { z } from 'zod'; +import { Provider } from './provider'; + +export const UserProfileSchema = z.object({ + id: z.number(), + nickname: z.string(), + profileImageUrl: z.string().url(), + provider: z.enum([Provider.github, Provider.google, Provider.guest]), + ticles: z.array(z.string()), +}); + +export type UserProfileResponse = z.infer; From b9c8d0ee0092abfb6ca2ec9e06defc01ee0e105a Mon Sep 17 00:00:00 2001 From: Eunseo Sim <55528304+simeunseo@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:33:04 +0900 Subject: [PATCH 03/18] =?UTF-8?q?feat:=20user=20=EA=B4=80=EB=A0=A8=20api?= =?UTF-8?q?=20=ED=9B=85=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/api/user.ts | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/apps/web/src/api/user.ts b/apps/web/src/api/user.ts index 33021cb0..edefbf7e 100644 --- a/apps/web/src/api/user.ts +++ b/apps/web/src/api/user.ts @@ -1,8 +1,24 @@ -export const getDashboardTicleList = async (params: GetDashboardListQueryType) => { - return request({ +import { + UserProfileOfMeResponse, + UserProfileOfMeSchema, + UserProfileResponse, + UserProfileSchema, +} from '@repo/types'; + +import request from '@/hooks/api/request'; + +export const getUserProfileOfMe = async () => { + return request({ method: 'GET', - url: '/dashboard', - params, - schema: DashboardListResponseSchema, + url: '/user/me', + schema: UserProfileOfMeSchema, + }); +}; + +export const getUserProfileByUserId = async (userId: number) => { + return request({ + method: 'GET', + url: `/user/${userId}`, + schema: UserProfileSchema, }); }; From 592649d4d8ad1ebed6962e8c9a6be9c158c4c2ab Mon Sep 17 00:00:00 2001 From: Eunseo Sim <55528304+simeunseo@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:51:03 +0900 Subject: [PATCH 04/18] =?UTF-8?q?feat:=20Header=20=EB=82=B4=20=EC=9C=A0?= =?UTF-8?q?=EC=A0=80=20=EC=A0=95=EB=B3=B4=20UI=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/components/common/Avatar/index.tsx | 2 ++ .../src/components/common/Header/UserInfo.tsx | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 apps/web/src/components/common/Header/UserInfo.tsx diff --git a/apps/web/src/components/common/Avatar/index.tsx b/apps/web/src/components/common/Avatar/index.tsx index dc0762e6..fbbc5786 100644 --- a/apps/web/src/components/common/Avatar/index.tsx +++ b/apps/web/src/components/common/Avatar/index.tsx @@ -5,6 +5,7 @@ import PersonIc from '@/assets/icons/person.svg?react'; import cn from '@/utils/cn'; const AVATAR_SIZE = { + xs: 'xs', sm: 'sm', md: 'md', lg: 'lg', @@ -15,6 +16,7 @@ const avatarVariants = cva( { variants: { size: { + [AVATAR_SIZE.xs]: 'h-[30px] w-[30px]', [AVATAR_SIZE.sm]: 'h-[50px] w-[50px]', [AVATAR_SIZE.md]: 'h-[84px] w-[84px]', [AVATAR_SIZE.lg]: 'h-[100px] w-[100px]', diff --git a/apps/web/src/components/common/Header/UserInfo.tsx b/apps/web/src/components/common/Header/UserInfo.tsx new file mode 100644 index 00000000..0a9e081d --- /dev/null +++ b/apps/web/src/components/common/Header/UserInfo.tsx @@ -0,0 +1,16 @@ +import { useUserProfileOfMe } from '@/hooks/api/user'; + +import Avatar from '../Avatar'; + +function UserInfo() { + const { data } = useUserProfileOfMe(); + + return ( + + ); +} + +export default UserInfo; From e43f5ffb858d36bcd5543165a6c35ed06ba30bff Mon Sep 17 00:00:00 2001 From: Eunseo Sim <55528304+simeunseo@users.noreply.github.com> Date: Tue, 26 Nov 2024 22:51:52 +0900 Subject: [PATCH 05/18] =?UTF-8?q?feat:=20Avatar=20story=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/stories/Avatar.stories.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/web/src/stories/Avatar.stories.tsx b/apps/web/src/stories/Avatar.stories.tsx index 3aef381f..2c53c8cb 100644 --- a/apps/web/src/stories/Avatar.stories.tsx +++ b/apps/web/src/stories/Avatar.stories.tsx @@ -9,10 +9,10 @@ const meta: Meta = { argTypes: { size: { control: 'inline-radio', - options: ['sm', 'md', 'lg'], + options: ['xs', 'sm', 'md', 'lg'], description: '아바타의 크기를 지정합니다.', table: { - type: { summary: 'sm | md | lg' }, + type: { summary: 'xs | sm | md | lg' }, }, }, src: { @@ -45,6 +45,7 @@ import Avatar from '@/components/common/Avatar'; /> // Different sizes + @@ -77,7 +78,7 @@ export const Size: Story = { controls: { disable: true }, }, render: () => { - const sizes = ['sm', 'md', 'lg'] as const; + const sizes = ['xs', 'sm', 'md', 'lg'] as const; return (
{sizes.map((size) => ( @@ -96,7 +97,7 @@ export const WithAndWithoutImage: Story = { controls: { disable: true }, }, render: () => { - const sizes = ['sm', 'md', 'lg'] as const; + const sizes = ['xs', 'sm', 'md', 'lg'] as const; return (
From 0b41c5dee72d58c82f38ab309e35a1e271d73793 Mon Sep 17 00:00:00 2001 From: Eunseo Sim <55528304+simeunseo@users.noreply.github.com> Date: Tue, 26 Nov 2024 23:43:47 +0900 Subject: [PATCH 06/18] =?UTF-8?q?feat:=20=EC=9D=B8=EC=A6=9D=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=97=A4=EB=8D=94=20?= =?UTF-8?q?=EB=82=B4=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EB=B6=84=EA=B8=B0=20=EC=B2=98=EB=A6=AC=20=EC=9E=84=EC=8B=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/common/Header/UserInfo.tsx | 52 +++++++++++++++++-- .../src/components/common/Header/index.tsx | 11 ++-- apps/web/src/hooks/api/user.ts | 1 + 3 files changed, 53 insertions(+), 11 deletions(-) diff --git a/apps/web/src/components/common/Header/UserInfo.tsx b/apps/web/src/components/common/Header/UserInfo.tsx index 0a9e081d..1dea74a8 100644 --- a/apps/web/src/components/common/Header/UserInfo.tsx +++ b/apps/web/src/components/common/Header/UserInfo.tsx @@ -1,14 +1,58 @@ +import { Link } from '@tanstack/react-router'; +import axios from 'axios'; +import { Provider } from '@repo/types'; + +import UserProfileOfMeDialog from '@/components/user/UserProfileOfMeDialog'; import { useUserProfileOfMe } from '@/hooks/api/user'; +import useModal from '@/hooks/useModal'; import Avatar from '../Avatar'; +import Button from '../Button'; + +const LOGIN_TYPE: Record = { + github: 'Github 로그인', + google: 'Google 로그인', + guest: '게스트 로그인', + local: '티클 로그인', +}; function UserInfo() { - const { data } = useUserProfileOfMe(); + const { data, error, isLoading } = useUserProfileOfMe(); + const { isOpen, onOpen, onClose } = useModal(); + + const isUnauthorized = axios.isAxiosError(error) && error.response?.status === 401; + + const loginType = data?.provider && LOGIN_TYPE[data.provider]; + + const AuthorizedContent = () => ( + <> +
+ + {data?.nickname} +
+ {isOpen && data && loginType && ( + + )} + + ); + + const UnauthorizedContent = () => ( + +
+ +
+ + ); return ( -
+
+
+ + + ); +} + +export default UserProfileDialog; diff --git a/apps/web/src/components/user/UserProfileOfMeDialog.tsx b/apps/web/src/components/user/UserProfileOfMeDialog.tsx index a7b11659..c5b013f1 100644 --- a/apps/web/src/components/user/UserProfileOfMeDialog.tsx +++ b/apps/web/src/components/user/UserProfileOfMeDialog.tsx @@ -2,7 +2,7 @@ import UserInfo from './UserInfo'; import Button from '../common/Button'; import { Dialog } from '../common/Dialog'; -interface UserProfileOfMeProps { +interface UserProfileOfMeDialogProps { isOpen: boolean; onClose: () => void; profileImageUrl: string; @@ -10,7 +10,7 @@ interface UserProfileOfMeProps { loginType: string; } -function UserProfileOfMeDialog({ isOpen, onClose, ...userInfo }: UserProfileOfMeProps) { +function UserProfileOfMeDialog({ isOpen, onClose, ...userInfo }: UserProfileOfMeDialogProps) { const handleLogout = () => { // TODO: 로그아웃 처리 alert('로그아웃 기능은 준비 중입니다!'); @@ -20,7 +20,7 @@ function UserProfileOfMeDialog({ isOpen, onClose, ...userInfo }: UserProfileOfMe 내 프로필 - + diff --git a/apps/web/src/hooks/api/user.ts b/apps/web/src/hooks/api/user.ts index 15b91912..6a97188c 100644 --- a/apps/web/src/hooks/api/user.ts +++ b/apps/web/src/hooks/api/user.ts @@ -14,5 +14,6 @@ export const useUserProfile = (userId: number) => { return useQuery({ queryKey: ['userProfile', userId], queryFn: () => getUserProfileByUserId(userId), + enabled: !!userId, }); }; From 911369d7f051dad8f9de4977fe0a47ddcf1d2f55 Mon Sep 17 00:00:00 2001 From: Eunseo Sim <55528304+simeunseo@users.noreply.github.com> Date: Wed, 27 Nov 2024 00:38:53 +0900 Subject: [PATCH 12/18] =?UTF-8?q?feat:=20=ED=8B=B0=ED=81=B4=20=EC=83=81?= =?UTF-8?q?=EC=84=B8=20=ED=8E=98=EC=9D=B4=EC=A7=80=EC=97=90=EC=84=9C=20?= =?UTF-8?q?=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EB=B3=B4=EC=97=AC=EC=A3=BC=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/web/src/components/ticle/detail/index.tsx | 9 +++++++-- apps/web/src/components/user/UserInfo.tsx | 2 +- apps/web/src/components/user/UserProfileDialog.tsx | 5 +++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/web/src/components/ticle/detail/index.tsx b/apps/web/src/components/ticle/detail/index.tsx index 00adfa16..8b645de8 100644 --- a/apps/web/src/components/ticle/detail/index.tsx +++ b/apps/web/src/components/ticle/detail/index.tsx @@ -61,11 +61,16 @@ function Detail() { className="flex cursor-pointer flex-col items-center gap-3" onClick={handleProfileClick} > - + {data.speakerName} {isOpen && ( - + )}
{data.speakerIntroduce} diff --git a/apps/web/src/components/user/UserInfo.tsx b/apps/web/src/components/user/UserInfo.tsx index 4fbdda7e..b41ddcba 100644 --- a/apps/web/src/components/user/UserInfo.tsx +++ b/apps/web/src/components/user/UserInfo.tsx @@ -12,7 +12,7 @@ function UserInfo({ profileImageUrl, nickname, loginType }: UserInfoProps) {
- 이름 + 아이디 {nickname}
diff --git a/apps/web/src/components/user/UserProfileDialog.tsx b/apps/web/src/components/user/UserProfileDialog.tsx index 973747c8..85411fdc 100644 --- a/apps/web/src/components/user/UserProfileDialog.tsx +++ b/apps/web/src/components/user/UserProfileDialog.tsx @@ -10,9 +10,10 @@ interface UserProfileOfMeProps { isOpen: boolean; onClose: () => void; speakerId: number; + nickname: string; } -function UserProfileDialog({ isOpen, onClose, speakerId }: UserProfileOfMeProps) { +function UserProfileDialog({ isOpen, onClose, speakerId, nickname }: UserProfileOfMeProps) { const { data } = useUserProfile(speakerId); const navigate = useNavigate({ from: '/ticle/$ticleId' }); @@ -26,7 +27,7 @@ function UserProfileDialog({ isOpen, onClose, speakerId }: UserProfileOfMeProps) const loginType = data?.provider && LOGIN_TYPE[data.provider]; return ( - {data.nickname}님의 프로필 + {nickname}님의 프로필
From 71c878619fd3be8c89dc93525f57777677c203d4 Mon Sep 17 00:00:00 2001 From: Eunseo Sim <55528304+simeunseo@users.noreply.github.com> Date: Wed, 27 Nov 2024 00:56:11 +0900 Subject: [PATCH 13/18] =?UTF-8?q?feat:=20=ED=8B=B0=ED=81=B4=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EB=AA=A9=EB=A1=9D=EC=97=90=EC=84=9C=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EB=85=B8?= =?UTF-8?q?=EC=B6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/entity/ticle.entity.ts | 3 +++ apps/api/src/ticle/ticle.service.ts | 3 +++ apps/web/src/components/ticle/list/TicleCard.tsx | 2 +- apps/web/src/components/ticle/list/index.tsx | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/api/src/entity/ticle.entity.ts b/apps/api/src/entity/ticle.entity.ts index 145d8dbc..c79d50bc 100644 --- a/apps/api/src/entity/ticle.entity.ts +++ b/apps/api/src/entity/ticle.entity.ts @@ -74,4 +74,7 @@ export class Ticle { }, }) tags: Tag[]; + + @Column({ type: 'varchar', name: 'profile_image_url', nullable: true }) + profileImageUrl: string; } diff --git a/apps/api/src/ticle/ticle.service.ts b/apps/api/src/ticle/ticle.service.ts index 82707c68..31dae389 100644 --- a/apps/api/src/ticle/ticle.service.ts +++ b/apps/api/src/ticle/ticle.service.ts @@ -39,6 +39,7 @@ export class TicleService { applicants: [], summary: null, tags: tags, + profileImageUrl: user.profileImageUrl, }); return await this.ticleRepository.save(newTicle); @@ -162,6 +163,7 @@ export class TicleService { 'ticle.endTime', 'ticle.speakerName', 'ticle.createdAt', + 'ticle.profileImageUrl', ]) .addSelect('GROUP_CONCAT(DISTINCT tags.name)', 'tagNames') .addSelect('COUNT(DISTINCT applicant.id)', 'applicantCount') @@ -202,6 +204,7 @@ export class TicleService { speakerName: ticle.ticle_speaker_name, applicantsCount: ticle.applicantCount, createdAt: ticle.ticle_created_at, + profileImageUrl: ticle.ticle_profile_image_url, })); const totalPages = Math.ceil(totalTicleCount.count / pageSize); diff --git a/apps/web/src/components/ticle/list/TicleCard.tsx b/apps/web/src/components/ticle/list/TicleCard.tsx index 6e4a13ad..e53b5920 100644 --- a/apps/web/src/components/ticle/list/TicleCard.tsx +++ b/apps/web/src/components/ticle/list/TicleCard.tsx @@ -21,7 +21,7 @@ const TicleCard = ({ speakerProfileImg, }: TicleCardProps) => { return ( -
+

{title}

diff --git a/apps/web/src/components/ticle/list/index.tsx b/apps/web/src/components/ticle/list/index.tsx index 4890f7ca..dbe2ec8c 100644 --- a/apps/web/src/components/ticle/list/index.tsx +++ b/apps/web/src/components/ticle/list/index.tsx @@ -93,6 +93,7 @@ function TicleList() { date={getDateString(ticle.startTime, ticle.endTime)} speaker={ticle.speakerName} applicantsCount={ticle.applicantsCount} + speakerProfileImg={ticle.profileImageUrl} /> ))} From 0f907d7cf7048dd5e5b12fb6358b947c5c0ff678 Mon Sep 17 00:00:00 2001 From: Eunseo Sim <55528304+simeunseo@users.noreply.github.com> Date: Wed, 27 Nov 2024 01:11:24 +0900 Subject: [PATCH 14/18] =?UTF-8?q?feat:=20=ED=8B=B0=ED=81=B4=20=EC=A0=84?= =?UTF-8?q?=EC=B2=B4=20=EB=AA=A9=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=EC=97=90?= =?UTF-8?q?=EC=84=9C=20=ED=94=84=EB=A1=9C=ED=95=84=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EA=B0=80=EC=A0=B8=EC=98=A4=EB=8A=94=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/api/src/ticle/ticle.service.ts | 1 - apps/web/src/components/ticle/list/index.tsx | 4 ++-- packages/types/src/ticle/ticleList.ts | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/api/src/ticle/ticle.service.ts b/apps/api/src/ticle/ticle.service.ts index c80e5b6a..a2ec54c6 100644 --- a/apps/api/src/ticle/ticle.service.ts +++ b/apps/api/src/ticle/ticle.service.ts @@ -39,7 +39,6 @@ export class TicleService { applicants: [], summary: null, tags: tags, - profileImageUrl: user.profileImageUrl, }); return await this.ticleRepository.save(newTicle); diff --git a/apps/web/src/components/ticle/list/index.tsx b/apps/web/src/components/ticle/list/index.tsx index dbe2ec8c..b5ecd948 100644 --- a/apps/web/src/components/ticle/list/index.tsx +++ b/apps/web/src/components/ticle/list/index.tsx @@ -76,7 +76,7 @@ function TicleList() {