first
Deploy Iddaai Frontend / build-and-deploy (push) Successful in 4m0s

This commit is contained in:
2026-04-16 13:36:34 +03:00
parent de5e145c4e
commit fc7a1ba567
218 changed files with 32370 additions and 0 deletions
+219
View File
@@ -0,0 +1,219 @@
import { apiRequest } from "@/lib/api/api-service";
import { ApiResponse } from "@/types/api-response";
/**
* Spor Toto Service
* Backend: /api/spor-toto/*
*/
// ========================
// Request DTOs
// ========================
export interface CreateBulletinDto {
gameCycleNo: number;
drawDate: string;
matches: {
matchId: string;
homeTeam: string;
awayTeam: string;
matchDate: string;
}[];
}
export interface UpdateResultsDto {
results: {
matchIndex: number;
homeScore: number;
awayScore: number;
}[];
}
export interface GenerateColumnsDto {
selections: { matchIndex: number; picks: ("1" | "X" | "2")[] }[];
strategy?: "FULL" | "REDUCED";
maxColumns?: number;
}
export interface EvaluateColumnsDto {
bulletinId: string;
columns: string[];
}
export interface GenerateSporTotoPredictionDto {
bulletinId: string;
strategy?: "CONSERVATIVE" | "BALANCED" | "AGGRESSIVE" | "FORMULA_6PCT";
}
// ========================
// Response DTOs
// ========================
export interface SporTotoMatchDto {
id: string;
matchIndex: number;
homeTeam: string;
awayTeam: string;
matchDate: string;
result?: string;
homeScore?: number;
awayScore?: number;
prediction?: {
pick: string;
confidence: number;
odds: Record<string, number>;
};
}
export interface SporTotoBulletinDto {
id: string;
gameCycleNo: number;
drawDate: string;
status: string;
matches: SporTotoMatchDto[];
totalPool?: number;
dividends?: Record<string, number>;
createdAt: string;
}
export interface SporTotoStatsDto {
poolDistribution: Record<string, number>;
expectedValue: Record<string, number>;
rolloverAmount: number;
consecutiveRollovers: number;
}
export interface ColumnGenerationResultDto {
columns: string[];
totalCost: number;
strategy: string;
}
export interface ColumnEvaluationResultDto {
results: { column: string; correct: number }[];
summary: Record<string, number>;
}
export interface SporTotoPredictionResultDto {
bulletin: SporTotoBulletinDto;
matchAnalysis: Record<string, unknown>;
systemCoupon: {
columns: string[];
cost: number;
};
evReport: {
expectedValue: number;
playRecommendation: string;
};
}
export interface RolloverHistoryItemDto {
bulletinId: string;
gameCycleNo: number;
rolloverAmount: number;
drawDate: string;
}
// ========================
// Service Methods
// ========================
const syncFromApi = () => {
return apiRequest<ApiResponse<unknown>>({
url: "/spor-toto/sync",
client: "core",
method: "post",
});
};
const listBulletins = (status?: string, limit?: number) => {
return apiRequest<ApiResponse<SporTotoBulletinDto[]>>({
url: "/spor-toto/bulletins",
client: "core",
method: "get",
params: { status, limit },
});
};
const getBulletinById = (id: string) => {
return apiRequest<ApiResponse<SporTotoBulletinDto>>({
url: `/spor-toto/bulletins/${id}`,
client: "core",
method: "get",
});
};
const createBulletin = (dto: CreateBulletinDto) => {
return apiRequest<ApiResponse<SporTotoBulletinDto>>({
url: "/spor-toto/bulletins",
client: "core",
method: "post",
data: dto,
});
};
const updateResults = (id: string, dto: UpdateResultsDto) => {
return apiRequest<ApiResponse<SporTotoBulletinDto>>({
url: `/spor-toto/bulletins/${id}/results`,
client: "core",
method: "patch",
data: dto,
});
};
const getBulletinStats = (id: string) => {
return apiRequest<ApiResponse<SporTotoStatsDto>>({
url: `/spor-toto/bulletins/${id}/stats`,
client: "core",
method: "get",
});
};
const getRolloverHistory = (limit?: number) => {
return apiRequest<ApiResponse<RolloverHistoryItemDto[]>>({
url: "/spor-toto/history",
client: "core",
method: "get",
params: { limit },
});
};
const generateColumns = (dto: GenerateColumnsDto) => {
return apiRequest<ApiResponse<ColumnGenerationResultDto>>({
url: "/spor-toto/columns/generate",
client: "core",
method: "post",
data: dto,
});
};
const evaluateColumns = (dto: EvaluateColumnsDto) => {
return apiRequest<ApiResponse<ColumnEvaluationResultDto>>({
url: "/spor-toto/columns/evaluate",
client: "core",
method: "post",
data: dto,
});
};
const generatePrediction = (dto: GenerateSporTotoPredictionDto) => {
return apiRequest<ApiResponse<SporTotoPredictionResultDto>>({
url: "/spor-toto/predict",
client: "core",
method: "post",
data: dto,
});
};
export const sporTotoService = {
syncFromApi,
listBulletins,
getBulletinById,
createBulletin,
updateResults,
getBulletinStats,
getRolloverHistory,
generateColumns,
evaluateColumns,
generatePrediction,
};
+15
View File
@@ -0,0 +1,15 @@
// Re-export types from service for barrel export convenience
export type {
CreateBulletinDto,
UpdateResultsDto,
GenerateColumnsDto,
EvaluateColumnsDto,
GenerateSporTotoPredictionDto,
SporTotoMatchDto,
SporTotoBulletinDto,
SporTotoStatsDto,
ColumnGenerationResultDto,
ColumnEvaluationResultDto,
SporTotoPredictionResultDto,
RolloverHistoryItemDto,
} from "./service";
+73
View File
@@ -0,0 +1,73 @@
import { useQuery, useMutation } from "@tanstack/react-query";
import { sporTotoService } from "./service";
import type {
GenerateColumnsDto,
EvaluateColumnsDto,
GenerateSporTotoPredictionDto,
} from "./service";
export const SporTotoQueryKeys = {
all: ["spor-toto"] as const,
bulletins: (params?: { status?: string; limit?: number }) =>
[...SporTotoQueryKeys.all, "bulletins", params] as const,
bulletin: (id: string) => [...SporTotoQueryKeys.all, "bulletin", id] as const,
bulletinStats: (id: string) =>
[...SporTotoQueryKeys.all, "bulletin-stats", id] as const,
rolloverHistory: (limit?: number) =>
[...SporTotoQueryKeys.all, "rollover-history", limit] as const,
};
export const useBulletins = (status?: string, limit?: number) => {
return useQuery({
queryKey: SporTotoQueryKeys.bulletins({ status, limit }),
queryFn: () => sporTotoService.listBulletins(status, limit),
});
};
export const useBulletinById = (id: string) => {
return useQuery({
queryKey: SporTotoQueryKeys.bulletin(id),
queryFn: () => sporTotoService.getBulletinById(id),
enabled: !!id,
});
};
export const useBulletinStats = (id: string) => {
return useQuery({
queryKey: SporTotoQueryKeys.bulletinStats(id),
queryFn: () => sporTotoService.getBulletinStats(id),
enabled: !!id,
});
};
export const useRolloverHistory = (limit?: number) => {
return useQuery({
queryKey: SporTotoQueryKeys.rolloverHistory(limit),
queryFn: () => sporTotoService.getRolloverHistory(limit),
});
};
export const useSyncBulletin = () => {
return useMutation({
mutationFn: () => sporTotoService.syncFromApi(),
});
};
export const useGenerateColumns = () => {
return useMutation({
mutationFn: (dto: GenerateColumnsDto) => sporTotoService.generateColumns(dto),
});
};
export const useEvaluateColumns = () => {
return useMutation({
mutationFn: (dto: EvaluateColumnsDto) => sporTotoService.evaluateColumns(dto),
});
};
export const useGeneratePrediction = () => {
return useMutation({
mutationFn: (dto: GenerateSporTotoPredictionDto) =>
sporTotoService.generatePrediction(dto),
});
};