"use client"; import { useState, useEffect } from "react"; import { savePaymentSettings, type PaymentProvider, type PaymentSettings } from "@/actions/payments"; import { syncSquareNow, getSyncLog, type SyncLogEntry } from "@/actions/square-sync-ui"; import WebhookLogsSection from "@/components/admin/WebhookLogsSection"; import { AdminInput, AdminTextInput, AdminSelect } from "./design-system"; type InventoryMode = "none" | "rc_to_square" | "square_to_rc" | "bidirectional"; type Props = { settings: { provider?: PaymentProvider | null; stripe_publishable_key?: string | null; stripe_secret_key?: string | null; square_access_token?: string | null; square_location_id?: string | null; square_sync_enabled?: boolean; square_inventory_mode?: InventoryMode; square_last_sync_at?: string | null; square_last_sync_error?: string | null; } | null; brandId: string; brands?: { id: string; name: string }[]; isPlatformAdmin?: boolean; }; export default function PaymentSettingsForm({ settings, brandId, brands = [], isPlatformAdmin = false }: Props) { const [activeBrandId, setActiveBrandId] = useState(brandId); const [provider, setProvider] = useState( (settings?.provider ?? "") as PaymentProvider | "" ); const [stripePublishableKey, setStripePublishableKey] = useState( settings?.stripe_publishable_key ?? "" ); const [stripeSecretKey, setStripeSecretKey] = useState( settings?.stripe_secret_key ?? "" ); const [squareAccessToken, setSquareAccessToken] = useState( settings?.square_access_token ?? "" ); const [squareLocationId, setSquareLocationId] = useState( settings?.square_location_id ?? "" ); const [saving, setSaving] = useState(false); const [saved, setSaved] = useState(false); const [error, setError] = useState(null); const [showStripe, setShowStripe] = useState(settings?.provider === "stripe" || settings?.provider === "square" ? settings.provider === "stripe" : false); const [showSquare, setShowSquare] = useState(settings?.provider === "square"); // Square Sync state const [squareSyncEnabled, setSquareSyncEnabled] = useState( settings?.square_sync_enabled ?? false ); const [squareInventoryMode, setSquareInventoryMode] = useState( settings?.square_inventory_mode ?? "none" ); const [syncing, setSyncing] = useState(false); const [syncResult, setSyncResult] = useState<{ success: boolean; message: string } | null>(null); const [syncLog, setSyncLog] = useState([]); const hasSquareToken = !!settings?.square_access_token; // Read URL params to show connection success/error useEffect(() => { const params = new URLSearchParams(window.location.search); if (params.get("square_connected") === "true") { setSyncResult({ success: true, message: "Square connected successfully!" }); window.history.replaceState({}, "", window.location.pathname); } const err = params.get("error"); if (err) { setSyncResult({ success: false, message: `Square connection failed: ${err}` }); window.history.replaceState({}, "", window.location.pathname); } }, []); // Load sync log on mount useEffect(() => { if (hasSquareToken) { getSyncLog(activeBrandId).then((result) => { if (result.success) setSyncLog(result.logs); }); } }, [hasSquareToken, activeBrandId]); async function handleSave(e: React.FormEvent) { e.preventDefault(); setSaving(true); setError(null); const result = await savePaymentSettings({ brandId: activeBrandId, provider: provider || null, stripePublishableKey: stripePublishableKey || undefined, stripeSecretKey: stripeSecretKey || undefined, squareAccessToken: squareAccessToken || undefined, squareLocationId: squareLocationId || undefined, squareSyncEnabled, squareInventoryMode, }); setSaving(false); if (!result.success) { setError(result.error ?? "Failed to save"); } else { setSaved(true); setTimeout(() => setSaved(false), 3000); } } async function handleSyncNow(type: string) { setSyncing(true); setSyncResult(null); const result = await syncSquareNow(activeBrandId, type as "products" | "orders" | "all"); setSyncResult({ success: result.success, message: result.success ? `Synced ${result.synced} item(s).` : `Sync failed: ${result.errors?.[0] ?? "Unknown error"}`, }); setSyncing(false); // Refresh sync log const logResult = await getSyncLog(brandId); if (logResult.success) setSyncLog(logResult.logs); } async function handleDisconnectSquare() { if (!confirm("Disconnect Square? This will clear the access token.")) return; setSaving(true); setError(null); const result = await savePaymentSettings({ brandId: activeBrandId, provider: provider || null, squareAccessToken: "", squareLocationId: "", squareSyncEnabled: false, squareInventoryMode: "none", }); setSaving(false); if (!result.success) { setError(result.error ?? "Failed to disconnect"); } else { setSaved(true); setTimeout(() => setSaved(false), 3000); } } const lastSyncAt = settings?.square_last_sync_at ? new Date(settings.square_last_sync_at).toLocaleString() : "Never"; return (
{/* Platform admin brand picker */} {isPlatformAdmin && brands.length > 0 && ( setActiveBrandId(e.target.value)} options={brands.map((b) => ({ value: b.id, label: b.name }))} /> )} {error && (
{error}
)} {saved && (
Payment settings saved.
)} {syncResult && (
{syncResult.message}
)} {/* Connected status banner */} {settings?.stripe_publishable_key && (

Stripe Connected

Payments are configured for this brand

)} {/* Provider selection */}

Choose how to process payments for this brand.

{[ { value: "", label: "None / Manual" }, { value: "stripe", label: "Stripe" }, { value: "square", label: "Square" }, ].map((opt) => ( ))}
{/* Stripe credentials */} {showStripe && (

Stripe

{settings?.stripe_publishable_key && ( Connected )}
{!settings?.stripe_publishable_key ? (

Connect your Stripe account to process payments. You'll be redirected to Stripe to authorize the connection.

Connect with Stripe
) : (

✓ Your Stripe account is connected and ready to accept payments.

)}
)} {/* Square credentials */} {showSquare && (

Square

{!hasSquareToken ? (

Connect your Square account via OAuth to enable sync.

Connect Square
) : ( <> setSquareLocationId(e.target.value)} placeholder="L..." /> )}
)} {/* Square Sync section */} {hasSquareToken && provider === "square" && (

Square Sync

Keep products, orders, and inventory in sync between Route Commerce and Square.

{/* Enable toggle */}
{squareSyncEnabled ? "Enabled" : "Disabled"}
{squareSyncEnabled && ( <> {/* Inventory mode */}

Inventory sync direction

{[ { value: "none", label: "None" }, { value: "rc_to_square", label: "RC → Square" }, { value: "square_to_rc", label: "Square → RC" }, { value: "bidirectional", label: "Bidirectional" }, ].map((opt) => ( ))}
{/* Sync Now buttons */}
{/* Last sync info */}
Last sync: {lastSyncAt} {settings?.square_last_sync_error && ( — {settings.square_last_sync_error} )}
{/* Sync log preview */} {syncLog.length > 0 && (

Recent sync activity

{syncLog.map((entry) => (
[{entry.direction ?? "—"}] {entry.event_type} — {entry.status} {new Date(entry.created_at).toLocaleTimeString()}
))}
)} )}
)} {/* Wholesale webhook log */} ); }