refactor(nui): Move context items into separate files

This commit is contained in:
Luke
2022-03-27 18:17:26 +02:00
parent ccf00a6a9e
commit ac832d4840
5 changed files with 201 additions and 194 deletions

View File

@@ -3,7 +3,7 @@ import CircleProgressbar from "./CircleProgressbar";
import Progressbar from "./Progressbar";
import TextUI from "./TextUI";
import InputDialog from "./InputDialog";
import ContextMenu from "./ContextMenu";
import ContextMenu from "./features/menu/ContextMenu";
const App: React.FC = () => {
return (

View File

@@ -1,193 +0,0 @@
import { useNuiEvent } from "../hooks/useNuiEvent";
import {
Box,
Text,
Flex,
Popover,
PopoverTrigger,
Portal,
PopoverContent,
PopoverBody,
Spacer,
ScaleFade,
} from "@chakra-ui/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { debugData } from "../utils/debugData";
import { useState } from "react";
interface Props {
title: string;
options: Options;
}
interface Options {
[key: string]: {
description?: string;
metadata?: string[] | { [key: string]: any };
subMenu?: boolean;
};
}
debugData<Props>([
{
action: "showContext",
data: {
title: "Vehicle garage",
options: {
["Dinka Blista"]: {
description: "Super cool vehicle",
subMenu: true,
metadata: {
["Plate"]: "KLT 192",
["Status"]: "In garage",
["Health"]: "30%",
},
},
["Elegy Nitro"]: {
description: "Even cooler vehicle",
metadata: ["Plate: JGM 971", "Status: In garage"],
},
["Burger"]: {
description: "Make a delicious burger",
metadata: {
["Bun"]: 3,
["Lettuce"]: 2,
["Meat"]: 1,
["Tomato"]: 1,
["Cheese"]: 2,
},
},
},
},
},
]);
const ContextMenu: React.FC = () => {
const [visible, setVisible] = useState(false);
const [contextMenu, setContextMenu] = useState<Props>({
title: "",
options: { [""]: { description: "", metadata: [""] } },
});
useNuiEvent<Props>("showContext", (data) => {
setContextMenu(data);
setVisible(true);
});
return (
<Flex
position="absolute"
w="75%"
h="80%"
justifyContent="flex-end"
alignItems="center"
>
<ScaleFade in={visible} unmountOnExit>
<Box w="xs" h={580}>
<Box borderRadius="md" bg="gray.800" mb={3}>
<Text
fontFamily="Poppins"
fontSize="md"
p={2}
textAlign="center"
fontWeight="light"
>
{contextMenu.title}
</Text>
</Box>
<Box maxH={560} overflowY="scroll">
{Object.entries(contextMenu.options).map((option, index) => (
<Popover
placement="right-start"
trigger="hover"
eventListeners={{ scroll: true }}
isLazy
>
<PopoverTrigger>
<Box
bg="gray.800"
borderRadius="md"
h="fit-content"
w="100%"
p={2}
mb={1}
fontFamily="Poppins"
fontSize="md"
transition="300ms"
_hover={{ bg: "gray.700" }}
key={`option-${index}`}
>
{/* TODO: react-markdown (?) */}
<Flex w="100%">
<Box>
<Box paddingBottom={1}>
<Text w="100%" fontWeight="medium">
{option[0]}
</Text>
</Box>
{option[1].description && (
<Box paddingBottom={1}>
<Text>{option[1].description}</Text>
</Box>
)}
</Box>
{option[1].subMenu && (
<>
<Spacer />
<Box
alignSelf="center"
justifySelf="center"
mr={4}
fontSize="xl"
>
<FontAwesomeIcon icon="chevron-right" />
</Box>
</>
)}
</Flex>
<Portal>
<PopoverContent
fontFamily="Poppins"
bg="gray.800"
outline="none"
border="none"
w="fit-content"
maxW="2xs"
>
<PopoverBody>
{option[1]?.metadata &&
Array.isArray(option[1].metadata) ? (
option[1].metadata.map(
(metadata: string, index) => (
<Text key={`context-metadata-${index}`}>
{metadata}
</Text>
)
)
) : (
<>
{typeof option[1].metadata === "object" &&
Object.entries(option[1].metadata).map(
(metadata: { [key: string]: any }, index) => (
<Text key={`context-metadata-${index}`}>
{metadata[0]}: {metadata[1]}
</Text>
)
)}
</>
)}
</PopoverBody>
</PopoverContent>
</Portal>
</Box>
</PopoverTrigger>
</Popover>
))}
</Box>
</Box>
</ScaleFade>
</Flex>
);
};
export default ContextMenu;

View File

@@ -0,0 +1,91 @@
import { useNuiEvent } from "../../../hooks/useNuiEvent";
import { Box, Text, Flex, ScaleFade } from "@chakra-ui/react";
import { debugData } from "../../../utils/debugData";
import { useState } from "react";
import { Options } from "../../../interfaces";
import Item from "./Item";
interface Props {
title: string;
options: Options;
}
debugData<Props>([
{
action: "showContext",
data: {
title: "Vehicle garage",
options: {
["Dinka Blista"]: {
description: "Super cool vehicle",
subMenu: true,
metadata: {
["Plate"]: "KLT 192",
["Status"]: "In garage",
["Health"]: "30%",
},
},
["Elegy Nitro"]: {
description: "Even cooler vehicle",
metadata: ["Plate: JGM 971", "Status: In garage"],
},
["Burger"]: {
description: "Make a delicious burger",
metadata: {
["Bun"]: 3,
["Lettuce"]: 2,
["Meat"]: 1,
["Tomato"]: 1,
["Cheese"]: 2,
},
},
},
},
},
]);
const ContextMenu: React.FC = () => {
const [visible, setVisible] = useState(false);
const [contextMenu, setContextMenu] = useState<Props>({
title: "",
options: { [""]: { description: "", metadata: [""] } },
});
useNuiEvent<Props>("showContext", (data) => {
setContextMenu(data);
setVisible(true);
});
return (
<Flex
position="absolute"
w="75%"
h="80%"
justifyContent="flex-end"
alignItems="center"
>
<ScaleFade in={visible} unmountOnExit>
<Box w="xs" h={580}>
<Box borderRadius="md" bg="gray.800" mb={3}>
<Text
fontFamily="Poppins"
fontSize="md"
p={2}
textAlign="center"
fontWeight="light"
>
{contextMenu.title}
</Text>
</Box>
<Box maxH={560} overflowY="scroll">
{Object.entries(contextMenu.options).map((option, index) => (
<Item option={option} key={`context-item-${index}`} />
))}
</Box>
</Box>
</ScaleFade>
</Flex>
);
};
export default ContextMenu;

View File

@@ -0,0 +1,100 @@
import {
Portal,
Popover,
PopoverTrigger,
PopoverBody,
PopoverContent,
Box,
Text,
Flex,
Spacer,
} from "@chakra-ui/react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Option } from "../../../interfaces";
const Item: React.FC<{
option: [string, Option];
}> = ({ option }) => {
return (
<Popover
placement="right-start"
trigger="hover"
eventListeners={{ scroll: true }}
isLazy
>
<PopoverTrigger>
<Box
bg="gray.800"
borderRadius="md"
h="fit-content"
w="100%"
p={2}
mb={1}
fontFamily="Poppins"
fontSize="md"
transition="300ms"
_hover={{ bg: "gray.700" }}
>
<Flex w="100%">
<Box>
<Box paddingBottom={1}>
<Text w="100%" fontWeight="medium">
{option[0]}
</Text>
</Box>
{option[1].description && (
<Box paddingBottom={1}>
<Text>{option[1].description}</Text>
</Box>
)}
</Box>
{option[1].subMenu && (
<>
<Spacer />
<Box
alignSelf="center"
justifySelf="center"
mr={4}
fontSize="xl"
>
<FontAwesomeIcon icon="chevron-right" />
</Box>
</>
)}
</Flex>
<Portal>
<PopoverContent
fontFamily="Poppins"
bg="gray.800"
outline="none"
border="none"
w="fit-content"
maxW="2xs"
>
<PopoverBody>
{option[1]?.metadata && Array.isArray(option[1].metadata) ? (
option[1].metadata.map((metadata: string, index: number) => (
<Text key={`context-metadata-${index}`}>{metadata}</Text>
))
) : (
<>
{typeof option[1].metadata === "object" &&
Object.entries(option[1].metadata).map(
(metadata: { [key: string]: any }, index) => (
<Text key={`context-metadata-${index}`}>
{metadata[0]}: {metadata[1]}
</Text>
)
)}
</>
)}
</PopoverBody>
</PopoverContent>
</Portal>
</Box>
</PopoverTrigger>
</Popover>
);
};
export default Item;

View File

@@ -0,0 +1,9 @@
export interface Option {
description?: string;
metadata?: string[] | { [key: string]: any };
subMenu?: boolean;
}
export interface Options {
[key: string]: Option;
}