From c7fe8ac18e2da416e561e8969e319621dea3d1bb Mon Sep 17 00:00:00 2001
From: mcbalaam <104003807+mcbalaam@users.noreply.github.com>
Date: Thu, 28 May 2026 07:42:04 +0700
Subject: [PATCH] feat: Vote panel UI cleanup; auto-close fix (#96166)
(conflict resolved)
---
tgui/packages/tgui/interfaces/VotePanel.tsx | 403 ++++++++++----------
1 file changed, 198 insertions(+), 205 deletions(-)
diff --git a/tgui/packages/tgui/interfaces/VotePanel.tsx b/tgui/packages/tgui/interfaces/VotePanel.tsx
index 4b4ca56bf69..086f1c5f945 100644
--- a/tgui/packages/tgui/interfaces/VotePanel.tsx
+++ b/tgui/packages/tgui/interfaces/VotePanel.tsx
@@ -216,217 +216,210 @@ const ChoicesPanel = (props) => {
const { currentVote, user } = data;
return (
-
-
- {currentVote && currentVote.countMethod === VoteSystem.VOTE_SINGLE ? (
- Select one option
- ) : null}
- {currentVote &&
- currentVote.choices.length !== 0 &&
- currentVote.countMethod === VoteSystem.VOTE_SINGLE ? (
-
- {currentVote.choices.map((choice) => (
-
- c.toUpperCase())}
- textAlign="right"
- buttons={
-
- }
- >
- {user.singleSelection &&
- choice.name === user.singleSelection && (
+ <>
+ {currentVote && currentVote.countMethod === VoteSystem.VOTE_SINGLE ? (
+ Select one option
+ ) : null}
+ {currentVote &&
+ currentVote.choices.length !== 0 &&
+ currentVote.countMethod === VoteSystem.VOTE_SINGLE ? (
+
+ {currentVote.choices.map((choice) => (
+
+ c.toUpperCase())}
+ textAlign="right"
+ buttons={
+
+ }
+ >
+ {user.singleSelection &&
+ choice.name === user.singleSelection && (
)}
- {currentVote.displayStatistics || user.isLowerAdmin /* SKYRAT EDIT*/ ? `${choice.votes} Votes` : null}
-
-
-
- ))}
-
- ) : null}
- {currentVote && currentVote.countMethod === VoteSystem.VOTE_MULTI ? (
- Select any number of options
- ) : null}
- {currentVote &&
- currentVote.choices.length !== 0 &&
- currentVote.countMethod === VoteSystem.VOTE_MULTI ? (
-
- {currentVote.choices.map((choice) => (
-
- c.toUpperCase())}
- textAlign="right"
- buttons={
-
- }
- >
- {user.multiSelection &&
- // BUBBER EDIT CHANGE - Original: [user.ckey.concat(choice.name)]
- user.multiSelection[`${user.ckey}_${choice.name}`] === 1 ? (
-
- ) : null}
- {
- user.isLowerAdmin
- ? `${choice.votes} Votes`
- : '' /* SKYRAT EDIT*/
- }
-
-
-
- ))}
-
- ) : null}
- {/* BUBBER EDIT ADDITION - Ranked Choice Voting */}
- {currentVote && currentVote.countMethod === VoteSystem.VOTE_RANKED ? (
-
- Click options to rank them in order of preference. Click again to
- remove.
-
- ) : null}
- {currentVote &&
- currentVote.choices.length !== 0 &&
- currentVote.countMethod === VoteSystem.VOTE_RANKED ? (
-
- {currentVote.choices
- .map((choice) => {
- // Get all current ranks for this user
- const userRanks: Record = {};
- let maxRank = 0;
- currentVote.choices.forEach((c) => {
- const rankKey = `${user.ckey}_${c.name}`;
- const rank = user.multiSelection?.[rankKey] || 0;
- if (rank > 0) {
- userRanks[c.name] = rank;
- maxRank = Math.max(maxRank, rank);
- }
- });
-
- // Get this choice's current rank
- const rankKey = `${user.ckey}_${choice.name}`;
- const currentRank = user.multiSelection?.[rankKey] || 0;
-
- return {
- choice,
- currentRank,
- userRanks,
- maxRank,
- };
- })
- // Sort by rank (unranked at bottom)
- .sort((a, b) => {
- if (a.currentRank === 0 && b.currentRank === 0) {
- // If both unranked, sort alphabetically
- return a.choice.name.localeCompare(b.choice.name);
+ {currentVote.displayStatistics ? `${choice.votes} Votes` : null}
+
+
+
+ ))}
+
+ ) : null}
+ {currentVote && currentVote.countMethod === VoteSystem.VOTE_MULTI ? (
+ Select any number of options
+ ) : null}
+ {currentVote &&
+ currentVote.choices.length !== 0 &&
+ currentVote.countMethod === VoteSystem.VOTE_MULTI ? (
+
+ {currentVote.choices.map((choice) => (
+
+ c.toUpperCase())}
+ textAlign="right"
+ buttons={
+
}
- if (a.currentRank === 0) return 1; // a is unranked, move to bottom
- if (b.currentRank === 0) return -1; // b is unranked, move to bottom
- return a.currentRank - b.currentRank; // sort by rank
- })
- .map(({ choice, currentRank, userRanks, maxRank }) => {
- // Function to get button text
- const getButtonText = () => {
- if (currentRank === 0) {
- return 'Vote';
- }
- return `Choice #${currentRank}`;
- };
+ >
+ {user.multiSelection &&
+ user.multiSelection[user.ckey.concat(choice.name)] === 1 ? (
+
+ ) : null}
+ {choice.votes} Votes
+
+
+
+ ))}
+
+ ) : null}
+ {/* BUBBER EDIT ADDITION - Ranked Choice Voting */}
+ {currentVote && currentVote.countMethod === VoteSystem.VOTE_RANKED ? (
+
+ Click options to rank them in order of preference. Click again to
+ remove.
+
+ ) : null}
+ {currentVote &&
+ currentVote.choices.length !== 0 &&
+ currentVote.countMethod === VoteSystem.VOTE_RANKED ? (
+
+ {currentVote.choices
+ .map((choice) => {
+ // Get all current ranks for this user
+ const userRanks: Record = {};
+ let maxRank = 0;
+ currentVote.choices.forEach((c) => {
+ const rankKey = `${user.ckey}_${c.name}`;
+ const rank = user.multiSelection?.[rankKey] || 0;
+ if (rank > 0) {
+ userRanks[c.name] = rank;
+ maxRank = Math.max(maxRank, rank);
+ }
+ });
- // Function to handle vote click
- const handleVoteClick = () => {
- if (currentRank > 0) {
- // Remove this rank and shift others up
- const newRanks: Record = {};
- Object.entries(userRanks).forEach(
- ([name, rank]: [string, number]) => {
- if (name === choice.name) {
- return; // Skip this one as we're removing it
- }
- if (rank > currentRank) {
- newRanks[name] = rank - 1; // Shift up
- } else {
- newRanks[name] = rank; // Keep same
- }
- },
- );
- // Send all rank updates
- Object.entries(newRanks).forEach(
- ([name, newRank]: [string, number]) => {
- act('voteRanked', {
- voteOption: name,
- voteRank: newRank,
- });
- },
- );
- // Remove this rank
- act('voteRanked', {
- voteOption: choice.name,
- voteRank: 0,
- });
- } else {
- // Add as next rank
- act('voteRanked', {
- voteOption: choice.name,
- voteRank: maxRank + 1,
- });
- }
- };
+ // Get this choice's current rank
+ const rankKey = `${user.ckey}_${choice.name}`;
+ const currentRank = user.multiSelection?.[rankKey] || 0;
- return (
-
- c.toUpperCase())}
- textAlign="right"
- buttons={
-
+ return {
+ choice,
+ currentRank,
+ userRanks,
+ maxRank,
+ };
+ })
+ // Sort by rank (unranked at bottom)
+ .sort((a, b) => {
+ if (a.currentRank === 0 && b.currentRank === 0) {
+ // If both unranked, sort alphabetically
+ return a.choice.name.localeCompare(b.choice.name);
+ }
+ if (a.currentRank === 0) return 1; // a is unranked, move to bottom
+ if (b.currentRank === 0) return -1; // b is unranked, move to bottom
+ return a.currentRank - b.currentRank; // sort by rank
+ })
+ .map(({ choice, currentRank, userRanks, maxRank }) => {
+ // Function to get button text
+ const getButtonText = () => {
+ if (currentRank === 0) {
+ return 'Vote';
+ }
+ return `Choice #${currentRank}`;
+ };
+
+ // Function to handle vote click
+ const handleVoteClick = () => {
+ if (currentRank > 0) {
+ // Remove this rank and shift others up
+ const newRanks: Record = {};
+ Object.entries(userRanks).forEach(
+ ([name, rank]: [string, number]) => {
+ if (name === choice.name) {
+ return; // Skip this one as we're removing it
}
- >
- {currentVote.displayStatistics || user.isLowerAdmin
- ? `${choice.votes} Votes`
- : null}
-
-
-
- );
- })}
-
- ) : null}
- {/* BUBBER EDIT ADDITION END */}
- {currentVote ? null : No vote active!}
-
-
+ if (rank > currentRank) {
+ newRanks[name] = rank - 1; // Shift up
+ } else {
+ newRanks[name] = rank; // Keep same
+ }
+ },
+ );
+ // Send all rank updates
+ Object.entries(newRanks).forEach(
+ ([name, newRank]: [string, number]) => {
+ act('voteRanked', {
+ voteOption: name,
+ voteRank: newRank,
+ });
+ },
+ );
+ // Remove this rank
+ act('voteRanked', {
+ voteOption: choice.name,
+ voteRank: 0,
+ });
+ } else {
+ // Add as next rank
+ act('voteRanked', {
+ voteOption: choice.name,
+ voteRank: maxRank + 1,
+ });
+ }
+ };
+
+ return (
+
+ c.toUpperCase())}
+ textAlign="right"
+ buttons={
+
+ }
+ >
+ {currentVote.displayStatistics || user.isLowerAdmin
+ ? `${choice.votes} Votes`
+ : null}
+
+
+
+ );
+ })}
+
+ ) : null}
+ {/* BUBBER EDIT ADDITION END */}
+ {currentVote ? null : No vote active!}
+ >
);
};