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 ? ( <>
Total pemasukan
{items?.totalIncome}
Total keuntungan
{items?.totalIncome * 0.02}
{selectedItems?.totalIncome}
pemasukan
{selectedItems?.totalOutcome}
pengeluaran
{filteredItems.name}
Total pemasukan
{formatIncome(items?.totalIncome)}
Total pengeluaran
{formatIncome(items?.totalOutcome)}
{formatIncome(selectedItems?.report.totalIncome)}
pemasukan
{formatIncome(selectedItems?.report.currentOutcome)}
pengeluaran
{selectedItems.name}
e.target.src = '/fallback-image.png'}
/>