feat(logistics): SMS problem as tag, red highlight for unagreed 2+ days

This commit is contained in:
root 2026-08-06 15:28:51 +00:00
parent d5849f0ab2
commit 4d47261321
2 changed files with 38 additions and 12 deletions

View File

@ -1,8 +1,8 @@
const isLocalhost = self.location.hostname === "localhost" || self.location.hostname === "127.0.0.1";
if (!isLocalhost) {
const STATIC_CACHE = "construction-delivery-static-v100";
const RUNTIME_CACHE = "construction-delivery-runtime-v100";
const STATIC_CACHE = "construction-delivery-static-v101";
const RUNTIME_CACHE = "construction-delivery-runtime-v101";
const APP_SHELL_URLS = ["/", "/index.html", "/manifest.webmanifest", "/icons/icon-192.png", "/icons/icon-512.png"];
self.addEventListener("install", (event) => {

View File

@ -150,36 +150,62 @@ const getDatabaseAge = (group) => {
const created = new Date(group.createdAt).getTime();
if (!Number.isFinite(created)) return { days: null, rowClass: "", textClass: "text-[var(--color-text-muted)]" };
const days = Math.max(0, Math.floor((Date.now() - created) / 86400000));
if (days >= 14) return { days, rowClass: "bg-[rgba(239,68,68,0.14)]", textClass: "font-bold text-[var(--color-danger)]" };
if (days >= 7) return { days, rowClass: "bg-[rgba(239,68,68,0.09)]", textClass: "font-semibold text-[var(--color-danger)]" };
if (days >= 3) return { days, rowClass: "bg-[rgba(245,158,11,0.08)]", textClass: "font-semibold text-[var(--color-warning)]" };
return { days, rowClass: "", textClass: "text-[var(--color-text-muted)]" };
};
// Not agreed = still waiting for customer confirmation / no delivery settled.
// These statuses mean the order has not been agreed yet.
const NOT_AGREED_STATUSES = new Set([
"delivery:pending_confirmation",
"delivery:manual_confirmation_required",
"status:manual_required",
"status:not_started",
"status:link_ready",
"status:pending_confirmation",
"status:unknown",
]);
const isNotAgreed = (group) => NOT_AGREED_STATUSES.has(getOrderGroupDisplayStatusValue(group));
// Red highlight: not agreed and 2+ days since the order was added to the system.
const getNotAgreedHighlight = (group) => {
if (!isNotAgreed(group)) return "";
const created = group.createdAt ? new Date(group.createdAt).getTime() : 0;
if (!Number.isFinite(created)) return "";
const days = Math.max(0, Math.floor((Date.now() - created) / 86400000));
return days >= 2 ? "bg-[rgba(239,68,68,0.12)]" : "";
};
const SMS_TAG = {
not_sent: { label: "SMS не отправлено", cls: "bg-[rgba(239,68,68,0.14)] text-[var(--color-danger)]" },
not_delivered: { label: "SMS не доставлено", cls: "bg-[rgba(245,158,11,0.14)] text-[var(--color-warning)]" },
};
const renderRow = (g, onSelectSet) => {
const statusTone = getOrderGroupStatusTone(g);
const stale = isStale(g);
const databaseAge = getDatabaseAge(g);
const smsTone = getSmsProblemTone(g);
const smsRowClass = smsTone === "not_sent"
? "bg-[rgba(239,68,68,0.08)]"
: smsTone === "not_delivered"
? "bg-[rgba(245,158,11,0.08)]"
: "";
const smsTag = smsTone !== "ok" ? SMS_TAG[smsTone] : null;
const notAgreedHighlight = getNotAgreedHighlight(g);
return (
<button
type="button"
key={g.id}
onClick={() => onSelectSet(g.id)}
className={`grid ${COLS} ${MIN_W} w-full border-t border-[var(--color-border)] text-left transition hover:bg-[var(--color-accent-soft)] ${
databaseAge.rowClass || (stale ? "bg-[rgba(245,158,11,0.06)]" : "") || smsRowClass
notAgreedHighlight || (stale ? "bg-[rgba(245,158,11,0.06)]" : "")
}`}
>
<div className="min-w-0 px-3 py-2.5">
<div className="flex items-center gap-1.5">
<div className="flex items-center gap-1.5 flex-wrap">
<span className="text-sm font-medium text-[var(--color-text)] truncate">
{g.customerName || g.groupKey || "—"}
</span>
{smsTag && (
<span className={`inline-flex items-center whitespace-nowrap rounded-full px-2 py-0.5 text-[10px] font-semibold ${smsTag.cls}`} title={smsTag.label}>
{smsTag.label}
</span>
)}
{stale && (
<span title="Обновлён >24ч назад" className="inline-block h-2 w-2 flex-shrink-0 rounded-full bg-[var(--color-warning)]"></span>
)}