Skip to content

Commit

Permalink
Re-add crew manifest, language menu, and tracked playtime TGUI interf…
Browse files Browse the repository at this point in the history
…aces
  • Loading branch information
Koshenko committed May 18, 2024
1 parent 8c381ce commit 02334af
Show file tree
Hide file tree
Showing 3 changed files with 324 additions and 0 deletions.
98 changes: 98 additions & 0 deletions tgui/packages/tgui/interfaces/CrewManifest.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { classes } from 'common/react';

import { useBackend } from '../backend';
import { Icon, Section, Table, Tooltip } from '../components';
import { Window } from '../layouts';

const commandJobs = [
'Head of Personnel',
'Head of Security',
'Chief Engineer',
'Research Director',
'Chief Medical Officer',
];

export const CrewManifest = (props) => {
const {
data: { manifest, positions },
} = useBackend();

return (
<Window
title="Souls of the Wasteland"
width={350}
height={500}
theme="mojavesun"
>
<Window.Content scrollable>
{Object.entries(manifest).map(([dept, crew]) => (
<Section
className={'CrewManifest--' + dept}
key={dept}
title={
dept +
(dept !== 'Misc'
? ` (${positions[dept].open} positions open)`
: '')
}
>
<Table>
{Object.entries(crew).map(([crewIndex, crewMember]) => (
<Table.Row key={crewIndex}>
<Table.Cell className={'CrewManifest__Cell'}>
{crewMember.name}
</Table.Cell>
<Table.Cell
className={classes([
'CrewManifest__Cell',
'CrewManifest__Icons',
])}
collapsing
>
{positions[dept].exceptions.includes(crewMember.rank) && (
<Tooltip content="No position limit" position="bottom">
<Icon className="CrewManifest__Icon" name="infinity" />
</Tooltip>
)}
{crewMember.rank === 'Captain' && (
<Tooltip content="Captain" position="bottom">
<Icon
className={classes([
'CrewManifest__Icon',
'CrewManifest__Icon--Command',
])}
name="star"
/>
</Tooltip>
)}
{commandJobs.includes(crewMember.rank) && (
<Tooltip content="Member of command" position="bottom">
<Icon
className={classes([
'CrewManifest__Icon',
'CrewManifest__Icon--Command',
'CrewManifest__Icon--Chevron',
])}
name="chevron-up"
/>
</Tooltip>
)}
</Table.Cell>
<Table.Cell
className={classes([
'CrewManifest__Cell',
'CrewManifest__Cell--Rank',
])}
collapsing
>
{crewMember.rank}
</Table.Cell>
</Table.Row>
))}
</Table>
</Section>
))}
</Window.Content>
</Window>
);
};
111 changes: 111 additions & 0 deletions tgui/packages/tgui/interfaces/LanguageMenu.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { useBackend } from '../backend';
import { Button, LabeledList, Section } from '../components';
import { Window } from '../layouts';

export const LanguageMenu = (props) => {
const { act, data } = useBackend();
const {
admin_mode,
is_living,
omnitongue,
languages = [],
unknown_languages = [],
} = data;
return (
<Window title="Language Menu" width={700} height={600}>
<Window.Content scrollable>
<Section title="Known Languages">
<LabeledList>
{languages.map((language) => (
<LabeledList.Item
key={language.name}
label={language.name}
buttons={
<>
{!!is_living && (
<Button
content={
language.is_default
? 'Default Language'
: 'Select as Default'
}
disabled={!language.can_speak}
selected={language.is_default}
onClick={() =>
act('select_default', {
language_name: language.name,
})
}
/>
)}
{!!admin_mode && (
<>
<Button
content="Grant"
onClick={() =>
act('grant_language', {
language_name: language.name,
})
}
/>
<Button
content="Remove"
onClick={() =>
act('remove_language', {
language_name: language.name,
})
}
/>
</>
)}
</>
}
>
{language.desc} Key: ,{language.key}{' '}
{language.can_understand
? 'Can understand.'
: 'Cannot understand.'}{' '}
{language.can_speak ? 'Can speak.' : 'Cannot speak.'}
</LabeledList.Item>
))}
</LabeledList>
</Section>
{!!admin_mode && (
<Section
title="Unknown Languages"
buttons={
<Button
content={'Omnitongue ' + (omnitongue ? 'Enabled' : 'Disabled')}
selected={omnitongue}
onClick={() => act('toggle_omnitongue')}
/>
}
>
<LabeledList>
{unknown_languages.map((language) => (
<LabeledList.Item
key={language.name}
label={language.name}
buttons={
<Button
content="Grant"
onClick={() =>
act('grant_language', {
language_name: language.name,
})
}
/>
}
>
{language.desc} Key: ,{language.key}{' '}
{!!language.shadow && '(gained from mob)'}{' '}
{language.can_speak ? 'Can speak.' : 'Cannot speak.'}
</LabeledList.Item>
))}
</LabeledList>
</Section>
)}
</Window.Content>
</Window>
);
};
115 changes: 115 additions & 0 deletions tgui/packages/tgui/interfaces/TrackedPlaytime.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { sortBy } from 'common/collections';

import { useBackend } from '../backend';
import { Box, Button, Flex, ProgressBar, Section, Table } from '../components';
import { Window } from '../layouts';

const JOB_REPORT_MENU_FAIL_REASON_TRACKING_DISABLED = 1;
const JOB_REPORT_MENU_FAIL_REASON_NO_RECORDS = 2;

const sortByPlaytime = sortBy(([_, playtime]) => -playtime);

const PlaytimeSection = (props) => {
const { playtimes } = props;

const sortedPlaytimes = sortByPlaytime(Object.entries(playtimes)).filter(
(entry) => entry[1],
);

if (!sortedPlaytimes.length) {
return 'No recorded playtime hours for this section.';
}

const mostPlayed = sortedPlaytimes[0][1];
return (
<Table>
{sortedPlaytimes.map(([jobName, playtime]) => {
const ratio = playtime / mostPlayed;
return (
<Table.Row key={jobName}>
<Table.Cell
collapsing
p={0.5}
style={{
'vertical-align': 'middle',
}}
>
<Box align="right">{jobName}</Box>
</Table.Cell>
<Table.Cell>
<ProgressBar maxValue={mostPlayed} value={playtime}>
<Flex>
<Flex.Item width={`${ratio * 100}%`} />
<Flex.Item>
{(playtime / 60).toLocaleString(undefined, {
minimumFractionDigits: 1,
maximumFractionDigits: 1,
})}
h
</Flex.Item>
</Flex>
</ProgressBar>
</Table.Cell>
</Table.Row>
);
})}
</Table>
);
};

export const TrackedPlaytime = (props) => {
const { act, data } = useBackend();
const {
failReason,
jobPlaytimes,
specialPlaytimes,
exemptStatus,
isAdmin,
livingTime,
ghostTime,
adminTime,
} = data;
return (
<Window title="Tracked Playtime" width={550} height={650}>
<Window.Content scrollable>
{(failReason &&
((failReason === JOB_REPORT_MENU_FAIL_REASON_TRACKING_DISABLED && (
<Box>This server has disabled tracking.</Box>
)) ||
(failReason === JOB_REPORT_MENU_FAIL_REASON_NO_RECORDS && (
<Box>You have no records.</Box>
)))) || (
<Box>
<Section title="Total">
<PlaytimeSection
playtimes={{
Ghost: ghostTime,
Living: livingTime,
Admin: adminTime,
}}
/>
</Section>
<Section
title="Jobs"
buttons={
!!isAdmin && (
<Button.Checkbox
checked={!!exemptStatus}
onClick={() => act('toggle_exempt')}
>
Job Playtime Exempt
</Button.Checkbox>
)
}
>
<PlaytimeSection playtimes={jobPlaytimes} />
</Section>
<Section title="Special">
<PlaytimeSection playtimes={specialPlaytimes} />
</Section>
</Box>
)}
</Window.Content>
</Window>
);
};

0 comments on commit 02334af

Please sign in to comment.