0% found this document useful (0 votes)
66 views27 pages

Coding Trading

The document is a React application that integrates Firebase for user authentication and data management, specifically for stock trading. It includes static data for stocks, stablecoins, news, market overview, and trading pairs, along with a candlestick chart component. The app allows users to buy and sell stocks, manage transactions, and view their balance, with real-time updates on stock prices and user authentication state.

Uploaded by

Brave Heart Sora
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
66 views27 pages

Coding Trading

The document is a React application that integrates Firebase for user authentication and data management, specifically for stock trading. It includes static data for stocks, stablecoins, news, market overview, and trading pairs, along with a candlestick chart component. The app allows users to buy and sell stocks, manage transactions, and view their balance, with real-time updates on stock prices and user authentication state.

Uploaded by

Brave Heart Sora
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 27

import React, { useState, useEffect } from 'react';

import { Search, ArrowUp, ArrowDown, LogOut, Home as HomeIcon, LineChart, Wallet,


BookOpen, User, ArrowLeft, TrendingUp, TrendingDown, Bell, Lock, HelpCircle,
Phone, ArrowRight, DollarSign, Repeat, Target, BarChart2, PlusCircle, MinusCircle,
Banknote, CreditCard, Landmark, QrCode, Heart, AlertCircle, RefreshCw,
CheckCircle, ChevronDown, Share2, Star, Settings, Filter } from 'lucide-react';
import { initializeApp } from 'firebase/app';
import { getAuth, signInWithEmailAndPassword, createUserWithEmailAndPassword,
onAuthStateChanged, signOut, signInWithCustomToken, signInAnonymously } from
'firebase/auth';
import { getFirestore, doc, setDoc, addDoc, collection, query, onSnapshot, getDoc
} from 'firebase/firestore';

// --- Firebase Configuration ---


const firebaseConfig = typeof __firebase_config !== 'undefined' ?
JSON.parse(__firebase_config) : {};
const initialAuthToken = typeof __initial_auth_token !== 'undefined' ?
__initial_auth_token : null;

const app = initializeApp(firebaseConfig);


const auth = getAuth(app);
const db = getFirestore(app);
const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id';

// --- Static Data ---


const stockData = [
{ id: 1, ticker: 'AAPL', name: 'Apple Inc.', price: 175.50, change: 1.25, isUp:
true, info: 'Perusahaan teknologi multinasional yang merancang, mengembangkan, dan
menjual elektronik konsumen, perangkat lunak komputer, dan layanan online.' },
{ id: 2, ticker: 'GOOGL', name: 'Alphabet Inc.', price: 152.10, change: -0.75,
isUp: false, info: 'Perusahaan induk dari Google dan beberapa perusahaan lain,
berfokus pada layanan dan produk terkait internet.' },
{ id: 3, ticker: 'MSFT', name: 'Microsoft Corp.', price: 410.20, change: 0.95,
isUp: true, info: 'Pengembang dan produsen lisensi perangkat lunak komputer,
elektronik konsumen, komputer pribadi, dan layanan terkait.' },
{ id: 4, ticker: 'AMZN', name: 'Amazon.com Inc.', price: 185.70, change: 2.15,
isUp: true, info: 'Perusahaan teknologi multinasional yang berfokus pada e-
commerce, komputasi awan, streaming digital, dan kecerdasan buatan.' },
{ id: 5, ticker: 'TSLA', name: 'Tesla, Inc.', price: 235.45, change: -3.50,
isUp: false, info: 'Produsen kendaraan listrik, panel surya, dan baterai, yang
berambisi untuk mempercepat transisi dunia ke energi berkelanjutan.' },
{ id: 6, ticker: 'ETH', name: 'Ethereum', price: 2000.00, change: 50.00, isUp:
true, info: 'Platform komputasi terdesentralisasi yang menjalankan aplikasi (smart
contracts).' },
{ id: 7, ticker: 'BTC', name: 'Bitcoin', price: 35000.00, change: -1200.00,
isUp: false, info: 'Mata uang digital terdesentralisasi pertama.' },
];

const mockStablecoins = [
{ id: 'USDT', name: 'Tether', price: 14849, change: 0.34, pair: 'USDT/IDR',
isUp: true },
{ id: 'USDC', name: 'USD Coin', price: 14850, change: -0.1, pair: 'USDC/IDR',
isUp: false },
{ id: 'DAI', name: 'Dai', price: 14845, change: 0.05, pair: 'DAI/IDR', isUp:
true },
];

const mockNews = [
{ id: 1, title: 'Federal Reserve Member Mengindikasikan Kenaikan Suku Bunga
Lebih Lanjut', source: 'Reuters', date: '2023-10-27' },
{ id: 2, title: 'Saham Teknologi Naik di Tengah Laporan Pendapatan yang Kuat',
source: 'Bloomberg', date: '2023-10-27' },
{ id: 3, title: 'Minyak Mentah Melonjak Setelah Laporan Penurunan Stok Global',
source: 'CNBC', date: '2023-10-26' },
];

const mockMarketOverview = [
{ id: 'btc', name: 'Bitcoin', price: 448297000, change: 2.85, isUp: true,
ticker: 'BTC/IDR' },
{ id: 'eth', name: 'Ethereum', price: 30964000, change: 0.54, isUp: true,
ticker: 'ETH/IDR' },
{ id: 'usdt', name: 'Tether', price: 14849, change: 0.34, isUp: true, ticker:
'USDT/IDR' },
];

const mockTopGainers = [
{ ticker: 'NVDA', name: 'NVIDIA Corp.', change: 5.30 },
{ ticker: 'META', name: 'Meta Platforms', change: 3.10 },
{ ticker: 'ADBE', name: 'Adobe Inc.', change: 2.75 },
];

const mockTopLosers = [
{ ticker: 'TSLA', name: 'Tesla, Inc.', change: -3.50 },
{ ticker: 'MSFT', name: 'Microsoft Corp.', change: -1.95 },
{ ticker: 'GOOGL', name: 'Alphabet Inc.', change: -1.20 },
];

const mockTradingPairs = [
{ ticker: 'CTSI/IDR', name: 'Cartesi', price: 4710, change: 31.49, isUp: true },
{ ticker: 'SHAN/IDR', name: 'Shiba Inu', price: 9, change: -5.00, isUp: false },
{ ticker: 'SOL/IDR', name: 'Solana', price: 654200, change: 10.15, isUp: true },
];

const eWalletOptions = ['Dana', 'Gopay', 'Link Aja', 'OVO', 'ShopeePay', 'Sakuku',


'JeniusPay', 'Isaku', 'Doku'];

const CandlestickChart = ({ width, height }) => {


const data = [
{ open: 40, high: 50, low: 30, close: 45, volume: 30 },
{ open: 45, high: 60, low: 40, close: 55, volume: 50 },
{ open: 55, high: 58, low: 50, close: 52, volume: 40 },
{ open: 52, high: 55, low: 48, close: 50, volume: 60 },
{ open: 50, high: 55, low: 40, close: 53, volume: 70 },
];

const scaleY = (value) => (1 - (value - 30) / 30) * height;


const candleWidth = 10;
const gap = 10;
const barWidth = 10;

return (
<svg width={width} height={height + 50} viewBox={`0 0 ${width} ${height +
50}`}>
{/* Price Lines */}
<line x1="0" y1={scaleY(50)} x2={width} y2={scaleY(50)} stroke="#fff"
strokeWidth="0.5" strokeDasharray="2,2" />
<line x1="0" y1={scaleY(40)} x2={width} y2={scaleY(40)} stroke="#fff"
strokeWidth="0.5" strokeDasharray="2,2" />
<text x={width} y={scaleY(50) + 2} textAnchor="end" fill="#fff"
fontSize="8">408.188.867</text>
<text x={width} y={scaleY(40) + 2} textAnchor="end" fill="#fff"
fontSize="8">401.141.500</text>

{/* Candlesticks */}


{data.map((d, i) => {
const x = i * (candleWidth + gap) + 10;
const y = d.open > d.close ? scaleY(d.open) : scaleY(d.close);
const candleHeight = Math.abs(scaleY(d.open) - scaleY(d.close));
const color = d.open > d.close ? '#ef4444' : '#22c55e'; // red or green

return (
<g key={i}>
{/* Wick */}
<line x1={x + candleWidth / 2} y1={scaleY(d.high)} x2={x + candleWidth
/ 2} y2={scaleY(d.low)} stroke={color} strokeWidth="1" />
{/* Candle Body */}
<rect x={x} y={y} width={candleWidth} height={candleHeight || 1}
fill={color} />
</g>
);
})}

{/* Mock Volume Bars */}


{data.map((d, i) => (
<rect
key={`vol-${i}`}
x={i * (barWidth + gap) + 10}
y={height + 40 - d.volume}
width={barWidth}
height={d.volume}
fill="#4b5563"
/>
))}
</svg>
);
};

// --- App Component ---


function App() {
const [searchTerm, setSearchTerm] = useState('');
const [stocks, setStocks] = useState(stockData);
const [user, setUser] = useState(null);
const [view, setView] = useState('login'); // 'login', 'register', 'home',
'trading', 'balance', 'transactions', 'account', 'pnl'
const [isAuthReady, setIsAuthReady] = useState(false);
const [balance, setBalance] = useState(10000); // Mock user balance
const [selectedStock, setSelectedStock] = useState(null);
const [userTransactions, setUserTransactions] = useState([]);
const [favoriteStocks, setFavoriteStocks] = useState([]);
const [isKycVerified, setIsKycVerified] = useState(false); // New state for KYC
const [showEwalletOptions, setShowEwalletOptions] = useState(false);
const [activeTab, setActiveTab] = useState('Trending'); // For homepage trading
pairs

const showAlert = (message, type = 'success') => {


const dialog = document.createElement('div');
let bgColor = type === 'success' ? 'bg-green-600' : 'bg-red-600';
let icon = type === 'success' ? '✔' : '❌';
dialog.className = `fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 $
{bgColor} text-white p-6 rounded-lg shadow-2xl z-50 transition-all duration-300
transform scale-0`;
dialog.innerHTML = `
<div class="flex flex-col items-center">
<div class="text-3xl mb-2">${icon}</div>
<p class="text-xl font-bold mb-4 text-center">${message}</p>
<button id="close-alert" class="px-4 py-2 bg-white text-gray-800 rounded-
md hover:bg-gray-100 transition-colors mt-2">OK</button>
</div>
`;
document.body.appendChild(dialog);
setTimeout(() => {
dialog.classList.remove('scale-0');
dialog.classList.add('scale-100');
}, 10);
document.getElementById('close-alert').onclick = () => {
dialog.classList.remove('scale-100');
dialog.classList.add('scale-0');
setTimeout(() => dialog.remove(), 300);
};
};

useEffect(() => {
const unsub = onAuthStateChanged(auth, async (currentUser) => {
if (currentUser) {
setUser(currentUser);
setView('home');
} else {
setUser(null);
setView('login');
}
setIsAuthReady(true);
});
return () => unsub();
}, []);
useEffect(() => {
const handleInitialAuth = async () => {
if (initialAuthToken) {
try {
await signInWithCustomToken(auth, initialAuthToken);
} catch (error) {
console.error("Error signing in with custom token:", error);
}
} else {
try {
await signInAnonymously(auth);
} catch (error) {
console.error("Error signing in anonymously:", error);
}
}
};
handleInitialAuth();
}, []);

useEffect(() => {
if (user) {
const intervalId = setInterval(() => {
setStocks(prevStocks => prevStocks.map(stock => {
const newPrice = (stock.price + (Math.random() * 2 - 1)).toFixed(2);
const newChange = (newPrice - stock.price).toFixed(2);
return {
...stock,
price: parseFloat(newPrice),
change: Math.abs(parseFloat(newChange)),
isUp: parseFloat(newChange) >= 0,
};
}));
}, 5000);
return () => clearInterval(intervalId);
}
}, [user]);

useEffect(() => {
let unsub;
if (user && isAuthReady) {
const userId = user.uid;
const transactionsColRef = collection(db, `artifacts/${appId}/users/$
{userId}/transactions`);
const q = query(transactionsColRef);
unsub = onSnapshot(q, (snapshot) => {
const transactions = snapshot.docs.map(doc => ({ id: doc.id, ...doc.data()
}));
const sortedTransactions = transactions.sort((a, b) => b.timestamp -
a.timestamp);
setUserTransactions(sortedTransactions);
}, (error) => {
console.error("Error fetching transactions: ", error);
});
}
return () => unsub && unsub();
}, [user, isAuthReady]);

const handleBuy = async (ticker, quantity, orderType) => {


const stock = stocks.find(s => s.ticker === ticker);
if (!stock) {
showAlert('Saham tidak ditemukan.', 'error');
return;
}
if (balance < stock.price * quantity) {
showAlert('Saldo tidak mencukupi.', 'error');
return;
}

try {
const userId = user.uid;
const transactionsColRef = collection(db, `artifacts/${appId}/users/$
{userId}/transactions`);
await addDoc(transactionsColRef, {
type: 'Beli',
ticker: stock.ticker,
price: stock.price,
quantity: parseInt(quantity),
orderType: orderType,
date: new Date().toISOString().slice(0, 10),
timestamp: new Date().getTime()
});
setBalance(prevBalance => prevBalance - (stock.price * quantity));
showAlert(`Anda berhasil melakukan order beli untuk ${quantity} saham $
{ticker}!`, 'success');
} catch (error) {
console.error("Error saving transaction: ", error);
showAlert("Gagal menyimpan transaksi.", 'error');
}
};

const handleSell = async (ticker, quantity, orderType) => {


const stock = stocks.find(s => s.ticker === ticker);
if (!stock) {
showAlert('Saham tidak ditemukan.', 'error');
return;
}

try {
const userId = user.uid;
const transactionsColRef = collection(db, `artifacts/${appId}/users/$
{userId}/transactions`);
await addDoc(transactionsColRef, {
type: 'Jual',
ticker: stock.ticker,
price: stock.price,
quantity: parseInt(quantity),
orderType: orderType,
date: new Date().toISOString().slice(0, 10),
timestamp: new Date().getTime()
});
setBalance(prevBalance => prevBalance + (stock.price * quantity));
showAlert(`Anda berhasil melakukan order jual untuk ${quantity} saham $
{ticker}!`, 'success');
} catch (error) {
console.error("Error saving transaction: ", error);
showAlert("Gagal menyimpan transaksi.", 'error');
}
};

const handleLogin = async (email, password) => {


try {
await signInWithEmailAndPassword(auth, email, password);
showAlert('Login berhasil!', 'success');
} catch (error) {
console.error(error);
if (error.code === 'auth/operation-not-allowed') {
showAlert('Login gagal. Otentikasi Email/Password tidak diaktifkan.
Silakan aktifkan di konsol Firebase Anda.', 'error');
} else {
showAlert('Email atau password salah.', 'error');
}
}
};

const handleRegister = async (email, password) => {


try {
const userCredential = await createUserWithEmailAndPassword(auth, email,
password);
const userDocRef = doc(db, `artifacts/${appId}/users/$
{userCredential.user.uid}/private/userProfile`);
await setDoc(userDocRef, { email: userCredential.user.email, createdAt: new
Date() });
showAlert('Registrasi berhasil! Anda sekarang masuk.', 'success');
} catch (error) {
console.error(error);
if (error.code === 'auth/operation-not-allowed') {
showAlert('Registrasi gagal. Otentikasi Email/Password tidak diaktifkan.
Silakan aktifkan di konsol Firebase Anda.', 'error');
} else {
showAlert('Registrasi gagal. Coba lagi.', 'error');
}
}
};

const handleLogout = async () => {


try {
await signOut(auth);
showAlert('Anda telah keluar.', 'success');
} catch (error) {
showAlert('Gagal keluar.', 'error');
}
};
const handleToggleFavorite = (stockId) => {
setFavoriteStocks(prevFavorites => {
if (prevFavorites.includes(stockId)) {
return prevFavorites.filter(id => id !== stockId);
} else {
return [...prevFavorites, stockId];
}
});
};

// --- Login Form Component ---


const LoginForm = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

const handleSubmit = (e) => {


e.preventDefault();
handleLogin(email, password);
};

return (
<div className="flex items-center justify-center min-h-screen bg-gray-900
text-gray-100 p-4 font-sans antialiased">
<div className="w-full max-w-md p-8 space-y-6 bg-gray-800 rounded-2xl
shadow-xl">
<div className="text-center">
<h1 className="text-4xl font-extrabold text-white tracking-tight">
<span className="bg-clip-text text-transparent bg-gradient-to-r
from-blue-400 to-blue-600">NYSE</span>
</h1>
<p className="mt-2 text-lg text-gray-400">Silakan masuk untuk
melanjutkan</p>
</div>
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="email" className="block text-sm font-medium text-
gray-300">Email</label>
<input
id="email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="mt-1 block w-full px-4 py-3 bg-gray-700 text-white
rounded-lg border border-gray-600 focus:ring-2 focus:ring-blue-500 focus:border-
blue-500 shadow-sm transition-all"
placeholder="Masukkan email"
required
/>
</div>
<div>
<label htmlFor="password" className="block text-sm font-medium text-
gray-300">Password</label>
<input
id="password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="mt-1 block w-full px-4 py-3 bg-gray-700 text-white
rounded-lg border border-gray-600 focus:ring-2 focus:ring-blue-500 focus:border-
blue-500 shadow-sm transition-all"
placeholder="Masukkan password"
required
/>
</div>
<button
type="submit"
className="w-full flex justify-center py-3 px-4 rounded-lg shadow-sm
text-lg font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none
focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors"
>
Masuk
</button>
</form>
<div className="text-center text-sm text-gray-500">
<p>Belum punya akun? <button onClick={() => setView('register')}
className="text-blue-400 hover:underline">Daftar di sini</button></p>
</div>
</div>
</div>
);
};

// --- Registration Form Component ---


const RegistrationForm = () => {
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');

const handleSubmit = (e) => {


e.preventDefault();
handleRegister(email, password);
};

return (
<div className="flex items-center justify-center min-h-screen bg-gray-900
text-gray-100 p-4 font-sans antialiased">
<div className="w-full max-w-md p-8 space-y-6 bg-gray-800 rounded-2xl
shadow-xl">
<div className="text-center">
<h1 className="text-4xl font-extrabold text-white tracking-tight">
<span className="bg-clip-text text-transparent bg-gradient-to-r
from-blue-400 to-blue-600">NYSE</span>
</h1>
<p className="mt-2 text-lg text-gray-400">Buat akun baru</p>
</div>
<form onSubmit={handleSubmit} className="space-y-6">
<div>
<label htmlFor="reg-email" className="block text-sm font-medium
text-gray-300">Email</label>
<input
id="reg-email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
className="mt-1 block w-full px-4 py-3 bg-gray-700 text-white
rounded-lg border border-gray-600 focus:ring-2 focus:ring-blue-500 focus:border-
blue-500 shadow-sm transition-all"
placeholder="Masukkan email"
required
/>
</div>
<div>
<label htmlFor="reg-password" className="block text-sm font-medium
text-gray-300">Password</label>
<input
id="reg-password"
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
className="mt-1 block w-full px-4 py-3 bg-gray-700 text-white
rounded-lg border border-gray-600 focus:ring-2 focus:ring-blue-500 focus:border-
blue-500 shadow-sm transition-all"
placeholder="Buat password"
required
/>
</div>
<button
type="submit"
className="w-full flex justify-center py-3 px-4 rounded-lg shadow-sm
text-lg font-medium text-white bg-green-600 hover:bg-green-700 focus:outline-none
focus:ring-2 focus:ring-offset-2 focus:ring-green-500 transition-colors"
>
Daftar
</button>
</form>
<div className="text-center text-sm text-gray-500">
<p>Sudah punya akun? <button onClick={() => setView('login')}
className="text-blue-400 hover:underline">Masuk di sini</button></p>
</div>
</div>
</div>
);
};

// --- Dashboard Layout Component ---


const DashboardLayout = ({ children }) => (
<div className="min-h-screen bg-gray-900 text-gray-100 font-sans antialiased">
<nav className="shadow-lg sticky top-0 z-10" style={{ backgroundImage:
'linear-gradient(to right, #B8860B, #FFD700)', borderBottom: '1px solid #FFD700'
}}>
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-16">
<div className="flex items-center">
<img src="http://googleusercontent.com/file_content/1" alt="NYSE
Logo" className="h-10 w-auto" />
</div>
<div className="flex items-center space-x-4">
<div className="flex space-x-2">
<NavButton icon={<HomeIcon size={20} />} text="Beranda"
active={view === 'home'} onClick={() => setView('home')} />
<NavButton icon={<LineChart size={20} />} text="Trading"
active={view === 'trading'} onClick={() => setView('trading')} />
<NavButton icon={<BookOpen size={20} />} text="Transaksi"
active={view === 'transactions'} onClick={() => setView('transactions')} />
<NavButton icon={<Wallet size={20} />} text="Saldo" active={view
=== 'balance'} onClick={() => setView('balance')} />
<NavButton icon={<User size={20} />} text="Akun" active={view ===
'account'} onClick={() => setView('account')} />
</div>
<button
onClick={handleLogout}
className="flex items-center space-x-2 px-3 py-2 bg-red-600 text-
white rounded-lg shadow-md hover:bg-red-700 transition-colors transform
hover:scale-105"
>
<LogOut size={20} />
<span className="hidden sm:inline">Keluar</span>
</button>
</div>
</div>
</div>
</nav>
<main className="p-4 md:p-8">
{children}
</main>
</div>
);

const NavButton = ({ icon, text, active, onClick }) => (


<button
onClick={onClick}
className={`flex items-center space-x-2 px-3 py-2 rounded-md transition-
colors ${
active ? 'bg-blue-600 text-white' : 'text-gray-300 hover:bg-gray-700
hover:text-white'
}`}
>
{icon}
<span className="hidden sm:inline">{text}</span>
</button>
);

// --- Page Components ---


const HomePage = () => {
const [activeTab, setActiveTab] = useState('Trending');
const renderTradingPairs = () => {
let data = [];
if (activeTab === 'Trending') {
data = mockTradingPairs;
} else if (activeTab === 'Gainers') {
data = mockTopGainers.map(g => ({ ...g, isUp: true }));
} else if (activeTab === 'Losers') {
data = mockTopLosers.map(l => ({ ...l, isUp: false }));
} else if (activeTab === 'Koin Baru') {
data = [{ ticker: 'NEW/IDR', name: 'New Coin', price: 100, change: 15.00,
isUp: true }];
}

return (
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-700">
<thead className="bg-gray-700">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-
400 uppercase tracking-wider">Nama</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-
400 uppercase tracking-wider">Harga</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-
400 uppercase tracking-wider">24h Chg %</th>
</tr>
</thead>
<tbody className="bg-gray-800 divide-y divide-gray-700">
{data.map((pair, index) => (
<tr key={index}>
<td className="px-6 py-4 whitespace-nowrap">
<div className="text-sm font-bold text-
white">{pair.ticker}</div>
<div className="text-xs text-gray-400">{pair.name}</div>
</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-
white">{pair.price ? `Rp ${pair.price.toLocaleString('id-ID')}` : 'N/A'}</td>
<td className={`px-6 py-4 whitespace-nowrap text-sm font-bold $
{pair.isUp ? 'text-green-400' : 'text-red-400'}`}>
{pair.isUp ? `+` : ''}{pair.change}%
</td>
</tr>
))}
</tbody>
</table>
</div>
);
};

return (
<div className="container mx-auto bg-gray-900 text-gray-100 font-sans
antialiased">
<header className="p-4 bg-gray-900 text-white flex items-center justify-
between rounded-b-2xl shadow-lg">
<div className="flex items-center space-x-2">
<button onClick={() => showAlert('Fitur belum tersedia.', 'error')}
className="p-2 rounded-full text-white">
<ChevronDown size={20} />
</button>
<span className="font-bold">PRO</span>
</div>
<div className="flex-1 text-center">
<p className="text-sm text-gray-400">Estimasi nilai aset</p>
<p className="text-2xl font-bold">XXX.XX IDR</p>
</div>
<div className="flex items-center space-x-4">
<button onClick={() => showAlert('Fitur pencarian.', 'success')}
className="text-white">
<Search size={20} />
</button>
<button onClick={() => showAlert('Fitur notifikasi.', 'success')}
className="text-white">
<Bell size={20} />
</button>
<button onClick={() => showAlert('Fitur profil.', 'success')}
className="text-white">
<User size={20} />
</button>
</div>
</header>

{/* Mock Carousel */}


<div className="overflow-hidden p-4">
<div className="flex space-x-4">
<div className="flex-shrink-0 w-[80vw] md:w-[400px] h-24 bg-gray-700
rounded-lg shadow-md flex items-center justify-center text-center p-2">
<img src="https://placehold.co/400x96/4b5563/fff?text=Promo+1"
alt="promo" className="rounded-lg w-full h-full object-cover" />
</div>
<div className="flex-shrink-0 w-[80vw] md:w-[400px] h-24 bg-gray-700
rounded-lg shadow-md flex items-center justify-center text-center p-2">
<img src="https://placehold.co/400x96/4b5563/fff?text=Promo+2"
alt="promo" className="rounded-lg w-full h-full object-cover" />
</div>
</div>
</div>

{/* Market Overview Grid */}


<div className="p-4">
<div className="grid grid-cols-3 gap-4">
{mockMarketOverview.map(asset => (
<div key={asset.id} className="bg-gray-800 p-3 rounded-lg shadow-
md">
<p className="text-sm font-semibold">{asset.ticker}</p>
<p className="text-lg font-bold mt-1">Rp
{asset.price.toLocaleString('id-ID')}</p>
<p className={`text-sm font-semibold ${asset.isUp ? 'text-green-
400' : 'text-red-400'}`}>
{asset.isUp ? '+' : ''}{asset.change}%
</p>
</div>
))}
</div>
</div>

{/* Feature Buttons */}


<div className="p-4 grid grid-cols-4 gap-4 text-center">
<button onClick={() => showAlert('Menuju halaman Setor (simulasi).',
'success')} className="flex flex-col items-center space-y-1">
<div className="p-3 bg-gray-700 rounded-full text-blue-400">
<PlusCircle size={24} />
</div>
<span className="text-xs text-gray-400">Setor</span>
</button>
<button onClick={() => setView('transactions')} className="flex flex-col
items-center space-y-1">
<div className="p-3 bg-gray-700 rounded-full text-blue-400">
<BookOpen size={24} />
</div>
<span className="text-xs text-gray-400">Riwayat</span>
</button>
<button onClick={() => showAlert('Menuju Chatroom (simulasi).',
'success')} className="flex flex-col items-center space-y-1">
<div className="p-3 bg-gray-700 rounded-full text-blue-400">
<HelpCircle size={24} />
</div>
<span className="text-xs text-gray-400">Chatroom</span>
</button>
<button onClick={() => showAlert('Menuju Academy (simulasi).',
'success')} className="flex flex-col items-center space-y-1">
<div className="p-3 bg-gray-700 rounded-full text-blue-400">
<User size={24} />
</div>
<span className="text-xs text-gray-400">Academy</span>
</button>
</div>

{/* Trading Pairs Table */}


<div className="p-4 space-y-4">
<div className="flex space-x-2 border-b border-gray-700">
{['Trending', 'Gainers', 'Losers', 'Koin Baru'].map(tab => (
<button
key={tab}
onClick={() => setActiveTab(tab)}
className={`pb-2 text-sm font-semibold transition-colors $
{activeTab === tab ? 'text-blue-400 border-b-2 border-blue-400' : 'text-gray-400
hover:text-white'}`}
>
{tab}
</button>
))}
</div>
{renderTradingPairs()}
</div>
</div>
);
};

const TradingPage = () => {


const [selectedStockId, setSelectedStockId] = useState(null);
const selectedStock = stocks.find(s => s.id === selectedStockId);

const handleStockClick = (id) => {


setSelectedStockId(id);
};

const handleBackClick = () => {


setSelectedStockId(null);
};

if (selectedStock) {
return (
<TradingViewPage stock={selectedStock} onBack={handleBackClick} />
);
}

return (
<div className="container mx-auto p-4 md:p-8 bg-gray-800 rounded-2xl shadow-
xl space-y-6">
<h2 className="text-3xl font-bold text-white">Pasar Trading</h2>
{/* Stablecoin Pairs Section */}
<section>
<h3 className="text-xl font-bold text-white mb-4">Pasangan
Stablecoin</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
{mockStablecoins.map(coin => (
<div key={coin.id} className="bg-gray-700 p-4 rounded-xl shadow-lg">
<h4 className="text-lg font-semibold text-white">{coin.name}</h4>
<p className="text-sm text-gray-400">{coin.pair}</p>
</div>
))}
</div>
</section>

<section>
<div className="flex justify-between items-center mb-6">
<h3 className="text-xl font-bold text-white">Semua Aset</h3>
<div className="relative w-full md:w-1/2 lg:w-1/3">
<input
type="text"
placeholder="Cari aset..."
className="w-full px-5 py-3 pl-12 rounded-full bg-gray-700 text-
white placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500
transition-all shadow-inner"
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
/>
<Search className="absolute left-4 top-1/2 transform -translate-y-
1/2 text-gray-400" size={20} />
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{stocks.filter(stock =>
stock.ticker.toLowerCase().includes(searchTerm.toLowerCase()) ||
stock.name.toLowerCase().includes(searchTerm.toLowerCase())
).length > 0 ? (
stocks.filter(stock =>
stock.ticker.toLowerCase().includes(searchTerm.toLowerCase()) ||
stock.name.toLowerCase().includes(searchTerm.toLowerCase())
).map(stock => (
<div key={stock.id} onClick={() => handleStockClick(stock.id)}
className="bg-gray-700 rounded-xl p-6 shadow-lg hover:shadow-2xl hover:cursor-
pointer transition-shadow duration-300">
<div className="flex justify-between items-start mb-4">
<div className="flex flex-col">
<h3 className="text-xl md:text-2xl font-bold text-white mb-
1">{stock.ticker}</h3>
<p className="text-sm text-gray-400">{stock.name}</p>
</div>
<div className="flex items-center gap-2">
<button onClick={(e) => { e.stopPropagation();
handleToggleFavorite(stock.id); }} className="text-gray-400 hover:text-red-500
transition-colors">
<Heart size={20} fill={favoriteStocks.includes(stock.id) ?
'currentColor' : 'none'} />
</button>
<div className={`text-right flex items-center gap-2 $
{stock.isUp ? 'text-green-400' : 'text-red-400'}`}>
<span className="text-2xl md:text-3xl font-bold">$
{stock.price.toFixed(2)}</span>
{stock.isUp ? <ArrowUp size={24} /> : <ArrowDown size={24}
/>}
</div>
</div>
</div>
<div className={`flex items-center gap-2 text-sm font-semibold
mb-4 ${stock.isUp ? 'text-green-400' : 'text-red-400'}`}>
<span>{stock.isUp ? '+' : '-'}$
{stock.change.toFixed(2)}</span>
<span className="text-gray-400">({((stock.change /
stock.price) * 100).toFixed(2)}%)</span>
</div>
</div>
))
) : (
<p className="col-span-full text-center text-gray-400 text-lg py-
10">Tidak ada saham yang cocok dengan pencarian Anda.</p>
)}
</div>
</section>
</div>
);
};

const TradingViewPage = ({ stock, onBack }) => {


const [quantity, setQuantity] = useState(1);
const [orderType, setOrderType] = useState('Market');
const [tradingTab, setTradingTab] = useState('Line');

// Mock Order Book data


const orderBook = {
bids: [
{ price: stock.price - 0.1, size: 500 },
{ price: stock.price - 0.2, size: 800 },
],
asks: [
{ price: stock.price + 0.1, size: 650 },
{ price: stock.price + 0.2, size: 920 },
],
};

// Mock Trade History data


const tradeHistory = [
{ time: '21:00:00', price: 175.50, amount: 0.12, type: 'buy' },
{ time: '20:59:58', price: 175.45, amount: 0.08, type: 'sell' },
{ time: '20:59:55', price: 175.52, amount: 0.25, type: 'buy' },
];

const handleSetPriceAlert = () => {


showAlert(`Peringatan harga untuk ${stock.ticker} diatur!`, 'success');
};

return (
<div className="container mx-auto p-4 md:p-8 bg-gray-800 rounded-2xl shadow-
xl">
{/* Header */}
<div className="flex items-center justify-between mb-4 pb-4 border-b
border-gray-700">
<div className="flex items-center space-x-4">
<button onClick={onBack} className="text-blue-400 hover:text-blue-500
transition-colors">
<ArrowLeft size={24} />
</button>
<div>
<div className="flex items-center">
<h2 className="text-xl font-bold text-
white">{stock.ticker}/IDR</h2>
<ChevronDown size={20} className="ml-2 text-gray-400" />
</div>
<p className={`text-3xl font-bold ${stock.isUp ? 'text-green-400' :
'text-red-400'}`}>
{stock.price.toLocaleString('id-ID')}
</p>
<p className={`text-sm font-semibold ${stock.isUp ? 'text-green-400'
: 'text-red-400'}`}>
{stock.isUp ? `+` : ''}{stock.change.toFixed(2)} ({((stock.change
/ stock.price) * 100).toFixed(2)}%)
</p>
</div>
</div>
<div className="flex items-center space-x-2">
<button onClick={() => showAlert('Berbagi.', 'success')} className="p-
2 rounded-full hover:bg-gray-700 transition-colors">
<Share2 size={20} />
</button>
<button onClick={() => handleToggleFavorite(stock.id)} className="p-2
rounded-full hover:bg-gray-700 transition-colors">
<Star size={20} fill={favoriteStocks.includes(stock.id) ?
'currentColor' : 'none'} />
</button>
</div>
</div>

{/* Chart Section */}


<div className="bg-gray-900 rounded-xl shadow-inner p-4 mb-6">
<div className="flex justify-between items-center text-sm mb-4">
<div className="flex space-x-2">
{['Line', '15m', '1h', '4h', '1D'].map(tab => (
<button
key={tab}
onClick={() => setTradingTab(tab)}
className={`px-3 py-1 rounded-full text-xs font-semibold $
{tradingTab === tab ? 'bg-blue-600 text-white' : 'text-gray-400 hover:text-
white'}`}
>
{tab}
</button>
))}
</div>
<div className="flex space-x-2">
<button onClick={() => setTradingTab('Depth')} className={`px-3 py-1
rounded-full text-xs font-semibold ${tradingTab === 'Depth' ? 'bg-blue-600 text-
white' : 'text-gray-400 hover:text-white'}`}>
Depth
</button>
<button onClick={() => showAlert('Pengaturan grafik.', 'success')}
className="text-gray-400 hover:text-white">
<Settings size={16} />
</button>
</div>
</div>
{/* Mock candlestick chart */}
<CandlestickChart width={800} height={300} />
{/* Technical Indicators */}
<div className="flex justify-center flex-wrap gap-4 mt-4 text-xs font-
semibold text-gray-400">
<span>MA</span>
<span>EMA</span>
<span>BOLL</span>
<span>VOL</span>
<button className="text-blue-400">
<Filter size={16} />
</button>
</div>
</div>

{/* Order Book, Trades, etc. */}


<div className="p-4 space-y-6">
<div className="flex space-x-4 border-b border-gray-700">
{['Order Book', 'Trades', 'Market Luar', 'Riwayat Transaksi'].map(tab
=> (
<button key={tab} className="pb-2 text-sm font-semibold text-gray-
400 hover:text-white border-b-2 border-transparent hover:border-white transition-
colors">
{tab}
</button>
))}
</div>

{/* Order Book and Execution */}


<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div>
<h3 className="text-lg font-bold text-white mb-2">Order Book</h3>
<div className="flex space-x-2 mb-2">
<span className="text-sm font-semibold text-green-400">Bid</span>
<span className="text-sm font-semibold text-red-400">Ask</span>
</div>
<div className="bg-gray-700 rounded-lg p-4">
<div className="flex justify-between items-center text-sm mb-2">
<span className="text-red-400">Bid</span>
<span className="text-red-400">Ask</span>
</div>
<div className="space-y-1">
{orderBook.asks.map((ask, index) => (
<div key={`ask-${index}`} className="flex justify-between
items-center text-sm text-red-400">
<span>{ask.size}</span>
<span>${ask.price.toFixed(2)}</span>
</div>
))}
<div className="py-2 border-t border-b border-gray-600">
<p className={`text-xl font-bold text-center ${stock.isUp ?
'text-green-400' : 'text-red-400'}`}>
${stock.price.toFixed(2)}
</p>
</div>
{orderBook.bids.map((bid, index) => (
<div key={`bid-${index}`} className="flex justify-between
items-center text-sm text-green-400">
<span>${bid.price.toFixed(2)}</span>
<span>{bid.size}</span>
</div>
))}
</div>
</div>
</div>

{/* Execution Buttons */}


<div>
<h3 className="text-lg font-bold text-white mb-2">Eksekusi</h3>
<div className="flex space-x-4">
<button onClick={() => handleBuy(stock.ticker, 1, 'Market')}
className="flex-1 flex items-center justify-center space-x-2 px-4 py-2 bg-green-
600 text-white rounded-lg shadow-md hover:bg-green-700 transition-colors transform
hover:scale-105">
<span>Beli</span>
</button>
<button onClick={() => handleSell(stock.ticker, 1, 'Market')}
className="flex-1 flex items-center justify-center space-x-2 px-4 py-2 bg-red-600
text-white rounded-lg shadow-md hover:bg-red-700 transition-colors transform
hover:scale-105">
<span>Jual</span>
</button>
</div>
</div>
</div>
</div>
</div>
);
};

const BalancePage = () => (


<div className="bg-gray-800 rounded-2xl shadow-xl p-8 max-w-2xl mx-auto space-
y-6">
<h2 className="text-3xl font-bold text-white mb-6">Saldo Akun</h2>

{/* Saldo Total dan Deposit */}


<div className="p-6 bg-gray-700 rounded-xl shadow-md flex justify-between
items-center">
<div>
<p className="text-gray-400 text-lg">Estimasi Nilai Akun:</p>
<p className="text-5xl font-bold text-green-400 mt-2">$
{balance.toLocaleString('en-US')}</p>
</div>
<button onClick={() => showAlert('Menuju ke halaman deposit...',
'success')} className="px-4 py-2 bg-blue-600 text-white rounded-lg shadow-md
hover:bg-blue-700 transition-colors flex items-center space-x-2">
<PlusCircle size={20} />
<span>Deposit</span>
</button>
</div>

{/* Opsi Deposit */}


<div className="bg-gray-700 rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-white mb-4">Deposit Gampang</h3>
<p className="text-sm text-gray-400 mb-4">Pilih metode pembayaran untuk
menambah saldo Anda.</p>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<button onClick={() => showAlert('Menggunakan Bank Transfer
(Simulasi)...', 'success')} className="flex items-center space-x-2 px-4 py-3 bg-
gray-600 text-white rounded-lg hover:bg-gray-500 transition-colors">
<Landmark size={20} />
<span>Bank Transfer</span>
</button>
{/* E-Wallet Section */}
<div className="relative">
<button onClick={() => setShowEwalletOptions(!showEwalletOptions)}
className="flex items-center space-x-2 px-4 py-3 bg-gray-600 text-white rounded-lg
hover:bg-gray-500 transition-colors w-full">
<CreditCard size={20} />
<span>E-Wallet</span>
</button>
{showEwalletOptions && (
<div className="absolute top-12 left-0 w-full bg-gray-700 rounded-lg
shadow-lg z-20 space-y-2 p-2">
{eWalletOptions.map((wallet, index) => (
<button key={index} onClick={() => showAlert(`Deposit melalui $
{wallet} (Simulasi)...`, 'success')} className="w-full text-left px-3 py-2 text-
white rounded-lg hover:bg-gray-600 transition-colors">
{wallet}
</button>
))}
</div>
)}
</div>
<button onClick={() => showAlert('Opsi deposit kripto (Simulasi)...',
'success')} className="flex items-center space-x-2 px-4 py-3 bg-gray-600 text-
white rounded-lg hover:bg-gray-500 transition-colors">
<DollarSign size={20} />
<span>Deposit Kripto</span>
</button>
</div>
</div>

{/* Konversi Aset Kecil */}


<div className="bg-gray-700 rounded-xl shadow-md p-6 flex justify-between
items-center">
<div>
<h3 className="text-xl font-bold text-white flex items-
center"><RefreshCw size={24} className="mr-2 text-blue-400" /> Konversi Aset
Kecil</h3>
<p className="text-sm text-gray-400">Konversi sisa-sisa aset kecil Anda
menjadi TKO.</p>
</div>
<button onClick={() => showAlert('Aset kecil Anda berhasil dikonversi ke
TKO (Simulasi).', 'success')} className="px-4 py-2 bg-blue-600 text-white rounded-
lg shadow-md hover:bg-blue-700 transition-colors">Konversi</button>
</div>
</div>
);

const TransactionsPage = () => (


<div className="bg-gray-800 rounded-2xl shadow-xl p-8 max-w-4xl mx-auto">
<h2 className="text-3xl font-bold text-white mb-6">Riwayat Transaksi</h2>
<div className="overflow-x-auto">
<table className="min-w-full divide-y divide-gray-700">
<thead className="bg-gray-700">
<tr>
<th scope="col" className="px-6 py-3 text-left text-xs font-medium
text-gray-400 uppercase tracking-wider">Tipe</th>
<th scope="col" className="px-6 py-3 text-left text-xs font-medium
text-gray-400 uppercase tracking-wider">Saham</th>
<th scope="col" className="px-6 py-3 text-left text-xs font-medium
text-gray-400 uppercase tracking-wider">Harga</th>
<th scope="col" className="px-6 py-3 text-left text-xs font-medium
text-gray-400 uppercase tracking-wider">Jumlah</th>
<th scope="col" className="px-6 py-3 text-left text-xs font-medium
text-gray-400 uppercase tracking-wider">Tanggal</th>
</tr>
</thead>
<tbody className="bg-gray-800 divide-y divide-gray-700">
{userTransactions.map(tx => (
<tr key={tx.id}>
<td className={`px-6 py-4 whitespace-nowrap text-sm font-medium $
{tx.type === 'Beli' ? 'text-green-400' : 'text-red-400'}`}>{tx.type}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-300
font-bold">{tx.ticker}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-
300">${tx.price.toFixed(2)}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-
300">{tx.quantity}</td>
<td className="px-6 py-4 whitespace-nowrap text-sm text-gray-
300">{tx.date}</td>
</tr>
))}
</tbody>
</table>
</div>
{userTransactions.length === 0 && (
<div className="p-6 text-center text-gray-400">
<p>Belum ada transaksi.</p>
</div>
)}
</div>
);

const AccountPage = () => (


<div className="bg-gray-800 rounded-2xl shadow-xl p-8 max-w-2xl mx-auto space-
y-6">
<h2 className="text-3xl font-bold text-white mb-6">Akun Pengguna</h2>

{/* Informasi Profil */}


<div className="bg-gray-700 rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-white flex items-center mb-4"><User
size={24} className="mr-2 text-blue-400" /> Informasi Profil</h3>
<p className="text-sm text-gray-400">ID Pengguna: <span className="text-
gray-200 font-semibold break-words">{user?.uid || 'N/A'}</span></p>
<p className="text-sm text-gray-400">Email: <span className="text-gray-200
font-semibold break-words">{user?.email || 'N/A'}</span></p>
<p className="text-sm text-gray-400 mt-2">Nama Lengkap: <span
className="text-gray-200 font-semibold">John Doe</span></p>
<p className="text-sm text-gray-400">Nomor Telepon: <span className="text-
gray-200 font-semibold">+62 812-3456-7890</span></p>
</div>

{/* Verifikasi Akun (KYC) */}


<div className="bg-gray-700 rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-white flex items-center mb-4">
<CheckCircle size={24} className={`mr-2 ${isKycVerified ? 'text-green-
400' : 'text-yellow-400'}`} /> Verifikasi Akun (KYC)
</h3>
{isKycVerified ? (
<div className="flex items-center space-x-2 text-green-400 font-
semibold">
<CheckCircle size={20} />
<span>Akun Anda telah diverifikasi.</span>
</div>
) : (
<div className="space-y-4">
<p className="text-sm text-gray-400">Silakan verifikasi akun Anda
untuk mengaktifkan fitur deposit dan penarikan.</p>
<button onClick={() => setIsKycVerified(true)} className="w-full px-4
py-2 bg-blue-600 text-white rounded-lg shadow-md hover:bg-blue-700 transition-
colors">Mulai Verifikasi</button>
</div>
)}
</div>

{/* Saldo Akun */}


<div className="bg-gray-700 rounded-xl shadow-md p-6 flex justify-between
items-center">
<div>
<h3 className="text-xl font-bold text-white flex items-center"><Wallet
size={24} className="mr-2 text-blue-400" /> Saldo Akun</h3>
<p className="text-gray-400 text-lg">Saldo saat ini: <span
className="text-green-400 font-bold">${balance.toLocaleString('en-US')}</span></p>
</div>
<button onClick={() => setView('balance')} className="px-4 py-2 bg-blue-
600 text-white rounded-lg shadow-md hover:bg-blue-700 transition-colors">Lihat
Detail</button>
</div>

{/* Riwayat Transaksi */}


<div className="bg-gray-700 rounded-xl shadow-md p-6 flex justify-between
items-center">
<div>
<h3 className="text-xl font-bold text-white flex items-center"><BookOpen
size={24} className="mr-2 text-blue-400" /> Riwayat Transaksi</h3>
<p className="text-sm text-gray-400">Lihat semua transaksi yang telah
Anda lakukan.</p>
</div>
<button onClick={() => setView('transactions')} className="px-4 py-2 bg-
blue-600 text-white rounded-lg shadow-md hover:bg-blue-700 transition-
colors">Lihat Riwayat</button>
</div>

{/* Mengikat Kartu Bank */}


<div className="bg-gray-700 rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-white flex items-center mb-
4"><CreditCard size={24} className="mr-2 text-blue-400" /> Mengikat Kartu
Bank</h3>
<p className="text-sm text-gray-400 mb-4">Hubungkan kartu bank Anda untuk
mempermudah deposit dan penarikan.</p>
<button onClick={() => showAlert('Fitur ini akan membuka formulir untuk
mengikat kartu bank (Simulasi).', 'success')} className="w-full px-4 py-2 bg-blue-
600 text-white rounded-lg shadow-md hover:bg-blue-700 transition-colors">Ikat
Kartu Bank</button>
</div>

{/* Pengaturan Keamanan */}


<div className="bg-gray-700 rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-white flex items-center mb-4"><Lock
size={24} className="mr-2 text-blue-400" /> Pengaturan Keamanan</h3>
<div className="flex flex-col space-y-2">
<button onClick={() => showAlert('Fitur ini akan memungkinkan Anda
mengubah kata sandi.', 'success')} className="flex items-center justify-between
px-4 py-3 bg-gray-600 text-white rounded-lg hover:bg-gray-500 transition-colors">
<span>Ubah Kata Sandi</span>
<ArrowRight size={20} />
</button>
<button onClick={() => showAlert('Fitur ini akan memungkinkan Anda
mengaktifkan otentikasi dua faktor (2FA).', 'success')} className="flex items-
center justify-between px-4 py-3 bg-gray-600 text-white rounded-lg hover:bg-gray-
500 transition-colors">
<span>Otentikasi Dua Faktor (2FA)</span>
<ArrowRight size={20} />
</button>
</div>
</div>

{/* Opsi Penarikan */}


<div className="bg-gray-700 rounded-xl shadow-md p-6 flex justify-between
items-center">
<div>
<h3 className="text-xl font-bold text-white flex items-
center"><TrendingDown size={24} className="mr-2 text-blue-400" /> Opsi
Penarikan</h3>
<p className="text-sm text-gray-400">Tarik dana dari akun Anda ke
rekening bank.</p>
</div>
<button onClick={() => showAlert('Fitur ini akan memungkinkan penarikan
dana.', 'success')} className="px-4 py-2 bg-green-600 text-white rounded-lg
shadow-md hover:bg-green-700 transition-colors">Tarik Dana</button>
</div>

{/* Notifikasi */}


<div className="bg-gray-700 rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-white flex items-center mb-4"><Bell
size={24} className="mr-2 text-blue-400" /> Notifikasi</h3>
<p className="text-sm text-gray-400">Tidak ada notifikasi baru saat
ini.</p>
</div>

{/* Pusat Bantuan/FAQ */}


<div className="bg-gray-700 rounded-xl shadow-md p-6">
<h3 className="text-xl font-bold text-white flex items-center mb-
4"><HelpCircle size={24} className="mr-2 text-blue-400" /> Pusat Bantuan</h3>
<p className="text-sm text-gray-400">Temukan jawaban atas pertanyaan umum
atau hubungi dukungan.</p>
<button onClick={() => showAlert('Fitur ini akan mengarahkan Anda ke
halaman Bantuan/FAQ.', 'success')} className="mt-4 px-4 py-2 bg-blue-600 text-
white rounded-lg shadow-md hover:bg-blue-700 transition-colors">Buka Pusat
Bantuan</button>
</div>

</div>
);

const EarnPage = () => (


<div className="bg-gray-800 rounded-2xl shadow-xl p-8 max-w-2xl mx-auto space-
y-6">
<h2 className="text-3xl font-bold text-white mb-6 flex items-
center"><DollarSign size={24} className="mr-2 text-green-400" /> Earn (Mock)</h2>
<p className="text-gray-400">Dapatkan pengembalian atas aset Anda melalui
berbagai produk Earn.</p>
<div className="bg-gray-700 rounded-xl p-6 shadow-md">
<h3 className="text-xl font-bold text-white mb-2">Staking Saham</h3>
<p className="text-sm text-gray-400 mb-4">Dapatkan imbalan dengan mengunci
aset saham Anda.</p>
<div className="flex justify-between items-center">
<div>
<p className="text-sm text-gray-400">APY Hingga</p>
<p className="text-xl font-bold text-green-400">12.5%</p>
</div>
<button onClick={() => showAlert('Fitur Staking (Simulasi) diaktifkan.',
'success')} className="px-4 py-2 bg-blue-600 text-white rounded-lg shadow-md
hover:bg-blue-700 transition-colors">Stake</button>
</div>
</div>
</div>
);

const DCA_Page = () => (


<div className="bg-gray-800 rounded-2xl shadow-xl p-8 max-w-2xl mx-auto space-
y-6">
<h2 className="text-3xl font-bold text-white mb-6 flex items-center"><Repeat
size={24} className="mr-2 text-blue-400" /> Dollar Cost Averaging (DCA)</h2>
<p className="text-gray-400">Otomatiskan investasi Anda untuk mengurangi
risiko dan memanfaatkan volatilitas pasar.</p>
<div className="bg-gray-700 rounded-xl p-6 shadow-md">
<h3 className="text-xl font-bold text-white mb-2">Buat Rencana DCA</h3>
<div className="space-y-4">
<div>
<label htmlFor="dca-asset" className="block text-sm font-medium text-
gray-300 mb-1">Pilih Aset</label>
<select id="dca-asset" className="w-full px-3 py-2 rounded-lg bg-gray-
600 text-white border border-gray-500 focus:ring-2 focus:ring-blue-500">
<option>AAPL</option>
<option>GOOGL</option>
<option>MSFT</option>
</select>
</div>
<div>
<label htmlFor="dca-amount" className="block text-sm font-medium text-
gray-300 mb-1">Jumlah Investasi ($)</label>
<input type="number" id="dca-amount" placeholder="50" className="w-
full px-3 py-2 rounded-lg bg-gray-600 text-white border border-gray-500
focus:ring-2 focus:ring-blue-500" />
</div>
<div>
<label htmlFor="dca-frequency" className="block text-sm font-medium
text-gray-300 mb-1">Frekuensi</label>
<select id="dca-frequency" className="w-full px-3 py-2 rounded-lg bg-
gray-600 text-white border border-gray-500 focus:ring-2 focus:ring-blue-500">
<option>Mingguan</option>
<option>Bulanan</option>
</select>
</div>
<button onClick={() => showAlert('Rencana DCA dibuat (Simulasi).',
'success')} className="w-full py-3 bg-blue-600 text-white rounded-lg shadow-md
hover:bg-blue-700 transition-colors">Buat Rencana</button>
</div>
</div>
</div>
);

const PnL_Page = () => (


<div className="bg-gray-800 rounded-2xl shadow-xl p-8 max-w-2xl mx-auto space-
y-6">
<h2 className="text-3xl font-bold text-white mb-6 flex items-
center"><BarChart2 size={24} className="mr-2 text-blue-400" /> Analisis P&L
(Mock)</h2>
<p className="text-gray-400">Lihat profit dan loss portofolio Anda secara
sekilas.</p>
<div className="bg-gray-700 rounded-xl p-6 shadow-md">
<h3 className="text-xl font-bold text-white mb-2">Ringkasan
Portofolio</h3>
<div className="space-y-2">
<div className="flex justify-between items-center">
<span className="text-gray-400">Nilai Portofolio:</span>
<span className="font-bold text-green-400">$12,500.00</span>
</div>
<div className="flex justify-between items-center">
<span className="text-gray-400">Total Profit & Loss:</span>
<span className="font-bold text-green-400">+$2,500.00 (+25%)</span>
</div>
</div>
</div>
</div>
);

if (!isAuthReady) {
return (
<div className="flex justify-center items-center h-screen bg-gray-900 text-
white">
Memuat...
</div>
);
}

if (!user) {
return (
<div className="min-h-screen bg-gray-900">
{view === 'login' ? <LoginForm /> : <RegistrationForm />}
</div>
);
}

return (
<DashboardLayout>
{view === 'home' && <HomePage />}
{view === 'trading' && <TradingPage />}
{view === 'balance' && <BalancePage />}
{view === 'transactions' && <TransactionsPage />}
{view === 'account' && <AccountPage />}
{view === 'pnl' && <PnL_Page />}
</DashboardLayout>
);
}

export default App;

You might also like