diff --git a/frontend/src/app/admin/disputes/page.tsx b/frontend/src/app/admin/disputes/page.tsx index b4861b21..4698852b 100644 --- a/frontend/src/app/admin/disputes/page.tsx +++ b/frontend/src/app/admin/disputes/page.tsx @@ -5,13 +5,10 @@ import { api } from "@/lib/api"; import { ProtectedPage } from "@/components/navigation/ProtectedPage"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/Card"; import { Button } from "@/components/ui/Button"; -import { PageError } from "@/components/common/PageError"; -import { ListItemSkeleton, PageHeaderSkeleton } from "@/components/common/PageSkeleton"; -import { ShieldAlert } from "lucide-react"; -import { EmptyState } from "@/components/common/EmptyState"; +import type { Dispute } from "@/types/admin"; export default function DisputeDashboard() { - const [disputes, setDisputes] = useState([]); + const [disputes, setDisputes] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -20,10 +17,9 @@ export default function DisputeDashboard() { setError(null); try { const data = await api.getDisputes(); - setDisputes(data as any[]); - } catch (err) { - console.error("Failed to fetch disputes:", err); - setError((err as Error).message ?? "Failed to load disputes."); + setDisputes(data as Dispute[]); + } catch (error) { + console.error("Failed to fetch disputes:", error); } finally { setLoading(false); } diff --git a/frontend/src/app/admin/governance/page.tsx b/frontend/src/app/admin/governance/page.tsx index 515e2f1a..b70891ac 100644 --- a/frontend/src/app/admin/governance/page.tsx +++ b/frontend/src/app/admin/governance/page.tsx @@ -5,13 +5,10 @@ import { api } from "@/lib/api"; import { ProtectedPage } from "@/components/navigation/ProtectedPage"; import { Card, CardContent, CardDescription, CardHeader, CardTitle, CardFooter } from "@/components/ui/Card"; import { Button } from "@/components/ui/Button"; -import { PageError } from "@/components/common/PageError"; -import { CardSkeleton, PageHeaderSkeleton } from "@/components/common/PageSkeleton"; -import { EmptyState } from "@/components/common/EmptyState"; -import { FileText } from "lucide-react"; +import type { GovernanceProposal } from "@/types/admin"; export default function GovernanceDashboard() { - const [proposals, setProposals] = useState([]); + const [proposals, setProposals] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); @@ -20,10 +17,9 @@ export default function GovernanceDashboard() { setError(null); try { const data = await api.getProposals(); - setProposals(data); - } catch (err) { - console.error("Failed to fetch proposals:", err); - setError((err as Error).message ?? "Failed to load proposals."); + setProposals(data as GovernanceProposal[]); + } catch (error) { + console.error("Failed to fetch proposals:", error); } finally { setLoading(false); } diff --git a/frontend/src/app/admin/kyc/page.tsx b/frontend/src/app/admin/kyc/page.tsx index d2664ad4..1d4fc232 100644 --- a/frontend/src/app/admin/kyc/page.tsx +++ b/frontend/src/app/admin/kyc/page.tsx @@ -7,25 +7,7 @@ import { ProtectedPage } from "@/components/navigation/ProtectedPage"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/Card"; import { Button } from "@/components/ui/Button"; import { Input } from "@/components/ui/Input"; -import { PageError } from "@/components/common/PageError"; -import { ListItemSkeleton, PageHeaderSkeleton, Skeleton } from "@/components/common/PageSkeleton"; -import { EmptyState } from "@/components/common/EmptyState"; -import { FileText } from "lucide-react"; - -type KycStatus = "PENDING" | "APPROVED" | "REJECTED" | "ESCALATED"; - -interface KycReview { - id: string; - userId: string; - status: KycStatus; - documents: any[]; - notes?: string; - user: { - username: string; - email: string; - }; - createdAt: string; -} +import type { KycDocument, KycReview, KycStatus } from "@/types/admin"; export default function KycDashboard() { const [reviews, setReviews] = useState([]); @@ -223,7 +205,7 @@ export default function KycDashboard() {
{Array.isArray(selectedReview.documents) && selectedReview.documents.length > 0 ? ( - selectedReview.documents.map((doc: any, i: number) => ( + selectedReview.documents.map((doc: KycDocument, i: number) => (
(''); - const [players, setPlayers] = useState([]); + const [players, setPlayers] = useState([]); const [countdown, setCountdown] = useState(null); useEffect(() => { diff --git a/frontend/src/app/play/party/page.tsx b/frontend/src/app/play/party/page.tsx index a08b056a..8357ddce 100644 --- a/frontend/src/app/play/party/page.tsx +++ b/frontend/src/app/play/party/page.tsx @@ -18,18 +18,11 @@ import PartyManager from '@/components/game/PartyManager'; import CountdownTimer from '@/components/game/CountdownTimer'; import ChatPanel from '@/components/game/ChatPanel'; import PlayerList from '@/components/game/PlayerList'; +import type { PartyPlayer } from '@/types/player'; const MAX_PARTY_SIZE = 4; const COUNTDOWN_SECONDS = 15; -interface PartyPlayer { - id: string; - username: string; - avatar?: string; - isReady: boolean; - isHost: boolean; -} - export default function PlayPartyPage() { const router = useRouter(); const [players, setPlayers] = useState([ diff --git a/frontend/src/app/profile/[id]/ProfilePageClient.tsx b/frontend/src/app/profile/[id]/ProfilePageClient.tsx index 95df9f3b..0c089a55 100644 --- a/frontend/src/app/profile/[id]/ProfilePageClient.tsx +++ b/frontend/src/app/profile/[id]/ProfilePageClient.tsx @@ -11,17 +11,7 @@ import { FriendsList } from '@/components/profile/FriendsList'; import { ActivityFeed } from '@/components/profile/ActivityFeed'; import { Button } from '@/components/ui/Button'; import { Share2, Settings, UserPlus, MessageCircle } from 'lucide-react'; -import type { PublicProfile, PlayerStats, Achievement, FriendEntry, ActivityEvent } from '@/types/profile'; -import type { EloPoint } from '@/types/user'; - -interface ProfilePageClientProps { - profile: PublicProfile; - stats: PlayerStats; - achievements: Achievement[]; - friends: FriendEntry[]; - activities: ActivityEvent[]; - eloHistory: EloPoint[]; -} +import type { PublicProfileViewProps } from '@/types/profile'; export function ProfilePageClient({ profile, @@ -30,7 +20,7 @@ export function ProfilePageClient({ friends, activities, eloHistory, -}: ProfilePageClientProps) { +}: PublicProfileViewProps) { const { user } = useAuth(); const viewerRelation: 'owner' | 'friend' | 'public' = diff --git a/frontend/src/app/tournaments/[id]/page.tsx b/frontend/src/app/tournaments/[id]/page.tsx index 235c6ed2..515fb4d3 100644 --- a/frontend/src/app/tournaments/[id]/page.tsx +++ b/frontend/src/app/tournaments/[id]/page.tsx @@ -14,7 +14,7 @@ import { ArrowLeft, RadioTower, ShieldAlert, Swords, Trophy } from "lucide-react import { Button } from "@/components/ui/Button"; import { useAuth } from "@/hooks/useAuth"; import { api } from "@/lib/api"; -import { TOURNAMENT_DETAIL_BANNER_SIZES } from "@/lib/tournamentImageSizes"; +import type { Tournament } from "@/types/tournament"; export default function TournamentDetailsPage() { const params = useParams(); @@ -25,7 +25,7 @@ export default function TournamentDetailsPage() { // branch below rather than rendering a hardcoded fallback. const tournamentId = Array.isArray(params.id) ? params.id[0] : params.id; const currentUserId = user?.id ?? "user-123"; - const [tournament, setTournament] = useState(null); + const [tournament, setTournament] = useState(null); const [isLoading, setIsLoading] = useState(true); const [fetchError, setFetchError] = useState(null); diff --git a/frontend/src/app/tournaments/[id]/register/page.tsx b/frontend/src/app/tournaments/[id]/register/page.tsx index 7d352d78..e75240f0 100644 --- a/frontend/src/app/tournaments/[id]/register/page.tsx +++ b/frontend/src/app/tournaments/[id]/register/page.tsx @@ -6,12 +6,13 @@ import { RegistrationForm } from "@/components/tournaments/RegistrationForm"; import { Button } from "@/components/ui/Button"; import { ArrowLeft, AlertCircle } from "lucide-react"; import { api } from "@/lib/api"; +import type { Tournament } from "@/types/tournament"; export default function TournamentRegisterPage() { const params = useParams(); const router = useRouter(); - const tournamentId = Array.isArray(params.id) ? params.id[0] : params.id; - const [tournament, setTournament] = useState(null); + const tournamentId = params.id as string; + const [tournament, setTournament] = useState(null); const [isLoading, setIsLoading] = useState(true); const [fetchError, setFetchError] = useState(null); diff --git a/frontend/src/app/tournaments/create/page.tsx b/frontend/src/app/tournaments/create/page.tsx index 7aeeac48..cd12ae6d 100644 --- a/frontend/src/app/tournaments/create/page.tsx +++ b/frontend/src/app/tournaments/create/page.tsx @@ -22,33 +22,14 @@ import { DollarSign, Gamepad2 } from "lucide-react"; -import { TournamentType, TournamentVisibility } from "@/types/tournament"; - -type Step = 1 | 2 | 3 | 4 | "preview" | "success"; - -interface TournamentFormData { - // Step 1: Basic Info - name: string; - gameType: string; - description: string; - // Step 2: Format & Rules - tournamentType: TournamentType; - matchFormat: string; - rules: string; - // Step 3: Entry & Prizes - entryFee: number; - prizePool: number; - prizeDistribution: string; - // Step 4: Schedule & Registration - visibility: TournamentVisibility; - maxParticipants: number; - registrationOpenDate: string; - registrationCloseDate: string; - startDate: string; - endDate: string; -} - -const initialFormData: TournamentFormData = { +import { + CreateCreateTournamentFormData, + CreateTournamentWizardStep, + TournamentType, + TournamentVisibility, +} from "@/types/tournament"; + +const initialFormData: CreateCreateTournamentFormData = { name: "", gameType: "", description: "", @@ -95,8 +76,8 @@ const tournamentTypes: { value: TournamentType; label: string; description: stri ]; export default function CreateTournamentPage() { - const [currentStep, setCurrentStep] = useState(1); - const [formData, setFormData] = useState(initialFormData); + const [currentStep, setCurrentStep] = useState(1); + const [formData, setFormData] = useState(initialFormData); const [errors, setErrors] = useState>({}); const [isSaving, setIsSaving] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false); @@ -136,7 +117,7 @@ export default function CreateTournamentPage() { return () => clearTimeout(timer); }, [formData, saveDraft]); - const validateStep = (step: Step): boolean => { + const validateStep = (step: CreateTournamentWizardStep): boolean => { const newErrors: Record = {}; if (step === 1) { @@ -183,15 +164,15 @@ export default function CreateTournamentPage() { const handleNext = () => { if (validateStep(currentStep)) { - setCurrentStep((prev) => (prev === 4 ? "preview" : (prev as Step) + 1) as Step); + setCurrentStep((prev) => (prev === 4 ? "preview" : (prev as CreateTournamentWizardStep) + 1) as CreateTournamentWizardStep); } }; const handleBack = () => { - setCurrentStep((prev) => (prev === "preview" ? 4 : (prev as Step) - 1) as Step); + setCurrentStep((prev) => (prev === "preview" ? 4 : (prev as CreateTournamentWizardStep) - 1) as CreateTournamentWizardStep); }; - const handleFieldChange = (field: keyof TournamentFormData, value: string | number) => { + const handleFieldChange = (field: keyof CreateTournamentFormData, value: string | number) => { setFormData((prev) => ({ ...prev, [field]: value })); // Clear error for this field if (errors[field]) { diff --git a/frontend/src/components/game/PartyManager.tsx b/frontend/src/components/game/PartyManager.tsx index e7c18e41..22205901 100644 --- a/frontend/src/components/game/PartyManager.tsx +++ b/frontend/src/components/game/PartyManager.tsx @@ -1,18 +1,11 @@ 'use client'; import { useState } from 'react'; - -interface Player { - id: string; - username: string; - avatar?: string; - isReady: boolean; - isHost: boolean; -} +import type { PartyPlayer } from '@/types/player'; interface PartyManagerProps { partyId?: string; - players: Player[]; + players: PartyPlayer[]; maxPlayers?: number; onInvite?: (playerId: string) => void; onLeave?: () => void; diff --git a/frontend/src/data/matchHub.ts b/frontend/src/data/matchHub.ts index 96db3938..1145d417 100644 --- a/frontend/src/data/matchHub.ts +++ b/frontend/src/data/matchHub.ts @@ -1,47 +1,6 @@ -import { BracketMatch, ScoreReport } from "@/types/bracket"; +import type { MatchHubDetails } from "@/types/match"; -export interface MatchHubEvent { - id: string; - type: "status" | "score" | "alert" | "report"; - message: string; - createdAt: string; -} - -export interface MatchHubPlayerSnapshot { - id: string; - username: string; - avatar?: string; - elo: number; - region: string; - seed: number; - record: string; - stats: Array<{ label: string; value: string }>; -} - -export interface MatchHubDetails { - id: string; - tournamentId: string; - tournamentName: string; - gameType: string; - bracketFormat: "single_elimination" | "double_elimination"; - roundLabel: string; - arenaLabel: string; - status: BracketMatch["status"]; - bestOf: number; - scheduledTime: string; - startedAt?: string; - streamTitle?: string; - prizePool: number; - player1: MatchHubPlayerSnapshot; - player2: MatchHubPlayerSnapshot; - scorePlayer1: number; - scorePlayer2: number; - winnerId?: string; - notes: string; - reports: ScoreReport[]; - feed: MatchHubEvent[]; - canDisputeUntil: string; -} +export type { MatchHubDetails, MatchHubEvent, MatchHubPlayerSnapshot } from "@/types/match"; export const matchHubDetails: Record = { "1-match-13": { diff --git a/frontend/src/types/admin.ts b/frontend/src/types/admin.ts new file mode 100644 index 00000000..f6f4a987 --- /dev/null +++ b/frontend/src/types/admin.ts @@ -0,0 +1,50 @@ +export type KycStatus = "PENDING" | "APPROVED" | "REJECTED" | "ESCALATED"; + +export interface KycDocument { + url: string; + type?: string; +} + +export interface KycReviewUser { + username: string; + email: string; +} + +export interface KycReview { + id: string; + userId: string; + status: KycStatus; + documents: KycDocument[]; + notes?: string; + user: KycReviewUser; + createdAt: string; +} + +export interface DisputeReporter { + username: string; +} + +export interface DisputeMatch { + onChainId: string; + playerAId: string; + playerBId: string; + winnerId: string; +} + +export interface Dispute { + id: string; + status: string; + reason: string; + evidenceUrls: string[]; + reporter: DisputeReporter; + match: DisputeMatch; +} + +export interface GovernanceProposal { + id: string; + status: string; + functionName: string; + description?: string; + targetContract: string; + _count: { votes: number }; +} diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts index d90951e6..eb131a9d 100644 --- a/frontend/src/types/index.ts +++ b/frontend/src/types/index.ts @@ -1,11 +1,15 @@ // Export all types export * from './achievement'; +export * from './admin'; export * from './bracket'; export * from './leaderboard'; export * from './match'; export * from './notification'; +export * from './player'; +export * from './profile'; export * from './social'; export * from './tournament'; +export * from './transaction'; export * from './user'; // Common API response types diff --git a/frontend/src/types/leaderboard.ts b/frontend/src/types/leaderboard.ts index 2311cdaf..3f460d6e 100644 --- a/frontend/src/types/leaderboard.ts +++ b/frontend/src/types/leaderboard.ts @@ -1,3 +1,14 @@ +/** Compact player row used on the legacy /leaderboard page mock table. */ +export interface LeaderboardPlayer { + rank: number; + userId: string; + username: string; + points: number; + wins: number; + winRate: number; + game: string; +} + export interface LeaderboardEntry { id: string userId: string diff --git a/frontend/src/types/match.ts b/frontend/src/types/match.ts index 6b5d39d1..6730f947 100644 --- a/frontend/src/types/match.ts +++ b/frontend/src/types/match.ts @@ -1,3 +1,5 @@ +import type { BracketMatch, ScoreReport } from "./bracket"; + // Match-related types export interface Match { id: string; @@ -85,4 +87,47 @@ export interface MatchDetail extends MatchWithPlayers { replayUrl?: string; canDispute?: boolean; disputeDeadline?: string; +} + +export interface MatchHubEvent { + id: string; + type: "status" | "score" | "alert" | "report"; + message: string; + createdAt: string; +} + +export interface MatchHubPlayerSnapshot { + id: string; + username: string; + avatar?: string; + elo: number; + region: string; + seed: number; + record: string; + stats: Array<{ label: string; value: string }>; +} + +export interface MatchHubDetails { + id: string; + tournamentId: string; + tournamentName: string; + gameType: string; + bracketFormat: "single_elimination" | "double_elimination"; + roundLabel: string; + arenaLabel: string; + status: BracketMatch["status"]; + bestOf: number; + scheduledTime: string; + startedAt?: string; + streamTitle?: string; + prizePool: number; + player1: MatchHubPlayerSnapshot; + player2: MatchHubPlayerSnapshot; + scorePlayer1: number; + scorePlayer2: number; + winnerId?: string; + notes: string; + reports: ScoreReport[]; + feed: MatchHubEvent[]; + canDisputeUntil: string; } \ No newline at end of file diff --git a/frontend/src/types/player.ts b/frontend/src/types/player.ts new file mode 100644 index 00000000..8cc649a2 --- /dev/null +++ b/frontend/src/types/player.ts @@ -0,0 +1,12 @@ +/** Base player identity used across lobby, party, and social UIs. */ +export interface Player { + id: string; + username: string; + avatar?: string; +} + +/** Player in a pre-game lobby or party with ready/host state. */ +export interface PartyPlayer extends Player { + isReady: boolean; + isHost: boolean; +} diff --git a/frontend/src/types/profile.ts b/frontend/src/types/profile.ts index 37e0b69b..335a7f59 100644 --- a/frontend/src/types/profile.ts +++ b/frontend/src/types/profile.ts @@ -49,6 +49,7 @@ export interface FriendEntry { avatar?: string; elo: number; status: 'online' | 'in-game' | 'offline'; + gamesPlayed?: number; lastSeen?: string; currentActivity?: string; mutualFriends?: number; @@ -77,6 +78,15 @@ export interface ProfileCustomization { export type PrivacySetting = 'everyone' | 'friends' | 'only_me'; +export interface PublicProfileViewProps { + profile: PublicProfile; + stats: PlayerStats; + achievements: Achievement[]; + friends: FriendEntry[]; + activities: ActivityEvent[]; + eloHistory: EloPoint[]; +} + export interface PrivacySettings { stats: PrivacySetting; matchHistory: PrivacySetting; diff --git a/frontend/src/types/tournament.ts b/frontend/src/types/tournament.ts index 00c5f45d..a6ce5ad0 100644 --- a/frontend/src/types/tournament.ts +++ b/frontend/src/types/tournament.ts @@ -92,6 +92,26 @@ export interface CreateTournamentRequest { startTime: string; } +export type CreateTournamentWizardStep = 1 | 2 | 3 | 4 | "preview" | "success"; + +export interface CreateTournamentFormData { + name: string; + gameType: string; + description: string; + tournamentType: TournamentType; + matchFormat: string; + rules: string; + entryFee: number; + prizePool: number; + prizeDistribution: string; + visibility: TournamentVisibility; + maxParticipants: number; + registrationOpenDate: string; + registrationCloseDate: string; + startDate: string; + endDate: string; +} + export interface TournamentFilters { gameType?: string; status?: TournamentStatus; diff --git a/frontend/src/types/transaction.ts b/frontend/src/types/transaction.ts new file mode 100644 index 00000000..f2c6cda6 --- /dev/null +++ b/frontend/src/types/transaction.ts @@ -0,0 +1,11 @@ +export type { + TxDirection, + TxHistoryItem, + TxKind, + TxMeta, + TxPhase, + TxStatus, +} from "@/lib/wallet/types"; + +/** Wallet transaction entry (deposit / withdraw) shown in history UIs. */ +export type { TxHistoryItem as Transaction } from "@/lib/wallet/types";