fix
This commit is contained in:
@@ -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<string, { owned: number; cost: number }>;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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<AdminMessage[]>([]);
|
||||
const [isAdmin, setIsAdmin] = useState(false);
|
||||
const [selectedUser, setSelectedUser] = useState<UserState & { id: string } | null>(null);
|
||||
const [clicks, setClicks] = useState(0);
|
||||
const [autoClickRate, setAutoClickRate] = useState(0);
|
||||
const [upgrades, setUpgrades] = useState<Record<string, { owned: number; cost: number }>>({});
|
||||
|
||||
// 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 (
|
||||
<div className="flex items-center justify-center min-h-screen bg-gray-900 text-white">
|
||||
@@ -111,6 +122,80 @@ const AdminPage: React.FC = () => {
|
||||
</div>
|
||||
|
||||
<div className="p-6 bg-gray-800 rounded-lg shadow-lg">
|
||||
<h2 className="text-2xl font-semibold mb-4">User Management</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold mb-4">Users</h3>
|
||||
<div className="max-h-96 overflow-y-auto bg-gray-700 p-4 rounded-md">
|
||||
<ul>
|
||||
{gameState &&
|
||||
Object.entries(gameState.users).map(([id, user]) => (
|
||||
<li
|
||||
key={id}
|
||||
className={`cursor-pointer p-3 rounded-md mb-2 ${selectedUser?.id === id ? 'bg-blue-500' : 'bg-gray-600'}`}
|
||||
onClick={() => {
|
||||
setSelectedUser({ id, ...user });
|
||||
setClicks(user.clicks);
|
||||
setUpgrades(user.upgrades);
|
||||
}}
|
||||
>
|
||||
{user.name}
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
{selectedUser && (
|
||||
<div>
|
||||
<h3 className="text-xl font-semibold mb-4">Edit User</h3>
|
||||
<div className="mb-4">
|
||||
<label htmlFor="clicks" className="block text-lg font-medium mb-2">
|
||||
Clicks:
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
id="clicks"
|
||||
className="w-full p-3 rounded-md bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
value={clicks}
|
||||
onChange={(e) => setClicks(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<label htmlFor="autoClickRate" className="block text-lg font-medium mb-2">
|
||||
Auto Click Rate:
|
||||
</label>
|
||||
<input
|
||||
type="number"
|
||||
id="autoClickRate"
|
||||
className="w-full p-3 rounded-md bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
value={autoClickRate}
|
||||
onChange={(e) => setAutoClickRate(Number(e.target.value))}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<label htmlFor="upgrades" className="block text-lg font-medium mb-2">
|
||||
Upgrades (JSON):
|
||||
</label>
|
||||
<textarea
|
||||
id="upgrades"
|
||||
className="w-full p-3 rounded-md bg-gray-700 border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500"
|
||||
rows={10}
|
||||
value={JSON.stringify(upgrades, null, 2)}
|
||||
onChange={(e) => setUpgrades(JSON.parse(e.target.value))}
|
||||
></textarea>
|
||||
</div>
|
||||
<button
|
||||
onClick={handleEditUser}
|
||||
className="w-full bg-green-600 hover:bg-green-700 text-white font-bold py-3 px-6 rounded-md transition duration-300 ease-in-out"
|
||||
>
|
||||
Save Changes
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="p-6 bg-gray-800 rounded-lg shadow-lg mt-8">
|
||||
<h2 className="text-2xl font-semibold mb-4">Received Admin Messages</h2>
|
||||
<div className="max-h-64 overflow-y-auto bg-gray-700 p-4 rounded-md">
|
||||
{receivedMessages.length === 0 ? (
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user