mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-18 15:36:02 +01:00
refactor(web/skillcheck): skillcheck mantine rewrite
This commit is contained in:
@@ -1,9 +1,8 @@
|
|||||||
import { Box, Center } from '@chakra-ui/react';
|
|
||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
import { useNuiEvent } from '../../hooks/useNuiEvent';
|
import { useNuiEvent } from '../../hooks/useNuiEvent';
|
||||||
import { debugData } from '../../utils/debugData';
|
|
||||||
import Indicator from './indicator';
|
import Indicator from './indicator';
|
||||||
import { fetchNui } from '../../utils/fetchNui';
|
import { fetchNui } from '../../utils/fetchNui';
|
||||||
|
import { useMantineTheme, Box, createStyles } from '@mantine/core';
|
||||||
|
|
||||||
interface CustomGameDifficulty {
|
interface CustomGameDifficulty {
|
||||||
areaSize: number;
|
areaSize: number;
|
||||||
@@ -28,7 +27,46 @@ const difficultyOffsets = {
|
|||||||
hard: 25,
|
hard: 25,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const useStyles = createStyles((theme) => ({
|
||||||
|
svg: {
|
||||||
|
position: 'absolute',
|
||||||
|
top: '50%',
|
||||||
|
left: '50%',
|
||||||
|
transform: 'translate(-50%, -50%)',
|
||||||
|
},
|
||||||
|
track: {
|
||||||
|
fill: 'transparent',
|
||||||
|
stroke: theme.colors.dark[4],
|
||||||
|
strokeWidth: 8,
|
||||||
|
},
|
||||||
|
skillArea: {
|
||||||
|
fill: 'transparent',
|
||||||
|
stroke: theme.fn.primaryColor(),
|
||||||
|
strokeWidth: 8,
|
||||||
|
},
|
||||||
|
indicator: {
|
||||||
|
stroke: 'red',
|
||||||
|
strokeWidth: 16,
|
||||||
|
fill: 'transparent',
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
position: 'absolute',
|
||||||
|
left: '50%',
|
||||||
|
top: '50%',
|
||||||
|
transform: 'translate(-50%, -50%)',
|
||||||
|
backgroundColor: theme.colors.dark[4],
|
||||||
|
width: 25,
|
||||||
|
height: 25,
|
||||||
|
textAlign: 'center',
|
||||||
|
borderRadius: 5,
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: 500,
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
const SkillCheck: React.FC = () => {
|
const SkillCheck: React.FC = () => {
|
||||||
|
const theme = useMantineTheme();
|
||||||
|
const { classes } = useStyles();
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const dataRef = useRef<GameDifficulty | GameDifficulty[] | null>(null);
|
const dataRef = useRef<GameDifficulty | GameDifficulty[] | null>(null);
|
||||||
const dataIndexRef = useRef<number>(0);
|
const dataIndexRef = useRef<number>(0);
|
||||||
@@ -74,31 +112,21 @@ const SkillCheck: React.FC = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Center height="100%" width="100%">
|
<>
|
||||||
{visible && (
|
{visible && (
|
||||||
<>
|
<>
|
||||||
<svg width={500} height={500}>
|
<svg r={50} width={500} height={500} className={classes.svg}>
|
||||||
{/*Circle track*/}
|
{/*Circle track*/}
|
||||||
<circle
|
<circle r={50} cx={250} cy={250} className={classes.track} strokeDasharray={circleCircumference} />
|
||||||
r={50}
|
|
||||||
cx={250}
|
|
||||||
cy={250}
|
|
||||||
fill="transparent"
|
|
||||||
stroke="rgba(0, 0, 0, 0.4)"
|
|
||||||
strokeWidth={5}
|
|
||||||
strokeDasharray={circleCircumference}
|
|
||||||
/>
|
|
||||||
{/*SkillCheck area*/}
|
{/*SkillCheck area*/}
|
||||||
<circle
|
<circle
|
||||||
r={50}
|
r={50}
|
||||||
cx={250}
|
cx={250}
|
||||||
cy={250}
|
cy={250}
|
||||||
fill="transparent"
|
|
||||||
stroke="white"
|
|
||||||
strokeDasharray={circleCircumference}
|
strokeDasharray={circleCircumference}
|
||||||
strokeDashoffset={circleCircumference - (Math.PI * 50 * skillCheck.difficultyOffset) / 180}
|
strokeDashoffset={circleCircumference - (Math.PI * 50 * skillCheck.difficultyOffset) / 180}
|
||||||
strokeWidth={5}
|
|
||||||
transform={`rotate(${skillCheck.angle}, 250, 250)`}
|
transform={`rotate(${skillCheck.angle}, 250, 250)`}
|
||||||
|
className={classes.skillArea}
|
||||||
/>
|
/>
|
||||||
<Indicator
|
<Indicator
|
||||||
angle={skillCheck.angle}
|
angle={skillCheck.angle}
|
||||||
@@ -113,27 +141,14 @@ const SkillCheck: React.FC = () => {
|
|||||||
: skillCheck.difficulty.speedMultiplier
|
: skillCheck.difficulty.speedMultiplier
|
||||||
}
|
}
|
||||||
handleComplete={handleComplete}
|
handleComplete={handleComplete}
|
||||||
|
className={classes.indicator}
|
||||||
skillCheck={skillCheck}
|
skillCheck={skillCheck}
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<Box
|
<Box className={classes.button}>E</Box>
|
||||||
position="absolute"
|
|
||||||
left="50%"
|
|
||||||
top="50%"
|
|
||||||
transform="translate(-50%, -50%)"
|
|
||||||
backgroundColor="rgba(0, 0, 0, 0.4)"
|
|
||||||
w={25}
|
|
||||||
h={25}
|
|
||||||
textAlign="center"
|
|
||||||
borderRadius={5}
|
|
||||||
fontFamily="Inter"
|
|
||||||
fontSize={16}
|
|
||||||
>
|
|
||||||
E
|
|
||||||
</Box>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Center>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { useKeyPress } from '../../hooks/useKeyPress';
|
import { useKeyPress } from '../../hooks/useKeyPress';
|
||||||
import { SkillCheckProps } from './index';
|
import { SkillCheckProps } from './index';
|
||||||
import { useInterval } from '@chakra-ui/react';
|
// import { useInterval } from '@chakra-ui/react';
|
||||||
|
import { useInterval } from '@mantine/hooks';
|
||||||
import { circleCircumference } from './index';
|
import { circleCircumference } from './index';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@@ -9,31 +10,29 @@ interface Props {
|
|||||||
offset: number;
|
offset: number;
|
||||||
multiplier: number;
|
multiplier: number;
|
||||||
skillCheck: SkillCheckProps;
|
skillCheck: SkillCheckProps;
|
||||||
|
className: string;
|
||||||
handleComplete: (success: boolean) => void;
|
handleComplete: (success: boolean) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Indicator: React.FC<Props> = ({ angle, offset, multiplier, handleComplete, skillCheck }) => {
|
const Indicator: React.FC<Props> = ({ angle, offset, multiplier, handleComplete, skillCheck, className }) => {
|
||||||
const [indicatorAngle, setIndicatorAngle] = useState(-90);
|
const [indicatorAngle, setIndicatorAngle] = useState(-90);
|
||||||
const [gameState, setGameState] = useState(false);
|
|
||||||
const isKeyPressed = useKeyPress('e');
|
const isKeyPressed = useKeyPress('e');
|
||||||
|
const interval = useInterval(
|
||||||
useInterval(
|
() =>
|
||||||
() => {
|
|
||||||
setIndicatorAngle((prevState) => {
|
setIndicatorAngle((prevState) => {
|
||||||
return (prevState += multiplier);
|
return (prevState += multiplier);
|
||||||
});
|
}),
|
||||||
},
|
1
|
||||||
gameState ? 1 : null
|
|
||||||
);
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setIndicatorAngle(-90);
|
setIndicatorAngle(-90);
|
||||||
setGameState(true);
|
interval.start();
|
||||||
}, [skillCheck]);
|
}, [skillCheck]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (indicatorAngle + 90 >= 360) {
|
if (indicatorAngle + 90 >= 360) {
|
||||||
setGameState(false);
|
interval.stop();
|
||||||
handleComplete(false);
|
handleComplete(false);
|
||||||
}
|
}
|
||||||
}, [indicatorAngle]);
|
}, [indicatorAngle]);
|
||||||
@@ -41,7 +40,7 @@ const Indicator: React.FC<Props> = ({ angle, offset, multiplier, handleComplete,
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isKeyPressed) return;
|
if (!isKeyPressed) return;
|
||||||
|
|
||||||
setGameState(false);
|
interval.stop();
|
||||||
|
|
||||||
if (indicatorAngle < angle || indicatorAngle > angle + offset) handleComplete(false);
|
if (indicatorAngle < angle || indicatorAngle > angle + offset) handleComplete(false);
|
||||||
else handleComplete(true);
|
else handleComplete(true);
|
||||||
@@ -52,12 +51,10 @@ const Indicator: React.FC<Props> = ({ angle, offset, multiplier, handleComplete,
|
|||||||
r={50}
|
r={50}
|
||||||
cx={250}
|
cx={250}
|
||||||
cy={250}
|
cy={250}
|
||||||
fill="transparent"
|
|
||||||
stroke="red"
|
|
||||||
strokeWidth={15}
|
|
||||||
strokeDasharray={circleCircumference}
|
strokeDasharray={circleCircumference}
|
||||||
strokeDashoffset={circleCircumference - 3}
|
strokeDashoffset={circleCircumference - 3}
|
||||||
transform={`rotate(${indicatorAngle}, 250, 250)`}
|
transform={`rotate(${indicatorAngle}, 250, 250)`}
|
||||||
|
className={className}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user