code:
import { round, toFixed } from 'common/math';
import { resolveAsset } from '../assets';
import { useBackend } from '../backend';
import { AnimatedNumber, Box, Button, Flex, Icon, NumberInput, ProgressBar, RoundGauge, Section, Table } from '../components';
import { COLORS } from '../constants';
import { Window } from '../layouts';
import { BeakerContents } from './common/BeakerContents';

export const ChemHeater = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    targetTemp,
    isActive,
    isFlashing,
    currentpH,
    isBeakerLoaded,
    currentTemp,
    beakerCurrentVolume,
    beakerMaxVolume,
    acidicBufferVol,
    basicBufferVol,
    dispenseVolume,
    upgradeLevel,
    tutorialMessage,
    beakerContents = [],
    activeReactions = [],
  } = data;
  return (
    <Window
      width={330}
      height={tutorialMessage ? 680 : 350}>
      <Window.Content scrollable>
        <Section
          title="Controls"
          buttons={(
            <Flex>
              <Button
                icon={"question"}
                selected={tutorialMessage}
                content={"Help"}
                left={-2}
                tooltip={"Guides you through a tutorial reaction!"}
                onClick={() => act('help')} />
              <Button
                icon={isActive ? 'power-off' : 'times'}
                selected={isActive}
                content={isActive ? 'On' : 'Off'}
                onClick={() => act('power')} />
            </Flex>
          )}>

                Heat

                Buffers

                <NumberInput
                  width="45px"
                  unit="u"
                  step={1}
                  stepPixelSize={3}
                  value={dispenseVolume}
                  minValue={1}
                  maxValue={10}
                  onDrag={(e, value) => act('disp_vol', {
                    target: value,
                  })} />

                Target:

                <NumberInput
                  width="65px"
                  unit="K"
                  step={10}
                  stepPixelSize={3}
                  value={round(targetTemp)}
                  minValue={0}
                  maxValue={1000}
                  onDrag={(e, value) => act('temperature', {
                    target: value,
                  })} />

                Acidic:

                <Button
                  icon={'syringe'}
                  disabled={!acidicBufferVol}
                  tooltip={'Inject'}
                  tooltipPosition={"left"}
                  onClick={() => act('acidBuffer', {
                    target: 1,
                  })} />

                {acidicBufferVol + "u"}

                <Button
                  icon={'upload'}
                  tooltip={'Draw all'}
                  tooltipPosition={"top"}
                  disabled={acidicBufferVol === 100}
                  onClick={() => act('acidBuffer', {
                    target: -100,
                  })} />

                Reading:

                <Box
                  width="60px"
                  textAlign="right">
                  {isBeakerLoaded && (
                    <AnimatedNumber
                      value={currentTemp}
                      format={value => toFixed(value) + ' K'} />
                  ) || '—'}
                </Box>

                Basic:

                <Button
                  icon={'syringe'}
                  tooltip={'Inject'}
                  tooltipPosition={"left"}
                  disabled={!basicBufferVol}
                  onClick={() => act('basicBuffer', {
                    target: 1,
                  })} />

                {basicBufferVol + "u"}

                <Button
                  icon={'upload'}
                  tooltip={'Draw all'}
                  disabled={basicBufferVol === 100}
                  onClick={() => act('basicBuffer', {
                    target: -100,
                  })} />

        {!!isBeakerLoaded && (
          <Section
            title="Reactions"
            buttons={(
              <Flex>
                <Flex.Item color="label">
                  <AnimatedNumber
                    value={currentpH}
                    format={value => 'pH: ' + round(value, 3)} />
                </Flex.Item>
                <Flex.Item>
                  <AnimatedNumber value={currentpH}>
                    {(_, value) => (
                      <RoundGauge
                        size={1.60}
                        value={value}
                        minValue={0}
                        maxValue={14}
                        alertAfter={isFlashing}
                        content={"test"}
                        format={value => null}
                        ranges={{
                          "red": [-0.22, 1.5],
                          "orange": [1.5, 3],
                          "yellow": [3, 4.5],
                          "olive": [4.5, 5],
                          "good": [5, 6],
                          "green": [6, 8.5],
                          "teal": [8.5, 9.5],
                          "blue": [9.5, 11],
                          "purple": [11, 12.5],
                          "violet": [12.5, 14],
                        }} />
                    )}
                  </AnimatedNumber>
                </Flex.Item>
              </Flex>
            )}>
            {activeReactions.length === 0 && (
              <Box color="label">
                No active reactions.
              </Box>
            ) || (

                    Reaction

                    {upgradeLevel < 4 ? "Status" : "Reaction quality"}

                    Target

                {activeReactions.map(reaction => (

                      {reaction.name}

                      {upgradeLevel < 4 && (
                        <Icon
                          name={reaction.danger ? "exclamation-triangle" : "spinner"}
                          color={reaction.danger && "red"}
                          spin={!reaction.danger}
                          ml={2.5} />
                      ) || (
                        <AnimatedNumber value={reaction.quality}>
                          {(_, value) => (
                            <RoundGauge
                              size={1.30}
                              value={value}
                              minValue={0}
                              maxValue={1}
                              alertAfter={reaction.purityAlert}
                              content={"test"}
                              format={value => null}
                              ml={5}
                              ranges={{
                                "red": [0, reaction.minPure],
                                "orange": [reaction.minPure, reaction.inverse],
                                "yellow": [reaction.inverse, 0.8],
                                "green": [0.8, 1],
                              }} />
                          )}
                        </AnimatedNumber>
                      )}

                      {upgradeLevel > 2 && (
                        <ProgressBar
                          value={reaction.reactedVol}
                          minValue={0}
                          maxValue={reaction.targetVol}
                          textAlign={'center'}
                          icon={reaction.overheat && "thermometer-full"}
                          width={7}
                          color={reaction.overheat ? "red" : "label"}>
                          {reaction.targetVol}u
                        </ProgressBar>
                      ) || (
                        <Box
                          color={reaction.danger && "red"}
                          ml={2}>
                          {reaction.targetVol}u
                        </Box>
                      )}

                ))}

            )}

        )}
        {tutorialMessage && (

            {tutorialMessage}

        )}
        <Section
          title="Beaker"
          buttons={!!isBeakerLoaded && (
            <>
              <Box inline color="label" mr={2}>
                {beakerCurrentVolume} / {beakerMaxVolume} units
              </Box>
              <Button
                icon="eject"
                content="Eject"
                onClick={() => act('eject')} />
            </>
          )}>
          <BeakerContents
            beakerLoaded={isBeakerLoaded}
            beakerContents={beakerContents} />

      </Window.Content>
    </Window>
  );
};


code:
import { useBackend, useSharedState } from '../backend';
import { AnimatedNumber, Box, Button, ColorBox, LabeledList, NumberInput, Section, Table } from '../components';
import { Window } from '../layouts';

export const ChemMaster = (props, context) => {
  const { data } = useBackend(context);
  const { screen } = data;
  return (
    <Window
      width={465}
      height={550}>
      <Window.Content scrollable>
        {screen === 'analyze' && (
          <AnalysisResults />
        ) || (
          <ChemMasterContent />
        )}
      </Window.Content>
    </Window>
  );
};

const ChemMasterContent = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    screen,
    beakerContents = [],
    bufferContents = [],
    beakerCurrentVolume,
    beakerMaxVolume,
    isBeakerLoaded,
    isPillBottleLoaded,
    pillBottleCurrentAmount,
    pillBottleMaxAmount,
  } = data;
  if (screen === 'analyze') {
    return <AnalysisResults />;
  }
  return (
    <>
      <Section
        title="Beaker"
        buttons={!!data.isBeakerLoaded && (
          <>
            <Box inline color="label" mr={2}>
              <AnimatedNumber
                value={beakerCurrentVolume}
                initial={0} />
              {` / ${beakerMaxVolume} units`}
            </Box>
            <Button
              icon="eject"
              content="Eject"
              onClick={() => act('eject')} />
          </>
        )}>
        {!isBeakerLoaded && (
          <Box color="label" mt="3px" mb="5px">
            No beaker loaded.
          </Box>
        )}
        {!!isBeakerLoaded && beakerContents.length === 0 && (
          <Box color="label" mt="3px" mb="5px">
            Beaker is empty.
          </Box>
        )}
        <ChemicalBuffer>
          {beakerContents.map(chemical => (
            <ChemicalBufferEntry
              key={chemical.id}
              chemical={chemical}
              transferTo="buffer" />
          ))}
        </ChemicalBuffer>
      </Section>
      <Section
        title="Buffer"
        buttons={(
          <>
            <Box inline color="label" mr={1}>
              Mode:
            </Box>
            <Button
              color={data.mode ? 'good' : 'bad'}
              icon={data.mode ? 'exchange-alt' : 'times'}
              content={data.mode ? 'Transfer' : 'Destroy'}
              onClick={() => act('toggleMode')} />
          </>
        )}>
        {bufferContents.length === 0 && (
          <Box color="label" mt="3px" mb="5px">
            Buffer is empty.
          </Box>
        )}
        <ChemicalBuffer>
          {bufferContents.map(chemical => (
            <ChemicalBufferEntry
              key={chemical.id}
              chemical={chemical}
              transferTo="beaker" />
          ))}
        </ChemicalBuffer>
      </Section>
      <Section
        title="Packaging">
        <PackagingControls />
      </Section>
      {!!isPillBottleLoaded && (
        <Section
          title="Pill Bottle"
          buttons={(
            <>
              <Box inline color="label" mr={2}>
                {pillBottleCurrentAmount} / {pillBottleMaxAmount} pills
              </Box>
              <Button
                icon="eject"
                content="Eject"
                onClick={() => act('ejectPillBottle')} />
            </>
          )} />
      )}
    </>
  );
};

const ChemicalBuffer = Table;

const ChemicalBufferEntry = (props, context) => {
  const { act } = useBackend(context);
  const { chemical, transferTo } = props;
  return (
    <Table.Row key={chemical.id}>
      <Table.Cell color="label">
        <AnimatedNumber
          value={chemical.volume}
          initial={0} />
        {` units of ${chemical.name}`}
      </Table.Cell>
      <Table.Cell collapsing>
        <Button
          content="1"
          onClick={() => act('transfer', {
            id: chemical.id,
            amount: 1,
            to: transferTo,
          })} />
        <Button
          content="5"
          onClick={() => act('transfer', {
            id: chemical.id,
            amount: 5,
            to: transferTo,
          })} />
        <Button
          content="10"
          onClick={() => act('transfer', {
            id: chemical.id,
            amount: 10,
            to: transferTo,
          })} />
        <Button
          content="All"
          onClick={() => act('transfer', {
            id: chemical.id,
            amount: 1000,
            to: transferTo,
          })} />
        <Button
          icon="ellipsis-h"
          title="Custom amount"
          onClick={() => act('transfer', {
            id: chemical.id,
            amount: -1,
            to: transferTo,
          })} />
        <Button
          icon="question"
          title="Analyze"
          onClick={() => act('analyze', {
            id: chemical.id,
          })} />
      </Table.Cell>
    </Table.Row>
  );
};

const PackagingControlsItem = props => {
  const {
    label,
    amountUnit,
    amount,
    onChangeAmount,
    onCreate,
    sideNote,
  } = props;
  return (
    <LabeledList.Item label={label}>
      <NumberInput
        width="84px"
        unit={amountUnit}
        step={1}
        stepPixelSize={15}
        value={amount}
        minValue={1}
        maxValue={10}
        onChange={onChangeAmount} />
      <Button
        ml={1}
        content="Create"
        onClick={onCreate} />
      <Box inline ml={1} color="label">
        {sideNote}
      </Box>
    </LabeledList.Item>
  );
};

const PackagingControls = (props, context) => {
  const { act, data } = useBackend(context);
  const [
    pillAmount,
    setPillAmount,
  ] = useSharedState(context, 'pillAmount', 1);
  const [
    patchAmount,
    setPatchAmount,
  ] = useSharedState(context, 'patchAmount', 1);
  const [
    bottleAmount,
    setBottleAmount,
  ] = useSharedState(context, 'bottleAmount', 1);
  const [
    packAmount,
    setPackAmount,
  ] = useSharedState(context, 'packAmount', 1);
  const {
    condi,
    chosenPillStyle,
    chosenCondiStyle,
    autoCondiStyle,
    pillStyles = [],
    condiStyles = [],
  } = data;
  const autoCondiStyleChosen = autoCondiStyle === chosenCondiStyle;
  return (
    <LabeledList>
      {!condi && (
        <LabeledList.Item label="Pill type">
          {pillStyles.map(pill => (
            <Button
              key={pill.id}
              width="30px"
              selected={pill.id === chosenPillStyle}
              textAlign="center"
              color="transparent"
              onClick={() => act('pillStyle', { id: pill.id })}>
              <Box mx={-1} className={pill.className} />
            </Button>
          ))}
        </LabeledList.Item>
      )}
      {!condi && (
        <PackagingControlsItem
          label="Pills"
          amount={pillAmount}
          amountUnit="pills"
          sideNote="max 50u"
          onChangeAmount={(e, value) => setPillAmount(value)}
          onCreate={() => act('create', {
            type: 'pill',
            amount: pillAmount,
            volume: 'auto',
          })} />
      )}
      {!condi && (
        <PackagingControlsItem
          label="Patches"
          amount={patchAmount}
          amountUnit="patches"
          sideNote="max 40u"
          onChangeAmount={(e, value) => setPatchAmount(value)}
          onCreate={() => act('create', {
            type: 'patch',
            amount: patchAmount,
            volume: 'auto',
          })} />
      )}
      {!condi && (
        <PackagingControlsItem
          label="Bottles"
          amount={bottleAmount}
          amountUnit="bottles"
          sideNote="max 30u"
          onChangeAmount={(e, value) => setBottleAmount(value)}
          onCreate={() => act('create', {
            type: 'bottle',
            amount: bottleAmount,
            volume: 'auto',
          })} />
      )}
      {!!condi && (
        <LabeledList.Item label="Bottle type">
          <Button.Checkbox
            onClick={() => act('condiStyle', { id: autoCondiStyleChosen ? condiStyles[0].id : autoCondiStyle })}
            checked={autoCondiStyleChosen}
            disabled={!condiStyles.length}>
            Guess from contents
          </Button.Checkbox>
        </LabeledList.Item>
      )}
      {!!condi && !autoCondiStyleChosen && (
        <LabeledList.Item label="">
          {condiStyles.map(style => (
            <Button
              key={style.id}
              width="30px"
              selected={style.id === chosenCondiStyle}
              textAlign="center"
              color="transparent"
              title={style.title}
              onClick={() => act('condiStyle', { id: style.id })}>
              <Box mx={-1} className={style.className} />
            </Button>
          ))}
        </LabeledList.Item>
      )}
      {!!condi && (
        <PackagingControlsItem
          label="Bottles"
          amount={bottleAmount}
          amountUnit="bottles"
          sideNote="max 50u"
          onChangeAmount={(e, value) => setBottleAmount(value)}
          onCreate={() => act('create', {
            type: 'condimentBottle',
            amount: bottleAmount,
            volume: 'auto',
          })} />
      )}
      {!!condi && (
        <PackagingControlsItem
          label="Packs"
          amount={packAmount}
          amountUnit="packs"
          sideNote="max 10u"
          onChangeAmount={(e, value) => setPackAmount(value)}
          onCreate={() => act('create', {
            type: 'condimentPack',
            amount: packAmount,
            volume: 'auto',
          })} />
      )}
    </LabeledList>
  );
};

const AnalysisResults = (props, context) => {
  const { act, data } = useBackend(context);
  const { analyzeVars } = data;
  return (
    <Section
      title="Analysis Results"
      buttons={(
        <Button
          icon="arrow-left"
          content="Back"
          onClick={() => act('goScreen', {
            screen: 'home',
          })} />
      )}>
      <LabeledList>
        <LabeledList.Item label="Name">
          {analyzeVars.name}
        </LabeledList.Item>
        <LabeledList.Item label="State">
          {analyzeVars.state}
        </LabeledList.Item>
        <LabeledList.Item label="pH">
          {analyzeVars.ph}
        </LabeledList.Item>
        <LabeledList.Item label="Color">
          <ColorBox color={analyzeVars.color} mr={1} />
          {analyzeVars.color}
        </LabeledList.Item>
        <LabeledList.Item label="Description">
          {analyzeVars.description}
        </LabeledList.Item>
        <LabeledList.Item label="Metabolization Rate">
          {analyzeVars.metaRate} u/minute
        </LabeledList.Item>
        <LabeledList.Item label="Overdose Threshold">
          {analyzeVars.overD}
        </LabeledList.Item>
        <LabeledList.Item label="Addiction Threshold">
          {analyzeVars.addicD}
        </LabeledList.Item>
      </LabeledList>
    </Section>
  );
};

repo_name: AnalWerewolf/sundown

license: mit


code:
import { useBackend } from '../backend';
import { Box, Button, Input, LabeledList, NumberInput, Section } from '../components';
import { Window } from '../layouts';

export const ChemPress = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    current_volume,
    product_name,
    pill_style,
    pill_styles = [],
    product,
    min_volume,
    max_volume,
  } = data;
  return (
    <Window
      width={300}
      height={227}>
      <Window.Content>
        <Section>
          <LabeledList>
            <LabeledList.Item label="Product">
              <Button.Checkbox
                content="Pills"
                checked={product === "pill"}
                onClick={() => act('change_product', {
                  product: "pill",
                })}
              />
              <Button.Checkbox
                content="Patches"
                checked={product === "patch"}
                onClick={() => act('change_product', {
                  product: "patch",
                })}
              />
              <Button.Checkbox
                content="Bottles"
                checked={product === "bottle"}
                onClick={() => act('change_product', {
                  product: "bottle",
                })}
              />
            </LabeledList.Item>
            <LabeledList.Item label="Volume">
              <NumberInput
                value={current_volume}
                unit="u"
                width="43px"
                minValue={min_volume}
                maxValue={max_volume}
                step={1}
                stepPixelSize={2}
                onChange={(e, value) => act('change_current_volume', {
                  volume: value,
                })} />
            </LabeledList.Item>
            <LabeledList.Item label="Name">
              <Input
                value={product_name}
                placeholder={product_name}
                onChange={(e, value) => act('change_product_name', {
                  name: value,
                })} />
              <Box as="span">
                {product}
              </Box>
            </LabeledList.Item>
            {product === "pill" && (
              <LabeledList.Item label="Style">
                {pill_styles.map(pill => (
                  <Button
                    key={pill.id}
                    width="30px"
                    selected={pill.id === pill_style}
                    textAlign="center"
                    color="transparent"
                    onClick={() => act('change_pill_style', {
                      id: pill.id,
                    })}>
                    <Box mx={-1} className={pill.class_name} />
                  </Button>
                ))}
              </LabeledList.Item>
            )}
          </LabeledList>
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend, useLocalState } from '../backend';
import { AnimatedNumber, Box, Button, Input, LabeledList, NumberInput, Section, RoundGauge, Stack } from '../components';
import { Window } from '../layouts';
import { round, toFixed } from 'common/math';

export const ChemReactionChamber = (props, context) => {
  const { act, data } = useBackend(context);

  const [
    reagentName,
    setReagentName,
  ] = useLocalState(context, 'reagentName', '');
  const [
    reagentQuantity,
    setReagentQuantity,
  ] = useLocalState(context, 'reagentQuantity', 1);

  const {
    emptying,
    temperature,
    ph,
    targetTemp,
    isReacting,
    reagentAcidic,
    reagentAlkaline,
  } = data;
  const reagents = data.reagents || [];
  return (
    <Window
      width={290}
      height={400}>
      <Window.Content>
        <Stack vertical fill>
          <Stack.Item>
            <Section
              title="Conditions"
              buttons={(
                <Stack>
                  <Stack.Item mt={0.3}>
                    {"Target:"}
                  </Stack.Item>
                  <Stack.Item>
                    <NumberInput
                      width="65px"
                      unit="K"
                      step={10}
                      stepPixelSize={3}
                      value={round(targetTemp)}
                      minValue={0}
                      maxValue={1000}
                      onDrag={(e, value) => act('temperature', {
                        target: value,
                      })} />
                  </Stack.Item>
                </Stack>
              )}>
              <Stack vertical>
                <Stack.Item>
                  <Stack fill>
                    <Stack.Item textColor="label">
                      Current Temperature:
                    </Stack.Item>
                    <Stack.Item grow>
                      <AnimatedNumber
                        value={temperature}
                        format={value => toFixed(value) + ' K'} />
                    </Stack.Item>
                    <Stack.Item grow>
                      <RoundGauge
                        value={ph}
                        minValue={0}
                        maxValue={14}
                        format={() => null}
                        position="absolute"
                        size={1.50}
                        top={0.5}
                        right={0.5}
                        ranges={{
                          "red": [-0.22, 1.5],
                          "orange": [1.5, 3],
                          "yellow": [3, 4.5],
                          "olive": [4.5, 5],
                          "good": [5, 6],
                          "green": [6, 8.5],
                          "teal": [8.5, 9.5],
                          "blue": [9.5, 11],
                          "purple": [11, 12.5],
                          "violet": [12.5, 14],
                        }} />
                    </Stack.Item>
                  </Stack>
                </Stack.Item>
                <Stack.Item>
                  <Stack fill>
                    <Stack.Item textColor="label">
                      {"ph:"}
                    </Stack.Item>
                    <Stack.Item grow={15}>
                      {ph}
                    </Stack.Item>
                    <Stack.Item grow mt={1} mb={-0.5}>
                      <Button
                        color="transparent"
                        icon="question"
                        tooltip={multiline`
                        In chemistry, pH is a scale used to specify
                        the acidity or basicity of an aqueous solution.
                        Acidic solutions are measured to have lower
                        pH values than basic or alkaline solutions.
                        The pH scale is logarithmic and inversely
                        indicates the concentration of hydrogen ions
                        in the solution.`}
                        tooltipPosition="bottom-start" />
                    </Stack.Item>
                  </Stack>
                </Stack.Item>
              </Stack>
            </Section>
          </Stack.Item>
          <Stack.Item grow>
            <Section
              title="Settings"
              fill
              scrollable
              buttons={(
                isReacting && (
                  <Box
                    inline
                    bold
                    color={"purple"}>
                    {"Reacting"}
                  </Box>
                ) || (
                  <Box
                    fontSize="16px"
                    inline
                    bold
                    color={emptying ? "bad" : "good"}>
                    {emptying ? "Emptying" : "Filling"}
                  </Box>
                )
              )}>
              <Stack vertical fill>
                <Stack.Item>
                  <LabeledList>
                    <LabeledList.Item label="Acidic pH limit">
                      <NumberInput
                        value={reagentAcidic}
                        minValue={-1000}
                        maxValue={1000}
                        step={1}
                        stepPixelSize={3}
                        width="39px"
                        onDrag={(e, value) => act('acidic', {
                          target: value,
                        })} />
                    </LabeledList.Item>
                    <LabeledList.Item label="Alkaline pH limit">
                      <NumberInput
                        value={reagentAlkaline}
                        minValue={-1000}
                        maxValue={1000}
                        step={1}
                        stepPixelSize={3}
                        width="39px"
                        onDrag={(e, value) => act('alkaline', {
                          target: value,
                        })} />
                      <Box inline mr={1} />
                    </LabeledList.Item>
                  </LabeledList>
                </Stack.Item>
                <Stack.Item>
                  <Stack fill>
                    <Stack.Item grow>
                      <Input
                        fluid
                        value=""
                        placeholder="Reagent Name"
                        onInput={(e, value) => setReagentName(value)} />
                    </Stack.Item>
                    <Stack.Item>
                      <NumberInput
                        value={reagentQuantity}
                        minValue={1}
                        maxValue={100}
                        step={1}
                        stepPixelSize={3}
                        width="39px"
                        onDrag={(e, value) => setReagentQuantity(value)} />
                      <Box inline mr={1} />
                    </Stack.Item>
                    <Stack.Item>
                      <Button
                        icon="plus"
                        onClick={() => act('add', {
                          chem: reagentName,
                          amount: reagentQuantity,
                        })} />
                    </Stack.Item>
                  </Stack>
                </Stack.Item>
                <Stack.Item>
                  <Stack vertical>
                    {reagents.map(reagent => (
                      <Stack.Item key={reagent}>
                        <Stack fill>
                          <Stack.Item mt={0.25} textColor="label">
                            {reagent.name+":"}
                          </Stack.Item>
                          <Stack.Item mt={0.25} grow>
                            {reagent.required_reagent}
                          </Stack.Item>
                          <Stack.Item>
                            <Button
                              icon="minus"
                              color="bad"
                              onClick={() => act('remove', {
                                chem: reagent.name,
                              })} />
                          </Stack.Item>
                        </Stack>
                      </Stack.Item>
                    ))}
                  </Stack>
                </Stack.Item>
              </Stack>
            </Section>
          </Stack.Item>
        </Stack>
      </Window.Content>
    </Window>
  );
};


code:
import { round } from 'common/math';
import { useBackend } from '../backend';
import { AnimatedNumber, Box, Button, Flex, LabeledList, NumberInput, ProgressBar, RoundGauge, Section, Table } from '../components';
import { Window } from '../layouts';
import { BeakerContents } from './common/BeakerContents';

export const ChemRecipeDebug = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    targetTemp,
    isActive,
    isFlashing,
    currentTemp,
    currentpH,
    forcepH,
    forceTemp,
    targetVol,
    targatpH,
    processing,
    processAll,
    index,
    endIndex,
    beakerSpawn,
    minTemp,
    editRecipeName,
    editRecipeCold,
    editRecipe = [],
    chamberContents = [],
    activeReactions = [],
    queuedReactions = [],
  } = data;
  return (
    <Window
      width={450}
      height={850}>
      <Window.Content scrollable>
        <Section
          title="Controls"
          buttons={(
            <>
              <Button
                icon={beakerSpawn ? 'power-off' : 'times'}
                selected={beakerSpawn}
                content={"Spawn beaker"}
                onClick={() => act('beakerSpawn')} />
              <Button
                icon={processAll ? 'power-off' : 'times'}
                selected={processAll}
                content={"All"}
                onClick={() => act('all')} />
            </>
          )}>
          <LabeledList>
            <LabeledList.Item label="Reactions">
              <Button
                icon="plus"
                onClick={() => act('setTargetList')} />
            </LabeledList.Item>
            <LabeledList.Item label="Queued">
              {processAll && (
                <Box>All</Box>
              ) || (
                <Box>
                  {queuedReactions.length && (
                    queuedReactions.map(entry => (
                      entry.name+", "
                    ))
                  )}
                </Box>
              )}
            </LabeledList.Item>
            <LabeledList.Item label="Temp">
              {currentTemp}K
              <NumberInput
                width="65px"
                unit="K"
                step={10}
                stepPixelSize={3}
                value={round(targetTemp)}
                minValue={0}
                maxValue={1000}
                onDrag={(e, value) => act('temperature', {
                  target: value,
                })} />
              <Button
                icon={forceTemp ? 'power-off' : 'times'}
                selected={forceTemp}
                content={"Force"}
                onClick={() => act('forceTemp')} />
              <Button
                icon={minTemp ? 'power-off' : 'times'}
                selected={minTemp}
                content={"MinTemp"}
                onClick={() => act('minTemp')} />
            </LabeledList.Item>
            <LabeledList.Item label="Vol multi">
              <NumberInput
                width="65px"
                unit="x"
                step={1}
                stepPixelSize={3}
                value={round(targetVol)}
                minValue={1}
                maxValue={200}
                onDrag={(e, value) => act('vol', {
                  target: value,
                })} />
            </LabeledList.Item>
            <LabeledList.Item label="pH">
              {currentpH}
              <NumberInput
                width="65px"
                step={0.1}
                stepPixelSize={3}
                value={targatpH}
                minValue={0}
                maxValue={14}
                onDrag={(e, value) => act('pH', {
                  target: value,
                })} />
              <Button
                icon={forcepH ? 'power-off' : 'times'}
                selected={forcepH}
                content={"Force"}
                onClick={() => act('forcepH')} />
            </LabeledList.Item>
            <LabeledList.Item label="Index">
              {index} of {endIndex}
            </LabeledList.Item>
            <LabeledList.Item label="Start">
              <Button
                icon={processing ? 'power-off' : 'times'}
                selected={!!processing}
                content={"Start"}
                onClick={() => act('start')} />
              <Button
                icon={processing ? 'times' : 'power-off'}
                color="red"
                content={"Stop"}
                onClick={() => act('stop')} />
            </LabeledList.Item>
          </LabeledList>
        </Section>
        <Section
          title="Recipe edit">
          <LabeledList>
            <LabeledList.Item label={editRecipeName ? editRecipeName : "lookup"}>
              <Button
                icon={'flask'}
                color="purple"
                content={"Select recipe"}
                onClick={() => act('setEdit')} />
            </LabeledList.Item>
            {!!editRecipe && (
              <>
                <LabeledList.Item label="is_cold_recipe">
                  <Button
                    icon={editRecipeCold ? 'smile' : 'times'}
                    color={editRecipeCold ? 'green' : 'red'}
                    content={"Cold?"}
                    onClick={() => act("updateVar", {
                      type: entry.name,
                      target: value,
                    })} />
                </LabeledList.Item>
                {editRecipe.map(entry => (
                  <LabeledList.Item label={entry.name} key={entry.name}>
                    <NumberInput
                      width="65px"
                      step={1}
                      stepPixelSize={3}
                      value={entry.var}
                      minValue={-9999}
                      maxValue={9999}
                      onDrag={(e, value) => act("updateVar", {
                        type: entry.name,
                        target: value,
                      })} />
                  </LabeledList.Item>
                ))}
              </>
            )}
            <LabeledList.Item label="Export">
              <Button
                icon={'save'}
                color="green"
                content={"export"}
                onClick={() => act('export')} />
            </LabeledList.Item>
          </LabeledList>
        </Section>
        <Section
          title="Reactions"
          buttons={(
            <Flex>
              <Flex.Item color="label">
                <AnimatedNumber
                  value={currentpH}
                  format={value => 'pH: ' + round(value, 3)} />
              </Flex.Item>
              <Flex.Item>
                <AnimatedNumber value={currentpH}>
                  {(_, value) => (
                    <RoundGauge
                      size={1.60}
                      value={value}
                      minValue={0}
                      maxValue={14}
                      alertAfter={isFlashing}
                      content={"test"}
                      format={value => null}
                      ranges={{
                        "red": [-0.22, 1.5],
                        "orange": [1.5, 3],
                        "yellow": [3, 4.5],
                        "olive": [4.5, 5],
                        "good": [5, 6],
                        "green": [6, 8.5],
                        "teal": [8.5, 9.5],
                        "blue": [9.5, 11],
                        "purple": [11, 12.5],
                        "violet": [12.5, 14],
                      }} />
                  )}
                </AnimatedNumber>
              </Flex.Item>
            </Flex>
          )}>
          {activeReactions.length === 0 && (
            <Box color="label">
              No active reactions.
            </Box>
          ) || (
            <Table>
              <Table.Row>
                <Table.Cell bold color="label">
                  Reaction
                </Table.Cell>
                <Table.Cell bold color="label">
                  {"Reaction quality"}
                </Table.Cell>
                <Table.Cell bold color="label">
                  Target
                </Table.Cell>
              </Table.Row>
              {activeReactions && activeReactions.map(reaction => (
                <Table.Row key="reactions">
                  <Table.Cell width={'60px'} color={reaction.danger && "red"}>
                    {reaction.name}
                  </Table.Cell>
                  <Table.Cell width={'100px'} pr={'10px'}>
                    <AnimatedNumber value={reaction.quality}>
                      {(_, value) => (
                        <RoundGauge
                          size={1.30}
                          value={value}
                          minValue={0}
                          maxValue={1}
                          alertAfter={reaction.purityAlert}
                          content={"test"}
                          format={value => null}
                          ml={5}
                          ranges={{
                            "red": [0, reaction.minPure],
                            "orange": [reaction.minPure, reaction.inverse],
                            "yellow": [reaction.inverse, 0.8],
                            "green": [0.8, 1],
                          }} />
                      )}
                    </AnimatedNumber>
                  </Table.Cell>
                  <Table.Cell width={'70px'}>
                    <ProgressBar
                      value={reaction.reactedVol}
                      minValue={0}
                      maxValue={reaction.targetVol}
                      textAlign={'center'}
                      icon={reaction.overheat && "thermometer-full"}
                      width={7}
                      color={reaction.overheat ? "red" : "label"}>
                      {reaction.targetVol}u
                    </ProgressBar>
                  </Table.Cell>
                </Table.Row>
              ))}
              <Table.Row />
            </Table>
          )}
        </Section>
        <Section
          title="Chamber"
          buttons={(
            <Box>
              {isActive ? "Reacting" : "Waiting"}
            </Box>
          )} >
          {chamberContents.length &&(
            <BeakerContents
              beakerLoaded
              beakerContents={chamberContents} />
          ) || (
            <Box>
              Nothing
            </Box>
          )}
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { toFixed } from 'common/math';
import { useBackend } from '../backend';
import { LabeledList, NumberInput, Section } from '../components';
import { Window } from '../layouts';

export const ChemSplitter = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    straight,
    side,
    max_transfer,
  } = data;
  return (
    <Window
      width={220}
      height={105}>
      <Window.Content>
        <Section>
          <LabeledList>
            <LabeledList.Item label="Straight">
              <NumberInput
                value={straight}
                unit="u"
                width="55px"
                minValue={1}
                maxValue={max_transfer}
                format={value => toFixed(value, 2)}
                step={0.05}
                stepPixelSize={4}
                onChange={(e, value) => act('set_amount', {
                  target: 'straight',
                  amount: value,
                })} />
            </LabeledList.Item>
            <LabeledList.Item label="Side">
              <NumberInput
                value={side}
                unit="u"
                width="55px"
                minValue={1}
                maxValue={max_transfer}
                format={value => toFixed(value, 2)}
                step={0.05}
                stepPixelSize={4}
                onChange={(e, value) => act('set_amount', {
                  target: 'side',
                  amount: value,
                })} />
            </LabeledList.Item>
          </LabeledList>
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { toFixed } from 'common/math';
import { useBackend } from '../backend';
import { Box, Button, Section } from '../components';
import { Window } from '../layouts';

export const ChemSynthesizer = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    amount,
    current_reagent,
    chemicals = [],
    possible_amounts = [],
  } = data;
  return (
    <Window
      width={300}
      height={375}>
      <Window.Content>
        <Section>
          <Box>
            {possible_amounts.map(possible_amount => (
              <Button
                icon="plus"
                key={toFixed(possible_amount, 0)}
                content={toFixed(possible_amount, 0)}
                selected={possible_amount === amount}
                onClick={() => act('amount', {
                  target: possible_amount,
                })} />
            ))}
          </Box>
          <Box mt={1}>
            {chemicals.map(chemical => (
              <Button
                key={chemical.id}
                icon="tint"
                content={chemical.title}
                width="129px"
                selected={chemical.id === current_reagent}
                onClick={() => act('select', {
                  reagent: chemical.id,
                })} />
            ))}
          </Box>
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { BooleanLike } from "common/react";
import { useBackend } from "../backend";
import { Button, Table } from "../components";
import { Window } from "../layouts";

type CircuitAdminPanelData = {
  circuits: {
    ref: string;
    name: string;
    creator: string;
    has_inserter: BooleanLike;
  }[]
}

export const CircuitAdminPanel = (props, context) => {
  const { act, data } = useBackend<CircuitAdminPanelData>(context);

  return (
    <Window title="Circuit Admin Panel" width={1200} height={500} resizable>
      <Window.Content>
        <Table>
          <Table.Row header>
            <Table.Cell>
              Circuit name
            </Table.Cell>

            <Table.Cell>
              Creator
            </Table.Cell>

            <Table.Cell>
              Actions
            </Table.Cell>
          </Table.Row>

          {data.circuits.map(circuit => {
            const createAct = (action: string) => () => {
              act(action, { circuit: circuit.ref });
            };

            return (
              <Table.Row key={circuit.ref}>
                <Table.Cell>
                  {circuit.name}
                </Table.Cell>

                <Table.Cell>
                  {circuit.creator}
                </Table.Cell>

                <Table.Cell>
                  <Button onClick={createAct("follow_circuit")}>
                    Follow
                  </Button>

                  <Button onClick={createAct("open_circuit")}>
                    Open
                  </Button>

                  <Button onClick={createAct("vv_circuit")}>
                    VV
                  </Button>

                  <Button onClick={createAct("save_circuit")}>
                    Save
                  </Button>

                  <Button onClick={createAct("duplicate_circuit")}>
                    Duplicate
                  </Button>

                  {!!circuit.has_inserter && (
                    <Button onClick={createAct("open_player_panel")}>
                      Player Panel
                    </Button>
                  )}
                </Table.Cell>
              </Table.Row>
            );
          })}
        </Table>
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from "../backend";
import { Stack, Section, Input, Button, Dropdown } from "../components";
import { Window } from "../layouts";

export const CircuitModule = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    input_ports,
    output_ports,
    global_port_types,
  } = data;
  return (
    <Window width={600} height={300}>
      <Window.Content scrollable>
        <Stack vertical>
          <Stack.Item>
            <Button
              content="View Internal Circuit"
              textAlign="center"
              fluid
              onClick={() => act("open_internal_circuit")}
            />
          </Stack.Item>
          <Stack.Item>
            <Stack width="100%">
              <Stack.Item basis="50%">

                  <Stack vertical>
                    {input_ports.map((val, index) => (
                      <PortEntry
                        key={index}
                        name={val.name}
                        datatype={val.type}
                        datatypeOptions={global_port_types}
                        onRemove={() => act("remove_input_port", {
                          port_id: index+1,
                        })}
                        onSetType={type => act("set_port_type", {
                          port_id: index+1,
                          is_input: true,
                          port_type: type,
                        })}
                        onEnter={(e, value) => act("set_port_name", {
                          port_id: index+1,
                          is_input: true,
                          port_name: value,
                        })}
                      />
                    ))}
                    <Stack.Item>
                      <Button
                        fluid
                        content="Add Input Port"
                        color="good"
                        icon="plus"
                        onClick={() => act("add_input_port")}
                      />
                    </Stack.Item>
                  </Stack>

              </Stack.Item>
              <Stack.Item basis="50%">

                  <Stack vertical>
                    {output_ports.map((val, index) => (
                      <PortEntry
                        key={index}
                        name={val.name}
                        datatype={val.type}
                        datatypeOptions={global_port_types}
                        onRemove={() => act("remove_output_port", {
                          port_id: index+1,
                        })}
                        onSetType={type => act("set_port_type", {
                          port_id: index+1,
                          is_input: false,
                          port_type: type,
                        })}
                        onEnter={(e, value) => act("set_port_name", {
                          port_id: index+1,
                          is_input: false,
                          port_name: value,
                        })}
                      />
                    ))}
                    <Stack.Item>
                      <Button
                        fluid
                        content="Add Output Port"
                        color="good"
                        icon="plus"
                        onClick={() => act("add_output_port")}
                      />
                    </Stack.Item>
                  </Stack>

              </Stack.Item>
            </Stack>
          </Stack.Item>
        </Stack>
      </Window.Content>
    </Window>
  );
};

const PortEntry = (props, context) => {
  const {
    onRemove,
    onEnter,
    onSetType,
    name,
    datatype,
    datatypeOptions = [],
    ...rest
  } = props;

  return (
    <Stack.Item {...rest}>
      <Stack>
        <Stack.Item grow>
          <Input
            placeholder="Name"
            value={name}
            onChange={onEnter}
            fluid
          />
        </Stack.Item>
        <Stack.Item>
          <Dropdown
            displayText={datatype}
            options={datatypeOptions}
            onSelected={onSetType}
          />
        </Stack.Item>
        <Stack.Item>
          <Button
            icon="times"
            color="red"
            onClick={onRemove}
          />
        </Stack.Item>
      </Stack>
    </Stack.Item>
  );
};


code:
import { Component } from "inferno";
import { useBackend } from "../backend";
import { Box, Stack, Section, Input, Button, Dropdown } from "../components";
import { Window } from "../layouts";

type Response = {
  name: string;
  bitflag: number;
}

type Parameter = {
  name: string;
  datatype: string;
}

type CircuitSignalHandlerState = {
  signal_id: string;
  responseList: Response[];
  parameterList: Parameter[];
  global: Boolean;
}

type CircuitSignalHandlerData ={
  global_port_types: string[];
}

type BitflagToString = {
  [key: number]: string;
}

export class CircuitSignalHandler
  extends Component<{}, CircuitSignalHandlerState> {
  bitflags: BitflagToString;

  constructor(props) {
    super(props);
    this.state = {
      signal_id: "signal_id",
      responseList: [],
      parameterList: [],
      global: false,
    };

    this.bitflags = {};

    for (let i = 0; i < 24; i++) {
      this.bitflags[1 << i] = `Flag ${i+1}`;
    }
  }

  render() {
    const { act, data } = useBackend<CircuitSignalHandlerData>(this.context);
    const { responseList, parameterList, signal_id, global }
      = this.state as CircuitSignalHandlerState;
    const {
      global_port_types,
    } = data;
    return (
      <Window width={600} height={300}>
        <Window.Content>
          <Stack vertical fill>
            <Stack.Item>
              <Stack fill>
                <Stack.Item grow>
                  <Input
                    placeholder="Signal ID"
                    value={signal_id}
                    fluid
                    onChange={(e, value) => this.setState({ signal_id: value })}
                  />
                </Stack.Item>
                <Stack.Item>
                  <Button.Checkbox
                    checked={global}
                    content="Global"
                    onClick={(e) => this.setState({ global: !global })}
                  />
                </Stack.Item>
              </Stack>
            </Stack.Item>
            <Stack.Item grow>
              <Stack fill>
                <Stack.Item grow={1} basis={0}>

                    <Stack vertical>
                      {responseList.map((val, index) => (
                        <Entry
                          key={index}
                          name={val.name}
                          current_option={this.bitflags[val.bitflag]}
                          onRemove={() => {
                            responseList.splice(index, 1);
                            this.setState({ parameterList });
                          }}
                          onEnter={(e, value) => {
                            const param = responseList[index];
                            param.name = value;
                            this.setState({ parameterList });
                          }}
                        />
                      ))}
                      <Stack.Item>
                        <Button
                          fluid
                          content="Add Response"
                          color="good"
                          icon="plus"
                          onClick={() => {
                            // Object.keys returns strings here, even though we
                            // have a number->key assoc array here, so we have
                            // to explicitly cast it to a number[] type.
                            const bitflag_keys = Object.keys(
                              this.bitflags
                            ) as unknown as number[];
                            responseList.push({
                              name: "Response",
                              bitflag: bitflag_keys[responseList.length],
                            });
                            this.setState({ parameterList });
                          }}
                        />
                      </Stack.Item>
                    </Stack>

                </Stack.Item>
                <Stack.Item grow={1} basis={0}>

                    <Stack vertical>
                      {parameterList.map((val, index) => (
                        <Entry
                          key={index}
                          name={val.name}
                          current_option={val.datatype}
                          options={global_port_types}
                          onRemove={() => {
                            parameterList.splice(index, 1);
                            this.setState({ parameterList });
                          }}
                          onSetOption={type => {
                            const param = parameterList[index];
                            param.datatype = type;
                            this.setState({ parameterList });
                          }}
                          onEnter={(e, value) => {
                            const param = parameterList[index];
                            param.name = value;
                            this.setState({ parameterList });
                          }}
                        />
                      ))}
                      <Stack.Item>
                        <Button
                          fluid
                          content="Add Parameter"
                          color="good"
                          icon="plus"
                          onClick={() => {
                            parameterList.push({
                              name: "Parameter",
                              datatype: global_port_types[0],
                            });
                            this.setState({ parameterList });
                          }}
                        />
                      </Stack.Item>
                    </Stack>

                </Stack.Item>
              </Stack>
            </Stack.Item>
            <Stack.Item>
              <Button
                content="Submit"
                textAlign="center"
                fluid
                onClick={() => act("add_new_id", {
                  signal_id: signal_id,
                  responses: responseList,
                  parameters: parameterList,
                  global: global,
                })}
              />
            </Stack.Item>
          </Stack>
        </Window.Content>
      </Window>
    );
  }
}

type EntryProps = {
  onRemove: (e: MouseEvent) => any;
  onEnter: (e: MouseEvent, value: string) => any;
  onSetOption?: (type: string) => any;
  name: string;
  current_option: string;
  options?: string[];
}

const Entry = (props: EntryProps, context) => {
  const {
    onRemove,
    onEnter,
    onSetOption,
    name,
    current_option,
    options = [],
    ...rest
  } = props;

  return (
    <Stack.Item {...rest}>
      <Stack>
        <Stack.Item grow>
          <Input
            placeholder="Name"
            value={name}
            onChange={onEnter}
            fluid
          />
        </Stack.Item>
        <Stack.Item>
          {options.length && (
            <Dropdown
              displayText={current_option}
              options={options}
              onSelected={onSetOption}
            />
          ) || (
            <Box
              textAlign="center"
              py="2px"
              px={2}
            >
              {current_option}
            </Box>
          )}
        </Stack.Item>
        <Stack.Item>
          <Button
            icon="times"
            color="red"
            onClick={onRemove}
          />
        </Stack.Item>
      </Stack>
    </Stack.Item>
  );
};


code:
import { useBackend } from '../backend';
import { Box, Button, Flex, LabeledList, NoticeBox, Section } from '../components';
import { Window } from '../layouts';

export const CivCargoHoldTerminal = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    pad,
    sending,
    status_report,
    id_inserted,
    id_bounty_info,
    picking,
  } = data;
  const in_text = "Welcome valued employee.";
  const out_text = "To begin, insert your ID into the console.";
  return (
    <Window
      width={500}
      height={375}>
      <Window.Content scrollable>
        <Flex>
          <Flex.Item>
            <NoticeBox
              color={!id_inserted ? 'default': 'blue'}>
              {id_inserted ? in_text : out_text}
            </NoticeBox>
            <Section
              title="Cargo Pad"
              buttons={(
                <>
                  <Button
                    icon={"sync"}
                    tooltip={"Check Contents"}
                    disabled={!pad || !id_inserted}
                    onClick={() => act('recalc')} />
                  <Button
                    icon={sending ? 'times' : 'arrow-up'}
                    tooltip={sending ? "Stop Sending" : "Send Goods"}
                    selected={sending}
                    disabled={!pad || !id_inserted}
                    onClick={() => act(sending ? 'stop' : 'send')} />
                  <Button
                    icon={id_bounty_info ? 'recycle' : 'pen'}
                    color={id_bounty_info ? 'green' : 'default'}
                    tooltip={id_bounty_info ? "Replace Bounty" : "New Bounty"}
                    disabled={!id_inserted}
                    onClick={() => act('bounty')} />
                  <Button
                    icon={'download'}
                    content={"Eject ID"}
                    disabled={!id_inserted}
                    onClick={() => act('eject')} />
                </>
              )}>
              <LabeledList>
                <LabeledList.Item
                  label="Status"
                  color={pad ? "good" : "bad"}>
                  {pad ? "Online" : "Not Found"}
                </LabeledList.Item>
                <LabeledList.Item label="Cargo Report">
                  {status_report}
                </LabeledList.Item>
              </LabeledList>
            </Section>
            {picking ? <BountyPickBox /> : <BountyTextBox />}
          </Flex.Item>
        </Flex>
      </Window.Content>
    </Window>
  );
};

const BountyTextBox = (props, context) => {
  const { data } = useBackend(context);
  const {
    id_bounty_info,
    id_bounty_value,
    id_bounty_num,
  } = data;
  const na_text = "N/A, please add a new bounty.";
  return (
    <Section title="Bounty Info">
      <LabeledList>
        <LabeledList.Item label="Description">
          {id_bounty_info ? id_bounty_info : na_text}
        </LabeledList.Item>
        <LabeledList.Item label="Quantity">
          {id_bounty_info ? id_bounty_num : "N/A"}
        </LabeledList.Item>
        <LabeledList.Item label="Value">
          {id_bounty_info ? id_bounty_value : "N/A"}
        </LabeledList.Item>
      </LabeledList>
    </Section>
  );
};

const BountyPickBox = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    id_bounty_names,
    id_bounty_values,
  } = data;
  return (
    <Section
      title="Please Select a Bounty:"
      textAlign="center">
      <Flex width="100%" wrap>
        <Flex.Item
          shrink={0}
          grow={0.5}>
          <Button
            fluid
            icon="check"
            color="green"
            content={id_bounty_names[0]}
            onClick={() => act('pick', { 'value': 1 })}>
            <Box fontSize="14px">
              Payout: {id_bounty_values[0]}
            </Box>
          </Button>
        </Flex.Item>
        <Flex.Item
          shrink={0}
          grow={0.5}
          px={1}>
          <Button
            fluid
            icon="check"
            color="green"
            content={id_bounty_names[1]}
            onClick={() => act('pick', { 'value': 2 })}>
            <Box fontSize="14px">
              Payout: {id_bounty_values[1]}
            </Box>
          </Button>
        </Flex.Item>
        <Flex.Item
          shrink={0}
          grow={0.5}>
          <Button
            fluid
            icon="check"
            color="green"
            content={id_bounty_names[2]}
            onClick={() => act('pick', { 'value': 3 })}>
            <Box fontSize="14px">
              Payout: {id_bounty_values[2]}
            </Box>
          </Button>
        </Flex.Item>
      </Flex>
    </Section>
  );
};


code:
import { useBackend } from "../backend";
import {
  Box,
  Button,
  Divider,
  LabeledList,
  Flex,
  Section,
} from "../components";
import { Window } from "../layouts";

export const Clipboard = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    pen,
    integrated_pen,
    top_paper,
    top_paper_ref,
    paper,
    paper_ref,
  } = data;
  return (
    <Window title="Clipboard" width={400} height={500}>
      <Window.Content backgroundColor="#704D25" scrollable>

          {pen ? (
            <LabeledList>
              <LabeledList.Item
                label="Pen"
                buttons={
                  <Button icon="eject" onClick={() => act("remove_pen")} />
                }
              >
                {pen}
              </LabeledList.Item>
            </LabeledList>
          ) : (integrated_pen ? (
            <Box color="white" align="center">
              There is a pen integrated into the clipboard's clip.
            </Box>
          ) : (
            <Box color="white" align="center">
              No pen attached!
            </Box>
          ))}

        <Divider />
        {top_paper ? (
          <Flex
            color="black"
            backgroundColor="white"
            style={{ padding: "2px 2px 0 2px" }}
          >
            <Flex.Item align="center" grow={1}>
              <Box align="center">{top_paper}</Box>
            </Flex.Item>
            <Flex.Item>
              <Button
                icon={pen ? "pen" : "eye"}
                onClick={() => act("edit_paper", { ref: top_paper_ref })}
              />
              <Button
                icon="tag"
                onClick={() => act("rename_paper", { ref: top_paper_ref })}
              />
              <Button
                icon="eject"
                onClick={() => act("remove_paper", { ref: top_paper_ref })}
              />
            </Flex.Item>
          </Flex>
        ) : (

            <Box color="white" align="center">
              The clipboard is empty!
            </Box>

        )}
        {paper.length > 0 && <Divider />}
        {paper.map((paper_item, index) => (
          <Flex
            key={paper_ref[index]}
            color="black"
            backgroundColor="white"
            style={{ padding: "2px 2px 0 2px" }}
            mb={0.5}
          >
            <Flex.Item>
              <Button
                icon="chevron-up"
                color="transparent"
                iconColor="black"
                onClick={() => act("move_top_paper", { ref: paper_ref[index] })}
              />
            </Flex.Item>
            <Flex.Item align="center" grow={1}>
              <Box align="center">{paper_item}</Box>
            </Flex.Item>
            <Flex.Item>
              <Button
                icon={pen ? "pen" : "eye"}
                onClick={() => act("edit_paper", { ref: paper_ref[index] })}
              />
              <Button
                icon="tag"
                onClick={() => act("rename_paper", { ref: paper_ref[index] })}
              />
              <Button
                icon="eject"
                onClick={() => act("remove_paper", { ref: paper_ref[index] })}
              />
            </Flex.Item>
          </Flex>
        ))}
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Button, LabeledList, Section } from '../components';
import { Window } from '../layouts';

const PREFIXES = [
  "Dark",
  "Hellish",
  "Fallen",
  "Fiery",
  "Sinful",
  "Blood",
  "Fluffy",
];

const TITLES = [
  "Lord",
  "Prelate",
  "Count",
  "Viscount",
  "Vizier",
  "Elder",
  "Adept",
];

const NAMES = [
  "hal",
  "ve",
  "odr",
  "neit",
  "ci",
  "quon",
  "mya",
  "folth",
  "wren",
  "geyr",
  "hil",
  "niet",
  "twou",
  "phi",
  "coa",
];

const SUFFIXES = [
  "the Red",
  "the Soulless",
  "the Master",
  "the Lord of all things",
  "Jr.",
];

// TODO: refactor the backend of this it's a trainwreck
export const CodexGigas = (props, context) => {
  const { act, data } = useBackend(context);
  return (
    <Window
      width={450}
      height={450}>
      <Window.Content>
        <Section>
          {data.name}
          <LabeledList>
            <LabeledList.Item label="Prefix">
              {PREFIXES.map(prefix => (
                <Button
                  key={prefix.toLowerCase()}
                  content={prefix}
                  disabled={data.currentSection !== 1}
                  onClick={() => act(prefix + ' ')} />
              ))}
            </LabeledList.Item>
            <LabeledList.Item label="Title">
              {TITLES.map(title => (
                <Button
                  key={title.toLowerCase()}
                  content={title}
                  disabled={data.currentSection > 2}
                  onClick={() => act(title + ' ')} />
              ))}
            </LabeledList.Item>
            <LabeledList.Item label="Name">
              {NAMES.map(name => (
                <Button
                  key={name.toLowerCase()}
                  content={name}
                  disabled={data.currentSection > 4}
                  onClick={() => act(name)} />
              ))}
            </LabeledList.Item>
            <LabeledList.Item label="Suffix">
              {SUFFIXES.map(suffix => (
                <Button
                  key={suffix.toLowerCase()}
                  content={suffix}
                  disabled={data.currentSection !== 4}
                  onClick={() => act(' ' + suffix)} />
              ))}
            </LabeledList.Item>
            <LabeledList.Item label="Submit">
              <Button
                content="Search"
                disabled={data.currentSection < 4}
                onClick={() => act('search')} />
            </LabeledList.Item>
          </LabeledList>
        </Section>
      </Window.Content>
    </Window>
  );
};


code:
import { useBackend } from '../backend';
import { Button, Dropdown, Input, Section, Stack, TextArea } from '../components';
import { Window } from '../layouts';

export const CommandReport = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    command_name,
    custom_name,
    command_name_presets = [],
    command_report_content,
    played_sound,
    announcer_sounds = [],
    announce_contents,
  } = data;
  return (
    <Window
      title="Create Command Report"
      width={325}
      height={525}
      theme="admin">
      <Window.Content>
        <Stack vertical>
          <Stack.Item>

              <Dropdown
                width="100%"
                selected={command_name}
                options={command_name_presets}
                onSelected={value => act('update_command_name', {
                  updated_name: value,
                })} />
              {!!custom_name && (
                <Input
                  width="100%"
                  mt={1}
                  value={command_name}
                  placeholder={command_name}
                  onChange={(e, value) => act("update_command_name", {
                    updated_name: value,
                  })} />
              )}

          </Stack.Item>
          <Stack.Item>

              <Dropdown
                width="100%"
                displayText={played_sound}
                options={announcer_sounds}
                onSelected={value => act('set_report_sound', {
                  picked_sound: value,
                })} />

          </Stack.Item>
          <Stack.Item>

              <TextArea
                height="200px"
                mb={1}
                value={command_report_content}
                onChange={(e, value) => act("update_report_contents", {
                  updated_contents: value,
                })} />
              <Stack vertical>
                <Stack.Item>
                  <Button.Checkbox
                    fluid
                    checked={announce_contents}
                    onClick={() => act("toggle_announce")}>
                    Announce Contents
                  </Button.Checkbox>
                </Stack.Item>
                <Stack.Item>
                  <Button.Confirm
                    fluid
                    icon="check"
                    color="good"
                    textAlign="center"
                    content="Submit Report"
                    onClick={() => act("submit_report")} />
                </Stack.Item>
              </Stack>

          </Stack.Item>
        </Stack>
      </Window.Content>
    </Window>
  );
};


code:
import { sortBy } from "common/collections";
import { capitalize } from "common/string";
import { useBackend, useLocalState } from "../backend";
import { Blink, Box, Button, Dimmer, Flex, Icon, Input, Modal, Section, TextArea } from "../components";
import { Window } from "../layouts";
import { sanitizeText } from "../sanitize";

const STATE_BUYING_SHUTTLE = "buying_shuttle";
const STATE_CHANGING_STATUS = "changing_status";
const STATE_MAIN = "main";
const STATE_MESSAGES = "messages";

// Used for whether or not you need to swipe to confirm an alert level change
const SWIPE_NEEDED = "SWIPE_NEEDED";

const EMAG_SHUTTLE_NOTICE
  = "This shuttle is deemed significantly dangerous to the crew, and is only supplied by the Syndicate.";

const sortShuttles = sortBy(
  shuttle => !shuttle.emagOnly,
  shuttle => shuttle.creditCost
);

const AlertButton = (props, context) => {
  const { act, data } = useBackend(context);
  const { alertLevelTick, canSetAlertLevel } = data;
  const { alertLevel, setShowAlertLevelConfirm } = props;

  const thisIsCurrent = data.alertLevel === alertLevel;

  return (
    <Button
      icon="exclamation-triangle"
      color={thisIsCurrent && "good"}
      content={capitalize(alertLevel)}
      onClick={() => {
        if (thisIsCurrent) {
          return;
        }

        if (canSetAlertLevel === SWIPE_NEEDED) {
          setShowAlertLevelConfirm([alertLevel, alertLevelTick]);
        } else {
          act("changeSecurityLevel", {
            newSecurityLevel: alertLevel,
          });
        }
      }}
    />
  );
};

const MessageModal = (props, context) => {
  const { data } = useBackend(context);
  const { maxMessageLength } = data;

  const [input, setInput] = useLocalState(context, props.label, "");

  const longEnough = props.minLength === undefined
    || input.length >= props.minLength;

  return (
    <Modal>
      <Flex direction="column">
        <Flex.Item fontSize="16px" maxWidth="90vw" mb={1}>
          {props.label}:
        </Flex.Item>

        <Flex.Item mr={2} mb={1}>
          <TextArea
            fluid
            height="20vh"
            width="80vw"
            backgroundColor="black"
            textColor="white"
            onInput={(_, value) => {
              setInput(value.substring(0, maxMessageLength));
            }}
            value={input}
          />
        </Flex.Item>

        <Flex.Item>
          <Button
            icon={props.icon}
            content={props.buttonText}
            color="good"
            disabled={!longEnough}
            tooltip={!longEnough ? "You need a longer reason." : ""}
            tooltipPosition="right"
            onClick={() => {
              if (longEnough) {
                setInput("");
                props.onSubmit(input);
              }
            }}
          />

          <Button
            icon="times"
            content="Cancel"
            color="bad"
            onClick={props.onBack}
          />
        </Flex.Item>

        {!!props.notice && (
          <Flex.Item maxWidth="90vw">{props.notice}</Flex.Item>
        )}
      </Flex>
    </Modal>
  );
};

const NoConnectionModal = () => {
  return (
    <Dimmer>
      <Flex direction="column" textAlign="center" width="300px">
        <Flex.Item>
          <Icon
            color="red"
            name="wifi"
            size={10}
          />

          <Blink>

          </Blink>
        </Flex.Item>

        <Flex.Item fontSize="16px">
          A connection to the station cannot be established.
        </Flex.Item>
      </Flex>
    </Dimmer>
  );
};

const PageBuyingShuttle = (props, context) => {
  const { act, data } = useBackend(context);

  return (
    <Box>

        <Button
          icon="chevron-left"
          content="Back"
          onClick={() => act("setState", { state: STATE_MAIN })}
        />

        Budget: {data.budget.toLocaleString()} credits

      {sortShuttles(data.shuttles).map(shuttle => (
        <Section
          title={(

              {shuttle.name}

          )}
          key={shuttle.ref}
          buttons={(
            <Button
              content={`${shuttle.creditCost.toLocaleString()} credits`}
              color={shuttle.emagOnly ? "red" : "default"}
              disabled={data.budget < shuttle.creditCost}
              onClick={() => act("purchaseShuttle", {
                shuttle: shuttle.ref,
              })}
              tooltip={
                data.budget < shuttle.creditCost
                  ? `You need ${shuttle.creditCost - data.budget} more credits.`
                  : (shuttle.emagOnly ? EMAG_SHUTTLE_NOTICE : undefined)
              }
              tooltipPosition="left"
            />
          )}>
          <Box>{shuttle.description}</Box>
          {
            shuttle.prerequisites
              ? Prerequisites: {shuttle.prerequisites}
              : null
          }

      ))}
    </Box>
  );
};

const PageChangingStatus = (props, context) => {
  const { act, data } = useBackend(context);
  const { maxStatusLineLength } = data;

  const [lineOne, setLineOne] = useLocalState(context, "lineOne", data.lineOne);
  const [lineTwo, setLineTwo] = useLocalState(context, "lineTwo", data.lineTwo);

  return (
    <Box>

        <Button
          icon="chevron-left"
          content="Back"
          onClick={() => act("setState", { state: STATE_MAIN })}
        />

        <Flex direction="column">
          <Flex.Item>
            <Button
              icon="times"
              content="Clear Alert"
              color="bad"
              onClick={() => act("setStatusPicture", { picture: "blank" })}
            />
          </Flex.Item>

          <Flex.Item mt={1}>
            <Button
              icon="check-square-o"
              content="Default"
              onClick={() => act("setStatusPicture", { picture: "default" })}
            />

            <Button
              icon="bell-o"
              content="Red Alert"
              onClick={() => act("setStatusPicture", { picture: "redalert" })}
            />

            <Button
              icon="exclamation-triangle"
              content="Lockdown"
              onClick={() => act("setStatusPicture", { picture: "lockdown" })}
            />

            <Button
              icon="exclamation-circle"
              content="Biohazard"
              onClick={() => act("setStatusPicture", { picture: "biohazard" })}
            />

            <Button
              icon="space-shuttle"
              content="Shuttle ETA"
              onClick={() => act("setStatusPicture", { picture: "shuttle" })}
            />
          </Flex.Item>
        </Flex>

        <Flex direction="column">
          <Flex.Item mb={1}>
            <Input
              maxLength={maxStatusLineLength}
              value={lineOne}
              width="200px"
              onChange={(_, value) => setLineOne(value)}
            />
          </Flex.Item>

          <Flex.Item mb={1}>
            <Input
              maxLength={maxStatusLineLength}
              value={lineTwo}
              width="200px"
              onChange={(_, value) => setLineTwo(value)}
            />
          </Flex.Item>

          <Flex.Item>
            <Button
              icon="comment-o"
              content="Message"
              onClick={() => act("setStatusMessage", {
                lineOne,
                lineTwo,
              })}
            />
          </Flex.Item>
        </Flex>

    </Box>
  );
};

const PageMain = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    alertLevel,
    alertLevelTick,
    aprilFools,
    callShuttleReasonMinLength,
    canBuyShuttles,
    canMakeAnnouncement,
    canMessageAssociates,
    canRecallShuttles,
    canRequestNuke,
    canSendToSectors,
    canSetAlertLevel,
    canToggleEmergencyAccess,
    emagged,
    emergencyAccess,
    importantActionReady,
    sectors,
    shuttleCalled,
    shuttleCalledPreviously,
    shuttleCanEvacOrFailReason,
    shuttleLastCalled,
    shuttleRecallable,
  } = data;

  const [callingShuttle, setCallingShuttle] = useLocalState(
    context, "calling_shuttle", false);
  const [messagingAssociates, setMessagingAssociates] = useLocalState(
    context, "messaging_associates", false);
  const [messagingSector, setMessagingSector] = useLocalState(
    context, "messaing_sector", null);
  const [requestingNukeCodes, setRequestingNukeCodes] = useLocalState(
    context, "requesting_nuke_codes", false);

  const [
    [showAlertLevelConfirm, confirmingAlertLevelTick],
    setShowAlertLevelConfirm,
  ] = useLocalState(context, "showConfirmPrompt", [null, null]);

  return (
    <Box>

        {shuttleCalled && (
          <Button.Confirm
            icon="space-shuttle"
            content="Recall Emergency Shuttle"
            color="bad"
            disabled={!canRecallShuttles || !shuttleRecallable}
            tooltip={(
              canRecallShuttles && (
                !shuttleRecallable && "It's too late for the emergency shuttle to be recalled."
              ) || (
                "You do not have permission to recall the emergency shuttle."
              )
            )}
            tooltipPosition="bottom-end"
            onClick={() => act("recallShuttle")}
          />
        ) || (
          <Button
            icon="space-shuttle"
            content="Call Emergency Shuttle"
            disabled={shuttleCanEvacOrFailReason !== 1}
            tooltip={
              shuttleCanEvacOrFailReason !== 1
                ? shuttleCanEvacOrFailReason
                : undefined
            }
            tooltipPosition="bottom-end"
            onClick={() => setCallingShuttle(true)}
          />
        )}
        {!!shuttleCalledPreviously && (
          shuttleLastCalled && (
            <Box>
              Most recent shuttle call/recall traced to:
              {" "}{shuttleLastCalled}
            </Box>
          ) || (
            <Box>Unable to trace most recent shuttle/recall signal.</Box>
          )
        )}

      {!!canSetAlertLevel && (

          <Flex justify="space-between">
            <Flex.Item>
              <Box>
                Currently on {capitalize(alertLevel)} Alert
              </Box>
            </Flex.Item>

            <Flex.Item>
              <AlertButton
                alertLevel="green"
                showAlertLevelConfirm={showAlertLevelConfirm}
                setShowAlertLevelConfirm={setShowAlertLevelConfirm}
              />

              <AlertButton
                alertLevel="blue"
                showAlertLevelConfirm={showAlertLevelConfirm}
                setShowAlertLevelConfirm={setShowAlertLevelConfirm}
              />
            </Flex.Item>
          </Flex>

      )}

        <Flex
          direction="column">
          {!!canMakeAnnouncement && <Button
            icon="bullhorn"
            content="Make Priority Announcement"
            onClick={() => act("makePriorityAnnouncement")}
          />}

          {!!aprilFools && !!canMakeAnnouncement && <Button
            icon="bullhorn"
            content="Call Emergency Meeting"
            onClick={() => act("emergency_meeting")}
          />}

          {!!canToggleEmergencyAccess && <Button.Confirm
            icon="id-card-o"
            content={`${emergencyAccess ? "Disable" : "Enable"} Emergency Maintenance Access`}
            color={emergencyAccess ? "bad" : undefined}
            onClick={() => act("toggleEmergencyAccess")}
          />}

          <Button
            icon="desktop"
            content="Set Status Display"
            onClick={() => act("setState", { state: STATE_CHANGING_STATUS })}
          />

          <Button
            icon="envelope-o"
            content="Message List"
            onClick={() => act("setState", { state: STATE_MESSAGES })}
          />

          {(canBuyShuttles !== 0) && <Button
            icon="shopping-cart"
            content="Purchase Shuttle"
            disabled={canBuyShuttles !== 1}
            // canBuyShuttles is a string detailing the fail reason
            // if one can be given
            tooltip={canBuyShuttles !== 1 ? canBuyShuttles : undefined}
            tooltipPosition="right"
            onClick={() => act("setState", { state: STATE_BUYING_SHUTTLE })}
          />}

          {!!canMessageAssociates && <Button
            icon="comment-o"
            content={`Send message to ${emagged ? "[UNKNOWN]" : "CentCom"}`}
            disabled={!importantActionReady}
            onClick={() => setMessagingAssociates(true)}
          />}

          {!!canRequestNuke && <Button
            icon="radiation"
            content="Request Nuclear Authentication Codes"
            disabled={!importantActionReady}
            onClick={() => setRequestingNukeCodes(true)}
          />}

          {!!emagged && <Button
            icon="undo"
            content="Restore Backup Routing Data"
            onClick={() => act("restoreBackupRoutingData")}
          />}
        </Flex>

      {!!canMessageAssociates && messagingAssociates && <MessageModal
        label={`Message to transmit to ${emagged ? "[ABNORMAL ROUTING COORDINATES]" : "CentCom"} via quantum entanglement`}
        notice="Please be aware that this process is very expensive, and abuse will lead to...termination. Transmission does not guarantee a response."
        icon="bullhorn"
        buttonText="Send"
        onBack={() => setMessagingAssociates(false)}
        onSubmit={message => {
          setMessagingAssociates(false);
          act("messageAssociates", {
            message,
          });
        }}
      />}

      {!!canRequestNuke && requestingNukeCodes && <MessageModal
        label="Reason for requesting nuclear self-destruct codes"
        notice="Misuse of the nuclear request system will not be tolerated under any circumstances. Transmission does not guarantee a response."
        icon="bomb"
        buttonText="Request Codes"
        onBack={() => setRequestingNukeCodes(false)}
        onSubmit={reason => {
          setRequestingNukeCodes(false);
          act("requestNukeCodes", {
            reason,
          });
        }}
      />}

      {!!callingShuttle && <MessageModal
        label="Nature of emergency"
        icon="space-shuttle"
        buttonText="Call Shuttle"
        minLength={callShuttleReasonMinLength}
        onBack={() => setCallingShuttle(false)}
        onSubmit={reason => {
          setCallingShuttle(false);
          act("callShuttle", {
            reason,
          });
        }}
      />}

      {
        !!canSetAlertLevel
        && showAlertLevelConfirm
        && confirmingAlertLevelTick === alertLevelTick
        && (
          <Modal>
            <Flex
              direction="column"
              textAlign="center"
              width="300px">
              <Flex.Item fontSize="16px" mb={2}>
                Swipe ID to confirm change
              </Flex.Item>

              <Flex.Item mr={2} mb={1}>
                <Button
                  icon="id-card-o"
                  content="Swipe ID"
                  color="good"
                  fontSize="16px"
                  onClick={() => act("changeSecurityLevel", {
                    newSecurityLevel: showAlertLevelConfirm,
                  })}
                />

                <Button
                  icon="times"
                  content="Cancel"
                  color="bad"
                  fontSize="16px"
                  onClick={() => setShowAlertLevelConfirm(false)}
                />
              </Flex.Item>
            </Flex>
          </Modal>
        )
      }

      {
        !!canSendToSectors
        && sectors.length > 0
        && (

            <Flex
              direction="column">
              {
                sectors.map(sectorName => (
                  <Flex.Item key={sectorName}>
                    <Button
                      content={
                        `Send a message to station in ${sectorName} sector`
                      }
                      disabled={!importantActionReady}
                      onClick={() => setMessagingSector(sectorName)}
                    />
                  </Flex.Item>
                ))
              }

              {sectors.length > 2 && (
                <Flex.Item>
                  <Button
                    content="Send a message to all allied stations"
                    disabled={!importantActionReady}
                    onClick={() => setMessagingSector("all")}
                  />
                </Flex.Item>
              )}
            </Flex>

        )
      }

      {
        !!canSendToSectors
        && sectors.length > 0
        && messagingSector
        && <MessageModal
          label="Message to send to allied station"
          notice="Please be aware that this process is very expensive, and abuse will lead to...termination."
          icon="bullhorn"
          buttonText="Send"
          onBack={() => setMessagingSector(null)}
          onSubmit={message => {
            act("sendToOtherSector", {
              destination: messagingSector,
              message,
            });

            setMessagingSector(null);
          }}
        />
      }
    </Box>
  );
};

const PageMessages = (props, context) => {
  const { act, data } = useBackend(context);
  const messages = data.messages || [];

  const children = [];

  children.push((

      <Button
        icon="chevron-left"
        content="Back"
        onClick={() => act("setState", { state: STATE_MAIN })}
      />

  ));

  const messageElements = [];

  for (const [messageIndex, message] of Object.entries(messages)) {
    let answers = null;

    if (message.possibleAnswers.length > 0) {
      answers = (
        <Box mt={1}>
          {message.possibleAnswers.map((answer, answerIndex) => (
            <Button
              content={answer}
              color={message.answered === answerIndex + 1 ? "good" : undefined}
              key={answerIndex}
              onClick={message.answered ? undefined : () => act("answerMessage", {
                message: parseInt(messageIndex, 10) + 1,
                answer: answerIndex + 1,
              })}
            />
          ))}
        </Box>
      );
    }

    const textHtml = {
      __html: sanitizeText(message.content),
    };

    messageElements.push((
      <Section
        title={message.title}
        key={messageIndex}
        buttons={(
          <Button.Confirm
            icon="trash"
            content="Delete"
            color="red"
            onClick={() => act("deleteMessage", {
              message: messageIndex + 1,
            })}
          />
        )}>
        <Box
          dangerouslySetInnerHTML={textHtml} />

        {answers}

    ));
  }

  children.push(messageElements.reverse());

  return children;
};

export const CommunicationsConsole = (props, context) => {
  const { act, data } = useBackend(context);
  const {
    authenticated,
    authorizeName,
    canLogOut,
    emagged,
    hasConnection,
    page,
    canRequestSafeCode,
    safeCodeDeliveryWait,
    safeCodeDeliveryArea,
  } = data;

  return (
    <Window
      width={400}
      height={650}
      theme={emagged ? "syndicate" : undefined}>
      <Window.Content scrollable>
        {!hasConnection && <NoConnectionModal />}

        {(canLogOut || !authenticated) && (

            <Button
              icon={authenticated ? "sign-out-alt" : "sign-in-alt"}
              content={authenticated ? `Log Out${authorizeName ? ` (${authorizeName})` : ""}` : "Log In"}
              color={authenticated ? "bad" : "good"}
              onClick={() => act("toggleAuthentication")}
            />

        )}

        {(!!canRequestSafeCode && (

            <Button
              icon="key"
              content="Request Safe Code"
              color="good"
              onClick={() => act("requestSafeCodes")} />

        )) || (!!safeCodeDeliveryWait && (

            {`Drop pod to ${safeCodeDeliveryArea} in \
            ${Math.round(safeCodeDeliveryWait/10)}s`}

        ))}

        {!!authenticated && (
          page === STATE_BUYING_SHUTTLE && <PageBuyingShuttle />
          || page === STATE_CHANGING_STATUS && <PageChangingStatus />
          || page === STATE_MAIN && <PageMain />
          || page === STATE_MESSAGES && <PageMessages />
          || <Box>Page not implemented: {page}</Box>
        )}
      </Window.Content>
    </Window>
  );
};


code:
import { createSearch } from 'common/string';
import { useBackend, useLocalState } from '../backend';
import { Material, MaterialAmount, MaterialFormatting, Materials, MATERIAL_KEYS } from './common/Materials';
import { Window } from '../layouts';
import { Box, Button, Input, Section, Stack, Tabs } from '../components';

const CATEGORY_ALL = "All";

const searchFor = searchText => createSearch(
  searchText,
  ([_, thing]) => thing.name + thing.description,
);

const getCategory = (category: string[]) => {
  return category[0] === "Circuitry" ? category[1] : category[0];
};

type Design = {
  name: string,
  description: string,
  materials: Record<keyof typeof MATERIAL_KEYS, number>,
  categories: string[],
}

type ComponentPrinterData = {
  designs: Record<string, Design>,
  materials: Material[],
};

const canProduce = (
  designMaterials: Design["materials"],
  storedMaterials: Material[],
) => {
  for (const material of storedMaterials) {
    const amountNeeded = designMaterials[material.name];

    if (amountNeeded && amountNeeded > material.amount) {
      return false;
    }
  }

  return true;
};

const MaterialCost = (props: {
  materials: Design["materials"],
}) => {
  return (
    <Stack>
      {Object.entries(props.materials)
        .map(([material, amount]) => {
          return (
            <Stack.Item key={material} mr={1}>
              <MaterialAmount
                name={material as keyof typeof MATERIAL_KEYS}
                amount={amount}
                formatting={MaterialFormatting.Locale}
                style={{
                  transform: 'scale(0.75) translate(0%, 10%)',
                }}
              />
            </Stack.Item>
          );
        })}
    </Stack>
  );
};

export const ComponentPrinter = (props, context) => {
  const { act, data } = useBackend<ComponentPrinterData>(context);

  const [currentCategory, setCurrentCategory] = useLocalState(context, "category", CATEGORY_ALL);
  const [searchText, setSearchText] = useLocalState(context, "searchText", "");

  return (
    <Window title="Component Printer" width={900} height={700}>
      <Window.Content scrollable>
        <Stack vertical>
          <Stack.Item>

              <Materials
                materials={data.materials || []}
                onEject={(ref, amount) => {
                  act("remove_mat", {
                    ref: ref,
                    amount: amount,
                  });
                }}
              />

          </Stack.Item>
          <Stack.Item>
            <Stack>
              <Stack.Item>

                  <Tabs vertical fill>
                    {Object.values(data.designs)
                      .reduce<string[]>((categories, design) => {
                        const category = getCategory(design.categories);
                        if (categories.indexOf(category) === -1) {
                          return [category, ...categories];
                        } else {
                          return categories;
                        }
                      }, [CATEGORY_ALL]).sort().map(category => {
                        return (
                          <Tabs.Tab key={category}
                            onClick={() => setCurrentCategory(category)}
                            selected={category === currentCategory}
                            fluid
                          >
                            {category}
                          </Tabs.Tab>
                        );
                      })}
                  </Tabs>

              </Stack.Item>

              <Stack.Item basis="100%">

                  <Stack vertical>
                    <Stack.Item>
                      <Input
                        placeholder="Search..."
                        autoFocus
                        fluid
                        value={searchText}
                        onInput={(_, value) => setSearchText(value)} />
                    </Stack.Item>

                    {Object.entries(data.designs)
                      .filter(([_, design]) => currentCategory === CATEGORY_ALL
                        || design.categories.indexOf(currentCategory) !== -1)
                      .filter(searchFor(searchText))
                      .map(([designId, design]) => {
                        return (
                          <Stack.Item key={designId}>
                            <Section title={design.name} buttons={(
                              <Button
                                onClick={() => {
                                  act("print", {
                                    designId,
                                  });
                                }}
                                disabled={
                                  !canProduce(design.materials, data.materials)
                                }
                                px={1.5}
                              >
                                Print
                              </Button>
                            )}>
                              <Box inline width="100%">
                                {design.description}
                              </Box>
                              <MaterialCost materials={design.materials} />

                          </Stack.Item>
                        );
                      })}
                  </Stack>

              </Stack.Item>
            </Stack>
          </Stack.Item>
        </Stack>
      </Window.Content>
    </Window>
  );
};