Skip to content

Commit

Permalink
feat(oracle tables): Continued working on oracles
Browse files Browse the repository at this point in the history
  • Loading branch information
scottbenton committed Jan 29, 2024
1 parent cfebb97 commit 4753144
Show file tree
Hide file tree
Showing 8 changed files with 348 additions and 26 deletions.
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,21 @@ export function OracleSectionContent(props: OracleSectionContentProps) {
)}
{openOracleState.openOracleId && (
<OracleTablesSection
homebrewId={homebrewId}
collections={
openOracleCollection?.oracle_type === "tables"
? openOracleCollection.collections ?? {}
: {}
}
rollables={openOracleCollection?.contents ?? {}}
dbPath={collectionDbPath}
parentCollectionKey={
// If we are not at the root and we are not editing an oracle, set the parent
openOracleState.openOracleId?.dbId &&
!oracleCollectionDialogState.oracleId
? openOracleState.openOracleId.dbId
: ""
}
/>
)}
<OracleCollectionsSection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,16 @@ import { OracleTableDialogContents } from "./OracleTablesSection/OracleTableDial
import { DialogTitleWithCloseButton } from "components/shared/DialogTitleWithCloseButton";

export interface OracleTablesSectionProps {
homebrewId: string;
collections: Record<string, OracleCollection>;
rollables: Record<string, OracleRollable>;
dbPath: string;
parentCollectionKey?: string;
}

export function OracleTablesSection(props: OracleTablesSectionProps) {
const { collections, rollables } = props;
const { homebrewId, collections, rollables, dbPath, parentCollectionKey } =
props;

const [oracleTableDialogState, setOracleTableDialogState] = useState<{
open: boolean;
Expand Down Expand Up @@ -101,8 +105,11 @@ export function OracleTablesSection(props: OracleTablesSectionProps) {
Create Oracle Table
</DialogTitleWithCloseButton>
<OracleTableDialogContents
homebrewId={homebrewId}
onClose={closeOracleTableDialog}
tables={oracleTableRollables}
dbPath={dbPath}
parentCollectionKey={parentCollectionKey}
/>
</Dialog>
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { PropsWithChildren } from "react";
import { Control, useWatch } from "react-hook-form";

interface DetailsField {
showDetails?: boolean;
}

export interface OptionalDetailsColumnProps<T extends DetailsField> {
control: Control<T>;
}

export function OptionalDetailsColumn<T extends DetailsField>(
props: PropsWithChildren<OptionalDetailsColumnProps<T>>
) {
const { control, children } = props;

const showDetails =
useWatch<T>({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
name: "showDetails" as any,
control,
}) ?? false;

if (!showDetails) {
return null;
} else {
return <>{children}</>;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import {
Alert,
Button,
IconButton,
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableFooter,
TableHead,
TableRow,
TextField,
Typography,
} from "@mui/material";
import {
Control,
FormState,
UseFormRegister,
UseFormWatch,
useFieldArray,
} from "react-hook-form";
import { Form } from "./OracleTableSimpleForm";
import DeleteIcon from "@mui/icons-material/Delete";
import { OracleTableSum } from "./OracleTableSum";
import { OptionalDetailsColumn } from "./OptionalDetailsColumn";

export interface OracleTableProps {
control: Control<Form>;
disabled?: boolean;
touchedFields: FormState<Form>["touchedFields"];
errors: FormState<Form>["errors"];
register: UseFormRegister<Form>;
watch: UseFormWatch<Form>;
}

export function OracleTable(props: OracleTableProps) {
const { control, disabled, touchedFields, errors, register, watch } = props;

const { fields, append, remove } = useFieldArray({
control,
name: "columnValues",
rules: {
validate: (values) => {
const total = values.reduce(
(acc, row) => (acc += row.rollChance ?? 0),
0
);

if (total !== 100) {
console.debug("DID NOT SUM");
return "Total roll chance must sum to 100%";
}
},
},
});

return (
<TableContainer component={Paper} variant={"outlined"}>
{errors.columnValues?.root?.message && (
<Alert severity="error">{errors.columnValues.root.message}</Alert>
)}
<Table size={"small"}>
<TableHead>
<TableRow>
<TableCell>
Chance (%)
<Typography
component={"div"}
variant={"caption"}
color={"textSecondary"}
>
Must sum to 100
</Typography>
</TableCell>
<TableCell>Result</TableCell>
<OptionalDetailsColumn control={control}>
<TableCell>Details</TableCell>
</OptionalDetailsColumn>
<TableCell />
</TableRow>
</TableHead>
<TableBody>
{fields.map((row, index) => (
<TableRow key={index}>
<TableCell>
<TextField
disabled={disabled}
variant={"standard"}
placeholder={"Roll"}
fullWidth
error={
touchedFields.columnValues?.[index]?.rollChance &&
!!errors.columnValues?.[index]?.rollChance
}
helperText={
touchedFields.columnValues?.[index]?.rollChance &&
!!errors.columnValues?.[index]?.rollChance
? errors.columnValues[index]?.rollChance?.message
: undefined
}
inputProps={{
defaultValue: "",
...register(`columnValues.${index}.rollChance`, {
required: "This field is required.",
valueAsNumber: true,
}),
}}
/>
</TableCell>

<TableCell>
<TextField
disabled={disabled}
variant={"standard"}
placeholder={"Result"}
fullWidth
error={
touchedFields.columnValues?.[index]?.result &&
!!errors.columnValues?.[index]?.result
}
helperText={
touchedFields.columnValues?.[index]?.result &&
!!errors.columnValues?.[index]?.result
? errors.columnValues[index]?.result?.message
: undefined
}
inputProps={{
defaultValue: "",
...register(`columnValues.${index}.result`, {
required: "This field is required.",
}),
}}
/>
</TableCell>
<OptionalDetailsColumn control={control}>
<TableCell>
<TextField
disabled={disabled}
variant={"standard"}
placeholder={"Details"}
fullWidth
error={
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(touchedFields.columnValues?.[index] as any)?.detail &&
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(!!errors.columnValues?.[index] as any)?.detail
}
helperText={
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(touchedFields.columnValues?.[index] as any)?.detail &&
// eslint-disable-next-line @typescript-eslint/no-explicit-any
!!(errors.columnValues?.[index] as any)?.detail
? // eslint-disable-next-line @typescript-eslint/no-explicit-any
(errors.columnValues?.[index] as any)?.result?.message
: undefined
}
inputProps={{
defaultValue: "",
...register(`columnValues.${index}.detail`, {
required: "This field is required.",
}),
}}
/>
</TableCell>
</OptionalDetailsColumn>
<TableCell sx={{ width: 0, minWidth: "fit-content" }}>
<IconButton onClick={() => remove(index)}>
<DeleteIcon />
</IconButton>
</TableCell>
</TableRow>
))}
</TableBody>
<TableFooter>
<TableRow>
<TableCell>
<OracleTableSum watch={watch} fields={fields} />
</TableCell>
<TableCell>
<Button
color={"inherit"}
onClick={() => append({ rollChance: 0, result: "" })}
>
Add Row
</Button>
</TableCell>
</TableRow>
</TableFooter>
</Table>
</TableContainer>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ export interface OracleTableDialogContentsProps {
homebrewId: string;
onClose: () => void;
tables: Record<string, OracleTableRollable>;
dbPath: string;
parentCollectionKey?: string;
}

export function OracleTableDialogContents(
props: OracleTableDialogContentsProps
) {
const { homebrewId, onClose, tables } = props;
const { homebrewId, onClose, tables, dbPath, parentCollectionKey } = props;

const [tableType, setTableType] = useState<ORACLE_TABLE_TYPE>();
// TODO - Support other oracle table types
const [tableType, setTableType] = useState<ORACLE_TABLE_TYPE>(
ORACLE_TABLE_TYPE.SIMPLE
);

return (
<>
Expand All @@ -26,6 +31,8 @@ export function OracleTableDialogContents(
homebrewId={homebrewId}
onClose={onClose}
tables={tables}
dbPath={dbPath}
parentCollectionKey={parentCollectionKey}
/>
)}
{tableType === ORACLE_TABLE_TYPE.SHARED_RESULTS && (
Expand Down
Loading

0 comments on commit 4753144

Please sign in to comment.