added csrf token
This commit is contained in:
parent
db816b4879
commit
e488062aed
@ -143,7 +143,7 @@ const AdminDashboard = () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="mx-auto flex w-full max-w-[1280px] items-center gap-4">
|
<div className="cursor-pointer mx-auto flex w-full max-w-[1280px] items-center gap-4">
|
||||||
<StatCard
|
<StatCard
|
||||||
label="Total Establishments"
|
label="Total Establishments"
|
||||||
value={loading ? '--' : summary.total_establishments}
|
value={loading ? '--' : summary.total_establishments}
|
||||||
|
|||||||
@ -590,108 +590,81 @@ const ValidationReview = () => {
|
|||||||
const checked = e.target.checked;
|
const checked = e.target.checked;
|
||||||
setShowPreviousNext(checked);
|
setShowPreviousNext(checked);
|
||||||
|
|
||||||
if (checked) {
|
// Uncheck → reset
|
||||||
try {
|
if (!checked) {
|
||||||
setFetchingNextQuarter(true);
|
|
||||||
|
|
||||||
const currentQuarter = quarterPeriods?.current_quarter || "Q4";
|
|
||||||
const currentYear = quarterPeriods?.current_year || 2025;
|
|
||||||
|
|
||||||
const establishmentId = submissionData?.establishment?.id;
|
|
||||||
const productId = submissionData?.products?.[0]?.product?.id;
|
|
||||||
|
|
||||||
if (!establishmentId || !currentQuarter || !currentYear || !productId) {
|
|
||||||
console.error("Missing required parameters:", {
|
|
||||||
establishmentId,
|
|
||||||
currentQuarter,
|
|
||||||
currentYear,
|
|
||||||
productId,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// API call
|
|
||||||
const response = await getBeforePreviousData(
|
|
||||||
establishmentId,
|
|
||||||
currentQuarter,
|
|
||||||
currentYear,
|
|
||||||
productId
|
|
||||||
);
|
|
||||||
|
|
||||||
let mappedDataMap = {};
|
|
||||||
|
|
||||||
if (response?.data) {
|
|
||||||
submissionData.products.forEach((product) => {
|
|
||||||
const pid = product?.product?.id;
|
|
||||||
if (pid) {
|
|
||||||
mappedDataMap[pid] = {
|
|
||||||
forecast_quantity_period_one:
|
|
||||||
response.data.current_quantity_period_one ?? 0,
|
|
||||||
forecast_quantity_period_two:
|
|
||||||
response.data.current_quantity_period_two ?? 0,
|
|
||||||
forecast_quantity_period_three:
|
|
||||||
response.data.current_quantity_period_three ?? 0,
|
|
||||||
|
|
||||||
forecast_cost_period_one:
|
|
||||||
response.data.current_cost_period_one ?? 0,
|
|
||||||
forecast_cost_period_two:
|
|
||||||
response.data.current_cost_period_two ?? 0,
|
|
||||||
forecast_cost_period_three:
|
|
||||||
response.data.current_cost_period_three ?? 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// if no backend data
|
|
||||||
submissionData.products.forEach((product) => {
|
|
||||||
const pid = product?.product?.id;
|
|
||||||
if (pid) {
|
|
||||||
mappedDataMap[pid] = {
|
|
||||||
forecast_quantity_period_one: 0,
|
|
||||||
forecast_quantity_period_two: 0,
|
|
||||||
forecast_quantity_period_three: 0,
|
|
||||||
forecast_cost_period_one: 0,
|
|
||||||
forecast_cost_period_two: 0,
|
|
||||||
forecast_cost_period_three: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setNextQuarterData(mappedDataMap);
|
|
||||||
|
|
||||||
// Calculate previous-previous quarter UI labels
|
|
||||||
const q = Number(currentQuarter.replace("Q", ""));
|
|
||||||
let historicalQuarter = `Q${q - 2}`;
|
|
||||||
let historicalYear = currentYear;
|
|
||||||
|
|
||||||
if (q - 2 <= 0) {
|
|
||||||
historicalQuarter = `Q${4 + (q - 2)}`;
|
|
||||||
historicalYear = currentYear - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
setAdditionalForecastQuarter(historicalQuarter);
|
|
||||||
setAdditionalForecastYear(historicalYear);
|
|
||||||
setAdditionalForecastMonths(
|
|
||||||
getMonthsForQuarter(historicalQuarter, historicalYear)
|
|
||||||
);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching before-previous data:", error);
|
|
||||||
} finally {
|
|
||||||
setFetchingNextQuarter(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// On uncheck, clear values
|
|
||||||
setNextQuarterData({});
|
setNextQuarterData({});
|
||||||
setAdditionalForecastQuarter("");
|
setAdditionalForecastQuarter("");
|
||||||
setAdditionalForecastYear("");
|
setAdditionalForecastYear("");
|
||||||
setAdditionalForecastMonths(["", "", ""]);
|
setAdditionalForecastMonths(["", "", ""]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
setFetchingNextQuarter(true);
|
||||||
|
|
||||||
|
const establishmentId = submissionData?.establishment?.id;
|
||||||
|
const productId = submissionData?.products?.[0]?.product?.id;
|
||||||
|
|
||||||
|
if (!establishmentId || !productId) {
|
||||||
|
console.error("Missing required params");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// API Call
|
||||||
|
const response = await getBeforePreviousData(
|
||||||
|
establishmentId,
|
||||||
|
quarterPeriods?.current_quarter,
|
||||||
|
quarterPeriods?.current_year,
|
||||||
|
productId
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
let mappedDataMap = {};
|
||||||
|
|
||||||
|
submissionData?.products?.forEach((product) => {
|
||||||
|
const pid = product?.product?.id;
|
||||||
|
if (!pid) return;
|
||||||
|
|
||||||
|
mappedDataMap[pid] = {
|
||||||
|
forecast_quantity_period_one:
|
||||||
|
response?.data?.forecast_quantity_period_one ?? 0,
|
||||||
|
forecast_quantity_period_two:
|
||||||
|
response?.data?.forecast_quantity_period_two ?? 0,
|
||||||
|
forecast_quantity_period_three:
|
||||||
|
response?.data?.forecast_quantity_period_three ?? 0,
|
||||||
|
|
||||||
|
forecast_cost_period_one:
|
||||||
|
response?.data?.forecast_cost_period_one ?? 0,
|
||||||
|
forecast_cost_period_two:
|
||||||
|
response?.data?.forecast_cost_period_two ?? 0,
|
||||||
|
forecast_cost_period_three:
|
||||||
|
response?.data?.forecast_cost_period_three ?? 0,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
setNextQuarterData(mappedDataMap);
|
||||||
|
|
||||||
|
// DIRECTLY FROM API – NO CALCULATION
|
||||||
|
const qp = response?.data?.quarter_periods;
|
||||||
|
|
||||||
|
setAdditionalForecastQuarter(qp?.forecast_quarter);
|
||||||
|
setAdditionalForecastYear(qp?.forecast_year);
|
||||||
|
setAdditionalForecastMonths([
|
||||||
|
qp?.forecast_month?.forecast_period_one,
|
||||||
|
qp?.forecast_month?.forecast_period_two,
|
||||||
|
qp?.forecast_month?.forecast_period_three,
|
||||||
|
]);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching forecast data:", error);
|
||||||
|
} finally {
|
||||||
|
setFetchingNextQuarter(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Helper to get forecast data for a specific product
|
// Helper to get forecast data for a specific product
|
||||||
const getCurrentYearForecastData = (productId) => {
|
const getCurrentYearForecastData = (productId) => {
|
||||||
if (!showPreviousNext || !productId) {
|
if (!showPreviousNext || !productId) {
|
||||||
@ -920,7 +893,7 @@ const getQuarterYearLabel = (quarter, year) => {
|
|||||||
const previousYear = quarterPeriods?.previous_year || 2025;
|
const previousYear = quarterPeriods?.previous_year || 2025;
|
||||||
const currentQuarter = quarterPeriods?.current_quarter || 'Q4';
|
const currentQuarter = quarterPeriods?.current_quarter || 'Q4';
|
||||||
const currentYear = quarterPeriods?.current_year || 2025;
|
const currentYear = quarterPeriods?.current_year || 2025;
|
||||||
const forecastQuarter = quarterPeriods?.forecast_quarter || 'Q1';
|
const forecastQuarter = quarterPeriods?.forecast_quarter || '-';
|
||||||
const forecastYear = quarterPeriods?.forecast_year || 2026;
|
const forecastYear = quarterPeriods?.forecast_year || 2026;
|
||||||
|
|
||||||
// Get dynamic month information from API response
|
// Get dynamic month information from API response
|
||||||
@ -962,8 +935,6 @@ const additionalForecastLabel =
|
|||||||
? `${additionalForecastQuarter} ${additionalForecastYear}`
|
? `${additionalForecastQuarter} ${additionalForecastYear}`
|
||||||
: '';
|
: '';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const establishmentDetails = [
|
const establishmentDetails = [
|
||||||
{
|
{
|
||||||
label: 'Establishment Name',
|
label: 'Establishment Name',
|
||||||
@ -1140,7 +1111,7 @@ const additionalForecastLabel =
|
|||||||
<select
|
<select
|
||||||
value={threshold}
|
value={threshold}
|
||||||
onChange={(e) => setThreshold(Number(e.target.value))}
|
onChange={(e) => setThreshold(Number(e.target.value))}
|
||||||
className="border border-[#D1D5DB] rounded-md px-3 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-[#92722A]"
|
className="border border-[#D1D5DB] rounded-md px-3 py-1 text-sm "
|
||||||
>
|
>
|
||||||
<option value="5">5%</option>
|
<option value="5">5%</option>
|
||||||
<option value="10">10%</option>
|
<option value="10">10%</option>
|
||||||
@ -1154,6 +1125,7 @@ const additionalForecastLabel =
|
|||||||
<option value="80">80%</option>
|
<option value="80">80%</option>
|
||||||
<option value="90">90%</option>
|
<option value="90">90%</option>
|
||||||
<option value="100">100%</option>
|
<option value="100">100%</option>
|
||||||
|
<option value="101">Above 100%</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
@ -1175,11 +1147,14 @@ const additionalForecastLabel =
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{varianceHighlighting && (
|
{varianceHighlighting && (
|
||||||
<div className="text-xs text-[#6B7280]">
|
<div className="text-xs text-[#6B7280]">
|
||||||
Cells with variance > {threshold}% will be highlighted
|
Cells with variance{" "}
|
||||||
</div>
|
{threshold <= 100 ? `≤ ${threshold}%` : "> 100%"} will be highlighted
|
||||||
)}
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<table className="min-w-full text-sm text-left border-collapse">
|
<table className="min-w-full text-sm text-left border-collapse">
|
||||||
<thead>
|
<thead>
|
||||||
|
|||||||
@ -444,7 +444,7 @@ React.useEffect(() => {
|
|||||||
<div className="px-6 pt-6 pb-5 space-y-4">
|
<div className="px-6 pt-6 pb-5 space-y-4">
|
||||||
<div className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
|
<div className="flex flex-col gap-2 md:flex-row md:items-center md:justify-between">
|
||||||
<h2 className="text-[18px] font-medium text-[#232528]">
|
<h2 className="text-[18px] font-medium text-[#232528]">
|
||||||
Manage Submissions <span className="text-[#7A7F87]">({filtered.length})</span>
|
Manage Submissions <span className="text-[#232528]">({filtered.length})</span>
|
||||||
</h2>
|
</h2>
|
||||||
<div className="flex flex-wrap gap-3">
|
<div className="flex flex-wrap gap-3">
|
||||||
<div className="relative w-[320px]">
|
<div className="relative w-[320px]">
|
||||||
|
|||||||
@ -30,26 +30,27 @@ const ToggleableInput = ({
|
|||||||
error ? "border-red-500" : "border-[#92722A]"
|
error ? "border-red-500" : "border-[#92722A]"
|
||||||
} focus:border-[#92722A] focus:ring-0 px-4 pr-11 text-sm bg-white`}
|
} focus:border-[#92722A] focus:ring-0 px-4 pr-11 text-sm bg-white`}
|
||||||
/>
|
/>
|
||||||
<button
|
{type === 'password' && (
|
||||||
type="button"
|
<button
|
||||||
className="absolute inset-y-0 right-0 px-3 flex items-center cursor-pointer"
|
type="button"
|
||||||
onClick={toggleShow}
|
className="absolute inset-y-0 right-0 px-3 flex items-center cursor-pointer"
|
||||||
aria-label="Toggle visibility"
|
onClick={toggleShow}
|
||||||
>
|
aria-label="Toggle visibility"
|
||||||
{show ? (
|
>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 text-[#92722A]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
{show ? (
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8S1 12 1 12z" />
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 text-[#92722A]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
<circle cx="12" cy="12" r="3" strokeWidth="2" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8S1 12 1 12z" />
|
||||||
</svg>
|
<circle cx="12" cy="12" r="3" strokeWidth="2" />
|
||||||
) : (
|
</svg>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 text-[#92722A]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
) : (
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"
|
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 text-[#92722A]" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||||
d="M13.875 18.825A10.05 10.05 0 0 1 12 19c-5.523 0-10-4.477-10-10a9.96 9.96 0 0 1 2.122-6.21m3.086-1.955A9.953 9.953 0 0 1 12 3c5.523 0 10 4.477 10 10 0 1.591-.372 3.093-1.034 4.432M9.88 9.88a3 3 0 1 0 4.24 4.24" />
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2"
|
||||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="m3 3 18 18" />
|
d="M13.875 18.825A10.05 10.05 0 0 1 12 19c-5.523 0-10-4.477-10-10a9.96 9.96 0 0 1 2.122-6.21m3.086-1.955A9.953 9.953 0 0 1 12 3c5.523 0 10 4.477 10 10 0 1.591-.372 3.093-1.034 4.432M9.88 9.88a3 3 0 1 0 4.24 4.24" />
|
||||||
</svg>
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="m3 3 18 18" />
|
||||||
|
</svg>
|
||||||
)}
|
)}
|
||||||
</button>
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
{error && <p className="text-xs text-red-600 mt-1">{error}</p>}
|
{error && <p className="text-xs text-red-600 mt-1">{error}</p>}
|
||||||
</div>
|
</div>
|
||||||
@ -220,49 +221,50 @@ if (newPassword !== confirmPassword) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ToggleableInput
|
<ToggleableInput
|
||||||
label="Verification Code"
|
label="Verification Code"
|
||||||
required
|
required
|
||||||
value={otp}
|
value={otp}
|
||||||
onChange={(e) => setOtp(e.target.value)}
|
onChange={(e) => setOtp(e.target.value)}
|
||||||
show={showOtp}
|
placeholder="Enter 6-digit code"
|
||||||
toggleShow={() => setShowOtp((v) => !v)}
|
error={otpError}
|
||||||
placeholder="Enter 6-digit code"
|
autoComplete="one-time-code"
|
||||||
error={otpError}
|
type="text"
|
||||||
autoComplete="one-time-code"
|
/>
|
||||||
/>
|
|
||||||
|
|
||||||
<ToggleableInput
|
<ToggleableInput
|
||||||
label="New Password"
|
label="New Password"
|
||||||
required
|
required
|
||||||
value={newPassword}
|
value={newPassword}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setNewPassword(value);
|
setNewPassword(value);
|
||||||
const passwordError = validatePassword(value);
|
const passwordError = validatePassword(value);
|
||||||
setNewPasswordError(passwordError);
|
setNewPasswordError(passwordError);
|
||||||
}}
|
}}
|
||||||
autoComplete="new-password"
|
type="password"
|
||||||
show={showNewPassword}
|
autoComplete="new-password"
|
||||||
toggleShow={() => setShowNewPassword((v) => !v)}
|
show={showNewPassword}
|
||||||
placeholder="Enter new password"
|
toggleShow={() => setShowNewPassword((v) => !v)}
|
||||||
error={newPasswordError}
|
placeholder="Enter new password"
|
||||||
/>
|
error={newPasswordError}
|
||||||
|
/>
|
||||||
|
|
||||||
<ToggleableInput
|
<ToggleableInput
|
||||||
label="Confirm New Password"
|
label="Confirm New Password"
|
||||||
required
|
required
|
||||||
value={confirmPassword}
|
value={confirmPassword}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
const value = e.target.value;
|
const value = e.target.value;
|
||||||
setConfirmPassword(value);
|
setConfirmPassword(value);
|
||||||
if (newPassword === value) setConfirmPasswordError("");
|
if (newPassword === value) setConfirmPasswordError("");
|
||||||
}}
|
}}
|
||||||
autoComplete="new-password"
|
type="password"
|
||||||
show={showConfirmPassword}
|
autoComplete="new-password"
|
||||||
toggleShow={() => setShowConfirmPassword((v) => !v)}
|
show={showConfirmPassword}
|
||||||
placeholder="Re-enter new password"
|
toggleShow={() => setShowConfirmPassword((v) => !v)}
|
||||||
error={confirmPasswordError}
|
placeholder="Re-enter new password"
|
||||||
/>
|
error={confirmPasswordError}
|
||||||
|
/>
|
||||||
{newPassword && (
|
{newPassword && (
|
||||||
<ul className="text-xs text-gray-600 list-disc pl-5 space-y-1">
|
<ul className="text-xs text-gray-600 list-disc pl-5 space-y-1">
|
||||||
<li className={/.{8,}/.test(newPassword) ? "text-green-600" : ""}>
|
<li className={/.{8,}/.test(newPassword) ? "text-green-600" : ""}>
|
||||||
|
|||||||
@ -1,12 +1,29 @@
|
|||||||
import apiClient from '@/services/api/apiClient';
|
import apiClient, { fetchCsrfToken } from './apiClient';
|
||||||
|
|
||||||
|
const withCsrf = async (requestFn, ...args) => {
|
||||||
|
try {
|
||||||
|
await fetchCsrfToken();
|
||||||
|
return await requestFn(...args);
|
||||||
|
} catch (error) {
|
||||||
|
if (error.response?.status === 403 && error.response?.data?.message?.includes('CSRF')) {
|
||||||
|
// If we get a CSRF error, try to refresh the token and retry once
|
||||||
|
await fetchCsrfToken();
|
||||||
|
return await requestFn(...args);
|
||||||
|
}
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const getRequest = (url, config = {}) => apiClient.get(url, config);
|
export const getRequest = (url, config = {}) => apiClient.get(url, config);
|
||||||
|
|
||||||
export const postRequest = (url, data, config = {}) => apiClient.post(url, data, config);
|
export const postRequest = (url, data, config = {}) =>
|
||||||
|
withCsrf(apiClient.post.bind(apiClient), url, data, config);
|
||||||
|
|
||||||
export const putRequest = (url, data, config = {}) => apiClient.put(url, data, config);
|
export const putRequest = (url, data, config = {}) =>
|
||||||
|
withCsrf(apiClient.put.bind(apiClient), url, data, config);
|
||||||
|
|
||||||
export const deleteRequest = (url, config = {}) => apiClient.delete(url, config);
|
export const deleteRequest = (url, config = {}) =>
|
||||||
|
withCsrf(apiClient.delete.bind(apiClient), url, config);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getRequest,
|
getRequest,
|
||||||
|
|||||||
@ -4,6 +4,9 @@ const baseURL = import.meta.env.VITE_API_BASE_URL;
|
|||||||
const appSignature = import.meta.env.VITE_API_APP_SIGNATURE;
|
const appSignature = import.meta.env.VITE_API_APP_SIGNATURE;
|
||||||
const fallbackToken = import.meta.env.VITE_API_TOKEN;
|
const fallbackToken = import.meta.env.VITE_API_TOKEN;
|
||||||
|
|
||||||
|
// Store CSRF token in memory
|
||||||
|
let csrfToken = null;
|
||||||
|
|
||||||
const apiClient = axios.create({
|
const apiClient = axios.create({
|
||||||
baseURL,
|
baseURL,
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
@ -14,8 +17,34 @@ const apiClient = axios.create({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches and stores a new CSRF token from the server
|
||||||
|
* @returns {Promise<string>} The CSRF token
|
||||||
|
*/
|
||||||
|
export const fetchCsrfToken = async () => {
|
||||||
|
try {
|
||||||
|
const response = await apiClient.get('/csrf-token');
|
||||||
|
csrfToken = response.data.csrfToken;
|
||||||
|
return csrfToken;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch CSRF token:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
apiClient.interceptors.request.use((config) => {
|
apiClient.interceptors.request.use((config) => {
|
||||||
config.headers = config.headers ?? {};
|
config.headers = config.headers ?? {};
|
||||||
|
|
||||||
|
// Skip auth for CSRF token endpoint
|
||||||
|
if (config.url === '/csrf-token') {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add CSRF token for write operations
|
||||||
|
if (csrfToken && ['post', 'put', 'patch', 'delete'].includes(config.method?.toLowerCase())) {
|
||||||
|
config.headers['X-CSRF-Token'] = csrfToken;
|
||||||
|
}
|
||||||
|
|
||||||
if (config.skipAuth) {
|
if (config.skipAuth) {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@ -34,6 +63,7 @@ apiClient.interceptors.request.use((config) => {
|
|||||||
// config.headers.Authorization = `Bearer ${token}`;
|
// config.headers.Authorization = `Bearer ${token}`;
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user