diff --git a/.yarn/cache/@next-swc-darwin-arm64-npm-14.2.4-86d534c3ee-8.zip b/.yarn/cache/@next-swc-darwin-arm64-npm-14.2.4-86d534c3ee-8.zip new file mode 100644 index 00000000..36e475bf Binary files /dev/null and b/.yarn/cache/@next-swc-darwin-arm64-npm-14.2.4-86d534c3ee-8.zip differ diff --git a/src/app/(sidebar)/write/[id]/api/useDeleteMemo.ts b/src/app/(sidebar)/write/[id]/api/useDeleteMemo.ts new file mode 100644 index 00000000..2b4a2868 --- /dev/null +++ b/src/app/(sidebar)/write/[id]/api/useDeleteMemo.ts @@ -0,0 +1,13 @@ +import { http } from '@/apis/http'; +import { useMutation } from '@tanstack/react-query'; + +export const deleteMemo = (cardId: string, memoId: number) => + http.delete({ + url: `/cards/${cardId}/card-memo/${memoId}`, + }); + +export const useDeleteMemo = (cardId: string) => + useMutation({ + mutationKey: ['delete-memo', cardId], + mutationFn: (memoId: number) => deleteMemo(cardId, memoId), + }); diff --git a/src/app/(sidebar)/write/[id]/api/useGetMemos.ts b/src/app/(sidebar)/write/[id]/api/useGetMemos.ts new file mode 100644 index 00000000..a53263e2 --- /dev/null +++ b/src/app/(sidebar)/write/[id]/api/useGetMemos.ts @@ -0,0 +1,20 @@ +import { http } from '@/apis/http'; +import { useSuspenseQuery } from '@tanstack/react-query'; + +export type GetMemosResponse = Array<{ + id: number; + content: string; + updatedAt: string; +}>; + +const getMemos = (cardId: string) => + http.get({ + url: `/cards/${cardId}/card-memo`, + }); + +export const useGetMemos = (cardId: string) => + useSuspenseQuery({ + queryKey: ['get-memos', cardId], + queryFn: () => getMemos(cardId), + select: ({ result }) => result, + }); diff --git a/src/app/(sidebar)/write/[id]/api/usePostMemo.ts b/src/app/(sidebar)/write/[id]/api/usePostMemo.ts new file mode 100644 index 00000000..d3bc4214 --- /dev/null +++ b/src/app/(sidebar)/write/[id]/api/usePostMemo.ts @@ -0,0 +1,14 @@ +import { http } from '@/apis/http'; +import { useMutation } from '@tanstack/react-query'; + +export const postMemo = (cardId: string, content: string) => + http.post({ + url: `/cards/${cardId}/card-memo`, + data: { content }, + }); + +export const usePostMemo = (cardId: string) => + useMutation({ + mutationKey: ['post-memo', cardId], + mutationFn: (content: string) => postMemo(cardId, content), + }); diff --git a/src/app/(sidebar)/write/[id]/api/usesPutMemo.ts b/src/app/(sidebar)/write/[id]/api/usesPutMemo.ts new file mode 100644 index 00000000..500eddda --- /dev/null +++ b/src/app/(sidebar)/write/[id]/api/usesPutMemo.ts @@ -0,0 +1,14 @@ +import { http } from '@/apis/http'; +import { useMutation } from '@tanstack/react-query'; + +export const putMemo = (cardId: string, memoId: number, content: string) => + http.put({ + url: `/cards/${cardId}/card-memo/${memoId}/content`, + data: { content }, + }); + +export const usePutMemo = (cardId: string) => + useMutation({ + mutationKey: ['put-memo', cardId], + mutationFn: ({ memoId, content }: { memoId: number; content: string }) => putMemo(cardId, memoId, content), + }); diff --git a/src/app/(sidebar)/write/[id]/components/MemoContainer/Memo/Memo.tsx b/src/app/(sidebar)/write/[id]/components/MemoContainer/Memo/Memo.tsx new file mode 100644 index 00000000..d29209b4 --- /dev/null +++ b/src/app/(sidebar)/write/[id]/components/MemoContainer/Memo/Memo.tsx @@ -0,0 +1,75 @@ +'use client'; + +import { useState, useRef, useEffect, useCallback } from 'react'; +import { Textarea } from '@/system/components/Textarea/Textarea'; +import { RemoveMemo } from '@/system/components/Icon/SVG/RemoveMemo'; +import { AnimatePresence } from 'framer-motion'; +import { motion } from 'framer-motion'; +import { GetMemosResponse } from '../../../api/useGetMemos'; +import { useMemosContext } from '../../../fetcher/MemosFetcher'; +import { useDeleteMemo } from '../../../api/useDeleteMemo'; +import { usePutMemo } from '@/app/(sidebar)/write/[id]/api/usesPutMemo'; + +export default function Memo({ id: memoId, content, updatedAt }: GetMemosResponse[number]) { + const { cardId } = useMemosContext(); + const prevMemo = useRef(content); + const [memo, setMemo] = useState(content || ''); + const [showCloseButton, setShowCloseButton] = useState(false); + const textareaRef = useRef(null); + const { mutate } = useDeleteMemo(cardId); + const { mutate: putMemo } = usePutMemo(cardId); + + const adjustTextareaHeight = useCallback(() => { + const textarea = textareaRef.current; + + if (textarea) { + textarea.style.height = 'auto'; + textarea.style.height = `${textarea.scrollHeight}px`; + } + }, []); + + useEffect(() => { + adjustTextareaHeight(); + + if (prevMemo.current !== memo) { + putMemo({ memoId, content: memo }); + } + }, [memo]); + + return ( +
setShowCloseButton(true)} + onMouseLeave={() => setShowCloseButton(false)}> +
+ +
+