From 79fb97d0a330f7d43df3952d13cd5a66f0767116 Mon Sep 17 00:00:00 2001 From: Koshenko Date: Fri, 17 May 2024 16:55:30 -0700 Subject: [PATCH] Re-add select equipment for TGUI --- .../tgui/interfaces/SelectEquipment.jsx | 218 ++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 tgui/packages/tgui/interfaces/SelectEquipment.jsx diff --git a/tgui/packages/tgui/interfaces/SelectEquipment.jsx b/tgui/packages/tgui/interfaces/SelectEquipment.jsx new file mode 100644 index 00000000000..b7017a92236 --- /dev/null +++ b/tgui/packages/tgui/interfaces/SelectEquipment.jsx @@ -0,0 +1,218 @@ +import { filter, map, sortBy, uniq } from 'common/collections'; +import { flow } from 'common/fp'; +import { createSearch } from 'common/string'; + +import { useBackend, useLocalState } from '../backend'; +import { Box, Button, Icon, Input, Section, Stack, Tabs } from '../components'; +import { Window } from '../layouts'; + +// here's an important mental define: +// custom outfits give a ref keyword instead of path +const getOutfitKey = (outfit) => outfit.path || outfit.ref; + +const useOutfitTabs = (categories) => { + return useLocalState('selected-tab', categories[0]); +}; + +export const SelectEquipment = (props) => { + const { act, data } = useBackend(); + const { name, icon64, current_outfit, favorites } = data; + + const isFavorited = (entry) => favorites?.includes(entry.path); + + const outfits = map((entry) => ({ + ...entry, + favorite: isFavorited(entry), + }))([...data.outfits, ...data.custom_outfits]); + + // even if no custom outfits were sent, we still want to make sure there's + // at least a 'Custom' tab so the button to create a new one pops up + const categories = uniq([ + ...outfits.map((entry) => entry.category), + 'Custom', + ]); + const [tab] = useOutfitTabs(categories); + + const [searchText, setSearchText] = useLocalState('searchText', ''); + const searchFilter = createSearch( + searchText, + (entry) => entry.name + entry.path, + ); + + const visibleOutfits = flow([ + filter((entry) => entry.category === tab), + filter(searchFilter), + sortBy( + (entry) => !entry.favorite, + (entry) => !entry.priority, + (entry) => entry.name, + ), + ])(outfits); + + const getOutfitEntry = (current_outfit) => + outfits.find((outfit) => getOutfitKey(outfit) === current_outfit); + + const currentOutfitEntry = getOutfitEntry(current_outfit); + + return ( + + + + + + + setSearchText(value)} + /> + + + + + + + + + + + + +
+ +
+
+ +
+ +
+
+
+
+
+
+
+ ); +}; + +const DisplayTabs = (props) => { + const { categories } = props; + const [tab, setTab] = useOutfitTabs(categories); + return ( + + {categories.map((category) => ( + setTab(category)} + > + {category} + + ))} + + ); +}; + +const OutfitDisplay = (props) => { + const { act, data } = useBackend(); + const { current_outfit } = data; + const { entries, currentTab } = props; + return ( +
+ {entries.map((entry) => ( + + )} +
+ ); +}; + +const CurrentlySelectedDisplay = (props) => { + const { act, data } = useBackend(); + const { current_outfit } = data; + const { entry } = props; + return ( + + {entry?.path && ( + + + act('togglefavorite', { + path: entry.path, + }) + } + /> + + )} + + Currently selected: + + {entry?.name} + + + + + + + ); +};