ORM ui qol (#73721)

## About The Pull Request
seperates everything into tabs and allows u to search. ur credits are
displayed on the ui and makes the buttons to print mats similar to
fabricators

![image](https://user-images.githubusercontent.com/95004236/222835992-a4ffa622-b718-4f3b-b8c7-9cbc8355c325.png)


## Why It's Good For The Game
more fun to use the orm

## Changelog
🆑
qol: made ORM easier to use
/🆑
This commit is contained in:
SMOSMOSMOSMOSMO
2023-03-05 13:15:31 -08:00
committed by GitHub
parent c24f82b281
commit 1c91c24dfb
2 changed files with 251 additions and 93 deletions
+49 -10
View File
@@ -213,21 +213,28 @@
/obj/machinery/mineral/ore_redemption/ui_data(mob/user)
var/list/data = list()
data["unclaimedPoints"] = points
data["materials"] = list()
var/datum/component/material_container/mat_container = materials.mat_container
if (mat_container)
for(var/mat in mat_container.materials)
var/datum/material/M = mat
var/amount = mat_container.materials[M]
for(var/datum/material/material as anything in mat_container.materials)
var/amount = mat_container.materials[material]
var/sheet_amount = amount / MINERAL_MATERIAL_AMOUNT
var/ref = REF(M)
data["materials"] += list(list("name" = M.name, "id" = ref, "amount" = sheet_amount, "value" = ore_values[M.type]))
data["materials"] += list(list(
"name" = material.name,
"id" = REF(material),
"amount" = sheet_amount,
"category" = "material",
"value" = ore_values[material.type],
))
data["alloys"] = list()
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
data["alloys"] += list(list("name" = D.name, "id" = D.id, "amount" = can_smelt_alloy(D)))
for(var/research in stored_research.researched_designs)
var/datum/design/alloy = SSresearch.techweb_design_by_id(research)
data["materials"] += list(list(
"name" = alloy.name,
"id" = alloy.id,
"category" = "alloy",
"amount" = can_smelt_alloy(alloy),
))
if (!mat_container)
data["disconnected"] = "local mineral storage is unavailable"
@@ -236,8 +243,40 @@
else if (materials.on_hold())
data["disconnected"] = "mineral withdrawal is on hold"
var/obj/item/card/id/card
if(isliving(user))
var/mob/living/customer = user
card = customer.get_idcard(hand_first = TRUE)
if(card?.registered_account)
data["user"] = list(
"name" = card.registered_account.account_holder,
"cash" = card.registered_account.account_balance,
)
return data
/obj/machinery/mineral/ore_redemption/ui_static_data(mob/user)
var/list/data = list()
var/datum/component/material_container/mat_container = materials.mat_container
if (mat_container)
for(var/datum/material/material as anything in mat_container.materials)
var/obj/material_display = initial(material.sheet_type)
data["material_icons"] += list(list(
"id" = REF(material),
"product_icon" = icon2base64(getFlatIcon(image(icon = initial(material_display.icon), icon_state = initial(material_display.icon_state)), no_anim=TRUE)),
))
for(var/research in stored_research.researched_designs)
var/datum/design/alloy = SSresearch.techweb_design_by_id(research)
var/obj/alloy_display = initial(alloy.build_path)
data["material_icons"] += list(list(
"id" = alloy.id,
"product_icon" = icon2base64(getFlatIcon(image(icon = initial(alloy_display.icon), icon_state = initial(alloy_display.icon_state)), no_anim=TRUE)),
))
return data
/obj/machinery/mineral/ore_redemption/ui_act(action, params)
. = ..()
if(.)
@@ -1,107 +1,226 @@
import { toTitleCase } from 'common/string';
import { useBackend, useLocalState } from '../backend';
import { BlockQuote, Box, Button, NumberInput, Section, Table } from '../components';
import { createSearch, toTitleCase } from 'common/string';
import { useBackend, useLocalState, useSharedState } from '../backend';
import { BlockQuote, Box, Button, Table, Tabs, Input, Stack, Icon, Section, LabeledList } from '../components';
import { Window } from '../layouts';
import { formatSiUnit } from '../format';
export const OreRedemptionMachine = (props, context) => {
const { act, data } = useBackend(context);
const { unclaimedPoints, materials, alloys } = data;
const { unclaimedPoints, materials, user } = data;
const [tab, setTab] = useSharedState(context, 'tab', 1);
const [searchItem, setSearchItem] = useLocalState(context, 'searchItem', '');
const [compact, setCompact] = useSharedState(context, 'compact', false);
const search = createSearch(searchItem, (materials) => materials.name);
const material_filtered =
searchItem.length > 0
? data.materials.filter(search)
: materials.filter((material) => material && material.category === tab);
return (
<Window title="Ore Redemption Machine" width={440} height={550}>
<Window.Content scrollable>
<Section>
<BlockQuote mb={1}>
This machine only accepts ore.
<br />
Gibtonite and Slag are not accepted.
</BlockQuote>
<Box>
<Box inline color="label" mr={1}>
Unclaimed points:
</Box>
{unclaimedPoints}
<Button
ml={2}
content="Claim"
disabled={unclaimedPoints === 0}
onClick={() => act('Claim')}
<Window title="Ore Redemption Machine" width={435} height={500}>
<Window.Content>
<Stack fill vertical>
<Section>
<Stack.Item>
<Section>
<Stack>
<Stack.Item>
<Icon
name="id-card"
size={3}
mr={1}
color={user ? 'green' : 'red'}
/>
</Stack.Item>
<Stack.Item>
{(!user && 'No user Detected') || (
<LabeledList>
<LabeledList.Item label="Name">
{user.name || 'No name detected'}
</LabeledList.Item>
<LabeledList.Item label="Balance">
{user.cash + ' cr' || 'No balance detected'}
</LabeledList.Item>
</LabeledList>
)}
</Stack.Item>
<Stack.Item>
<Button
mt={0.5}
textAlign="center"
color={compact ? 'red' : 'green'}
content="Compact"
onClick={() => setCompact(!compact)}
/>
</Stack.Item>
</Stack>
</Section>
</Stack.Item>
</Section>
<Section>
<Stack.Item>
<Box>
<Icon name="coins" color="gold" />
<Box inline color="label" ml={1}>
Unclaimed points:
</Box>
{unclaimedPoints}
<Button
ml={2}
content="Claim"
disabled={unclaimedPoints === 0}
onClick={() => act('Claim')}
/>
</Box>
</Stack.Item>
</Section>
<Section>
<Stack.Item>
<BlockQuote>
This machine only accepts ore. Gibtonite and Slag are not
accepted.
</BlockQuote>
</Stack.Item>
</Section>
<Tabs>
<Tabs.Tab
icon="list"
lineHeight="23px"
selected={tab === 'material'}
onClick={() => {
setTab('material');
if (searchItem.length > 0) {
setSearchItem('');
}
}}>
Materials
</Tabs.Tab>
<Tabs.Tab
icon="list"
lineHeight="23px"
selected={tab === 'alloy'}
onClick={() => {
setTab('alloy');
if (searchItem.length > 0) {
setSearchItem('');
}
}}>
Alloys
</Tabs.Tab>
<Input
autofocus
position="relative"
left="25%"
bottom="5%"
height="20px"
width="150px"
placeholder="Search Material..."
value={searchItem}
onInput={(e, value) => {
setSearchItem(value);
if (value.length > 0) {
setTab(1);
}
}}
fluid
/>
</Box>
</Section>
<Section title="Materials">
<Table>
{materials.map((material) => (
<MaterialRow
key={material.id}
material={material}
onRelease={(amount) =>
act('Release', {
id: material.id,
sheets: amount,
})
}
/>
))}
</Table>
</Section>
<Section title="Alloys">
<Table>
{alloys.map((material) => (
<MaterialRow
key={material.id}
material={material}
onRelease={(amount) =>
act('Smelt', {
id: material.id,
sheets: amount,
})
}
/>
))}
</Table>
</Section>
</Tabs>
<Stack.Item grow>
<Section fill scrollable>
<Table>
{material_filtered.map((material) => (
<MaterialRow
key={material.id}
material={material}
onRelease={(amount) => {
if (material.category === 'material') {
act('Release', {
id: material.id,
sheets: amount,
});
} else {
act('Smelt', {
id: material.id,
sheets: amount,
});
}
}}
/>
))}
</Table>
</Section>
</Stack.Item>
</Stack>
</Window.Content>
</Window>
);
};
const MaterialRow = (props, context) => {
const { data } = useBackend(context);
const { material_icons } = data;
const { material, onRelease } = props;
const [compact, setCompact] = useLocalState(context, 'compact', false);
const [amount, setAmount] = useLocalState(
context,
'amount' + material.name,
1
const display = material_icons.find(
(mat_icon) => mat_icon.id === material.id
);
const amountAvailable = Math.floor(material.amount);
const print_amount = 5;
const max_sheets = 50;
return (
<Table.Row>
<Table.Cell>{toTitleCase(material.name).replace('Alloy', '')}</Table.Cell>
<Table.Cell collapsing textAlign="right">
<Box mr={2} color="label" inline>
{material.value && material.value + ' cr'}
<Table.Row className="candystripe" collapsing>
{!compact && (
<Table.Cell collapsing>
<Box
as="img"
m={1}
src={`data:image/jpeg;base64,${display.product_icon}`}
height="18px"
width="18px"
style={{
'-ms-interpolation-mode': 'nearest-neighbor',
'vertical-align': 'middle',
}}
/>
</Table.Cell>
)}
<Table.Cell>{toTitleCase(material.name)}</Table.Cell>
<Table.Cell collapsing textAlign="left">
<Box color="label">
{formatSiUnit(material.amount, 0)}{' '}
{material.amount === 1 ? 'sheet' : 'sheets'}
</Box>
</Table.Cell>
<Table.Cell collapsing textAlign="right">
<Box mr={2} color="label" inline>
{amountAvailable} sheets
</Box>
</Table.Cell>
<Table.Cell collapsing>
<NumberInput
width="32px"
step={1}
stepPixelSize={5}
minValue={1}
maxValue={50}
value={amount}
onChange={(e, value) => setAmount(value)}
<Table.Cell collapsing textAlign="left">
<Button
content="x1"
color="transparent"
tooltip={material.value ? material.value + ' cr' : 'No cost'}
onClick={() => onRelease(1)}
/>
<Button
disabled={amountAvailable < 1}
content="Release"
onClick={() => onRelease(amount)}
content={'x' + print_amount}
color="transparent"
tooltip={
material.value ? material.value * print_amount + ' cr' : 'No cost'
}
onClick={() => onRelease(print_amount)}
/>
<Button.Input
content={
'[Max: ' +
(material.amount < max_sheets ? material.amount : max_sheets) +
']'
}
color={'transparent'}
maxValue={max_sheets}
onCommit={(e, value) => {
onRelease(value);
}}
/>
</Table.Cell>
</Table.Row>