add: blocked repair install feedback

This commit is contained in:
Tom Boullay
2026-05-11 12:56:54 +02:00
parent f9340ae57d
commit 0e32c76bce
@@ -1,4 +1,4 @@
import { useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import * as THREE from "three"; import * as THREE from "three";
import type { RepairCasePlaceholder } from "@/components/three/gameplay/RepairCaseModel"; import type { RepairCasePlaceholder } from "@/components/three/gameplay/RepairCaseModel";
import { RepairObjectModel } from "@/components/three/gameplay/RepairObjectModel"; import { RepairObjectModel } from "@/components/three/gameplay/RepairObjectModel";
@@ -42,10 +42,12 @@ interface RepairRepairingStepProps {
} }
interface RepairInstallTargetProps { interface RepairInstallTargetProps {
blockedFeedback: boolean;
fillColor: string; fillColor: string;
isReadyToInstall: boolean; isReadyToInstall: boolean;
label: string; label: string;
ringColor: string; ringColor: string;
onBlocked: () => void;
onRepair: () => void; onRepair: () => void;
} }
@@ -71,6 +73,8 @@ export function RepairRepairingStep({
const [depositedBrokenPartIds, setDepositedBrokenPartIds] = useState< const [depositedBrokenPartIds, setDepositedBrokenPartIds] = useState<
Record<string, boolean> Record<string, boolean>
>({}); >({});
const [showBlockedInstallFeedback, setShowBlockedInstallFeedback] =
useState(false);
const replacementParts = getReplacementParts(config); const replacementParts = getReplacementParts(config);
const brokenPartsToDeposit = getBrokenPartsToDeposit(config, brokenParts); const brokenPartsToDeposit = getBrokenPartsToDeposit(config, brokenParts);
const requiredReplacementPart = replacementParts.find( const requiredReplacementPart = replacementParts.find(
@@ -111,6 +115,18 @@ export function RepairRepairingStep({
? `Ranger pièce cassée` ? `Ranger pièce cassée`
: `Approcher ${requiredReplacementLabel}`; : `Approcher ${requiredReplacementLabel}`;
useEffect(() => {
if (!showBlockedInstallFeedback) return undefined;
const timeoutId = window.setTimeout(() => {
setShowBlockedInstallFeedback(false);
}, 900);
return () => {
window.clearTimeout(timeoutId);
};
}, [showBlockedInstallFeedback]);
function handleReplacementPosition( function handleReplacementPosition(
partId: string, partId: string,
position: THREE.Vector3, position: THREE.Vector3,
@@ -161,10 +177,12 @@ export function RepairRepairingStep({
return ( return (
<group ref={groupRef}> <group ref={groupRef}>
<RepairInstallTarget <RepairInstallTarget
blockedFeedback={showBlockedInstallFeedback}
fillColor={installFillColor} fillColor={installFillColor}
isReadyToInstall={isReadyToInstall} isReadyToInstall={isReadyToInstall}
label={installLabel} label={installLabel}
ringColor={installColor} ringColor={installColor}
onBlocked={() => setShowBlockedInstallFeedback(true)}
onRepair={onRepair} onRepair={onRepair}
/> />
@@ -268,10 +286,12 @@ export function RepairRepairingStep({
} }
function RepairInstallTarget({ function RepairInstallTarget({
blockedFeedback,
fillColor, fillColor,
isReadyToInstall, isReadyToInstall,
label, label,
ringColor, ringColor,
onBlocked,
onRepair, onRepair,
}: RepairInstallTargetProps): React.JSX.Element { }: RepairInstallTargetProps): React.JSX.Element {
return ( return (
@@ -280,7 +300,10 @@ function RepairInstallTarget({
colliders="ball" colliders="ball"
label={label} label={label}
onTrigger={() => { onTrigger={() => {
if (!isReadyToInstall) return; if (!isReadyToInstall) {
onBlocked();
return;
}
onRepair(); onRepair();
}} }}
@@ -293,6 +316,18 @@ function RepairInstallTarget({
<ringGeometry args={[0.15, 0.9, 96]} /> <ringGeometry args={[0.15, 0.9, 96]} />
<meshBasicMaterial color={fillColor} transparent opacity={0.35} /> <meshBasicMaterial color={fillColor} transparent opacity={0.35} />
</mesh> </mesh>
{blockedFeedback ? (
<group position={[0, 0.28, 0]}>
<mesh rotation={[Math.PI / 2, 0, 0]}>
<torusGeometry args={[1.08, 0.035, 12, 96]} />
<meshBasicMaterial color={ringColor} transparent opacity={0.95} />
</mesh>
<mesh>
<sphereGeometry args={[0.12, 16, 16]} />
<meshBasicMaterial color={ringColor} transparent opacity={0.95} />
</mesh>
</group>
) : null}
</TriggerObject> </TriggerObject>
); );
} }