fix(reporting): never strand a collected item, and log real PB errors
Two failure paths were swallowing their errors. 1. handleCollect returned early when the photo upload failed. Status was already flipped to `collected` at that point, but the early return skipped `setItems`, leaving a successfully-collected item on screen still looking un-collected. The driver re-collected it and re-attempted the same oversized upload — one record picked up 29 failed attempts in a single morning. The item now clears off the list either way, and a photo failure is a warning toast telling the driver to add it from the office, not a silent stall. 2. handleProblem logged nothing. PocketBase puts the real reason in `response.data` keyed by field name; the top-level message is always the useless "Something went wrong while processing your request." That is exactly what hid the problem_type mismatch fixed separately in PB today: the select was missing out_of_stock/partial_stock/quality_issue/wrong_item, so four of the five Report Problem buttons 400'd with no visible reason.
This commit is contained in:
parent
efba1bbf2f
commit
bb5a585af6
1 changed files with 49 additions and 17 deletions
66
app/page.tsx
66
app/page.tsx
|
|
@ -284,6 +284,15 @@ const loadItems = useCallback(async (showLoading = true) => {
|
|||
// visual record. We do this AFTER the status flip so a
|
||||
// failure here doesn't strand the item in `assigned` —
|
||||
// the collection is the more important state change.
|
||||
//
|
||||
// The item is cleared off the list either way. An earlier
|
||||
// version returned early on upload failure, which left a
|
||||
// successfully-collected item sitting on screen still looking
|
||||
// un-collected; the driver re-collected it, re-attempted the
|
||||
// same oversized upload, and one record picked up 29 failed
|
||||
// attempts in a single morning on 2026-10-12.
|
||||
let photoFailed = false;
|
||||
let photoFailure = '';
|
||||
if (photo) {
|
||||
try {
|
||||
await uploadOrderItemAttachment({
|
||||
|
|
@ -293,29 +302,37 @@ const loadItems = useCallback(async (showLoading = true) => {
|
|||
notes: notes || undefined,
|
||||
});
|
||||
} catch (uploadErr) {
|
||||
// Status already changed. Surface the failure so the
|
||||
// driver knows the photo did NOT persist (a success
|
||||
// toast here would be a lie). Known PB bug: image/* mime
|
||||
// detection rejects camera JPEGs — until that server
|
||||
// side detection is fixed, photos will keep failing.
|
||||
// The collection itself succeeded, so this is a warning,
|
||||
// not a failure — but the driver must still know the photo
|
||||
// did NOT persist. A success toast here would be a lie.
|
||||
//
|
||||
// (The "Known PB bug: image/* mime detection rejects camera
|
||||
// JPEGs" note that used to live here was wrong: PB's own
|
||||
// logs show every attempt failing as `400 unexpected EOF`
|
||||
// — the multipart body truncated in transit, not a format
|
||||
// rejection. `order_item_attachements` has mimeTypes=null,
|
||||
// so nothing was checking the type at all. Fixed by
|
||||
// compressing the photo client-side in lib/image.ts.)
|
||||
photoFailed = true;
|
||||
photoFailure = uploadErr instanceof Error ? uploadErr.message : 'unknown error';
|
||||
console.error('Photo upload failed:', uploadErr);
|
||||
const reason =
|
||||
uploadErr instanceof Error ? uploadErr.message : 'unknown error';
|
||||
showToast(
|
||||
`Item collected — but photo upload failed (${reason})`,
|
||||
'warning'
|
||||
);
|
||||
return; // skip the success toast that follows
|
||||
}
|
||||
}
|
||||
|
||||
setItems((prev) => prev.filter((i) => i.id !== item.id));
|
||||
setShowCollectModal(false);
|
||||
showToast(
|
||||
photo
|
||||
? 'Collection completed · photo uploaded'
|
||||
: 'Collection completed successfully'
|
||||
);
|
||||
if (photoFailed) {
|
||||
showToast(
|
||||
`Collected, but the photo didn't upload (${photoFailure}) — add it from the office.`,
|
||||
'warning',
|
||||
);
|
||||
} else {
|
||||
showToast(
|
||||
photo
|
||||
? 'Collection completed · photo uploaded'
|
||||
: 'Collection completed successfully',
|
||||
);
|
||||
}
|
||||
} catch (err) {
|
||||
showToast('Failed to update collection', 'error');
|
||||
}
|
||||
|
|
@ -336,6 +353,21 @@ const loadItems = useCallback(async (showLoading = true) => {
|
|||
// rather than just disappearing.
|
||||
showToast('Problem reported — item sent back to the pool', 'warning');
|
||||
} catch (err) {
|
||||
// PB puts the actual reason in `response.data` keyed by field
|
||||
// name — the top-level `message` is always the useless
|
||||
// "Something went wrong while processing your request." A 400 here
|
||||
// is almost always a select-field value the schema doesn't allow
|
||||
// (this cost us every problem report on 2026-10-14: problem_type
|
||||
// was missing out_of_stock/partial_stock/quality_issue/wrong_item).
|
||||
// Logging only the message hid that for months.
|
||||
const detail = (err as { response?: { data?: Record<string, { message?: string }> } })
|
||||
?.response?.data;
|
||||
console.error(
|
||||
'Failed to report problem:',
|
||||
item.id,
|
||||
problemType,
|
||||
detail ? JSON.stringify(detail) : err,
|
||||
);
|
||||
showToast('Failed to report problem', 'error');
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue