diff --git a/src/components/CryptoCalculatorModal.jsx b/src/components/CryptoCalculatorModal.jsx
new file mode 100644
index 0000000..57ba024
--- /dev/null
+++ b/src/components/CryptoCalculatorModal.jsx
@@ -0,0 +1,157 @@
+import React, { useState, useEffect, useRef } from 'react';
+
+export default function CryptoCalculatorModal({ coinData, onClose }) {
+ const [amount, setAmount] = useState('');
+ const [selectedCoinId, setSelectedCoinId] = useState(coinData[0]?.id || '');
+
+ const [searchTerm, setSearchTerm] = useState('');
+ const [isDropdownOpen, setIsDropdownOpen] = useState(false);
+ const dropdownRef = useRef(null);
+
+ const [result, setResult] = useState(null);
+
+ useEffect(() => {
+ setResult(null);
+ }, [amount, selectedCoinId]);
+
+ useEffect(() => {
+ function handleClickOutside(event) {
+ if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
+ setIsDropdownOpen(false);
+ }
+ }
+ document.addEventListener("mousedown", handleClickOutside);
+ return () => {
+ document.removeEventListener("mousedown", handleClickOutside);
+ };
+ }, [dropdownRef]);
+
+
+ const isButtonDisabled = !amount || parseFloat(amount) <= 0;
+
+ const handleCalculate = () => {
+ const coin = coinData.find((c) => c.id === selectedCoinId);
+ const inputAmount = parseFloat(amount);
+ if (!coin) return;
+
+ const changePercent = coin.price_change_percentage_24h;
+ const changeDecimal = changePercent / 100;
+ const profitOrLoss = inputAmount * changeDecimal;
+ const finalAmount = inputAmount + profitOrLoss;
+
+ setResult({
+ finalAmount: finalAmount.toFixed(2),
+ profitOrLoss: profitOrLoss.toFixed(2),
+ isProfit: profitOrLoss >= 0,
+ error: null,
+ });
+ };
+
+ const filteredCoins = coinData.filter(coin =>
+ coin.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
+ coin.symbol.toLowerCase().includes(searchTerm.toLowerCase())
+ );
+
+ const selectedCoin = coinData.find(c => c.id === selectedCoinId);
+
+ return (
+
+
e.stopPropagation()}>
+
+
24h Profit/Loss Calculator
+
+
+
+ setAmount(e.target.value)}
+ placeholder="e.g., 100"
+ className="modal-input"
+ />
+
+
+
+
+
+
{
+ setSearchTerm(e.target.value);
+ setIsDropdownOpen(true);
+ }}
+ onFocus={() => setIsDropdownOpen(true)}
+ placeholder="Search coin..."
+ />
+ {isDropdownOpen && (
+
+ {filteredCoins.length > 0 ? (
+ filteredCoins.map((coin) => (
+
{
+ setSelectedCoinId(coin.id);
+ setSearchTerm('');
+ setIsDropdownOpen(false);
+ }}
+ >
+

+ {coin.name} ({coin.symbol.toUpperCase()})
+
+ ))
+ ) : (
+
+ No results found
+
+ )}
+
+ )}
+
+
+
+
+
+ {result && (
+
+ {result.error ? (
+
{result.error}
+ ) : (
+ <>
+
Your ${amount} invested 24h ago would now be worth:
+
+ ${result.finalAmount}
+
+
+ A {result.isProfit ? 'profit' : 'loss'} of{' '}
+
+ {result.isProfit ? '+' : ''}${result.profitOrLoss}
+
+
+ >
+ )}
+
+ )}
+
+
+ );
+}
diff --git a/src/pages/Crypto.jsx b/src/pages/Crypto.jsx
index 3d659e7..0781f34 100644
--- a/src/pages/Crypto.jsx
+++ b/src/pages/Crypto.jsx
@@ -26,7 +26,7 @@ import Card from "../components/Card.jsx";
import formatNumber from "../utilities/numberFormatter.js";
import HeroSection from '../components/HeroSection';
import CryptoImg from '../Images/Cryptocurrency.jpg';
-
+import CryptoCalculatorModal from "../components/CryptoCalculatorModal.jsx";
export default function Crypto() {
const [coins, setCoins] = useState([]);
@@ -34,6 +34,7 @@ export default function Crypto() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const [page, setPage] = useState(1);
+ const [isCalculatorOpen, setIsCalculatorOpen] = useState(false);
useEffect(() => {
fetchCoins();
@@ -79,6 +80,23 @@ export default function Crypto() {
style={{ marginBottom: "1rem" }}
/>
+
+
+
+
{loading && }
@@ -134,6 +152,14 @@ export default function Crypto() {
+
+ {isCalculatorOpen && coins.length > 0 && (
+ setIsCalculatorOpen(false)}
+ />
+ )}
+
);
}
diff --git a/src/styles.css b/src/styles.css
index e395cd2..751b1c4 100644
--- a/src/styles.css
+++ b/src/styles.css
@@ -922,4 +922,138 @@ blockquote {
}
}
+.modal-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: rgba(0, 0, 0, 0.7);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+ animation: fadeIn 0.2s ease-out;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+ to {
+ opacity: 1;
+ }
+}
+
+.modal {
+ background-color: var(--bg);
+ color: var(--text);
+ padding: 2rem;
+ border-radius: var(--radius);
+ width: 90%;
+ max-width: 500px;
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
+ position: relative;
+ animation: modalSlideIn 0.3s ease-out;
+}
+
+@keyframes modalSlideIn {
+ from {
+ opacity: 0;
+ transform: translateY(-20px) scale(0.95);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+}
+
+.modal-close-button {
+ position: absolute;
+ top: 1rem;
+ right: 1rem;
+ background: transparent;
+ border: none;
+ font-size: 1.5rem;
+ cursor: pointer;
+ color: var(--text);
+ opacity: 0.7;
+ transition: opacity 0.2s ease;
+}
+
+.modal-close-button:hover {
+ opacity: 1;
+}
+.modal-input-group {
+ margin-bottom: 1rem;
+}
+
+.modal-input-group label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: bold;
+}
+
+.modal-input {
+ width: 100%;
+ padding: 0.5rem 0.75rem;
+ border: 1px solid var(--border);
+ border-radius: var(--radius);
+ background: var(--bg-alt);
+ color: var(--text);
+ box-sizing: border-box;
+}
+
+.modal-button {
+ width: 100%;
+ padding: 0.75rem;
+ font-size: 1rem;
+}
+
+.modal-result {
+ margin-top: 1.5rem;
+ padding: 1rem;
+ border: 1px solid var(--border);
+ border-radius: var(--radius);
+ background-color: var(--bg-alt);
+ text-align: center;
+}
+
+.modal-dropdown-container {
+ position: relative;
+}
+
+.modal-dropdown-list {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ right: 0;
+ background-color: var(--bg);
+ border: 1px solid var(--border);
+ border-top: none;
+ border-radius: 0 0 var(--radius) var(--radius);
+ max-height: 150px;
+ overflow-y: auto;
+ z-index: 1001;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+}
+
+.modal-dropdown-item,
+.modal-dropdown-item-none {
+ padding: 0.75rem;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.modal-dropdown-item:hover {
+ background-color: var(--bg-alt);
+}
+
+.modal-dropdown-item-none {
+ font-style: italic;
+ opacity: 0.7;
+ cursor: default;
+}