← back to Stayclaim
src/components/sponsored/SponsoredCard.tsx
85 lines
/**
* SponsoredCard — paid Promote-a-Listing unit.
*
* FIREWALL RULES (see plan §1 "Promote-a-Listing editorial firewall"):
* - The ONLY component allowed to use coral as a fill color.
* - Has NO TierBadge slot — A/B/C/D is reserved for historical facts.
* - Never writes to event, entity_place_association, or any provenance table.
* - Lives in src/components/sponsored/* so a lint boundary can enforce
* that editorial components don't import from here (and vice versa).
* - Always carries "Sponsored · Current listing" eyebrow + source logo.
*/
import { FREE_FOREVER } from '@/lib/flags';
import { safeHttpUrl } from '@/lib/url-guards';
type SponsoredSource = 'zillow' | 'redfin' | 'airbnb' | 'other';
const SOURCE_LABEL: Record<SponsoredSource, string> = {
zillow: 'Zillow',
redfin: 'Redfin',
airbnb: 'Airbnb',
other: 'Listing',
};
export function SponsoredCard({
source,
title,
priceLabel,
url,
imageUrl,
}: {
source: SponsoredSource;
title: string;
priceLabel?: string;
url: string;
imageUrl?: string;
}) {
// Soft-disabled when FREE_FOREVER=true — pastdoor doesn't accept paid placements.
// 2026-05-05 (refactor agent): use the canonical flag from lib/flags.ts instead
// of re-reading process.env, so SSR/RSC builds don't drift between init-time
// (flags.ts) and render-time (this component) values.
if (FREE_FOREVER) return null;
return (
<aside
className="relative bg-ink text-sand border border-coral/30 rounded-none p-5 font-sans"
data-sponsored="true"
aria-label="Sponsored current listing"
>
<div className="mb-3 flex items-center justify-between text-[10px] uppercase tracking-[0.15em] text-sand/60">
<span className="inline-flex items-center gap-2">
<span className="inline-block h-2 w-2 rounded-full bg-coral" />
Sponsored · Current listing
</span>
<span className="text-sand/50">{SOURCE_LABEL[source]}</span>
</div>
{safeHttpUrl(imageUrl) && (
<div className="mb-4 aspect-[16/9] overflow-hidden">
<img src={safeHttpUrl(imageUrl)!} alt="" className="h-full w-full object-cover" />
</div>
)}
<div className="mb-4">
<h3 className="font-sans text-base font-medium text-sand leading-snug">{title}</h3>
{priceLabel && <p className="mt-1 text-sm text-sand/70">{priceLabel}</p>}
</div>
<a
href={safeHttpUrl(url) ?? '#'}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-2 border border-coral px-4 py-1.5 text-xs uppercase tracking-wider text-coral hover:bg-coral hover:text-ink transition"
>
View on {SOURCE_LABEL[source]}
<span aria-hidden>→</span>
</a>
<p className="mt-3 text-[10px] text-sand/40 leading-relaxed">
This is paid placement. The historical record below is independent.
</p>
</aside>
);
}