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
4 changes: 2 additions & 2 deletions src/components/auth/LoginCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ interface FloatingInputProps {
}

interface LoginResponse {
success: boolean
isSuccess: boolean
code: string
message: string
data: {
Expand Down Expand Up @@ -89,7 +89,7 @@ const LoginCard = () => {
})
.json<LoginResponse>()

if (res.success && res.data) {
if (res.isSuccess && res.data) {
localStorage.setItem('accessToken', res.data.accessToken)
localStorage.setItem('refreshToken', res.data.refreshToken)
navigate({ to: '/' })
Expand Down
18 changes: 13 additions & 5 deletions src/components/post/CommentItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,19 @@ export default function CommentItem({
onDoubleClick={() => onDoubleClick(comment.id)}
>
<div className="flex flex-1 gap-3">
<img
src={comment.profileImageUrl}
className={`${isReply ? 'h-6 w-6' : 'h-8 w-8'} shrink-0 rounded-full object-cover`}
alt=""
/>
{comment.profileImageUrl ? (
<img
src={comment.profileImageUrl}
className={`${isReply ? 'h-6 w-6' : 'h-8 w-8'} shrink-0 rounded-full object-cover`}
alt=""
/>
) : (
<div
className={`${isReply ? 'h-6 w-6 text-xs' : 'h-8 w-8 text-sm'} flex shrink-0 items-center justify-center rounded-full bg-gray-200 font-semibold text-gray-500`}
>
{comment.nickname.trim().slice(0, 1).toUpperCase() || '?'}
</div>
)}
<div className="text-sm">
<span className="mr-2 font-semibold text-black">
{comment.nickname}
Expand Down
2 changes: 1 addition & 1 deletion src/components/post/PostDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default function PostDetail() {
fetch(`/api/v1/posts/${postId}`)
.then((res) => res.json())
.then((json) => {
if (json.success) setPostData(json.data)
if (json.isSuccess) setPostData(json.data)
})
}, [postId])

Expand Down
34 changes: 23 additions & 11 deletions src/components/post/PostInfoSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default function PostInfoSection({ data }: { data: PostData | null }) {
)
const result = await response.json()

if (result.success && result.data.length > 0) {
if (result.isSuccess && result.data.length > 0) {
setComments((prev) => {
if (pageNum === 1) return result.data
const existingIds = new Set(prev.map((c) => c.id))
Expand Down Expand Up @@ -107,11 +107,17 @@ export default function PostInfoSection({ data }: { data: PostData | null }) {
<div className="flex h-full flex-col bg-white">
<div className="flex shrink-0 items-center justify-between border-b border-gray-200 px-4 py-3">
<div className="flex items-center gap-3">
<img
src={data?.userImage || ''}
className="h-8 w-8 rounded-full object-cover"
alt=""
/>
{data?.userImage ? (
<img
src={data.userImage}
className="h-8 w-8 rounded-full object-cover"
alt=""
/>
) : (
<div className="flex h-8 w-8 items-center justify-center rounded-full bg-gray-200 text-sm font-semibold text-gray-500">
{data?.username?.trim().slice(0, 1).toUpperCase() || '?'}
</div>
)}
<div className="text-sm font-semibold text-black">
{data?.username || ''}
</div>
Expand All @@ -129,11 +135,17 @@ export default function PostInfoSection({ data }: { data: PostData | null }) {
/>

<div className="mb-2 flex gap-3 px-1 py-3">
<img
src={data?.userImage || ''}
className="h-8 w-8 shrink-0 rounded-full object-cover"
alt=""
/>
{data?.userImage ? (
<img
src={data.userImage}
className="h-8 w-8 shrink-0 rounded-full object-cover"
alt=""
/>
) : (
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-gray-200 text-sm font-semibold text-gray-500">
{data?.username?.trim().slice(0, 1).toUpperCase() || '?'}
</div>
)}
<div className="text-sm text-black">
<span className="mr-2 font-semibold">{data?.username}</span>
<span className="whitespace-pre-wrap">{data?.caption}</span>
Expand Down
2 changes: 1 addition & 1 deletion src/entities/album/api/createAlbum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export async function createAlbum(

const parsed = CreateAlbumResponseSchema.parse(raw) as CreateAlbumResponse

if (!parsed.success) {
if (!parsed.isSuccess) {
throw new Error(parsed.message || 'Failed to create album')
}

Expand Down
2 changes: 1 addition & 1 deletion src/entities/album/api/getAlbumDetail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export async function getAlbumDetail(albumId: number): Promise<AlbumDetail> {

const parsed = ApiResponseSchema(AlbumDetailSchema).parse(raw)

if (!parsed.success) {
if (!parsed.isSuccess) {
throw new Error(parsed.message || 'Failed to load album')
}

Expand Down
2 changes: 1 addition & 1 deletion src/entities/album/api/getMyAlbums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export async function getMyAlbums(): Promise<AlbumSummary[]> {

const parsed = ApiResponseSchema(AlbumSummarySchema.array()).parse(raw)

if (!parsed.success) {
if (!parsed.isSuccess) {
throw new Error(parsed.message || 'Failed to load albums')
}

Expand Down
2 changes: 1 addition & 1 deletion src/entities/album/model/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const ApiResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>
code: z.string(),
message: z.string(),
data: dataSchema,
success: z.boolean(),
isSuccess: z.boolean(),
})

export const CreateAlbumResponseSchema = ApiResponseSchema(z.number())
Expand Down
2 changes: 1 addition & 1 deletion src/entities/feed/api/getFeed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export async function getFeed(params: GetFeedParams = {}): Promise<FeedPage> {

const parsed = ApiResponseSchema(FeedPageSchema).parse(raw)

if (!parsed.success) {
if (!parsed.isSuccess) {
throw new Error(parsed.message || 'Failed to load feed')
}

Expand Down
4 changes: 2 additions & 2 deletions src/entities/feed/model/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { z } from 'zod'
export const FeedAuthorSchema = z.object({
userId: z.number(),
nickname: z.string(),
profileImageUrl: z.string().min(1),
profileImageUrl: z.string().nullable(),
})

export const FeedItemSchema = z.object({
Expand Down Expand Up @@ -32,5 +32,5 @@ export const ApiResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>
code: z.string(),
message: z.string(),
data: dataSchema,
success: z.boolean(),
isSuccess: z.boolean(),
})
16 changes: 11 additions & 5 deletions src/entities/feed/ui/FeedCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,17 @@ export function FeedCard({ item, className, onOpenPost }: FeedCardProps) {

<CardHeader className="flex flex-row items-center gap-3 px-3 py-2">
<div className="size-8 shrink-0 overflow-hidden rounded-full bg-gray-200">
<img
src={item.author.profileImageUrl}
alt={`${item.author.nickname} 프로필`}
className="h-full w-full object-cover"
/>
{item.author.profileImageUrl ? (
<img
src={item.author.profileImageUrl}
alt={`${item.author.nickname} 프로필`}
className="h-full w-full object-cover"
/>
) : (
<div className="flex h-full w-full items-center justify-center text-sm font-semibold text-gray-500">
{item.author.nickname.trim().slice(0, 1).toUpperCase() || '?'}
</div>
)}
</div>
<div className="flex flex-col">
<span className="text-sm leading-tight font-semibold">
Expand Down
2 changes: 1 addition & 1 deletion src/entities/post/api/getBookmarkedPosts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export async function getBookmarkedPosts(): Promise<PostListItem[]> {

const parsed = ApiResponseSchema(PostListItemSchema.array()).parse(raw)

if (!parsed.success) {
if (!parsed.isSuccess) {
throw new Error(parsed.message || 'Failed to load bookmarked posts')
}

Expand Down
2 changes: 1 addition & 1 deletion src/entities/post/api/getExplorePosts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export async function getExplorePosts(): Promise<PostListItem[]> {

const parsed = ApiResponseSchema(PostListItemSchema.array()).parse(raw)

if (!parsed.success) {
if (!parsed.isSuccess) {
throw new Error(parsed.message || 'Failed to load explore posts')
}

Expand Down
4 changes: 2 additions & 2 deletions src/entities/post/model/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export const PostListItemSchema = z.object({
id: z.number(),
userId: z.number(),
nickname: z.string(),
profileImageUrl: z.string(),
profileImageUrl: z.string().nullable(),
content: z.string(),
albumId: z.number().nullable(),
images: z.array(PostImageSchema),
Expand All @@ -27,5 +27,5 @@ export const ApiResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>
code: z.string(),
message: z.string(),
data: dataSchema,
success: z.boolean(),
isSuccess: z.boolean(),
})
2 changes: 1 addition & 1 deletion src/entities/search/api/deleteRecentSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export async function deleteRecentSearch({
const raw = await response.json()
const parsed = DeleteRecentSearchResponseSchema.parse(raw)

if (!parsed.success) {
if (!parsed.isSuccess) {
throw new Error(parsed.message || 'Failed to delete recent search')
}
}
2 changes: 1 addition & 1 deletion src/entities/search/api/getRecentSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export async function getRecentSearch(): Promise<RecentSearchItem[]> {
const raw = await response.json()
const parsed = RecentSearchListResponseSchema.parse(raw)

if (!parsed.success) {
if (!parsed.isSuccess) {
throw new Error(parsed.message || 'Failed to load recent searches')
}

Expand Down
2 changes: 1 addition & 1 deletion src/entities/search/api/postRecentSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export async function postRecentSearch({
const raw = await response.json()
const parsed = PostRecentSearchResponseSchema.parse(raw)

if (!parsed.success) {
if (!parsed.isSuccess) {
throw new Error(parsed.message || 'Failed to save recent search')
}

Expand Down
1 change: 1 addition & 0 deletions src/entities/search/model/hooks/useRecentSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export function useRecentSearchQuery() {
return useQuery<RecentSearchItem[]>({
queryKey: RECENT_SEARCH_QUERY_KEY,
queryFn: getRecentSearch,
staleTime: Infinity,
})
}

Expand Down
10 changes: 5 additions & 5 deletions src/entities/search/model/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ export const RecentSearchItemSchema = z.object({
searchId: z.number(),
userId: z.number(),
nickname: z.string(),
profileImageUrl: z.string(),
name: z.string(),
profileImageUrl: z.string().nullable(),
name: z.string().nullable(),
followed: z.boolean(),
})

Expand All @@ -15,7 +15,7 @@ export const RecentSearchListResponseSchema = z.object({
data: z.object({
items: z.array(RecentSearchItemSchema),
}),
success: z.boolean(),
isSuccess: z.boolean(),
})

export const PostRecentSearchResponseSchema = z.object({
Expand All @@ -24,11 +24,11 @@ export const PostRecentSearchResponseSchema = z.object({
data: z.object({
searchId: z.number(),
}),
success: z.boolean(),
isSuccess: z.boolean(),
})

export const DeleteRecentSearchResponseSchema = z.object({
code: z.string(),
message: z.string(),
success: z.boolean(),
isSuccess: z.boolean(),
})
4 changes: 2 additions & 2 deletions src/entities/story/model/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import { z } from 'zod'
export const StoryFeedItemSchema = z.object({
userId: z.number(),
nickname: z.string(),
profileImageUrl: z.string(),
profileImageUrl: z.string().nullable(),
hasUnseenStory: z.boolean(),
})

export const StoryFeedResponseSchema = z.object({
code: z.string(),
message: z.string(),
data: z.array(StoryFeedItemSchema),
success: z.boolean(),
isSuccess: z.boolean(),
})
16 changes: 16 additions & 0 deletions src/entities/user/api/getProfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { instance } from '@/shared/api/ky'
import { ProfileUserResponseSchema } from '../model/schema'
import type { ProfileUser } from '../model/types'

type GetProfileParams = {
userId: number
}

export async function getProfile({
userId,
}: GetProfileParams): Promise<ProfileUser> {
const response = await instance.get(`api/v1/users/${userId}/profile`)
const raw = await response.json()
const parsed = ProfileUserResponseSchema.parse(raw)
return parsed.data
}
10 changes: 10 additions & 0 deletions src/entities/user/model/hooks/useProfile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useQuery } from '@tanstack/react-query'
import { getProfile } from '../../api/getProfile'

export function useProfile(userId: number) {
return useQuery({
queryKey: ['profile', userId],
queryFn: () => getProfile({ userId }),
enabled: userId > 0,
})
}
26 changes: 23 additions & 3 deletions src/entities/user/model/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { z } from 'zod'
export const SearchUserSchema = z.object({
userId: z.number(),
nickname: z.string(),
profileImageUrl: z.string(),
name: z.string(),
profileImageUrl: z.string().nullable(),
name: z.string().nullable(),
followed: z.boolean(),
})

Expand All @@ -14,5 +14,25 @@ export const SearchUserResponseSchema = z.object({
data: z.object({
users: z.array(SearchUserSchema),
}),
success: z.boolean(),
isSuccess: z.boolean(),
})

export const ProfileUserSchema = z.object({
userId: z.number(),
nickname: z.string(),
name: z.string().nullable(),
bio: z.string().nullable(),
profileImageUrl: z.string().nullable(),
postsCount: z.number(),
followerCount: z.number(),
followingCount: z.number(),
me: z.boolean(),
followed: z.boolean(),
})

export const ProfileUserResponseSchema = z.object({
code: z.string(),
message: z.string(),
data: ProfileUserSchema,
isSuccess: z.boolean(),
})
3 changes: 2 additions & 1 deletion src/entities/user/model/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { z } from 'zod'
import { SearchUserSchema } from './schema'
import { ProfileUserSchema, SearchUserSchema } from './schema'

export type SearchUser = z.infer<typeof SearchUserSchema>
export type ProfileUser = z.infer<typeof ProfileUserSchema>
Loading