From b1ae4c5d826da0b83b81c3c62eb5474e75ea99d6 Mon Sep 17 00:00:00 2001 From: Kediri Technopark Date: Sat, 23 Aug 2025 08:06:05 +0000 Subject: [PATCH] ok --- src/components/ProductDetailPage.js | 110 ++++++++++++++++++++++------ 1 file changed, 89 insertions(+), 21 deletions(-) diff --git a/src/components/ProductDetailPage.js b/src/components/ProductDetailPage.js index 8ef6b04..a83168c 100644 --- a/src/components/ProductDetailPage.js +++ b/src/components/ProductDetailPage.js @@ -11,10 +11,60 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin const [showSubscriptionSelector, setShowSubscriptionSelector] = useState(false); const [showNamingInput, setShowNamingInput] = useState(false); - const [customName, setCustomName] = useState(''); const navigate = useNavigate(); + const [customName, setCustomName] = useState(''); + const [status, setStatus] = useState('idle'); // 'idle' | 'checking' | 'available' | 'unavailable' | 'error' + + + const tokenCookie = document.cookie.split('; ').find(row => row.startsWith('token=')); + const token = tokenCookie ? tokenCookie.split('=')[1] : ''; + + + // Helper panggil API kamu (GET + token header) + async function checkProductAvailability(name, token) { + const url = `https://bot.kediritechnopark.com/webhook/store_production/check_p_availability?productId=${product.id}&name=${encodeURIComponent(name)}`; + const res = await fetch(url, { + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + Accept: 'application/json', + }, + }); + if (!res.ok) throw new Error(`Server error ${res.status}`); + const data = await res.json(); // expected: { allowed: true|false } + return Boolean(data.allowed); + } + // Auto check saat user mengetik (debounce) + useEffect(() => { + if (product.unique_name == false) return; + + const name = customName.trim(); + if (!name) { + setStatus('idle'); + return; + } + let cancelled = false; + setStatus('checking'); + + const t = setTimeout(async () => { + try { + const allowed = await checkProductAvailability(name, token); + if (cancelled) return; + setStatus(allowed ? 'available' : 'unavailable'); + } catch (e) { + if (cancelled) return; + setStatus('error'); + } + }, 500); + + return () => { + cancelled = true; + clearTimeout(t); + }; + }, [customName, token]); + const onCheckout = () => { const tokenCookie = document.cookie.split('; ').find(row => row.startsWith('token=')); const token = tokenCookie ? tokenCookie.split('=')[1] : ''; @@ -29,7 +79,7 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin subscriptions.some(sub => String(sub.product_id) === String(product.id) || String(sub.product_parent_id) === String(product.id) ); - console.log(hasMatchingSubscription) + // ✅ Check subscription first if (hasMatchingSubscription) { const matching = subscriptions.filter(sub => @@ -86,7 +136,7 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin if (product.children && product.children.length > 0) { // don’t redirect yet → go to child selector - setShowSubscriptionSelector(false); + setShowSubscriptionSelector(false); setShowNamingInput(false); setShowChildSelector(true); @@ -126,26 +176,38 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin }; useEffect(() => { - if (!product.executeCheckout && willDo === 'checkout') { + if (willDo === 'checkout') { onCheckout(); } - else if (product.children && product.children.length > 0) { - setShowChildSelector(true); - } - else { - - const tokenCookie = document.cookie.split('; ').find(row => row.startsWith('token=')); - const token = tokenCookie ? tokenCookie.split('=')[1] : ''; - const encodedName = encodeURIComponent(product.name); - const itemsParam = JSON.stringify([product.id]); - - window.location.href = `https://checkout.kediritechnopark.com/?token=${token}&itemsId=${itemsParam}&set_name=${encodedName}&redirect_uri=https://kediritechnopark.com/products&redirect_failed=https://kediritechnopark.com`; - } if (setWillDo) setWillDo(''); }, []); const priceColor = product.price === 0 ? '#059669' : '#2563eb'; + // Komponen kecil untuk menampilkan status teks + const StatusLine = () => { + if (status === 'idle') return null; + const map = { + checking: 'Memeriksa…', + available: 'Nama tersedia', + unavailable: 'Nama tidak tersedia', + error: 'Gagal memeriksa. Coba lagi.', + }; + const color = + status === 'available' + ? '#16a34a' + : status === 'unavailable' + ? '#dc2626' + : status === 'checking' + ? '#2563eb' + : '#6b7280'; + return ( +
+ {map[status]} +
+ ); + }; + return (
{/* Default view */} @@ -239,8 +301,8 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin
)} - {/* Naming input */} + {showNamingInput && (
Buat {product.name.split('%%%')[0]} Baru
@@ -249,18 +311,24 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin placeholder="Nama produk..." className={styles.input} value={customName} - onChange={(e) => setCustomName(e.target.value)} - style={{ width: '100%', padding: '8px', marginBottom: '16px', borderRadius: '10px' }} + onChange={(e) => { + const value = e.target.value.replace(/\s+/g, '-'); // Ganti spasi dengan - + setCustomName(value); + }} + style={{ width: '100%', padding: '8px', marginBottom: '8px', borderRadius: '10px' }} /> -
+ {product.unique_name && } + +