fix: react-doctor modal/dialog/dropzone a11y — 18 files to role+tabIndex+onKeyDown or dialog
This commit is contained in:
@@ -176,9 +176,8 @@ export function detectColumnMappings(
|
||||
});
|
||||
|
||||
// Collect sample values and handle disambiguation
|
||||
for (const mapping of mappings) {
|
||||
const colIdx = headers.indexOf(mapping.csvColumn);
|
||||
if (colIdx === -1 || mapping.field === null) continue;
|
||||
for (const [colIdx, mapping] of mappings.entries()) {
|
||||
if (mapping.field === null) continue;
|
||||
|
||||
const samples: string[] = [];
|
||||
for (const row of rows) {
|
||||
@@ -223,9 +222,8 @@ export function mapRowToContactEntry(
|
||||
let normalizedEmail: string | null = null;
|
||||
let normalizedPhone: string | null = null;
|
||||
|
||||
for (const mapping of mappings) {
|
||||
for (const [colIdx, mapping] of mappings.entries()) {
|
||||
if (mapping.field === null) continue;
|
||||
const colIdx = mappings.indexOf(mapping);
|
||||
const raw = row[colIdx] ?? "";
|
||||
|
||||
switch (mapping.field) {
|
||||
@@ -252,7 +250,10 @@ export function mapRowToContactEntry(
|
||||
break;
|
||||
case "tags":
|
||||
entry.tags = raw
|
||||
? raw.split(/[;:,]/).map((t) => t.trim()).filter(Boolean)
|
||||
? raw.split(/[;:,]/).flatMap((t) => {
|
||||
const trimmed = t.trim();
|
||||
return trimmed ? [trimmed] : [];
|
||||
})
|
||||
: undefined;
|
||||
break;
|
||||
case "email_opt_in":
|
||||
|
||||
+10
-5
@@ -26,9 +26,11 @@ export function parseProductCSV(csvText: string): {
|
||||
}
|
||||
|
||||
const header = lines[0].split(",").map((h) => h.trim().toLowerCase());
|
||||
const headerSet = new Set(header);
|
||||
const VALID_TYPES = new Set(["Pickup", "Shipping", "Pickup & Shipping"]);
|
||||
const required = ["name", "price", "type"];
|
||||
for (const col of required) {
|
||||
if (!header.includes(col)) {
|
||||
if (!headerSet.has(col)) {
|
||||
return { success: false, error: `Missing required column: ${col}` };
|
||||
}
|
||||
}
|
||||
@@ -60,7 +62,7 @@ export function parseProductCSV(csvText: string): {
|
||||
}
|
||||
|
||||
const type = cols[typeIdx] ?? "";
|
||||
if (!["Pickup", "Shipping", "Pickup & Shipping"].includes(type)) {
|
||||
if (!VALID_TYPES.has(type)) {
|
||||
errors.push({ row: i + 1, error: `Invalid type: ${type}` });
|
||||
continue;
|
||||
}
|
||||
@@ -125,11 +127,13 @@ export function parseStopCSV(csvText: string): {
|
||||
// Build column index map — common synonyms supported
|
||||
const rawHeader = lines[0].split(",").map((h) => h.trim());
|
||||
const header = rawHeader.map((h) => h.toLowerCase());
|
||||
const headerIndex = new Map<string, number>();
|
||||
header.forEach((h, i) => headerIndex.set(h, i));
|
||||
|
||||
function idx(...names: string[]): number {
|
||||
for (const n of names) {
|
||||
const i = header.indexOf(n);
|
||||
if (i >= 0) return i;
|
||||
const i = headerIndex.get(n);
|
||||
if (i !== undefined) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -215,9 +219,10 @@ export function parseOrderCSV(csvText: string): {
|
||||
}
|
||||
|
||||
const header = lines[0].split(",").map((h) => h.trim().toLowerCase());
|
||||
const headerSet = new Set(header);
|
||||
const required = ["customer_name", "customer_email", "stop_id", "product_id", "quantity", "fulfillment"];
|
||||
for (const col of required) {
|
||||
if (!header.includes(col)) {
|
||||
if (!headerSet.has(col)) {
|
||||
return { success: false, error: `Missing required column: ${col}` };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user