Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 41 additions & 7 deletions src/components/NewsBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,70 @@
<<<<<<< HEAD
/**
* News Banner Component.
* A dismissible top-level banner for announcing major protocol updates or news.
* Persists visibility only within the current session.
*/
=======
"use client";

import React, { useState } from 'react';
import { X } from 'lucide-react';
import Icon from './ui/Icon';
>>>>>>> upstream/main

import React, { useState } from 'react';
import { X, Sparkles } from 'lucide-react';

/**
* A stylized notification banner for global announcements.
*/
export default function NewsBanner() {
// --- Component State ---
const [isVisible, setIsVisible] = useState(true);

// 1. Conditional Rendering for Visibility
if (!isVisible) return null;

return (
<div className="bg-gradient-to-r from-blue-600 to-purple-600 text-white py-3 px-4 relative">
<div
className="bg-gradient-to-r from-blue-600 to-indigo-700 text-white py-2.5 px-4 relative shadow-md z-50 animate-in slide-in-from-top duration-500"
role="status"
aria-label="Important Announcement"
>
<div className="max-w-7xl mx-auto flex items-center justify-center">
<div className="flex items-center gap-2">
<span className="text-lg">🚀</span>
<span className="text-sm font-medium">
TradeFlow Mainnet Beta is now live! 🚀
<div className="flex items-center gap-3">
{/* Decorative Icon */}
<div className="bg-white/20 p-1 rounded-lg">
<Sparkles size={14} className="text-blue-100" />
</div>
<span className="text-[11px] sm:text-xs font-black uppercase tracking-[0.2em]">
TradeFlow Mainnet Beta is now live!
</span>
<span className="hidden sm:inline-block bg-white text-blue-600 text-[10px] px-2 py-0.5 rounded-full font-bold">
NEW
</span>
</div>
</div>

{/* Dismiss Button */}
<button
onClick={() => setIsVisible(false)}
className="absolute right-4 top-1/2 transform -translate-y-1/2 text-white/80 hover:text-white transition-colors"
aria-label="Close banner"
className="absolute right-3 top-1/2 transform -translate-y-1/2 p-1.5 text-white/70 hover:text-white hover:bg-white/10 rounded-full transition-all active:scale-90"
aria-label="Dismiss banner"
>
<<<<<<< HEAD
<X size={14} />
=======
<Icon icon={X} dense />
>>>>>>> upstream/main
</button>
</div>
);
}

<<<<<<< HEAD
=======
// Inconsequential change for repo health

// Maintenance: minor update
>>>>>>> upstream/main
101 changes: 78 additions & 23 deletions src/components/ProModeSection.tsx
Original file line number Diff line number Diff line change
@@ -1,77 +1,129 @@
/**
* Pro Mode Section Component.
* Handles the logic for toggling advanced trading features,
* including token-gated access to high-resolution charts.
*/

"use client";

import React, { useState, useEffect } from "react";
import dynamic from "next/dynamic";
import Toggle from "../app/Toggle";
import { useTokenStore } from "../stores/tokenStore";
import PremiumUnlockModal from "./PremiumUnlockModal";
<<<<<<< HEAD
import { Zap, Crown, Lock } from "lucide-react";
=======
import SkeletonCard from "./ui/SkeletonCard";
>>>>>>> upstream/main

// Dynamically import the heavy chart component with loading fallback
/**
* Dynamically import the heavy TradingView-style chart component.
* Uses a skeleton fallback to prevent layout shifts during hydration.
*/
const LivePriceChart = dynamic(() => import("../components/LivePriceChart"), {
ssr: false,
loading: () => (
<<<<<<< HEAD
<div className="w-full h-96 bg-slate-900/50 rounded-3xl border border-slate-700/30 flex items-center justify-center animate-pulse">
=======
<SkeletonCard height="h-96" className="flex items-center justify-center">
>>>>>>> upstream/main
<div className="text-center">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-500 mx-auto mb-3"></div>
<p className="text-slate-400 text-sm">Loading Pro Chart...</p>
<div className="animate-spin rounded-full h-10 w-10 border-t-2 border-b-2 border-blue-500 mx-auto mb-4"></div>
<p className="text-slate-500 text-[10px] font-black uppercase tracking-widest">Hydrating Pro Engine...</p>
</div>
</SkeletonCard>
),
});

/**
* A section that manages the state and access control for "Pro Mode".
*/
export default function ProModeSection() {
// --- Component State ---
/** Local toggle state for the current session */
const [isProMode, setIsProMode] = useState(false);
/** Controls visibility of the TF token paywall modal */
const [showPaywall, setShowPaywall] = useState(false);

/** Access logic from the token store */
const { tfTokenBalance, isConnected, hasProModeAccess } = useTokenStore();

/**
* Handles user interaction with the Pro Mode toggle.
* Validates wallet connection and token requirements before enabling.
*/
const handleProModeToggle = () => {
// If trying to enable pro mode
// 1. Logic for enabling Pro Mode
if (!isProMode) {
if (!isConnected) {
// User is not connected to wallet
alert('Please connect your wallet to enable Pro Mode');
// TODO: Replace with a non-blocking toast notification
alert('Please connect your Stellar wallet to access Pro Mode features.');
return;
}

if (!hasProModeAccess()) {
// User doesn't have enough TF tokens - show paywall
// User is connected but lacks sufficient TF token balance
setShowPaywall(true);
return;
}
}

// Allow toggle (either disabling pro mode or user has access)
// 2. Commit the toggle state change
setIsProMode(!isProMode);
};

return (
<>
<div className="bg-slate-800/40 rounded-2xl border border-slate-700/50 p-6 mt-8">
<div className="flex items-center justify-between mb-4">
<div>
<h3 className="text-lg font-semibold text-white">Pro Mode Charts</h3>
<p className="text-sm text-slate-400">
Enable advanced TradingView-style charts with live data.
{!isConnected && " (Connect wallet to enable)"}
{isConnected && !hasProModeAccess() && " (Requires 1,000+ TF tokens)"}
<section
className="bg-slate-800/30 rounded-3xl border border-slate-700/50 p-8 mt-12 group transition-all duration-500 hover:bg-slate-800/50"
aria-labelledby="pro-mode-title"
>
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6">
<div className="space-y-2">
<div className="flex items-center gap-3">
<div className={`p-2 rounded-xl transition-colors duration-500 ${isProMode ? "bg-blue-500 text-white shadow-lg shadow-blue-500/20" : "bg-slate-700 text-slate-400"}`}>
{isProMode ? <Zap size={20} /> : <Crown size={20} />}
</div>
<h3 id="pro-mode-title" className="text-xl font-bold text-white tracking-tight">Pro Mode Analytics</h3>
</div>
<p className="text-sm text-slate-500 leading-relaxed max-w-lg">
Unlock advanced technical indicators and sub-second price feeds.
{!isConnected && (
<span className="flex items-center gap-1.5 mt-2 text-rose-400/80 font-medium">
<Lock size={12} /> Connect wallet to unlock
</span>
)}
{isConnected && !hasProModeAccess() && (
<span className="flex items-center gap-1.5 mt-2 text-blue-400/80 font-medium">
<Zap size={12} /> Requires 1,000+ TF utility tokens
</span>
)}
</p>
</div>
<Toggle
isOn={isProMode}
onToggle={handleProModeToggle}
disabled={!isConnected || (!hasProModeAccess() && !isProMode)}
/>

<div className="flex items-center gap-4 bg-slate-900/40 p-4 rounded-2xl border border-slate-800">
<span className={`text-[10px] font-black uppercase tracking-widest ${isProMode ? "text-blue-400" : "text-slate-600"}`}>
{isProMode ? "Active" : "Inactive"}
</span>
<Toggle
isOn={isProMode}
onToggle={handleProModeToggle}
disabled={!isConnected || (!hasProModeAccess() && !isProMode)}
/>
</div>
</div>

{/* Conditional Rendering of Pro Content */}
{isProMode && (
<div className="mt-6">
<div className="mt-10 animate-in fade-in slide-in-from-bottom-4 duration-700">
<LivePriceChart />
</div>
)}
</div>
</section>

{/* Paywall Modal Overlay */}
<PremiumUnlockModal
isOpen={showPaywall}
onClose={() => setShowPaywall(false)}
Expand All @@ -81,6 +133,9 @@ export default function ProModeSection() {
);
}

<<<<<<< HEAD
=======
// Inconsequential change for repo health

// Maintenance: minor update
>>>>>>> upstream/main
Loading
Loading