This commit is contained in:
Vassshhh
2025-08-23 16:26:47 +07:00
parent b1ae4c5d82
commit 4ec28f7089
2 changed files with 48 additions and 68 deletions

View File

@@ -38,7 +38,7 @@ function HomePage({
if (tab === 'products') scrollToProduct();
if (tab === 'academy') scrollToCourse();
}, [productSectionRef, courseSectionRef]);
}, [productSectionRef.current, courseSectionRef.current]);
return (
<>
@@ -194,31 +194,42 @@ function App() {
if (!productModalRequest || !subscriptions) return;
const { productId, authorizedUri, unauthorizedUri } = productModalRequest;
console.log(subscriptions)
const hasAccess = subscriptions && subscriptions.some(
sub => sub.product_id === productId || sub.product_parent_id === productId
);
console.log(hasAccess)
console.log("hasAccess:", hasAccess);
if (hasAccess) {
if (authorizedUri) {
let finalUri = decodeURIComponent(authorizedUri);
const token = document.cookie.match(/(^| )token=([^;]+)/)?.[2];
if (finalUri.includes('token=null') || finalUri.includes('token=')) {
// --- ambil product_name distinct berdasarkan productId/parent ---
const relatedSubs = subscriptions.filter(
sub => sub.product_id === productId || sub.product_parent_id === productId
);
const distinctNames = [...new Set(relatedSubs.map(sub => sub.product_name))];
if (distinctNames.length > 1) {
// lebih dari 1 → pakai dashboard=true
const url = new URL(finalUri);
url.searchParams.set('token', token || '');
url.searchParams.set("token", token || "");
finalUri = url.toString();
} else if (distinctNames.length === 1) {
// hanya 1 → tambahkan productName=<nama> sebelum query lain
const url = new URL(finalUri);
url.searchParams.set("token", token || "");
url.searchParams.set("productName", distinctNames[0]);
finalUri = url.toString();
}
window.location.href = finalUri;
}
else {// Assuming you already imported processProducts from './processProducts'
} else {
// fallback ambil detail produk via fetch
fetch('https://bot.kediritechnopark.com/webhook/store-production/products', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
itemsId: [productId],
withChildren: true,
@@ -227,9 +238,7 @@ function App() {
.then(res => res.json())
.then(data => {
if (Array.isArray(data) && data.length > 0) {
// Process the raw data to group children under their parent
const processed = processProducts(data);
// Set the first product (which should be the parent with children nested)
setSelectedProduct(processed[0]);
setShowedModal('product');
}
@@ -240,12 +249,9 @@ function App() {
if (unauthorizedUri) {
window.location.href = decodeURIComponent(unauthorizedUri);
} else {
fetch('https://bot.kediritechnopark.com/webhook/store-production/products', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
itemsId: [productId],
withChildren: true,
@@ -254,9 +260,7 @@ function App() {
.then(res => res.json())
.then(data => {
if (Array.isArray(data) && data.length > 0) {
// Process the raw data to group children under their parent
const processed = processProducts(data);
// Set the first product (which should be the parent with children nested)
setSelectedProduct(processed[0]);
setShowedModal('product');
}

View File

@@ -1,7 +1,6 @@
import React, { useState, useEffect } from "react";
import { Container, Row, Col, Card, Button, Tabs, Tab, Form } from "react-bootstrap";
import { useNavigate } from "react-router-dom";
import processProducts from '../../helper/processProducts';
const Dashboard = ({
subscriptions,
@@ -28,7 +27,6 @@ const Dashboard = ({
}
});
// 🔹 Handle input settings
const handleSettingsChange = (field, value, nested = false) => {
if (nested) {
setSettings((prev) => ({
@@ -40,7 +38,6 @@ const Dashboard = ({
}
};
// 🔹 Save profile
const saveSettings = () => {
fetch("https://bot.kediritechnopark.com/webhook-test/user-production/data", {
method: "PUT",
@@ -52,7 +49,6 @@ const Dashboard = ({
.catch((err) => alert("Error updating settings: " + err));
};
// 🔹 Group subscriptions
const groupSubscriptionsByProductName = (subs) => {
const result = {};
subs.forEach((sub) => {
@@ -82,7 +78,6 @@ const Dashboard = ({
return result;
};
// 🔹 Fetch produk berdasarkan subscription
useEffect(() => {
if (!subscriptions) return;
@@ -96,54 +91,46 @@ const Dashboard = ({
})
.then((res) => res.json())
.then((data) => {
console.log(data)
const dataMap = {};
data.forEach((item) => {
dataMap[item.id] = { ...item, children: [] };
});
// Masukkan anak-anak ke parent-nya
data.forEach((item) => {
if (item.sub_product_of && dataMap[item.sub_product_of]) {
dataMap[item.sub_product_of].children.push(dataMap[item.id]);
}
});
console.log(dataMap)
const enrichedData = Object.values(groupedSubs)
.filter((group) => data.some((p) => p.id === group.product_id))
.map((group) => {
const productData = data.find((p) => p.id === group.product_id);
let image = productData?.image || "";
let description = productData?.description || "";
let site_url = productData?.site_url || "";
if (!image && productData?.sub_product_of) {
console.log(productData)
let realProductName = productData?.name || "";
if (!description && productData?.sub_product_of) {
const parent = data.find((p) => p.id === productData.sub_product_of);
image = parent?.image || "";
description = parent?.description || "";
site_url = parent?.site_url || "";
realProductName = parent.name;
}
return {
executeCheckout: group.product_name,
id: group.product_id,
name: group.product_name,
realProductName,
type: productData?.type || "product",
image,
description,
site_url,
price: productData?.price || 0,
currency: productData?.currency || "IDR",
duration: productData?.duration || {},
sub_product_of: productData?.sub_product_of || null,
is_visible: productData?.is_visible ?? true,
unit_type: productData?.unit_type || group.unit_type,
quantity: group.quantity,
end_date: group.end_date,
children: dataMap[productData?.sub_product_of]?.children || []
};
});
console.log(enrichedData)
setProducts(enrichedData);
})
.catch((err) => console.error("Fetch error:", err));
@@ -151,18 +138,13 @@ const Dashboard = ({
return (
<Container fluid className="mt-4">
<Tabs
activeKey={activeTab}
onSelect={(k) => setActiveTab(k)}
className="mb-3"
>
{/* Produk Saya */}
<Tabs activeKey={activeTab} onSelect={(k) => setActiveTab(k)} className="mb-3">
<Tab eventKey="products" title="Produk Saya">
<Row>
{products.map((product) => (
<Col md={4} key={product.id} className="mb-4">
{products.map((product, i) => (
<Col md={4} key={i} className="mb-4">
<Card
className={`h-100 shadow-sm ${hoveredCard === product.name ? "border-primary" : ""}`}
className={`h-100 shadow-sm p-2 ${hoveredCard === product.name ? "border-primary" : ""}`}
onMouseEnter={() => setHoveredCard(product.name)}
onMouseLeave={() => setHoveredCard(null)}
onClick={() => {
@@ -170,27 +152,25 @@ const Dashboard = ({
setShowedModal("product");
}}
>
{product.image && (
<Card.Img variant="top" src={product.image} />
)}
<Card.Body>
<Card.Title>{product.name.split("%%%")[0]}</Card.Title>
<Card.Text>{product.description}</Card.Text>
<Card.Title>
📦 {product.name.split("%%%")[0] + ' - ' + product.realProductName}
</Card.Title>
<Card.Text style={{ fontSize: "0.9rem", color: "#555" }}>
{product.description}
</Card.Text>
</Card.Body>
<Card.Footer>
<Card.Footer className="d-flex justify-content-between align-items-center">
<small className="text-muted">
{product.unit_type === "duration"
? `Valid until: ${product.end_date
? new Date(product.end_date).toLocaleDateString()
: "N/A"
}`
: `SISA TOKEN ${product.quantity || 0}`}
? `Valid until: ${product.end_date ? new Date(product.end_date).toLocaleDateString() : "N/A"}`
: `SISA TOKEN: ${product.quantity || 0}`}
</small>
<Button
variant="primary"
variant="outline-primary"
size="sm"
className="float-end"
onClick={() => {
onClick={(e) => {
e.stopPropagation();
setSelectedProduct(product);
setShowedModal("product");
setWillDo("checkout");
@@ -203,21 +183,19 @@ const Dashboard = ({
</Col>
))}
{/* Tambah produk baru */}
<Col md={4} className="mb-4">
<Card
className={`h-100 shadow-sm text-center align-items-center justify-content-center`}
className="h-100 shadow-sm d-flex justify-content-center align-items-center text-center"
onClick={() => navigate("/?tab=products")}
>
<Card.Body>
<h5>+ Tambah produk baru</h5>
<h5 style={{ color: "#007bff" }}> Tambah Produk Baru</h5>
</Card.Body>
</Card>
</Col>
</Row>
</Tab>
{/* Profil Pengguna */}
<Tab eventKey="settings" title="Profil Pengguna">
<Form>
<Row>
@@ -232,7 +210,6 @@ const Dashboard = ({
/>
</Form.Group>
</Col>
<Col md={6}>
<Form.Group className="mb-3">
<Form.Label>Email</Form.Label>
@@ -333,7 +310,6 @@ const Dashboard = ({
</Form>
</Tab>
{/* Orders */}
<Tab eventKey="orders" title="Pembelian">
<h4>My Orders</h4>
<p>Orders list will be displayed here.</p>