Files
nademitex_user/src/stores/catalogRequests.ts
T

207 lines
5.0 KiB
TypeScript
Raw Normal View History

import { defineStore } from 'pinia'
import { computed, ref } from 'vue'
import { apiRequest } from '@/services/http'
const STORAGE_KEY = 'ft_catalog_requests'
export type CatalogRequestItem = {
productId: string
productName: string
productCode: string
quantity: number
}
/** UI statuses (legacy) + server statuses mapped in */
export type CatalogRequestStatus =
| 'submitted'
| 'reviewing'
| 'preparing'
| 'shipped'
| 'delivered'
| 'new'
| 'approved'
| 'ready_to_ship'
| 'returned'
| 'cancelled'
export type CatalogRequest = {
id: string
createdAt: string
status: CatalogRequestStatus
note?: string
items: CatalogRequestItem[]
}
const SERVER_TO_UI: Record<string, CatalogRequestStatus> = {
new: 'submitted',
approved: 'reviewing',
ready_to_ship: 'preparing',
delivered: 'delivered',
returned: 'delivered',
cancelled: 'submitted',
}
function readAll(): CatalogRequest[] {
try {
const raw = localStorage.getItem(STORAGE_KEY)
if (!raw) return []
const parsed = JSON.parse(raw) as unknown
return Array.isArray(parsed) ? (parsed as CatalogRequest[]) : []
} catch {
return []
}
}
function writeAll(list: CatalogRequest[]) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(list))
}
const STATUS_LABELS: Record<string, string> = {
submitted: 'ثبت‌شده',
reviewing: 'در حال بررسی',
preparing: 'آماده‌سازی',
shipped: 'ارسال‌شده',
delivered: 'تحویل‌شده',
new: 'درخواست جدید',
approved: 'تأیید شده',
ready_to_ship: 'آماده ارسال',
returned: 'بازگردانده شده',
cancelled: 'لغو شده',
}
function mapServerRow(row: {
id: string
createdAt: string
status: string
note?: string
items: Array<{
productId: string
productName: string
productCode: string
quantity: number
}>
}): CatalogRequest {
return {
id: row.id,
createdAt: row.createdAt,
status: SERVER_TO_UI[row.status] ?? (row.status as CatalogRequestStatus),
note: row.note,
items: row.items.map((i) => ({
productId: i.productId,
productName: i.productName,
productCode: i.productCode,
quantity: i.quantity,
})),
}
}
export const useCatalogRequestsStore = defineStore('catalogRequests', () => {
const requests = ref<CatalogRequest[]>(readAll())
const useApi = ref(true)
const sorted = computed(() =>
[...requests.value].sort((a, b) => b.createdAt.localeCompare(a.createdAt)),
)
function statusLabel(status: CatalogRequest['status']) {
return STATUS_LABELS[status] ?? status
}
async function hydrate() {
if (!useApi.value) {
requests.value = readAll()
return
}
try {
const rows = await apiRequest<
Array<{
id: string
createdAt: string
status: string
note?: string
items: Array<{
productId: string
productName: string
productCode: string
quantity: number
}>
}>
>('/catalog-requests')
requests.value = rows.map(mapServerRow)
writeAll(requests.value)
} catch {
useApi.value = false
requests.value = readAll()
}
}
async function create(input: { items: CatalogRequestItem[]; note?: string }) {
const items = input.items
.filter((i) => i.productId && i.quantity > 0)
.map((i) => ({
...i,
quantity: Math.max(1, Math.floor(i.quantity)),
}))
if (!items.length) {
return { success: false as const, message: 'حداقل یک قلم با تعداد معتبر لازم است.' }
}
if (useApi.value) {
try {
const row = await apiRequest<{
id: string
createdAt: string
status: string
note?: string
items: Array<{
productId: string
productName: string
productCode: string
quantity: number
}>
}>('/catalog-requests', {
method: 'POST',
body: {
note: input.note?.trim() || undefined,
items: items.map((i) => ({
productId: i.productId,
quantity: i.quantity,
})),
},
})
const mapped = mapServerRow(row)
requests.value = [mapped, ...requests.value.filter((r) => r.id !== mapped.id)]
writeAll(requests.value)
return { success: true as const, request: mapped }
} catch (err) {
useApi.value = false
// fall through to local
}
}
const row: CatalogRequest = {
id: `cr-${Date.now()}`,
createdAt: new Date().toISOString(),
status: 'submitted',
note: input.note?.trim() || undefined,
items,
}
requests.value = [row, ...requests.value]
writeAll(requests.value)
return { success: true as const, request: row }
}
function getById(id: string) {
return requests.value.find((r) => r.id === id) ?? null
}
return {
requests,
sorted,
statusLabel,
create,
getById,
hydrate,
}
})