email plus return item statuses

This commit is contained in:
jackiettran
2025-10-06 15:41:48 -04:00
parent 67cc997ddc
commit 5c3d505988
28 changed files with 5861 additions and 259 deletions

View File

@@ -52,18 +52,6 @@ export const resetCSRFToken = () => {
csrfToken = null;
};
// Check if authentication cookie exists
export const hasAuthCookie = (): boolean => {
return document.cookie
.split("; ")
.some((cookie) => cookie.startsWith("accessToken="));
};
// Check if user has any auth indicators
export const hasAuthIndicators = (): boolean => {
return hasAuthCookie();
};
api.interceptors.request.use(async (config) => {
// Add CSRF token to headers for state-changing requests
const method = config.method?.toUpperCase() || "";
@@ -119,14 +107,14 @@ api.interceptors.response.use(
if (error.response?.status === 401) {
const errorData = error.response?.data as any;
// Don't redirect for NO_TOKEN on public endpoints
if (errorData?.code === "NO_TOKEN") {
// Let the app handle this - user simply isn't logged in
return Promise.reject(error);
}
// If token is expired, try to refresh
if (errorData?.code === "TOKEN_EXPIRED" && !originalRequest._retry) {
// Try to refresh for token errors
// Note: We can't check refresh token from JS (httpOnly cookies)
// The backend will determine if refresh is possible
if (
(errorData?.code === "TOKEN_EXPIRED" ||
errorData?.code === "NO_TOKEN") &&
!originalRequest._retry
) {
if (isRefreshing) {
// If already refreshing, queue the request
return new Promise((resolve, reject) => {
@@ -152,18 +140,10 @@ api.interceptors.response.use(
isRefreshing = false;
processQueue(refreshError as AxiosError);
// Refresh failed, redirect to login
window.location.href = "/login";
// Refresh failed - let React Router handle redirects via PrivateRoute
return Promise.reject(refreshError);
}
}
// For other 401 errors, check if we should redirect
// Only redirect if this is not a login/register request
const isAuthEndpoint = originalRequest.url?.includes("/auth/");
if (!isAuthEndpoint && errorData?.error !== "Access token required") {
window.location.href = "/login";
}
}
return Promise.reject(error);
@@ -223,8 +203,19 @@ export const rentalAPI = {
reviewItem: (id: string, data: any) =>
api.post(`/rentals/${id}/review-item`, data),
getRefundPreview: (id: string) => api.get(`/rentals/${id}/refund-preview`),
getLateFeePreview: (id: string, actualReturnDateTime: string) =>
api.get(`/rentals/${id}/late-fee-preview`, {
params: { actualReturnDateTime },
}),
cancelRental: (id: string, reason?: string) =>
api.post(`/rentals/${id}/cancel`, { reason }),
// Return status marking
markReturn: (
id: string,
data: { status: string; actualReturnDateTime?: string; notes?: string }
) => api.post(`/rentals/${id}/mark-return`, data),
reportDamage: (id: string, data: any) =>
api.post(`/rentals/${id}/report-damage`, data),
};
export const messageAPI = {
@@ -277,4 +268,35 @@ export const mapsAPI = {
getHealth: () => api.get("/maps/health"),
};
export const conditionCheckAPI = {
submitConditionCheck: (rentalId: string, formData: FormData) =>
api.post(`/condition-checks/${rentalId}`, formData, {
headers: { "Content-Type": "multipart/form-data" },
}),
getConditionChecks: (rentalId: string) =>
api.get(`/condition-checks/${rentalId}`),
getConditionCheckTimeline: (rentalId: string) =>
api.get(`/condition-checks/${rentalId}/timeline`),
getAvailableChecks: () => api.get("/condition-checks"),
};
export const notificationAPI = {
getNotifications: (params?: { limit?: number; page?: number }) =>
api.get("/notifications", { params }),
getUnreadCount: () => api.get("/notifications/unread-count"),
markAsRead: (notificationId: string) =>
api.patch(`/notifications/${notificationId}/read`),
markAllAsRead: () => api.patch("/notifications/mark-all-read"),
// Development endpoints
createTestNotification: (data: {
type?: string;
title: string;
message: string;
metadata?: any;
}) => api.post("/notifications/test", data),
triggerConditionReminders: () =>
api.post("/notifications/test/condition-reminders"),
cleanupExpired: () => api.post("/notifications/test/cleanup-expired"),
};
export default api;