Redirect Solved 09-10
This commit is contained in:
parent
b3beb64265
commit
a7b7be491e
|
|
@ -488,7 +488,7 @@ const ProcessStepOne = () => {
|
||||||
transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES &&
|
transactionTemplateToggle !== TRANSACTION_TEMPLATE_TOGGLE.TEMPLATES &&
|
||||||
<div className="flex justify-between items-center">
|
<div className="flex justify-between items-center">
|
||||||
<h2 className=" text-lg font-medium mb-4 pt-6 text-[var(--processStepOneTextHead)]">Signers</h2>
|
<h2 className=" text-lg font-medium mb-4 pt-6 text-[var(--processStepOneTextHead)]">Signers</h2>
|
||||||
<div className="flex items-center mr-3">
|
{/* <div className="flex items-center mr-3">
|
||||||
<input
|
<input
|
||||||
checked={signType === SignTypeEnum.selfSign}
|
checked={signType === SignTypeEnum.selfSign}
|
||||||
onChange={(e) => handleSelfSignCb(e)}
|
onChange={(e) => handleSelfSignCb(e)}
|
||||||
|
|
@ -496,7 +496,7 @@ const ProcessStepOne = () => {
|
||||||
/>
|
/>
|
||||||
<label htmlFor="default-checkbox" className="ms-2 text-sm flex gap-1 text-slate-600">
|
<label htmlFor="default-checkbox" className="ms-2 text-sm flex gap-1 text-slate-600">
|
||||||
I AM THE ONLY SIGNER</label>
|
I AM THE ONLY SIGNER</label>
|
||||||
</div>
|
</div> */}
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -164,18 +164,21 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
||||||
if (res.data.length) {
|
if (res.data.length) {
|
||||||
const defaultVal = res.data.filter((obj, indx) => "default" in obj && obj.default);
|
const defaultVal = res.data.filter((obj, indx) => "default" in obj && obj.default);
|
||||||
|
|
||||||
const { id, initialsBlob, signatureBlob } = defaultVal[0];
|
if (defaultVal.length > 0) {
|
||||||
|
const { id, initialsBlob, signatureBlob } = defaultVal[0];
|
||||||
|
|
||||||
if (initialsBlob && signatureBlob) {
|
if (initialsBlob && signatureBlob) {
|
||||||
setSaved({
|
setSaved({
|
||||||
signatureId: id,
|
signatureId: id,
|
||||||
saveType: SaveTypeEnum.DRAW,
|
saveType: SaveTypeEnum.DRAW,
|
||||||
save: true,
|
save: true,
|
||||||
signature: signatureBlob,
|
signature: signatureBlob,
|
||||||
initial: initialsBlob,
|
initial: initialsBlob,
|
||||||
isDefaultAndClicked: true
|
isDefaultAndClicked: true
|
||||||
});
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
setPreSaveSignatures(preSavedSignatures)
|
setPreSaveSignatures(preSavedSignatures)
|
||||||
}
|
}
|
||||||
|
|
@ -705,28 +708,31 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
||||||
return (
|
return (
|
||||||
<div className="h-full flex flex-col">
|
<div className="h-full flex flex-col">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<div className="mb-6 px-4 sm:px-6">
|
<div className="my-4 px-4 sm:px-6">
|
||||||
<h2 className="text-2xl font-semibold text-gray-900 mb-2">Saved Signatures</h2>
|
<h2 className="text-2xl font-semibold text-gray-900 mb-1">Saved Signatures</h2>
|
||||||
<p className="text-sm text-gray-600">Select from your pre-saved signatures</p>
|
<p className="text-sm text-gray-600">Select from your pre-saved signatures</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Signatures List */}
|
{/* Horizontal Scrollable List */}
|
||||||
<div className="flex-1 overflow-y-auto px-2 sm:px-6">
|
<div className="flex-1 overflow-x-auto px-2 sm:px-6">
|
||||||
<div className="space-y-4">
|
<div className="flex flex-col space-x-4 max-h-[40vh] gap-2">
|
||||||
{preSaveSignatures.map((signature) => (
|
{preSaveSignatures.map((signature) => (
|
||||||
<div
|
<div
|
||||||
key={signature?.id}
|
key={signature?.id}
|
||||||
className="flex flex-col md:flex-row md:space-x-4 bg-white rounded-xl border border-gray-200 p-4 hover:shadow-lg transition-shadow duration-200"
|
onClick={() => setSelectedSignature(signature?.id)}
|
||||||
|
className={`cursor-pointer bg-white rounded-xl border p-4 w-full flex justify-between items-start transition-shadow duration-200 gap-3
|
||||||
|
${selectedSignature === signature?.id ? 'border-blue-500 shadow-lg' : 'border-gray-200'}
|
||||||
|
`}
|
||||||
|
style={{ minWidth: '220px' }} // each card width
|
||||||
>
|
>
|
||||||
{/* Full Signature */}
|
{/* Signature */}
|
||||||
<div className="flex-1 flex flex-col space-y-2 border-l-4 border-blue-500 rounded-l-xl pl-4 md:pl-6 py-2">
|
<div className="w-[60%] flex flex-col">
|
||||||
<span className="text-sm font-medium text-gray-600">Signed by:</span>
|
<span className="text-sm font-medium text-gray-600 mb-1">Signed by:</span>
|
||||||
|
<div className="w-full bg-gray-50 rounded-lg p-2 flex items-center justify-center min-h-[60px]">
|
||||||
<div className="bg-gray-50 rounded-lg p-2 flex items-center justify-center min-h-[50px]">
|
|
||||||
{signature?.signatureType !== 'SELECT' && signature?.signatureBlob ? (
|
{signature?.signatureType !== 'SELECT' && signature?.signatureBlob ? (
|
||||||
<img
|
<img
|
||||||
src={`data:${signature?.signatureMimeType};base64,${signature?.signatureBlob}`}
|
src={`data:${signature?.signatureMimeType};base64,${signature?.signatureBlob}`}
|
||||||
className="max-h-[60px] w-full object-contain"
|
className="w-full h-12 object-contain"
|
||||||
alt={`${signature?.firstName ?? ''} ${signature?.lastName ?? ''} signature`}
|
alt={`${signature?.firstName ?? ''} ${signature?.lastName ?? ''} signature`}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -739,19 +745,17 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{/* <span className="text-xs text-gray-500 truncate mt-1 text-center w-full">{signature?.signatureHash ?? ' '}</span> */}
|
||||||
<span className="text-xs text-gray-500 truncate">{signature?.signatureHash ?? ' '}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Initials */}
|
{/* Initials */}
|
||||||
<div className="flex-1 flex flex-col space-y-2 border-l-4 border-green-500 rounded-l-xl pl-4 md:pl-6 py-2 mt-4 md:mt-0">
|
<div className="w-[40%] flex flex-col">
|
||||||
<span className="text-sm font-medium text-gray-600">Initials</span>
|
<span className="text-sm font-medium text-gray-600 mb-1">Initials</span>
|
||||||
|
<div className="bg-gray-50 rounded-lg p-1 flex items-center justify-center min-h-[40px]">
|
||||||
<div className="bg-gray-50 rounded-lg p-2 flex items-center justify-center min-h-[50px]">
|
|
||||||
{signature?.signatureType !== 'SELECT' && signature?.initialsBlob ? (
|
{signature?.signatureType !== 'SELECT' && signature?.initialsBlob ? (
|
||||||
<img
|
<img
|
||||||
src={`data:${signature?.initialsMimeType};base64,${signature?.initialsBlob}`}
|
src={`data:${signature?.initialsMimeType};base64,${signature?.initialsBlob}`}
|
||||||
className="max-h-[60px] w-full object-contain"
|
className="w-full h-10 object-contain"
|
||||||
alt={`${signature?.firstName ?? ''} ${signature?.lastName ?? ''} initials`}
|
alt={`${signature?.firstName ?? ''} ${signature?.lastName ?? ''} initials`}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
|
|
@ -764,8 +768,7 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
||||||
)
|
)
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{/* <span className="text-xs text-gray-500 truncate mt-1 text-center w-full">{signature?.initialsHash ?? ' '}</span> */}
|
||||||
<span className="text-xs text-gray-500 truncate">{signature?.initialsHash ?? ' '}</span>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
@ -775,6 +778,7 @@ const ClientSignCon: React.FC<ClientSignConProps> = ({
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import axios from "axios";
|
||||||
|
|
||||||
const api = axios.create({
|
const api = axios.create({
|
||||||
baseURL: import.meta.env.VITE_BASE_URI,
|
baseURL: import.meta.env.VITE_BASE_URI,
|
||||||
maxRedirects: 5,
|
maxRedirects: 10,
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
|
|
@ -49,6 +49,19 @@ api.interceptors.response.use(
|
||||||
if (window.location.pathname === "/login" || window.location.pathname === "/register") {
|
if (window.location.pathname === "/login" || window.location.pathname === "/register") {
|
||||||
window.location.href = "/";
|
window.location.href = "/";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof response.data === 'string' && response.data.toLowerCase().includes('<!doctype html>')) {
|
||||||
|
// Likely a full HTML page, handle accordinglys
|
||||||
|
window.location.href = response.request.responseURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response && (response.status === 301 || response.status === 302)) {
|
||||||
|
const redirectUrl = response.headers["location"];
|
||||||
|
if (redirectUrl) {
|
||||||
|
window.location.href = redirectUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
},
|
},
|
||||||
async error => {
|
async error => {
|
||||||
|
|
@ -58,12 +71,13 @@ api.interceptors.response.use(
|
||||||
// const res = error.response;
|
// const res = error.response;
|
||||||
|
|
||||||
// 🔹 Handle 301/302 manually
|
// 🔹 Handle 301/302 manually
|
||||||
// if (res && (res.status === 301 || res.status === 302)) {
|
|
||||||
// const redirectUrl = res.headers["location"];
|
if (error && (error.status === 301 || error.status === 302)) {
|
||||||
// if (redirectUrl) {
|
const redirectUrl = error.headers["location"];
|
||||||
// window.location.href = redirectUrl;
|
if (redirectUrl) {
|
||||||
// }
|
window.location.href = redirectUrl;
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Prevent multiple refresh attempts
|
// Prevent multiple refresh attempts
|
||||||
// if (error.response?.status === 401 || error.response?.status === 500) {
|
// if (error.response?.status === 401 || error.response?.status === 500) {
|
||||||
|
|
|
||||||
|
|
@ -2,45 +2,46 @@
|
||||||
import axios, { AxiosInstance } from "axios";
|
import axios, { AxiosInstance } from "axios";
|
||||||
|
|
||||||
const defaultHeaders = {
|
const defaultHeaders = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"ngrok-skip-browser-warning": "69420",
|
"ngrok-skip-browser-warning": "69420",
|
||||||
};
|
};
|
||||||
|
|
||||||
const axiosInstance: AxiosInstance = axios.create({
|
const axiosInstance: AxiosInstance = axios.create({
|
||||||
baseURL: import.meta.env.VITE_BASE_URI,
|
baseURL: import.meta.env.VITE_BASE_URI,
|
||||||
withCredentials: true,
|
withCredentials: true,
|
||||||
headers: defaultHeaders,
|
headers: defaultHeaders,
|
||||||
validateStatus: (status) => status >= 200 && status < 400,
|
validateStatus: (status) => status >= 200 && status < 400,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
axiosInstance.interceptors.response.use(
|
axiosInstance.interceptors.response.use(
|
||||||
(response) => {
|
(response) => {
|
||||||
// ✅ Handle backend "soft redirects"
|
|
||||||
if (response?.data?.redirect) {
|
|
||||||
const redirectUrl = response.data.redirect;
|
|
||||||
|
|
||||||
// Use location.replace to avoid back button returning to invalid page
|
if (typeof response.data === 'string' && response.data.toLowerCase().includes('<!doctype html>')) {
|
||||||
window.location.replace(redirectUrl);
|
// Likely a full HTML page, handle accordingly
|
||||||
// OR window.location.href = redirectUrl; if you want history entry
|
window.location.href = response.request.responseURL;
|
||||||
|
}
|
||||||
|
|
||||||
// Optionally return a rejected promise to stop normal handling
|
if (response && (response.status === 301 || response.status === 302)) {
|
||||||
return Promise.reject({ redirected: true });
|
const redirectUrl = response.headers["location"];
|
||||||
|
if (redirectUrl) {
|
||||||
|
window.location.href = redirectUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise just continue as normal
|
||||||
|
return response;
|
||||||
|
},
|
||||||
|
(error) => {
|
||||||
|
// Optionally handle backend 302 or 3xx here (if returned as error)
|
||||||
|
if (error.response?.status === 302 && error.response?.headers?.location) {
|
||||||
|
window.location.replace(error.response.headers.location);
|
||||||
|
return Promise.reject({ redirected: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pass through all other errors
|
||||||
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise just continue as normal
|
|
||||||
return response;
|
|
||||||
},
|
|
||||||
(error) => {
|
|
||||||
// Optionally handle backend 302 or 3xx here (if returned as error)
|
|
||||||
if (error.response?.status === 302 && error.response?.headers?.location) {
|
|
||||||
window.location.replace(error.response.headers.location);
|
|
||||||
return Promise.reject({ redirected: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pass through all other errors
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
export default axiosInstance;
|
export default axiosInstance;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue