Skip to content

Feature idea: "newly available" badge on cat cards #40

Closed

Description

@BrandonML

Idea

Show a "new" badge on a cat card when the animal recently became available for adoption, so returning users can spot fresh listings without re-browsing everything.

The core problem

The RG v5 API has no field for "the date this animal's status changed to Available." That event only exists as an unstructured history entry in an org's RG admin panel, which the public API doesn't expose. So this has to be approximated from the date fields we can get, and the approximation will occasionally be wrong.

What we investigated

Audited all fields on the animals schema against org 8537 (Rebels Rescue) — see the "field audit" and "date comparison" discussion in session history for the full data. Then cross-checked 4 specific animals (Binx, Dottie, Loretta, Tessa) against their actual status-change-to-available date, looked up by hand in Rebels Rescue's own RG admin panel, to see how far off each candidate field was from ground truth:

Cat createdDate availableDate updatedDate true available-status date (RG admin)
Binx 2026-06-11 2026-07-08 2026-08-26 2026-07-17
Dottie 2026-06-11 2026-07-08 2026-08-26 2026-07-17
Tessa 2026-07-26 2026-09-01 2026-08-27 2026-08-15
Loretta 2025-06-10 2025-07-13 2026-08-17 2026-08-17 (adopted, then returned)

Findings:

  • updatedDate is unusable as the primary signal. It bumps on any edit (photo, description, etc.), not just a status change, so it drifts far from the true date once anything else touches the record (Binx/Dottie/Tessa above).
  • availableDate is the closest semantic match, but noisy in both directions — not just late. Binx/Dottie's field value is earlier than the true date (would make them look older than they are); Tessa's is later than the true date (would make her look newer than she is). Observed drift in these examples: 9–17 days.
  • updatedDate is, however, a guaranteed upper bound. A status change is itself an edit, so updatedDate can never be earlier than the true status-change date — only later, if something else was edited afterward. Loretta's record confirms this exactly: her updatedDate (8/17) matches her true return-to-available date (8/17) precisely, because nothing else was edited after the return. This makes updatedDate useless as a point estimate but valid as a sanity ceiling: if updatedDate itself is old, the animal cannot possibly be newly available.
  • Loretta is a structurally different case, not just noise. RG's expected behavior: when an adopted animal is returned, it goes back to Available status, but availableDate stays frozen at the original listing date and does not update on the return — confirmed as expected RG behavior, not a bug. No amount of tuning a window on availableDate alone will catch this pattern. adoptedDate being present is the tell that an animal was adopted at some point; combined with a current status of Available, that indicates a return, and updatedDate (not availableDate) is the better proxy for that specific case — based on the one example we could confirm (Loretta), so treat this branch as a hypothesis to validate against a few more manually-checked returned-animal cases before fully trusting it.
  • availableDate is optional per RG org, not guaranteed to be populated — RG lets each org decide whether to require it. It happens to be required for Rebels Rescue, but we can't assume that for every org in the dataset. Any animal missing availableDate can't be evaluated by this logic at all and should just be excluded from "new" consideration (no badge), not defaulted to some other field.

Recommended logic

if availableDate is null/empty:
    isNew = false   // can't evaluate without it; some orgs don't populate this field, nothing to fall back to

else if statuses.name != "Available":
    isNew = false

else if adoptedDate is present:            // adopted-then-returned pattern
    isNew = (now - updatedDate) <= 60 days

else:
    isNew = (now - availableDate) <= 60 days
            AND (now - updatedDate) <= 60 days   // free upper-bound sanity check, can only remove false positives

60 days was chosen as a window generous enough to absorb the 9–17 day drift observed above without flipping the badge on ordinary data-entry lag, while still meaningfully distinguishing recent listings from long-standing ones. Worth re-validating against more real examples if we want tighter confidence before launch, but there's a hard ceiling on precision here regardless — RG simply doesn't expose the ground-truth timestamp via the public API, so this is deliberately an approximation with a known, small error band, not an exact signal.

Implementation notes

  • availableDate and adoptedDate aren't currently in ANIMAL_FIELDS in server/rescuegroups.js — both need to be added to the fields[animals] request.
  • UI for badge/label the same concept as Highlight Senior Cats #44 . Utilize a Bootstrap style badge with a color scheme that draws attention but also fits the existing Tabby design scheme. The badge will have label text like "New" or "Recently Added" or similar. Placement of the label is open to discussion, but initial thinking is upper left or right overlayed on the cat photo. Note: Account for edge case scenario where the cat is both a senior and newly available, resulting in both badges to be displayed. This is OK, but they must be properly spaced when both are visible. When only one is visible, the other badge's HTML must not be displayed/rendered, so that its styling (e.g., margins and padding) are not still being applied even when not visible.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions