2025-12-26 16:05:08 +00:00

255 lines
8.9 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client';
import React, { useEffect, useMemo, useState } from 'react';
import { getAccessToken_client } from '@/utils/apiHelper_client';
import { useRouter } from 'next/navigation';
import axios from 'axios';
type StoreFromAPI = {
userid: string;
store_name: string;
store_description: string;
store_url: string;
store_url_path: string;
store_last_opened_time: string | null;
store_last_opened_time_raw: string | null;
store_logo_url: string;
};
type ApiOk = { code: 'STORE_PRESENT'; message: string; store: StoreFromAPI };
type ApiMiss = { code: 'USER_NOT_FOUND_OR_NO_STORE'; message: string };
type ApiResp = ApiOk | ApiMiss | any;
const read = async (r: Response) =>
r.headers.get('content-type')?.includes('application/json') ? r.json() : r.text();
function safeDateFormat(input?: string | null) {
if (!input) return '—';
const d = new Date(input);
return isNaN(d.getTime()) ? '—' : d.toLocaleString();
}
export default function EbayAuthPage() {
const router = useRouter()
const [status, setStatus] = useState<'loading' | 'connected' | 'disconnected'>('loading');
const [store, setStore] = useState<StoreFromAPI | null>(null);
const [toast, setToast] = useState<string>('');
const [connecting, setConnecting] = useState(false);
const [connectingAnother, setConnectingAnother] = useState(false);
const [payment, setPayment] = useState<any>(null);
const returnUrl = useMemo(() => {
if (typeof window === 'undefined') return '';
return `${window.location.origin}${window.location.pathname}`;
}, []);
useEffect(() => {
const role = localStorage.getItem("user_role");
const sessionId = localStorage.getItem("payment_session");
// ✅ Admins and Partners can access directly (skip payment check)
if (role === "admin" || role === "partner") {
return;
}
// 🚫 If no payment session, redirect to pricing
if (!sessionId) {
router.push("/pricing");
return;
}
// ✅ Otherwise, check payment details
const fetchPaymentDetails = async () => {
try {
const res: any = await axios.get(
"https://ebay.backend.data4autos.com/api/payment/details",
{ params: { session_id: sessionId } }
);
setPayment(res.data.payment);
} catch (err) {
console.error("Error fetching payment details:", err);
}
};
fetchPaymentDetails();
}, [router]);
useEffect(() => {
(async () => {
try {
// await getAccessToken_client().catch(() => null);
const userid = sessionStorage.getItem('USERID') || undefined;
if (!userid) {
setStatus('disconnected');
setToast('No user session found. Please sign in.');
return;
}
const res = await fetch(
'https://ebay.backend.data4autos.com/api/motorstate/auth/ebay/store/checkstorestatus',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userid }),
cache: 'no-store',
}
);
const data: ApiResp = await read(res);
if (data?.code === 'STORE_PRESENT' && data?.store) {
setStore(data.store);
setStatus('connected');
} else {
setStatus('disconnected');
}
} catch {
setStatus('disconnected');
}
})();
}, []);
const OAUTH_ENDPOINT = 'https://ebay.backend.data4autos.com/api/ebay/oauth/motorstate/login';
const startOauth = () => {
setConnecting(true);
const url = `${OAUTH_ENDPOINT}?return_url=${encodeURIComponent(returnUrl)}`;
window.location.href = url;
};
const startOauthAnother = () => {
setConnectingAnother(true);
const url = `${OAUTH_ENDPOINT}?return_url=${encodeURIComponent(returnUrl)}&add_another=1`;
window.location.href = url;
};
const { subtitle, logoUrl, desc, link, lastOpen } = useMemo(() => {
if (!store)
return { subtitle: '', logoUrl: '', desc: '', link: '', lastOpen: '—' };
return {
subtitle: store.store_name || store.store_url_path,
logoUrl: store.store_logo_url,
desc: store.store_description,
link: store.store_url,
lastOpen: safeDateFormat(store.store_last_opened_time || store.store_last_opened_time_raw),
};
}, [store]);
return (
<div className="min-h-[83vh] flex items-center justify-center bg-gradient-to-br from-[#00d1ff]/10 via-white to-[#00d1ff]/20 p-6">
<div className="max-w-2xl w-full bg-white shadow-xl rounded-2xl p-8 border border-blue-100">
{toast && (
<div className="mb-4 text-sm text-blue-800 bg-blue-50 border border-blue-200 rounded-lg px-4 py-2">
{toast}
</div>
)}
{status === 'loading' && (
<div className="text-center space-y-3">
<div className="inline-flex items-center gap-2 bg-blue-50 text-blue-600 px-4 py-1 rounded-full text-sm">
<span className="animate-spin"></span> Checking your store status
</div>
<h1 className="text-2xl font-semibold text-gray-800">Verifying eBay connection</h1>
</div>
)}
{status === 'connected' && (
<div className="space-y-5">
<div className="flex items-center justify-center gap-2 bg-green-50 text-green-700 border border-green-200 rounded-full px-4 py-1 w-fit mx-auto text-sm">
Connected
</div>
<h1 className="text-center text-3xl font-bold text-gray-900">
eBay connected successfully! 🎉
</h1>
<div className="border border-gray-200 rounded-xl shadow-inner p-6 bg-gradient-to-b from-white to-gray-50">
<div className="flex items-center gap-4 mb-4">
{logoUrl ? (
<img
src={logoUrl}
alt="Store Logo"
className="w-16 h-16 rounded-lg border border-gray-200 object-cover"
/>
) : (
<div className="w-16 h-16 bg-gray-100 rounded-lg flex items-center justify-center text-xl font-bold text-gray-600">
{(subtitle || 'S').slice(0, 1)}
</div>
)}
<div>
<h2 className="text-lg font-semibold text-gray-800">{subtitle}</h2>
<p className="text-sm text-gray-500">
Last opened: <span className="font-medium">{lastOpen}</span>
</p>
</div>
</div>
{desc && <p className="text-gray-600 mb-4">{desc}</p>}
<div className="flex flex-wrap gap-3">
{link && (
<a
href={link}
target="_blank"
rel="noopener noreferrer"
className="bg-[#00d1ff] text-white px-4 py-2 rounded-lg font-semibold shadow hover:bg-[#00bce6] transition"
>
Visit eBay Store
</a>
)}
<a
href="/"
className="px-4 py-2 border border-[#00d1ff] text-[#00d1ff] rounded-lg font-semibold hover:bg-[#00d1ff] hover:text-white transition"
>
Go to Dashboard
</a>
</div>
<div className="mt-6">
<button
onClick={startOauthAnother}
disabled={connectingAnother}
className={`w-full px-4 py-2 rounded-lg font-semibold transition ${connectingAnother
? 'bg-blue-300 cursor-not-allowed'
: 'bg-[#00d1ff] hover:bg-[#00bce6] text-white'
}`}
>
{connectingAnother ? 'Redirecting…' : 'Connect another eBay store'}
</button>
<p className="text-sm text-gray-500 mt-2">
Use this to link an additional eBay store.
</p>
</div>
</div>
</div>
)}
{status === 'disconnected' && (
<div className="space-y-4 text-center">
<h1 className="text-3xl font-bold text-gray-900">eBay Settings</h1>
<p className="text-gray-600">
Connect your eBay store to enable product sync, inventory updates, and order flow.
</p>
<button
onClick={startOauth}
disabled={connecting}
className={`w-full px-4 py-2 rounded-lg font-semibold transition ${connecting
? 'bg-blue-300 cursor-not-allowed'
: 'bg-[#00d1ff] hover:bg-[#00bce6] text-white'
}`}
>
{connecting ? 'Redirecting to eBay…' : 'Connect your eBay store'}
</button>
<p className="text-sm text-gray-500">
Youll be redirected to eBay to authorize access, then returned here.
</p>
</div>
)}
</div>
</div>
);
}