feat: add inspection_expiry/has_etc/tire_type fields, icons in schedule view, and WebSocket real-time sync

Co-authored-by: h <57948770+h@users.noreply.github.com>
Agent-Logs-Url: https://github.com/h/CarReservation/sessions/6d0f25ae-6db4-4937-ae2b-6674456a5ca1
This commit is contained in:
copilot-swe-agent[bot]
2026-03-22 03:58:07 +00:00
parent ea564b18c5
commit ece803ee1d
13 changed files with 451 additions and 26 deletions

View File

@@ -1,16 +1,36 @@
import { useState } from 'react';
import { useState, useCallback } from 'react';
import ScheduleView from './components/ScheduleView.jsx';
import CarManagement from './components/CarManagement.jsx';
import TimelineView from './components/TimelineView.jsx';
import useWebSocket from './hooks/useWebSocket.js';
import styles from './App.module.css';
export default function App() {
const [page, setPage] = useState('schedule');
const [reloadKey, setReloadKey] = useState(0);
const handleWsMessage = useCallback((msg) => {
if (msg.type === 'data_changed') {
setReloadKey((k) => k + 1);
}
}, []);
const { status: wsStatus } = useWebSocket(handleWsMessage);
return (
<div className={styles.app}>
<header className={styles.header}>
<h1 className={styles.title}>🚗 代車スケジュール管理</h1>
<div className={styles.headerLeft}>
<span
className={`${styles.wsIndicator} ${styles['wsIndicator_' + wsStatus]}`}
title={
wsStatus === 'connected' ? 'リアルタイム同期: 接続中' :
wsStatus === 'connecting' || wsStatus === 'disconnected' ? 'リアルタイム同期: 再接続中...' :
'リアルタイム同期: 接続失敗'
}
/>
<h1 className={styles.title}>🚗 代車スケジュール管理</h1>
</div>
<nav className={styles.nav}>
<button
className={`${styles.navBtn} ${page === 'schedule' ? styles.active : ''}`}
@@ -32,10 +52,17 @@ export default function App() {
</button>
</nav>
</header>
{wsStatus === 'error' && (
<div className={styles.wsError}>
サーバーとの接続が切断されましたページを再読み込みしてください
</div>
)}
<main className={styles.main}>
{page === 'schedule' && <ScheduleView />}
{page === 'timeline' && <TimelineView />}
{page === 'cars' && <CarManagement />}
{page === 'schedule' && <ScheduleView reloadKey={reloadKey} />}
{page === 'timeline' && <TimelineView reloadKey={reloadKey} />}
{page === 'cars' && <CarManagement reloadKey={reloadKey} />}
</main>
</div>
);