Initial commit of Descrybe v2 without local scratch artifacts.
Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
import type { ShopifyConfig, WooCommerceConfig } from "$lib/types";
|
||||
|
||||
export type StoreWizardChannel = "shopify" | "woocommerce";
|
||||
|
||||
export type StoreWizardStepId = "connect" | "test" | "sync" | "done";
|
||||
|
||||
export const STORE_WIZARD_STEPS: readonly StoreWizardStepId[] = [
|
||||
"connect",
|
||||
"test",
|
||||
"sync",
|
||||
"done"
|
||||
] as const;
|
||||
|
||||
export type StoreWizardEvidence = {
|
||||
hasCredentials: boolean;
|
||||
testOk: boolean;
|
||||
hasSynced: boolean;
|
||||
};
|
||||
|
||||
const CHANNEL_KEY = "descrybe.storeWizard.channel";
|
||||
|
||||
export function isStoreWizardChannel(value: string | null | undefined): value is StoreWizardChannel {
|
||||
return value === "shopify" || value === "woocommerce";
|
||||
}
|
||||
|
||||
export function readStoredWizardChannel(): StoreWizardChannel | null {
|
||||
if (typeof localStorage === "undefined") return null;
|
||||
try {
|
||||
const raw = localStorage.getItem(CHANNEL_KEY);
|
||||
return isStoreWizardChannel(raw) ? raw : null;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function writeStoredWizardChannel(channel: StoreWizardChannel | null): void {
|
||||
if (typeof localStorage === "undefined") return;
|
||||
try {
|
||||
if (!channel) localStorage.removeItem(CHANNEL_KEY);
|
||||
else localStorage.setItem(CHANNEL_KEY, channel);
|
||||
} catch {
|
||||
/* ignore quota / private mode */
|
||||
}
|
||||
}
|
||||
|
||||
export function connectorHref(
|
||||
channel: StoreWizardChannel,
|
||||
step: Exclude<StoreWizardStepId, "done">
|
||||
): string {
|
||||
const base = channel === "shopify" ? "/stores/shopify" : "/woocommerce";
|
||||
const params = new URLSearchParams({ from: "wizard" });
|
||||
if (step === "test") params.set("focus", "test");
|
||||
if (step === "sync") params.set("focus", "sync");
|
||||
return `${base}?${params.toString()}`;
|
||||
}
|
||||
|
||||
export function evidenceFromConfig(
|
||||
config: ShopifyConfig | WooCommerceConfig | null | undefined
|
||||
): StoreWizardEvidence {
|
||||
if (!config) {
|
||||
return { hasCredentials: false, testOk: false, hasSynced: false };
|
||||
}
|
||||
const testStatus = String(config.last_test_status ?? "").toLowerCase();
|
||||
const productMaps = Number(config.product_map_count ?? 0);
|
||||
return {
|
||||
hasCredentials: Boolean(config.has_credentials),
|
||||
testOk: testStatus === "ok" || testStatus === "success",
|
||||
hasSynced:
|
||||
Boolean(config.last_synced_at) ||
|
||||
Boolean(config.pending_sync) ||
|
||||
productMaps > 0
|
||||
};
|
||||
}
|
||||
|
||||
/** Contiguous completed-step count (stop at first incomplete). Order matches STORE_WIZARD_STEPS. */
|
||||
export function wizardCompletedCount(evidence: StoreWizardEvidence): number {
|
||||
const flags = [evidence.hasCredentials, evidence.testOk, evidence.hasSynced, true];
|
||||
let count = 0;
|
||||
for (let i = 0; i < STORE_WIZARD_STEPS.length; i++) {
|
||||
const step = STORE_WIZARD_STEPS[i];
|
||||
if (step === "done") {
|
||||
if (count >= 3) count = 4;
|
||||
break;
|
||||
}
|
||||
if (!flags[i]) break;
|
||||
count += 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
export function wizardCurrentStep(evidence: StoreWizardEvidence): StoreWizardStepId {
|
||||
const done = wizardCompletedCount(evidence);
|
||||
if (done >= STORE_WIZARD_STEPS.length) return "done";
|
||||
return STORE_WIZARD_STEPS[done] ?? "connect";
|
||||
}
|
||||
|
||||
export function parseWizardFocus(raw: string | null | undefined): "test" | "sync" | null {
|
||||
if (raw === "test" || raw === "sync") return raw;
|
||||
return null;
|
||||
}
|
||||
|
||||
export function isWizardReturn(searchParams: URLSearchParams): boolean {
|
||||
return searchParams.get("from") === "wizard" || parseWizardFocus(searchParams.get("focus")) != null;
|
||||
}
|
||||
Reference in New Issue
Block a user