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

View File

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