Keep same-name add refusals and refused removal order in onboarding
Step 2 keyed each refusal by the dinner's name, so a second add of the same name still in flight replaced the first add's refusal when it was refused too. Each attempt now keys its refusal uniquely; trying a change again once it has been refused still clears that earlier refusal. A refused removal was put back at the index it had in the list as it stood when it was removed, so refusing two overlapping removals of A and B restored B, A, C until a reread corrected it. A removal now only marks its Regular in the cache and the list hides it; a refusal clears the mark, so the Regular returns to its own place whatever else changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useState, type FormEvent } from 'react'
|
||||
import { useRef, useState, type FormEvent } from 'react'
|
||||
import { Plus } from 'lucide-react'
|
||||
import { useNavigate } from 'react-router'
|
||||
import { useAddRegular, useRegulars, useRemoveRegular, type Regular } from '../dinners/api.ts'
|
||||
@@ -31,9 +31,11 @@ function sameName(a: string, b: string): boolean {
|
||||
return a.trim().toLowerCase() === b.trim().toLowerCase()
|
||||
}
|
||||
|
||||
// Refusal is one add or removal the server turned down. key names the
|
||||
// change, so trying it again replaces its refusal and no other.
|
||||
type Refusal = { key: string; text: string }
|
||||
// Refusal is one add or removal the server turned down. key is unique to
|
||||
// that attempt, so two attempts of the same change in flight each keep their
|
||||
// own refusal. change names what was tried, so trying it again once it has
|
||||
// been refused clears the earlier refusal and no other.
|
||||
type Refusal = { key: number; change: string; text: string }
|
||||
|
||||
// RegularsStep is onboarding step 2, handoff mock 1h: the household adds
|
||||
// the dinners it makes on repeat. Each add and remove shows at once and is
|
||||
@@ -48,6 +50,7 @@ export function RegularsStep() {
|
||||
// latest change, which would hide a refusal while another change is in
|
||||
// flight.
|
||||
const [refusals, setRefusals] = useState<Refusal[]>([])
|
||||
const attempts = useRef(0)
|
||||
const list = regulars.data ?? []
|
||||
const picks = commonPicks.filter((pick) => !list.some((regular) => sameName(regular.name, pick)))
|
||||
// Next waits for every add to be answered, so a refused add's error shows
|
||||
@@ -55,13 +58,11 @@ export function RegularsStep() {
|
||||
const adding = list.some((regular) => regular.pending)
|
||||
const saved = list.filter((regular) => !regular.pending).length
|
||||
|
||||
function track(key: string, what: string, change: Promise<unknown>) {
|
||||
setRefusals((all) => all.filter((refusal) => refusal.key !== key))
|
||||
change.catch((error: Error) => {
|
||||
setRefusals((all) => [
|
||||
...all.filter((refusal) => refusal.key !== key),
|
||||
{ key, text: `Could not ${what}: ${error.message}` },
|
||||
])
|
||||
function track(change: string, what: string, answer: Promise<unknown>) {
|
||||
const key = ++attempts.current
|
||||
setRefusals((all) => all.filter((refusal) => refusal.change !== change))
|
||||
answer.catch((error: Error) => {
|
||||
setRefusals((all) => [...all, { key, change, text: `Could not ${what}: ${error.message}` }])
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user