MAJOR UPPDATE: "First Ai"

feat: add AI categorization for products and enhance user management

- Integrated AI service for category suggestions in receipt import and product management.
- Added premium subscription feature for users with corresponding API endpoints.
- Implemented admin interface for managing pending product suggestions.
- Enhanced user management to include premium status and corresponding UI updates.
- Updated database schema to support new fields for premium status and product status.
This commit is contained in:
Nils-Johan Gynther
2026-04-19 10:34:21 +02:00
parent 0286ab0991
commit 054a19ed7c
30 changed files with 917 additions and 77 deletions
+66
View File
@@ -105,3 +105,69 @@ export async function bulkSetCategory(ids: number[], categoryId: number | null)
revalidatePath('/admin/products');
}
export async function suggestProductCategory(productId: number) {
const res = await fetch(`${API_BASE}/api/products/${productId}/suggest-category`, {
method: 'GET',
headers: { ...(await getAuthHeaders()) },
cache: 'no-store',
});
if (!res.ok) {
const text = await res.text();
throw new Error(`AI-kategorisering misslyckades: ${text}`);
}
return res.json() as Promise<{
categoryId: number;
categoryName: string;
path: string;
confidence: 'high' | 'medium' | 'low';
usedFallback: boolean;
}>;
}
export async function suggestBulkCategories(productIds?: number[]) {
const res = await fetch(`${API_BASE}/api/products/ai-categorize-bulk`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...(await getAuthHeaders()) },
body: JSON.stringify({ productIds }),
cache: 'no-store',
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Bulk-AI-kategorisering misslyckades: ${text}`);
}
return res.json() as Promise<
{
productId: number;
productName: string;
suggestion: {
categoryId: number;
categoryName: string;
path: string;
confidence: 'high' | 'medium' | 'low';
usedFallback: boolean;
};
}[]
>;
}
export async function setProductStatus(id: number, status: 'active' | 'rejected') {
const res = await fetch(`${API_BASE}/api/products/${id}/status`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json', ...(await getAuthHeaders()) },
body: JSON.stringify({ status }),
cache: 'no-store',
});
if (!res.ok) {
const text = await res.text();
throw new Error(`Kunde inte uppdatera status: ${text}`);
}
revalidatePath('/admin/products');
revalidatePath('/admin/products/pending');
}