added front - react+ts

ocr improved
This commit is contained in:
2025-12-11 05:20:53 +03:00
parent 73b1477368
commit 02681340c5
39 changed files with 6286 additions and 267 deletions

View File

@@ -0,0 +1,67 @@
import axios from 'axios';
import type {
CatalogItem,
CreateInvoiceRequest,
MatchRequest, // Используем новый тип
HealthResponse,
InvoiceResponse,
ProductMatch,
Recommendation,
UnmatchedItem
} from './types';
// Базовый URL
const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8080/api';
const apiClient = axios.create({
baseURL: API_URL,
headers: {
'Content-Type': 'application/json',
},
});
apiClient.interceptors.response.use(
(response) => response,
(error) => {
console.error('API Error:', error);
return Promise.reject(error);
}
);
export const api = {
checkHealth: async (): Promise<HealthResponse> => {
const { data } = await apiClient.get<HealthResponse>('/health');
return data;
},
getRecommendations: async (): Promise<Recommendation[]> => {
const { data } = await apiClient.get<Recommendation[]>('/recommendations');
return data;
},
getCatalogItems: async (): Promise<CatalogItem[]> => {
const { data } = await apiClient.get<CatalogItem[]>('/ocr/catalog');
return data;
},
getMatches: async (): Promise<ProductMatch[]> => {
const { data } = await apiClient.get<ProductMatch[]>('/ocr/matches');
return data;
},
getUnmatched: async (): Promise<UnmatchedItem[]> => {
const { data } = await apiClient.get<UnmatchedItem[]>('/ocr/unmatched');
return data;
},
// Обновили тип аргумента payload
createMatch: async (payload: MatchRequest): Promise<{ status: string }> => {
const { data } = await apiClient.post<{ status: string }>('/ocr/match', payload);
return data;
},
createInvoice: async (payload: CreateInvoiceRequest): Promise<InvoiceResponse> => {
const { data } = await apiClient.post<InvoiceResponse>('/invoices/send', payload);
return data;
},
};

View File

@@ -0,0 +1,98 @@
// --- Общие типы ---
export type UUID = string;
// --- Каталог и Фасовки (API v2.0) ---
export interface ProductContainer {
id: UUID;
name: string; // "Пачка 180г"
count: number; // 0.180
}
export interface CatalogItem {
// Основные поля (snake_case)
id: UUID;
name: string;
code: string;
measure_unit: string; // "кг", "л"
containers: ProductContainer[]; // Массив фасовок
// Fallback (на всякий случай)
ID?: UUID;
Name?: string;
Code?: string;
MeasureUnit?: string;
Containers?: ProductContainer[];
}
// --- Матчинг (Обучение) ---
export interface MatchRequest {
raw_name: string;
product_id: UUID;
quantity: number;
container_id?: UUID; // Новое поле
}
export interface ProductMatch {
// snake_case (v2.0)
raw_name: string;
product_id: UUID;
product?: CatalogItem;
quantity: number;
container_id?: UUID;
container?: ProductContainer;
updated_at: string;
// Fallback
RawName?: string;
ProductID?: UUID;
Product?: CatalogItem;
Quantity?: number;
ContainerId?: UUID;
Container?: ProductContainer;
}
// --- Нераспознанное ---
export interface UnmatchedItem {
raw_name: string;
count: number;
last_seen: string;
}
// --- Остальные типы (без изменений) ---
export interface Recommendation {
ID: UUID;
Type: string;
ProductID: UUID;
ProductName: string;
Reason: string;
CreatedAt: string;
}
export interface InvoiceItemRequest {
product_id: UUID;
amount: number;
price: number;
}
export interface CreateInvoiceRequest {
document_number: string;
date_incoming: string;
supplier_id: UUID;
store_id: UUID;
items: InvoiceItemRequest[];
}
export interface InvoiceResponse {
status: string;
created_number: string;
}
export interface HealthResponse {
status: string;
time: string;
}