fix: eliminate API prefix double-encoding across all dashboard components
All checks were successful
build-and-release / build (push) Successful in 1m40s
All checks were successful
build-and-release / build (push) Successful in 1m40s
All dashboard pages and widgets had one of three bugs: - const API = "/api" combined with paths already starting /api → double prefix - const API = '/api/gateway' → nonexistent gateway path prefix - cleanPath stripping /api off paths when API was set to "" Fix: set const API = "" uniformly and remove cleanPath rewrite in all 30+ affected files (CompanyJobsPage, CompanyApplicationsPage, CreditsPage, JobSeekerJobsPage, CustomerRequirementsPage, all widgets, etc.). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
6318b445d7
commit
49b979eb16
32 changed files with 273 additions and 294 deletions
|
|
@ -5,7 +5,7 @@
|
||||||
"name": "frontend-solid",
|
"name": "frontend-solid",
|
||||||
"runtimeExecutable": "npm",
|
"runtimeExecutable": "npm",
|
||||||
"runtimeArgs": ["run", "dev"],
|
"runtimeArgs": ["run", "dev"],
|
||||||
"port": 3000
|
"port": 3001
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
import { For, Show, createSignal, onMount } from "solid-js";
|
import { For, Show, createSignal, onMount } from "solid-js";
|
||||||
import { BTN_GHOST, BTN_ORANGE, CARD, INPUT, LABEL } from "~/components/DashboardShell";
|
import { BTN_GHOST, BTN_ORANGE, CARD, INPUT, LABEL } from "~/components/DashboardShell";
|
||||||
|
|
||||||
const API = "/api";
|
const API = "";
|
||||||
|
|
||||||
interface JobItem {
|
interface JobItem {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -49,8 +49,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import {
|
||||||
LABEL,
|
LABEL,
|
||||||
} from "~/components/DashboardShell";
|
} from "~/components/DashboardShell";
|
||||||
|
|
||||||
const API = "/api";
|
const API = "";
|
||||||
|
|
||||||
interface JobItem {
|
interface JobItem {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { For, Show, createSignal, onMount } from 'solid-js';
|
import { For, Show, createSignal, onMount } from 'solid-js';
|
||||||
import { BTN_GHOST, CARD } from '~/components/DashboardShell';
|
import { BTN_GHOST, CARD } from '~/components/DashboardShell';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
type JobItem = { id: string; title: string };
|
type JobItem = { id: string; title: string };
|
||||||
type ApplicationItem = {
|
type ApplicationItem = {
|
||||||
|
|
@ -18,8 +18,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { BTN_GHOST, BTN_ORANGE, BTN_PRIMARY, CARD, ORANGE, NAVY, PKG_CARD } from
|
||||||
import { PROFESSIONAL_ROLE_SET, ROLE_PREFIXES, type RoleKey } from "./RoleDashboardShared";
|
import { PROFESSIONAL_ROLE_SET, ROLE_PREFIXES, type RoleKey } from "./RoleDashboardShared";
|
||||||
import { openPayuCheckout, submitPayuCheckout } from "~/lib/payu";
|
import { openPayuCheckout, submitPayuCheckout } from "~/lib/payu";
|
||||||
|
|
||||||
const API = "/api";
|
const API = "";
|
||||||
|
|
||||||
type Props = { roleKey: RoleKey; dashboardConfig?: Record<string, any> | null };
|
type Props = { roleKey: RoleKey; dashboardConfig?: Record<string, any> | null };
|
||||||
|
|
||||||
|
|
@ -79,8 +79,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -421,11 +420,20 @@ export default function CreditsPage(props: Props) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const paymentResult = await openPayuCheckout({
|
const paymentResult = await submitPayuCheckout({
|
||||||
|
key: orderData.key,
|
||||||
|
txnid: orderData.txnid || orderData.order_id,
|
||||||
amount: orderData.amount,
|
amount: orderData.amount,
|
||||||
currency: orderData.currency,
|
productinfo: orderData.productinfo,
|
||||||
txnId: orderData.txnid || orderData.order_id,
|
firstname: orderData.firstname,
|
||||||
description: `${pkg.name} - ${pkg.tracecoins_amount} Tracecoins`,
|
email: orderData.email,
|
||||||
|
phone: orderData.phone || "",
|
||||||
|
surl: orderData.surl,
|
||||||
|
furl: orderData.furl,
|
||||||
|
hash: orderData.hash,
|
||||||
|
payu_base_url: orderData.payu_base_url,
|
||||||
|
udf1: orderData.udf1,
|
||||||
|
udf2: orderData.udf2,
|
||||||
});
|
});
|
||||||
|
|
||||||
const verifyRes = await apiFetch("/api/payments/verify", {
|
const verifyRes = await apiFetch("/api/payments/verify", {
|
||||||
|
|
@ -490,247 +498,241 @@ export default function CreditsPage(props: Props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const CheckoutModal = () => {
|
const CheckoutModal = () => {
|
||||||
const state = checkout();
|
|
||||||
const pkg = state.package;
|
|
||||||
const aiPkg = state.aiCreditPackage;
|
|
||||||
if (!pkg && !aiPkg) return null;
|
|
||||||
|
|
||||||
const title = pkg ? `${pkg.tracecoins_amount} Tracecoins` : `${aiPkg!.credits} AI Credits`;
|
|
||||||
const price = pkg ? pkg.price : aiPkg!.price_inr;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Portal>
|
<Show when={checkout().package || checkout().aiCreditPackage}>
|
||||||
<div
|
<Portal>
|
||||||
style={{
|
|
||||||
position: "fixed",
|
|
||||||
inset: "0",
|
|
||||||
background: "rgba(0,0,0,0.5)",
|
|
||||||
display: "flex",
|
|
||||||
"align-items": "center",
|
|
||||||
"justify-content": "center",
|
|
||||||
"z-index": "1000",
|
|
||||||
padding: "20px",
|
|
||||||
}}
|
|
||||||
onClick={(e) => {
|
|
||||||
if (e.target === e.currentTarget && state.step !== "processing") closeCheckout();
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
background: "#fff",
|
position: "fixed",
|
||||||
"border-radius": "16px",
|
inset: "0",
|
||||||
padding: "24px",
|
background: "rgba(0,0,0,0.5)",
|
||||||
"max-width": "420px",
|
display: "flex",
|
||||||
width: "100%",
|
"align-items": "center",
|
||||||
"box-shadow": "0 20px 60px rgba(0,0,0,0.2)",
|
"justify-content": "center",
|
||||||
|
"z-index": "1000",
|
||||||
|
padding: "20px",
|
||||||
|
}}
|
||||||
|
onClick={(e) => {
|
||||||
|
if (e.target === e.currentTarget && checkout().step !== "processing") closeCheckout();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{/* Header */}
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
background: "#fff",
|
||||||
"justify-content": "space-between",
|
"border-radius": "16px",
|
||||||
"align-items": "center",
|
padding: "24px",
|
||||||
"margin-bottom": "20px",
|
"max-width": "420px",
|
||||||
|
width: "100%",
|
||||||
|
"box-shadow": "0 20px 60px rgba(0,0,0,0.2)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<h3
|
{/* Header */}
|
||||||
style={{ margin: "0", "font-size": "18px", "font-weight": "700", color: "#111827" }}
|
|
||||||
>
|
|
||||||
{state.step === "success"
|
|
||||||
? "✓ Payment Successful"
|
|
||||||
: state.step === "error"
|
|
||||||
? "Payment Failed"
|
|
||||||
: "Checkout"}
|
|
||||||
</h3>
|
|
||||||
<Show when={state.step !== "processing"}>
|
|
||||||
<button
|
|
||||||
onClick={closeCheckout}
|
|
||||||
style={{
|
|
||||||
background: "none",
|
|
||||||
border: "none",
|
|
||||||
cursor: "pointer",
|
|
||||||
"font-size": "24px",
|
|
||||||
color: "#9CA3AF",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
×
|
|
||||||
</button>
|
|
||||||
</Show>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Package Summary */}
|
|
||||||
<Show when={state.step !== "success"}>
|
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
background: "#F9FAFB",
|
display: "flex",
|
||||||
"border-radius": "12px",
|
"justify-content": "space-between",
|
||||||
padding: "16px",
|
"align-items": "center",
|
||||||
"margin-bottom": "20px",
|
"margin-bottom": "20px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p style={{ margin: "0 0 8px", "font-size": "13px", color: "#6B7280" }}>Package</p>
|
<h3
|
||||||
<p
|
style={{ margin: "0", "font-size": "18px", "font-weight": "700", color: "#111827" }}
|
||||||
style={{
|
|
||||||
margin: "0 0 4px",
|
|
||||||
"font-size": "16px",
|
|
||||||
"font-weight": "700",
|
|
||||||
color: "#111827",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
{pkg ? pkg.name : aiPkg?.name}
|
{checkout().step === "success"
|
||||||
</p>
|
? "✓ Payment Successful"
|
||||||
<p
|
: checkout().step === "error"
|
||||||
style={{
|
? "Payment Failed"
|
||||||
margin: "0",
|
: "Checkout"}
|
||||||
"font-size": "24px",
|
</h3>
|
||||||
"font-weight": "800",
|
<Show when={checkout().step !== "processing"}>
|
||||||
color: "#FF5E13",
|
<button
|
||||||
}}
|
onClick={closeCheckout}
|
||||||
>
|
|
||||||
{formatCurrency(price)}
|
|
||||||
</p>
|
|
||||||
<p style={{ margin: "8px 0 0", "font-size": "14px", color: "#15803D" }}>
|
|
||||||
+{title}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
{/* Success State */}
|
|
||||||
<Show when={state.step === "success"}>
|
|
||||||
<div style={{ "text-align": "center", padding: "20px 0" }}>
|
|
||||||
<div style={{ "font-size": "48px", "margin-bottom": "16px" }}>🎉</div>
|
|
||||||
<p style={{ margin: "0 0 8px", "font-size": "16px", color: "#111827" }}>
|
|
||||||
Payment successful!
|
|
||||||
</p>
|
|
||||||
<p style={{ margin: "0 0 16px", "font-size": "14px", color: "#6B7280" }}>
|
|
||||||
{title} have been credited to your account.
|
|
||||||
</p>
|
|
||||||
<p style={{ margin: "0", "font-size": "12px", color: "#9CA3AF" }}>
|
|
||||||
Order ID: {state.orderId}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<button
|
|
||||||
onClick={closeCheckout}
|
|
||||||
style={{ ...BTN_PRIMARY, width: "100%", "margin-top": "16px" }}
|
|
||||||
>
|
|
||||||
Done
|
|
||||||
</button>
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
{/* Error State */}
|
|
||||||
<Show when={state.step === "error"}>
|
|
||||||
<div style={{ "text-align": "center", padding: "20px 0" }}>
|
|
||||||
<div style={{ "font-size": "48px", "margin-bottom": "16px" }}>❌</div>
|
|
||||||
<p style={{ margin: "0 0 16px", "font-size": "14px", color: "#B91C1C" }}>
|
|
||||||
{state.error || "Payment failed. Please try again."}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div style={{ display: "flex", gap: "12px" }}>
|
|
||||||
<button
|
|
||||||
onClick={() => setCheckout((c) => ({ ...c, step: "form", error: "" }))}
|
|
||||||
style={{ ...BTN_GHOST, flex: "1" }}
|
|
||||||
>
|
|
||||||
Try Again
|
|
||||||
</button>
|
|
||||||
<button onClick={closeCheckout} style={{ ...BTN_PRIMARY, flex: "1" }}>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
{/* Processing State */}
|
|
||||||
<Show when={state.step === "processing"}>
|
|
||||||
<div style={{ "text-align": "center", padding: "40px 0" }}>
|
|
||||||
<div style={{ "margin-bottom": "16px" }}>
|
|
||||||
<div
|
|
||||||
style={{
|
style={{
|
||||||
width: "48px",
|
background: "none",
|
||||||
height: "48px",
|
border: "none",
|
||||||
border: "4px solid #E5E7EB",
|
cursor: "pointer",
|
||||||
"border-top-color": "#FF5E13",
|
"font-size": "24px",
|
||||||
"border-radius": "50%",
|
color: "#9CA3AF",
|
||||||
animation: "spin 1s linear infinite",
|
|
||||||
margin: "0 auto",
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<p style={{ margin: "0", "font-size": "16px", color: "#111827" }}>
|
|
||||||
Processing Payment...
|
|
||||||
</p>
|
|
||||||
<p style={{ margin: "8px 0 0", "font-size": "13px", color: "#6B7280" }}>
|
|
||||||
Please wait while we process your payment.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</Show>
|
|
||||||
|
|
||||||
{/* Payment Form */}
|
|
||||||
<Show when={state.step === "form"}>
|
|
||||||
<div style={{ display: "flex", "flex-direction": "column", gap: "14px" }}>
|
|
||||||
<Show when={state.error}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
background: "#FEF2F2",
|
|
||||||
border: "1px solid #FECACA",
|
|
||||||
"border-radius": "8px",
|
|
||||||
padding: "12px",
|
|
||||||
color: "#B91C1C",
|
|
||||||
"font-size": "13px",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{state.error}
|
×
|
||||||
</div>
|
</button>
|
||||||
</Show>
|
</Show>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* PayU Notice */}
|
{/* Package Summary */}
|
||||||
|
<Show when={checkout().step !== "success"}>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
background: "#FFF7ED",
|
background: "#F9FAFB",
|
||||||
border: "1px solid #FDBA74",
|
"border-radius": "12px",
|
||||||
"border-radius": "8px",
|
padding: "16px",
|
||||||
padding: "12px",
|
"margin-bottom": "20px",
|
||||||
"font-size": "13px",
|
|
||||||
color: "#9A3412",
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
PayU Secure Checkout will open in a secure page. Cancelled or failed
|
<p style={{ margin: "0 0 8px", "font-size": "13px", color: "#6B7280" }}>Package</p>
|
||||||
payments will not be credited.
|
<p
|
||||||
|
style={{
|
||||||
|
margin: "0 0 4px",
|
||||||
|
"font-size": "16px",
|
||||||
|
"font-weight": "700",
|
||||||
|
color: "#111827",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{checkout().package ? checkout().package!.name : checkout().aiCreditPackage?.name}
|
||||||
|
</p>
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
margin: "0",
|
||||||
|
"font-size": "24px",
|
||||||
|
"font-weight": "800",
|
||||||
|
color: "#FF5E13",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{formatCurrency(checkout().package ? checkout().package!.price : checkout().aiCreditPackage!.price_inr)}
|
||||||
|
</p>
|
||||||
|
<p style={{ margin: "8px 0 0", "font-size": "14px", color: "#15803D" }}>
|
||||||
|
+{checkout().package ? `${checkout().package!.tracecoins_amount} Tracecoins` : `${checkout().aiCreditPackage!.credits} AI Credits`}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
{/* Pay Button */}
|
{/* Success State */}
|
||||||
|
<Show when={checkout().step === "success"}>
|
||||||
|
<div style={{ "text-align": "center", padding: "20px 0" }}>
|
||||||
|
<div style={{ "font-size": "48px", "margin-bottom": "16px" }}>🎉</div>
|
||||||
|
<p style={{ margin: "0 0 8px", "font-size": "16px", color: "#111827" }}>
|
||||||
|
Payment successful!
|
||||||
|
</p>
|
||||||
|
<p style={{ margin: "0 0 16px", "font-size": "14px", color: "#6B7280" }}>
|
||||||
|
{checkout().package ? `${checkout().package!.tracecoins_amount} Tracecoins` : `${checkout().aiCreditPackage!.credits} AI Credits`} have been credited to your account.
|
||||||
|
</p>
|
||||||
|
<p style={{ margin: "0", "font-size": "12px", color: "#9CA3AF" }}>
|
||||||
|
Order ID: {checkout().orderId}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
<button
|
<button
|
||||||
onClick={processPayment}
|
onClick={closeCheckout}
|
||||||
style={{
|
style={{ ...BTN_PRIMARY, width: "100%", "margin-top": "16px" }}
|
||||||
...BTN_PRIMARY,
|
|
||||||
width: "100%",
|
|
||||||
padding: "14px",
|
|
||||||
"font-size": "15px",
|
|
||||||
"font-weight": "700",
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
Pay {formatCurrency(price)}
|
Done
|
||||||
</button>
|
</button>
|
||||||
|
</Show>
|
||||||
|
|
||||||
<p
|
{/* Error State */}
|
||||||
style={{
|
<Show when={checkout().step === "error"}>
|
||||||
margin: "0",
|
<div style={{ "text-align": "center", padding: "20px 0" }}>
|
||||||
"font-size": "11px",
|
<div style={{ "font-size": "48px", "margin-bottom": "16px" }}>❌</div>
|
||||||
color: "#9CA3AF",
|
<p style={{ margin: "0 0 16px", "font-size": "14px", color: "#B91C1C" }}>
|
||||||
"text-align": "center",
|
{checkout().error || "Payment failed. Please try again."}
|
||||||
}}
|
</p>
|
||||||
>
|
</div>
|
||||||
Secure payment powered by PayU
|
<div style={{ display: "flex", gap: "12px" }}>
|
||||||
</p>
|
<button
|
||||||
</div>
|
onClick={() => setCheckout((c) => ({ ...c, step: "form", error: "" }))}
|
||||||
</Show>
|
style={{ ...BTN_GHOST, flex: "1" }}
|
||||||
|
>
|
||||||
|
Try Again
|
||||||
|
</button>
|
||||||
|
<button onClick={closeCheckout} style={{ ...BTN_PRIMARY, flex: "1" }}>
|
||||||
|
Cancel
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
{/* Processing State */}
|
||||||
|
<Show when={checkout().step === "processing"}>
|
||||||
|
<div style={{ "text-align": "center", padding: "40px 0" }}>
|
||||||
|
<div style={{ "margin-bottom": "16px" }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: "48px",
|
||||||
|
height: "48px",
|
||||||
|
border: "4px solid #E5E7EB",
|
||||||
|
"border-top-color": "#FF5E13",
|
||||||
|
"border-radius": "50%",
|
||||||
|
animation: "spin 1s linear infinite",
|
||||||
|
margin: "0 auto",
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<p style={{ margin: "0", "font-size": "16px", color: "#111827" }}>
|
||||||
|
Processing Payment...
|
||||||
|
</p>
|
||||||
|
<p style={{ margin: "8px 0 0", "font-size": "13px", color: "#6B7280" }}>
|
||||||
|
Please wait while we process your payment.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
{/* Payment Form */}
|
||||||
|
<Show when={checkout().step === "form"}>
|
||||||
|
<div style={{ display: "flex", "flex-direction": "column", gap: "14px" }}>
|
||||||
|
<Show when={checkout().error}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: "#FEF2F2",
|
||||||
|
border: "1px solid #FECACA",
|
||||||
|
"border-radius": "8px",
|
||||||
|
padding: "12px",
|
||||||
|
color: "#B91C1C",
|
||||||
|
"font-size": "13px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{checkout().error}
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
|
||||||
|
{/* PayU Notice */}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
background: "#FFF7ED",
|
||||||
|
border: "1px solid #FDBA74",
|
||||||
|
"border-radius": "8px",
|
||||||
|
padding: "12px",
|
||||||
|
"font-size": "13px",
|
||||||
|
color: "#9A3412",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
PayU Secure Checkout will open in a secure page. Cancelled or failed
|
||||||
|
payments will not be credited.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Pay Button */}
|
||||||
|
<button
|
||||||
|
onClick={processPayment}
|
||||||
|
style={{
|
||||||
|
...BTN_PRIMARY,
|
||||||
|
width: "100%",
|
||||||
|
padding: "14px",
|
||||||
|
"font-size": "15px",
|
||||||
|
"font-weight": "700",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Pay {formatCurrency(checkout().package ? checkout().package!.price : checkout().aiCreditPackage!.price_inr)}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<p
|
||||||
|
style={{
|
||||||
|
margin: "0",
|
||||||
|
"font-size": "11px",
|
||||||
|
color: "#9CA3AF",
|
||||||
|
"text-align": "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Secure payment powered by PayU
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<style>{`
|
||||||
<style>{`
|
@keyframes spin {
|
||||||
@keyframes spin {
|
to { transform: rotate(360deg); }
|
||||||
to { transform: rotate(360deg); }
|
}
|
||||||
}
|
`}</style>
|
||||||
`}</style>
|
</Portal>
|
||||||
</Portal>
|
</Show>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { For, Show, createSignal } from 'solid-js';
|
import { For, Show, createSignal } from 'solid-js';
|
||||||
import { BTN_GHOST, BTN_ORANGE, BTN_PRIMARY, CARD, INPUT, LABEL } from '~/components/DashboardShell';
|
import { BTN_GHOST, BTN_ORANGE, BTN_PRIMARY, CARD, INPUT, LABEL } from '~/components/DashboardShell';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
const NAVY = '#0D0D2A';
|
const NAVY = '#0D0D2A';
|
||||||
const ORANGE = '#FF5E13';
|
const ORANGE = '#FF5E13';
|
||||||
|
|
||||||
|
|
@ -10,8 +10,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
import { For, Show, createMemo, createSignal, onMount } from "solid-js";
|
import { For, Show, createMemo, createSignal, onMount } from "solid-js";
|
||||||
import { BTN_GHOST, BTN_PRIMARY, CARD, INPUT, LABEL } from "~/components/DashboardShell";
|
import { BTN_GHOST, BTN_PRIMARY, CARD, INPUT, LABEL } from "~/components/DashboardShell";
|
||||||
|
|
||||||
const API = "/api";
|
const API = "";
|
||||||
|
|
||||||
type RequirementItem = {
|
type RequirementItem = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -30,8 +30,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
import { For, Show, createSignal, onMount } from 'solid-js';
|
import { For, Show, createSignal, onMount } from 'solid-js';
|
||||||
import { BTN_GHOST, BTN_ORANGE, CARD, INPUT, LABEL } from '~/components/DashboardShell';
|
import { BTN_GHOST, BTN_ORANGE, CARD, INPUT, LABEL } from '~/components/DashboardShell';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
|
||||||
|
|
||||||
type RequirementItem = {
|
type RequirementItem = {
|
||||||
id: string;
|
id: string;
|
||||||
title: string;
|
title: string;
|
||||||
|
|
@ -28,8 +26,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(path, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
@ -84,7 +81,7 @@ export default function CustomerResponsesPage(props: Props) {
|
||||||
setLoadingRows(true);
|
setLoadingRows(true);
|
||||||
setErr('');
|
setErr('');
|
||||||
try {
|
try {
|
||||||
const res = await apiFetch(`/api/leads/customer/${requirementId}`);
|
const res = await apiFetch(`/api/customers/requests?lead_id=${requirementId}&page=1&limit=50`);
|
||||||
const payload = await res.json().catch(() => ({}));
|
const payload = await res.json().catch(() => ({}));
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
setRows([]);
|
setRows([]);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { Camera, Scissors, GraduationCap, Code2, Clapperboard, PenTool, Megaphon
|
||||||
const NAVY = "#0D0D2A";
|
const NAVY = "#0D0D2A";
|
||||||
const ORANGE = "#FF5E13";
|
const ORANGE = "#FF5E13";
|
||||||
|
|
||||||
const API = "/api";
|
const API = "";
|
||||||
|
|
||||||
const MAIN_ROLES = [
|
const MAIN_ROLES = [
|
||||||
{ key: "COMPANY", name: "Company", Icon: Users, subtitle: "Hire talent, post jobs, and manage applications in one path." },
|
{ key: "COMPANY", name: "Company", Icon: Users, subtitle: "Hire talent, post jobs, and manage applications in one path." },
|
||||||
|
|
@ -40,8 +40,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { HelpCircle } from "lucide-solid";
|
||||||
import { BTN_GHOST, CARD, INPUT } from "~/components/DashboardShell";
|
import { BTN_GHOST, CARD, INPUT } from "~/components/DashboardShell";
|
||||||
import { type RoleKey } from "./RoleDashboardShared";
|
import { type RoleKey } from "./RoleDashboardShared";
|
||||||
|
|
||||||
const API = "/api";
|
const API = "";
|
||||||
const NAVY = "#0D0D2A";
|
const NAVY = "#0D0D2A";
|
||||||
const ORANGE = "#FF5E13";
|
const ORANGE = "#FF5E13";
|
||||||
|
|
||||||
|
|
@ -24,8 +24,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { For, Show, createSignal, onMount } from 'solid-js';
|
import { For, Show, createSignal, onMount } from 'solid-js';
|
||||||
import { BTN_GHOST, BTN_PRIMARY, CARD } from '~/components/DashboardShell';
|
import { BTN_GHOST, BTN_PRIMARY, CARD } from '~/components/DashboardShell';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
type ApplicationItem = {
|
type ApplicationItem = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -17,8 +17,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { Sparkles, Loader } from "lucide-solid";
|
||||||
import { BTN_GHOST, BTN_PRIMARY, CARD, INPUT } from "~/components/DashboardShell";
|
import { BTN_GHOST, BTN_PRIMARY, CARD, INPUT } from "~/components/DashboardShell";
|
||||||
import { readJobSeekerProfile, updateJobSeekerCustomData } from "~/lib/job-seeker-custom-data";
|
import { readJobSeekerProfile, updateJobSeekerCustomData } from "~/lib/job-seeker-custom-data";
|
||||||
|
|
||||||
const API = "/api";
|
const API = "";
|
||||||
|
|
||||||
type JobItem = {
|
type JobItem = {
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { createSignal } from 'solid-js';
|
||||||
import { LogOut } from 'lucide-solid';
|
import { LogOut } from 'lucide-solid';
|
||||||
import { BTN_GHOST, BTN_ORANGE, CARD } from '~/components/DashboardShell';
|
import { BTN_GHOST, BTN_ORANGE, CARD } from '~/components/DashboardShell';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
const NAVY = '#0D0D2A';
|
const NAVY = '#0D0D2A';
|
||||||
const ORANGE = '#FF5E13';
|
const ORANGE = '#FF5E13';
|
||||||
|
|
||||||
|
|
@ -11,8 +11,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import {
|
||||||
|
|
||||||
// Inline apiFetch matching ProfilePage pattern
|
// Inline apiFetch matching ProfilePage pattern
|
||||||
async function apiFetch(path: string, opts?: RequestInit) {
|
async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
const token = typeof window !== 'undefined'
|
const token = typeof window !== 'undefined'
|
||||||
? (sessionStorage.getItem('nxtgauge_access_token') || '')
|
? (sessionStorage.getItem('nxtgauge_access_token') || '')
|
||||||
: '';
|
: '';
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { For, Show, createSignal, onMount } from 'solid-js';
|
||||||
import { Bell } from 'lucide-solid';
|
import { Bell } from 'lucide-solid';
|
||||||
import { BTN_GHOST, BTN_ORANGE, CARD } from '~/components/DashboardShell';
|
import { BTN_GHOST, BTN_ORANGE, CARD } from '~/components/DashboardShell';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
const NAVY = '#0D0D2A';
|
const NAVY = '#0D0D2A';
|
||||||
const ORANGE = '#FF5E13';
|
const ORANGE = '#FF5E13';
|
||||||
|
|
||||||
|
|
@ -11,8 +11,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import { Coins, Image, BriefcaseBusiness, UserCircle2, CheckCircle2 } from 'luci
|
||||||
import { CARD, BTN_GHOST, BTN_PRIMARY, INPUT, LABEL, NAVY } from '~/components/DashboardShell';
|
import { CARD, BTN_GHOST, BTN_PRIMARY, INPUT, LABEL, NAVY } from '~/components/DashboardShell';
|
||||||
import { readJobSeekerProfile, updateJobSeekerCustomData } from '~/lib/job-seeker-custom-data';
|
import { readJobSeekerProfile, updateJobSeekerCustomData } from '~/lib/job-seeker-custom-data';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
const BTN_NAVY = {
|
const BTN_NAVY = {
|
||||||
height: '36px',
|
height: '36px',
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ import { For, Show, createMemo, createSignal, onMount } from "solid-js";
|
||||||
import { BTN_GHOST, BTN_PRIMARY, CARD, INPUT } from "~/components/DashboardShell";
|
import { BTN_GHOST, BTN_PRIMARY, CARD, INPUT } from "~/components/DashboardShell";
|
||||||
import { ROLE_PREFIXES, type RoleKey } from "./RoleDashboardShared";
|
import { ROLE_PREFIXES, type RoleKey } from "./RoleDashboardShared";
|
||||||
|
|
||||||
const API = "/api";
|
const API = "";
|
||||||
|
|
||||||
type Props = { roleKey: RoleKey };
|
type Props = { roleKey: RoleKey };
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { For, Show, createSignal, onMount } from 'solid-js';
|
||||||
import { BTN_GHOST, CARD } from '~/components/DashboardShell';
|
import { BTN_GHOST, CARD } from '~/components/DashboardShell';
|
||||||
import { ROLE_PREFIXES, type RoleKey } from './RoleDashboardShared';
|
import { ROLE_PREFIXES, type RoleKey } from './RoleDashboardShared';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
type Props = { roleKey: RoleKey };
|
type Props = { roleKey: RoleKey };
|
||||||
|
|
||||||
|
|
@ -20,8 +20,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -638,7 +638,7 @@ export default function ProfilePage(props: Props) {
|
||||||
return Array.from(new Set(missing));
|
return Array.from(new Set(missing));
|
||||||
}
|
}
|
||||||
const data = await res.json().catch(() => []);
|
const data = await res.json().catch(() => []);
|
||||||
const items = Array.isArray(data) ? data : data?.items ?? [];
|
const items = Array.isArray(data) ? data : data?.items ?? data?.data ?? [];
|
||||||
if (!Array.isArray(items) || items.length === 0) missing.push("Showcase items");
|
if (!Array.isArray(items) || items.length === 0) missing.push("Showcase items");
|
||||||
} catch {
|
} catch {
|
||||||
missing.push("Showcase items");
|
missing.push("Showcase items");
|
||||||
|
|
@ -863,7 +863,7 @@ export default function ProfilePage(props: Props) {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body: { roleKey: props.roleKey, profile_data: { ...form(), ...docUrls() } },
|
body: { roleKey: props.roleKey, profile_data: { ...form(), ...docUrls() } },
|
||||||
});
|
});
|
||||||
if (status === 200) {
|
if (status === 200 || status === 201) {
|
||||||
setVerificationStatus("PENDING");
|
setVerificationStatus("PENDING");
|
||||||
props.onVerificationStatusChange?.("PENDING");
|
props.onVerificationStatusChange?.("PENDING");
|
||||||
setSubmitMsg("Submitted! We will review your profile and notify you.");
|
setSubmitMsg("Submitted! We will review your profile and notify you.");
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { For, Show, createSignal, onMount } from 'solid-js';
|
||||||
import { Settings as SettingsIcon } from 'lucide-solid';
|
import { Settings as SettingsIcon } from 'lucide-solid';
|
||||||
import { BTN_GHOST, BTN_ORANGE, BTN_PRIMARY, CARD, INPUT, LABEL } from '~/components/DashboardShell';
|
import { BTN_GHOST, BTN_ORANGE, BTN_PRIMARY, CARD, INPUT, LABEL } from '~/components/DashboardShell';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
const NAVY = '#0D0D2A';
|
const NAVY = '#0D0D2A';
|
||||||
const ORANGE = '#FF5E13';
|
const ORANGE = '#FF5E13';
|
||||||
|
|
||||||
|
|
@ -11,8 +11,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { For, Show, createSignal, onMount } from 'solid-js';
|
||||||
import { RefreshCw } from 'lucide-solid';
|
import { RefreshCw } from 'lucide-solid';
|
||||||
import { BTN_GHOST, BTN_PRIMARY, CARD } from '~/components/DashboardShell';
|
import { BTN_GHOST, BTN_PRIMARY, CARD } from '~/components/DashboardShell';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
const NAVY = '#0D0D2A';
|
const NAVY = '#0D0D2A';
|
||||||
const ORANGE = '#FF5E13';
|
const ORANGE = '#FF5E13';
|
||||||
|
|
||||||
|
|
@ -18,8 +18,7 @@ async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
typeof window !== "undefined"
|
typeof window !== "undefined"
|
||||||
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
? window.sessionStorage.getItem("nxtgauge_access_token") || ""
|
||||||
: "";
|
: "";
|
||||||
const cleanPath = path.startsWith("/api/") ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: "include",
|
credentials: "include",
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,14 @@ import DashboardWidget from './DashboardWidget';
|
||||||
import type { RoleKey } from '../RoleDashboardShared';
|
import type { RoleKey } from '../RoleDashboardShared';
|
||||||
import { ROLE_PREFIXES } from '../RoleDashboardShared';
|
import { ROLE_PREFIXES } from '../RoleDashboardShared';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
async function apiFetch(path: string, opts?: RequestInit) {
|
async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
const token =
|
const token =
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,14 @@ import { FileText } from 'lucide-solid';
|
||||||
import DashboardWidget from './DashboardWidget';
|
import DashboardWidget from './DashboardWidget';
|
||||||
import type { RoleKey } from '../RoleDashboardShared';
|
import type { RoleKey } from '../RoleDashboardShared';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
async function apiFetch(path: string, opts?: RequestInit) {
|
async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
const token =
|
const token =
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,14 @@ import { Briefcase } from 'lucide-solid';
|
||||||
import DashboardWidget from './DashboardWidget';
|
import DashboardWidget from './DashboardWidget';
|
||||||
import type { RoleKey } from '../RoleDashboardShared';
|
import type { RoleKey } from '../RoleDashboardShared';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
async function apiFetch(path: string, opts?: RequestInit) {
|
async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
const token =
|
const token =
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,14 @@ import DashboardWidget from './DashboardWidget';
|
||||||
import type { RoleKey } from '../RoleDashboardShared';
|
import type { RoleKey } from '../RoleDashboardShared';
|
||||||
import { PROFESSIONAL_ROLE_SET, ROLE_PREFIXES } from '../RoleDashboardShared';
|
import { PROFESSIONAL_ROLE_SET, ROLE_PREFIXES } from '../RoleDashboardShared';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
async function apiFetch(path: string, opts?: RequestInit) {
|
async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
const token =
|
const token =
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -5,15 +5,14 @@ import type { RoleKey } from '../RoleDashboardShared';
|
||||||
import { PROFESSIONAL_ROLE_SET, ROLE_PREFIXES } from '../RoleDashboardShared';
|
import { PROFESSIONAL_ROLE_SET, ROLE_PREFIXES } from '../RoleDashboardShared';
|
||||||
import { fetchProfile } from '~/lib/api';
|
import { fetchProfile } from '~/lib/api';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
async function apiFetch(path: string, opts?: RequestInit) {
|
async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
const token =
|
const token =
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,14 @@ import { ClipboardList } from 'lucide-solid';
|
||||||
import DashboardWidget from './DashboardWidget';
|
import DashboardWidget from './DashboardWidget';
|
||||||
import type { RoleKey } from '../RoleDashboardShared';
|
import type { RoleKey } from '../RoleDashboardShared';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
async function apiFetch(path: string, opts?: RequestInit) {
|
async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
const token =
|
const token =
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,14 @@ import { Star } from 'lucide-solid';
|
||||||
import DashboardWidget from './DashboardWidget';
|
import DashboardWidget from './DashboardWidget';
|
||||||
import type { RoleKey } from '../RoleDashboardShared';
|
import type { RoleKey } from '../RoleDashboardShared';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
async function apiFetch(path: string, opts?: RequestInit) {
|
async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
const token =
|
const token =
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,14 @@ import { ShieldCheck } from 'lucide-solid';
|
||||||
import DashboardWidget from './DashboardWidget';
|
import DashboardWidget from './DashboardWidget';
|
||||||
import type { RoleKey } from '../RoleDashboardShared';
|
import type { RoleKey } from '../RoleDashboardShared';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
async function apiFetch(path: string, opts?: RequestInit) {
|
async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
const token =
|
const token =
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,14 @@ import DashboardWidget from './DashboardWidget';
|
||||||
import type { RoleKey } from '../RoleDashboardShared';
|
import type { RoleKey } from '../RoleDashboardShared';
|
||||||
import { ROLE_PREFIXES } from '../RoleDashboardShared';
|
import { ROLE_PREFIXES } from '../RoleDashboardShared';
|
||||||
|
|
||||||
const API = '/api/gateway';
|
const API = '';
|
||||||
|
|
||||||
async function apiFetch(path: string, opts?: RequestInit) {
|
async function apiFetch(path: string, opts?: RequestInit) {
|
||||||
const token =
|
const token =
|
||||||
typeof window !== 'undefined'
|
typeof window !== 'undefined'
|
||||||
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
? window.sessionStorage.getItem('nxtgauge_access_token') || ''
|
||||||
: '';
|
: '';
|
||||||
const cleanPath = path.startsWith('/api/') ? path.slice(4) : path;
|
return fetch(`${API}${path}`, {
|
||||||
return fetch(`${API}${cleanPath}`, {
|
|
||||||
...opts,
|
...opts,
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
headers: {
|
headers: {
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,7 @@ const ROLE_BASED_SIDEBAR: Record<RoleKey, string[]> = {
|
||||||
"Jobs",
|
"Jobs",
|
||||||
"Applications",
|
"Applications",
|
||||||
"Shortlisted Candidates",
|
"Shortlisted Candidates",
|
||||||
|
"Credits",
|
||||||
"Explore Nxtgauge",
|
"Explore Nxtgauge",
|
||||||
"Verification",
|
"Verification",
|
||||||
"Help Center",
|
"Help Center",
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,7 @@ export default function BuyTracecoinsPage() {
|
||||||
|
|
||||||
const [packages] = createResource(async () => {
|
const [packages] = createResource(async () => {
|
||||||
const roleKey = resolveRoleKey();
|
const roleKey = resolveRoleKey();
|
||||||
const res = await api.get(`/pricing/packages?role=${encodeURIComponent(roleKey)}&roleKey=${encodeURIComponent(roleKey)}`);
|
const res = await api.get(`/packages?role=${encodeURIComponent(roleKey)}&roleKey=${encodeURIComponent(roleKey)}`);
|
||||||
return res.data?.packages || [];
|
return res.data?.packages || [];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue