ok
This commit is contained in:
12
src/App.js
12
src/App.js
@@ -10,9 +10,9 @@ import ProductSection from './components/ProductSection';
|
|||||||
import AcademySection from './components/AcademySection';
|
import AcademySection from './components/AcademySection';
|
||||||
import AboutUsSection from './components/AboutUsSection';
|
import AboutUsSection from './components/AboutUsSection';
|
||||||
// KnowledgeBaseSection hidden temporarily
|
// KnowledgeBaseSection hidden temporarily
|
||||||
// import KnowledgeBaseSection from './components/KnowledgeBaseSection';
|
import KnowledgeBaseSection from './components/KnowledgeBaseSection';
|
||||||
// ClientsSection hidden temporarily
|
// ClientsSection hidden temporarily
|
||||||
// import ClientsSection from './components/ClientsSection';
|
import ClientsSection from './components/ClientsSection';
|
||||||
import FAQSection from './components/FAQSection';
|
import FAQSection from './components/FAQSection';
|
||||||
import Footer from './components/Footer';
|
import Footer from './components/Footer';
|
||||||
import ProductDetailPage from './components/ProductDetailPage';
|
import ProductDetailPage from './components/ProductDetailPage';
|
||||||
@@ -36,8 +36,8 @@ function HomePage({
|
|||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const tab = params.get('tab');
|
const tab = params.get('tab');
|
||||||
|
|
||||||
if(tab === 'products') scrollToProduct();
|
if (tab === 'products') scrollToProduct();
|
||||||
if(tab === 'academy') scrollToCourse();
|
if (tab === 'academy') scrollToCourse();
|
||||||
}, [productSectionRef, courseSectionRef]);
|
}, [productSectionRef, courseSectionRef]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -165,8 +165,8 @@ function App() {
|
|||||||
// Jika sudah login, tidak langsung fetch di sini — akan diproses saat subscriptions tersedia
|
// Jika sudah login, tidak langsung fetch di sini — akan diproses saat subscriptions tersedia
|
||||||
}
|
}
|
||||||
|
|
||||||
if(tab === 'products') scrollToProduct();
|
if (tab === 'products') scrollToProduct();
|
||||||
if(tab === 'academy') scrollToCourse();
|
if (tab === 'academy') scrollToCourse();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|||||||
@@ -105,6 +105,10 @@ const LoginRegister = ({setShowedModal}) => {
|
|||||||
window.history.replaceState({}, '', newUrl);
|
window.history.replaceState({}, '', newUrl);
|
||||||
setShowedModal('product');
|
setShowedModal('product');
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const modalType = params.get('modal');
|
||||||
|
if(!modalType)
|
||||||
navigate('/dashboard');
|
navigate('/dashboard');
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,34 +23,14 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin
|
|||||||
requestLogin('checkout');
|
requestLogin('checkout');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (product.type == 'product') {
|
|
||||||
|
if (product.type === 'product') {
|
||||||
const hasMatchingSubscription = Array.isArray(subscriptions) &&
|
const hasMatchingSubscription = Array.isArray(subscriptions) &&
|
||||||
subscriptions.some(sub =>
|
subscriptions.some(sub =>
|
||||||
String(sub.product_id) === String(product.id) || String(sub.product_parent_id) === String(product.id)
|
String(sub.product_id) === String(product.id) || String(sub.product_parent_id) === String(product.id)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Always show children selector first if product has children
|
// ✅ Check subscription first
|
||||||
if (product.children && product.children.length > 0) {
|
|
||||||
setShowChildSelector(true);
|
|
||||||
|
|
||||||
if (hasMatchingSubscription) {
|
|
||||||
const matching = subscriptions.filter(sub =>
|
|
||||||
String(sub.product_id) === String(product.id) || String(sub.product_parent_id) === String(product.id)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (matching.length > 0) {
|
|
||||||
// ✅ Select only the first for each product_name
|
|
||||||
const uniqueByName = Array.from(
|
|
||||||
new Map(matching.map(sub => [sub.product_name, sub])).values()
|
|
||||||
);
|
|
||||||
|
|
||||||
setMatchingSubscriptions(uniqueByName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No children, but has subscription match
|
|
||||||
if (hasMatchingSubscription) {
|
if (hasMatchingSubscription) {
|
||||||
const matching = subscriptions.filter(sub =>
|
const matching = subscriptions.filter(sub =>
|
||||||
String(sub.product_id) === String(product.id) || String(sub.product_parent_id) === String(product.id)
|
String(sub.product_id) === String(product.id) || String(sub.product_parent_id) === String(product.id)
|
||||||
@@ -64,55 +44,59 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin
|
|||||||
setMatchingSubscriptions(uniqueByName);
|
setMatchingSubscriptions(uniqueByName);
|
||||||
setShowSubscriptionSelector(true);
|
setShowSubscriptionSelector(true);
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
const itemsParam = JSON.stringify([product.id]);
|
const itemsParam = JSON.stringify([product.id]);
|
||||||
window.location.href = `https://checkout.kediritechnopark.com/?token=${token}&itemsId=${itemsParam}&set_name=${product.name}&redirect_uri=https://kediritechnopark.com/products&redirect_failed=https://kediritechnopark.com`;
|
window.location.href = `https://checkout.kediritechnopark.com/?token=${token}&itemsId=${itemsParam}&set_name=${product.name}&redirect_uri=https://kediritechnopark.com/products&redirect_failed=https://kediritechnopark.com`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ✅ If no subscription → ask for new product name
|
||||||
setShowNamingInput(true);
|
setShowNamingInput(true);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
// No children, no matching subscription
|
|
||||||
|
// Fallback: direct checkout
|
||||||
const itemsParam = JSON.stringify([product.id]);
|
const itemsParam = JSON.stringify([product.id]);
|
||||||
window.location.href = `https://checkout.kediritechnopark.com/?token=${token}&itemsId=${itemsParam}&redirect_uri=https://kediritechnopark.com/products&redirect_failed=https://kediritechnopark.com`;
|
window.location.href = `https://checkout.kediritechnopark.com/?token=${token}&itemsId=${itemsParam}&redirect_uri=https://kediritechnopark.com/products&redirect_failed=https://kediritechnopark.com`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ✅ Confirm child selection (final step after naming)
|
||||||
const onConfirmChildren = () => {
|
const onConfirmChildren = () => {
|
||||||
if (matchingSubscriptions.length > 0 && !product.executeCheckout) {
|
if (selectedChildIds.length === 0) {
|
||||||
setShowChildSelector(false);
|
alert('Pilih minimal satu produk');
|
||||||
setShowSubscriptionSelector(true);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!product.executeCheckout){
|
|
||||||
setShowChildSelector(false);
|
|
||||||
setShowNamingInput(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
const tokenCookie = document.cookie.split('; ').find(row => row.startsWith('token='));
|
const tokenCookie = document.cookie.split('; ').find(row => row.startsWith('token='));
|
||||||
const token = tokenCookie ? tokenCookie.split('=')[1] : '';
|
const token = tokenCookie ? tokenCookie.split('=')[1] : '';
|
||||||
|
|
||||||
if (selectedChildIds.length === 0) {
|
const encodedName = encodeURIComponent(customName.trim() || product.name);
|
||||||
alert('Pilih minimal satu produk');
|
const itemsParam = JSON.stringify(selectedChildIds);
|
||||||
return;
|
|
||||||
}
|
window.location.href = `https://checkout.kediritechnopark.com/?token=${token}&itemsId=${itemsParam}&new_name=${encodedName}&redirect_uri=https://kediritechnopark.com/products&redirect_failed=https://kediritechnopark.com`;
|
||||||
const encodedName = encodeURIComponent(product.executeCheckout);
|
|
||||||
const itemsParam = selectedChildIds.length > 0 ? JSON.stringify(selectedChildIds) : 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`;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ✅ User sets name first → then if product has children, show child selector
|
||||||
const onFinalCheckoutNewProduct = () => {
|
const onFinalCheckoutNewProduct = () => {
|
||||||
if (!customName.trim()) {
|
if (!customName.trim()) {
|
||||||
alert('Nama produk tidak boleh kosong');
|
alert('Nama produk tidak boleh kosong');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (product.children && product.children.length > 0) {
|
||||||
|
// don’t redirect yet → go to child selector
|
||||||
|
setShowSubscriptionSelector(false);
|
||||||
|
|
||||||
|
setShowNamingInput(false);
|
||||||
|
setShowChildSelector(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no children → go straight to checkout
|
||||||
const tokenCookie = document.cookie.split('; ').find(row => row.startsWith('token='));
|
const tokenCookie = document.cookie.split('; ').find(row => row.startsWith('token='));
|
||||||
const token = tokenCookie ? tokenCookie.split('=')[1] : '';
|
const token = tokenCookie ? tokenCookie.split('=')[1] : '';
|
||||||
const itemsParam = selectedChildIds.length > 0 ? JSON.stringify(selectedChildIds) : JSON.stringify([product.id]);
|
const itemsParam = JSON.stringify([product.id]);
|
||||||
const encodedName = encodeURIComponent(customName.trim());
|
const encodedName = encodeURIComponent(customName.trim());
|
||||||
|
|
||||||
window.location.href = `https://checkout.kediritechnopark.com/?token=${token}&itemsId=${itemsParam}&new_name=${encodedName}&redirect_uri=https://kediritechnopark.com/products&redirect_failed=https://kediritechnopark.com`;
|
window.location.href = `https://checkout.kediritechnopark.com/?token=${token}&itemsId=${itemsParam}&new_name=${encodedName}&redirect_uri=https://kediritechnopark.com/products&redirect_failed=https://kediritechnopark.com`;
|
||||||
@@ -145,13 +129,14 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin
|
|||||||
if (willDo === 'checkout') {
|
if (willDo === 'checkout') {
|
||||||
onCheckout();
|
onCheckout();
|
||||||
}
|
}
|
||||||
if(setWillDo) setWillDo(''); // Reset willDo after handling
|
if (setWillDo) setWillDo('');
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const priceColor = product.price === 0 ? '#059669' : '#2563eb';
|
const priceColor = product.price === 0 ? '#059669' : '#2563eb';
|
||||||
console.log(product)
|
|
||||||
return (
|
return (
|
||||||
<div className={styles.container}>
|
<div className={styles.container}>
|
||||||
|
{/* Default view */}
|
||||||
{!showChildSelector && !showSubscriptionSelector && !showNamingInput && (
|
{!showChildSelector && !showSubscriptionSelector && !showNamingInput && (
|
||||||
<>
|
<>
|
||||||
<div className={styles.image} style={{ backgroundImage: `url(${product.image})` }}></div>
|
<div className={styles.image} style={{ backgroundImage: `url(${product.image})` }}></div>
|
||||||
@@ -184,11 +169,11 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin
|
|||||||
sub.product_id === product.id || sub.product_parent_id === product.id
|
sub.product_id === product.id || sub.product_parent_id === product.id
|
||||||
) && product.end_date ? 'Perpanjang' : 'Checkout'}
|
) && product.end_date ? 'Perpanjang' : 'Checkout'}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Child selector */}
|
||||||
{showChildSelector && (
|
{showChildSelector && (
|
||||||
<div className={styles.childSelector}>
|
<div className={styles.childSelector}>
|
||||||
<h3>Pilih Paket</h3>
|
<h3>Pilih Paket</h3>
|
||||||
@@ -198,25 +183,16 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin
|
|||||||
type="radio"
|
type="radio"
|
||||||
value={child.id}
|
value={child.id}
|
||||||
checked={selectedChildIds.includes(child.id)}
|
checked={selectedChildIds.includes(child.id)}
|
||||||
onChange={e => {
|
onChange={() => setSelectedChildIds([child.id])}
|
||||||
const checked = e.target.checked;
|
|
||||||
setSelectedChildIds(prev =>
|
|
||||||
checked ? [...prev, child.id] : prev.filter(id => id !== child.id)
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<div>
|
<div> {child.name}</div>
|
||||||
{child.name}
|
<div>Rp {parseInt(child.price || 0).toLocaleString('id-ID')}</div>
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
Rp {parseInt(child.price || 0).toLocaleString('id-ID')}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
))}
|
))}
|
||||||
<div className={styles.buttonGroup}>
|
<div className={styles.buttonGroup}>
|
||||||
<button className={styles.button} onClick={() => setShowChildSelector(false)}>
|
<button className={styles.button} onClick={() => { setShowChildSelector(false); setShowNamingInput(true); }}>
|
||||||
Kembali
|
Kembali
|
||||||
</button>
|
</button>
|
||||||
<button className={styles.button} onClick={onConfirmChildren}>
|
<button className={styles.button} onClick={onConfirmChildren}>
|
||||||
@@ -226,17 +202,18 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Subscription selector */}
|
||||||
{showSubscriptionSelector && !showNamingInput && (
|
{showSubscriptionSelector && !showNamingInput && (
|
||||||
<div className={styles.childSelector}>
|
<div className={styles.childSelector}>
|
||||||
<h5>Kamu sudah punya produk ini</h5>
|
<h5>Kamu sudah punya produk ini</h5>
|
||||||
<div className={styles.childProduct} onClick={()=>{setShowedModal('');navigate('/dashboard')}}>
|
<div className={styles.childProduct} onClick={() => { setShowedModal(''); navigate('/dashboard') }}>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<div>Perpanjang produk ini</div>
|
<div>Perpanjang produk ini</div>
|
||||||
<div>➔</div>
|
<div>➔</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<h6>Atau</h6>
|
<h6>Atau</h6>
|
||||||
<label className={styles.childProduct} onClick={()=>{setSelectedSubscriptionId(0); onConfirmSelector();}}>
|
<label className={styles.childProduct} onClick={() => { setSelectedSubscriptionId(0); onConfirmSelector(); }}>
|
||||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||||
<div>Tambah {product.name.split('%%%')[0]} baru</div>
|
<div>Tambah {product.name.split('%%%')[0]} baru</div>
|
||||||
<div>➔</div>
|
<div>➔</div>
|
||||||
@@ -250,6 +227,7 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Naming input */}
|
||||||
{showNamingInput && (
|
{showNamingInput && (
|
||||||
<div className={styles.childSelector}>
|
<div className={styles.childSelector}>
|
||||||
<h5>Buat {product.name.split('%%%')[0]} Baru</h5>
|
<h5>Buat {product.name.split('%%%')[0]} Baru</h5>
|
||||||
@@ -262,47 +240,20 @@ const ProductDetail = ({ willDo, setWillDo, subscriptions, product, requestLogin
|
|||||||
style={{ width: '100%', padding: '8px', marginBottom: '16px', borderRadius: '10px' }}
|
style={{ width: '100%', padding: '8px', marginBottom: '16px', borderRadius: '10px' }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{
|
|
||||||
matchingSubscriptions.some(
|
|
||||||
(sub) => sub.product_name === `${product.name}@${customName}`
|
|
||||||
) && (
|
|
||||||
<p style={{ color: 'red', marginBottom: '10px' }}>
|
|
||||||
Nama produk sudah digunakan.
|
|
||||||
</p>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
<div className={styles.buttonGroup}>
|
<div className={styles.buttonGroup}>
|
||||||
<button
|
<button className={styles.button} onClick={() => setShowNamingInput(false)}>
|
||||||
className={styles.button}
|
|
||||||
onClick={() => {
|
|
||||||
setShowNamingInput(false);
|
|
||||||
|
|
||||||
const hasMatchingSubscription = Array.isArray(subscriptions) &&
|
|
||||||
subscriptions.some(sub =>
|
|
||||||
String(sub.product_id) === String(product.id) || String(sub.product_parent_id) === String(product.id)
|
|
||||||
);
|
|
||||||
if (hasMatchingSubscription) setShowSubscriptionSelector(true);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Kembali
|
Kembali
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={styles.button}
|
className={styles.button}
|
||||||
onClick={onFinalCheckoutNewProduct}
|
onClick={onFinalCheckoutNewProduct}
|
||||||
disabled={
|
disabled={customName.trim() === ''}
|
||||||
customName.trim() === '' ||
|
|
||||||
matchingSubscriptions.some(
|
|
||||||
(sub) => sub.product_name === `${product.name}@${customName}`
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
Checkout
|
Lanjut
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -91,7 +91,6 @@
|
|||||||
.carouselContainer {
|
.carouselContainer {
|
||||||
position: relative;
|
position: relative;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 0 56px;
|
|
||||||
min-height: 380px; /* compact */
|
min-height: 380px; /* compact */
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +132,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.carouselContainer {
|
.carouselContainer {
|
||||||
padding: 0 60px;
|
|
||||||
min-height: 420px;
|
min-height: 420px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,7 +165,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.carouselContainer {
|
.carouselContainer {
|
||||||
padding: 0 50px;
|
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -210,7 +207,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.carouselContainer {
|
.carouselContainer {
|
||||||
padding: 0 40px;
|
|
||||||
min-height: 370px;
|
min-height: 370px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +249,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.carouselContainer {
|
.carouselContainer {
|
||||||
padding: 0 30px;
|
|
||||||
min-height: 320px;
|
min-height: 320px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,7 +291,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.carouselContainer {
|
.carouselContainer {
|
||||||
padding: 0 25px;
|
|
||||||
min-height: 300px;
|
min-height: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user