diff --git a/src/App.js b/src/App.js index 452f007..013bdd8 100644 --- a/src/App.js +++ b/src/App.js @@ -124,6 +124,7 @@ function App() { .catch(err => console.error('Fetch error:', err)); } }, []); + useEffect(() => { const params = new URLSearchParams(window.location.search); const modalType = params.get('modal'); @@ -146,6 +147,7 @@ function App() { // Jika sudah login, tidak langsung fetch di sini — akan diproses saat subscriptions tersedia } }, []); + useEffect(() => { const params = new URLSearchParams(window.location.search); const modalType = params.get('modal'); @@ -167,12 +169,15 @@ function App() { }, []); useEffect(() => { - if (!productModalRequest) return; + console.log(subscriptions) + if (!productModalRequest || !subscriptions) return; const { productId, authorizedUri, unauthorizedUri } = productModalRequest; - - const hasAccess = subscriptions && subscriptions.some(sub => sub.product_id === productId); - + console.log(subscriptions) + const hasAccess = subscriptions && subscriptions.some( + sub => sub.product_id === productId || sub.product_parent_id === productId + ); + console.log(hasAccess) if (hasAccess) { if (authorizedUri) { let finalUri = decodeURIComponent(authorizedUri); diff --git a/src/components/Dashboard.js b/src/components/Dashboard.js index 1db87e6..075a20c 100644 --- a/src/components/Dashboard.js +++ b/src/components/Dashboard.js @@ -1,8 +1,20 @@ import React, { useState, useEffect } from 'react'; import { TrendingUp, TrendingDown, DollarSign, ShoppingCart, Users } from 'lucide-react'; import styles from './Dashboard.module.css'; +import processProducts from '../helper/processProducts'; + const Dashboard = () => { + const [unitType, setUnitType] = useState('duration'); + const [durationUnit, setDurationUnit] = useState('day'); + const [availableTypes, setAvailableTypes] = useState([]); + const [availableGroups, setAvailableGroups] = useState([]); + const [selectedType, setSelectedType] = useState(null); + const [selectedGroup, setSelectedGroup] = useState(null); + const [isVisible, setIsVisible] = useState(true); + const [products, setProducts] = useState([]); + + const [dashboardData, setDashboardData] = useState({ totalRevenue: { amount: 10215845, @@ -24,10 +36,9 @@ const Dashboard = () => { { date: '22/06', items: 200, revenue: 800 }, { date: '23/06', items: 750, revenue: 450 }, { date: '24/06', items: 550, revenue: 200 }, - { date: '24/06', items: 300, revenue: 350 }, - { date: '24/06', items: 900, revenue: 450 }, - { date: '24/06', items: 550, revenue: 200 }, - { date: '24/06', items: 700, revenue: 300 } + { date: '25/06', items: 300, revenue: 350 }, + { date: '26/06', items: 900, revenue: 450 }, + { date: '27/06', items: 550, revenue: 200 }, ], latestTransactions: [ { @@ -73,58 +84,88 @@ const Dashboard = () => { ] }); - // Function untuk connect ke n8n webhook - const connectToN8NWebhook = async (webhookUrl) => { - try { - const response = await fetch(webhookUrl, { - method: 'GET', - headers: { - 'Content-Type': 'application/json', - }, - }); - - if (response.ok) { - const data = await response.json(); - setDashboardData(data); - } - } catch (error) { - console.error('Error connecting to n8n webhook:', error); - } - }; + useEffect(() => { + const fetchDistinctOptions = async () => { + const match = document.cookie.match(new RegExp('(^| )token=([^;]+)')); + if (!match) return; + const token = match[2]; + + try { + const res = await fetch('https://bot.kediritechnopark.com/webhook/store-dev/get-products', { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}`, + }, + }); + + const result = await res.json(); // hasil berupa array produk + const products = result || []; + + // Ambil distinct `type` dan `group` manual + const types = [...new Set(products.map(p => p.type).filter(Boolean))]; + const groups = [...new Set(products.map(p => p.group).filter(Boolean))]; + + setAvailableTypes(types); + setAvailableGroups(groups); + setProducts(processProducts(products)); + } catch (err) { + console.error('Gagal ambil produk:', err); + } + }; + + fetchDistinctOptions(); + }, []); + - // Function untuk send data ke n8n webhook const sendDataToN8N = async (webhookUrl, data) => { - try { - const response = await fetch(webhookUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(data), - }); - - if (response.ok) { - console.log('Data sent successfully to n8n'); + const match = document.cookie.match(new RegExp('(^| )token=([^;]+)')); + if (match) { + const token = match[2]; + + const payload = { + ...data, + duration: data.unit_type === 'token' ? null : data.duration, + quantity: data.unit_type === 'duration' ? null : data.quantity, + }; + + if (!token) { + alert('Token tidak ditemukan. Silakan login kembali.'); + return; + } + + try { + const response = await fetch(webhookUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}`, + }, + body: JSON.stringify(payload), + }); + + if (response.ok) { + alert('Dorm berhasil ditambahkan!'); + } else { + const errorText = await response.text(); + console.error('Response Error:', errorText); + alert('Gagal mengirim data: ' + response.status); + } + } catch (error) { + console.error('Error sending data to n8n:', error); + alert('Terjadi kesalahan saat mengirim data.'); } - } catch (error) { - console.error('Error sending data to n8n:', error); } }; - const formatCurrency = (amount) => { - return new Intl.NumberFormat('id-ID').format(amount); - }; + const formatCurrency = (amount) => new Intl.NumberFormat('id-ID').format(amount); const getStatusClass = (status) => { switch (status) { - case 'confirmed': - return styles.statusConfirmed; - case 'waiting payment': - return styles.statusWaiting; - case 'payment expired': - return styles.statusExpired; - default: - return styles.statusConfirmed; + case 'confirmed': return styles.statusConfirmed; + case 'waiting payment': return styles.statusWaiting; + case 'payment expired': return styles.statusExpired; + default: return styles.statusConfirmed; } }; @@ -134,11 +175,9 @@ const Dashboard = () => {

{title}

-
{currency && `${currency} `}{formatCurrency(value)}
-
{isNegative ? ( @@ -152,31 +191,19 @@ const Dashboard = () => { from last week
-
{period}
); const BarChart = ({ data }) => { const maxValue = Math.max(...data.map(item => Math.max(item.items, item.revenue))); - return (
{data.map((item, index) => (
-
-
+
+
{item.date}
@@ -187,78 +214,32 @@ const Dashboard = () => { return (
- {/* Stats Cards */}
- - - + + +
- {/* Charts and Transactions */}
- {/* Report Statistics */} -
-
-
-

Report Statistics

-

Period: 22 - 29 May 2025

-
-
-
-
- Items Sold -
-
-
- Revenue -
-
-
- -
+ {/* Chart and Transactions UI as before */} +
- {/* Latest Transactions */} -
+ {/*

Latest Transactions

- see all transactions + see all
- +
- {dashboardData.latestTransactions.map((transaction) => ( + {products.map((transaction) => (
-
- {transaction.avatar} -

{transaction.name}

on {transaction.date}

- +
IDR {formatCurrency(transaction.amount)} @@ -271,7 +252,170 @@ const Dashboard = () => {
))}
+
*/} +
+
+

Products

+
+ +
+ {products.map((product) => ( +
+
+
+

{product.name}

+ {product.children && product.children.map((child) => ( + +

- {child.name}

+ ))} +
+
+ +
+ + IDR {formatCurrency(product.amount)} + +
+ + {product.status} + +
+
+ ))} +
+
+

Tambah Produk Baru

+
{ + e.preventDefault(); + const form = e.target; + const isToken = unitType === 'token'; + const durationValue = form.duration_value?.value; + const quantityValue = form.duration_quantity?.value; + + const dormData = { + name: form.name.value, + type: selectedType, + image: form.image.value, + description: form.description.value, + price: parseInt(form.price.value, 10), + currency: 'IDR', + duration: isToken ? null : { [durationUnit]: parseInt(durationValue, 10) }, + quantity: isToken ? parseInt(quantityValue, 10) : null, + unit_type: unitType, + sub_product_of: null, + is_visible: isVisible, + group: selectedGroup, + site_url: form.site_url.value || null, + created_at: new Date().toISOString(), + updated_at: new Date().toISOString() + }; + + sendDataToN8N('https://bot.kediritechnopark.com/webhook/store-dev/add-product', dormData); + }} + className={styles.form} + > +
+ + +
+
+ +