Refactoring the puzzle and organizing files

environments/review-captcha-mo-b0pok8/deployments/4881
danidfra 2024-10-10 14:13:46 -03:00
rodzic 2aa21874f7
commit e040c9f981
3 zmienionych plików z 64 dodań i 109 usunięć

Wyświetl plik

@ -0,0 +1,64 @@
import React, { useRef } from 'react';
interface IPuzzleCaptcha {
bg: string;
puzzle: string;
position: { x: number; y: number };
onChange(point: { x: number; y: number }): void;
}
export const PuzzleCaptcha: React.FC<IPuzzleCaptcha> = ({ bg, puzzle, position, onChange }) => {
const ref = useRef<HTMLDivElement>(null);
const calculateNewPosition = (
clientX: number,
clientY: number,
elementWidth: number,
elementHeight: number,
dropArea: DOMRect,
) => {
const newX = Math.min(Math.max(clientX - dropArea.left - elementWidth / 2, 0), dropArea.width - elementWidth);
const newY = Math.min(Math.max(clientY - dropArea.top - elementHeight / 2, 0), dropArea.height - elementHeight);
return { x: newX, y: newY };
};
const handlePointerMove = (e: React.PointerEvent<HTMLImageElement>) => {
if (!e.currentTarget.hasPointerCapture(e.pointerId)) return;
const dropArea = ref.current?.getBoundingClientRect();
if (!dropArea) return;
const newPosition = calculateNewPosition(e.clientX, e.clientY, e.currentTarget.width, e.currentTarget.height, dropArea);
onChange(newPosition);
};
const handleTouchMove = (event: React.TouchEvent<HTMLImageElement>) => {
const touch = event.touches[0];
const dropArea = ref.current?.getBoundingClientRect();
if (!dropArea) return;
const newPosition = calculateNewPosition(touch.clientX, touch.clientY, 61, 61, dropArea);
onChange(newPosition);
};
return (
<div id='drop-area' ref={ref} className='relative'>
<img
className='drop-shadow-black absolute z-[101] w-[61px] drop-shadow-2xl hover:cursor-grab'
src={puzzle}
alt=''
onPointerDown={(e) => e.currentTarget.setPointerCapture(e.pointerId)}
onPointerMove={handlePointerMove}
onPointerUp={(e) => e.currentTarget.releasePointerCapture(e.pointerId)}
onTouchMove={handleTouchMove}
style={{
filter: 'drop-shadow(2px 0 0 #fff) drop-shadow(0 2px 0 #fff) drop-shadow(-2px 0 0 #fff) drop-shadow(0 -2px 0 #fff)',
left: position.x,
top: position.y,
}}
draggable={false}
/>
<img src={bg} alt='' className='rounded-2xl' draggable={false} />
</div>
);
};

Wyświetl plik

@ -1,109 +0,0 @@
import React, { useRef, useState } from 'react';
interface IPuzzleCaptcha {
bg: string;
puzzle: string;
position: { x: number; y: number };
onChange(point: { x: number; y: number }): void;
}
export const PuzzleCaptcha: React.FC<IPuzzleCaptcha> = ({ bg, puzzle, position, onChange }) => {
const ref = useRef<HTMLDivElement>(null);
const [touchOffsetX, setTouchOffsetX] = useState(0);
const [touchOffsetY, setTouchOffsetY] = useState(0);
const handlePointerDown = (e: React.PointerEvent<HTMLImageElement>) => {
e.currentTarget.setPointerCapture(e.pointerId);
};
const handlePointerMove = (e: React.PointerEvent<HTMLImageElement>) => {
if (!e.currentTarget.hasPointerCapture(e.pointerId)) return;
const rect = ref.current?.getBoundingClientRect();
if (!rect) return;
const newPosition = {
x: e.clientX - rect.left - e.currentTarget.width / 2,
y: e.clientY - rect.top - e.currentTarget.height / 2,
};
onChange(newPosition);
};
const handleTouchStart = (event: React.TouchEvent<HTMLImageElement>) => {
const imageElement = event.currentTarget.getBoundingClientRect();
const touch = event.touches[0];
const offsetX = touch.clientX - imageElement.left;
const offsetY = touch.clientY - imageElement.top;
setTouchOffsetX(offsetX);
setTouchOffsetY(offsetY);
};
const handleTouchMove = (event: React.TouchEvent<HTMLImageElement>) => {
const touch = event.touches[0];
const dropArea = document.getElementById('drop-area')?.getBoundingClientRect();
if (!dropArea) return;
const newLeft = touch.clientX - dropArea.left - touchOffsetX;
const newTop = touch.clientY - dropArea.top - touchOffsetY;
const imageWidth = 61;
const imageHeight = 61;
const limitedLeft = Math.min(Math.max(newLeft, 0), dropArea.width - imageWidth);
const limitedTop = Math.min(Math.max(newTop, 0), dropArea.height - imageHeight);
onChange({ x: limitedLeft, y: limitedTop });
};
const handlePointerUp = (e: React.PointerEvent<HTMLImageElement>) => {
e.currentTarget.releasePointerCapture(e.pointerId);
};
const handleTouchDrop = (event: React.TouchEvent<HTMLDivElement>) => {
event.preventDefault();
const dropArea = document.getElementById('drop-area')?.getBoundingClientRect();
if (!dropArea) return;
const touch = event.changedTouches[0];
const newLeft = touch.clientX - dropArea.left - touchOffsetX;
const newTop = touch.clientY - dropArea.top - touchOffsetY;
const imageWidth = 61;
const imageHeight = 61;
const limitedLeft = Math.min(Math.max(newLeft, 0), dropArea.width - imageWidth);
const limitedTop = Math.min(Math.max(newTop, 0), dropArea.height - imageHeight);
onChange({ x: limitedLeft, y: limitedTop });
};
return (
<div id='drop-area' ref={ref} className='relative' onTouchEnd={handleTouchDrop}>
<img
className='drop-shadow-black absolute z-[101] w-[61px] drop-shadow-2xl hover:cursor-grab'
src={puzzle}
alt=''
onTouchStart={handleTouchStart}
onTouchMove={handleTouchMove}
onPointerDown={handlePointerDown}
onPointerMove={handlePointerMove}
onPointerUp={handlePointerUp}
style={{
filter: 'drop-shadow(2px 0 0 #fff) drop-shadow(0 2px 0 #fff) drop-shadow(-2px 0 0 #fff) drop-shadow(0 -2px 0 #fff)',
left: position.x,
top: position.y,
}}
draggable={false}
/>
<img src={bg} alt='' className='rounded-2xl' draggable={false} />
</div>
);
};