Merge pull request #51 from rede5/persistencia-de-login-auth-refresh-11312080794
Persistência de Login (Auth Refresh)
This commit is contained in:
commit
0c59752758
5 changed files with 128 additions and 61 deletions
|
|
@ -154,7 +154,7 @@ func (h *Handler) Register(c *gin.Context) {
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: false,
|
Secure: false,
|
||||||
SameSite: http.SameSiteStrictMode,
|
SameSite: http.SameSiteStrictMode,
|
||||||
MaxAge: 15 * 60,
|
MaxAge: 180 * 60, // 3 hours
|
||||||
})
|
})
|
||||||
|
|
||||||
c.JSON(http.StatusCreated, gin.H{
|
c.JSON(http.StatusCreated, gin.H{
|
||||||
|
|
@ -243,7 +243,7 @@ func (h *Handler) Login(c *gin.Context) {
|
||||||
HttpOnly: true,
|
HttpOnly: true,
|
||||||
Secure: false,
|
Secure: false,
|
||||||
SameSite: http.SameSiteStrictMode,
|
SameSite: http.SameSiteStrictMode,
|
||||||
MaxAge: 15 * 60, // 15 mins
|
MaxAge: 180 * 60, // 3 hours
|
||||||
})
|
})
|
||||||
|
|
||||||
// Handle Nullable Fields
|
// Handle Nullable Fields
|
||||||
|
|
@ -362,6 +362,17 @@ func (h *Handler) Refresh(c *gin.Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set new access_token cookie
|
||||||
|
http.SetCookie(c.Writer, &http.Cookie{
|
||||||
|
Name: "access_token",
|
||||||
|
Value: accessToken,
|
||||||
|
Path: "/",
|
||||||
|
HttpOnly: true,
|
||||||
|
Secure: false,
|
||||||
|
SameSite: http.SameSiteStrictMode,
|
||||||
|
MaxAge: 180 * 60, // 3 hours
|
||||||
|
})
|
||||||
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"access_token": accessToken,
|
"access_token": accessToken,
|
||||||
"expires_at": accessExp,
|
"expires_at": accessExp,
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ func LoadConfig() *Config {
|
||||||
DBDsn: getEnv("DB_DSN", ""),
|
DBDsn: getEnv("DB_DSN", ""),
|
||||||
JwtAccessSecret: getEnv("JWT_ACCESS_SECRET", "secret"),
|
JwtAccessSecret: getEnv("JWT_ACCESS_SECRET", "secret"),
|
||||||
JwtRefreshSecret: getEnv("JWT_REFRESH_SECRET", "refresh_secret"),
|
JwtRefreshSecret: getEnv("JWT_REFRESH_SECRET", "refresh_secret"),
|
||||||
JwtAccessTTLMinutes: getEnvAsInt("JWT_ACCESS_TTL_MINUTES", 15),
|
JwtAccessTTLMinutes: getEnvAsInt("JWT_ACCESS_TTL_MINUTES", 180),
|
||||||
JwtRefreshTTLDays: getEnvAsInt("JWT_REFRESH_TTL_DAYS", 30),
|
JwtRefreshTTLDays: getEnvAsInt("JWT_REFRESH_TTL_DAYS", 30),
|
||||||
CorsAllowedOrigins: getEnv("CORS_ALLOWED_ORIGINS", "*"),
|
CorsAllowedOrigins: getEnv("CORS_ALLOWED_ORIGINS", "*"),
|
||||||
SwaggerHost: getEnv("SWAGGER_HOST", "localhost:8080"),
|
SwaggerHost: getEnv("SWAGGER_HOST", "localhost:8080"),
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
import React, { createContext, useContext, useState, ReactNode, useEffect } from 'react';
|
import React, { createContext, useContext, useState, ReactNode, useEffect } from 'react';
|
||||||
import { User, UserRole } from '../types';
|
import { User, UserRole } from '../types';
|
||||||
|
import { apiFetch } from '../services/apiService';
|
||||||
|
|
||||||
// Mock Users Database
|
// Mock Users Database
|
||||||
const MOCK_USERS: User[] = [
|
const MOCK_USERS: User[] = [
|
||||||
|
|
@ -88,7 +89,7 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const API_URL = import.meta.env.VITE_API_URL || "http://localhost:8080";
|
const API_URL = import.meta.env.VITE_API_URL || "http://localhost:8080";
|
||||||
const response = await fetch(`${API_URL}/api/me`, {
|
const response = await apiFetch(`${API_URL}/api/me`, {
|
||||||
headers: {
|
headers: {
|
||||||
'Authorization': `Bearer ${token}`
|
'Authorization': `Bearer ${token}`
|
||||||
}
|
}
|
||||||
|
|
@ -97,7 +98,6 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
const backendUser = data.user;
|
const backendUser = data.user;
|
||||||
console.log("AuthContext: restoreSession raw user:", backendUser);
|
|
||||||
const mappedUser: User = {
|
const mappedUser: User = {
|
||||||
id: backendUser.id,
|
id: backendUser.id,
|
||||||
email: backendUser.email,
|
email: backendUser.email,
|
||||||
|
|
@ -122,7 +122,6 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) =>
|
||||||
professionalId: data.profissional?.id, // Map professional ID
|
professionalId: data.profissional?.id, // Map professional ID
|
||||||
functions: data.profissional?.functions || [],
|
functions: data.profissional?.functions || [],
|
||||||
};
|
};
|
||||||
console.log("AuthContext: restoreSession mapped user:", mappedUser);
|
|
||||||
if (!backendUser.ativo) {
|
if (!backendUser.ativo) {
|
||||||
console.warn("User is not active, logging out.");
|
console.warn("User is not active, logging out.");
|
||||||
logout();
|
logout();
|
||||||
|
|
|
||||||
|
|
@ -651,9 +651,7 @@ export const DataProvider: React.FC<{ children: ReactNode }> = ({
|
||||||
});
|
});
|
||||||
|
|
||||||
const result = await getAgendas(visibleToken);
|
const result = await getAgendas(visibleToken);
|
||||||
console.log("Raw Agenda Data:", result.data); // Debug logging
|
|
||||||
if (result.data) {
|
if (result.data) {
|
||||||
console.log("Sample event from backend:", result.data[0]); // DEBUG: Ver estrutura e status
|
|
||||||
|
|
||||||
// Map backend status to frontend EventStatus
|
// Map backend status to frontend EventStatus
|
||||||
const mapStatus = (backendStatus: string): EventStatus => {
|
const mapStatus = (backendStatus: string): EventStatus => {
|
||||||
|
|
@ -797,11 +795,9 @@ export const DataProvider: React.FC<{ children: ReactNode }> = ({
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchProfs = async () => {
|
const fetchProfs = async () => {
|
||||||
const token = localStorage.getItem('token');
|
const token = localStorage.getItem('token');
|
||||||
console.log("[DEBUG] Fetching Professionals...", { token });
|
|
||||||
if (token) {
|
if (token) {
|
||||||
try {
|
try {
|
||||||
const result = await getProfessionals(token);
|
const result = await getProfessionals(token);
|
||||||
console.log("[DEBUG] Fetch Professionals Result:", result);
|
|
||||||
if (result.data) {
|
if (result.data) {
|
||||||
const mappedProfs: Professional[] = result.data.map((p: any) => ({
|
const mappedProfs: Professional[] = result.data.map((p: any) => ({
|
||||||
id: p.id,
|
id: p.id,
|
||||||
|
|
@ -851,8 +847,6 @@ export const DataProvider: React.FC<{ children: ReactNode }> = ({
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Failed to fetch professionals", error);
|
console.error("Failed to fetch professionals", error);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
console.warn("[DEBUG] No token found for fetching professionals");
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
fetchProfs();
|
fetchProfs();
|
||||||
|
|
|
||||||
|
|
@ -2,20 +2,83 @@
|
||||||
const API_BASE_URL =
|
const API_BASE_URL =
|
||||||
import.meta.env.VITE_API_URL || "http://localhost:8080";
|
import.meta.env.VITE_API_URL || "http://localhost:8080";
|
||||||
|
|
||||||
console.log('API_BASE_URL:', API_BASE_URL);
|
|
||||||
console.log('VITE_API_URL:', import.meta.env.VITE_API_URL);
|
|
||||||
|
|
||||||
interface ApiResponse<T> {
|
interface ApiResponse<T> {
|
||||||
data: T | null;
|
data: T | null;
|
||||||
error: string | null;
|
error: string | null;
|
||||||
isBackendDown: boolean;
|
isBackendDown: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wrapper request handler for 401 token refresh
|
||||||
|
let isRefreshing = false;
|
||||||
|
let refreshSubscribers: ((token: string) => void)[] = [];
|
||||||
|
|
||||||
|
function subscribeTokenRefresh(cb: (token: string) => void) {
|
||||||
|
refreshSubscribers.push(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onRefreshed(token: string) {
|
||||||
|
refreshSubscribers.forEach((cb) => cb(token));
|
||||||
|
refreshSubscribers = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function apiFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
|
||||||
|
let response = await fetch(input, init);
|
||||||
|
|
||||||
|
if (response.status === 401) {
|
||||||
|
const originalRequest = input;
|
||||||
|
const originalInit = init || {};
|
||||||
|
|
||||||
|
if (!isRefreshing) {
|
||||||
|
isRefreshing = true;
|
||||||
|
try {
|
||||||
|
const refreshRes = await fetch(`${API_BASE_URL}/auth/refresh`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
credentials: 'include', // Send the HttpOnly refresh_token cookie
|
||||||
|
});
|
||||||
|
|
||||||
|
if (refreshRes.ok) {
|
||||||
|
const data = await refreshRes.json();
|
||||||
|
const newAccessToken = data.access_token;
|
||||||
|
localStorage.setItem('token', newAccessToken);
|
||||||
|
isRefreshing = false;
|
||||||
|
onRefreshed(newAccessToken);
|
||||||
|
} else {
|
||||||
|
isRefreshing = false;
|
||||||
|
// Refresh failed (token expired/invalid), logout
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
window.location.href = '/entrar';
|
||||||
|
throw new Error('Session expired');
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
isRefreshing = false;
|
||||||
|
localStorage.removeItem('token');
|
||||||
|
window.location.href = '/entrar';
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the token to refresh and then retry the request
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
subscribeTokenRefresh((newToken) => {
|
||||||
|
// Update the Authorization header with the new token
|
||||||
|
const newHeaders = new Headers(originalInit.headers);
|
||||||
|
newHeaders.set('Authorization', `Bearer ${newToken}`);
|
||||||
|
originalInit.headers = newHeaders;
|
||||||
|
|
||||||
|
fetch(originalRequest, originalInit).then(resolve).catch(reject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
// Função auxiliar para fazer requisições
|
// Função auxiliar para fazer requisições
|
||||||
async function fetchFromBackend<T>(endpoint: string): Promise<ApiResponse<T>> {
|
async function fetchFromBackend<T>(endpoint: string): Promise<ApiResponse<T>> {
|
||||||
try {
|
try {
|
||||||
const region = localStorage.getItem("photum_selected_region") || "SP";
|
const region = localStorage.getItem("photum_selected_region") || "SP";
|
||||||
const response = await fetch(`${API_BASE_URL}${endpoint}`, {
|
const response = await apiFetch(`${API_BASE_URL}${endpoint}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -96,7 +159,7 @@ export async function createProfessional(data: any, token?: string): Promise<Api
|
||||||
}
|
}
|
||||||
headers["x-regiao"] = region;
|
headers["x-regiao"] = region;
|
||||||
|
|
||||||
const response = await fetch(`${API_BASE_URL}/api/profissionais`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/profissionais`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: headers,
|
headers: headers,
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
|
|
@ -128,7 +191,7 @@ export async function createProfessional(data: any, token?: string): Promise<Api
|
||||||
*/
|
*/
|
||||||
export async function updateProfessional(id: string, data: any, token: string): Promise<ApiResponse<any>> {
|
export async function updateProfessional(id: string, data: any, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/profissionais/${id}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/profissionais/${id}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -164,7 +227,7 @@ export async function updateProfessional(id: string, data: any, token: string):
|
||||||
*/
|
*/
|
||||||
export async function updateUserProfile(data: any, token: string): Promise<ApiResponse<any>> {
|
export async function updateUserProfile(data: any, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/me`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/me`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -200,7 +263,7 @@ export async function updateUserProfile(data: any, token: string): Promise<ApiRe
|
||||||
*/
|
*/
|
||||||
export async function deleteProfessional(id: string, token: string): Promise<ApiResponse<void>> {
|
export async function deleteProfessional(id: string, token: string): Promise<ApiResponse<void>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/profissionais/${id}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/profissionais/${id}`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -234,7 +297,7 @@ export async function deleteProfessional(id: string, token: string): Promise<Api
|
||||||
*/
|
*/
|
||||||
export async function getProfessionalById(id: string, token: string): Promise<ApiResponse<any>> {
|
export async function getProfessionalById(id: string, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/profissionais/${id}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/profissionais/${id}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -269,7 +332,7 @@ export async function getProfessionalById(id: string, token: string): Promise<Ap
|
||||||
*/
|
*/
|
||||||
export async function getProfessionals(token: string): Promise<ApiResponse<any[]>> {
|
export async function getProfessionals(token: string): Promise<ApiResponse<any[]>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/profissionais`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/profissionais`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -370,7 +433,7 @@ export async function getCadastroFot(token: string, empresaId?: string): Promise
|
||||||
url += `&empresa_id=${empresaId}`;
|
url += `&empresa_id=${empresaId}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(url, {
|
const response = await apiFetch(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -404,7 +467,7 @@ export async function getCadastroFot(token: string, empresaId?: string): Promise
|
||||||
*/
|
*/
|
||||||
export async function createCadastroFot(data: any, token: string): Promise<ApiResponse<any>> {
|
export async function createCadastroFot(data: any, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/cadastro-fot`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/cadastro-fot`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -440,7 +503,7 @@ export async function createCadastroFot(data: any, token: string): Promise<ApiRe
|
||||||
*/
|
*/
|
||||||
export async function updateCadastroFot(id: string, data: any, token: string): Promise<ApiResponse<any>> {
|
export async function updateCadastroFot(id: string, data: any, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/cadastro-fot/${id}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/cadastro-fot/${id}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -476,7 +539,7 @@ export async function updateCadastroFot(id: string, data: any, token: string): P
|
||||||
*/
|
*/
|
||||||
export async function checkFotHasEvents(fotId: string, token: string): Promise<ApiResponse<{ hasEvents: boolean; eventCount: number }>> {
|
export async function checkFotHasEvents(fotId: string, token: string): Promise<ApiResponse<{ hasEvents: boolean; eventCount: number }>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/cadastro-fot/${fotId}/eventos`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/cadastro-fot/${fotId}/eventos`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -510,7 +573,7 @@ export async function checkFotHasEvents(fotId: string, token: string): Promise<A
|
||||||
*/
|
*/
|
||||||
export async function finalizeFOT(id: string, finalizada: boolean, token: string): Promise<ApiResponse<any>> {
|
export async function finalizeFOT(id: string, finalizada: boolean, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/cadastro-fot/${id}/finalize`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/cadastro-fot/${id}/finalize`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -538,7 +601,7 @@ export async function finalizeFOT(id: string, finalizada: boolean, token: string
|
||||||
*/
|
*/
|
||||||
export async function deleteCadastroFot(id: string, token: string): Promise<ApiResponse<void>> {
|
export async function deleteCadastroFot(id: string, token: string): Promise<ApiResponse<void>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/cadastro-fot/${id}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/cadastro-fot/${id}`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -598,7 +661,7 @@ export async function getUniversities(): Promise<
|
||||||
// Agenda
|
// Agenda
|
||||||
export const createAgenda = async (token: string, data: any) => {
|
export const createAgenda = async (token: string, data: any) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/agenda`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/agenda`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -624,7 +687,7 @@ export const createAgenda = async (token: string, data: any) => {
|
||||||
// Agenda
|
// Agenda
|
||||||
export const getAgendas = async (token: string): Promise<ApiResponse<any[]>> => {
|
export const getAgendas = async (token: string): Promise<ApiResponse<any[]>> => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/agenda`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/agenda`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -648,7 +711,7 @@ export const getAgendas = async (token: string): Promise<ApiResponse<any[]>> =>
|
||||||
// Agenda - Update
|
// Agenda - Update
|
||||||
export const updateAgenda = async (token: string, id: string, data: any) => {
|
export const updateAgenda = async (token: string, id: string, data: any) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/agenda/${id}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/agenda/${id}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -673,7 +736,7 @@ export const updateAgenda = async (token: string, id: string, data: any) => {
|
||||||
|
|
||||||
export const updateAssignmentStatus = async (token: string, eventId: string, professionalId: string, status: string, reason?: string) => {
|
export const updateAssignmentStatus = async (token: string, eventId: string, professionalId: string, status: string, reason?: string) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/agenda/${eventId}/professionals/${professionalId}/status`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/agenda/${eventId}/professionals/${professionalId}/status`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
|
|
@ -702,7 +765,7 @@ export const updateAssignmentStatus = async (token: string, eventId: string, pro
|
||||||
*/
|
*/
|
||||||
export async function getPendingUsers(token: string): Promise<ApiResponse<any[]>> {
|
export async function getPendingUsers(token: string): Promise<ApiResponse<any[]>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/admin/users/pending`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/admin/users/pending`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -736,7 +799,7 @@ export async function getPendingUsers(token: string): Promise<ApiResponse<any[]>
|
||||||
*/
|
*/
|
||||||
export async function approveUser(userId: string, token: string): Promise<ApiResponse<any>> {
|
export async function approveUser(userId: string, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/admin/users/${userId}/approve`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/admin/users/${userId}/approve`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -770,7 +833,7 @@ export async function approveUser(userId: string, token: string): Promise<ApiRes
|
||||||
*/
|
*/
|
||||||
export async function rejectUser(userId: string, token: string): Promise<ApiResponse<any>> {
|
export async function rejectUser(userId: string, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/admin/users/${userId}/reject`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/admin/users/${userId}/reject`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -805,7 +868,7 @@ export async function rejectUser(userId: string, token: string): Promise<ApiResp
|
||||||
*/
|
*/
|
||||||
export async function updateUserRole(userId: string, role: string, token: string): Promise<ApiResponse<any>> {
|
export async function updateUserRole(userId: string, role: string, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/admin/users/${userId}/role`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/admin/users/${userId}/role`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -845,7 +908,7 @@ export async function assignProfessional(token: string, eventId: string, profess
|
||||||
body.funcao_id = funcaoId;
|
body.funcao_id = funcaoId;
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await fetch(`${API_BASE_URL}/api/agenda/${eventId}/professionals`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/agenda/${eventId}/professionals`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -871,7 +934,7 @@ export async function assignProfessional(token: string, eventId: string, profess
|
||||||
*/
|
*/
|
||||||
export async function removeProfessional(token: string, eventId: string, professionalId: string): Promise<ApiResponse<void>> {
|
export async function removeProfessional(token: string, eventId: string, professionalId: string): Promise<ApiResponse<void>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/agenda/${eventId}/professionals/${professionalId}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/agenda/${eventId}/professionals/${professionalId}`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -895,7 +958,7 @@ export async function removeProfessional(token: string, eventId: string, profess
|
||||||
*/
|
*/
|
||||||
export async function getAllUsers(token: string): Promise<ApiResponse<any[]>> {
|
export async function getAllUsers(token: string): Promise<ApiResponse<any[]>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/admin/users`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/admin/users`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -929,7 +992,7 @@ export async function getAllUsers(token: string): Promise<ApiResponse<any[]>> {
|
||||||
*/
|
*/
|
||||||
export async function createAdminUser(data: any, token: string): Promise<ApiResponse<any>> {
|
export async function createAdminUser(data: any, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/admin/users`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/admin/users`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -965,7 +1028,7 @@ export async function createAdminUser(data: any, token: string): Promise<ApiResp
|
||||||
*/
|
*/
|
||||||
export async function getEventProfessionals(token: string, eventId: string): Promise<ApiResponse<any[]>> {
|
export async function getEventProfessionals(token: string, eventId: string): Promise<ApiResponse<any[]>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/agenda/${eventId}/professionals`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/agenda/${eventId}/professionals`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -990,7 +1053,7 @@ export async function getEventProfessionals(token: string, eventId: string): Pro
|
||||||
*/
|
*/
|
||||||
export async function updateEventStatus(token: string, eventId: string, status: string): Promise<ApiResponse<void>> {
|
export async function updateEventStatus(token: string, eventId: string, status: string): Promise<ApiResponse<void>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/agenda/${eventId}/status`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/agenda/${eventId}/status`, {
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -1016,7 +1079,7 @@ export async function updateEventStatus(token: string, eventId: string, status:
|
||||||
*/
|
*/
|
||||||
export async function notifyLogistics(token: string, eventId: string, passengerOrders?: any): Promise<ApiResponse<void>> {
|
export async function notifyLogistics(token: string, eventId: string, passengerOrders?: any): Promise<ApiResponse<void>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/agenda/${eventId}/notify-logistics`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/agenda/${eventId}/notify-logistics`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -1042,7 +1105,7 @@ export async function notifyLogistics(token: string, eventId: string, passengerO
|
||||||
*/
|
*/
|
||||||
export async function adminCreateUser(data: any, token: string): Promise<ApiResponse<any>> {
|
export async function adminCreateUser(data: any, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/admin/users`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/admin/users`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -1078,7 +1141,7 @@ export async function adminCreateUser(data: any, token: string): Promise<ApiResp
|
||||||
*/
|
*/
|
||||||
export async function getUploadURL(filename: string, contentType: string): Promise<ApiResponse<{ upload_url: string; public_url: string }>> {
|
export async function getUploadURL(filename: string, contentType: string): Promise<ApiResponse<{ upload_url: string; public_url: string }>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/auth/upload-url`, {
|
const response = await apiFetch(`${API_BASE_URL}/auth/upload-url`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -1122,7 +1185,7 @@ export async function deleteAccessCode(token: string, id: string) {
|
||||||
// Helpers for unified fetch
|
// Helpers for unified fetch
|
||||||
async function fetchFromBackendAuthenticated(url: string, token: string) {
|
async function fetchFromBackendAuthenticated(url: string, token: string) {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(url, {
|
const res = await apiFetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": `Bearer ${token}`,
|
"Authorization": `Bearer ${token}`,
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -1139,7 +1202,7 @@ async function fetchFromBackendAuthenticated(url: string, token: string) {
|
||||||
|
|
||||||
async function mutationFetch(url: string, method: string, body: any, token: string) {
|
async function mutationFetch(url: string, method: string, body: any, token: string) {
|
||||||
try {
|
try {
|
||||||
const res = await fetch(url, {
|
const res = await apiFetch(url, {
|
||||||
method,
|
method,
|
||||||
headers: {
|
headers: {
|
||||||
"Authorization": `Bearer ${token}`,
|
"Authorization": `Bearer ${token}`,
|
||||||
|
|
@ -1164,7 +1227,7 @@ async function mutationFetch(url: string, method: string, body: any, token: stri
|
||||||
* Realiza o upload do arquivo para a URL pré-assinada
|
* Realiza o upload do arquivo para a URL pré-assinada
|
||||||
*/
|
*/
|
||||||
export async function uploadFileToSignedUrl(uploadUrl: string, file: File): Promise<void> {
|
export async function uploadFileToSignedUrl(uploadUrl: string, file: File): Promise<void> {
|
||||||
const response = await fetch(uploadUrl, {
|
const response = await apiFetch(uploadUrl, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": file.type,
|
"Content-Type": file.type,
|
||||||
|
|
@ -1189,7 +1252,7 @@ export interface EscalaInput {
|
||||||
|
|
||||||
export async function createEscala(data: EscalaInput, token: string): Promise<ApiResponse<{ id: string }>> {
|
export async function createEscala(data: EscalaInput, token: string): Promise<ApiResponse<{ id: string }>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/escalas`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/escalas`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -1213,7 +1276,7 @@ export async function createEscala(data: EscalaInput, token: string): Promise<Ap
|
||||||
|
|
||||||
export async function listEscalas(agendaId: string, token: string): Promise<ApiResponse<any[]>> {
|
export async function listEscalas(agendaId: string, token: string): Promise<ApiResponse<any[]>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/escalas?agenda_id=${agendaId}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/escalas?agenda_id=${agendaId}`, {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -1231,7 +1294,7 @@ export async function listEscalas(agendaId: string, token: string): Promise<ApiR
|
||||||
|
|
||||||
export async function deleteEscala(id: string, token: string): Promise<ApiResponse<any>> {
|
export async function deleteEscala(id: string, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/escalas/${id}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/escalas/${id}`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
});
|
});
|
||||||
|
|
@ -1249,7 +1312,7 @@ export async function deleteEscala(id: string, token: string): Promise<ApiRespon
|
||||||
|
|
||||||
export async function updateEscala(id: string, data: Partial<EscalaInput>, token: string): Promise<ApiResponse<any>> {
|
export async function updateEscala(id: string, data: Partial<EscalaInput>, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/escalas/${id}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/escalas/${id}`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -1282,7 +1345,7 @@ export interface CarroInput {
|
||||||
|
|
||||||
export async function createCarro(data: CarroInput, token: string): Promise<ApiResponse<{ id: string }>> {
|
export async function createCarro(data: CarroInput, token: string): Promise<ApiResponse<{ id: string }>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/logistica/carros`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/logistica/carros`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
|
headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
|
||||||
body: JSON.stringify(data),
|
body: JSON.stringify(data),
|
||||||
|
|
@ -1295,7 +1358,7 @@ export async function createCarro(data: CarroInput, token: string): Promise<ApiR
|
||||||
|
|
||||||
export async function listCarros(agendaId: string, token: string): Promise<ApiResponse<any[]>> {
|
export async function listCarros(agendaId: string, token: string): Promise<ApiResponse<any[]>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/logistica/carros?agenda_id=${agendaId}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/logistica/carros?agenda_id=${agendaId}`, {
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
});
|
});
|
||||||
const resData = await response.json();
|
const resData = await response.json();
|
||||||
|
|
@ -1306,7 +1369,7 @@ export async function listCarros(agendaId: string, token: string): Promise<ApiRe
|
||||||
|
|
||||||
export async function deleteCarro(id: string, token: string): Promise<ApiResponse<any>> {
|
export async function deleteCarro(id: string, token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/logistica/carros/${id}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/logistica/carros/${id}`, {
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
headers: { "Authorization": `Bearer ${token}` },
|
headers: { "Authorization": `Bearer ${token}` },
|
||||||
});
|
});
|
||||||
|
|
@ -1317,7 +1380,7 @@ export async function deleteCarro(id: string, token: string): Promise<ApiRespons
|
||||||
|
|
||||||
export async function addPassenger(carroId: string, profissionalId: string, token: string) {
|
export async function addPassenger(carroId: string, profissionalId: string, token: string) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/logistica/carros/${carroId}/passageiros`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/logistica/carros/${carroId}/passageiros`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
|
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` },
|
||||||
body: JSON.stringify({ profissional_id: profissionalId })
|
body: JSON.stringify({ profissional_id: profissionalId })
|
||||||
|
|
@ -1329,7 +1392,7 @@ export async function addPassenger(carroId: string, profissionalId: string, toke
|
||||||
|
|
||||||
export async function removePassenger(carroId: string, profissionalId: string, token: string) {
|
export async function removePassenger(carroId: string, profissionalId: string, token: string) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/logistica/carros/${carroId}/passageiros/${profissionalId}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/logistica/carros/${carroId}/passageiros/${profissionalId}`, {
|
||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
headers: { 'Authorization': `Bearer ${token}` }
|
headers: { 'Authorization': `Bearer ${token}` }
|
||||||
});
|
});
|
||||||
|
|
@ -1340,7 +1403,7 @@ export async function removePassenger(carroId: string, profissionalId: string, t
|
||||||
|
|
||||||
export async function listPassengers(carroId: string, token: string) {
|
export async function listPassengers(carroId: string, token: string) {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/logistica/carros/${carroId}/passageiros`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/logistica/carros/${carroId}/passageiros`, {
|
||||||
headers: { 'Authorization': `Bearer ${token}` }
|
headers: { 'Authorization': `Bearer ${token}` }
|
||||||
});
|
});
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
@ -1361,7 +1424,7 @@ export async function verifyAccessCode(code: string): Promise<ApiResponse<{ vali
|
||||||
*/
|
*/
|
||||||
export async function getProfessionalFinancialStatement(token: string): Promise<ApiResponse<any>> {
|
export async function getProfessionalFinancialStatement(token: string): Promise<ApiResponse<any>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/profissionais/me/financial-statement`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/profissionais/me/financial-statement`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -1396,7 +1459,7 @@ export async function getProfessionalFinancialStatement(token: string): Promise<
|
||||||
*/
|
*/
|
||||||
export async function getPrice(token: string, eventName: string, serviceName: string): Promise<ApiResponse<{ valor: number }>> {
|
export async function getPrice(token: string, eventName: string, serviceName: string): Promise<ApiResponse<{ valor: number }>> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`${API_BASE_URL}/api/finance/price?event=${encodeURIComponent(eventName)}&service=${encodeURIComponent(serviceName)}`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/finance/price?event=${encodeURIComponent(eventName)}&service=${encodeURIComponent(serviceName)}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -1419,7 +1482,7 @@ export async function getPrice(token: string, eventName: string, serviceName: st
|
||||||
export const setCoordinator = async (token: string, eventId: string, professionalId: string, isCoordinator: boolean) => {
|
export const setCoordinator = async (token: string, eventId: string, professionalId: string, isCoordinator: boolean) => {
|
||||||
try {
|
try {
|
||||||
const region = localStorage.getItem("photum_selected_region") || "SP";
|
const region = localStorage.getItem("photum_selected_region") || "SP";
|
||||||
const response = await fetch(`${API_BASE_URL}/api/agenda/${eventId}/professionals/${professionalId}/coordinator`, {
|
const response = await apiFetch(`${API_BASE_URL}/api/agenda/${eventId}/professionals/${professionalId}/coordinator`, {
|
||||||
method: "PUT",
|
method: "PUT",
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${token}`,
|
Authorization: `Bearer ${token}`,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue