useDropdown hook, review requests
This commit is contained in:
parent
bcef200765
commit
ffe95a12f2
@ -31,7 +31,7 @@ module.exports = {
|
||||
// Best Practices
|
||||
eqeqeq: ["error", "always"], // Enforce '===' instead of '=='
|
||||
curly: ["error", "multi-line", "consistent"], // Require curly braces for all control statements
|
||||
"no-unused-vars": "warn", // Warn about variables that are declared but not used
|
||||
"no-unused-vars": "off", // Not needed with TypeScript
|
||||
|
||||
// React Specific
|
||||
"react/jsx-filename-extension": [1, { extensions: [".tsx"] }], // Allow jsx syntax in .tsx files
|
||||
|
@ -4,52 +4,103 @@ import { useCallback, useState } from "react";
|
||||
import { useCameraPermission } from "react-native-vision-camera";
|
||||
import { showAlert } from "../../lib/alert-messages";
|
||||
|
||||
interface VideoFlowInputParams {
|
||||
sessionName?: string;
|
||||
gameType: string;
|
||||
tableSize: string;
|
||||
// TODO: #122 should decide on what values/labels go here.
|
||||
enum GameType {
|
||||
FreePlay = "freePlay",
|
||||
StraightPool = "straightPool",
|
||||
NineBall = "nineBall",
|
||||
}
|
||||
// TODO: #122 should be int -- inch value of table size.
|
||||
enum TableSize {
|
||||
NineFoot = "nineFoot",
|
||||
EightFoot = "eightFoot",
|
||||
SevenFoot = "sevenFoot",
|
||||
}
|
||||
|
||||
interface VideoUserInputMeta {
|
||||
sessionName: string;
|
||||
gameType: GameType | null;
|
||||
tableSize: TableSize | null;
|
||||
}
|
||||
|
||||
interface VideoFlowInputParams extends VideoUserInputMeta {
|
||||
videoId?: number;
|
||||
}
|
||||
|
||||
export const useVideoDetails = ({ mode, videoId, params, navigation }) => {
|
||||
function useDropdown<T>(
|
||||
initialValue: T | null,
|
||||
options: Array<{ label: string; value: T }>,
|
||||
closeOthers: () => void,
|
||||
) {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [value, setValue] = useState<T | null>(initialValue);
|
||||
const [optionsList, setOptionsList] = useState(options);
|
||||
|
||||
const toggleOpen = useCallback(() => {
|
||||
if (!isOpen) {
|
||||
closeOthers();
|
||||
}
|
||||
setIsOpen(!isOpen);
|
||||
}, [isOpen, closeOthers]);
|
||||
|
||||
return {
|
||||
isOpen,
|
||||
toggleOpen,
|
||||
value,
|
||||
setValue,
|
||||
optionsList,
|
||||
setOptionsList,
|
||||
setIsOpen,
|
||||
};
|
||||
}
|
||||
|
||||
export const useVideoDetails = ({
|
||||
params: {
|
||||
mode,
|
||||
videoId,
|
||||
sessionName: initialSessionName,
|
||||
gameType: initialGameType,
|
||||
tableSize: initialTableSize,
|
||||
},
|
||||
navigation,
|
||||
}) => {
|
||||
const initialState = {
|
||||
sessionName: initialSessionName || "",
|
||||
gameType: initialGameType || null,
|
||||
tableSize: initialTableSize || null,
|
||||
};
|
||||
const { hasPermission, requestPermission } = useCameraPermission();
|
||||
|
||||
// Initial state setup
|
||||
const initialState = mode === "save-video" && params ? params : {};
|
||||
|
||||
// Session name input
|
||||
// Should session name be required?
|
||||
const [sessionName, setSessionName] = useState<string>(
|
||||
initialState.sessionName || "",
|
||||
);
|
||||
|
||||
// Game type dropdown
|
||||
const [gameTypeOpen, setGameTypeOpen] = useState<boolean>(false);
|
||||
const [gameType, setGameType] = useState<string | null>(
|
||||
initialState.gameType || null,
|
||||
const closeAllDropdowns = useCallback(() => {
|
||||
gameType.setIsOpen(false);
|
||||
tableSize.setIsOpen(false);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
const gameType = useDropdown<GameType | null>(
|
||||
initialState.gameType,
|
||||
[
|
||||
{ label: "Free Play", value: GameType.FreePlay },
|
||||
{ label: "Straight Pool", value: GameType.StraightPool },
|
||||
{ label: "Nine Ball", value: GameType.NineBall },
|
||||
],
|
||||
closeAllDropdowns,
|
||||
);
|
||||
const [gameTypes, setGameTypes] = useState([
|
||||
{ label: "Free Play", value: "freePlay" },
|
||||
{ label: "Straight Pool", value: "straightPool" },
|
||||
{ label: "Nine Ball", value: "nineBall" },
|
||||
]);
|
||||
|
||||
// Table size dropdown
|
||||
const [tableSizeOpen, setTableSizeOpen] = useState<boolean>(false);
|
||||
const [tableSize, setTableSize] = useState<string>(
|
||||
initialState.tableSize || "",
|
||||
const tableSize = useDropdown<TableSize | null>(
|
||||
initialState.tableSize,
|
||||
[
|
||||
{ label: `9'`, value: TableSize.NineFoot },
|
||||
{ label: `8'`, value: TableSize.EightFoot },
|
||||
{ label: `7'`, value: TableSize.SevenFoot },
|
||||
],
|
||||
closeAllDropdowns,
|
||||
);
|
||||
const [tableSizes, setTableSizes] = useState([
|
||||
{ label: `9'`, value: "nineFoot" },
|
||||
{ label: `8'`, value: "eightFoot" },
|
||||
{ label: `7'`, value: "sevenFoot" },
|
||||
]);
|
||||
|
||||
// Toggle dropdowns mutually exclusive
|
||||
const onGameTypeOpen = useCallback(() => setTableSizeOpen(false), []);
|
||||
const onTableSizeOpen = useCallback(() => setGameTypeOpen(false), []);
|
||||
|
||||
// GraphQL Mutation
|
||||
const [TerminateUploadStream, { loading, error }] =
|
||||
gql.useTerminateUploadStreamMutation();
|
||||
|
||||
@ -60,12 +111,21 @@ export const useVideoDetails = ({ mode, videoId, params, navigation }) => {
|
||||
}
|
||||
|
||||
if (mode === "start-video") {
|
||||
const params: VideoFlowInputParams = { sessionName, gameType, tableSize };
|
||||
const params: VideoFlowInputParams = {
|
||||
sessionName,
|
||||
gameType: gameType.value,
|
||||
tableSize: tableSize.value,
|
||||
};
|
||||
navigation.push("Camera", params);
|
||||
} else {
|
||||
try {
|
||||
await TerminateUploadStream({
|
||||
variables: { videoId, videoName: sessionName, tableSize, gameType },
|
||||
variables: {
|
||||
videoId,
|
||||
videoName: sessionName,
|
||||
tableSize: tableSize.value,
|
||||
gameType: gameType.value,
|
||||
},
|
||||
});
|
||||
navigation.push("Tabs");
|
||||
} catch (err) {
|
||||
@ -78,19 +138,7 @@ export const useVideoDetails = ({ mode, videoId, params, navigation }) => {
|
||||
sessionName,
|
||||
setSessionName,
|
||||
gameType,
|
||||
setGameType,
|
||||
gameTypeOpen,
|
||||
setGameTypeOpen,
|
||||
gameTypes,
|
||||
setGameTypes,
|
||||
onGameTypeOpen,
|
||||
tableSize,
|
||||
setTableSize,
|
||||
setTableSizes,
|
||||
tableSizeOpen,
|
||||
setTableSizeOpen,
|
||||
tableSizes,
|
||||
onTableSizeOpen,
|
||||
handleSubmit,
|
||||
loading,
|
||||
error,
|
||||
|
@ -9,34 +9,20 @@ import {
|
||||
View,
|
||||
} from "react-native";
|
||||
import DropDownPicker from "react-native-dropdown-picker";
|
||||
// @ts-ignore
|
||||
import { useVideoDetails } from "../../component/video/use-video-details";
|
||||
|
||||
import { globalInputStyles } from "../../styles";
|
||||
import { recordStyles as styles } from "./styles";
|
||||
|
||||
export default function VideoDetails({ navigation, route }): React.JSX.Element {
|
||||
const { mode, videoId } = route.params;
|
||||
const { mode } = route.params;
|
||||
const {
|
||||
sessionName,
|
||||
setSessionName,
|
||||
gameType,
|
||||
setGameType,
|
||||
tableSize,
|
||||
setTableSize,
|
||||
gameTypeOpen,
|
||||
setGameTypeOpen,
|
||||
tableSizeOpen,
|
||||
setTableSizeOpen,
|
||||
onGameTypeOpen,
|
||||
onTableSizeOpen,
|
||||
handleSubmit,
|
||||
loading,
|
||||
tableSizes,
|
||||
gameTypes,
|
||||
setGameTypes,
|
||||
setTableSizes,
|
||||
} = useVideoDetails({ mode, videoId, params: route.params, navigation });
|
||||
} = useVideoDetails({ params: route.params, navigation });
|
||||
|
||||
const dropDownStyles = {
|
||||
style: globalInputStyles.dropdownStyle,
|
||||
@ -61,26 +47,24 @@ export default function VideoDetails({ navigation, route }): React.JSX.Element {
|
||||
<DropDownPicker
|
||||
zIndex={3000}
|
||||
zIndexInverse={1000}
|
||||
open={gameTypeOpen}
|
||||
value={gameType}
|
||||
items={gameTypes}
|
||||
setOpen={setGameTypeOpen}
|
||||
setValue={setGameType}
|
||||
setItems={setGameTypes}
|
||||
onOpen={onGameTypeOpen}
|
||||
open={gameType.isOpen}
|
||||
value={gameType.value}
|
||||
items={gameType.optionsList}
|
||||
setOpen={gameType.toggleOpen}
|
||||
setValue={gameType.setValue}
|
||||
setItems={gameType.setOptionsList}
|
||||
{...dropDownStyles}
|
||||
/>
|
||||
<Text style={globalInputStyles.dropdownTitle}>Table size</Text>
|
||||
<Text style={globalInputStyles.dropdownTitle}>Table Size</Text>
|
||||
<DropDownPicker
|
||||
zIndex={2000}
|
||||
zIndexInverse={2000}
|
||||
open={tableSizeOpen}
|
||||
value={tableSize}
|
||||
items={tableSizes}
|
||||
setOpen={setTableSizeOpen}
|
||||
setValue={setTableSize}
|
||||
setItems={setTableSizes}
|
||||
onOpen={onTableSizeOpen}
|
||||
open={tableSize.isOpen}
|
||||
value={tableSize.value}
|
||||
items={tableSize.optionsList}
|
||||
setOpen={tableSize.toggleOpen}
|
||||
setValue={tableSize.setValue}
|
||||
setItems={tableSize.setOptionsList}
|
||||
{...dropDownStyles}
|
||||
/>
|
||||
</View>
|
||||
|
Loading…
Reference in New Issue
Block a user