feat(web): optimistic UI updates with debounced server sync
Ship and weapon updates now apply locally immediately so stepper clicks feel instant. Server sends are debounced (300ms) and batched so rapid clicks produce a single network call. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useCallback } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import TopBar from '../components/layout/TopBar';
|
||||
import PageContainer from '../components/layout/PageContainer';
|
||||
@@ -7,29 +7,16 @@ import MobilitySection from '../components/dashboard/MobilitySection';
|
||||
import WeaponsSection from '../components/dashboard/WeaponsSection';
|
||||
import NotesSection from '../components/dashboard/NotesSection';
|
||||
import { useShipStore } from '../store/use-ship-store';
|
||||
import type { Ship } from '../types/ship';
|
||||
|
||||
export default function ShipDashboardPage() {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const { ship, weapons, loading, joinShip, leaveShip, updateShip, createWeapon, updateWeapon, deleteWeapon } = useShipStore();
|
||||
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (id) joinShip(id);
|
||||
return () => leaveShip();
|
||||
}, [id, joinShip, leaveShip]);
|
||||
|
||||
const handleUpdate = useCallback(
|
||||
(patch: Partial<Ship>) => {
|
||||
// Debounce rapid changes (e.g. stepper clicks)
|
||||
if (debounceRef.current) clearTimeout(debounceRef.current);
|
||||
debounceRef.current = setTimeout(() => {
|
||||
updateShip(patch);
|
||||
}, 300);
|
||||
},
|
||||
[updateShip],
|
||||
);
|
||||
|
||||
if (loading || !ship) {
|
||||
return (
|
||||
<>
|
||||
@@ -45,15 +32,15 @@ export default function ShipDashboardPage() {
|
||||
<>
|
||||
<TopBar title={ship.name} />
|
||||
<PageContainer>
|
||||
<VitalsSection ship={ship} onUpdate={handleUpdate} />
|
||||
<MobilitySection ship={ship} onUpdate={handleUpdate} />
|
||||
<VitalsSection ship={ship} onUpdate={updateShip} />
|
||||
<MobilitySection ship={ship} onUpdate={updateShip} />
|
||||
<WeaponsSection
|
||||
weapons={weapons}
|
||||
onCreateWeapon={createWeapon}
|
||||
onUpdateWeapon={updateWeapon}
|
||||
onDeleteWeapon={deleteWeapon}
|
||||
/>
|
||||
<NotesSection notes={ship.notes} onUpdate={handleUpdate} />
|
||||
<NotesSection notes={ship.notes} onUpdate={updateShip} />
|
||||
</PageContainer>
|
||||
</>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user