Implemented the Plan Detail view to display consumption overages or forfeitures
This commit is contained in:
63
src/features/consumption/plan-detail-controller.js
Normal file
63
src/features/consumption/plan-detail-controller.js
Normal file
@@ -0,0 +1,63 @@
|
||||
function createConsumptionPlanDetailController({ messageTypes, requestConsumerTokenServiceOnce, sendRuntimeMessage,
|
||||
appendBackgroundRequestLog, renderPlanDetailBadges, environment }) {
|
||||
const { document } = environment;
|
||||
const states = new WeakMap();
|
||||
const pending = new Map();
|
||||
|
||||
function createPlanDetailSection(plan) {
|
||||
const section = document.createElement("div");
|
||||
section.className = "opportunities-extension-plan-detail-badges";
|
||||
section.dataset.subPlanNum = String(plan.subPlanNum || "").trim();
|
||||
section.setAttribute("aria-live", "polite");
|
||||
states.set(section, { status: "idle" });
|
||||
return section;
|
||||
}
|
||||
async function request(subPlanNum) {
|
||||
const authorizations = await requestConsumerTokenServiceOnce();
|
||||
const response = await sendRuntimeMessage({ type: messageTypes.requestConsumptionPlanDetail, subPlanNum,
|
||||
authorization: authorizations && authorizations.accountPlans });
|
||||
appendBackgroundRequestLog(response?.debugRequests);
|
||||
if (!response?.ok) throw new Error(response?.error || "Unable to load consumption plan details.");
|
||||
return response.items;
|
||||
}
|
||||
function loadPlanDetailForPanel(panel, plan) {
|
||||
const section = panel?.querySelector(".opportunities-extension-plan-detail-badges");
|
||||
if (!section) return Promise.resolve();
|
||||
const state = states.get(section);
|
||||
if (state?.status === "ready") return Promise.resolve();
|
||||
if (state?.status === "loading") return state.promise;
|
||||
const subPlanNum = String(plan.subPlanNum || "").trim();
|
||||
section.textContent = "";
|
||||
section.setAttribute("aria-busy", "true");
|
||||
const skeleton = document.createElement("span");
|
||||
skeleton.className = "opportunities-extension-account-plans-skeleton-bar opportunities-extension-plan-detail-skeleton";
|
||||
skeleton.setAttribute("role", "status");
|
||||
skeleton.setAttribute("aria-label", "Loading plan projection");
|
||||
section.append(skeleton);
|
||||
const current = { status: "loading", promise: null };
|
||||
states.set(section, current);
|
||||
current.promise = (async () => {
|
||||
try {
|
||||
if (!subPlanNum) throw new Error("Sub plan number is unavailable.");
|
||||
if (!pending.has(subPlanNum)) pending.set(subPlanNum, request(subPlanNum).finally(() => pending.delete(subPlanNum)));
|
||||
const items = await pending.get(subPlanNum);
|
||||
if (!section.isConnected || states.get(section) !== current) return;
|
||||
current.status = "ready";
|
||||
renderPlanDetailBadges(section, items);
|
||||
} catch (error) {
|
||||
if (!section.isConnected || states.get(section) !== current) return;
|
||||
current.status = "error";
|
||||
section.textContent = "";
|
||||
const notice = document.createElement("span");
|
||||
notice.className = "opportunities-extension-plan-detail-error";
|
||||
notice.setAttribute("role", "alert");
|
||||
notice.textContent = error.message || "Unable to load plan details.";
|
||||
section.append(notice);
|
||||
} finally {
|
||||
if (states.get(section) === current) section.setAttribute("aria-busy", "false");
|
||||
}
|
||||
})();
|
||||
return current.promise;
|
||||
}
|
||||
return { createPlanDetailSection, loadPlanDetailForPanel };
|
||||
}
|
||||
Reference in New Issue
Block a user