From 56c0b7f3ec9ca23498e74686ef5e01aa4a0ccc6d Mon Sep 17 00:00:00 2001 From: wnhlee <2wheeh@gmail.com> Date: Wed, 20 Mar 2024 22:27:44 +0900 Subject: [PATCH] feat: add EditableContext --- .../components/review/client/review-title.tsx | 4 ++ ui/src/context/editor/editable-context.tsx | 50 +++++++++++++++++++ .../hooks/review/use-update-review-button.ts | 3 ++ 3 files changed, 57 insertions(+) create mode 100644 ui/src/context/editor/editable-context.tsx diff --git a/ui/src/components/review/client/review-title.tsx b/ui/src/components/review/client/review-title.tsx index 6ef98248..f9dc31f3 100644 --- a/ui/src/components/review/client/review-title.tsx +++ b/ui/src/components/review/client/review-title.tsx @@ -7,6 +7,7 @@ import { useDebouncedCallback } from '@/hooks/common/use-debounced-callback'; import { MAX_TITLE_LENGTH } from '@/lib/constants/review'; import { MAX_MOVIE_NAME_LENGTH } from '@/lib/constants/common'; import { normalizeWhitespace } from '@/lib/utils/common/normalizeWhitespace'; +import { useEditable } from '@/context/editor/editable-context'; export default function ReviewTitle({ placeholder, @@ -40,6 +41,8 @@ export default function ReviewTitle({ setValue(newText); }; + const { isEditable } = useEditable() ?? {}; + return ( ); } diff --git a/ui/src/context/editor/editable-context.tsx b/ui/src/context/editor/editable-context.tsx new file mode 100644 index 00000000..c5f79860 --- /dev/null +++ b/ui/src/context/editor/editable-context.tsx @@ -0,0 +1,50 @@ +'use client'; + +import { createContext, useContext, useEffect, useState, type ReactNode } from 'react'; +import { useEditorRef } from '@/context/editor/editor-ref-context'; + +interface ContextShape { + isEditable: boolean; + authorId: string; + setIsEditable?: (isEditable: boolean) => void; +} + +const EditableContext = createContext<ContextShape | null>(null); + +export function EditableProvider({ + children, + authorId, +}: { + children: ReactNode; + authorId: string; +}) { + const { editorRef } = useEditorRef() ?? {}; + + if (!editorRef) { + throw new Error('EditableProvider must be used within a EditorProvider'); + } + + const editor = editorRef.current; + + const [isEditable, _setIsEditable] = useState(() => (editor ? editor.isEditable() : false)); + + useEffect( + () => + editor?.registerEditableListener((editable) => { + _setIsEditable(editable); + }), + [editor] + ); + + const setIsEditable = (isEditable: boolean) => editor?.setEditable(isEditable); + + return ( + <EditableContext.Provider value={{ isEditable, authorId, setIsEditable }}> + {children} + </EditableContext.Provider> + ); +} + +export function useEditable() { + return useContext(EditableContext); +} diff --git a/ui/src/hooks/review/use-update-review-button.ts b/ui/src/hooks/review/use-update-review-button.ts index b7f9e673..fecca318 100644 --- a/ui/src/hooks/review/use-update-review-button.ts +++ b/ui/src/hooks/review/use-update-review-button.ts @@ -4,12 +4,14 @@ import { useReview } from '@/context/review/review-context'; import { useToast } from '@/context/common/toast-context'; import { useApiError } from '@/hooks/common/use-api-error'; import { updateReview } from '@/lib/apis/review/client'; +import { useEditable } from '@/context/editor/editable-context'; export function useUpdateReivewButton() { const router = useRouter(); const { id } = useParams(); const { emitToast } = useToast(); + const { setIsEditable } = useEditable() ?? {}; const { disabled, setDisabled, validateAndGetData } = useReview(); const { handleApiError } = useApiError(); @@ -23,6 +25,7 @@ export function useUpdateReivewButton() { try { await updateReview(Number(id), data); + setIsEditable?.(false); emitToast('리뷰 수정 완료', 'success'); router.refresh(); } catch (error) {