add fixed ADS
This commit is contained in:
137
App.tsx
137
App.tsx
@@ -17,6 +17,15 @@ const App: React.FC = () => {
|
|||||||
const [errorMsg, setErrorMsg] = useState<string | null>(null);
|
const [errorMsg, setErrorMsg] = useState<string | null>(null);
|
||||||
|
|
||||||
// Polling Logic
|
// Polling Logic
|
||||||
|
useEffect(() => {
|
||||||
|
try {
|
||||||
|
// @ts-ignore
|
||||||
|
(window.adsbygoogle = window.adsbygoogle || []).push({});
|
||||||
|
} catch (e) {
|
||||||
|
console.error("AdSense error", e);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let isMounted = true;
|
let isMounted = true;
|
||||||
let timeoutId: number;
|
let timeoutId: number;
|
||||||
@@ -136,28 +145,42 @@ const App: React.FC = () => {
|
|||||||
<nav className="flex-1 px-4 space-y-2 mt-4">
|
<nav className="flex-1 px-4 space-y-2 mt-4">
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveTab('dashboard')}
|
onClick={() => setActiveTab('dashboard')}
|
||||||
className={`w-full flex items-center p-3 rounded-xl transition-all ${
|
className={`w-full flex items-center p-3 rounded-xl transition-all ${activeTab === 'dashboard'
|
||||||
activeTab === 'dashboard'
|
? 'bg-blue-600 text-white shadow-lg shadow-blue-900/20'
|
||||||
? 'bg-blue-600 text-white shadow-lg shadow-blue-900/20'
|
: 'text-gray-400 hover:bg-gray-800 hover:text-gray-200'
|
||||||
: 'text-gray-400 hover:bg-gray-800 hover:text-gray-200'
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<LayoutDashboard size={20} />
|
<LayoutDashboard size={20} />
|
||||||
<span className="ml-3 hidden lg:block font-medium">대시보드</span>
|
<span className="ml-3 hidden lg:block font-medium">대시보드</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
onClick={() => setActiveTab('settings')}
|
onClick={() => setActiveTab('settings')}
|
||||||
className={`w-full flex items-center p-3 rounded-xl transition-all ${
|
className={`w-full flex items-center p-3 rounded-xl transition-all ${activeTab === 'settings'
|
||||||
activeTab === 'settings'
|
? 'bg-blue-600 text-white shadow-lg shadow-blue-900/20'
|
||||||
? 'bg-blue-600 text-white shadow-lg shadow-blue-900/20'
|
: 'text-gray-400 hover:bg-gray-800 hover:text-gray-200'
|
||||||
: 'text-gray-400 hover:bg-gray-800 hover:text-gray-200'
|
}`}
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<SettingsIcon size={20} />
|
<SettingsIcon size={20} />
|
||||||
<span className="ml-3 hidden lg:block font-medium">설정 (EEPROM)</span>
|
<span className="ml-3 hidden lg:block font-medium">설정 (EEPROM)</span>
|
||||||
</button>
|
</button>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
{/* AdSense Unit */}
|
||||||
|
<div className="px-4 pb-2">
|
||||||
|
<div className="text-[10px] text-gray-600 text-center mb-1">Sponsored</div>
|
||||||
|
<ins className="adsbygoogle"
|
||||||
|
style={{ display: "block" }}
|
||||||
|
data-ad-client="ca-pub-4444852135420953"
|
||||||
|
data-ad-slot="7799405796"
|
||||||
|
data-ad-format="auto"
|
||||||
|
data-full-width-responsive="true"></ins>
|
||||||
|
<script>
|
||||||
|
(adsbygoogle = window.adsbygoogle || []).push({ });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<div className="p-4 border-t border-gray-800">
|
<div className="p-4 border-t border-gray-800">
|
||||||
<div className="flex flex-col gap-2">
|
<div className="flex flex-col gap-2">
|
||||||
{connectionState === ConnectionState.CONNECTED ? (
|
{connectionState === ConnectionState.CONNECTED ? (
|
||||||
@@ -169,12 +192,12 @@ const App: React.FC = () => {
|
|||||||
<span className="hidden lg:inline">연결 해제</span>
|
<span className="hidden lg:inline">연결 해제</span>
|
||||||
</button>
|
</button>
|
||||||
) : (
|
) : (
|
||||||
<button
|
<button
|
||||||
onClick={handleConnect}
|
onClick={handleConnect}
|
||||||
disabled={connectionState === ConnectionState.CONNECTING}
|
disabled={connectionState === ConnectionState.CONNECTING}
|
||||||
className="w-full py-3 px-4 bg-green-600 text-white rounded-xl hover:bg-green-500 transition-colors flex items-center justify-center font-semibold shadow-lg shadow-green-900/20"
|
className="w-full py-3 px-4 bg-green-600 text-white rounded-xl hover:bg-green-500 transition-colors flex items-center justify-center font-semibold shadow-lg shadow-green-900/20"
|
||||||
>
|
>
|
||||||
{connectionState === ConnectionState.CONNECTING ? <RefreshCw className="animate-spin" size={18}/> : <Usb size={18} className="mr-2" />}
|
{connectionState === ConnectionState.CONNECTING ? <RefreshCw className="animate-spin" size={18} /> : <Usb size={18} className="mr-2" />}
|
||||||
<span className="hidden lg:inline">BMS 연결</span>
|
<span className="hidden lg:inline">BMS 연결</span>
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
@@ -190,58 +213,58 @@ const App: React.FC = () => {
|
|||||||
{activeTab === 'dashboard' ? '개요 (Overview)' : '설정 (Configuration)'}
|
{activeTab === 'dashboard' ? '개요 (Overview)' : '설정 (Configuration)'}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex items-center gap-4">
|
||||||
{connectionState === ConnectionState.CONNECTED && (
|
{connectionState === ConnectionState.CONNECTED && (
|
||||||
<div className="flex items-center text-xs font-mono text-green-400 bg-green-900/20 px-3 py-1 rounded-full border border-green-900/50">
|
<div className="flex items-center text-xs font-mono text-green-400 bg-green-900/20 px-3 py-1 rounded-full border border-green-900/50">
|
||||||
<div className="w-2 h-2 rounded-full bg-green-500 mr-2 animate-pulse"></div>
|
<div className="w-2 h-2 rounded-full bg-green-500 mr-2 animate-pulse"></div>
|
||||||
CONNECTED
|
CONNECTED
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
{connectionState === ConnectionState.DISCONNECTED && (
|
{connectionState === ConnectionState.DISCONNECTED && (
|
||||||
<div className="flex items-center text-xs font-mono text-gray-500 bg-gray-800 px-3 py-1 rounded-full">
|
<div className="flex items-center text-xs font-mono text-gray-500 bg-gray-800 px-3 py-1 rounded-full">
|
||||||
<div className="w-2 h-2 rounded-full bg-gray-500 mr-2"></div>
|
<div className="w-2 h-2 rounded-full bg-gray-500 mr-2"></div>
|
||||||
OFFLINE
|
OFFLINE
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{/* Content Body with Right Sidebar */}
|
{/* Content Body with Right Sidebar */}
|
||||||
<div className="flex-1 flex overflow-hidden">
|
<div className="flex-1 flex overflow-hidden">
|
||||||
{/* Main View */}
|
{/* Main View */}
|
||||||
<main className="flex-1 overflow-hidden bg-gray-950 relative">
|
<main className="flex-1 overflow-hidden bg-gray-950 relative">
|
||||||
{errorMsg && (
|
{errorMsg && (
|
||||||
<div className="bg-red-900/80 text-white px-6 py-2 flex items-center justify-center text-sm font-medium backdrop-blur absolute top-0 left-0 right-0 z-30 animate-in slide-in-from-top-2">
|
<div className="bg-red-900/80 text-white px-6 py-2 flex items-center justify-center text-sm font-medium backdrop-blur absolute top-0 left-0 right-0 z-30 animate-in slide-in-from-top-2">
|
||||||
<AlertCircle size={16} className="mr-2" />
|
<AlertCircle size={16} className="mr-2" />
|
||||||
{errorMsg}
|
{errorMsg}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{renderContent()}
|
||||||
|
|
||||||
|
{/* Empty State Overlay */}
|
||||||
|
{connectionState !== ConnectionState.CONNECTED && (
|
||||||
|
<div className="absolute inset-0 bg-gray-950/80 backdrop-blur-sm z-10 flex flex-col items-center justify-center p-6 text-center">
|
||||||
|
<div className="w-16 h-16 bg-gray-800 rounded-2xl flex items-center justify-center mb-6 shadow-xl border border-gray-700">
|
||||||
|
<Usb size={32} className="text-gray-500" />
|
||||||
</div>
|
</div>
|
||||||
)}
|
<h2 className="text-2xl font-bold text-white mb-2">장치가 연결되지 않았습니다</h2>
|
||||||
|
<p className="text-gray-400 max-w-md mb-8">
|
||||||
|
JBD BMS를 UART-to-USB 어댑터로 연결하여 실시간 상태를 확인하고 설정을 변경하세요.
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
onClick={handleConnect}
|
||||||
|
className="py-3 px-8 bg-blue-600 hover:bg-blue-500 text-white font-semibold rounded-xl transition-all shadow-lg shadow-blue-900/30 flex items-center"
|
||||||
|
>
|
||||||
|
<Usb size={18} className="mr-2" /> 장치 연결하기
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</main>
|
||||||
|
|
||||||
{renderContent()}
|
{/* Right Terminal Panel */}
|
||||||
|
<aside className="w-80 lg:w-96 border-l border-gray-800 bg-gray-950 flex flex-col flex-shrink-0 z-20">
|
||||||
{/* Empty State Overlay */}
|
<Terminal />
|
||||||
{connectionState !== ConnectionState.CONNECTED && (
|
</aside>
|
||||||
<div className="absolute inset-0 bg-gray-950/80 backdrop-blur-sm z-10 flex flex-col items-center justify-center p-6 text-center">
|
|
||||||
<div className="w-16 h-16 bg-gray-800 rounded-2xl flex items-center justify-center mb-6 shadow-xl border border-gray-700">
|
|
||||||
<Usb size={32} className="text-gray-500"/>
|
|
||||||
</div>
|
|
||||||
<h2 className="text-2xl font-bold text-white mb-2">장치가 연결되지 않았습니다</h2>
|
|
||||||
<p className="text-gray-400 max-w-md mb-8">
|
|
||||||
JBD BMS를 UART-to-USB 어댑터로 연결하여 실시간 상태를 확인하고 설정을 변경하세요.
|
|
||||||
</p>
|
|
||||||
<button
|
|
||||||
onClick={handleConnect}
|
|
||||||
className="py-3 px-8 bg-blue-600 hover:bg-blue-500 text-white font-semibold rounded-xl transition-all shadow-lg shadow-blue-900/30 flex items-center"
|
|
||||||
>
|
|
||||||
<Usb size={18} className="mr-2"/> 장치 연결하기
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</main>
|
|
||||||
|
|
||||||
{/* Right Terminal Panel */}
|
|
||||||
<aside className="w-80 lg:w-96 border-l border-gray-800 bg-gray-950 flex flex-col flex-shrink-0 z-20">
|
|
||||||
<Terminal />
|
|
||||||
</aside>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user