Fix Tailwind CSS styling configuration

- Add tailwind.config.ts with proper content paths and theme config
- Add postcss.config.js for Tailwind and autoprefixer processing
- Downgrade tailwindcss to v3.4.17 and add missing PostCSS dependencies
- Update Dockerfile to clarify build process
- Fix UI styling issues in Docker environment
This commit is contained in:
mindesbunister
2025-07-12 23:29:42 +02:00
parent cf58d41444
commit a9bbcc7b5f
22 changed files with 3833 additions and 1020 deletions

View File

@@ -0,0 +1,124 @@
import { NextRequest, NextResponse } from 'next/server'
import { tradingViewAutomation } from '../../../lib/tradingview-automation'
export async function GET(request: NextRequest) {
try {
console.log('📊 Getting TradingView session status...')
// Initialize if not already done (Docker-safe initialization)
if (!tradingViewAutomation['browser']) {
console.log('🐳 Initializing TradingView automation in Docker environment...')
await tradingViewAutomation.init()
}
// Get lightweight session information without navigation
const sessionInfo = await tradingViewAutomation.getQuickSessionStatus()
// Determine connection status based on browser state and URL
let connectionStatus = 'unknown'
if (sessionInfo.browserActive) {
if (sessionInfo.currentUrl.includes('tradingview.com')) {
connectionStatus = 'connected'
} else if (sessionInfo.currentUrl) {
connectionStatus = 'disconnected'
} else {
connectionStatus = 'unknown'
}
} else {
connectionStatus = 'disconnected'
}
const response = {
success: true,
session: {
...sessionInfo,
connectionStatus,
lastChecked: new Date().toISOString(),
dockerEnv: process.env.DOCKER_ENV === 'true',
environment: process.env.NODE_ENV || 'development'
}
}
console.log('✅ Session status retrieved:', response.session)
return NextResponse.json(response)
} catch (error) {
console.error('❌ Failed to get session status:', error)
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Failed to get session status',
session: {
isAuthenticated: false,
hasSavedCookies: false,
hasSavedStorage: false,
cookiesCount: 0,
currentUrl: '',
connectionStatus: 'error',
lastChecked: new Date().toISOString(),
dockerEnv: process.env.DOCKER_ENV === 'true',
environment: process.env.NODE_ENV || 'development'
}
}, { status: 500 })
}
}
export async function POST(request: NextRequest) {
try {
const { action } = await request.json()
console.log(`🔧 Session action requested: ${action} (Docker: ${process.env.DOCKER_ENV === 'true'})`)
// Initialize if not already done (Docker-safe initialization)
if (!tradingViewAutomation['browser']) {
console.log('🐳 Initializing TradingView automation for session action in Docker...')
await tradingViewAutomation.init()
}
let result: any = { success: true }
switch (action) {
case 'refresh':
const refreshed = await tradingViewAutomation.refreshSession()
result.refreshed = refreshed
result.message = refreshed ? 'Session refreshed successfully' : 'Failed to refresh session'
break
case 'clear':
await tradingViewAutomation.clearSession()
result.message = 'Session data cleared successfully'
break
case 'test':
const testResult = await tradingViewAutomation.testSessionPersistence()
result.testResult = testResult
result.message = testResult.isValid ? 'Session is valid' : 'Session is invalid or expired'
break
case 'login-status':
const isLoggedIn = await tradingViewAutomation.checkLoginStatus()
result.isLoggedIn = isLoggedIn
result.message = isLoggedIn ? 'User is logged in' : 'User is not logged in'
break
default:
result.success = false
result.error = `Unknown action: ${action}`
return NextResponse.json(result, { status: 400 })
}
console.log(`✅ Session action '${action}' completed:`, result)
return NextResponse.json({
...result,
dockerEnv: process.env.DOCKER_ENV === 'true',
environment: process.env.NODE_ENV || 'development'
})
} catch (error) {
console.error('❌ Session action failed:', error)
return NextResponse.json({
success: false,
error: error instanceof Error ? error.message : 'Session action failed',
dockerEnv: process.env.DOCKER_ENV === 'true',
environment: process.env.NODE_ENV || 'development'
}, { status: 500 })
}
}

View File

@@ -1,7 +1,170 @@
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--bg-primary: #0a0a0b;
--bg-secondary: #1a1a1b;
--bg-tertiary: #262626;
--bg-card: #1e1e1f;
--border-primary: #333;
--text-primary: #ffffff;
--text-secondary: #a1a1aa;
--text-accent: #22d3ee;
--success: #10b981;
--danger: #ef4444;
--warning: #f59e0b;
--purple: #8b5cf6;
--blue: #3b82f6;
}
* {
box-sizing: border-box;
}
body {
font-family: 'Inter', system-ui, sans-serif;
background: linear-gradient(135deg, var(--bg-primary) 0%, #0f0f0f 100%);
color: var(--text-primary);
overflow-x: hidden;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 6px;
}
::-webkit-scrollbar-track {
background: var(--bg-secondary);
}
::-webkit-scrollbar-thumb {
background: var(--border-primary);
border-radius: 3px;
}
::-webkit-scrollbar-thumb:hover {
background: #555;
}
/* Glass morphism effect */
.glass {
background: rgba(26, 26, 27, 0.8);
backdrop-filter: blur(20px);
border: 1px solid rgba(255, 255, 255, 0.1);
}
/* Gradient borders */
.gradient-border {
position: relative;
background: var(--bg-card);
border-radius: 12px;
}
.gradient-border::before {
content: '';
position: absolute;
inset: 0;
padding: 1px;
background: linear-gradient(135deg, rgba(34, 211, 238, 0.3), rgba(139, 92, 246, 0.3));
border-radius: inherit;
mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
mask-composite: subtract;
}
/* Button components */
@layer components {
.btn {
@apply px-4 py-2 rounded-lg font-medium transition-all duration-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-900;
}
.btn-primary {
@apply bg-gradient-to-r from-cyan-500 to-blue-600 hover:from-cyan-600 hover:to-blue-700 text-white shadow-lg hover:shadow-cyan-500/25;
}
.btn-secondary {
@apply bg-gray-700 hover:bg-gray-600 text-gray-100 border border-gray-600;
}
.btn-success {
@apply bg-gradient-to-r from-green-500 to-emerald-600 hover:from-green-600 hover:to-emerald-700 text-white shadow-lg hover:shadow-green-500/25;
}
.btn-danger {
@apply bg-gradient-to-r from-red-500 to-rose-600 hover:from-red-600 hover:to-rose-700 text-white shadow-lg hover:shadow-red-500/25;
}
.btn-warning {
@apply bg-gradient-to-r from-yellow-500 to-orange-600 hover:from-yellow-600 hover:to-orange-700 text-white shadow-lg hover:shadow-yellow-500/25;
}
.card {
@apply bg-gray-900/50 backdrop-blur-sm border border-gray-800 rounded-xl p-6 shadow-xl hover:shadow-2xl transition-all duration-300;
}
.card-gradient {
@apply relative overflow-hidden;
background: linear-gradient(135deg, rgba(30, 30, 31, 0.9) 0%, rgba(26, 26, 27, 0.9) 100%);
}
.card-gradient::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 1px;
background: linear-gradient(90deg, transparent, rgba(34, 211, 238, 0.5), transparent);
}
.status-indicator {
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium;
}
.status-online {
@apply bg-green-100 text-green-800 border border-green-200;
}
.status-offline {
@apply bg-red-100 text-red-800 border border-red-200;
}
.status-pending {
@apply bg-yellow-100 text-yellow-800 border border-yellow-200;
}
}
/* Animations */
@keyframes pulse-glow {
0%, 100% {
box-shadow: 0 0 5px rgba(34, 211, 238, 0.5);
}
50% {
box-shadow: 0 0 20px rgba(34, 211, 238, 0.8), 0 0 30px rgba(34, 211, 238, 0.4);
}
}
.pulse-glow {
animation: pulse-glow 2s ease-in-out infinite;
}
@keyframes slide-up {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.slide-up {
animation: slide-up 0.6s ease-out;
}
/* Loading spinner */
.spinner {
@apply inline-block w-4 h-4 border-2 border-gray-300 border-t-cyan-500 rounded-full animate-spin;
}

View File

@@ -3,16 +3,68 @@ import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'Trading Bot Dashboard',
description: 'AI-powered trading bot dashboard with auto-trading, analysis, and developer tools.'
description: 'AI-powered trading bot dashboard with auto-trading, analysis, and developer tools.',
viewport: 'width=device-width, initial-scale=1',
}
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body className="bg-gray-950 text-gray-100 min-h-screen" suppressHydrationWarning>
<main className="max-w-5xl mx-auto py-8">
{children}
</main>
<body className="bg-gray-950 text-gray-100 min-h-screen antialiased" suppressHydrationWarning>
<div className="min-h-screen bg-gradient-to-br from-gray-950 via-gray-900 to-gray-950">
{/* Header */}
<header className="border-b border-gray-800 bg-gray-900/50 backdrop-blur-sm">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center h-16">
<div className="flex items-center space-x-4">
<div className="flex items-center space-x-2">
<div className="w-8 h-8 bg-gradient-to-br from-cyan-400 to-blue-600 rounded-lg flex items-center justify-center">
<span className="text-white font-bold text-sm">TB</span>
</div>
<div>
<h1 className="text-xl font-bold text-white">Trading Bot</h1>
<p className="text-xs text-gray-400">AI-Powered Dashboard</p>
</div>
</div>
</div>
<div className="flex items-center space-x-4">
<div className="hidden sm:flex items-center space-x-2 text-sm">
<div className="w-2 h-2 bg-green-400 rounded-full animate-pulse"></div>
<span className="text-gray-300">Live</span>
</div>
<div className="flex items-center space-x-2">
<div className="w-8 h-8 bg-gray-700 rounded-full flex items-center justify-center">
<span className="text-gray-300 text-sm">👤</span>
</div>
</div>
</div>
</div>
</div>
</header>
{/* Main Content */}
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
{children}
</main>
{/* Footer */}
<footer className="border-t border-gray-800 bg-gray-900/30 backdrop-blur-sm mt-16">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-6">
<div className="flex flex-col sm:flex-row justify-between items-center">
<div className="text-sm text-gray-400">
© 2025 Trading Bot Dashboard. Powered by AI.
</div>
<div className="flex items-center space-x-4 mt-4 sm:mt-0">
<div className="text-xs text-gray-500">
Next.js 15 TypeScript Tailwind CSS
</div>
</div>
</div>
</div>
</footer>
</div>
</body>
</html>
)

View File

@@ -1,11 +1,20 @@
import AIAnalysisPanel from '../components/AIAnalysisPanel'
import Dashboard from '../components/Dashboard'
export default function HomePage() {
return (
<>
<AIAnalysisPanel />
<div className="space-y-8">
{/* Hero Section */}
<div className="text-center py-8">
<h1 className="text-4xl font-bold bg-gradient-to-r from-cyan-400 to-blue-600 bg-clip-text text-transparent mb-4">
AI Trading Dashboard
</h1>
<p className="text-gray-400 text-lg max-w-2xl mx-auto">
Advanced cryptocurrency trading with AI-powered analysis, automated execution, and real-time monitoring.
</p>
</div>
{/* Main Dashboard */}
<Dashboard />
</>
</div>
)
}