import React, { useState, useEffect } from 'react'; import { useNavigate } from "react-router-dom"; import styles from './LinktreePage.module.css'; import { loginUser, getAnalytics, createCafeOwner } from "../helpers/userHelpers"; import { getOwnedCafes, createCafe, updateCafe } from "../helpers/cafeHelpers"; import { getMyTransactions } from "../helpers/transactionHelpers"; import { unsubscribeUser } from "../helpers/subscribeHelpers.js"; import { getLocalStorage, removeLocalStorage } from "../helpers/localStorageHelpers"; import { ThreeDots } from "react-loader-spinner"; import Header from '../components/Header'; import CircularDiagram from "./CircularDiagram"; import API_BASE_URL from '../config'; import BarChart from '../components/BarChart'; const LinktreePage = ({ user, setModal }) => { const navigate = useNavigate(); const [inputtingPassword, setInputtingPassword] = useState(false); const [username, setUsername] = useState(''); const [password, setPassword] = useState(''); const [loading, setLoading] = useState(false); const [error, setError] = useState(false); const [items, setItems] = useState([]); const [isCreating, setIsCreating] = useState(false); const [newItem, setNewItem] = useState({ name: "", type: "" }); const [isModalOpen, setIsModalOpen] = useState(false); const [expanded, setIsExpand] = useState(false); const [expandedCafeId, setExpandedCafeId] = useState(null); const [selectedItemId, setSelectedItemId] = useState(0); const [selectedSubItemId, setSelectedSubItemId] = useState(0); // Handle expand/collapse of cafe details const handleToggleExpand = (cafeId) => { setExpandedCafeId(expandedCafeId === cafeId ? null : cafeId); }; // Handle user transactions const handleMyTransactions = async () => { try { setError(false); setLoading(true); const response = await getMyTransactions(); if (response) { setItems(response); } else { setError(true); } } catch (error) { setError(true); } finally { setLoading(false); console.log(items); } }; // Handle login const handleLogin = async () => { try { setError(false); setLoading(true); const response = await loginUser(username, password); if (response.success) { localStorage.setItem('auth', response.token); window.location.href = response.cafeId ? `/${response.cafeId}` : '/'; } else { setError(true); } } catch (error) { setError(true); } finally { setLoading(false); } }; // Handle logout const handleLogout = () => { removeLocalStorage("auth"); unsubscribeUser(); navigate(0); }; // Fetch data when the user changes useEffect(() => { if (user) { setLoading(true); switch (user.roleId) { case 0: getAnalytics().then(setItems).catch(console.error).finally(() => setLoading(false)); break; case 1: getAnalytics().then(setItems).catch(console.error).finally(() => setLoading(false)); break; case 3: handleMyTransactions(); break; default: setLoading(false); break; } } console.log(items); }, [user]); // Handle create item (admin or cafe owner) const handleCreateItem = async () => { try { if (user.roleId < 1) { const newOwner = await createCafeOwner(newItem.email, newItem.username, newItem.password); setItems([...items, { userId: newOwner.userId, name: newOwner.username }]); } else { const newCafe = await createCafe(newItem.name); setItems([...items, { cafeId: newCafe.cafeId, name: newCafe.name }]); } setIsCreating(false); setNewItem({ name: "", type: "" }); } catch (error) { console.error("Error creating item:", error); } }; const formatIncome = (amount) => { if (amount >= 1_000_000_000) { // Format for billions const billions = amount / 1_000_000_000; return billions.toFixed(0) + "b"; // No decimal places for billions } else if (amount >= 1_000_000) { // Format for millions const millions = amount / 1_000_000; return millions.toFixed(2).replace(/\.00$/, "") + "m"; // Two decimal places, remove trailing '.00' } else if (amount >= 1_000) { // Format for thousands const thousands = amount / 1_000; return thousands.toFixed(1).replace(/\.0$/, "") + "k"; // One decimal place, remove trailing '.0' } else { // Less than a thousand if (amount != null) return amount.toString(); } }; const colors = [ // Complementary (for contrast with olive green) "#FF6347", // Tomato red (complementary to olive green) "#FF4500", // Orange red (complementary to olive green) // Analogous to olive green "#D0E14F", // Light green-yellow "#A9C96E", // Muted olive green (your bg color itself) "#A5B24F", // Earthy olive green // Triadic (balanced and vibrant palette) "#FF00FF", // Magenta (triadic color) "#1E90FF", // Dodger blue (triadic color) "#32CD32", // Lime green (triadic color) // Neutral tones "#FFDAB9", // Peach (light neutral tone) "#4B0082", // Indigo (dark neutral tone) "#8B4513", // Saddle brown (earthy neutral) ]; const selectedItems = items.items?.find(item => (item.userId || item.cafeId) === selectedItemId); // If the selected tenant is found, extract the cafes const selectedSubItems = selectedItems?.subItems || []; // 1. Optionally combine all report items from cafes of the selected tenant const allSelectedSubItems = selectedSubItems.flatMap(cafe => cafe.report?.items || selectedItems.report.items || []); // 2. Retrieve the specific cafe's report items if needed const filteredItems = selectedSubItems.find(cafe => cafe.cafeId == selectedSubItemId) || { report: { items: [] } }; // 3. Decide whether to use combined items or individual cafe items const segments = (selectedItemId != 0 && selectedItemId != -1 && selectedSubItemId == 0 ? allSelectedSubItems : selectedItemId != 0 && selectedItemId != -1 ? filteredItems.report?.items || [] : items?.items || []).map((item, index) => ({ percentage: item.percentage || (items.totalIncome / item.totalIncome || items.totalIncome / item.report.totalIncome) * 100, value: item.username || item.name, color: (colors && colors[index]) || "#cccccc", // Safe check for colors array })) || []; // Ensure segments is an empty array if no items are availabled // Function to combine items of all cafes for the selected tenant console.log(selectedItems) function combineSelectedTenantCafeReports(selectedItems) { return selectedItems.cafes.flatMap(cafe => cafe.report?.items || []); } return ( <> {user && user.roleId < 2 ? ( <>
setIsModalOpen(true)} isLogout={handleLogout} user={user} showProfile={true} setModal={setModal} HeaderMargin='0px' />
{user.roleId == 0 ? ( selectedItemId == 0 || selectedItemId == -1 ? (

Total pemasukan

{items?.totalIncome}

Total keuntungan

{items?.totalIncome * 0.02}

) : (

{selectedItems?.totalIncome}

pemasukan

{selectedItems?.totalOutcome}

pengeluaran

{filteredItems.name}

) ) : ( selectedItemId == 0 || selectedItemId == -1 ? (

Total pemasukan

{formatIncome(items?.totalIncome)}

Total pengeluaran

{formatIncome(items?.totalOutcome)}

) : (

{formatIncome(selectedItems?.report.totalIncome)}

pemasukan

{formatIncome(selectedItems?.report.currentOutcome)}

pengeluaran

{selectedItems.name}

) )}

terlakuu

{segments && segments.map((item, index) => (
{item.percentage == 'Infinity' || isNaN(item.percentage) ? 0 : item.percentage}%   {item.value}
))} {segments.length < 1 && <>
-
-
-
-
}

penambahan stok

Semua {user.roleId < 1 ? 'penyewa' : 'kedai yang dikau miliki'}
{user.roleId < 1 &&
{ setSelectedItemId(selectedItemId == -1 ? 0 : -1); setModal('add-tenant') }} > Tambah penyewa
} { items?.items?.length > 0 ? ( items.items.map((item) => { const isTenantSelected = selectedItemId === (item.userId || item.cafeId); const tenantBackgroundColor = isTenantSelected && !selectedSubItemId ? 'rgb(69, 69, 69)' : 'rgb(114, 114, 114)'; const hasSubItems = item?.subItems?.length > 0; return (
{ setSelectedItemId(isTenantSelected && !selectedSubItemId ? 0 : (item.userId || item.cafeId)); setSelectedSubItemId(0); // Reset subitem selection when changing tenant }} style={{ backgroundColor: tenantBackgroundColor }} className={isTenantSelected ? styles.rectangleNLine : styles.rectangle} >

{item.username || item.name}  

Rp{formatIncome(item.totalIncome || item.report?.totalIncome) || 0}

{/* Only show cafes if the tenant is selected */} {selectedItemId === (item.userId || item.cafeId) && hasSubItems && item.subItems.map((subItem) => { const isCafeSelected = selectedSubItemId == (subItem.cafeId || subItem.userId); const cafeBackgroundColor = isCafeSelected ? 'rgb(69, 69, 69)' : 'rgb(114, 114, 114)'; return (
{ setSelectedSubItemId(isCafeSelected ? 0 : (subItem.cafeId || subItem.userId)); // Toggle subitem selection setSelectedItemId(item.userId || item.cafeId); // Ensure tenant stays selected }} style={{ backgroundColor: cafeBackgroundColor }} > {subItem.name || subItem.username} {/*  pendapatan {formatIncome(subItem.report?.totalIncome || 0)} */}
); })} {selectedItemId == item.cafeId &&
{ }} style={{}} > tambah kasir
}
); }) ) : (
No tenants available
) } {user.roleId > 0 &&
setSelectedItemId(selectedItemId == -1 ? 0 : -1)} > Tambah kedai
}
) : (
COBA KEDAIMASTER
{['pemesanan langsung dari meja', 'pengelolaan pesanan dan keuangan', 'tentukan suasana musik', 'pengelolaan stok dan manajemen', 'jangan pernah ragukan pelanggan'].map((item, index) => (
{item}
))}
diskon 0%
Solusi berbasis web untuk memudahkan pengelolaan kedai, dengan fitur yang mempermudah pemilik, kasir, dan tamu berinteraksi.
{getLocalStorage('auth') == null && (
setUsername(e.target.value)} />
setPassword(e.target.value)} />
)}
Pelajari lebih lanjut Tentang kedaimaster.com setModal('join')} > Daftarkan kedaimu
Linktree visual e.target.src = '/fallback-image.png'} />
)} ); }; export default LinktreePage;