Add refusals tab to the order dashboard
Orders whose Nova Poshta status is a refusal (102/103/105/108) now show only under «Отказы», whether or not they have a receipt. GET /orders takes tab=no_receipt|has_receipt|refused instead of has_receipt. NP statuses are also polled for orders that already have a receipt, until NP reports a final status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@ import { cancelReceipt, createReceipts } from '@/api/receipts'
|
||||
import '@/pages/DashboardPage.css'
|
||||
import { useAuth } from '@/features/auth/useAuth'
|
||||
import { OrderDetailModal } from '@/features/orders/OrderDetailModal'
|
||||
import type { Order } from '@/features/orders/types'
|
||||
import type { Order, OrderTab } from '@/features/orders/types'
|
||||
import { useOrders } from '@/features/orders/useOrders'
|
||||
import { defaultPrepayment, prepaymentMatches, toKopecks } from '@/features/receipts/money'
|
||||
import { CANCELLABLE, RECEIPT_STATUS } from '@/features/receipts/types'
|
||||
@@ -19,11 +19,10 @@ const ROLE_LABEL: Record<string, string> = {
|
||||
viewer: 'Наблюдатель',
|
||||
}
|
||||
|
||||
type Tab = 'no_receipt' | 'has_receipt'
|
||||
|
||||
const TABS: { key: Tab; label: string }[] = [
|
||||
const TABS: { key: OrderTab; label: string }[] = [
|
||||
{ key: 'no_receipt', label: 'Без чека' },
|
||||
{ key: 'has_receipt', label: 'Выписаны чеки' },
|
||||
{ key: 'refused', label: 'Отказы' },
|
||||
]
|
||||
|
||||
function npStatusTone(order: Order): 'delivered' | 'processing' | 'danger' | 'new' {
|
||||
@@ -47,8 +46,8 @@ function paymentBadge(order: Order): { label: string; tone: 'delivered' | 'proce
|
||||
|
||||
export function DashboardPage() {
|
||||
const { user, logout } = useAuth()
|
||||
const [tab, setTab] = useState<Tab>('no_receipt')
|
||||
const { data: orders, isLoading, isError } = useOrders(tab === 'has_receipt')
|
||||
const [tab, setTab] = useState<OrderTab>('no_receipt')
|
||||
const { data: orders, isLoading, isError } = useOrders(tab)
|
||||
const queryClient = useQueryClient()
|
||||
const [selected, setSelected] = useState<Set<string>>(new Set())
|
||||
const [search, setSearch] = useState('')
|
||||
@@ -103,7 +102,8 @@ export function DashboardPage() {
|
||||
|
||||
async function handleCancel(order: Order) {
|
||||
if (!order.receipt_id) return
|
||||
if (!window.confirm(`Отменить ЕТТН-чек по заказу ${order.id}? Заказ вернётся в очередь.`)) return
|
||||
const outcome = tab === 'refused' ? 'Заказ останется в отказах.' : 'Заказ вернётся в очередь.'
|
||||
if (!window.confirm(`Отменить ЕТТН-чек по заказу ${order.id}? ${outcome}`)) return
|
||||
setCancellingId(order.id)
|
||||
try {
|
||||
await cancelReceipt(order.receipt_id)
|
||||
@@ -336,7 +336,7 @@ export function DashboardPage() {
|
||||
Чек
|
||||
</button>
|
||||
)}
|
||||
{order.receipt_status && (tab === 'has_receipt' || !CANCELLABLE.has(order.receipt_status)) && (
|
||||
{order.receipt_status && (tab !== 'no_receipt' || !CANCELLABLE.has(order.receipt_status)) && (
|
||||
<span
|
||||
className={`orders-status orders-status--${RECEIPT_STATUS[order.receipt_status].tone}`}
|
||||
title={order.receipt_error ?? undefined}
|
||||
@@ -344,7 +344,7 @@ export function DashboardPage() {
|
||||
{RECEIPT_STATUS[order.receipt_status].label}
|
||||
</span>
|
||||
)}
|
||||
{tab === 'has_receipt' && canFiscalize && order.receipt_status && CANCELLABLE.has(order.receipt_status) && (
|
||||
{tab !== 'no_receipt' && canFiscalize && order.receipt_status && CANCELLABLE.has(order.receipt_status) && (
|
||||
<button
|
||||
type="button"
|
||||
className="orders-delete-btn"
|
||||
@@ -354,7 +354,7 @@ export function DashboardPage() {
|
||||
Отменить
|
||||
</button>
|
||||
)}
|
||||
{canDelete && tab === 'no_receipt' && (
|
||||
{canDelete && (tab === 'no_receipt' || (tab === 'refused' && !order.has_receipt)) && (
|
||||
<button
|
||||
type="button"
|
||||
className="orders-delete-btn"
|
||||
|
||||
Reference in New Issue
Block a user