Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion FarmersMarketplace
Submodule FarmersMarketplace deleted from a53c78
24 changes: 24 additions & 0 deletions __tests__/components/Badge.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import Badge from '@/components/ui/Badge';

describe('Badge', () => {
it('renders default variant correctly', () => {
render(<Badge>Default Badge</Badge>);
expect(screen.getByText('Default Badge')).toBeInTheDocument();
expect(screen.getByText('Default Badge')).toHaveClass('bg-brand-green');
});

it('renders elite variant with gold/amber styling', () => {
render(<Badge variant="elite">Elite Tier</Badge>);
const badge = screen.getByText('Elite Tier');
expect(badge).toBeInTheDocument();
expect(badge).toHaveClass('bg-amber-500');
expect(badge).toHaveClass('border-amber-300');
});

it('applies custom className', () => {
render(<Badge className="custom-class">Test</Badge>);
expect(screen.getByText('Test')).toHaveClass('custom-class');
});
});
48 changes: 48 additions & 0 deletions __tests__/components/PlayerCard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import PlayerCard from '@/components/PlayerCard';
import type { Player } from '@/types';

const mockPlayer: Player = {
id: '1',
wallet: 'GTESTWALLET',
vitals: {
name: 'Test Player',
age: 25,
position: 'ST',
region: 'Europe',
nationality: 'England',
},
ipfsHash: 'test-hash',
progressLevel: 0,
milestones: [],
createdAt: 1234567890,
};

describe('PlayerCard', () => {
it('renders player information correctly', () => {
render(<PlayerCard player={mockPlayer} />);
expect(screen.getByText('Test Player')).toBeInTheDocument();
expect(screen.getByText('ST · Europe')).toBeInTheDocument();
});

it('does not show Elite Tier badge for level 0', () => {
render(<PlayerCard player={{ ...mockPlayer, progressLevel: 0 }} />);
expect(screen.queryByText('Elite Tier')).not.toBeInTheDocument();
});

it('does not show Elite Tier badge for level 1', () => {
render(<PlayerCard player={{ ...mockPlayer, progressLevel: 1 }} />);
expect(screen.queryByText('Elite Tier')).not.toBeInTheDocument();
});

it('does not show Elite Tier badge for level 2', () => {
render(<PlayerCard player={{ ...mockPlayer, progressLevel: 2 }} />);
expect(screen.queryByText('Elite Tier')).not.toBeInTheDocument();
});

it('shows Elite Tier badge for level 3', () => {
render(<PlayerCard player={{ ...mockPlayer, progressLevel: 3 }} />);
expect(screen.getByText('Elite Tier')).toBeInTheDocument();
});
});
18 changes: 17 additions & 1 deletion app/player/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useEffect, useState } from "react";
import { useParams } from "next/navigation";
import { useWallet } from "@/hooks/useWallet";
import ProgressBar from "@/components/ProgressBar";
import Badge from "@/components/ui/Badge";
import { getPlayer } from "@/lib/contract";
import { buildPayToContact } from "@/lib/contract";
import { ipfsUrl } from "@/lib/ipfs";
Expand Down Expand Up @@ -35,6 +36,16 @@ export default function PlayerProfile() {

return (
<div className="max-w-2xl mx-auto flex flex-col gap-8">
{/* Elite Tier Banner */}
{player.progressLevel === 3 && (
<div className="bg-gradient-to-r from-amber-500 to-amber-600 text-black rounded-xl p-4 text-center">
<Badge variant="elite" className="text-sm py-1 px-3">
Elite Tier
</Badge>
<p className="text-sm font-semibold mt-2">Highest verifiable status achieved</p>
</div>
)}

{/* Header */}
<div className="bg-brand-card border border-gray-800 rounded-xl p-6 flex gap-6 items-start">
<div className="w-20 h-20 rounded-full bg-gray-700 overflow-hidden shrink-0">
Expand All @@ -44,7 +55,12 @@ export default function PlayerProfile() {
)}
</div>
<div className="flex-1">
<h1 className="text-2xl font-bold text-white">{player.vitals.name}</h1>
<div className="flex items-center gap-2">
<h1 className="text-2xl font-bold text-white">{player.vitals.name}</h1>
{player.progressLevel === 3 && (
<Badge variant="elite">Elite Tier</Badge>
)}
</div>
<p className="text-gray-400 text-sm mt-1">
{player.vitals.position} · {player.vitals.region} · Age {player.vitals.age}
</p>
Expand Down
8 changes: 7 additions & 1 deletion components/PlayerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Link from "next/link";
import type { Player } from "@/types";
import { PROGRESS_LABELS } from "@/types";
import ProgressBar from "./ProgressBar";
import Badge from "./ui/Badge";

export default function PlayerCard({ player }: { player: Player }) {
const { id, vitals, progressLevel, ipfsHash } = player;
Expand All @@ -20,7 +21,12 @@ export default function PlayerCard({ player }: { player: Player }) {
</div>

<div>
<h3 className="font-semibold text-white">{vitals.name}</h3>
<div className="flex items-center gap-2">
<h3 className="font-semibold text-white">{vitals.name}</h3>
{progressLevel === 3 && (
<Badge variant="elite">Elite Tier</Badge>
)}
</div>
<p className="text-sm text-gray-400">
{vitals.position} · {vitals.region}
</p>
Expand Down
18 changes: 18 additions & 0 deletions components/ui/Badge.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface BadgeProps {
variant?: "default" | "elite";
children: React.ReactNode;
className?: string;
}

export default function Badge({ variant = "default", children, className = "" }: BadgeProps) {
const variants = {
default: "bg-brand-green text-black",
elite: "bg-amber-500 text-black border-2 border-amber-300",
};

return (
<span className={`inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-semibold ${variants[variant]} ${className}`}>
{children}
</span>
);
}