122 lines
3.7 KiB
TypeScript
122 lines
3.7 KiB
TypeScript
import { optima } from "$lib";
|
|
import { handleApiError } from "$lib/optima-api/errorHandler";
|
|
import { checkPermissions } from "$lib/permissions";
|
|
import type { PageServerLoad } from "./$types";
|
|
|
|
function withTimeoutFallback<T>(
|
|
promise: Promise<T>,
|
|
timeoutMs: number,
|
|
fallback: T,
|
|
): Promise<T> {
|
|
return new Promise<T>((resolve) => {
|
|
const timer = setTimeout(() => resolve(fallback), timeoutMs);
|
|
promise
|
|
.then((value) => {
|
|
clearTimeout(timer);
|
|
resolve(value);
|
|
})
|
|
.catch(() => {
|
|
clearTimeout(timer);
|
|
resolve(fallback);
|
|
});
|
|
});
|
|
}
|
|
|
|
export const load: PageServerLoad = async ({ locals, url }) => {
|
|
const accessToken = locals.session?.accessToken;
|
|
if (!accessToken) {
|
|
return {
|
|
opportunities: [],
|
|
opportunityTypes: [],
|
|
totalPages: 1,
|
|
currentPage: 1,
|
|
totalRecords: 0,
|
|
search: "",
|
|
includeClosed: false,
|
|
dashSearch: "",
|
|
dashIncludeClosed: false,
|
|
permissions: {},
|
|
tab: "dashboard",
|
|
};
|
|
}
|
|
|
|
const tab = url.searchParams.get("tab") ?? "dashboard";
|
|
const page = Math.max(1, Number(url.searchParams.get("page")) || 1);
|
|
const search = url.searchParams.get("search") || "";
|
|
const includeClosed = url.searchParams.get("includeClosed") !== "false";
|
|
const dashSearch = "";
|
|
const dashIncludeClosed = url.searchParams.get("dashIncludeClosed") === "true";
|
|
const rpp = 30;
|
|
|
|
console.log("[sales load] tab:", tab, "dashIncludeClosed:", dashIncludeClosed, "url:", url.toString());
|
|
|
|
try {
|
|
const [result, meResult, permissions, opportunityTypesResult, metrics] =
|
|
await Promise.all([
|
|
tab !== "dashboard"
|
|
? optima.sales
|
|
.fetchMany(accessToken, page, search, rpp, includeClosed)
|
|
.catch((err) => {
|
|
console.error(
|
|
"Failed to fetch opportunities:",
|
|
err?.response?.data ?? err?.message ?? err,
|
|
);
|
|
return {
|
|
data: [],
|
|
meta: {
|
|
pagination: { totalPages: 1, currentPage: 1, totalRecords: 0 },
|
|
},
|
|
};
|
|
})
|
|
: null,
|
|
tab === "dashboard"
|
|
? optima.sales.fetchMe(accessToken, dashIncludeClosed).catch((err) => {
|
|
console.error(
|
|
"Failed to fetch my opportunities:",
|
|
err?.response?.data ?? err?.message ?? err,
|
|
);
|
|
return { data: [] };
|
|
})
|
|
: null,
|
|
checkPermissions(accessToken, [
|
|
"sales.opportunity.fetch.many",
|
|
"sales.opportunity.create",
|
|
"sales.opportunity.fetch.@me",
|
|
"sales.opportunity.fetch.all",
|
|
]),
|
|
optima.sales
|
|
.fetchOpportunityTypes(accessToken)
|
|
.catch(() => ({ data: [] })),
|
|
withTimeoutFallback(
|
|
optima.sales.fetchMetrics(accessToken).catch(() => null),
|
|
2500,
|
|
null,
|
|
),
|
|
]);
|
|
|
|
const opportunities =
|
|
tab === "dashboard"
|
|
? (meResult?.data?.data ?? meResult?.data?.opportunities ?? meResult?.data ?? [])
|
|
: (result?.data?.data ?? result?.data?.opportunities ?? result?.data ?? []);
|
|
const pagination =
|
|
result?.meta?.pagination ?? result?.data?.meta?.pagination ?? null;
|
|
|
|
return {
|
|
opportunities,
|
|
opportunityTypes: opportunityTypesResult?.data ?? [],
|
|
totalPages: pagination?.totalPages ?? 1,
|
|
currentPage: pagination?.currentPage ?? page,
|
|
totalRecords: pagination?.totalRecords ?? opportunities.length ?? 0,
|
|
search,
|
|
includeClosed,
|
|
dashSearch,
|
|
dashIncludeClosed,
|
|
permissions,
|
|
tab,
|
|
metrics,
|
|
};
|
|
} catch (err) {
|
|
handleApiError(err);
|
|
}
|
|
};
|