This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import { apiRequest } from "@/lib/api/api-service";
|
||||
import { ApiResponse, PaginatedData } from "@/types/api-response";
|
||||
import {
|
||||
MatchResponseDto,
|
||||
MatchListParams,
|
||||
MatchQueryDto,
|
||||
ActiveLeagueDto,
|
||||
LeagueWithMatchesDto,
|
||||
} from "./types";
|
||||
|
||||
/**
|
||||
* Matches Service
|
||||
* Backend: /api/matches/*
|
||||
*/
|
||||
|
||||
const listMatches = (params?: MatchListParams) => {
|
||||
return apiRequest<ApiResponse<PaginatedData<MatchResponseDto>>>({
|
||||
url: "/matches",
|
||||
client: "core",
|
||||
method: "get",
|
||||
params,
|
||||
});
|
||||
};
|
||||
|
||||
const getMatchDetails = (id: string) => {
|
||||
return apiRequest<ApiResponse<MatchResponseDto>>({
|
||||
url: `/matches/${id}`,
|
||||
client: "core",
|
||||
method: "get",
|
||||
});
|
||||
};
|
||||
|
||||
const queryMatches = (queryDto: MatchQueryDto) => {
|
||||
return apiRequest<ApiResponse<LeagueWithMatchesDto[]>>({
|
||||
url: "/matches/query",
|
||||
client: "core",
|
||||
method: "post",
|
||||
data: queryDto,
|
||||
});
|
||||
};
|
||||
|
||||
const getActiveLeagues = (sport?: string) => {
|
||||
return apiRequest<ApiResponse<ActiveLeagueDto[]>>({
|
||||
url: "/matches/leagues/active",
|
||||
client: "core",
|
||||
method: "get",
|
||||
params: sport ? { sport } : undefined,
|
||||
});
|
||||
};
|
||||
|
||||
export const matchesService = {
|
||||
listMatches,
|
||||
getMatchDetails,
|
||||
queryMatches,
|
||||
getActiveLeagues,
|
||||
};
|
||||
@@ -0,0 +1,118 @@
|
||||
// ========================
|
||||
// Enums & Constants
|
||||
// ========================
|
||||
|
||||
export type SportType = "football" | "basketball";
|
||||
|
||||
export type MatchStatus =
|
||||
| "LIVE"
|
||||
| "Finished"
|
||||
| "Not Started"
|
||||
| "UPCOMING"
|
||||
| "NOT_STARTED"
|
||||
| string;
|
||||
|
||||
// ========================
|
||||
// Query DTOs
|
||||
// ========================
|
||||
|
||||
export interface TeamFilterDto {
|
||||
name?: string;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export interface OddFilterDto {
|
||||
market: string;
|
||||
minOdd?: number;
|
||||
maxOdd?: number;
|
||||
}
|
||||
|
||||
export interface DateRangeDto {
|
||||
from: string;
|
||||
to: string;
|
||||
}
|
||||
|
||||
export interface MatchQueryDto {
|
||||
sport: SportType;
|
||||
limit?: number;
|
||||
leagueId?: string;
|
||||
status?: MatchStatus;
|
||||
date?: string; // YYYY-MM-DD
|
||||
team?: TeamFilterDto;
|
||||
odds?: OddFilterDto[];
|
||||
dateRange?: DateRangeDto;
|
||||
}
|
||||
|
||||
export interface MatchListParams {
|
||||
page?: number;
|
||||
limit?: number;
|
||||
sport?: SportType;
|
||||
}
|
||||
|
||||
// ========================
|
||||
// Response DTOs
|
||||
// ========================
|
||||
|
||||
export interface MatchResponseDto {
|
||||
id: string;
|
||||
matchName: string;
|
||||
matchSlug?: string;
|
||||
mstUtc: number | string; // Timestamp
|
||||
date?: string | Date;
|
||||
status: MatchStatus;
|
||||
state?: string;
|
||||
|
||||
// Scores
|
||||
scoreHome?: number;
|
||||
scoreAway?: number;
|
||||
score?: { home: number; away: number };
|
||||
htScoreHome?: number;
|
||||
htScoreAway?: number;
|
||||
|
||||
// Teams
|
||||
homeTeamName: string;
|
||||
homeTeamLogo?: string;
|
||||
awayTeamName: string;
|
||||
awayTeamLogo?: string;
|
||||
|
||||
// League & Country
|
||||
leagueName?: string;
|
||||
countryName?: string;
|
||||
|
||||
// Odds (dynamic key-value)
|
||||
odds?: Record<string, Record<string, { odd: string }>>;
|
||||
|
||||
// Nested Objects (from Backend include)
|
||||
homeTeam?: { name: string; logo?: string; [key: string]: unknown };
|
||||
awayTeam?: { name: string; logo?: string; [key: string]: unknown };
|
||||
league?: {
|
||||
name: string;
|
||||
country?: { name: string; flag?: string };
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
export interface ActiveLeagueDto {
|
||||
id: string;
|
||||
name: string;
|
||||
code?: string;
|
||||
countryName?: string;
|
||||
countryFlag?: string;
|
||||
matchCount: number;
|
||||
liveCount: number;
|
||||
}
|
||||
|
||||
export interface LeagueWithMatchesDto {
|
||||
id: string;
|
||||
name: string;
|
||||
code?: string;
|
||||
country: {
|
||||
id: string;
|
||||
name: string;
|
||||
flagUrl?: string; // Backend uses flagUrl
|
||||
};
|
||||
sport: SportType;
|
||||
matches: MatchResponseDto[];
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { useQuery, useMutation } from "@tanstack/react-query";
|
||||
import { matchesService } from "./service";
|
||||
import type { MatchListParams, MatchQueryDto } from "./types";
|
||||
|
||||
export const MatchesQueryKeys = {
|
||||
all: ["matches"] as const,
|
||||
list: (params?: MatchListParams) =>
|
||||
[...MatchesQueryKeys.all, "list", params] as const,
|
||||
detail: (id: string) => [...MatchesQueryKeys.all, "detail", id] as const,
|
||||
activeLeagues: (sport?: string) =>
|
||||
[...MatchesQueryKeys.all, "activeLeagues", sport] as const,
|
||||
};
|
||||
|
||||
export const useListMatches = (params?: MatchListParams) => {
|
||||
return useQuery({
|
||||
queryKey: MatchesQueryKeys.list(params),
|
||||
queryFn: () => matchesService.listMatches(params),
|
||||
});
|
||||
};
|
||||
|
||||
export const useMatchDetails = (id: string) => {
|
||||
return useQuery({
|
||||
queryKey: MatchesQueryKeys.detail(id),
|
||||
queryFn: () => matchesService.getMatchDetails(id),
|
||||
enabled: !!id,
|
||||
});
|
||||
};
|
||||
|
||||
export const useQueryMatches = () => {
|
||||
return useMutation({
|
||||
mutationFn: (queryDto: MatchQueryDto) =>
|
||||
matchesService.queryMatches(queryDto),
|
||||
});
|
||||
};
|
||||
|
||||
export const useActiveLeagues = (sport?: string) => {
|
||||
return useQuery({
|
||||
queryKey: MatchesQueryKeys.activeLeagues(sport),
|
||||
queryFn: () => matchesService.getActiveLeagues(sport),
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user