npm package: @ludustack/react
Description: Pure rendering React components for displaying gamification data
Latest version: 0.0.11

# @ludustack/react

Beautiful React components for displaying gamification data.

**🎮 [LuduStack](https://ludustack.com)** - The complete gamification platform for developers.

## Overview

The `@ludustack/react` package provides pure rendering UI components for displaying gamification data. These components take data as props and render beautiful, responsive interfaces.

- **🎨 Pure Rendering**: Components only display data passed as props
- **📊 Beautiful UI**: Responsive, accessible components with animations
- **⚡ Lightweight**: No data fetching, no complex state management
- **🔧 Customizable**: Flexible styling and behavior options

## Installation

```bash
npm install @ludustack/react @ludustack/sdk
```

> Install `@ludustack/sdk` for server-side data fetching.

## Quick Start

### 1. Fetch Data Server-Side

```tsx
// app/page.tsx (Next.js Server Component)
import { LudustackSDK } from "@ludustack/sdk";
import { PlayerCard } from "@ludustack/react";

export default async function GamePage() {
  // Server-side data fetching
  const sdk = new LudustackSDK({
    apiKey: process.env.LUDUSTACK_API_KEY!,
    gameId: "your-game-id",
  });

  const player = await sdk.player.getById("player-123");
  const game = await sdk.game.getById("your-game-id");

  return (
    <div>
      <h1>Player Dashboard</h1>
      <PlayerCard
        player={player}
        game={game}
        onViewProfileClick={(player) => {
          // Handle navigation
          console.log("View profile for", player.displayName);
        }}
      />
    </div>
  );
}
```

### 2. Client-Side Operations

```tsx
// app/components/player-actions.tsx
"use client";

import { givePointsAction } from "../actions/gamification";

export function PlayerActions({ playerId }: { playerId: string }) {
  const handleGivePoints = async () => {
    await givePointsAction(playerId, 100, "manual_award");
  };

  return <button onClick={handleGivePoints}>Give 100 Points</button>;
}
```

```tsx
// app/actions/gamification.ts (Server Action)
"use server";

import { LudustackSDK } from "@ludustack/sdk";

export async function givePointsAction(
  playerId: string,
  points: number,
  action: string
) {
  const sdk = new LudustackSDK({
    apiKey: process.env.LUDUSTACK_API_KEY!,
    gameId: process.env.LUDUSTACK_GAME_ID!,
  });

  return await sdk.operations.givePoints(playerId, points, action);
}
```

## Available Components

### `<PlayerCard />`

Displays comprehensive player information including avatar, points, level, and progress.

```tsx
<PlayerCard
  player={player} // Required: Player data
  game={game} // Optional: Game data for context
  showGameInfo={true} // Optional: Show game information
  sortIndex={0} // Optional: Position in ranking
  onViewProfileClick={(player) => {}} // Optional: Profile click handler
  onEditPlayerClick={(player) => {}} // Optional: Edit click handler
/>
```

### `<PlayerBadge />`

Compact player information display.

```tsx
<PlayerBadge player={player} onClick={() => console.log("Badge clicked")} />
```

### `<LeaderboardTable />`

Displays ranked players in a table format.

```tsx
<LeaderboardTable
  players={players} // Required: Array of players
  title="Top Players" // Optional: Table title
  highlightedPlayerId="player-123" // Optional: Highlight specific player
/>
```

### `<PointsDisplay />`

Shows player points with optional animations.

```tsx
<PointsDisplay
  points={150}
  singular="point"
  plural="points"
  animateChanges={true}
/>
```

## Data Fetching Examples

### Next.js Server Components

```tsx
// app/leaderboard/page.tsx
import { LudustackSDK } from "@ludustack/sdk";
import { LeaderboardTable } from "@ludustack/react";

export default async function LeaderboardPage() {
  const sdk = new LudustackSDK({
    apiKey: process.env.LUDUSTACK_API_KEY!,
    gameId: "your-game-id",
  });

  const players = await sdk.player.list({
    gameId: "your-game-id",
    sortBy: "points",
    order: "desc",
    limit: 10,
  });

  return (
    <div>
      <h1>Leaderboard</h1>
      <LeaderboardTable players={players} title="Top 10 Players" />
    </div>
  );
}
```

### API Routes

```tsx
// app/api/players/[id]/route.ts
import { NextRequest, NextResponse } from "next/server";
import { LudustackSDK } from "@ludustack/sdk";

export async function GET(
  request: NextRequest,
  { params }: { params: { id: string } }
) {
  const sdk = new LudustackSDK({
    apiKey: process.env.LUDUSTACK_API_KEY!,
    gameId: process.env.LUDUSTACK_GAME_ID!,
  });

  try {
    const player = await sdk.player.getById(params.id);
    return NextResponse.json(player);
  } catch (error) {
    return NextResponse.json({ error: "Player not found" }, { status: 404 });
  }
}
```

### Server Actions

```tsx
// app/actions/achievements.ts
"use server";

import { LudustackSDK } from "@ludustack/sdk";
import { revalidatePath } from "next/cache";

export async function processAchievementAction(
  playerId: string,
  achievementId: string,
  options?: { forceComplete?: boolean }
) {
  const sdk = new LudustackSDK({
    apiKey: process.env.LUDUSTACK_API_KEY!,
    gameId: process.env.LUDUSTACK_GAME_ID!,
  });

  const result = await sdk.operations.processAchievement(
    playerId,
    achievementId,
    options
  );

  revalidatePath("/player/[id]", "page");
  return result;
}
```

## Animation Utilities

```tsx
import { useAnimationStyles } from "@ludustack/react";

function MyComponent() {
  // Ensures animation styles are loaded
  useAnimationStyles();

  return (
    <div className="animate-in fade-in duration-200">Animated content</div>
  );
}
```

## Data Models

### Player Model

```typescript
interface Player {
  id: string;
  displayName?: string;
  username?: string;
  email?: string;
  externalId?: string;
  avatarUrl?: string;
  points?: number;
  level?: {
    currentLevelNumber?: number;
    currentLevelName?: string;
    levelProgress?: number;
    nextLevelThreshold?: number | null;
  };
  gameId?: string;
}
```

### Game Model

```typescript
interface Game {
  id: string;
  name: string;
  status?: string;
  description?: string;
  type?: string;
}
```

## TypeScript Support

Full TypeScript support with strict type definitions:

```tsx
import { Player, Game, PlayerCardProps } from "@ludustack/react";

const player: Player = {
  id: "player-123",
  displayName: "Player Name",
  points: 250,
  level: {
    currentLevelNumber: 3,
    currentLevelName: "Explorer",
    levelProgress: 65,
    nextLevelThreshold: 500,
  },
};
```

## Styling

Components use Tailwind CSS classes and support custom styling:

```tsx
<PlayerCard player={player} className="bg-blue-50 border-blue-200" />
```

## Performance

- **No API calls**: Components only render data, no network requests
- **Server-side rendering**: Compatible with SSR/SSG for faster initial loads
- **Efficient animations**: Lightweight CSS-based animations
- **Small bundle**: No SDK or complex dependencies in client bundle

## Support

For support, please:

- Visit [our main website](https://ludustack.com)
- [Contact us](https://x.com/programad)
- Check [our documentation](https://ludustack.com/docs)

## License

MIT