diff --git a/surfsense_web/lib/apis/chat-comments-api.service.ts b/surfsense_web/lib/apis/chat-comments-api.service.ts new file mode 100644 index 000000000..8fa683e1c --- /dev/null +++ b/surfsense_web/lib/apis/chat-comments-api.service.ts @@ -0,0 +1,168 @@ +import { + type CreateCommentRequest, + type CreateReplyRequest, + type DeleteCommentRequest, + type GetCommentsRequest, + type GetMentionsRequest, + type MarkMentionReadRequest, + type UpdateCommentRequest, + createCommentRequest, + createCommentResponse, + createReplyRequest, + createReplyResponse, + deleteCommentRequest, + deleteCommentResponse, + getCommentsRequest, + getCommentsResponse, + getMentionsRequest, + getMentionsResponse, + markAllMentionsReadResponse, + markMentionReadRequest, + markMentionReadResponse, + updateCommentRequest, + updateCommentResponse, +} from "@/contracts/types/chat-comments.types"; +import { ValidationError } from "@/lib/error"; +import { baseApiService } from "./base-api.service"; + +class ChatCommentsApiService { + /** + * Get comments for a message + */ + getComments = async (request: GetCommentsRequest) => { + const parsed = getCommentsRequest.safeParse(request); + + if (!parsed.success) { + const errorMessage = parsed.error.issues.map((issue) => issue.message).join(", "); + throw new ValidationError(`Invalid request: ${errorMessage}`); + } + + return baseApiService.get( + `/api/v1/messages/${parsed.data.message_id}/comments`, + getCommentsResponse + ); + }; + + /** + * Create a top-level comment + */ + createComment = async (request: CreateCommentRequest) => { + const parsed = createCommentRequest.safeParse(request); + + if (!parsed.success) { + const errorMessage = parsed.error.issues.map((issue) => issue.message).join(", "); + throw new ValidationError(`Invalid request: ${errorMessage}`); + } + + return baseApiService.post( + `/api/v1/messages/${parsed.data.message_id}/comments`, + createCommentResponse, + { body: { content: parsed.data.content } } + ); + }; + + /** + * Create a reply to a comment + */ + createReply = async (request: CreateReplyRequest) => { + const parsed = createReplyRequest.safeParse(request); + + if (!parsed.success) { + const errorMessage = parsed.error.issues.map((issue) => issue.message).join(", "); + throw new ValidationError(`Invalid request: ${errorMessage}`); + } + + return baseApiService.post( + `/api/v1/comments/${parsed.data.comment_id}/replies`, + createReplyResponse, + { body: { content: parsed.data.content } } + ); + }; + + /** + * Update a comment + */ + updateComment = async (request: UpdateCommentRequest) => { + const parsed = updateCommentRequest.safeParse(request); + + if (!parsed.success) { + const errorMessage = parsed.error.issues.map((issue) => issue.message).join(", "); + throw new ValidationError(`Invalid request: ${errorMessage}`); + } + + return baseApiService.put( + `/api/v1/comments/${parsed.data.comment_id}`, + updateCommentResponse, + { body: { content: parsed.data.content } } + ); + }; + + /** + * Delete a comment + */ + deleteComment = async (request: DeleteCommentRequest) => { + const parsed = deleteCommentRequest.safeParse(request); + + if (!parsed.success) { + const errorMessage = parsed.error.issues.map((issue) => issue.message).join(", "); + throw new ValidationError(`Invalid request: ${errorMessage}`); + } + + return baseApiService.delete( + `/api/v1/comments/${parsed.data.comment_id}`, + deleteCommentResponse + ); + }; + + /** + * Get mentions for current user + */ + getMentions = async (request?: GetMentionsRequest) => { + const parsed = getMentionsRequest.safeParse(request ?? {}); + + if (!parsed.success) { + const errorMessage = parsed.error.issues.map((issue) => issue.message).join(", "); + throw new ValidationError(`Invalid request: ${errorMessage}`); + } + + const params = new URLSearchParams(); + if (parsed.data.search_space_id !== undefined) { + params.set("search_space_id", String(parsed.data.search_space_id)); + } + if (parsed.data.unread_only !== undefined) { + params.set("unread_only", String(parsed.data.unread_only)); + } + + const queryString = params.toString(); + const url = queryString ? `/api/v1/mentions?${queryString}` : "/api/v1/mentions"; + + return baseApiService.get(url, getMentionsResponse); + }; + + /** + * Mark a mention as read + */ + markMentionRead = async (request: MarkMentionReadRequest) => { + const parsed = markMentionReadRequest.safeParse(request); + + if (!parsed.success) { + const errorMessage = parsed.error.issues.map((issue) => issue.message).join(", "); + throw new ValidationError(`Invalid request: ${errorMessage}`); + } + + return baseApiService.put( + `/api/v1/mentions/${parsed.data.mention_id}/read`, + markMentionReadResponse + ); + }; + + /** + * Mark all mentions as read + */ + markAllMentionsRead = async () => { + return baseApiService.put("/api/v1/mentions/read-all", markAllMentionsReadResponse); + }; +} + +export const chatCommentsApiService = new ChatCommentsApiService(); +