Files
dashboards/apps/business/src/services/storeSpecialService.ts
T
Alireza HassaniandCursor 652f4d07b6 Show other-pages stats and store-specials AI matching.
Add the Statistics pages row for static_page views, wire specials AI match UI, and tidy Businesses page styles.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-16 17:33:44 +03:30

102 lines
2.5 KiB
TypeScript

import { apiRequest } from '../lib/api'
import { getActiveBusinessId } from '../lib/businessContext'
import type { StoreSpecial } from '../types/storeSpecial'
export interface StoreSpecialsListResponse {
items: StoreSpecial[]
total: number
page: number
pageSize: number
}
export interface CreateStoreSpecialPayload {
key: string
title: string
storeItemIds?: string[]
productIds?: string[]
sortOrder?: number
isActive?: boolean
}
export interface UpdateStoreSpecialPayload {
key?: string
title?: string
storeItemIds?: string[]
productIds?: string[]
sortOrder?: number
isActive?: boolean
}
function businessPath(suffix = '') {
const businessId = getActiveBusinessId()
if (!businessId) {
throw new Error('No active business selected. Please sign in again.')
}
return `/businesses/${businessId}/store-specials${suffix}`
}
export async function listStoreSpecials(page = 1, pageSize = 50, signal?: AbortSignal) {
return apiRequest<StoreSpecialsListResponse>(
`${businessPath()}?page=${page}&pageSize=${pageSize}`,
{ auth: true, signal },
)
}
export async function createStoreSpecial(payload: CreateStoreSpecialPayload) {
return apiRequest<{ message: string; special: StoreSpecial }>(businessPath(), {
method: 'POST',
auth: true,
body: payload,
})
}
export async function updateStoreSpecial(specialId: string, payload: UpdateStoreSpecialPayload) {
return apiRequest<{ message: string; special: StoreSpecial }>(businessPath(`/${specialId}`), {
method: 'PATCH',
auth: true,
body: payload,
})
}
export async function deleteStoreSpecial(specialId: string) {
return apiRequest<{ message: string }>(businessPath(`/${specialId}`), {
method: 'DELETE',
auth: true,
})
}
export interface SpecialItemsAiMatchCandidate {
storeItemId: string
productId: string
productTitle: string
productNameFa: string
productImage: string | null
variantId: string
variantLabel: string
currentPrice: number | null
score: number
}
export interface SpecialItemsAiMatchRow {
lineIndex: number
raw: string
price: number | null
selected: boolean
updatePrice: boolean
confidence: number
reason: string | null
candidate: SpecialItemsAiMatchCandidate | null
}
export async function matchStoreSpecialListWithAi(text: string, signal?: AbortSignal) {
return apiRequest<{ message: string; matches: SpecialItemsAiMatchRow[] }>(
businessPath('/ai-match'),
{
method: 'POST',
auth: true,
body: { text },
signal,
},
)
}