File size: 2,222 Bytes
5351cc8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | import type { RecordComment } from "./recordCommentsApi";
export interface RecordCommentsState {
pid: number;
comments: RecordComment[];
draft: string;
loading: boolean;
posting: boolean;
error: string;
}
export type RecordCommentsAction =
| { type: "record"; pid: number }
| { type: "loaded"; pid: number; comments: RecordComment[] }
| { type: "load-failed"; pid: number; error: string }
| { type: "draft"; pid: number; draft: string }
| { type: "posting"; pid: number }
| { type: "posted"; pid: number; comment: RecordComment }
| { type: "post-failed"; pid: number; error: string }
| { type: "deleted"; pid: number; commentId: string }
| { type: "delete-failed"; pid: number; error: string };
export function initialRecordCommentsState(pid: number): RecordCommentsState {
return {
pid,
comments: [],
draft: "",
loading: true,
posting: false,
error: "",
};
}
/**
* Every async completion carries the pid it started against. A completion for
* a record that is no longer rendered is ignored wholesale; it can never add,
* remove, or error a different record's comment feed.
*/
export function recordCommentsReducer(
state: RecordCommentsState,
action: RecordCommentsAction
): RecordCommentsState {
if (action.type === "record") return initialRecordCommentsState(action.pid);
if (action.pid !== state.pid) return state;
switch (action.type) {
case "loaded":
return { ...state, comments: action.comments, loading: false, error: "" };
case "load-failed":
return { ...state, loading: false, error: action.error };
case "draft":
return { ...state, draft: action.draft };
case "posting":
return { ...state, posting: true, error: "" };
case "posted":
return {
...state,
comments: [...state.comments, action.comment],
draft: "",
posting: false,
};
case "post-failed":
return { ...state, posting: false, error: action.error };
case "deleted":
return {
...state,
comments: state.comments.filter((comment) => comment.id !== action.commentId),
};
case "delete-failed":
return { ...state, error: action.error };
}
}
|