use-review-comments.ts
1 import { useReducer, useCallback } from 'react'; 2 import type { PendingReviewComment, DiffSide } from './types'; 3 4 type Action = 5 | { type: 'ADD'; comment: PendingReviewComment } 6 | { type: 'REMOVE'; id: string } 7 | { type: 'EDIT'; id: string; body: string } 8 | { type: 'CLEAR_ALL' }; 9 10 function reducer(state: PendingReviewComment[], action: Action): PendingReviewComment[] { 11 switch (action.type) { 12 case 'ADD': 13 return [...state, action.comment]; 14 case 'REMOVE': 15 return state.filter((c) => c.id !== action.id); 16 case 'EDIT': 17 return state.map((c) => (c.id === action.id ? { ...c, body: action.body } : c)); 18 case 'CLEAR_ALL': 19 return []; 20 } 21 } 22 23 export function useReviewComments() { 24 const [comments, dispatch] = useReducer(reducer, []); 25 26 const addComment = useCallback( 27 (params: { 28 filePath: string; 29 line: number; 30 side: DiffSide; 31 body: string; 32 hunkHeader: string; 33 codeSnippet: string; 34 slideIndex: number; 35 }) => { 36 dispatch({ 37 type: 'ADD', 38 comment: { id: crypto.randomUUID(), ...params }, 39 }); 40 }, 41 [] 42 ); 43 44 const removeComment = useCallback((id: string) => { 45 dispatch({ type: 'REMOVE', id }); 46 }, []); 47 48 const editComment = useCallback((id: string, body: string) => { 49 dispatch({ type: 'EDIT', id, body }); 50 }, []); 51 52 const clearAll = useCallback(() => { 53 dispatch({ type: 'CLEAR_ALL' }); 54 }, []); 55 56 return { comments, addComment, removeComment, editComment, clearAll }; 57 }