summaryrefslogblamecommitdiff
path: root/frontend/src/components/VNInterface.tsx
blob: 318a9b9653773e46b454fea6dce04963cea936fc (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
                                        
                                       










                                            
            
























































































                                                                                                   





                                                                                                                                          





                                                                                                                                            









































































































                                                                                                                        
import React, { useEffect } from 'react'
import { Link } from 'react-router-dom'
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 (
    <div className={`vn-interface ${isVisible ? 'fade-in' : 'fade-out'}`}>
      {/* Background */}
      <div className="vn-background">
        <img 
          src="/__gaogao__56242cbde8f18ac64522e410bad04e68_waifu2x_art_noise2.png" 
          alt="Background image"
          className="background-image"
        />
      </div>

      {/* Combined Info Panel (Top Right) */}
      <div className="floating-info-panel">
        <div className="info-panel-content">
          {/* Weather Section */}
          <div className="weather-section">
            <div className="weather-icon">🌤️</div>
            <div className="weather-details">
              <div className="weather-location">Tokyo</div>
              <div className="weather-temp">22°C Sunny</div>
            </div>
          </div>
          
          {/* Time Section */}
          <div className="time-section">
            <div className="japan-date">{currentTime.toLocaleDateString('ja-JP', { 
              year: 'numeric', 
              month: 'long', 
              day: 'numeric',
              weekday: 'short'
            })}</div>
            <div className="japan-time">{currentTime.toLocaleTimeString('ja-JP', { 
              hour12: false,
              hour: '2-digit',
              minute: '2-digit'
            })}</div>
          </div>
          
          {/* Status Section */}
          <div className="status-section">
            <div className="status-item">
              <span className="info-label">Balance:</span>
              <span className="info-value yen-balance">¥{yenBalance.toLocaleString()}</span>
            </div>
            <div className="status-item">
              <span className="info-label">System:</span>
              <span
                className="info-value live-status clickable"
                onClick={toggleStandby}
                title="Click to toggle between LIVE and STANDBY"
              >
                <span className={`status-dot ${isStandby ? 'standby' : 'live'}`}></span>
                {isStandby ? 'STDBY' : 'LIVE'}
              </span>
            </div>
            <div className="status-item">
              <Link to="/daemons" style={{ color: '#66ccff', textDecoration: 'none', display: 'flex', alignItems: 'center', gap: '4px' }}>
                <span className="info-label">Mesh:</span>
                <span className="info-value">Daemons</span>
              </Link>
            </div>
            <div className="status-item">
              <Link to="/contracts" style={{ color: '#66ccff', textDecoration: 'none', display: 'flex', alignItems: 'center', gap: '4px' }}>
                <span className="info-label">View:</span>
                <span className="info-value">Contracts</span>
              </Link>
            </div>
          </div>
        </div>
      </div>

      {/* Main VN Viewport */}
      <div className="vn-viewport">
        <div className="vn-content">
        </div>
      </div>

      {/* Dialogue Panel (Bottom) */}
      <div className="floating-dialogue-panel">
        <div className="dialogue-content">
          <div className="dialogue-speaker">???</div>
          <div className="dialogue-text">
            A warm CRT glow fills the room. A figure turns towards you...
          </div>
        </div>
      </div>

      {/* Input/Choice Panel (Bottom) */}
      <div className="floating-input-panel">
        <div className="input-content">
          {!showChoices ? (
            // Text Input Mode
            <input 
              type="text" 
              className="vn-text-input" 
              placeholder="Type your response..."
              onKeyPress={(e) => {
                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
            <div className="choice-buttons">
              <button className="choice-btn" onClick={() => console.log('Choice: Hello?')}>"Hello?"</button>
              <button className="choice-btn" onClick={() => console.log('Choice: Who are you?')}>"Who are you?"</button>
              <button className="choice-btn" onClick={() => console.log('Choice: Stay silent')}>(Stay silent)</button>
            </div>
          )}
          
          {/* Toggle Button */}
          <button
            className="toggle-input-btn"
            onClick={toggleShowChoices}
            title={showChoices ? "Switch to text input" : "Switch to choice options"}
          >
            {showChoices ? "⎀" : "≡"}
          </button>
        </div>
      </div>

      {/* Floating Settings Button */}
      <button className="floating-logout-btn" onClick={() => showSettingsModalStore.set(true)}>
        <span className="btn-icon">⚙</span>
        <span className="btn-text">Settings</span>
      </button>

      {/* Settings Modal */}
      {showSettingsModal && (
        <div className="modal-overlay" onClick={() => showSettingsModalStore.set(false)}>
          <div className="settings-modal" onClick={(e) => e.stopPropagation()}>
            <div className="modal-header">
              <h2 className="modal-title">Settings</h2>
              <button className="modal-close-btn" onClick={() => showSettingsModalStore.set(false)}>
                ×
              </button>
            </div>
            <div className="modal-content">
              <div className="settings-section">
                <h3>Display Options</h3>
                <div className="setting-item">
                  <label>
                    <input type="checkbox" defaultChecked /> Enable animations
                  </label>
                </div>
              </div>
              <div className="settings-section">
                <h3>Audio</h3>
                <div className="setting-item">
                  <label>Master Volume</label>
                  <input type="range" min="0" max="100" defaultValue="75" />
                </div>
              </div>
            </div>
            <div className="modal-footer">
              <button className="modal-btn secondary" onClick={() => showSettingsModalStore.set(false)}>
                Cancel
              </button>
              <button className="modal-btn logout" onClick={() => { showSettingsModalStore.set(false); onLogout(); }}>
                Logout
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}