Grabbed dndbeyond's source code
``` ~/go/bin/sourcemapper -output ddb -jsurl https://media.dndbeyond.com/character-app/static/js/main.90aa78c5.js ```
This commit is contained in:
@@ -0,0 +1,243 @@
|
||||
import axios, { Canceler } from "axios";
|
||||
import React from "react";
|
||||
import { connect, DispatchProp } from "react-redux";
|
||||
|
||||
import { Checkbox } from "@dndbeyond/character-components/es";
|
||||
import {
|
||||
ApiAdapterUtils,
|
||||
ApiRequests,
|
||||
rulesEngineSelectors,
|
||||
characterActions,
|
||||
Condition,
|
||||
RuleData,
|
||||
ShortModelInfoContract,
|
||||
CharacterTheme,
|
||||
} from "@dndbeyond/character-rules-engine/es";
|
||||
|
||||
import { Header } from "~/subApps/sheet/components/Sidebar/components/Header";
|
||||
import { RestoreLifeManager } from "~/subApps/sheet/components/Sidebar/panes/HitPointsManagePane/RestoreLifeManager/RestoreLifeManager";
|
||||
|
||||
import { toastMessageActions } from "../../../actions/toastMessage";
|
||||
import { ThemeButton } from "../../../components/common/Button";
|
||||
import { SharedAppState } from "../../../stores/typings";
|
||||
import { AppLoggerUtils } from "../../../utils";
|
||||
|
||||
interface Props extends DispatchProp {
|
||||
activeConditions: Array<Condition>;
|
||||
ruleData: RuleData;
|
||||
isDead: boolean;
|
||||
theme: CharacterTheme;
|
||||
}
|
||||
interface State {
|
||||
resetMaxHpModifier: boolean;
|
||||
adjustConditionLevel: boolean;
|
||||
restMessage: string | null;
|
||||
}
|
||||
class LongRestPane extends React.PureComponent<Props, State> {
|
||||
loadMessageCanceler: null | Canceler = null;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
resetMaxHpModifier: true,
|
||||
adjustConditionLevel: false,
|
||||
restMessage: null,
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.loadMessage();
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
if (this.loadMessageCanceler !== null) {
|
||||
this.loadMessageCanceler();
|
||||
}
|
||||
}
|
||||
|
||||
loadMessage = (): void => {
|
||||
if (this.loadMessageCanceler !== null) {
|
||||
this.loadMessageCanceler();
|
||||
}
|
||||
|
||||
ApiRequests.getCharacterRestLong({
|
||||
cancelToken: new axios.CancelToken((c) => {
|
||||
this.loadMessageCanceler = c;
|
||||
}),
|
||||
})
|
||||
.then((response) => {
|
||||
let message = ApiAdapterUtils.getResponseData(response);
|
||||
if (message !== null) {
|
||||
this.setState({
|
||||
restMessage: message,
|
||||
});
|
||||
}
|
||||
this.loadMessageCanceler = null;
|
||||
})
|
||||
.catch(AppLoggerUtils.handleAdhocApiError);
|
||||
};
|
||||
|
||||
reset = (): void => {
|
||||
this.setState({
|
||||
resetMaxHpModifier: true,
|
||||
});
|
||||
};
|
||||
|
||||
handleReset = (): void => {
|
||||
this.setState({
|
||||
resetMaxHpModifier: true,
|
||||
adjustConditionLevel: false,
|
||||
});
|
||||
};
|
||||
|
||||
handleSave = (): void => {
|
||||
const { resetMaxHpModifier, adjustConditionLevel } = this.state;
|
||||
const { dispatch } = this.props;
|
||||
|
||||
dispatch(
|
||||
characterActions.longRest(resetMaxHpModifier, adjustConditionLevel)
|
||||
);
|
||||
dispatch(
|
||||
toastMessageActions.toastSuccess(
|
||||
"Long Rest Taken",
|
||||
"You have completed a long rest. Relevant abilities have been reset."
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
handleResetMaxHpChange = (enabled: boolean): void => {
|
||||
this.setState({
|
||||
resetMaxHpModifier: enabled,
|
||||
});
|
||||
};
|
||||
|
||||
handleAdjustExhaustionLevel = (enabled: boolean): void => {
|
||||
this.setState({
|
||||
adjustConditionLevel: enabled,
|
||||
});
|
||||
};
|
||||
|
||||
handleRestoreToLife = (restoreType: ShortModelInfoContract): void => {
|
||||
const { dispatch } = this.props;
|
||||
const restoreChoice = restoreType.name === "Full" ? "full" : "1";
|
||||
|
||||
dispatch(characterActions.restoreLife(restoreType.id));
|
||||
dispatch(
|
||||
toastMessageActions.toastSuccess(
|
||||
"Character Restored to Life",
|
||||
`You have been restored to life with ${restoreChoice} HP.`
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
renderRecover = (): React.ReactNode => {
|
||||
const { resetMaxHpModifier, adjustConditionLevel, restMessage } =
|
||||
this.state;
|
||||
|
||||
const { isDead, activeConditions } = this.props;
|
||||
|
||||
if (isDead) {
|
||||
return (
|
||||
<div className="ct-reset-pane__recover-sources">
|
||||
Your character is dead
|
||||
</div>
|
||||
);
|
||||
}
|
||||
const exhaustionIsActive = activeConditions.find(
|
||||
(condition) => condition.level !== null
|
||||
);
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="ct-reset-pane__recover-sources">
|
||||
{restMessage === null
|
||||
? "Asking the server what will be reset..."
|
||||
: restMessage}
|
||||
</div>
|
||||
<div className="ct-reset-pane__recover-max-hp">
|
||||
<Checkbox
|
||||
label="Reset Maximum HP changes during this rest"
|
||||
initiallyEnabled={resetMaxHpModifier}
|
||||
onChange={this.handleResetMaxHpChange}
|
||||
/>
|
||||
</div>
|
||||
{exhaustionIsActive && (
|
||||
<div className="ct-reset-pane__reset-exhaustion-level">
|
||||
<Checkbox
|
||||
label="Recover 1 Level of Exhaustion during this rest (requires food and drink)"
|
||||
initiallyEnabled={adjustConditionLevel}
|
||||
onChange={this.handleAdjustExhaustionLevel}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
renderActions = (): React.ReactNode => {
|
||||
const { isDead, ruleData, theme } = this.props;
|
||||
|
||||
if (isDead) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<RestoreLifeManager onSave={this.handleRestoreToLife} />
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="ct-reset-pane__actions">
|
||||
<div className="ct-reset-pane__action">
|
||||
<ThemeButton onClick={this.handleSave} enableConfirm={true}>
|
||||
Take Long Rest
|
||||
</ThemeButton>
|
||||
</div>
|
||||
<div className="ct-reset-pane__action">
|
||||
<ThemeButton onClick={this.handleReset} style="outline">
|
||||
Reset
|
||||
</ThemeButton>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="ct-reset-pane">
|
||||
<Header>Long Rest</Header>
|
||||
|
||||
<div className="ct-reset-pane__intro">
|
||||
<p>
|
||||
A long rest is a period of extended downtime, at least 8 hours long,
|
||||
during which a character sleeps for at least 6 hours and performs no
|
||||
more than 2 hours of light activity, such as reading, talking,
|
||||
eating, or standing watch.
|
||||
</p>
|
||||
<p>
|
||||
If the rest is interrupted by a period of strenuous activity — at
|
||||
least 1 hour of walking, fighting, casting spells, or similar
|
||||
adventuring activity — the characters must begin the rest again to
|
||||
gain any benefit from it.
|
||||
</p>
|
||||
</div>
|
||||
<div className="ct-reset-pane__recover">
|
||||
<div className="ct-reset-pane__recover-heading">Recover</div>
|
||||
{this.renderRecover()}
|
||||
</div>
|
||||
{this.renderActions()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function mapStateToProps(state: SharedAppState) {
|
||||
return {
|
||||
activeConditions: rulesEngineSelectors.getActiveConditions(state),
|
||||
isDead: rulesEngineSelectors.isDead(state),
|
||||
ruleData: rulesEngineSelectors.getRuleData(state),
|
||||
theme: rulesEngineSelectors.getCharacterTheme(state),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(LongRestPane);
|
||||
@@ -0,0 +1,4 @@
|
||||
import LongRestPane from "./LongRestPane";
|
||||
|
||||
export default LongRestPane;
|
||||
export { LongRestPane };
|
||||
Reference in New Issue
Block a user