/ lib / use-review-comments.ts
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  }