From 3e7b2beca1136a42700a7e1aebfe4c0fb2861a00 Mon Sep 17 00:00:00 2001 From: soryu Date: Sat, 15 Nov 2025 18:00:09 +0000 Subject: Initial commit --- frontend/src/components/VNInterface.tsx | 208 ++++++++++++++++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 frontend/src/components/VNInterface.tsx (limited to 'frontend/src/components/VNInterface.tsx') diff --git a/frontend/src/components/VNInterface.tsx b/frontend/src/components/VNInterface.tsx new file mode 100644 index 0000000..be71d27 --- /dev/null +++ b/frontend/src/components/VNInterface.tsx @@ -0,0 +1,208 @@ +import React, { useEffect } from 'react' +import { useStore } from '@nanostores/react' +import { + isStandbyStore, + currentTimeStore, + weatherStore, + showChoicesStore, + showSettingsModalStore, + isVisibleStore, + yenBalanceStore, + toggleStandby, + toggleShowChoices, + updateTime +} from '../stores' + +interface VNInterfaceProps { + onLogout: () => void +} + +export function VNInterface({ onLogout }: VNInterfaceProps) { + const isStandby = useStore(isStandbyStore) + const currentTime = useStore(currentTimeStore) + const weather = useStore(weatherStore) + const showChoices = useStore(showChoicesStore) + const showSettingsModal = useStore(showSettingsModalStore) + const isVisible = useStore(isVisibleStore) + const yenBalance = useStore(yenBalanceStore) + + // Fade in effect on mount + useEffect(() => { + const timer = setTimeout(() => { + isVisibleStore.set(true) + }, 100) + return () => clearTimeout(timer) + }, []) + + // Update clock every second (Japan Time) + useEffect(() => { + const timer = setInterval(() => { + const now = new Date() + // Convert to Japan Time (UTC+9) + const japanTime = new Date(now.getTime() + (now.getTimezoneOffset() * 60000) + (9 * 3600000)) + updateTime() + }, 1000) + return () => clearInterval(timer) + }, []) + + return ( +
+ {/* Background */} +
+ Background image +
+ + {/* Combined Info Panel (Top Right) */} +
+
+ {/* Weather Section */} +
+
🌤️
+
+
Tokyo
+
22°C Sunny
+
+
+ + {/* Time Section */} +
+
{currentTime.toLocaleDateString('ja-JP', { + year: 'numeric', + month: 'long', + day: 'numeric', + weekday: 'short' + })}
+
{currentTime.toLocaleTimeString('ja-JP', { + hour12: false, + hour: '2-digit', + minute: '2-digit' + })}
+
+ + {/* Status Section */} +
+
+ Balance: + ¥{yenBalance.toLocaleString()} +
+
+ System: + + + {isStandby ? 'STDBY' : 'LIVE'} + +
+
+
+
+ + {/* Main VN Viewport */} +
+
+
+
+ + {/* Dialogue Panel (Bottom) */} +
+
+
???
+
+ A warm CRT glow fills the room. A figure turns towards you... +
+
+
+ + {/* Input/Choice Panel (Bottom) */} +
+
+ {!showChoices ? ( + // Text Input Mode + { + if (e.key === 'Enter') { + const target = e.target as HTMLInputElement; + if (target.value.trim()) { + console.log('User input:', target.value); + target.value = ''; + } + } + }} + /> + ) : ( + // Choice Options Mode +
+ + + +
+ )} + + {/* Toggle Button */} + +
+
+ + {/* Floating Settings Button */} + + + {/* Settings Modal */} + {showSettingsModal && ( +
showSettingsModalStore.set(false)}> +
e.stopPropagation()}> +
+

Settings

+ +
+
+
+

Display Options

+
+ +
+
+
+

Audio

+
+ + +
+
+
+
+ + +
+
+
+ )} +
+ ) +} -- cgit v1.2.3