mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-24 05:30:05 +01:00
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  ## 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:
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user