feat(status): add estimate customer actions
This commit is contained in:
parent
efdc4d5be1
commit
6f6891134e
9 changed files with 699 additions and 3 deletions
|
|
@ -6,6 +6,29 @@ export type OlympusRepairStatusHistoryItem = {
|
|||
created_at: string;
|
||||
};
|
||||
|
||||
export type OlympusEstimateItem = {
|
||||
item_type: string;
|
||||
title: string;
|
||||
description: string | null;
|
||||
quantity: string | number;
|
||||
unit: string;
|
||||
unit_price_cents: number;
|
||||
total_cents: number;
|
||||
};
|
||||
|
||||
export type OlympusEstimate = {
|
||||
estimate_number: string;
|
||||
status: "draft" | "sent" | "approved" | "declined" | "expired" | "cancelled" | string;
|
||||
title: string;
|
||||
customer_message: string | null;
|
||||
subtotal_cents: number;
|
||||
tax_cents: number;
|
||||
total_cents: number;
|
||||
currency: string;
|
||||
valid_until: string | null;
|
||||
items: OlympusEstimateItem[];
|
||||
};
|
||||
|
||||
export type OlympusRepairStatus = {
|
||||
repair_number: string;
|
||||
public_status_label: string;
|
||||
|
|
@ -13,12 +36,19 @@ export type OlympusRepairStatus = {
|
|||
device_model: string;
|
||||
status_history_public: OlympusRepairStatusHistoryItem[];
|
||||
updated_at: string;
|
||||
estimate?: OlympusEstimate | null;
|
||||
};
|
||||
|
||||
export type RepairStatusResult =
|
||||
| { ok: true; status: OlympusRepairStatus }
|
||||
| { ok: false; reason: "invalid" | "unavailable" };
|
||||
|
||||
export type EstimateAction = "approve" | "decline" | "question";
|
||||
|
||||
export type EstimateActionResult =
|
||||
| { ok: true }
|
||||
| { ok: false; reason: "invalid" | "unavailable" | "failed" };
|
||||
|
||||
function getStatusApiBaseUrl() {
|
||||
return process.env.OLYMPUS_PUBLIC_STATUS_API_URL?.replace(/\/$/, "") ?? "";
|
||||
}
|
||||
|
|
@ -68,3 +98,48 @@ export async function fetchOlympusRepairStatus(token: string): Promise<RepairSta
|
|||
return { ok: false, reason: "unavailable" };
|
||||
}
|
||||
}
|
||||
|
||||
export async function submitOlympusEstimateAction(
|
||||
token: string,
|
||||
action: EstimateAction,
|
||||
message?: string,
|
||||
): Promise<EstimateActionResult> {
|
||||
const baseUrl = getStatusApiBaseUrl();
|
||||
|
||||
if (!baseUrl || !token.trim()) {
|
||||
return { ok: false, reason: "unavailable" };
|
||||
}
|
||||
|
||||
const headers: HeadersInit = {
|
||||
Accept: "application/json",
|
||||
"Content-Type": "application/json",
|
||||
};
|
||||
const apiToken = getStatusApiToken();
|
||||
|
||||
if (apiToken) {
|
||||
headers.Authorization = `Bearer ${apiToken}`;
|
||||
}
|
||||
|
||||
let response: Response;
|
||||
|
||||
try {
|
||||
response = await fetch(`${baseUrl}/public/repairs/status/${encodeURIComponent(token)}/estimate/${action}`, {
|
||||
method: "POST",
|
||||
headers,
|
||||
body: JSON.stringify({ message: message?.trim() || null }),
|
||||
cache: "no-store",
|
||||
});
|
||||
} catch {
|
||||
return { ok: false, reason: "unavailable" };
|
||||
}
|
||||
|
||||
if (response.status === 401 || response.status === 403 || response.status === 404) {
|
||||
return { ok: false, reason: "invalid" };
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
return { ok: false, reason: "failed" };
|
||||
}
|
||||
|
||||
return { ok: true };
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue