Initial commit: SAPIENS Stock service
This commit is contained in:
136
components/stock-header.tsx
Normal file
136
components/stock-header.tsx
Normal file
@ -0,0 +1,136 @@
|
||||
"use client"
|
||||
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { TrendingUp, TrendingDown, Star } from "lucide-react"
|
||||
|
||||
interface StockHeaderProps {
|
||||
symbol: string
|
||||
activeTab: string
|
||||
onTabChange: (tab: string) => void
|
||||
}
|
||||
|
||||
export function StockHeader({ symbol, activeTab, onTabChange }: StockHeaderProps) {
|
||||
// Mock data - in real app this would come from an API
|
||||
const stockData = {
|
||||
TSLA: {
|
||||
name: "Tesla, Inc.",
|
||||
symbol: "TSLA",
|
||||
exchange: "NASDAQ",
|
||||
price: 423.39,
|
||||
afterHoursPrice: 417.13,
|
||||
change: 18.4,
|
||||
changePercent: 4.38,
|
||||
afterHoursChange: -6.26,
|
||||
afterHoursChangePercent: -1.48,
|
||||
lastUpdate: "At close: Sep 25, 4:00 PM EDT",
|
||||
afterHoursUpdate: "After hours: Sep 26, 6:08 AM EDT",
|
||||
},
|
||||
}
|
||||
|
||||
const stock = stockData[symbol as keyof typeof stockData] || stockData.TSLA
|
||||
const isPositive = stock.change > 0
|
||||
const isAfterHoursPositive = stock.afterHoursChange > 0
|
||||
|
||||
const tabs = [
|
||||
{ id: "overview", label: "Overview" },
|
||||
{ id: "historical", label: "Historical Data" },
|
||||
{ id: "financials", label: "Financials" },
|
||||
{ id: "earnings", label: "Earnings" },
|
||||
{ id: "research", label: "Research" },
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="bg-card border border-border rounded-lg">
|
||||
<div className="p-3 sm:p-4 md:p-6">
|
||||
<div className="flex items-start justify-between mb-3 sm:mb-4 md:mb-6">
|
||||
<div className="flex items-center space-x-2 sm:space-x-3">
|
||||
<div className="w-8 h-8 sm:w-10 sm:h-10 bg-destructive rounded-sm flex items-center justify-center">
|
||||
<span className="text-destructive-foreground font-bold text-sm sm:text-base">T</span>
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-lg sm:text-xl md:text-2xl font-bold text-foreground leading-tight">{stock.name}</h1>
|
||||
<div className="flex items-center space-x-1 sm:space-x-2 text-muted-foreground">
|
||||
<span className="text-xs sm:text-sm">{stock.symbol}</span>
|
||||
<span className="text-xs sm:text-sm">•</span>
|
||||
<span className="text-xs sm:text-sm">{stock.exchange}</span>
|
||||
<Badge variant="secondary" className="ml-1 sm:ml-2 text-xs">
|
||||
🇺🇸
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Button variant="outline" size="sm" className="text-xs sm:text-sm bg-transparent">
|
||||
<Star className="w-3 h-3 sm:w-4 sm:h-4 mr-1 sm:mr-2" />
|
||||
Add to Watchlist
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 sm:gap-6 md:gap-8">
|
||||
{/* Regular Hours */}
|
||||
<div>
|
||||
<div className="flex items-baseline space-x-2 sm:space-x-3 md:space-x-4 mb-1 sm:mb-2">
|
||||
<span className="text-2xl font-bold text-foreground leading-tight">US${stock.price.toFixed(2)}</span>
|
||||
<div className={`flex items-center space-x-1 ${isPositive ? "text-success" : "text-destructive"}`}>
|
||||
{isPositive ? (
|
||||
<TrendingUp className="w-3 h-3 sm:w-4 sm:h-4" />
|
||||
) : (
|
||||
<TrendingDown className="w-3 h-3 sm:w-4 sm:h-4" />
|
||||
)}
|
||||
<span className="font-medium text-sm sm:text-base">US${Math.abs(stock.change).toFixed(2)}</span>
|
||||
<span className="font-medium text-sm sm:text-base">
|
||||
{isPositive ? "+" : ""}
|
||||
{stock.changePercent.toFixed(2)}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-xs sm:text-sm text-muted-foreground leading-tight">{stock.lastUpdate}</p>
|
||||
</div>
|
||||
|
||||
{/* After Hours */}
|
||||
<div>
|
||||
<div className="flex items-baseline space-x-2 sm:space-x-3 md:space-x-4 mb-1 sm:mb-2">
|
||||
<span className="text-2xl font-bold text-foreground leading-tight">
|
||||
US${stock.afterHoursPrice.toFixed(2)}
|
||||
</span>
|
||||
<div
|
||||
className={`flex items-center space-x-1 ${isAfterHoursPositive ? "text-success" : "text-destructive"}`}
|
||||
>
|
||||
{isAfterHoursPositive ? (
|
||||
<TrendingUp className="w-3 h-3 sm:w-4 sm:h-4" />
|
||||
) : (
|
||||
<TrendingDown className="w-3 h-3 sm:w-4 sm:h-4" />
|
||||
)}
|
||||
<span className="font-medium text-sm sm:text-base">
|
||||
US${Math.abs(stock.afterHoursChange).toFixed(2)}
|
||||
</span>
|
||||
<span className="font-medium text-sm sm:text-base">
|
||||
{isAfterHoursPositive ? "+" : ""}
|
||||
{stock.afterHoursChangePercent.toFixed(2)}%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-xs sm:text-sm text-muted-foreground leading-tight">{stock.afterHoursUpdate}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-3 sm:space-x-4 md:space-x-6 border-t border-border px-3 sm:px-4 md:px-6 py-2 sm:py-3">
|
||||
{tabs.map((tab) => (
|
||||
<Button
|
||||
key={tab.id}
|
||||
variant="ghost"
|
||||
onClick={() => onTabChange(tab.id)}
|
||||
className={`rounded-none pb-2 sm:pb-3 text-xs sm:text-sm ${
|
||||
activeTab === tab.id
|
||||
? "text-foreground border-b-2 border-primary"
|
||||
: "text-muted-foreground hover:text-foreground"
|
||||
}`}
|
||||
>
|
||||
{tab.label}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user