You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chajia/lib/flock/saved-freight-presets.ts

146 lines
3.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/**
* Flock 登录态「常用货件」:按客户维度存浏览器 localStorage供搜索快速回填。
*/
export const FLOCK_SAVED_FREIGHT_MAX = 40;
export type FlockSavedFreightPreset = {
id: string;
/** 列表/搜索显示名 */
name: string;
description: string;
quantity: string;
packagingType: string;
lengthIn: string;
widthIn: string;
heightIn: string;
totalWeightLb: string;
freightClass: string;
stackable: boolean;
turnable: boolean;
updatedAt: string;
};
export type FlockSavedFreightSource = {
description: string;
quantity: string;
packagingType: string;
lengthIn: string;
widthIn: string;
heightIn: string;
totalWeightLb: string;
freightClass: string;
stackable: boolean;
turnable: boolean;
};
export function flockSavedFreightStorageKey(customerId: string): string {
const id = customerId.trim() || "anon";
return `chajia.flock.savedFreight.v1:${id}`;
}
function isPreset(v: unknown): v is FlockSavedFreightPreset {
if (!v || typeof v !== "object") return false;
const o = v as Record<string, unknown>;
return (
typeof o.id === "string" &&
typeof o.name === "string" &&
typeof o.description === "string"
);
}
export function parseFlockSavedFreightList(
raw: string | null,
): FlockSavedFreightPreset[] {
if (!raw) return [];
try {
const data = JSON.parse(raw) as unknown;
if (!Array.isArray(data)) return [];
return data.filter(isPreset).slice(0, FLOCK_SAVED_FREIGHT_MAX);
} catch {
return [];
}
}
export function loadFlockSavedFreight(
customerId: string,
storage: Pick<Storage, "getItem"> = globalThis.localStorage,
): FlockSavedFreightPreset[] {
try {
return parseFlockSavedFreightList(
storage.getItem(flockSavedFreightStorageKey(customerId)),
);
} catch {
return [];
}
}
export function persistFlockSavedFreight(
customerId: string,
list: FlockSavedFreightPreset[],
storage: Pick<Storage, "setItem"> = globalThis.localStorage,
): void {
const trimmed = list.slice(0, FLOCK_SAVED_FREIGHT_MAX);
storage.setItem(
flockSavedFreightStorageKey(customerId),
JSON.stringify(trimmed),
);
}
export function filterFlockSavedFreight(
list: FlockSavedFreightPreset[],
query: string,
): FlockSavedFreightPreset[] {
const q = query.trim().toLowerCase();
if (!q) return list;
return list.filter(
(p) =>
p.name.toLowerCase().includes(q) ||
p.description.toLowerCase().includes(q),
);
}
/** 同名(忽略大小写)覆盖;新条目插到最前 */
export function upsertFlockSavedFreight(
list: FlockSavedFreightPreset[],
preset: FlockSavedFreightPreset,
): FlockSavedFreightPreset[] {
const nameKey = preset.name.trim().toLowerCase();
const without = list.filter(
(p) => p.id !== preset.id && p.name.trim().toLowerCase() !== nameKey,
);
return [preset, ...without].slice(0, FLOCK_SAVED_FREIGHT_MAX);
}
export function removeFlockSavedFreight(
list: FlockSavedFreightPreset[],
id: string,
): FlockSavedFreightPreset[] {
return list.filter((p) => p.id !== id);
}
export function buildFlockSavedFreightPreset(
source: FlockSavedFreightSource,
name: string,
id = `sf-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`,
): FlockSavedFreightPreset | null {
const desc = source.description.trim();
const displayName = name.trim() || desc;
if (!displayName && !desc) return null;
return {
id,
name: displayName || desc,
description: desc || displayName,
quantity: source.quantity,
packagingType: source.packagingType,
lengthIn: source.lengthIn,
widthIn: source.widthIn,
heightIn: source.heightIn,
totalWeightLb: source.totalWeightLb,
freightClass: source.freightClass,
stackable: Boolean(source.stackable),
turnable: Boolean(source.turnable),
updatedAt: new Date().toISOString(),
};
}