From 2546eb30fe66762515712d0a9339875db23e142f Mon Sep 17 00:00:00 2001 From: aewing Date: Tue, 6 Jan 2026 14:29:47 +0000 Subject: [PATCH] Fields are working now as expected. need to remove job size gues and guess source and move schedule confidence to beside start date, but this gets us back on the right path. --- frontend/index.html | 409 +++++++++++++++++++++++++++++++++++++++++++- server.ts | 48 ++++++ 2 files changed, 450 insertions(+), 7 deletions(-) diff --git a/frontend/index.html b/frontend/index.html index d93a1f3..5202d10 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -5,6 +5,8 @@ Job Creation Form + + diff --git a/server.ts b/server.ts index 87fd8a2..1cf1b1b 100644 --- a/server.ts +++ b/server.ts @@ -693,6 +693,54 @@ app.post('/api/submit', async (c) => { if (dueIso) data.Due_Date = dueIso; if (startIso) data.Start_Date = startIso; + // Address validation: require plausible address, coordinates, OR Address_Notes provided + const addr = (data.Job_Address || '').toString().trim(); + const addrNotes = (data.Address_Notes || '').toString().trim(); + + // Check if it looks like coordinates: pattern "lat, lon" or "lat,lon" + const coordPattern = /^-?\d+\.?\d*\s*,\s*-?\d+\.?\d*$/; + const isCoordinates = coordPattern.test(addr); + + // Check if it looks like a real address: has digit(s) and letter(s), at least 5 chars + const hasDigit = /\d/.test(addr); + const hasAlpha = /[A-Za-z]/.test(addr); + const isAddress = addr.length >= 5 && hasDigit && hasAlpha; + + const addressLooksValid = isCoordinates || isAddress; + if (!addressLooksValid && addrNotes.length < 5) { + return c.json({ + success: false, + message: 'Provide a real address (e.g., 123 Main St, City, State), coordinates (e.g., 34.0522, -118.2437), or enter directions in Address Notes.' + }, 400); + } + data.Job_Address = addr; + data.Address_Notes = addrNotes; + +// Job name validation: must be at least 4 characters, contain letters, not symbols-only, not "n/a" + const jobName = (data.Job_Name || '').toString().trim(); + const invalidLiterals = ['n/a', 'na', 'n.a.', 'n\\a', 'none']; + const onlySymbols = /^[^A-Za-z0-9]+$/.test(jobName); + const hasLetters = /[A-Za-z]/.test(jobName); + const isInvalidLiteral = invalidLiterals.includes(jobName.toLowerCase()); + const isLongEnough = jobName.length >= 4; + if (!isLongEnough || !hasLetters || onlySymbols || isInvalidLiteral) { + return c.json({ + success: false, + message: 'Job name must be at least 4 characters with letters (no symbols-only, no N/A).' + }, 400); + } + data.Job_Name = jobName; + + // Enforce Job_Type and Job_Division selection + const jobType = (data.Job_Type || '').toString().trim(); + const jobDivision = (data.Job_Division || '').toString().trim(); + if (!jobType || !jobDivision) { + return c.json({ + success: false, + message: 'Please select both Job Type and Job Division.' + }, 400); + } + // Get all existing job numbers and find the max const existingJobs = await pb.collection(process.env.PB_COLLECTION!).getFullList({ fields: 'Job_Number',