Initial commit: fabric-trade-admin panel with responsive layouts and UI refinements.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user