Build post chat and attachment workflows
This commit is contained in:
@@ -15,6 +15,7 @@ export async function apiRequest<T>(path: string, options: RequestOptions = {}):
|
||||
const response = await fetch(`${API_BASE_URL}${path}`, {
|
||||
...options,
|
||||
headers,
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
const data = await response.json().catch(() => ({}));
|
||||
@@ -40,6 +41,7 @@ export async function apiFormRequest<T>(path: string, formData: FormData, token?
|
||||
method: "POST",
|
||||
headers,
|
||||
body: formData,
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
const data = await response.json().catch(() => ({}));
|
||||
|
||||
@@ -16,20 +16,35 @@ type LoginResponse = {
|
||||
user: AuthUser;
|
||||
};
|
||||
|
||||
type AcceptInvitationResponse = {
|
||||
message: string;
|
||||
user: AuthUser;
|
||||
};
|
||||
|
||||
type MeResponse = {
|
||||
user: AuthUser;
|
||||
};
|
||||
|
||||
export function getStoredToken() {
|
||||
return localStorage.getItem(TOKEN_STORAGE_KEY);
|
||||
return sessionStorage.getItem(TOKEN_STORAGE_KEY);
|
||||
}
|
||||
|
||||
export function storeToken(token: string) {
|
||||
localStorage.setItem(TOKEN_STORAGE_KEY, token);
|
||||
localStorage.removeItem(TOKEN_STORAGE_KEY);
|
||||
sessionStorage.setItem(TOKEN_STORAGE_KEY, token);
|
||||
}
|
||||
|
||||
export function clearStoredToken() {
|
||||
localStorage.removeItem(TOKEN_STORAGE_KEY);
|
||||
sessionStorage.removeItem(TOKEN_STORAGE_KEY);
|
||||
}
|
||||
|
||||
export async function logout() {
|
||||
await apiRequest<{ message: string }>("/auth/logout", {
|
||||
method: "POST",
|
||||
}).catch(() => undefined);
|
||||
localStorage.removeItem(TOKEN_STORAGE_KEY);
|
||||
sessionStorage.removeItem(TOKEN_STORAGE_KEY);
|
||||
}
|
||||
|
||||
export async function login(email: string, password: string) {
|
||||
@@ -43,11 +58,19 @@ export async function login(email: string, password: string) {
|
||||
}
|
||||
|
||||
export async function acceptInvitation(token: string, name: string, password: string) {
|
||||
const response = await apiRequest<LoginResponse>("/auth/invitations/accept", {
|
||||
const response = await apiRequest<AcceptInvitationResponse>("/auth/invitations/accept", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ token, name, password }),
|
||||
});
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function refreshSession() {
|
||||
const response = await apiRequest<LoginResponse>("/auth/refresh", {
|
||||
method: "POST",
|
||||
});
|
||||
|
||||
storeToken(response.access_token);
|
||||
return response;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { API_BASE_URL, apiFormRequest, apiRequest } from "@/lib/api";
|
||||
import { API_BASE_URL, ApiError, apiFormRequest, apiRequest } from "@/lib/api";
|
||||
|
||||
export type Holiday = {
|
||||
id: string;
|
||||
@@ -51,6 +51,34 @@ export type Attachment = {
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
export type ChatChannel = "external" | "internal";
|
||||
|
||||
export type ChatMessage = {
|
||||
id: string;
|
||||
calendar_item_id: string;
|
||||
channel: ChatChannel;
|
||||
body: string;
|
||||
created_by: string | null;
|
||||
author_name: string;
|
||||
author_role: string;
|
||||
created_at: string;
|
||||
edited_at: string | null;
|
||||
deleted_at: string | null;
|
||||
attachments: ChatAttachment[] | null;
|
||||
};
|
||||
|
||||
export type ChatAttachment = {
|
||||
id: string;
|
||||
chat_message_id: string;
|
||||
original_filename: string;
|
||||
stored_filename: string;
|
||||
mime_type: string;
|
||||
size_bytes: number;
|
||||
storage_driver: string;
|
||||
created_by: string | null;
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
export type CreateCustomDateInput = {
|
||||
client_id?: string;
|
||||
name: string;
|
||||
@@ -120,6 +148,18 @@ type AttachmentResponse = {
|
||||
attachment: Attachment;
|
||||
};
|
||||
|
||||
type ChatAttachmentResponse = {
|
||||
attachment: ChatAttachment;
|
||||
};
|
||||
|
||||
type ChatMessagesResponse = {
|
||||
messages: ChatMessage[];
|
||||
};
|
||||
|
||||
type ChatMessageResponse = {
|
||||
message: ChatMessage;
|
||||
};
|
||||
|
||||
export async function listHolidays(token: string, year: number) {
|
||||
const response = await apiRequest<HolidaysResponse>(`/calendar/holidays?year=${year}`, {
|
||||
method: "GET",
|
||||
@@ -251,6 +291,99 @@ export async function uploadAttachment(token: string, itemId: string, file: File
|
||||
return response.attachment;
|
||||
}
|
||||
|
||||
export async function deleteAttachment(token: string, attachmentId: string) {
|
||||
const response = await apiRequest<AttachmentResponse>(`/calendar/attachments/${attachmentId}`, {
|
||||
method: "DELETE",
|
||||
token,
|
||||
});
|
||||
|
||||
return response.attachment;
|
||||
}
|
||||
|
||||
export async function listChatMessages(token: string, itemId: string, channel: ChatChannel) {
|
||||
const params = new URLSearchParams({ channel });
|
||||
const response = await apiRequest<ChatMessagesResponse>(`/calendar/items/${itemId}/chat?${params.toString()}`, {
|
||||
method: "GET",
|
||||
token,
|
||||
});
|
||||
|
||||
return response.messages;
|
||||
}
|
||||
|
||||
export async function createChatMessage(token: string, itemId: string, channel: ChatChannel, body: string) {
|
||||
const response = await apiRequest<ChatMessageResponse>(`/calendar/items/${itemId}/chat`, {
|
||||
method: "POST",
|
||||
token,
|
||||
body: JSON.stringify({ channel, body }),
|
||||
});
|
||||
|
||||
return response.message;
|
||||
}
|
||||
|
||||
export async function updateChatMessage(token: string, messageId: string, body: string) {
|
||||
const response = await apiRequest<ChatMessageResponse>(`/calendar/chat/messages/${messageId}`, {
|
||||
method: "PATCH",
|
||||
token,
|
||||
body: JSON.stringify({ body }),
|
||||
});
|
||||
|
||||
return response.message;
|
||||
}
|
||||
|
||||
export async function deleteChatMessage(token: string, messageId: string) {
|
||||
const response = await apiRequest<ChatMessageResponse>(`/calendar/chat/messages/${messageId}`, {
|
||||
method: "DELETE",
|
||||
token,
|
||||
});
|
||||
|
||||
return response.message;
|
||||
}
|
||||
|
||||
export async function uploadChatAttachment(token: string, messageId: string, file: File) {
|
||||
const formData = new FormData();
|
||||
formData.set("file", file);
|
||||
|
||||
const response = await apiFormRequest<ChatAttachmentResponse>(`/calendar/chat/messages/${messageId}/attachments`, formData, token);
|
||||
return response.attachment;
|
||||
}
|
||||
|
||||
export async function downloadAttachmentBlob(token: string, attachmentId: string) {
|
||||
return downloadProtectedBlob(token, attachmentDownloadURL(attachmentId));
|
||||
}
|
||||
|
||||
export async function downloadChatAttachmentBlob(token: string, attachmentId: string) {
|
||||
return downloadProtectedBlob(token, chatAttachmentDownloadURL(attachmentId));
|
||||
}
|
||||
|
||||
async function downloadProtectedBlob(token: string, url: string) {
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
credentials: "include",
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const data = await response.json().catch(() => ({}));
|
||||
const message =
|
||||
typeof data === "object" && data !== null && "message" in data
|
||||
? String(data.message)
|
||||
: "Nao foi possivel baixar o anexo.";
|
||||
throw new ApiError(message, response.status);
|
||||
}
|
||||
|
||||
return response.blob();
|
||||
}
|
||||
|
||||
export function attachmentDownloadURL(attachmentId: string) {
|
||||
return `${API_BASE_URL}/calendar/attachments/${attachmentId}/download`;
|
||||
}
|
||||
|
||||
export function chatAttachmentDownloadURL(attachmentId: string) {
|
||||
return `${API_BASE_URL}/calendar/chat/attachments/${attachmentId}/download`;
|
||||
}
|
||||
|
||||
export function chatStreamURL(itemId: string, channel: ChatChannel) {
|
||||
const params = new URLSearchParams({ channel });
|
||||
return `${API_BASE_URL}/calendar/items/${itemId}/chat/stream?${params.toString()}`;
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ export type Invitation = {
|
||||
accepted_at: string | null;
|
||||
created_at: string;
|
||||
invitation_url?: string;
|
||||
email_sent: boolean;
|
||||
email_error?: string;
|
||||
};
|
||||
|
||||
type UsersResponse = {
|
||||
|
||||
Reference in New Issue
Block a user