| | import apiClient from "./client"; |
| | import type { |
| | GenerateResponse, |
| | BatchResponse, |
| | MatrixGenerateResponse, |
| | TestingMatrixResponse, |
| | AnglesResponse, |
| | ConceptsResponse, |
| | CompatibleConceptsResponse, |
| | AngleInfo, |
| | ConceptInfo, |
| | DbStatsResponse, |
| | AdsListResponse, |
| | AdCreativeDB, |
| | HealthResponse, |
| | ApiRootResponse, |
| | ImageCorrectResponse, |
| | ImageRegenerateResponse, |
| | ModelsListResponse, |
| | LoginResponse, |
| | Niche, |
| | CreativeAnalysisResponse, |
| | CreativeModifyResponse, |
| | FileUploadResponse, |
| | ModificationMode, |
| | CreativeAnalysisData, |
| | MotivatorGenerateRequest, |
| | MotivatorGenerateResponse, |
| | } from "../../types/api"; |
| |
|
| | |
| | export const getHealth = async (): Promise<HealthResponse> => { |
| | const response = await apiClient.get<HealthResponse>("/health"); |
| | return response.data; |
| | }; |
| |
|
| | export const getApiInfo = async (): Promise<ApiRootResponse> => { |
| | const response = await apiClient.get<ApiRootResponse>("/"); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const generateAd = async (params: { |
| | niche: Niche; |
| | num_images: number; |
| | image_model?: string | null; |
| | target_audience?: string | null; |
| | offer?: string | null; |
| | use_trending?: boolean; |
| | trending_context?: string | null; |
| | }): Promise<GenerateResponse> => { |
| | const response = await apiClient.post<GenerateResponse>("/generate", params); |
| | return response.data; |
| | }; |
| |
|
| | export const generateBatch = async (params: { |
| | niche: Niche; |
| | count: number; |
| | image_model?: string | null; |
| | method?: "standard" | "matrix" | null; |
| | target_audience?: string | null; |
| | offer?: string | null; |
| | }): Promise<BatchResponse> => { |
| | const response = await apiClient.post<BatchResponse>("/generate/batch", params); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const generateMatrixAd = async (params: { |
| | niche: Niche; |
| | angle_key?: string | null; |
| | concept_key?: string | null; |
| | custom_angle?: string | null; |
| | custom_concept?: string | null; |
| | num_images: number; |
| | image_model?: string | null; |
| | target_audience?: string | null; |
| | offer?: string | null; |
| | core_motivator?: string; |
| | }): Promise<MatrixGenerateResponse> => { |
| | const response = await apiClient.post<MatrixGenerateResponse>("/matrix/generate", params); |
| | return response.data; |
| | }; |
| |
|
| | export const generateMotivators = async ( |
| | params: MotivatorGenerateRequest |
| | ): Promise<MotivatorGenerateResponse> => { |
| | const response = await apiClient.post<MotivatorGenerateResponse>( |
| | "/api/motivator/generate", |
| | { ...params, count: params.count ?? 6 } |
| | ); |
| | return response.data; |
| | }; |
| |
|
| | |
| | const EXTENSIVE_POLL_INTERVAL_MS = 5500; |
| | const EXTENSIVE_POLL_TIMEOUT_MS = 20 * 60 * 1000; |
| |
|
| | export const getExtensiveJobStatus = async (jobId: string): Promise<{ job_id: string; status: "running" | "completed" | "failed"; error?: string }> => { |
| | const response = await apiClient.get(`/extensive/status/${jobId}`); |
| | return response.data; |
| | }; |
| |
|
| | export const getExtensiveJobResult = async (jobId: string): Promise<BatchResponse> => { |
| | const response = await apiClient.get<BatchResponse>(`/extensive/result/${jobId}`); |
| | return response.data; |
| | }; |
| |
|
| | export const generateExtensiveAd = async (params: { |
| | niche: Niche; |
| | custom_niche?: string | null; |
| | target_audience?: string | null; |
| | offer?: string | null; |
| | num_images: number; |
| | image_model?: string | null; |
| | num_strategies: number; |
| | }): Promise<BatchResponse> => { |
| | const requestParams = { |
| | niche: params.niche, |
| | num_images: params.num_images || 1, |
| | num_strategies: params.num_strategies || 1, |
| | ...(params.custom_niche && { custom_niche: params.custom_niche }), |
| | ...(params.target_audience && { target_audience: params.target_audience }), |
| | ...(params.offer && { offer: params.offer }), |
| | ...(params.image_model && { image_model: params.image_model }), |
| | }; |
| | const response = await apiClient.post<{ job_id: string; message?: string }>("/extensive/generate", requestParams); |
| | const jobId = response.data?.job_id; |
| | if (!jobId) { |
| | throw new Error("Server did not return a job ID"); |
| | } |
| | const deadline = Date.now() + EXTENSIVE_POLL_TIMEOUT_MS; |
| | for (;;) { |
| | const status = await getExtensiveJobStatus(jobId); |
| | if (status.status === "completed") { |
| | return getExtensiveJobResult(jobId); |
| | } |
| | if (status.status === "failed") { |
| | throw new Error(status.error || "Extensive generation failed"); |
| | } |
| | if (Date.now() >= deadline) { |
| | throw new Error("Extensive generation timed out. Try fewer strategies or images."); |
| | } |
| | await new Promise((r) => setTimeout(r, EXTENSIVE_POLL_INTERVAL_MS)); |
| | } |
| | }; |
| |
|
| | export const generateTestingMatrix = async (params: { |
| | niche: Niche; |
| | angle_count: number; |
| | concept_count: number; |
| | strategy: "balanced" | "top_performers" | "diverse"; |
| | }): Promise<TestingMatrixResponse> => { |
| | const response = await apiClient.post<TestingMatrixResponse>("/matrix/testing", params); |
| | return response.data; |
| | }; |
| |
|
| | export const getAllAngles = async (): Promise<AnglesResponse> => { |
| | const response = await apiClient.get<AnglesResponse>("/matrix/angles"); |
| | return response.data; |
| | }; |
| |
|
| | export const getAllConcepts = async (): Promise<ConceptsResponse> => { |
| | const response = await apiClient.get<ConceptsResponse>("/matrix/concepts"); |
| | return response.data; |
| | }; |
| |
|
| | export const getAngle = async (angleKey: string): Promise<AngleInfo> => { |
| | const response = await apiClient.get<AngleInfo>(`/matrix/angle/${angleKey}`); |
| | return response.data; |
| | }; |
| |
|
| | export const getConcept = async (conceptKey: string): Promise<ConceptInfo> => { |
| | const response = await apiClient.get<ConceptInfo>(`/matrix/concept/${conceptKey}`); |
| | return response.data; |
| | }; |
| |
|
| | export const getCompatibleConcepts = async (angleKey: string): Promise<CompatibleConceptsResponse> => { |
| | const response = await apiClient.get<CompatibleConceptsResponse>(`/matrix/compatible/${angleKey}`); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const refineCustomAngleOrConcept = async (params: { |
| | text: string; |
| | type: "angle" | "concept"; |
| | niche: Niche; |
| | goal?: string; |
| | }): Promise<{ status: string; type: "angle" | "concept"; refined?: any; error?: string }> => { |
| | const response = await apiClient.post("/matrix/refine-custom", params); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const getDbStats = async (): Promise<DbStatsResponse> => { |
| | const response = await apiClient.get<DbStatsResponse>("/db/stats"); |
| | return response.data; |
| | }; |
| |
|
| | export const listAds = async (params?: { |
| | niche?: string | null; |
| | generation_method?: string | null; |
| | limit?: number; |
| | offset?: number; |
| | }): Promise<AdsListResponse> => { |
| | const response = await apiClient.get<AdsListResponse>("/db/ads", { params }); |
| | return response.data; |
| | }; |
| |
|
| | export const getAd = async (adId: string): Promise<AdCreativeDB> => { |
| | const response = await apiClient.get<AdCreativeDB>(`/db/ad/${adId}`); |
| | return response.data; |
| | }; |
| |
|
| | export const deleteAd = async (adId: string): Promise<{ success: boolean; deleted_id: string }> => { |
| | const response = await apiClient.delete<{ success: boolean; deleted_id: string }>(`/db/ad/${adId}`); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const getStrategies = async (niche: Niche): Promise<any> => { |
| | const response = await apiClient.get(`/strategies/${niche}`); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const correctImage = async (params: { |
| | image_id: string; |
| | image_url?: string; |
| | user_instructions?: string; |
| | auto_analyze?: boolean; |
| | }): Promise<ImageCorrectResponse> => { |
| | const response = await apiClient.post<ImageCorrectResponse>("/api/correct", params); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const regenerateImage = async (params: { |
| | image_id: string; |
| | image_model?: string | null; |
| | preview_only?: boolean; |
| | }): Promise<ImageRegenerateResponse> => { |
| | const response = await apiClient.post<ImageRegenerateResponse>("/api/regenerate", { |
| | ...params, |
| | preview_only: params.preview_only ?? true, |
| | }); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const confirmImageSelection = async (params: { |
| | image_id: string; |
| | selection: "new" | "original"; |
| | new_image_url?: string | null; |
| | new_r2_url?: string | null; |
| | new_filename?: string | null; |
| | new_model?: string | null; |
| | new_seed?: number | null; |
| | }): Promise<{ status: string; message: string; selection: string; new_image_url?: string }> => { |
| | const response = await apiClient.post("/api/regenerate/confirm", params); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const getImageModels = async (): Promise<ModelsListResponse> => { |
| | const response = await apiClient.get<ModelsListResponse>("/api/models"); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const login = async (username: string, password: string): Promise<LoginResponse> => { |
| | const response = await apiClient.post<LoginResponse>("/auth/login", { |
| | username, |
| | password, |
| | }); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const editAdCopy = async (params: { |
| | ad_id: string; |
| | field: "title" | "headline" | "primary_text" | "description" | "body_story" | "cta"; |
| | value: string; |
| | mode: "manual" | "ai"; |
| | user_suggestion?: string; |
| | }): Promise<{ edited_value: string; success: boolean }> => { |
| | const response = await apiClient.post<{ edited_value: string; success: boolean }>("/db/ad/edit", params); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const downloadImageProxy = async (params: { |
| | image_url?: string; |
| | image_id?: string; |
| | }): Promise<Blob> => { |
| | const response = await apiClient.get("/api/download-image", { |
| | params, |
| | responseType: "blob", |
| | }); |
| | return response.data as Blob; |
| | }; |
| |
|
| | |
| |
|
| | |
| | export const uploadCreative = async (file: File): Promise<FileUploadResponse> => { |
| | const formData = new FormData(); |
| | formData.append("file", file); |
| |
|
| | const response = await apiClient.post<FileUploadResponse>( |
| | "/api/creative/upload", |
| | formData, |
| | { |
| | headers: { |
| | "Content-Type": "multipart/form-data", |
| | }, |
| | } |
| | ); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const analyzeCreativeByUrl = async (params: { |
| | image_url: string; |
| | }): Promise<CreativeAnalysisResponse> => { |
| | const response = await apiClient.post<CreativeAnalysisResponse>( |
| | "/api/creative/analyze", |
| | params |
| | ); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const analyzeCreativeByFile = async ( |
| | file: File |
| | ): Promise<CreativeAnalysisResponse> => { |
| | const formData = new FormData(); |
| | formData.append("file", file); |
| |
|
| | const response = await apiClient.post<CreativeAnalysisResponse>( |
| | "/api/creative/analyze/upload", |
| | formData, |
| | { |
| | headers: { |
| | "Content-Type": "multipart/form-data", |
| | }, |
| | } |
| | ); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const modifyCreative = async (params: { |
| | image_url: string; |
| | analysis?: CreativeAnalysisData | null; |
| | angle?: string; |
| | concept?: string; |
| | mode: ModificationMode; |
| | image_model?: string | null; |
| | user_prompt?: string; |
| | }): Promise<CreativeModifyResponse> => { |
| | const response = await apiClient.post<CreativeModifyResponse>( |
| | "/api/creative/modify", |
| | params |
| | ); |
| | return response.data; |
| | }; |
| |
|
| | |
| | export const exportBulkAds = async (adIds: string[]): Promise<Blob> => { |
| | const response = await apiClient.post( |
| | "/api/export/bulk", |
| | { ad_ids: adIds }, |
| | { responseType: "blob" } |
| | ); |
| | return response.data as Blob; |
| | }; |
| |
|