import { useCallback, useState } from "react"; import * as THREE from "three"; import { RepairObjectModel } from "@/components/three/gameplay/RepairObjectModel"; import { RepairPromptVideo } from "@/components/three/gameplay/RepairPromptVideo"; import { GrabbableObject } from "@/components/three/interaction/GrabbableObject"; import { TriggerObject } from "@/components/three/interaction/TriggerObject"; import type { RepairMissionConfig } from "@/data/gameplay/repairMissions"; import type { Vector3Tuple } from "@/types/three/three"; const INSTALL_TARGET_POSITION: Vector3Tuple = [0, 0.8, 0]; const INSTALL_TARGET_VECTOR = new THREE.Vector3(...INSTALL_TARGET_POSITION); const REPLACEMENT_START_POSITION: Vector3Tuple = [0, 1.35, 1.8]; const REPAIR_INSTALL_RADIUS = 1.1; interface RepairRepairingStepProps { config: RepairMissionConfig; onRepair: () => void; } export function RepairRepairingStep({ config, onRepair, }: RepairRepairingStepProps): React.JSX.Element { const [isReplacementPlaced, setIsReplacementPlaced] = useState(false); const replacementPart = config.replacementParts[0]; const replacementModelPath = replacementPart?.modelPath ?? config.modelPath; const replacementLabel = replacementPart?.label ?? config.label; const installColor = isReplacementPlaced ? "#22c55e" : "#f97316"; const installFillColor = isReplacementPlaced ? "#86efac" : "#fed7aa"; const handleReplacementPosition = useCallback((position: THREE.Vector3) => { const isPlaced = position.distanceTo(INSTALL_TARGET_VECTOR) <= REPAIR_INSTALL_RADIUS; setIsReplacementPlaced((current) => current === isPlaced ? current : isPlaced, ); }, []); return ( { if (!isReplacementPlaced) return; onRepair(); }} > ); }