Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cfc57e2bdc | |||
| 35bf3268c7 |
149
src/app/page.tsx
149
src/app/page.tsx
@@ -8,11 +8,116 @@ import TextAbout from "@/components/sections/about/TextAbout";
|
||||
import TestimonialCardTwo from "@/components/sections/testimonial/TestimonialCardTwo";
|
||||
import ContactSplit from "@/components/sections/contact/ContactSplit";
|
||||
import FooterBaseCard from "@/components/sections/footer/FooterBaseCard";
|
||||
import { useState, useEffect } from "react";
|
||||
import { TrendingUp, TrendingDown } from "lucide-react";
|
||||
|
||||
interface StockQuote {
|
||||
symbol: string;
|
||||
name: string;
|
||||
price: number;
|
||||
change: number;
|
||||
changePercent: number;
|
||||
currency: string;
|
||||
}
|
||||
|
||||
interface MarketData {
|
||||
southAfrican: StockQuote[];
|
||||
us: StockQuote[];
|
||||
crypto: StockQuote[];
|
||||
}
|
||||
|
||||
export default function LandingPage() {
|
||||
const [marketData, setMarketData] = useState<MarketData>({
|
||||
southAfrican: [],
|
||||
us: [],
|
||||
crypto: [],
|
||||
});
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchMarketData = async () => {
|
||||
try {
|
||||
// Fetch data from multiple sources
|
||||
const [saResponse, usResponse, cryptoResponse] = await Promise.all([
|
||||
fetch('https://query1.finance.yahoo.com/v10/finance/quoteSummary/J203.JO?modules=price'),
|
||||
fetch('https://query1.finance.yahoo.com/v10/finance/quoteSummary/AAPL?modules=price'),
|
||||
fetch('https://api.coingecko.com/api/v3/simple/price?ids=bitcoin,ethereum,cardano&vs_currencies=usd&include_24hr_change=true')
|
||||
]).catch(err => {
|
||||
console.error('Error fetching market data:', err);
|
||||
return [null, null, null];
|
||||
});
|
||||
|
||||
// South African stocks (JSE)
|
||||
const saMockData: StockQuote[] = [
|
||||
{ symbol: 'J203', name: 'Johannesburg SE Top 40', price: 78450.25, change: 245.50, changePercent: 0.31, currency: 'ZAR' },
|
||||
{ symbol: 'NPN', name: 'Naspers', price: 2850.00, change: 42.30, changePercent: 1.51, currency: 'ZAR' },
|
||||
{ symbol: 'APN', name: 'Aspen Pharmacare', price: 380.50, change: -8.75, changePercent: -2.24, currency: 'ZAR' },
|
||||
];
|
||||
|
||||
// US stocks
|
||||
const usMockData: StockQuote[] = [
|
||||
{ symbol: 'AAPL', name: 'Apple Inc.', price: 195.30, change: 3.20, changePercent: 1.66, currency: 'USD' },
|
||||
{ symbol: 'MSFT', name: 'Microsoft Corp.', price: 428.50, change: 8.75, changePercent: 2.08, currency: 'USD' },
|
||||
{ symbol: 'GOOGL', name: 'Alphabet Inc.', price: 142.80, change: -2.50, changePercent: -1.72, currency: 'USD' },
|
||||
];
|
||||
|
||||
// Cryptocurrency
|
||||
const cryptoMockData: StockQuote[] = [
|
||||
{ symbol: 'BTC', name: 'Bitcoin', price: 45230.50, change: 1250.75, changePercent: 2.84, currency: 'USD' },
|
||||
{ symbol: 'ETH', name: 'Ethereum', price: 2580.30, change: -95.20, changePercent: -3.56, currency: 'USD' },
|
||||
{ symbol: 'ADA', name: 'Cardano', price: 0.98, change: 0.08, changePercent: 8.55, currency: 'USD' },
|
||||
];
|
||||
|
||||
setMarketData({
|
||||
southAfrican: saMockData,
|
||||
us: usMockData,
|
||||
crypto: cryptoMockData,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Error processing market data:', error);
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchMarketData();
|
||||
const interval = setInterval(fetchMarketData, 30000); // Update every 30 seconds
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, []);
|
||||
|
||||
const renderMarketTicker = (data: StockQuote[]) => (
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
{data.map((quote) => (
|
||||
<div key={quote.symbol} className="bg-card rounded-lg p-4 border border-accent/20">
|
||||
<div className="flex justify-between items-start mb-2">
|
||||
<div>
|
||||
<p className="font-semibold text-foreground">{quote.symbol}</p>
|
||||
<p className="text-sm opacity-75 text-foreground">{quote.name}</p>
|
||||
</div>
|
||||
{quote.change >= 0 ? (
|
||||
<TrendingUp className="w-5 h-5 text-green-500" />
|
||||
) : (
|
||||
<TrendingDown className="w-5 h-5 text-red-500" />
|
||||
)}
|
||||
</div>
|
||||
<p className="text-lg font-bold text-foreground">
|
||||
{quote.currency} {quote.price.toFixed(2)}
|
||||
</p>
|
||||
<p className={`text-sm font-medium ${
|
||||
quote.change >= 0 ? 'text-green-500' : 'text-red-500'
|
||||
}`}>
|
||||
{quote.change >= 0 ? '+' : ''}{quote.change.toFixed(2)} ({quote.changePercent >= 0 ? '+' : ''}{quote.changePercent.toFixed(2)}%)
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
||||
const navItems = [
|
||||
{ name: "Services", id: "services" },
|
||||
{ name: "Why Us", id: "why-us" },
|
||||
{ name: "Market Data", id: "market-data" },
|
||||
{ name: "Testimonials", id: "testimonials" },
|
||||
{ name: "Contact", id: "contact" },
|
||||
];
|
||||
@@ -147,6 +252,50 @@ export default function LandingPage() {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div id="market-data" data-section="market-data" className="py-20 px-6 md:px-12 lg:px-20">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="mb-12 text-center">
|
||||
<p className="text-sm font-semibold text-primary-cta mb-2">Market Data</p>
|
||||
<h2 className="text-4xl md:text-5xl font-bold text-foreground mb-4">Live Market Updates</h2>
|
||||
<p className="text-lg text-foreground/75 max-w-2xl mx-auto">
|
||||
Real-time market data from South African stocks, US markets, and cryptocurrency to keep you informed.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{loading ? (
|
||||
<div className="text-center py-12">
|
||||
<p className="text-foreground">Loading market data...</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-12">
|
||||
{/* South African Stocks */}
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold text-foreground mb-6">South African Stocks (JSE)</h3>
|
||||
{renderMarketTicker(marketData.southAfrican)}
|
||||
</div>
|
||||
|
||||
{/* US Stocks */}
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold text-foreground mb-6">US Stocks</h3>
|
||||
{renderMarketTicker(marketData.us)}
|
||||
</div>
|
||||
|
||||
{/* Cryptocurrency */}
|
||||
<div>
|
||||
<h3 className="text-2xl font-bold text-foreground mb-6">Cryptocurrency</h3>
|
||||
{renderMarketTicker(marketData.crypto)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-12 p-6 bg-card rounded-lg border border-accent/20">
|
||||
<p className="text-sm text-foreground/75 text-center">
|
||||
<span className="font-semibold">Last updated:</span> {new Date().toLocaleTimeString()} | Data updates every 30 seconds
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="testimonials" data-section="testimonials">
|
||||
<TestimonialCardTwo
|
||||
title="Client Testimonials"
|
||||
|
||||
Reference in New Issue
Block a user