mirror of
https://github.com/velocitatem/PHANTOM.git
synced 2026-05-31 08:33:36 +00:00
refactor tracking to ues callbacks instead of refs
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import type { EventName } from '@/lib/events';
|
||||
import { useHoverTracking } from '@/hooks/useHoverTracking';
|
||||
|
||||
const dispatchInteraction = (eventName: EventName, productId?: string, metadata?: Record<string, unknown>) => {
|
||||
const e = new CustomEvent('definedInteraction', {
|
||||
@@ -29,8 +30,20 @@ const PriceDisplay = ({ price }: { price: number }) => (
|
||||
);
|
||||
|
||||
export default function AirlineCard({ flight }: { flight: Flight }) {
|
||||
const durationRef = useHoverTracking({
|
||||
eventName: 'hover_over_title',
|
||||
productId: flight.id,
|
||||
metadata: { elementText: flight.duration },
|
||||
});
|
||||
|
||||
const priceRef = useHoverTracking({
|
||||
eventName: 'hover_over_paragraph',
|
||||
productId: flight.id,
|
||||
metadata: { elementText: `$${flight.basePrice}` },
|
||||
});
|
||||
|
||||
const handleCardClick = () => {
|
||||
dispatchInteraction('product_view', flight.id, {
|
||||
dispatchInteraction('view_item_page', flight.id, {
|
||||
cabinClass: flight.cabinClass,
|
||||
fareRule: flight.fareRule,
|
||||
price: flight.basePrice,
|
||||
@@ -41,7 +54,6 @@ export default function AirlineCard({ flight }: { flight: Flight }) {
|
||||
<div
|
||||
className="flight-card cursor-pointer"
|
||||
onClick={handleCardClick}
|
||||
onMouseEnter={() => dispatchInteraction('product_hover', flight.id)}
|
||||
>
|
||||
<div className="flight-timing">
|
||||
<div className="flight-time">{flight.departure.time}</div>
|
||||
@@ -49,7 +61,7 @@ export default function AirlineCard({ flight }: { flight: Flight }) {
|
||||
</div>
|
||||
|
||||
<div className="flight-route">
|
||||
<div className="flight-duration">{flight.duration}</div>
|
||||
<div ref={durationRef} className="flight-duration">{flight.duration}</div>
|
||||
<div className="flight-stops">
|
||||
{flight.stops === 0 ? 'Direct' : `${flight.stops} stop${flight.stops > 1 ? 's' : ''}`}
|
||||
</div>
|
||||
@@ -66,8 +78,10 @@ export default function AirlineCard({ flight }: { flight: Flight }) {
|
||||
{flight.refundable && (
|
||||
<div className="badge-value text-xs mb-2">Refundable</div>
|
||||
)}
|
||||
<div ref={priceRef}>
|
||||
<PriceDisplay price={flight.basePrice} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use client';
|
||||
|
||||
import type { EventName } from '@/lib/events';
|
||||
import { useHoverTracking } from '@/hooks/useHoverTracking';
|
||||
|
||||
const dispatchInteraction = (eventName: EventName, productId?: string, metadata?: Record<string, unknown>) => {
|
||||
const e = new CustomEvent('definedInteraction', {
|
||||
@@ -42,8 +43,20 @@ const AmenityIcon = ({ name }: { name: string }) => {
|
||||
};
|
||||
|
||||
export default function HotelCard({ hotel }: { hotel: Hotel }) {
|
||||
const titleRef = useHoverTracking({
|
||||
eventName: 'hover_over_title',
|
||||
productId: hotel.id,
|
||||
metadata: { elementText: hotel.name },
|
||||
});
|
||||
|
||||
const priceRef = useHoverTracking({
|
||||
eventName: 'hover_over_paragraph',
|
||||
productId: hotel.id,
|
||||
metadata: { elementText: `$${hotel.pricePerNight}` },
|
||||
});
|
||||
|
||||
const handleCardClick = () => {
|
||||
dispatchInteraction('product_view', hotel.id, {
|
||||
dispatchInteraction('view_item_page', hotel.id, {
|
||||
roomType: hotel.roomType,
|
||||
price: hotel.pricePerNight,
|
||||
nights: hotel.nights,
|
||||
@@ -54,14 +67,13 @@ export default function HotelCard({ hotel }: { hotel: Hotel }) {
|
||||
<div
|
||||
className="hotel-card cursor-pointer"
|
||||
onClick={handleCardClick}
|
||||
onMouseEnter={() => dispatchInteraction('product_hover', hotel.id)}
|
||||
>
|
||||
<div className="hotel-image bg-gray-200 flex items-center justify-center">
|
||||
<span className="text-gray-400 text-sm">Image</span>
|
||||
</div>
|
||||
|
||||
<div className="hotel-info">
|
||||
<h3 className="hotel-name">{hotel.name}</h3>
|
||||
<h3 ref={titleRef} className="hotel-name">{hotel.name}</h3>
|
||||
<div className="hotel-location text-sm mb-2">{hotel.roomType}</div>
|
||||
<div className="text-sm text-[var(--text-secondary)] mb-2">
|
||||
{hotel.checkIn} - {hotel.checkOut}
|
||||
@@ -77,7 +89,9 @@ export default function HotelCard({ hotel }: { hotel: Hotel }) {
|
||||
</div>
|
||||
|
||||
<div className="hotel-pricing">
|
||||
<div ref={priceRef}>
|
||||
<PriceDisplay price={hotel.pricePerNight} perNight />
|
||||
</div>
|
||||
<div className="text-xs text-[var(--text-secondary)] mt-1">
|
||||
${hotel.pricePerNight * hotel.nights} total for {hotel.nights} night{hotel.nights > 1 ? 's' : ''}
|
||||
</div>
|
||||
|
||||
@@ -42,23 +42,6 @@ export const useInteractionTracking = () => {
|
||||
setReady(true);
|
||||
});
|
||||
|
||||
const handleClick = (e: MouseEvent) => {
|
||||
if (!sidRef.current) return;
|
||||
const tgt = e.target as HTMLElement;
|
||||
const page = window.location.pathname;
|
||||
track({
|
||||
sessionId: sidRef.current,
|
||||
eventName: 'click',
|
||||
page,
|
||||
metadata: {
|
||||
x: e.clientX,
|
||||
y: e.clientY,
|
||||
targetEl: tgt.tagName,
|
||||
targetUrl: tgt instanceof HTMLAnchorElement ? tgt.href : undefined,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const handlePageView = () => {
|
||||
if (!sidRef.current) return;
|
||||
const page = window.location.pathname;
|
||||
@@ -94,11 +77,9 @@ export const useInteractionTracking = () => {
|
||||
if (!ready) return;
|
||||
|
||||
handlePageView();
|
||||
document.addEventListener('click', handleClick);
|
||||
document.addEventListener('definedInteraction', handleDefinedInteraction);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener('click', handleClick);
|
||||
document.removeEventListener('definedInteraction', handleDefinedInteraction);
|
||||
};
|
||||
}, [ready]);
|
||||
|
||||
Reference in New Issue
Block a user