loopable / web /src /customer-grid /recordCommentsState.ts
fsanyoto's picture
Deploy AIOS web (React glide grid + FastAPI slice)
5351cc8 verified
Raw
History Blame Contribute Delete
2.22 kB
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 };
}
}