"use client"; /** Payment → Chat bridge, mounted only while the chat route is active. */ import { useEffect, useRef } from "react"; import { shallowEqual } from "@xstate/react"; import { hasPendingChatUnlock } from "@/lib/navigation/chat_unlock_session"; import { useChatDispatch, useChatSelector, } from "@/stores/chat/chat-context"; import { usePaymentSelector } from "@/stores/payment/payment-context"; export function ChatPaymentSuccessSync() { const paymentState = usePaymentSelector( (state) => ({ currentOrderId: state.context.currentOrderId, isPaid: state.matches("paid"), orderStatus: state.context.orderStatus, }), shallowEqual, ); const characterId = useChatSelector((state) => state.context.characterId); const chatDispatch = useChatDispatch(); const lastPaidKeyRef = useRef(null); useEffect(() => { if (!paymentState.isPaid || !paymentState.currentOrderId) return; const paidKey = `${paymentState.currentOrderId}:${paymentState.orderStatus}`; if (lastPaidKeyRef.current === paidKey) return; lastPaidKeyRef.current = paidKey; let cancelled = false; void (async () => { if (await hasPendingChatUnlock(characterId)) return; if (!cancelled) chatDispatch({ type: "ChatPaymentSucceeded" }); })(); return () => { cancelled = true; }; }, [ chatDispatch, characterId, paymentState.currentOrderId, paymentState.isPaid, paymentState.orderStatus, ]); return null; }