167 lines
4.2 KiB
TypeScript
167 lines
4.2 KiB
TypeScript
import { computed, inject, provide, reactive, ref, type InjectionKey } from 'vue'
|
|
import { useRouter } from 'vue-router'
|
|
import { companies, orders as initialOrders } from '@/data/mockData'
|
|
import { generateOrderNumber } from '@/utils/format'
|
|
import type { Order, SettlementMethod } from '@/types'
|
|
|
|
import { useToast } from '@/composables/useToast'
|
|
|
|
export function useOrdersPage() {
|
|
const router = useRouter()
|
|
const toast = useToast()
|
|
|
|
const orderList = ref<Order[]>([...initialOrders])
|
|
const activeTab = ref('all')
|
|
const selectedOrderId = ref<string>('')
|
|
const searchQuery = ref('')
|
|
const showAddModal = ref(false)
|
|
const showDetailPanel = ref(false)
|
|
const showDetailModal = ref(false)
|
|
const formError = ref('')
|
|
|
|
const emptyForm = () => ({
|
|
customerName: '',
|
|
companyId: companies[0]?.id ?? '',
|
|
settlementMethod: 'check' as SettlementMethod,
|
|
meterage: 1000,
|
|
customerPhone: '',
|
|
})
|
|
|
|
const form = reactive(emptyForm())
|
|
|
|
const isFormValid = computed(
|
|
() => form.customerName.trim().length > 0 && form.companyId.length > 0,
|
|
)
|
|
|
|
const filteredOrders = computed(() => {
|
|
let list = orderList.value
|
|
if (activeTab.value !== 'all') {
|
|
list = list.filter((o) => o.status === activeTab.value)
|
|
}
|
|
if (searchQuery.value.trim()) {
|
|
const q = searchQuery.value.trim()
|
|
list = list.filter(
|
|
(o) => o.orderNumber.includes(q) || o.customerName.includes(q),
|
|
)
|
|
}
|
|
return list
|
|
})
|
|
|
|
const selectedOrder = computed(() =>
|
|
orderList.value.find((o) => o.id === selectedOrderId.value) ?? null,
|
|
)
|
|
|
|
function selectOrder(order: Order, openDetail = false) {
|
|
selectedOrderId.value = order.id
|
|
if (openDetail) {
|
|
showDetailPanel.value = true
|
|
}
|
|
}
|
|
|
|
function openOrderDetail(order: Order) {
|
|
selectedOrderId.value = order.id
|
|
showDetailModal.value = true
|
|
}
|
|
|
|
function closeDetailPanel() {
|
|
showDetailPanel.value = false
|
|
}
|
|
|
|
function closeDetailModal() {
|
|
showDetailModal.value = false
|
|
}
|
|
|
|
function settlementLabel(method: string) {
|
|
return method === 'check' ? 'چکی' : 'نقدی'
|
|
}
|
|
|
|
function goPricing(order: Order) {
|
|
router.push(`/orders/${order.id}/pricing`)
|
|
}
|
|
|
|
function goChecks(order: Order) {
|
|
router.push(`/orders/${order.id}/checks`)
|
|
}
|
|
|
|
function openAddModal() {
|
|
Object.assign(form, emptyForm())
|
|
formError.value = ''
|
|
showAddModal.value = true
|
|
}
|
|
|
|
function closeAddModal() {
|
|
showAddModal.value = false
|
|
formError.value = ''
|
|
}
|
|
|
|
function submitAddOrder() {
|
|
if (!isFormValid.value) {
|
|
formError.value = 'نام مشتری و شرکت الزامی هستند.'
|
|
return
|
|
}
|
|
|
|
const company = companies.find((c) => c.id === form.companyId)
|
|
const newOrder: Order = {
|
|
id: `ord-${crypto.randomUUID().slice(0, 8)}`,
|
|
orderNumber: generateOrderNumber(),
|
|
customerName: form.customerName.trim(),
|
|
companyName: company?.name ?? '—',
|
|
companyId: form.companyId,
|
|
settlementMethod: form.settlementMethod,
|
|
totalAmount: null,
|
|
meterage: form.meterage,
|
|
status: 'pending_review',
|
|
createdAt: new Date().toISOString(),
|
|
customerPhone: form.customerPhone.trim() || undefined,
|
|
items: [],
|
|
}
|
|
|
|
orderList.value.unshift(newOrder)
|
|
selectedOrderId.value = newOrder.id
|
|
toast.success('سفارش جدید ثبت شد.')
|
|
closeAddModal()
|
|
}
|
|
|
|
return {
|
|
companies,
|
|
orderList,
|
|
activeTab,
|
|
selectedOrderId,
|
|
searchQuery,
|
|
showAddModal,
|
|
showDetailPanel,
|
|
showDetailModal,
|
|
formError,
|
|
form,
|
|
isFormValid,
|
|
filteredOrders,
|
|
selectedOrder,
|
|
selectOrder,
|
|
openOrderDetail,
|
|
closeDetailPanel,
|
|
closeDetailModal,
|
|
settlementLabel,
|
|
goPricing,
|
|
goChecks,
|
|
openAddModal,
|
|
closeAddModal,
|
|
submitAddOrder,
|
|
}
|
|
}
|
|
|
|
export type OrdersPageContext = ReturnType<typeof useOrdersPage>
|
|
|
|
export const ORDERS_PAGE_KEY: InjectionKey<OrdersPageContext> = Symbol('orders-page')
|
|
|
|
export function provideOrdersPage() {
|
|
const ctx = useOrdersPage()
|
|
provide(ORDERS_PAGE_KEY, ctx)
|
|
return ctx
|
|
}
|
|
|
|
export function useOrdersPageContext() {
|
|
const ctx = inject(ORDERS_PAGE_KEY)
|
|
if (!ctx) throw new Error('Orders page context is missing')
|
|
return ctx
|
|
}
|