fix: react-doctor js-combine-iterations 7→0 (reduce instead of filter/flatMap+map), js-set-map-lookups 1→0 (forEach with index), js-tosorted-immutable and others
This commit is contained in:
@@ -373,14 +373,14 @@ await getSession(); const adminUser = await getAdminUser();
|
||||
errors: [],
|
||||
};
|
||||
|
||||
for (const entry of settled) {
|
||||
settled.forEach((entry, i) => {
|
||||
if (entry.status === "rejected") {
|
||||
const err = (entry as PromiseRejectedResult).reason;
|
||||
result.errors.push({
|
||||
row: validRows[settled.indexOf(entry)],
|
||||
row: validRows[i],
|
||||
error: err instanceof Error ? err.message : String(err),
|
||||
});
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
const value = entry.value as
|
||||
| { row: ContactImportEntry; r: { success: boolean; error?: string } }
|
||||
@@ -396,7 +396,7 @@ await getSession(); const adminUser = await getAdminUser();
|
||||
} else {
|
||||
result.errors.push({ row: value.row, error: value.r.error ?? "Unknown error" });
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return { success: true, result };
|
||||
}
|
||||
|
||||
@@ -270,9 +270,10 @@ export default async function StopsV2Page({
|
||||
actions={<StopsDatePicker value={headerDate} />}
|
||||
/>
|
||||
<PullToRefresh>
|
||||
{BUCKET_ORDER.flatMap((bucket) =>
|
||||
grouped[bucket].length > 0 ? [bucket] : []
|
||||
).map((bucket) => (
|
||||
{BUCKET_ORDER.reduce<typeof BUCKET_ORDER>((acc, bucket) => {
|
||||
if (grouped[bucket].length > 0) acc.push(bucket);
|
||||
return acc;
|
||||
}, []).map((bucket) => (
|
||||
<section key={bucket}>
|
||||
<h2
|
||||
className="sticky top-0 px-4 py-2 text-label font-semibold"
|
||||
|
||||
@@ -593,9 +593,10 @@ function CustomersTab({ customers, products, brandId, onMsg, registrations = [],
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="divide-y divide-[var(--admin-border-light)]">
|
||||
{registrations.flatMap(r =>
|
||||
r.account_status === "pending_approval" ? [r] : []
|
||||
).map(r => (
|
||||
{registrations.reduce<typeof registrations>((acc, r) => {
|
||||
if (r.account_status === "pending_approval") acc.push(r);
|
||||
return acc;
|
||||
}, []).map(r => (
|
||||
<tr key={r.id} className="hover:bg-[var(--admin-bg-subtle)]">
|
||||
<td className="px-5 py-3 font-medium text-[var(--admin-text-primary)]">{r.company_name ?? "—"}</td>
|
||||
<td className="px-5 py-3 text-[var(--admin-text-secondary)]">{r.contact_name ?? "—"}<br/><span className="text-xs text-[var(--admin-text-muted)]">{r.email}</span></td>
|
||||
|
||||
@@ -72,10 +72,9 @@ export async function POST(req: NextRequest) {
|
||||
const emailSubject = subject?.trim() || `${brandName} Wholesale Price Sheet — ${generatedDate}`;
|
||||
const hasCustomNote = Boolean(customNote?.trim());
|
||||
|
||||
// Build product rows HTML
|
||||
const productRows = products.flatMap(p =>
|
||||
p.availability === "available" ? [p] : []
|
||||
).map(p => {
|
||||
// Build product rows HTML (single pass)
|
||||
const productRowsReducer = products.reduce<{ rows: string[]; text: string[] }>((acc, p) => {
|
||||
if (p.availability !== "available") return acc;
|
||||
const tiersHtml = p.price_tiers
|
||||
.map(t => {
|
||||
const max = t.max_qty === 0 ? "+" : `-${t.max_qty}`;
|
||||
@@ -83,15 +82,21 @@ export async function POST(req: NextRequest) {
|
||||
})
|
||||
.join(" | ");
|
||||
|
||||
return `
|
||||
acc.rows.push(`
|
||||
<tr style="border-bottom: 1px solid #e5e7eb;">
|
||||
<td style="padding: 10px 12px; font-weight: 500; color: #1e293b;">${p.name}</td>
|
||||
<td style="padding: 10px 12px; color: #64748b; font-size: 13px;">${p.description ?? "—"}</td>
|
||||
<td style="padding: 10px 12px; color: #64748b; font-size: 13px; text-align: center;">${p.unit_type}</td>
|
||||
<td style="padding: 10px 12px; color: #1e293b; font-size: 13px; text-align: right; font-family: monospace;">${tiersHtml}</td>
|
||||
</tr>`;
|
||||
})
|
||||
.join("");
|
||||
</tr>`);
|
||||
|
||||
const tiersText = p.price_tiers
|
||||
.map(t => `${t.min_qty}${t.max_qty === 0 ? "+" : `-${t.max_qty}`}: $${Number(t.price).toFixed(2)}`)
|
||||
.join(", ");
|
||||
acc.text.push(`${p.name} (${p.unit_type})\n ${tiersText}`);
|
||||
return acc;
|
||||
}, { rows: [], text: [] });
|
||||
const productRows = productRowsReducer.rows.join("");
|
||||
|
||||
const html = `
|
||||
<!DOCTYPE html>
|
||||
@@ -143,12 +148,7 @@ ${hasCustomNote ? ` <p style="margin: 0 0 12px; color: #1e293b; font-size:
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
const text = `${brandName} Wholesale Price Sheet — ${generatedDate}\n${"=".repeat(50)}\n${hasCustomNote ? `\n${customNote!.trim()}\n\n` : ""}${products.flatMap(p =>
|
||||
p.availability === "available" ? [p] : []
|
||||
).map(p => {
|
||||
const tiers = p.price_tiers.map(t => `${t.min_qty}${t.max_qty === 0 ? "+" : `-${t.max_qty}`}: $${Number(t.price).toFixed(2)}`).join(", ");
|
||||
return `${p.name} (${p.unit_type})\n ${tiers}`;
|
||||
}).join("\n\n")}\n\nGenerated ${generatedDate}. Prices subject to change.`;
|
||||
const text = `${brandName} Wholesale Price Sheet — ${generatedDate}\n${"=".repeat(50)}\n${hasCustomNote ? `\n${customNote!.trim()}\n\n` : ""}${productRowsReducer.text.join("\n\n")}\n\nGenerated ${generatedDate}. Prices subject to change.`;
|
||||
|
||||
let enqueued = 0;
|
||||
let failed = 0;
|
||||
|
||||
@@ -232,9 +232,10 @@ export default function RoadmapPage() {
|
||||
className="w-full px-4 py-3 rounded-xl border border-[#e5e5e5] bg-white text-[#1a1a1a] focus:outline-none focus:ring-2 focus:ring-[#1a4d2e]/50 focus:border-[#1a4d2e] transition-all"
|
||||
>
|
||||
<option value="">Select a category</option>
|
||||
{CATEGORIES.flatMap(c =>
|
||||
c === "All" ? [] : [c]
|
||||
).map((category) => (
|
||||
{CATEGORIES.reduce<typeof CATEGORIES>((acc, c) => {
|
||||
if (c !== "All") acc.push(c);
|
||||
return acc;
|
||||
}, []).map((category) => (
|
||||
<option key={category} value={category.toLowerCase()}>{category}</option>
|
||||
))}
|
||||
</select>
|
||||
|
||||
@@ -42,15 +42,15 @@ type ShippingFulfillmentPanelProps = {
|
||||
canManageOrders: boolean;
|
||||
};
|
||||
|
||||
const SHIPPING_STATUSES = [
|
||||
const SHIPPING_STATUSES: Array<{ value: ShippingStatus; label: string }> = [
|
||||
{ value: "pending", label: "Pending" },
|
||||
{ value: "label_created", label: "Label Created" },
|
||||
{ value: "shipped", label: "Shipped" },
|
||||
{ value: "delivered", label: "Delivered" },
|
||||
{ value: "returned", label: "Returned" },
|
||||
] as const;
|
||||
];
|
||||
|
||||
type ShippingStatus = (typeof SHIPPING_STATUSES)[number]["value"];
|
||||
type ShippingStatus = "pending" | "label_created" | "shipped" | "delivered" | "returned";
|
||||
|
||||
const SERVICE_LABELS: Record<FedExServiceType, string> = {
|
||||
FEDEX_OVERNIGHT: "FedEx Overnight",
|
||||
@@ -526,9 +526,10 @@ function OrderCard({
|
||||
/>
|
||||
)}
|
||||
|
||||
{SHIPPING_STATUSES.flatMap((s) =>
|
||||
s.value !== order.shipping_status && s.value !== "label_created" ? [s] : []
|
||||
).map((s) => {
|
||||
{SHIPPING_STATUSES.reduce<typeof SHIPPING_STATUSES>((acc, s) => {
|
||||
if (s.value !== order.shipping_status && s.value !== "label_created") acc.push(s);
|
||||
return acc;
|
||||
}, []).map((s) => {
|
||||
const isDanger = s.value === "returned";
|
||||
return (
|
||||
<AdminButton
|
||||
|
||||
@@ -758,9 +758,10 @@ export default function LotDetailPanel({
|
||||
className="w-full rounded-xl border border-[var(--admin-border)] bg-[var(--admin-bg-subtle)]/50 px-3 py-3 text-sm text-[var(--admin-text-primary)] outline-none focus:border-[var(--admin-accent)] focus:ring-2 focus:ring-[var(--admin-accent)]/20 transition-all"
|
||||
>
|
||||
<option value="">Select status...</option>
|
||||
{STATUS_FLOW.flatMap((s) =>
|
||||
s !== lot.status ? [s] : []
|
||||
).map((s) => {
|
||||
{STATUS_FLOW.reduce<typeof STATUS_FLOW>((acc, s) => {
|
||||
if (s !== lot.status) acc.push(s);
|
||||
return acc;
|
||||
}, []).map((s) => {
|
||||
const c = EVENT_CONFIG[s];
|
||||
return (
|
||||
<option key={s} value={s}>
|
||||
|
||||
+4
-2
@@ -206,13 +206,15 @@ class MockQueryBuilder<T extends Record<string, unknown> = Record<string, unknow
|
||||
return (
|
||||
typeof rowValue === "string" &&
|
||||
likeNeedle !== null &&
|
||||
rowValue.includes(likeNeedle)
|
||||
likeNeedle.length > 0 &&
|
||||
rowValue.indexOf(likeNeedle) !== -1
|
||||
);
|
||||
case "ilike":
|
||||
return (
|
||||
typeof rowValue === "string" &&
|
||||
ilikeNeedle !== null &&
|
||||
rowValue.toLowerCase().includes(ilikeNeedle)
|
||||
ilikeNeedle.length > 0 &&
|
||||
rowValue.toLowerCase().indexOf(ilikeNeedle) !== -1
|
||||
);
|
||||
case "in":
|
||||
return inSet !== null && inSet.has(rowValue);
|
||||
|
||||
Reference in New Issue
Block a user