Skip to content

Commit

Permalink
[MIRROR] [no gbp] Fixes cargo express console (#2145)
Browse files Browse the repository at this point in the history
* [no gbp] Fixes cargo express console (#82843)

Cargo express console does not send amounts by name

Fixed and touched up the express console a bit
![Screenshot 2024-04-22
195254](https://github.com/tgstation/tgstation/assets/42397676/c099cdc0-6b4d-4348-9b5b-f9d4cc325d0b)
Bug fix (no issue yet)
:cl:
fix: Cargo express console fixed: No more bluescreen
/:cl:

* [no gbp] Fixes cargo express console

---------

Co-authored-by: Jeremiah <[email protected]>
Co-authored-by: Mal <[email protected]>
  • Loading branch information
3 people authored and StealsThePRs committed Apr 23, 2024
1 parent df3285b commit d7089ca
Show file tree
Hide file tree
Showing 2 changed files with 296 additions and 0 deletions.
238 changes: 238 additions & 0 deletions tgui/packages/tgui/interfaces/Cargo/CargoCatalog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
import { sortBy } from 'common/collections';
import { useMemo } from 'react';

import { useBackend, useSharedState } from '../../backend';
import {
Button,
Icon,
Input,
Section,
Stack,
Table,
Tabs,
Tooltip,
} from '../../components';
import { formatMoney } from '../../format';
import { CargoCartButtons } from './CargoButtons';
import { searchForSupplies } from './helpers';
import { CargoData, Supply, SupplyCategory } from './types';

type Props = {
express?: boolean;
};

export function CargoCatalog(props: Props) {
const { express } = props;
const { act, data } = useBackend<CargoData>();
const { self_paid } = data;

const supplies = Object.values(data.supplies);

const [activeSupplyName, setActiveSupplyName] = useSharedState(
'supply',
supplies[0]?.name,
);

const [searchText, setSearchText] = useSharedState('search_text', '');

const packs = useMemo(() => {
let fetched: Supply[] | undefined;

if (activeSupplyName === 'search_results') {
fetched = searchForSupplies(supplies, searchText);
} else {
fetched = supplies.find(
(supply) => supply.name === activeSupplyName,
)?.packs;
}

if (!fetched) return [];

fetched = sortBy(fetched, (pack: Supply) => pack.name);

return fetched;
}, [activeSupplyName, supplies, searchText]);

return (
<Section
fill
title="Catalog"
buttons={
!express && (
<>
<CargoCartButtons />
<Button
color={self_paid ? 'caution' : 'transparent'}
icon={self_paid ? 'check-square-o' : 'square-o'}
ml={2}
onClick={() => act('toggleprivate')}
tooltip="Use your own funds to purchase items."
>
Buy Privately
</Button>
</>
)
}
>
<Stack fill>
<Stack.Item grow>
<CatalogTabs
activeSupplyName={activeSupplyName}
categories={supplies}
searchText={searchText}
setActiveSupplyName={setActiveSupplyName}
setSearchText={setSearchText}
/>
</Stack.Item>
<Stack.Divider />
<Stack.Item grow={express ? 2 : 3}>
<CatalogList packs={packs} />
</Stack.Item>
</Stack>
</Section>
);
}

type CatalogTabsProps = {
activeSupplyName: string;
categories: SupplyCategory[];
searchText: string;
setActiveSupplyName: (name: string) => void;
setSearchText: (text: string) => void;
};

function CatalogTabs(props: CatalogTabsProps) {
const {
activeSupplyName,
categories,
searchText,
setActiveSupplyName,
setSearchText,
} = props;

const sorted = sortBy(categories, (supply) => supply.name);

return (
<Tabs vertical>
<Tabs.Tab
key="search_results"
selected={activeSupplyName === 'search_results'}
>
<Stack align="center">
<Stack.Item>
<Icon name="search" />
</Stack.Item>
<Stack.Item grow>
<Input
fluid
placeholder="Search..."
value={searchText}
onInput={(e, value) => {
if (value === searchText) {
return;
}

if (value.length) {
// Start showing results
setActiveSupplyName('search_results');
} else if (activeSupplyName === 'search_results') {
// return to normal category
setActiveSupplyName(sorted[0]?.name);
}
setSearchText(value);
}}
/>
</Stack.Item>
</Stack>
</Tabs.Tab>

{sorted.map((supply) => (
<Tabs.Tab
className="candystripe"
color={supply.name === activeSupplyName ? 'green' : undefined}
key={supply.name}
selected={supply.name === activeSupplyName}
onClick={() => {
setActiveSupplyName(supply.name);
setSearchText('');
}}
>
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<span>{supply.name}</span>
<span> {supply.packs.length}</span>
</div>
</Tabs.Tab>
))}
</Tabs>
);
}

type CatalogListProps = {
packs: SupplyCategory['packs'];
};

function CatalogList(props: CatalogListProps) {
const { act, data } = useBackend<CargoData>();
const { amount_by_name = {}, max_order, self_paid, app_cost } = data;
const { packs = [] } = props;

return (
<Section fill scrollable>
<Table>
{packs.map((pack) => {
let color = '';
const digits = Math.floor(Math.log10(pack.cost) + 1);
if (self_paid) {
color = 'caution';
} else if (digits >= 5 && digits <= 6) {
color = 'yellow';
} else if (digits > 6) {
color = 'bad';
}

return (
<Table.Row key={pack.name} className="candystripe">
<Table.Cell color="label">{pack.name}</Table.Cell>
<Table.Cell collapsing>
{!!pack.small_item && (
<Tooltip content="Small Item">
<Icon color="purple" name="compress-alt" />
</Tooltip>
)}
</Table.Cell>
<Table.Cell collapsing>
{!!pack.access && (
<Tooltip content="Restricted">
<Icon color="average" name="lock" />
</Tooltip>
)}
</Table.Cell>
<Table.Cell collapsing textAlign="right">
<Button
color={color}
tooltip={pack.desc}
tooltipPosition="left"
disabled={(amount_by_name[pack.name] || 0) >= max_order}
onClick={() =>
act('add', {
id: pack.id,
})
}
minWidth={5}
mb={0.5}
>
{formatMoney(
(self_paid && !pack.goody) || app_cost
? Math.round(pack.cost * 1.1)
: pack.cost,
)}{' '}
cr
</Button>
</Table.Cell>
</Table.Row>
);
})}
</Table>
</Section>
);
}
58 changes: 58 additions & 0 deletions tgui/packages/tgui/interfaces/Cargo/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { BooleanLike } from 'common/react';

export type CargoData = {
amount_by_name: Record<string, number> | undefined;
app_cost?: number;
away: BooleanLike;
can_approve_requests: BooleanLike;
can_send: BooleanLike;
cart: CartEntry[];
department: string;
docked: BooleanLike;
grocery: number;
loan_dispatched: BooleanLike;
loan: BooleanLike;
location: string;
max_order: number;
message: string;
points: number;
requests: Request[];
requestonly: BooleanLike;
self_paid: BooleanLike;
supplies: Record<string, SupplyCategory>;
};

export type SupplyCategory = {
name: string;
packs: Supply[];
};

export type Supply = {
access: BooleanLike;
cost: number;
desc: string;
goody: BooleanLike;
id: string;
name: string;
small_item: BooleanLike;
};

type CartEntry = {
amount: number;
can_be_cancelled: BooleanLike;
cost_type: string;
cost: number;
dep_order: BooleanLike;
id: string;
object: string;
orderer: string;
paid: BooleanLike;
};

type Request = {
cost: number;
id: string;
object: string;
orderer: string;
reason: string;
};

0 comments on commit d7089ca

Please sign in to comment.