From 0d3962cff9746bcab30a62b4425ebc4d406cf73e Mon Sep 17 00:00:00 2001 From: Jeremiah <42397676+jlsnow301@users.noreply.github.com> Date: Tue, 1 Apr 2025 12:38:10 -0700 Subject: [PATCH] Library console in typescript (#90221) ## About The Pull Request Huge jsx UI converted over to typescript, removed uselocalstate, and some tiny qol changes to boot. This is not a rewrite, it should function exactly the same
photos Inventory screen is split into sections so you shouldn't lose the search controls while scrolling ![Screenshot 2025-03-24 130056](https://github.com/user-attachments/assets/9a5e188f-1960-490d-9b86-884d2ee8636a) Native tabs for poster selection, candy striped ![Screenshot 2025-03-24 130104](https://github.com/user-attachments/assets/da1aca51-cded-4988-b9cc-bf87a2465867) Modal gets a bit more padding ![Screenshot 2025-03-24 130113](https://github.com/user-attachments/assets/37410b1e-9fe3-40ff-a87d-e9ffaa01f15b)
## Why It's Good For The Game Big win for typescript conversions. The file is made more digestible as well ## Changelog :cl: fix: The library console has been refactored. Report any issues in the github! /:cl: --- .../interfaces/LibraryAdmin/BookListing.tsx | 3 +- .../tgui/interfaces/LibraryConsole.jsx | 934 ------------------ .../LibraryConsole/components/PageSelect.tsx | 58 ++ .../LibraryConsole/components/PopoutMenu.tsx | 71 ++ .../components/ScrollableSection.tsx | 26 + .../LibraryConsole/components/Search.tsx | 162 +++ .../tgui/interfaces/LibraryConsole/index.tsx | 49 + .../LibraryConsole/screens/Archive.tsx | 41 + .../LibraryConsole/screens/Checkout.tsx | 203 ++++ .../LibraryConsole/screens/Forbidden.tsx | 60 ++ .../LibraryConsole/screens/Inventory.tsx | 83 ++ .../LibraryConsole/screens/Print.tsx | 97 ++ .../LibraryConsole/screens/Upload.tsx | 216 ++++ .../tgui/interfaces/LibraryConsole/types.ts | 63 ++ .../LibraryConsole/useLibraryContext.ts | 15 + .../tgui/interfaces/LibraryVisitor.jsx | 2 +- 16 files changed, 1147 insertions(+), 936 deletions(-) delete mode 100644 tgui/packages/tgui/interfaces/LibraryConsole.jsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/components/PageSelect.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/components/PopoutMenu.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/components/ScrollableSection.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/components/Search.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/index.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/screens/Archive.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/screens/Checkout.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/screens/Forbidden.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/screens/Inventory.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/screens/Print.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/screens/Upload.tsx create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/types.ts create mode 100644 tgui/packages/tgui/interfaces/LibraryConsole/useLibraryContext.ts diff --git a/tgui/packages/tgui/interfaces/LibraryAdmin/BookListing.tsx b/tgui/packages/tgui/interfaces/LibraryAdmin/BookListing.tsx index fd12a5e3e40..bb8b8c5d62b 100644 --- a/tgui/packages/tgui/interfaces/LibraryAdmin/BookListing.tsx +++ b/tgui/packages/tgui/interfaces/LibraryAdmin/BookListing.tsx @@ -2,7 +2,8 @@ import { Box, NoticeBox, Stack } from 'tgui-core/components'; import { useBackend } from '../../backend'; import { Window } from '../../layouts'; -import { PageSelect, SearchAndDisplay } from '../LibraryConsole'; +import { PageSelect } from '../LibraryConsole/components/PageSelect'; +import { SearchAndDisplay } from '../LibraryConsole/components/Search'; import { LibraryAdminData } from './types'; export function BookListing(props) { diff --git a/tgui/packages/tgui/interfaces/LibraryConsole.jsx b/tgui/packages/tgui/interfaces/LibraryConsole.jsx deleted file mode 100644 index 87d87f9bac8..00000000000 --- a/tgui/packages/tgui/interfaces/LibraryConsole.jsx +++ /dev/null @@ -1,934 +0,0 @@ -import { map, sortBy } from 'common/collections'; -import { useState } from 'react'; -import { - Box, - Button, - Dropdown, - Flex, - Input, - LabeledList, - Modal, - NoticeBox, - NumberInput, - Section, - Stack, - Table, -} from 'tgui-core/components'; -import { classes } from 'tgui-core/react'; - -import { useBackend, useLocalState } from '../backend'; -import { Window } from '../layouts'; -import { sanitizeText } from '../sanitize'; - -export const LibraryConsole = (props) => { - const { act, data } = useBackend(); - const { display_lore } = data; - return ( - - - - - - - - - - - - - ); -}; - -export const PopoutMenu = (props) => { - const { act, data } = useBackend(); - const { screen_state, show_dropdown, display_lore } = data; - return ( -
- - -
- ); -}; - -export const PageDisplay = (props) => { - const { act, data } = useBackend(); - const { screen_state } = data; - /* eslint-disable indent */ - /* eslint-disable operator-linebreak */ - return screen_state === 1 ? ( - - ) : screen_state === 2 ? ( - - ) : screen_state === 3 ? ( - - ) : screen_state === 4 ? ( - - ) : screen_state === 5 ? ( - - ) : screen_state === 6 ? ( - - ) : null; - /* eslint-enable indent */ - /* eslint-enable operator-linebreak */ -}; - -export const Inventory = (props) => { - const { act, data } = useBackend(); - const { inventory_page_count, inventory_page, has_inventory } = data; - if (!has_inventory) { - return ( - No Book Records detected. Update your inventory! - ); - } - return ( - - - } - /> - - - - act('switch_inventory_page', { - page: value, - }) - } - /> - - - ); -}; - -export const InventoryDetails = (props) => { - const { act, data } = useBackend(); - const inventory = sortBy( - map(data.inventory, (book, i) => ({ - ...book, - // Generate a unique id - key: i, - })), - (book) => book.key, - ); - return ( -
- - - Remove - Title - Author - - {inventory.map((book) => ( - - - - - {book.title} - {book.author} - - ))} -
-
- ); -}; - -export const Checkout = (props) => { - const { act, data } = useBackend(); - const { checkout_page, checkout_page_count } = data; - - const [checkoutBook, setCheckoutBook] = useLocalState('CheckoutBook', false); - return ( - - - - - } - /> - - - - act('switch_checkout_page', { - page: value, - }) - } - /> - - - - - - - - - - - # - Category - Title - Author - - {records.map((record) => ( - - - - - {record.category} - {record.title} - {record.author} - - ))} -
- - ); -}; - -export const Upload = (props) => { - const { act, data } = useBackend(); - const { - active_newscaster_cooldown, - cache_author, - cache_content, - cache_title, - can_db_request, - has_cache, - has_scanner, - cooldown_string, - } = data; - const [uploadToDB, setUploadToDB] = useLocalState('UploadDB', false); - if (!has_scanner) { - return ( - - No nearby scanner detected, construct one to continue. - - ); - } - if (!has_cache) { - return Scan in a book to upload.; - } - const contentHtml = { - __html: sanitizeText(cache_content), - }; - return ( - <> - - - - Current Scan Cache - - - - - - - - - Title: - - - - - act('set_cache_title', { - title: value, - }) - } - /> - - - - Author: - - - - - act('set_cache_author', { - author: value, - }) - } - /> - - - - -
- -
-
-
-
- - - - + + + + + + + {!!display_lore && ( + + )} + + + ); +} + +export function PopoutEntry(props) { + const { act, data } = useBackend(); + + const { id, text, icon, color, font } = props; + const { screen_state, show_dropdown } = data; + + const selected_color = color || 'good'; + const deselected_color = color || ''; + + return ( + + + + ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/components/ScrollableSection.tsx b/tgui/packages/tgui/interfaces/LibraryConsole/components/ScrollableSection.tsx new file mode 100644 index 00000000000..af5aa3273d0 --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/components/ScrollableSection.tsx @@ -0,0 +1,26 @@ +import { ReactNode } from 'react'; +import { Section, Stack } from 'tgui-core/components'; + +type Props = { + contents: ReactNode; + header: ReactNode; +}; + +export function ScrollableSection(props: Props) { + const { contents, header } = props; + + return ( + + +
+ {header} +
+
+ +
+ {contents} +
+
+
+ ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/components/Search.tsx b/tgui/packages/tgui/interfaces/LibraryConsole/components/Search.tsx new file mode 100644 index 00000000000..6406886f7cd --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/components/Search.tsx @@ -0,0 +1,162 @@ +import { useBackend } from 'tgui/backend'; +import { + Button, + Dropdown, + Input, + Section, + Stack, + Table, +} from 'tgui-core/components'; + +import { LibraryConsoleData } from '../types'; + +export function SearchAndDisplay(props) { + return ( + + + + + + + + + ); +} + +function SearchTabs(props) { + const { act, data } = useBackend(); + const { + author, + book_id, + can_db_request, + category, + params_changed, + search_categories = [], + title, + } = data; + + return ( +
+ + + + + + act('set_search_id', { + id: value, + }) + } + /> + + + + act('set_search_category', { + category: value, + }) + } + /> + + + + act('set_search_title', { + title: value, + }) + } + /> + + + + act('set_search_author', { + author: value, + }) + } + /> + + + + + + + + +
+ ); +} + +function SearchResults(props) { + const { act, data } = useBackend(); + const { pages } = data; + + const sorted = pages + .map((record, i) => ({ + ...record, + // Generate a unique id + key: i, + })) + .sort((a, b) => a.key - b.key); + + return ( +
+ + + # + Category + Title + Author + + {sorted.map((record) => ( + + + + + {record.category} + {record.title} + {record.author} + + ))} +
+
+ ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/index.tsx b/tgui/packages/tgui/interfaces/LibraryConsole/index.tsx new file mode 100644 index 00000000000..8441d600c2e --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/index.tsx @@ -0,0 +1,49 @@ +import { useState } from 'react'; +import { Stack } from 'tgui-core/components'; + +import { useBackend } from '../../backend'; +import { Window } from '../../layouts'; +import { PopoutMenu } from './components/PopoutMenu'; +import { Archive } from './screens/Archive'; +import { Checkout } from './screens/Checkout'; +import { Forbidden } from './screens/Forbidden'; +import { Inventory } from './screens/Inventory'; +import { Print } from './screens/Print'; +import { Upload } from './screens/Upload'; +import { LibraryConsoleData } from './types'; +import { LibraryContext } from './useLibraryContext'; + +export function LibraryConsole(props) { + const { data } = useBackend(); + const { display_lore, screen_state } = data; + + const checkoutBookState = useState(false); + const uploadToDBState = useState(false); + + return ( + + + + + + + + + {screen_state === 1 && } + {screen_state === 2 && } + {screen_state === 3 && } + {screen_state === 4 && } + {screen_state === 5 && } + {screen_state === 6 && } + + + + + + ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/screens/Archive.tsx b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Archive.tsx new file mode 100644 index 00000000000..9cd0c42dd1f --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Archive.tsx @@ -0,0 +1,41 @@ +import { useBackend } from 'tgui/backend'; +import { NoticeBox, Stack } from 'tgui-core/components'; + +import { PageSelect } from '../components/PageSelect'; +import { SearchAndDisplay } from '../components/Search'; +import { LibraryConsoleData } from '../types'; + +export function Archive(props) { + const { act, data } = useBackend(); + const { can_connect, can_db_request, page_count, our_page } = data; + + if (!can_connect) { + return ( + + Unable to retrieve book listings. Please contact your system + administrator for assistance. + + ); + } + + return ( + + + + + + + act('switch_page', { + page: value, + }) + } + /> + + + ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/screens/Checkout.tsx b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Checkout.tsx new file mode 100644 index 00000000000..94f091aec77 --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Checkout.tsx @@ -0,0 +1,203 @@ +import { useState } from 'react'; +import { useBackend } from 'tgui/backend'; +import { + Button, + Dropdown, + Input, + LabeledList, + Modal, + NoticeBox, + NumberInput, + Stack, + Table, +} from 'tgui-core/components'; + +import { PageSelect } from '../components/PageSelect'; +import { ScrollableSection } from '../components/ScrollableSection'; +import { LibraryConsoleData } from '../types'; +import { useLibraryContext } from '../useLibraryContext'; + +export function Checkout(props) { + const { act, data } = useBackend(); + const { checkout_page, checkout_page_count } = data; + + const { checkoutBookState } = useLibraryContext(); + const [checkoutBook, setCheckoutBook] = checkoutBookState; + + return ( + + + + + } + /> + + + + act('switch_checkout_page', { + page: value, + }) + } + /> + + + + + + + {!!checkoutBook && } + + ); +} + +function CheckoutModal(props) { + const { act, data } = useBackend(); + + const inventory = data.inventory + .map((book, i) => ({ + ...book, + // Generate a unique id + key: i, + })) + .sort((a, b) => a.key - b.key); + + const { checkoutBookState } = useLibraryContext(); + const [checkoutBook, setCheckoutBook] = checkoutBookState; + + const [bookName, setBookName] = useState('Insert Book name...'); + const [checkoutee, setCheckoutee] = useState('Recipient'); + const [checkoutPeriod, setCheckoutPeriod] = useState(5); + + return ( + + + + Are you sure you want to loan out this book? + + + book.title)} + onSelected={(e) => setBookName(e)} + /> + + + + + setCheckoutee(value)} + /> + + + setCheckoutPeriod(value)} + /> + + + + + + + + + + + + + + + + ); +} + +export function CheckoutEntries(props) { + const { act, data } = useBackend(); + const { checkouts = [] } = data; + + return ( + + + Title + Author + Borrower + Time Left + Check-In + + {checkouts.length === 0 ? ( + + + No books checked out. + + + ) : ( + checkouts.map((entry) => ( + + {entry.title} + {entry.author} + {entry.borrower} + + {entry.overdue ? 'Overdue' : entry.due_in_minutes + ' Minutes'} + + +
+ ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/screens/Forbidden.tsx b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Forbidden.tsx new file mode 100644 index 00000000000..9029b6cddc5 --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Forbidden.tsx @@ -0,0 +1,60 @@ +import { useBackend } from 'tgui/backend'; +import { Box, Button, Modal, Stack } from 'tgui-core/components'; + +const description = + 'Abf vqrnz cebprffhf pbzchgngvbanyvf fghqrer vapvcvrzhf\nCebprffhf pbzchgngvbanyrf fhag erf nofgenpgnr dhnr pbzchgngberf vapbyhag\nHg ribyihag, cebprffhf nyvn nofgenpgn dhnr qngn znavchyner qvphaghe\nRibyhgvbavf cebprffhf qvevtvghe cre rkrzcyhz erthynr cebtenzzngvf ibpngv\nUbzvarf cebtenzzngn nq cebprffhf erpgbf rssvpvhag\nEriren fcvevghf pbzchgngbevv phz vapnagnzragvf pbavhatvzhf\nCebprffhf pbzchgngvbanyvf rfg zhyghz fvzvyvf vqrnr irarsvpnr fcvevghf\nivqrev nhg gnatv aba cbgrfg\nAba rfg rk zngrevn pbzcbfvgn\nFrq vq cynpreng vcfhz\nAba cbgrfg bcrenev bchf vagryyrpghnyr\nErfcbaqrev cbgrfg\nZhaqhz nssvprer cbgrfg rebtnaqb crphavnz nq evcnz iry cre oenppuvhz \nebobgv snoevpnaqb zbqrenaqb\nPbafvyvvf hgvzhe cebprffvohf nhthenaqv fhag fvphg vapnagnzragn irarsvpvv'; + +export function Forbidden(props) { + return ( + + {description} + + + ); +} + +function ForbiddenModal(props) { + const { act } = useBackend(); + + return ( + + + Accessing Forbidden Lore Vault v 1.3: + + + Are you absolutely sure you want to proceed? + + + EldritchRelics Inc. will take no responsibility for this choice + + + + + + + + + + + ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/screens/Inventory.tsx b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Inventory.tsx new file mode 100644 index 00000000000..f3911c1c9aa --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Inventory.tsx @@ -0,0 +1,83 @@ +import { useBackend } from 'tgui/backend'; +import { Button, NoticeBox, Stack, Table } from 'tgui-core/components'; + +import { PageSelect } from '../components/PageSelect'; +import { ScrollableSection } from '../components/ScrollableSection'; +import { LibraryConsoleData } from '../types'; + +export function Inventory(props) { + const { act, data } = useBackend(); + const { inventory_page_count, inventory_page, has_inventory } = data; + + if (!has_inventory) { + return ( + No Book Records detected. Update your inventory! + ); + } + + return ( + + + } + /> + + + + act('switch_inventory_page', { + page: value, + }) + } + /> + + + ); +} + +function InventoryDetails(props) { + const { act, data } = useBackend(); + const { inventory = [] } = data; + + const sorted = inventory + .map((book, i) => ({ + ...book, + // Generate a unique id + key: i, + })) + .sort((a, b) => a.key - b.key); + + return ( + + + Title + Author + Remove + + {sorted.map((book) => ( + + {book.title} + {book.author} + + + + + ))} +
+ ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/screens/Print.tsx b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Print.tsx new file mode 100644 index 00000000000..ed6ca65c5f8 --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Print.tsx @@ -0,0 +1,97 @@ +import { useState } from 'react'; +import { useBackend } from 'tgui/backend'; +import { Box, Button, Section, Stack, Tabs } from 'tgui-core/components'; +import { classes } from 'tgui-core/react'; + +import { LibraryConsoleData } from '../types'; + +export function Print(props) { + const { act, data } = useBackend(); + const { bible_name, bible_sprite, deity, posters, religion } = data; + + const [selectedPoster, setSelectedPoster] = useState(posters[0]); + + return ( + + + + +
+ + {posters.map((poster) => { + const selected = selectedPoster === poster; + + return ( + setSelectedPoster(poster)} + > + {poster} + + ); + })} + +
+
+ + + + {bible_name} + + + In the Name of {deity} + + + For the Sake of {religion} + + + + + + +
+
+ + + + + + + + + + +
+ ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/screens/Upload.tsx b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Upload.tsx new file mode 100644 index 00000000000..71e36806f81 --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/screens/Upload.tsx @@ -0,0 +1,216 @@ +import { useState } from 'react'; +import { useBackend } from 'tgui/backend'; +import { sanitizeText } from 'tgui/sanitize'; +import { + Box, + Button, + Dropdown, + Input, + LabeledList, + Modal, + NoticeBox, + Section, + Stack, +} from 'tgui-core/components'; + +import { LibraryConsoleData } from '../types'; +import { useLibraryContext } from '../useLibraryContext'; + +export function Upload(props) { + const { act, data } = useBackend(); + const { + active_newscaster_cooldown, + cache_author, + cache_content, + cache_title, + can_db_request, + cooldown_string, + has_cache, + has_scanner, + } = data; + + const { uploadToDBState } = useLibraryContext(); + const [uploadToDB, setUploadToDB] = uploadToDBState; + + if (!has_scanner) { + return ( + + No nearby scanner detected, construct one to continue. + + ); + } + + if (!has_cache) { + return Scan in a book to upload.; + } + + const contentHtml = { + __html: sanitizeText(cache_content), + }; + + return ( + <> + + + + Current Scan Cache + + + + + + + + + Title: + + + + + act('set_cache_title', { + title: value, + }) + } + /> + + + + Author: + + + + + act('set_cache_author', { + author: value, + }) + } + /> + + + + +
+ +
+
+
+
+ + + + + + + + + + +
+ {!!uploadToDB && } + + ); +} + +function UploadModal(props) { + const { act, data } = useBackend(); + const { upload_categories, default_category, can_db_request } = data; + + const { uploadToDBState } = useLibraryContext(); + const [uploadToDB, setUploadToDB] = uploadToDBState; + + const [uploadCategory, setUploadCategory] = useState(''); + + const display_category = uploadCategory || default_category; + + return ( + + + Are you sure you want to upload this book to the database? + + + + setUploadCategory(value)} + /> + + + + + + + + + + + + ); +} diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/types.ts b/tgui/packages/tgui/interfaces/LibraryConsole/types.ts new file mode 100644 index 00000000000..be9b7173a4c --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/types.ts @@ -0,0 +1,63 @@ +import { BooleanLike } from 'tgui-core/react'; + +type CheckoutEntry = { + author: string; + borrower: string; + due_in_minutes: number; + id: string; + overdue: BooleanLike; + ref: string; + title: string; +}; + +type InventoryEntry = { + author: string; + ref: string; + title: string; +}; + +type Page = { + author: string; + category: string; + id: string; + title: string; +}; + +export type LibraryConsoleData = { + active_newscaster_cooldown: BooleanLike; + author: string; + bible_name: string; + bible_sprite: string; + book_id: string; + cache_author: string; + cache_content: string; + cache_title: string; + can_connect: BooleanLike; + can_db_request: BooleanLike; + category: string; + checkout_page_count: number; + checkout_page: number; + checkouts: CheckoutEntry[]; + cooldown_string: string; + default_category: string; + deity: string; + display_lore: BooleanLike; + has_cache: BooleanLike; + has_checkout: BooleanLike; + has_inventory: BooleanLike; + has_scanner: BooleanLike; + inventory_page_count: number; + inventory_page: number; + inventory: InventoryEntry[]; + our_page: number; + page_count: number; + pages: Page[]; + params_changed: BooleanLike; + posters: string[]; + religion: string; + screen_state: number; + search_categories: string[]; + show_dropdown: BooleanLike; + title: string; + upload_categories: string[]; +}; diff --git a/tgui/packages/tgui/interfaces/LibraryConsole/useLibraryContext.ts b/tgui/packages/tgui/interfaces/LibraryConsole/useLibraryContext.ts new file mode 100644 index 00000000000..7cb1ead667b --- /dev/null +++ b/tgui/packages/tgui/interfaces/LibraryConsole/useLibraryContext.ts @@ -0,0 +1,15 @@ +import { createContext, Dispatch, SetStateAction, useContext } from 'react'; + +type LibraryContextType = { + checkoutBookState: [boolean, Dispatch>]; + uploadToDBState: [boolean, Dispatch>]; +}; + +export const LibraryContext = createContext({ + checkoutBookState: [false, () => {}], + uploadToDBState: [false, () => {}], +}); + +export function useLibraryContext() { + return useContext(LibraryContext); +} diff --git a/tgui/packages/tgui/interfaces/LibraryVisitor.jsx b/tgui/packages/tgui/interfaces/LibraryVisitor.jsx index 50ea9bad108..d4a10c5f34c 100644 --- a/tgui/packages/tgui/interfaces/LibraryVisitor.jsx +++ b/tgui/packages/tgui/interfaces/LibraryVisitor.jsx @@ -12,7 +12,7 @@ import { import { useBackend } from '../backend'; import { Window } from '../layouts'; -import { PageSelect } from './LibraryConsole'; +import { PageSelect } from './LibraryConsole/components/PageSelect'; export const LibraryVisitor = (props) => { return (