forked from CSGOWTF/csgowtf
Convert the players page and related components from DaisyUI to the custom neon design system, matching the landing page and matches page visual style. Adds decorative blur orbs, neon glow effects, and consistent color semantics across PlayerCard, RecentPlayers, and TrackPlayerModal components. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
178 lines
4.9 KiB
Svelte
178 lines
4.9 KiB
Svelte
<script lang="ts">
|
|
import { createEventDispatcher } from 'svelte';
|
|
import { Info, AlertCircle, Loader2 } from 'lucide-svelte';
|
|
import Modal from '$lib/components/ui/Modal.svelte';
|
|
import { playersAPI } from '$lib/api/players';
|
|
import { toast } from '$lib/stores/toast';
|
|
|
|
interface Props {
|
|
playerId: string;
|
|
playerName: string;
|
|
isTracked: boolean;
|
|
open: boolean;
|
|
ontracked?: () => void;
|
|
onuntracked?: () => void;
|
|
}
|
|
|
|
let {
|
|
playerId,
|
|
playerName,
|
|
isTracked,
|
|
open = $bindable(),
|
|
ontracked,
|
|
onuntracked
|
|
}: Props = $props();
|
|
|
|
const dispatch = createEventDispatcher();
|
|
|
|
let authCode = $state('');
|
|
let isLoading = $state(false);
|
|
let error = $state('');
|
|
|
|
async function handleTrack() {
|
|
if (!authCode.trim()) {
|
|
error = 'Auth code is required';
|
|
return;
|
|
}
|
|
|
|
isLoading = true;
|
|
error = '';
|
|
|
|
try {
|
|
await playersAPI.trackPlayer(playerId, authCode);
|
|
toast.success('Player tracking activated successfully!');
|
|
open = false;
|
|
dispatch('tracked');
|
|
ontracked?.();
|
|
} catch (err: unknown) {
|
|
error = err instanceof Error ? err.message : 'Failed to track player';
|
|
toast.error(error);
|
|
} finally {
|
|
isLoading = false;
|
|
}
|
|
}
|
|
|
|
async function handleUntrack() {
|
|
isLoading = true;
|
|
error = '';
|
|
|
|
try {
|
|
await playersAPI.untrackPlayer(playerId);
|
|
toast.success('Player tracking removed successfully');
|
|
open = false;
|
|
dispatch('untracked');
|
|
onuntracked?.();
|
|
} catch (err: unknown) {
|
|
error = err instanceof Error ? err.message : 'Failed to untrack player';
|
|
toast.error(error);
|
|
} finally {
|
|
isLoading = false;
|
|
}
|
|
}
|
|
|
|
function handleClose() {
|
|
open = false;
|
|
authCode = '';
|
|
error = '';
|
|
}
|
|
</script>
|
|
|
|
<Modal bind:open onClose={handleClose} title={isTracked ? 'Untrack Player' : 'Track Player'}>
|
|
<div class="space-y-4">
|
|
<!-- Info Alert -->
|
|
<div class="flex items-start gap-3 rounded-lg border border-neon-blue/30 bg-neon-blue/10 p-4">
|
|
<Info class="h-5 w-5 shrink-0 text-neon-blue" />
|
|
<div class="text-sm text-neon-blue">
|
|
{#if isTracked}
|
|
<p>
|
|
Remove <strong class="font-semibold">{playerName}</strong> from automatic match tracking.
|
|
</p>
|
|
{:else}
|
|
<p>
|
|
Add <strong class="font-semibold">{playerName}</strong> to the tracking system to automatically
|
|
fetch new matches.
|
|
</p>
|
|
{/if}
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Auth Code Input (only for tracking, untrack doesn't need auth) -->
|
|
{#if !isTracked}
|
|
<div class="space-y-2">
|
|
<label class="block text-sm font-medium text-white" for="authCode">
|
|
Authentication Code *
|
|
</label>
|
|
<input
|
|
id="authCode"
|
|
type="text"
|
|
placeholder="Enter your auth code"
|
|
class="w-full rounded-lg border border-neon-blue/30 bg-void px-4 py-2.5 text-white placeholder-white/40 transition-all duration-300 focus:border-neon-blue focus:outline-none focus:ring-1 focus:ring-neon-blue disabled:opacity-50"
|
|
bind:value={authCode}
|
|
disabled={isLoading}
|
|
required
|
|
/>
|
|
<p class="text-xs text-white/50">Required to verify ownership of this Steam account</p>
|
|
</div>
|
|
{/if}
|
|
|
|
<!-- Error Message -->
|
|
{#if error}
|
|
<div class="flex items-start gap-3 rounded-lg border border-neon-red/30 bg-neon-red/10 p-4">
|
|
<AlertCircle class="h-5 w-5 shrink-0 text-neon-red" />
|
|
<span class="text-sm text-neon-red">{error}</span>
|
|
</div>
|
|
{/if}
|
|
|
|
<!-- Help Text -->
|
|
<div class="text-sm text-white/60">
|
|
<p class="mb-2 font-medium text-white/70">How to get your authentication code:</p>
|
|
<ol class="list-inside list-decimal space-y-1">
|
|
<li>Open CS2 and go to Settings → Game</li>
|
|
<li>Enable the Developer Console</li>
|
|
<li>
|
|
Press <kbd class="rounded border border-white/20 bg-void px-2 py-0.5 font-mono text-xs"
|
|
>~</kbd
|
|
> to open the console
|
|
</li>
|
|
<li>
|
|
Type: <code class="rounded bg-void px-1.5 py-0.5 font-mono text-neon-blue">status</code>
|
|
</li>
|
|
<li>Copy the code shown next to "Account:"</li>
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
|
|
{#snippet actions()}
|
|
<button
|
|
class="rounded-lg border border-white/20 px-4 py-2 text-sm font-medium text-white/70 transition-all duration-300 hover:bg-white/10 hover:text-white disabled:opacity-50"
|
|
onclick={handleClose}
|
|
disabled={isLoading}
|
|
>
|
|
Cancel
|
|
</button>
|
|
{#if isTracked}
|
|
<button
|
|
class="flex items-center gap-2 rounded-lg bg-neon-red px-4 py-2 text-sm font-medium text-white transition-all duration-300 hover:shadow-[0_0_20px_rgba(255,51,102,0.4)] disabled:opacity-50"
|
|
onclick={handleUntrack}
|
|
disabled={isLoading}
|
|
>
|
|
{#if isLoading}
|
|
<Loader2 class="h-4 w-4 animate-spin" />
|
|
{/if}
|
|
Untrack Player
|
|
</button>
|
|
{:else}
|
|
<button
|
|
class="flex items-center gap-2 rounded-lg bg-neon-blue px-4 py-2 text-sm font-medium text-void transition-all duration-300 hover:shadow-[0_0_20px_rgba(0,212,255,0.4)] disabled:opacity-50"
|
|
onclick={handleTrack}
|
|
disabled={isLoading}
|
|
>
|
|
{#if isLoading}
|
|
<Loader2 class="h-4 w-4 animate-spin" />
|
|
{/if}
|
|
Track Player
|
|
</button>
|
|
{/if}
|
|
{/snippet}
|
|
</Modal>
|