Skip to content

Fallback affiliate tracking link copy#216

Closed
morganschp wants to merge 1 commit into
profullstack:masterfrom
morganschp:fix-affiliate-tracking-copy-fallback
Closed

Fallback affiliate tracking link copy#216
morganschp wants to merge 1 commit into
profullstack:masterfrom
morganschp:fix-affiliate-tracking-copy-fallback

Conversation

@morganschp
Copy link
Copy Markdown
Contributor

Summary

  • add a Clipboard API fallback for the affiliate offer tracking-link Copy button
  • only show the copied state after a copy path succeeds
  • show a manual-copy error when Clipboard API and textarea fallback both fail
  • add component coverage for the apply-then-copy success fallback and full copy failure paths

Fixes #155

Validation

  • ./node_modules/.bin/vitest run 'src/app/affiliates/[slug]/OfferDetailClient.test.tsx'
  • ./node_modules/.bin/eslint 'src/app/affiliates/[slug]/OfferDetailClient.tsx' 'src/app/affiliates/[slug]/OfferDetailClient.test.tsx'
  • ./node_modules/.bin/prettier --check 'src/app/affiliates/[slug]/OfferDetailClient.tsx' 'src/app/affiliates/[slug]/OfferDetailClient.test.tsx'
  • ./node_modules/.bin/tsc --noEmit --pretty false
  • git diff --check -- 'src/app/affiliates/[slug]/OfferDetailClient.tsx' 'src/app/affiliates/[slug]/OfferDetailClient.test.tsx'

uGig gig: https://ugig.net/gig/cmexbmp260001ju04n3qmkdko

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 23, 2026

Greptile Summary

This PR adds a Clipboard API fallback for the affiliate offer tracking-link copy button, ensuring the copy works in browsers/contexts where navigator.clipboard.writeText is unavailable or blocked, and surfaces a clear inline error when both paths fail.

  • copyText tries navigator.clipboard.writeText first; on rejection it falls through to a document.execCommand(\"copy\") textarea trick via copyWithTextarea.
  • handleCopyTrackingUrl gates the "Copied!" state behind a successful copy result and shows a manual-copy error message when both paths return false.
  • Two new Vitest tests cover the fallback-succeeds path and the all-paths-fail path; formatting-only changes are scattered throughout the rest of the file.

Confidence Score: 5/5

The change is isolated to the copy-button handler and its helper functions; the fallback chain is correct, error state is cleared on every new attempt, and no existing behavior is affected.

The copyText → copyWithTextarea fallback chain handles all three outcomes correctly. State management is straightforward: copyError is always cleared at the top of handleCopyTrackingUrl before the new attempt, so stale error messages cannot persist across clicks. The two new tests faithfully exercise the fallback and total-failure paths. The bulk of the diff is Prettier reformatting with no logic changes.

No files require special attention.

Important Files Changed

Filename Overview
src/app/affiliates/[slug]/OfferDetailClient.tsx Adds copyText/copyWithTextarea helpers and handleCopyTrackingUrl handler; Copy button now reflects success/failure state with copiedTrackingUrl and copyError state; remaining changes are prettier reformatting only.
src/app/affiliates/[slug]/OfferDetailClient.test.tsx New test file covering two new code paths: Clipboard API rejection falling through to textarea execCommand success, and full copy failure showing the manual-copy error message.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A([User clicks Copy]) --> B[handleCopyTrackingUrl]
    B --> C[setCopyError '']
    C --> D{navigator.clipboard?.writeText exists?}
    D -->|Yes| E[clipboard.writeText]
    E -->|resolves| F[return true]
    E -->|rejects| G[copyWithTextarea fallback]
    D -->|No| G
    G --> H[append textarea to DOM, focus + select]
    H --> I[document.execCommand 'copy']
    I -->|true| J[return true]
    I -->|false / throws| K[return false]
    F --> L{copied?}
    J --> L
    K --> L
    L -->|true| M[setCopiedTrackingUrl true, button shows 'Copied!']
    M --> N[setTimeout 2s, reset to 'Copy']
    L -->|false| O[setCopyError 'Copy failed...', button stays 'Copy']
Loading

Reviews (3): Last reviewed commit: "Fallback affiliate tracking link copy" | Re-trigger Greptile

Comment on lines +166 to +167
setCopiedTrackingUrl(true);
setTimeout(() => setCopiedTrackingUrl(false), 2000);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The setTimeout ID is never stored, so a second click within the 2-second window stacks an additional timer. When the first timer fires it resets copiedTrackingUrl to false early — the button snaps back to "Copy" before the expected interval elapses from the most recent click. Storing the ID in a useRef and calling clearTimeout on entry fixes this.

Suggested change
setCopiedTrackingUrl(true);
setTimeout(() => setCopiedTrackingUrl(false), 2000);
setCopiedTrackingUrl(true);
if (copyTimerRef.current) clearTimeout(copyTimerRef.current);
copyTimerRef.current = window.setTimeout(() => setCopiedTrackingUrl(false), 2000);

Comment on lines +120 to +127
describe("OfferDetailClient tracking link copy", () => {
beforeEach(() => {
vi.clearAllMocks();
mockApi();
mockClipboard(vi.fn().mockResolvedValue(undefined));
mockExecCommand(true);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Missing test for the primary (happy-path) copy flow — where navigator.clipboard.writeText resolves successfully. The beforeEach wires up a resolving writeText mock but no test exercises that path and asserts that the button transitions from "Copy" → "Copied!" without invoking document.execCommand. Without this, a regression that silently skips the Clipboard API or always falls through to the textarea path would go undetected.

@ralyodio ralyodio closed this May 23, 2026
@ralyodio ralyodio reopened this May 23, 2026
@ralyodio ralyodio closed this May 23, 2026
@ralyodio ralyodio reopened this May 23, 2026
@ralyodio ralyodio closed this May 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: affiliate tracking link copy fails when Clipboard API is blocked

2 participants