Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions apps/web/src/components/OfferSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,32 @@ export default function OfferSelector({
return allOffers.find(o => o.id === selectedOfferId) || null
}, [selectedOfferId, allOffers])

// Initialize selectors from selected offer
// Initialize/sync selectors from selected offer
// This effect handles two cases:
// 1. Initial mount with a selectedOfferId - wait for offers to load then sync
// 2. selectedOfferId prop changes externally - sync to new offer
// We track which offer we've synced to avoid interfering with manual user selection
const [lastSyncedOfferId, setLastSyncedOfferId] = useState<string | null | undefined>(undefined)

useEffect(() => {
if (selectedOffer) {
setSelectedProviderId(selectedOffer.provider_id)
setSelectedOfferType(selectedOffer.offer_type)
// We have a valid offer - sync the selectors if not already synced to this offer
if (lastSyncedOfferId !== selectedOffer.id) {
setSelectedProviderId(selectedOffer.provider_id)
setSelectedOfferType(selectedOffer.offer_type)
setLastSyncedOfferId(selectedOffer.id)
}
} else if (selectedOfferId === null || selectedOfferId === undefined) {
// Offer was cleared externally - reset selectors
if (lastSyncedOfferId !== null) {
setSelectedProviderId(null)
setSelectedOfferType(null)
setLastSyncedOfferId(null)
}
Comment on lines +115 to +119
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The condition lastSyncedOfferId !== null will fail to reset selectors when lastSyncedOfferId is undefined (its initial state).

This can happen on initial render if selectedOfferId is null or undefined from the start. In this case, lastSyncedOfferId would be undefined, but the condition checks for !== null, so the reset won't happen.

Change the condition to:

if (lastSyncedOfferId !== null && lastSyncedOfferId !== undefined) {

Or more concisely:

if (lastSyncedOfferId != null) { // using != instead of !== checks both null and undefined

Copilot uses AI. Check for mistakes.
}
}, [selectedOffer])
// Note: when selectedOfferId is set but selectedOffer is null (offers loading),
// we wait - the effect will re-run when offers finish loading
}, [selectedOffer, selectedOfferId, lastSyncedOfferId])
Comment on lines 105 to +123
Copy link

Copilot AI Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Critical bug: This effect will interfere with manual user selection. When a user manually changes selectedProviderId via handleProviderChange (line 127), the effect will immediately re-sync the selectors back to the old selectedOffer values, preventing the user from changing their selection.

The issue occurs because:

  1. User changes provider → handleProviderChange sets selectedProviderId to new value
  2. selectedOfferId prop hasn't changed yet (still old offer)
  3. Effect runs → selectedOffer is still the old offer and lastSyncedOfferId !== selectedOffer.id is true
  4. Effect resets selectedProviderId back to old offer's provider

To fix this, you need to update lastSyncedOfferId when users manually interact with the selectors (in handleProviderChange, handleOfferTypeChange, and handleClear). This tells the effect that the user is actively changing the selection and prevents it from overwriting their changes. For example:

const handleProviderChange = (providerId: string | null) => {
  setSelectedProviderId(providerId)
  setSelectedOfferType(null)
  setLastSyncedOfferId(undefined) // Signal that user is manually selecting
}

Copilot uses AI. Check for mistakes.

// Reset offer type when provider changes
const handleProviderChange = (providerId: string | null) => {
Expand Down