This commit is contained in:
Tomas Dvorak
2025-10-19 17:16:57 +02:00
parent e9a63073e5
commit 77213f4e83
76 changed files with 9728 additions and 935 deletions
+24 -2
View File
@@ -14,7 +14,18 @@ export interface AIGenerateBlogResp {
export async function generateBlogAI(payload: AIGenerateBlogReq): Promise<AIGenerateBlogResp> {
const { data } = await api.post<AIGenerateBlogResp>('/ai/blog/generate', payload);
return data;
// Handle potential JSON string response from AI (defensive parsing)
let parsedData = data;
if (typeof data === 'string') {
try {
parsedData = JSON.parse(data);
} catch {
throw new Error('AI vrátila neplatný formát odpovědi');
}
}
return parsedData;
}
export interface AIGenerateAboutReq {
@@ -34,5 +45,16 @@ export interface AIGenerateAboutResp {
export async function generateAboutAI(payload: AIGenerateAboutReq): Promise<AIGenerateAboutResp> {
const { data } = await api.post<AIGenerateAboutResp>('/ai/about/generate', payload);
return data;
// Handle potential JSON string response from AI (defensive parsing)
let parsedData = data;
if (typeof data === 'string') {
try {
parsedData = JSON.parse(data);
} catch {
throw new Error('AI vrátila neplatný formát odpovědi');
}
}
return parsedData;
}
+4
View File
@@ -21,6 +21,8 @@ export interface Article {
image_url?: string;
author?: { id: number; first_name?: string; last_name?: string; email: string };
category_id?: number;
category?: { id: number; name: string; description?: string; slug?: string; created_at?: string; updated_at?: string };
category_name?: string;
published?: boolean;
featured?: boolean;
created_at?: string;
@@ -41,6 +43,7 @@ export interface Article {
youtube_video_title?: string;
youtube_video_url?: string;
youtube_video_thumbnail?: string;
attachments?: Array<{ name: string; url: string; mime_type?: string; size?: number }>;
}
// --- Article ⇄ Match link ---
@@ -139,6 +142,7 @@ export interface CreateArticlePayload {
youtube_video_title?: string;
youtube_video_url?: string;
youtube_video_thumbnail?: string;
attachments?: Array<{ name: string; url: string; mime_type?: string; size?: number }>;
}
export async function createArticle(payload: CreateArticlePayload) {
+144
View File
@@ -0,0 +1,144 @@
import api from './api';
export interface ImageProcessRequest {
image_url: string;
operation?: string;
width?: number;
height?: number;
crop_x?: number;
crop_y?: number;
crop_width?: number;
crop_height?: number;
rotation?: number;
flip_h?: boolean;
flip_v?: boolean;
brightness?: number;
contrast?: number;
saturation?: number;
blur?: number;
sharpen?: number;
grayscale?: boolean;
quality?: number;
}
export interface QuickEditRequest {
image_url: string;
width?: number;
rotation?: number;
flip_h?: boolean;
flip_v?: boolean;
brightness?: number;
contrast?: number;
saturation?: number;
grayscale?: boolean;
quality?: number;
}
export interface ImageProcessResponse {
url: string;
format?: string;
}
/**
* Process image with various operations (crop, resize, filters, etc.)
*/
export const processImage = async (request: ImageProcessRequest): Promise<ImageProcessResponse> => {
const response = await api.post('/image-processing/process', request);
return response.data;
};
/**
* Quick edit for common operations in one call
*/
export const quickEditImage = async (request: QuickEditRequest): Promise<ImageProcessResponse> => {
const response = await api.post('/image-processing/quick-edit', request);
return response.data;
};
/**
* Crop and upload image file
*/
export const cropAndUpload = async (
file: File,
cropData?: { x: number; y: number; width: number; height: number },
quality = 85,
maxWidth = 1500
): Promise<ImageProcessResponse> => {
const formData = new FormData();
formData.append('image', file);
if (cropData) {
formData.append('crop_data', JSON.stringify(cropData));
}
formData.append('quality', quality.toString());
formData.append('max_width', maxWidth.toString());
const response = await api.post('/image-processing/crop-upload', formData, {
headers: {
'Content-Type': 'multipart/form-data',
},
});
return response.data;
};
/**
* Resize image to specific width (maintains aspect ratio)
*/
export const resizeImage = async (imageUrl: string, width: number, quality = 85): Promise<ImageProcessResponse> => {
return quickEditImage({
image_url: imageUrl,
width,
quality,
});
};
/**
* Apply filters to image
*/
export const applyFilters = async (
imageUrl: string,
filters: {
brightness?: number;
contrast?: number;
saturation?: number;
blur?: number;
grayscale?: boolean;
},
quality = 85
): Promise<ImageProcessResponse> => {
return quickEditImage({
image_url: imageUrl,
...filters,
quality,
});
};
/**
* Rotate image (90, 180, 270 degrees)
*/
export const rotateImage = async (imageUrl: string, rotation: number, quality = 85): Promise<ImageProcessResponse> => {
return quickEditImage({
image_url: imageUrl,
rotation,
quality,
});
};
/**
* Flip image horizontally or vertically
*/
export const flipImage = async (
imageUrl: string,
flipH: boolean,
flipV: boolean,
quality = 85
): Promise<ImageProcessResponse> => {
return quickEditImage({
image_url: imageUrl,
flip_h: flipH,
flip_v: flipV,
quality,
});
};