Skip to content

Commit 066f30b

Browse files
committed
Fiixed
1 parent bdbce61 commit 066f30b

File tree

4 files changed

+124
-57
lines changed

4 files changed

+124
-57
lines changed

veto-board/src/components/BanPhase.jsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -101,35 +101,35 @@ export default function BanPhase({ series, onSuccess }) {
101101
// After you've loaded the combos, filter them before displaying in UI
102102
const filteredAvailable = useMemo(() => {
103103
if (!available || !available.length) return [];
104-
104+
105105
return available.map(group => {
106106
// Clone the group
107107
const newGroup = {...group};
108-
109-
// Filter the combos based on ban/pick status
108+
109+
// Filter the combos based on exact combo ban/pick status
110110
newGroup.combos = (group.combos || []).filter(combo => {
111111
const mapId = Number(combo.map_id);
112112
const modeId = Number(group.mode_id);
113-
114-
// Skip if map is picked for any mode
115-
if (pickedMapIds.has(mapId)) {
113+
114+
if (!mapId || !modeId) return false;
115+
116+
// Build exact combo key and check explicit combo bans/picks
117+
const comboKey = `${mapId}:${modeId}`;
118+
if (bannedCombinations.has(comboKey) || pickedCombinations.has(comboKey)) {
116119
return false;
117120
}
118-
119-
// For objective, check combination bans
120-
if (isObjectiveCombo) {
121-
const comboKey = `${mapId}:${modeId}`;
122-
return !bannedCombinations.has(comboKey);
123-
}
124-
// For slayer, check slayer-specific bans
125-
else {
126-
return !slayerBannedMapIds.has(mapId);
121+
122+
// For slayer flow, also respect map-level slayer bans (map-only bans)
123+
if (!isObjectiveCombo && slayerBannedMapIds.has(mapId)) {
124+
return false;
127125
}
126+
127+
return true;
128128
});
129-
129+
130130
return newGroup;
131131
}).filter(group => group.combos && group.combos.length > 0);
132-
}, [available, isObjectiveCombo, bannedCombinations, slayerBannedMapIds, pickedMapIds]);
132+
}, [available, isObjectiveCombo, bannedCombinations, slayerBannedMapIds, pickedCombinations]);
133133

134134
return (
135135
<div className="bg-gray-800 text-white p-4 mt-4 rounded space-y-4">

veto-board/src/components/ComboPicker.jsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,18 @@ export default function ComboPicker({
4747
<div className="flex flex-wrap gap-2">
4848
{group.combos.map((combo, idx) => {
4949
const mapId = normMapId(combo);
50-
const modeId = normModeId(combo);
50+
// prefer combo.mode, fall back to group.mode / group.modeId
51+
const modeId =
52+
normModeId(combo) ??
53+
normModeId(group) ??
54+
(typeof group.modeId === "number" ? group.modeId : null) ??
55+
(typeof group.mode === "number" ? group.mode : null);
5156
return (
5257
<button
53-
key={`${mapId}-${modeId}-${idx}`}
58+
key={`${mapId}-${modeId ?? "no-mode"}-${idx}`}
5459
onClick={() => onPick && onPick(mapId, modeId)}
55-
disabled={loading || !mapId || !modeId}
60+
// disable when no map or no explicit mode id (null/undefined)
61+
disabled={loading || !mapId || modeId == null}
5662
className="bg-blue-600 hover:bg-blue-700 disabled:opacity-50 px-3 py-2 rounded text-sm"
5763
>
5864
{mapLabel(combo)}

veto-board/src/index.css

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ body {
1616
-moz-osx-font-smoothing: grayscale;
1717
}
1818

19-
/* nicer scrollbars for the messages pane */
19+
/* Mobile-friendly scrollbars */
2020
.custom-scroll::-webkit-scrollbar {
21-
width: 10px;
21+
width: 8px;
2222
}
2323

2424
.custom-scroll::-webkit-scrollbar-track {
@@ -28,11 +28,60 @@ body {
2828
.custom-scroll::-webkit-scrollbar-thumb {
2929
background: rgba(255, 255, 255, 0.06);
3030
border-radius: 9999px;
31-
border: 3px solid transparent;
31+
border: 2px solid transparent;
3232
background-clip: padding-box;
3333
}
3434

35-
/* small card shadow in dark */
35+
/* Mobile touch targets */
36+
@media (max-width: 768px) {
37+
.custom-scroll::-webkit-scrollbar {
38+
width: 6px;
39+
}
40+
41+
/* Ensure minimum touch target size */
42+
button {
43+
min-height: 44px;
44+
}
45+
46+
/* Improve tap highlights */
47+
button, a, [role="button"] {
48+
-webkit-tap-highlight-color: rgba(59, 130, 246, 0.1);
49+
}
50+
}
51+
52+
/* Card shadows */
3653
.shadow-lg {
3754
box-shadow: 0 6px 18px rgba(2, 6, 23, 0.6);
55+
}
56+
57+
/* Mobile-specific utilities */
58+
@media (max-width: 640px) {
59+
/* Reduce padding on small screens */
60+
.mobile-reduced-padding {
61+
padding: 0.75rem !important;
62+
}
63+
64+
/* Stack flex items on mobile */
65+
.mobile-stack {
66+
flex-direction: column !important;
67+
}
68+
69+
/* Full width on mobile */
70+
.mobile-full-width {
71+
width: 100% !important;
72+
}
73+
}
74+
75+
/* Prevent horizontal scrolling */
76+
html, body {
77+
overflow-x: hidden;
78+
}
79+
80+
/* Ensure text doesn't overflow */
81+
.truncate-mobile {
82+
@media (max-width: 640px) {
83+
overflow: hidden;
84+
text-overflow: ellipsis;
85+
white-space: nowrap;
86+
}
3887
}

veto-board/src/lib/bans.js

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,15 @@
55
export const getMapId = (x) =>
66
x?.map_id || x?.map?.id || x?.map || x?.id || x?.pk || null;
77

8-
export const getModeId = (x) =>
9-
x?.mode_id || x?.mode?.id || x?.mode || null;
8+
export const getModeId = (x) =>
9+
// prefer explicit objective_mode fields, then generic mode fields
10+
x?.objective_mode_id ||
11+
x?.objective_mode ||
12+
x?.mode_id ||
13+
x?.mode?.id ||
14+
x?.mode ||
15+
x?.modeId ||
16+
null;
1017

1118
export const getModeName = (x) => {
1219
if (!x) return "";
@@ -15,21 +22,22 @@ export const getModeName = (x) => {
1522
};
1623

1724
export const isSlayerMode = (modeVal) => {
18-
if (!modeVal) return false;
19-
20-
// Check for mode ID 6 (Slayer)
21-
if (modeVal === 6 || modeVal === "6") return true;
22-
23-
// Check string values
25+
if (modeVal == null) return false;
26+
// Prefer numeric mode id if available (mode.id, mode_id, or raw value)
27+
const parsed = Number(modeVal?.id ?? modeVal?.mode_id ?? modeVal);
28+
if (!isNaN(parsed) && parsed === 6) return true;
29+
// Fallback: only treat explicit string mentions of "slayer" as Slayer
2430
if (typeof modeVal === "string") {
25-
return modeVal.toLowerCase() === "slayer" || modeVal.toLowerCase().includes("slayer");
31+
const s = modeVal.toLowerCase();
32+
return s === "slayer" || s.includes("slayer");
2633
}
27-
28-
// Check name property
29-
const name = modeVal.name || modeVal.mode_name || modeVal.mode || "";
30-
return name.toLowerCase() === "slayer" || name.toLowerCase().includes("slayer");
34+
// If object has a name-like property, check it safely
35+
const name = (typeof modeVal?.name === "string" && modeVal.name) ||
36+
(typeof modeVal?.mode_name === "string" && modeVal.mode_name) ||
37+
"";
38+
return name.toLowerCase().includes("slayer");
3139
};
32-
40+
3341
export function processBansAndPicks(actions) {
3442
const bans = actions?.filter(a => a.action_type === "BAN") || [];
3543
const picks = actions?.filter(a => a.action_type === "PICK") || [];
@@ -48,15 +56,18 @@ export function processBansAndPicks(actions) {
4856

4957
console.log(`[DEBUG] Processing ban:`, ban);
5058

51-
// FIXED: Prioritize 'kind' field, then fallback to mode checks
52-
const isSlayerBan =
53-
ban.kind === "SLAYER_MAP" ||
54-
(ban.mode_id === 6) ||
55-
(ban.mode === "Slayer") ||
56-
(ban.mode_name === "Slayer") ||
57-
isSlayerMode(ban.mode) ||
58-
isSlayerMode(ban.mode_name);
59-
59+
// Determine mode id using helper, then decide if this is a Slayer ban.
60+
const banModeId = Number(getModeId(ban));
61+
62+
// If kind explicitly indicates objective, trust it and never treat as Slayer.
63+
const kindStr = typeof ban.kind === "string" ? ban.kind.toUpperCase() : "";
64+
const isObjectiveKind = kindStr.includes("OBJECTIVE");
65+
// Only treat numeric modeId === 6 as Slayer when kind is absent/ambiguous
66+
const isSlayerBan = ban.kind === "SLAYER_MAP" || (!isObjectiveKind && banModeId === 6);
67+
if (banModeId === 6 && isObjectiveKind) {
68+
console.warn(`[WARN] Ban has mode=6 but kind=${ban.kind}; treating as OBJECTIVE_COMBO (defensive)`, ban);
69+
}
70+
6071
console.log(`[DEBUG] Map ${ban.map} (ID: ${mapId}) - kind: ${ban.kind}, isSlayerBan: ${isSlayerBan}`);
6172

6273
if (isSlayerBan) {
@@ -75,21 +86,22 @@ export function processBansAndPicks(actions) {
7586
for (const pick of picks) {
7687
const mapId = Number(getMapId(pick));
7788
if (!mapId) continue;
78-
89+
7990
pickedMapIds.add(mapId);
80-
91+
8192
const modeId = Number(getModeId(pick));
8293
if (modeId) {
8394
pickedCombinations.add(`${mapId}:${modeId}`);
8495
}
85-
86-
const isSlayerPick =
87-
pick.kind === "SLAYER_MAP" ||
88-
pick.slot_type === "SLAYER" ||
89-
(pick.mode_id === 6) ||
90-
isSlayerMode(pick.mode) ||
91-
isSlayerMode(pick.mode_name);
92-
96+
97+
const pickModeId = Number(getModeId(pick));
98+
const pickKindStr = typeof pick.kind === "string" ? pick.kind.toUpperCase() : "";
99+
const pickIsObjectiveKind = pickKindStr.includes("OBJECTIVE");
100+
const isSlayerPick = pick.kind === "SLAYER_MAP" || (!pickIsObjectiveKind && pickModeId === 6);
101+
if (pickModeId === 6 && pickIsObjectiveKind) {
102+
console.warn(`[WARN] Pick has mode=6 but kind=${pick.kind}; treating as OBJECTIVE (defensive)`, pick);
103+
}
104+
93105
if (isSlayerPick) {
94106
slayerPickedMapIds.add(mapId);
95107
console.log(`[DEBUG] Classified as SLAYER pick: ${pick.map}`);

0 commit comments

Comments
 (0)