Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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
2 changes: 2 additions & 0 deletions src/components/auth/LoginCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ interface LoginResponse {
message: string
data: {
accessToken: string
refreshToken: string
} | null
}

Expand Down Expand Up @@ -92,6 +93,7 @@ const LoginCard = () => {

if (res.isSuccess && res.data) {
localStorage.setItem('accessToken', res.data.accessToken)
localStorage.setItem('refreshToken', res.data.refreshToken)
await invalidateCurrentUser()
navigate({ to: '/' })
} else {
Expand Down
18 changes: 14 additions & 4 deletions src/entities/album/api/attachPostToAlbum.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { instance } from '@/shared/api/ky'

export async function attachPostToAlbum(params: {
type AttachPostToAlbumParams = {
albumId: number
postId: number
}): Promise<void> {
const { albumId, postId } = params
loggedInUser: number | null
}

export async function attachPostToAlbum({
albumId,
postId,
loggedInUser,
}: AttachPostToAlbumParams): Promise<void> {
const searchParams = new URLSearchParams()
if (loggedInUser !== null) {
searchParams.set('loggedInUser', String(loggedInUser))
}
const response = await instance.post(
`api/v1/albums/${albumId}/posts/${postId}`
`api/v1/albums/${albumId}/posts/${postId}`,
{ searchParams }
)

if (!response.ok) {
Expand Down
15 changes: 13 additions & 2 deletions src/entities/album/api/createAlbum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,24 @@ import type {
CreateAlbumResponse,
} from '@/entities/album/model/types'

export async function createAlbum(
type CreateAlbumParams = {
payload: CreateAlbumRequest
): Promise<number> {
loggedInUser: number | null
}

export async function createAlbum({
payload,
loggedInUser,
}: CreateAlbumParams): Promise<number> {
const parsedRequest = CreateAlbumRequestSchema.parse(payload)

const searchParams = new URLSearchParams()
if (loggedInUser !== null) {
searchParams.set('loggedInUser', String(loggedInUser))
}
const response = await instance.post('api/v1/albums', {
json: parsedRequest,
searchParams,
})

const raw = await response.json()
Expand Down
18 changes: 16 additions & 2 deletions src/entities/album/api/deleteAlbum.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import { instance } from '@/shared/api/ky'

export async function deleteAlbum(albumId: number): Promise<void> {
const response = await instance.delete(`api/v1/albums/${albumId}`)
type DeleteAlbumParams = {
albumId: number
loggedInUser: number | null
}

export async function deleteAlbum({
albumId,
loggedInUser,
}: DeleteAlbumParams): Promise<void> {
const searchParams = new URLSearchParams()
if (loggedInUser !== null) {
searchParams.set('loggedInUser', String(loggedInUser))
}
const response = await instance.delete(`api/v1/albums/${albumId}`, {
searchParams,
})

if (!response.ok) {
throw new Error('Failed to delete album')
Expand Down
18 changes: 14 additions & 4 deletions src/entities/album/api/detachPostFromAlbum.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { instance } from '@/shared/api/ky'

export async function detachPostFromAlbum(params: {
type DetachPostFromAlbumParams = {
albumId: number
postId: number
}): Promise<void> {
const { albumId, postId } = params
loggedInUser: number | null
}

export async function detachPostFromAlbum({
albumId,
postId,
loggedInUser,
}: DetachPostFromAlbumParams): Promise<void> {
const searchParams = new URLSearchParams()
if (loggedInUser !== null) {
searchParams.set('loggedInUser', String(loggedInUser))
}
const response = await instance.delete(
`api/v1/albums/${albumId}/posts/${postId}`
`api/v1/albums/${albumId}/posts/${postId}`,
{ searchParams }
)

if (!response.ok) {
Expand Down
18 changes: 16 additions & 2 deletions src/entities/album/api/getAlbumDetail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,22 @@ import {
} from '@/entities/album/model/schema'
import type { AlbumDetail } from '@/entities/album/model/types'

export async function getAlbumDetail(albumId: number): Promise<AlbumDetail> {
const response = await instance.get(`api/v1/albums/${albumId}`)
type GetAlbumDetailParams = {
albumId: number
loggedInUser: number | null
}

export async function getAlbumDetail({
albumId,
loggedInUser,
}: GetAlbumDetailParams): Promise<AlbumDetail> {
const searchParams = new URLSearchParams()
if (loggedInUser !== null) {
searchParams.set('loggedInUser', String(loggedInUser))
}
const response = await instance.get(`api/v1/albums/${albumId}`, {
searchParams,
})

const raw = await response.json()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,14 @@ import {
} from '@/entities/album/model/schema'
import type { AlbumSummary } from '@/entities/album/model/types'

export async function getMyAlbums(): Promise<AlbumSummary[]> {
const response = await instance.get('api/v1/albums/my')
type GetUserAlbumsParams = {
userId: number
}

export async function getUserAlbums({
userId,
}: GetUserAlbumsParams): Promise<AlbumSummary[]> {
const response = await instance.get(`api/v1/albums/users/${userId}`)

const raw = await response.json()

Expand Down
18 changes: 15 additions & 3 deletions src/entities/album/api/updateAlbumTitle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,26 @@ import { instance } from '@/shared/api/ky'
import { CreateAlbumRequestSchema } from '@/entities/album/model/schema'
import type { CreateAlbumRequest } from '@/entities/album/model/types'

export async function updateAlbumTitle(
albumId: number,
type UpdateAlbumTitleParams = {
albumId: number
payload: CreateAlbumRequest
): Promise<void> {
loggedInUser: number | null
}

export async function updateAlbumTitle({
albumId,
payload,
loggedInUser,
}: UpdateAlbumTitleParams): Promise<void> {
const parsedRequest = CreateAlbumRequestSchema.parse(payload)

const searchParams = new URLSearchParams()
if (loggedInUser !== null) {
searchParams.set('loggedInUser', String(loggedInUser))
}
const response = await instance.patch(`api/v1/albums/${albumId}`, {
json: parsedRequest,
searchParams,
})

if (!response.ok) {
Expand Down
7 changes: 5 additions & 2 deletions src/entities/album/model/hooks/useAlbumDetailQuery.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
import { useQuery } from '@tanstack/react-query'
import { useCurrentUserId } from '@/shared/auth/useCurrentUser'

import { getAlbumDetail } from '@/entities/album/api/getAlbumDetail'
import type { AlbumDetail } from '@/entities/album/model/types'

export function useAlbumDetailQuery(albumId: number | null) {
const loggedInUser = useCurrentUserId()

return useQuery<AlbumDetail>({
queryKey: ['album', albumId],
queryKey: ['album', albumId, loggedInUser],
queryKeyHashFn: (key) => JSON.stringify(key),
enabled: albumId != null,
queryFn: () => {
if (albumId == null) {
throw new Error('albumId is required')
}

return getAlbumDetail(albumId)
return getAlbumDetail({ albumId, loggedInUser })
},
})
}
6 changes: 4 additions & 2 deletions src/entities/album/model/hooks/useCreateAlbumMutation.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useCurrentUserId } from '@/shared/auth/useCurrentUser'
import { createAlbum } from '@/entities/album/api/createAlbum'
import type { CreateAlbumRequest } from '@/entities/album/model/types'

export function useCreateAlbumMutation() {
const queryClient = useQueryClient()
const loggedInUser = useCurrentUserId()

return useMutation({
mutationFn: (payload: CreateAlbumRequest) => createAlbum(payload),
mutationFn: (payload: CreateAlbumRequest) =>
createAlbum({ payload, loggedInUser }),
onSuccess: () => {
// 앨범 목록 쿼리 무효화하여 자동으로 다시 가져오기
queryClient.invalidateQueries({ queryKey: ['albums', 'my'] })
},
})
Expand Down
11 changes: 0 additions & 11 deletions src/entities/album/model/hooks/useMyAlbumsQuery.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useMutation, useQueryClient } from '@tanstack/react-query'
import { useCurrentUserId } from '@/shared/auth/useCurrentUser'
import { updateAlbumTitle } from '@/entities/album/api/updateAlbumTitle'
import type { CreateAlbumRequest } from '@/entities/album/model/types'

export function useUpdateAlbumTitleMutation() {
const queryClient = useQueryClient()
const loggedInUser = useCurrentUserId()

return useMutation({
mutationFn: ({
Expand All @@ -12,9 +14,8 @@ export function useUpdateAlbumTitleMutation() {
}: {
albumId: number
payload: CreateAlbumRequest
}) => updateAlbumTitle(albumId, payload),
}) => updateAlbumTitle({ albumId, payload, loggedInUser }),
onSuccess: () => {
// 앨범 목록 쿼리 무효화하여 자동으로 다시 가져오기
queryClient.invalidateQueries({ queryKey: ['albums', 'my'] })
},
})
Expand Down
20 changes: 20 additions & 0 deletions src/entities/album/model/hooks/useUserAlbumsQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useQuery } from '@tanstack/react-query'
import { getUserAlbums } from '@/entities/album/api/getUserAlbums'
import type { AlbumSummary } from '@/entities/album/model/types'

type UseUserAlbumsQueryParams = {
userId: number
enabled?: boolean
}

export function useUserAlbumsQuery({
userId,
enabled = true,
}: UseUserAlbumsQueryParams) {
return useQuery<AlbumSummary[]>({
queryKey: ['albums', 'user', userId],
queryFn: () => getUserAlbums({ userId }),
enabled: enabled && userId > 0,
retry: false,
})
}
2 changes: 1 addition & 1 deletion src/entities/album/model/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ export const ApiResponseSchema = <T extends z.ZodTypeAny>(dataSchema: T) =>

export const CreateAlbumResponseSchema = ApiResponseSchema(z.number())
export const AlbumDetailResponseSchema = ApiResponseSchema(AlbumDetailSchema)
export const MyAlbumsResponseSchema = ApiResponseSchema(
export const UserAlbumsResponseSchema = ApiResponseSchema(
z.array(AlbumSummarySchema)
)
4 changes: 2 additions & 2 deletions src/entities/album/model/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
ApiResponseSchema,
CreateAlbumRequestSchema,
CreateAlbumResponseSchema,
MyAlbumsResponseSchema,
UserAlbumsResponseSchema,
} from './schema'

export type CreateAlbumRequest = z.infer<typeof CreateAlbumRequestSchema>
Expand All @@ -19,7 +19,7 @@ export type AlbumDetail = z.infer<typeof AlbumDetailSchema>
export type AlbumSummary = z.infer<typeof AlbumSummarySchema>

export type AlbumDetailResponse = z.infer<typeof AlbumDetailResponseSchema>
export type MyAlbumsResponse = z.infer<typeof MyAlbumsResponseSchema>
export type UserAlbumsResponse = z.infer<typeof UserAlbumsResponseSchema>

export type ApiResponse<T> = z.infer<
ReturnType<typeof ApiResponseSchema<z.ZodType<T>>>
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 @@ -13,8 +13,8 @@ export const FeedItemSchema = z.object({
likeCount: z.number().nonnegative(),
commentCount: z.number().nonnegative(),
createdAt: z.string(),
liked: z.boolean(),
bookmarked: z.boolean(),
isLiked: z.boolean().default(false),
isBookmarked: z.boolean().default(false),
})

export const FeedPageSchema = z.object({
Expand Down
16 changes: 8 additions & 8 deletions src/entities/feed/ui/FeedCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ type FeedCardProps = {
export function FeedCard({ item, className, onOpenPost }: FeedCardProps) {
const toggleLikeMutation = useToggleLikeMutation({
postId: item.postId,
initiallyLiked: item.liked,
initiallyLiked: item.isLiked,
})

const toggleBookmarkMutation = useToggleBookmarkMutation({
postId: item.postId,
initiallyBookmarked: item.bookmarked,
initiallyBookmarked: item.isBookmarked,
})

const handleOpenPost = () => {
Expand All @@ -31,12 +31,12 @@ export function FeedCard({ item, className, onOpenPost }: FeedCardProps) {

const handleToggleLike = () => {
if (toggleLikeMutation.isPending) return
toggleLikeMutation.mutate(!item.liked)
toggleLikeMutation.mutate(!item.isLiked)
}

const handleToggleBookmark = () => {
if (toggleBookmarkMutation.isPending) return
toggleBookmarkMutation.mutate(!item.bookmarked)
toggleBookmarkMutation.mutate(!item.isBookmarked)
}

return (
Expand Down Expand Up @@ -93,14 +93,14 @@ export function FeedCard({ item, className, onOpenPost }: FeedCardProps) {
variant="ghost"
size="icon"
className="h-9 w-9"
aria-pressed={item.liked}
aria-pressed={item.isLiked}
disabled={toggleLikeMutation.isPending}
onClick={handleToggleLike}
>
<Heart
className={cn(
'size-6 transition-colors',
item.liked ? 'fill-red-500 text-red-500' : 'text-foreground'
item.isLiked ? 'fill-red-500 text-red-500' : 'text-foreground'
)}
/>
</Button>
Expand All @@ -111,14 +111,14 @@ export function FeedCard({ item, className, onOpenPost }: FeedCardProps) {
variant="ghost"
size="icon"
className="h-9 w-9"
aria-pressed={item.bookmarked}
aria-pressed={item.isBookmarked}
disabled={toggleBookmarkMutation.isPending}
onClick={handleToggleBookmark}
>
<Bookmark
className={cn(
'size-6 transition-colors',
item.bookmarked ? 'fill-black text-black' : 'text-foreground'
item.isBookmarked ? 'fill-black text-black' : 'text-foreground'
)}
/>
</Button>
Expand Down
Loading