From d773f4db2ff5dce051510dae6674e34edf5d27bf Mon Sep 17 00:00:00 2001
From: Aylong <69762909+AyIong@users.noreply.github.com>
Date: Thu, 30 Jan 2025 18:00:12 +0200
Subject: [PATCH] Supply Consoles restyle & order content preview (#89198)
## About The Pull Request
In a nutshell, everything will be visible in the `Demo` section.
But if you want some details...
- Filling of static_data was divided into procs, for better
understanding and possibility to use the same actions in two order
consoles
- Added an image of the first item in crate at each order (almost)
- Added the ability to see what is inside an order, the information is
not always accurate due to the nature of some orders such as random hats
- Slightly remaked layout, making everything look more cohesive and
eliminating the empty space at the bottom of the screen
- When buying anonymously, the original price does not disappear, but is
crossed out, and the new price is written below it
## Demo
Screenshots
Supply Console
| Before | After |
| - | - |
|

|

|
Express Console
| Before | After |
| - | - |
|

|

|
Other
| Content preview | Express login |
| - | - |
|

|

|
Video
https://github.com/user-attachments/assets/c7e16206-39f5-413c-9eea-c0284350c4a3
## Why It's Good For The Game
More convenience plus a bit prettier.
The ability to view the contents of an order, even if some madman didn't
describe its contents in the description (those who did this are really
crazy)
Section with tabs scrolls on both 515 and 516
And little cleaner data receiving code
## Changelog
:cl:
qol: Supply console got little redesign, and ability to see what can be
inside a order.
code: Supply console and express supply console, now use a unified
method of acquiring data
/:cl:
---------
Co-authored-by: Ivory
Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com>
---
code/modules/cargo/expressconsole.dm | 33 +-
code/modules/cargo/orderconsole.dm | 92 +++-
.../tgui/interfaces/Cargo/CargoCart.tsx | 52 ++-
.../tgui/interfaces/Cargo/CargoCatalog.tsx | 398 +++++++++++-------
.../tgui/interfaces/Cargo/CargoRequests.tsx | 17 +-
.../tgui/interfaces/Cargo/CargoStatus.tsx | 2 +-
tgui/packages/tgui/interfaces/Cargo/index.tsx | 102 +++--
tgui/packages/tgui/interfaces/Cargo/types.ts | 10 +
.../packages/tgui/interfaces/CargoExpress.tsx | 102 +++--
9 files changed, 494 insertions(+), 314 deletions(-)
diff --git a/code/modules/cargo/expressconsole.dm b/code/modules/cargo/expressconsole.dm
index 4070301bfbe..86a4d4f3a4f 100644
--- a/code/modules/cargo/expressconsole.dm
+++ b/code/modules/cargo/expressconsole.dm
@@ -92,26 +92,17 @@
/obj/machinery/computer/cargo/express/proc/packin_up(forced = FALSE) // oh shit, I'm sorry
meme_pack_data = list() // sorry for what?
- if (!forced && !SSshuttle.initialized) // Subsystem is still sleeping, add ourselves to its buffer and abort
- SSshuttle.express_consoles += src
- return
- for(var/pack in SSshuttle.supply_packs) // our quartermaster taught us not to be ashamed of our supply packs
- var/datum/supply_pack/P = SSshuttle.supply_packs[pack] // specially since they're such a good price and all
- if(!meme_pack_data[P.group]) // yeah, I see that, your quartermaster gave you good advice
- meme_pack_data[P.group] = list( // it gets cheaper when I return it
- "name" = P.group, // mmhm
- "packs" = list() // sometimes, I return it so much, I rip the manifest
- ) // see, my quartermaster taught me a few things too
- if((P.hidden) || (P.special)) // like, how not to rip the manifest
- continue// by using someone else's crate
- if(P.contraband && !contraband) // will you show me?
- continue // i'd be right happy to
- meme_pack_data[P.group]["packs"] += list(list(
- "name" = P.name,
- "cost" = P.get_cost() * get_discount(),
- "id" = pack,
- "desc" = P.desc || P.name // If there is a description, use it. Otherwise use the pack's name.
- ))
+ if(!forced && !SSshuttle.initialized) // our quartermaster taught us not to be ashamed of our supply packs
+ SSshuttle.express_consoles += src // specially since they're such a good price and all
+ return // yeah, I see that, your quartermaster gave you good advice
+ // it gets cheaper when I return it
+ for(var/pack_id in SSshuttle.supply_packs) // mmhm
+ var/datum/supply_pack/pack = SSshuttle.supply_packs[pack_id] // sometimes, I return it so much, I rip the manifest
+ if(!meme_pack_data[pack.group]) // see, my quartermaster taught me a few things too
+ meme_pack_data[pack.group] = list( // like, how not to rip the manifest
+ "name" = pack.group, // by using someone else's crate
+ "packs" = get_packs_data(pack.group, express = TRUE), // will you show me?
+ ) // i'd be right happy to
/obj/machinery/computer/cargo/express/ui_data(mob/user)
var/canBeacon = beacon && (isturf(beacon.loc) || ismob(beacon.loc))//is the beacon in a valid location?
@@ -146,7 +137,7 @@
data["supplies"] = meme_pack_data
return data
-/obj/machinery/computer/cargo/express/proc/get_discount()
+/obj/machinery/computer/cargo/express/get_discount()
return (obj_flags & EMAGGED) ? EXPRESS_EMAG_DISCOUNT : 1
/obj/machinery/computer/cargo/express/ui_act(action, params, datum/tgui/ui)
diff --git a/code/modules/cargo/orderconsole.dm b/code/modules/cargo/orderconsole.dm
index 87a085707c0..409dc197e43 100644
--- a/code/modules/cargo/orderconsole.dm
+++ b/code/modules/cargo/orderconsole.dm
@@ -95,9 +95,9 @@
var/list/data = list()
data["department"] = "Cargo" // Hardcoded here, for customization in budgetordering.dm AKA NT IRN
data["location"] = SSshuttle.supply.getStatusText()
- var/datum/bank_account/D = SSeconomy.get_dep_account(cargo_account)
- if(D)
- data["points"] = D.account_balance
+ var/datum/bank_account/bank = SSeconomy.get_dep_account(cargo_account)
+ if(bank)
+ data["points"] = bank.account_balance
data["grocery"] = SSshuttle.chef_groceries.len
data["away"] = SSshuttle.supply.getDockedId() == docking_away
data["self_paid"] = self_paid
@@ -162,26 +162,78 @@
var/list/data = list()
data["max_order"] = CARGO_MAX_ORDER
data["supplies"] = list()
- for(var/pack in SSshuttle.supply_packs)
- var/datum/supply_pack/P = SSshuttle.supply_packs[pack]
- if(!data["supplies"][P.group])
- data["supplies"][P.group] = list(
- "name" = P.group,
- "packs" = list()
+
+ for(var/pack_id in SSshuttle.supply_packs)
+ var/datum/supply_pack/pack = SSshuttle.supply_packs[pack_id]
+ if(!data["supplies"][pack.group])
+ data["supplies"][pack.group] = list(
+ "name" = pack.group,
+ "packs" = get_packs_data(pack.group),
)
- if((P.hidden && !(obj_flags & EMAGGED)) || (P.contraband && !contraband) || (P.special && !P.special_enabled) || P.drop_pod_only)
- continue
- data["supplies"][P.group]["packs"] += list(list(
- "name" = P.name,
- "cost" = P.get_cost(),
- "id" = pack,
- "desc" = P.desc || P.name, // If there is a description, use it. Otherwise use the pack's name.
- "goody" = P.goody,
- "access" = P.access,
- "contraband" = P.contraband,
- ))
+
return data
+/**
+ * returns a list of supply packs for a certain group
+ * * group - the group of packs to return
+ * * express - if this is an express console
+ */
+/obj/machinery/computer/cargo/proc/get_packs_data(group, express = FALSE)
+ var/list/packs = list()
+ for(var/pack_id in SSshuttle.supply_packs)
+ var/datum/supply_pack/pack = SSshuttle.supply_packs[pack_id]
+ if(pack.group != group)
+ continue
+
+ // Express console packs check
+ if(express && (pack.hidden || pack.special))
+ continue
+
+ if(!express && ((pack.hidden && !(obj_flags & EMAGGED)) || (pack.special && !pack.special_enabled) || pack.drop_pod_only))
+ continue
+
+ if(pack.contraband && !contraband)
+ continue
+
+ var/obj/item/first_item = length(pack.contains) > 0 ? pack.contains[1] : null
+ packs += list(list(
+ "name" = pack.name,
+ "cost" = pack.get_cost() * get_discount(),
+ "id" = pack_id,
+ "desc" = pack.desc || pack.name, // If there is a description, use it. Otherwise use the pack's name.
+ "first_item_icon" = first_item?.icon,
+ "first_item_icon_state" = first_item?.icon_state,
+ "goody" = pack.goody,
+ "access" = pack.access,
+ "contraband" = pack.contraband,
+ "contains" = get_pack_contains(pack),
+ ))
+
+ return packs
+
+/**
+ * returns a list of the contents of a supply pack
+ * * pack - the pack to get the contents of
+ */
+/obj/machinery/computer/cargo/proc/get_pack_contains(datum/supply_pack/pack)
+ var/list/contains = list()
+ for(var/obj/item/item as anything in pack.contains)
+ contains += list(list(
+ "name" = item.name,
+ "icon" = item.greyscale_config ? null : item.icon,
+ "icon_state" = item.greyscale_config ? null : item.icon_state,
+ "amount" = pack.contains[item]
+ ))
+
+ return contains
+
+/**
+ * returns the discount multiplier applied to all supply packs,
+ * the discount is calculated as follows: pack_cost * get_discount()
+ */
+/obj/machinery/computer/cargo/proc/get_discount()
+ return 1
+
/**
* adds an supply pack to the checkout cart
* * user - the mobe doing this order
diff --git a/tgui/packages/tgui/interfaces/Cargo/CargoCart.tsx b/tgui/packages/tgui/interfaces/Cargo/CargoCart.tsx
index 41c05acdb05..af3fc11981e 100644
--- a/tgui/packages/tgui/interfaces/Cargo/CargoCart.tsx
+++ b/tgui/packages/tgui/interfaces/Cargo/CargoCart.tsx
@@ -11,7 +11,6 @@ import {
import { formatMoney } from 'tgui-core/format';
import { useBackend } from '../../backend';
-import { CargoCartButtons } from './CargoButtons';
import { CargoData } from './types';
export function CargoCart(props) {
@@ -23,16 +22,18 @@ export function CargoCart(props) {
return (
- }>
+
{cart.length > 0 && !!can_send && (
-
-
+
+
- {!sendable && }
+ {!sendable && (
+
+ )}
+
+
+
+
+ {sorted.map((supply) => (
+ {
+ setActiveSupplyName(supply.name);
+ setSearchText('');
+ }}
+ >
+
+ {supply.name}
+ {supply.packs.length}
+
+
+ ))}
+
+
+
+ {!express && (
+ act('toggleprivate')}
+ tooltip="Use your own funds to purchase items."
+ tooltipPosition="top"
+ >
+ Buy Privately
+
+ )}
+
+
);
}
type CatalogListProps = {
packs: SupplyCategory['packs'];
+ openContents: Dispatch>;
};
function CatalogList(props: CatalogListProps) {
const { act, data } = useBackend();
const { amount_by_name = {}, max_order, self_paid, app_cost } = data;
- const { packs = [] } = props;
+ const { packs = [], openContents } = props;
return (
-
-