From 79c38efc943b2a66c69fa1d5d796f9b9683727f7 Mon Sep 17 00:00:00 2001 From: Arjun S <37960163+arjunindia@users.noreply.github.com> Date: Mon, 4 Aug 2025 08:56:13 +0000 Subject: [PATCH] fix --- party/index.ts | 33 +++++++++++++- src/components/AdminPage.tsx | 87 +++++++++++++++++++++++++++++++++++- src/hooks/usePartyKit.ts | 21 ++++++++- src/types.ts | 1 + 4 files changed, 137 insertions(+), 5 deletions(-) diff --git a/party/index.ts b/party/index.ts index 833639d..45d3c13 100644 --- a/party/index.ts +++ b/party/index.ts @@ -74,7 +74,14 @@ interface UserJoinMessage extends AuthenticatedMessage { type: 'user-join'; } -type Message = ClickMessage | PurchaseUpgradeMessage | ApplyMultiplierBonusMessage | UserJoinMessage | AdminBroadcastMessage; // Updated Message type +interface EditUserMessage extends AuthenticatedMessage { + type: 'edit-user'; + targetUserId: string; + clicks: number; + upgrades: Record; +} + +type Message = ClickMessage | PurchaseUpgradeMessage | ApplyMultiplierBonusMessage | UserJoinMessage | AdminBroadcastMessage | EditUserMessage; // Updated Message type const UPGRADES: Upgrade[] = [ { @@ -369,11 +376,29 @@ export default class GameServer implements Party.Server { console.warn(`Unauthorized admin broadcast attempt from ${currentUserId}.`); } break; + case 'edit-user': + if (isAuthenticated && currentUserId === this.party.env.CLERK_ADMIN_USERID) { + this.handleEditUser(data); + } else { + console.warn(`Unauthorized edit user attempt from ${currentUserId}.`); + } + break; } this.broadcast(); } + handleEditUser(data: EditUserMessage) { + const { targetUserId, clicks, upgrades } = data; + const userState = this.gameState.users[targetUserId]; + + if (userState) { + userState.clicks = clicks; + userState.upgrades = upgrades; + this.updateGameMultipliers(targetUserId); + } + } + // handleUserJoin is now fully integrated into onMessage and can be removed or simplified. // Removing it as its logic is now directly in onMessage. // handleUserJoin(data: UserJoinMessage) { @@ -475,7 +500,7 @@ export default class GameServer implements Party.Server { } } - updateGameMultipliers(userId: string) { + updateGameMultipliers(userId: string, autoClickRateOverride?: number) { const userState = this.gameState.users[userId]; if (!userState) return; @@ -494,6 +519,10 @@ export default class GameServer implements Party.Server { } }); + if (autoClickRateOverride !== undefined) { + userState.autoClickRate = autoClickRateOverride; + } + this.setupAutoClicker(); } diff --git a/src/components/AdminPage.tsx b/src/components/AdminPage.tsx index 4097afd..7269c57 100644 --- a/src/components/AdminPage.tsx +++ b/src/components/AdminPage.tsx @@ -1,6 +1,7 @@ import React, { useState, useEffect } from 'react'; import { useUser } from '@clerk/clerk-react'; import { usePartyKit } from '../hooks/usePartyKit'; +import { UserState } from '../types'; interface AdminMessage { type: 'admin-message'; @@ -10,11 +11,15 @@ interface AdminMessage { const AdminPage: React.FC = () => { const { user } = useUser(); - const { sendMessage, lastMessage, getToken } = usePartyKit(); + const { sendMessage, lastMessage, getToken, gameState, editUser } = usePartyKit(); const [broadcastMessage, setBroadcastMessage] = useState(''); const [targetUserId, setTargetUserId] = useState(''); const [receivedMessages, setReceivedMessages] = useState([]); const [isAdmin, setIsAdmin] = useState(false); + const [selectedUser, setSelectedUser] = useState(null); + const [clicks, setClicks] = useState(0); + const [autoClickRate, setAutoClickRate] = useState(0); + const [upgrades, setUpgrades] = useState>({}); // Replace with your actual admin user ID from .env or similar const CLERK_ADMIN_USERID = import.meta.env.VITE_CLERK_ADMIN_USERID; @@ -62,6 +67,12 @@ const AdminPage: React.FC = () => { } }; + const handleEditUser = () => { + if (selectedUser) { + editUser(selectedUser.id, clicks, autoClickRate, upgrades); + } + }; + if (!isAdmin) { return (
@@ -111,6 +122,80 @@ const AdminPage: React.FC = () => {
+

User Management

+
+
+

Users

+
+
    + {gameState && + Object.entries(gameState.users).map(([id, user]) => ( +
  • { + setSelectedUser({ id, ...user }); + setClicks(user.clicks); + setUpgrades(user.upgrades); + }} + > + {user.name} +
  • + ))} +
+
+
+ {selectedUser && ( +
+

Edit User

+
+ + setClicks(Number(e.target.value))} + /> +
+
+ + setAutoClickRate(Number(e.target.value))} + /> +
+
+ + +
+ +
+ )} +
+
+ +

Received Admin Messages

{receivedMessages.length === 0 ? ( diff --git a/src/hooks/usePartyKit.ts b/src/hooks/usePartyKit.ts index e8b697e..0c85296 100644 --- a/src/hooks/usePartyKit.ts +++ b/src/hooks/usePartyKit.ts @@ -3,7 +3,7 @@ import PartySocket from 'partysocket'; import { GameState } from '../types'; import { useAuth, useUser } from '@clerk/clerk-react'; -const PARTY_HOST = import.meta.env.DEV ? 'localhost:1999' : 'bozo-clicker.arjunindia.partykit.dev'; +const PARTY_HOST = import.meta.env.DEV ? 'https://solid-rotary-phone-pg69xw5vj7rc7r55-1999.app.github.dev' : 'bozo-clicker.arjunindia.partykit.dev'; export function usePartyKit() { const { getToken, isLoaded, isSignedIn } = useAuth(); @@ -120,6 +120,22 @@ export function usePartyKit() { const currentUserId = isSignedIn && user ? user.id : undefined; const currentUserName = isSignedIn && user ? (user.username || user.fullName || user.emailAddresses[0].emailAddress) : undefined; + const editUser = useCallback(async (targetUserId: string, clicks: number, autoClickRate: number, upgrades: any) => { + if (socket && isSignedIn && user) { + const token = await getToken(); + socket.send(JSON.stringify({ + type: 'edit-user', + token, + userId: user.id, + userName: user.username || user.fullName || user.emailAddresses[0].emailAddress, + targetUserId, + clicks, + autoClickRate, + upgrades + })); + } + }, [socket, isSignedIn, user, getToken]); + return { gameState, sendClick, @@ -129,6 +145,7 @@ export function usePartyKit() { lastMessage, // Expose lastMessage userId: currentUserId, userName: currentUserName, - getToken // Expose getToken + getToken, // Expose getToken + editUser, }; } diff --git a/src/types.ts b/src/types.ts index 9c479c2..bac136e 100644 --- a/src/types.ts +++ b/src/types.ts @@ -29,6 +29,7 @@ export interface Upgrade { mascotTiers?: MascotTier[]; // New: for defining mascot tiers for friendBoost oneTime?: boolean; // New: Indicates if the upgrade is a one-time purchase newsTitles?: string[]; // New: Array of news titles for the news upgrade + youtubeId?: string; // New: YouTube ID for the upgrade } export interface MascotTier {