diff --git a/src/components/icons/IconShare.vue b/src/components/icons/IconShare.vue new file mode 100644 index 0000000..b51f8e6 --- /dev/null +++ b/src/components/icons/IconShare.vue @@ -0,0 +1,41 @@ + + + diff --git a/src/components/layout/BottomNav.vue b/src/components/layout/BottomNav.vue index 8107353..32e9430 100644 --- a/src/components/layout/BottomNav.vue +++ b/src/components/layout/BottomNav.vue @@ -14,9 +14,9 @@ function navigate(path: string, event: Event) { const target = event.currentTarget if (target instanceof HTMLElement) target.blur() - // «ثبت سفارش»: سبد خالی → انتخاب شرکت؛ در غیر این صورت سبد خرید + // «ثبت سفارش»: سبد خالی → دسته‌بندی‌ها؛ در غیر این صورت سبد خرید if (path === '/cart' && cartStore.itemCount === 0) { - router.push('/companies') + router.push('/categories') return } router.push(path) diff --git a/src/composables/useCartPage.ts b/src/composables/useCartPage.ts index 59d240b..2a40f47 100644 --- a/src/composables/useCartPage.ts +++ b/src/composables/useCartPage.ts @@ -74,12 +74,7 @@ export function useCartPage() { async function createNewInvoice() { await cartStore.createNewCartForSameCompany() showFullDialog.value = false - const companyId = cartStore.selectedCompanyId || cartStore.activeCart?.companyId - if (companyId) { - router.push(`/companies/${companyId}/catalogs`) - } else { - router.push('/companies') - } + router.push('/categories') } onMounted(() => { diff --git a/src/router/index.ts b/src/router/index.ts index e59e28a..97779a4 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -121,8 +121,13 @@ const router = createRouter({ { path: '/companies/:companyId/catalogs/:catalogId/products', name: 'company-products', - component: () => import('@/views/products/ProductListView.vue'), - meta: { requiresAuth: true }, + redirect: (to) => ({ + path: '/products', + query: { + catalogId: String(to.params.catalogId ?? ''), + companyId: String(to.params.companyId ?? ''), + }, + }), }, { path: '/cart', diff --git a/src/services/agentApi.ts b/src/services/agentApi.ts index bbd3128..88e615e 100644 --- a/src/services/agentApi.ts +++ b/src/services/agentApi.ts @@ -25,6 +25,7 @@ export type BrowseProductDto = { companyId?: string catalogId?: string catalogCode?: string + catalogName?: string color?: string minMeterage?: number orderMultiplier?: number @@ -80,12 +81,16 @@ export async function fetchCatalogCategories() { export async function fetchBrowseProducts(query?: { categoryId?: string season?: string + catalogId?: string + companyId?: string }) { return apiRequest('/products', { query: { activeOnly: true, categoryId: query?.categoryId, season: query?.season, + catalogId: query?.catalogId, + companyId: query?.companyId, }, }) } diff --git a/src/stores/cart.ts b/src/stores/cart.ts index 4272302..fd39931 100644 --- a/src/stores/cart.ts +++ b/src/stores/cart.ts @@ -231,14 +231,15 @@ export const useCartStore = defineStore('cart', () => { catalogCode: string, meterage: number, ): Promise<{ success: boolean; message?: string }> { - const company = catalogStore.getCompany(product.companyId) - if (!company) { - return { success: false, message: 'شرکت محصول یافت نشد.' } + if (!catalogStore.companies.length) { + await catalogStore.loadCompanies() } - - const cart = getOrCreateCart(company) - const companyMax = company.maxMeteragePerInvoice - const currentCompanyMeterage = companyMeterage(cart, company.id) + const company = catalogStore.getCompany(product.companyId) + const cart = activeCart.value ?? emptyCart() + const companyMax = company?.maxMeteragePerInvoice ?? DEFAULT_MAX_METERAGE + const currentCompanyMeterage = product.companyId + ? companyMeterage(cart, product.companyId) + : 0 const existing = cart.items.find((i) => i.productId === product.id) const previousMeterage = existing?.meterage ?? 0 @@ -254,6 +255,9 @@ export const useCartStore = defineStore('cart', () => { } if (useLocalCart()) { + if (!company) { + return { success: false, message: 'شرکت محصول یافت نشد.' } + } return addItemLocal(product, catalogCode, meterage, company) } @@ -271,7 +275,7 @@ export const useCartStore = defineStore('cart', () => { }) } applyServerCart(serverCart) - selectedCompanyId.value = company.id + selectedCompanyId.value = company?.id || product.companyId || selectedCompanyId.value return { success: true } } catch (e) { return { diff --git a/src/stores/crm.ts b/src/stores/crm.ts index 2e4e933..9b3e634 100644 --- a/src/stores/crm.ts +++ b/src/stores/crm.ts @@ -25,6 +25,7 @@ function mapProduct(p: { companyId?: string catalogId?: string catalogCode?: string + catalogName?: string color?: string minMeterage?: number orderMultiplier?: number @@ -63,6 +64,7 @@ function mapProduct(p: { companyId: p.companyId, catalogId: p.catalogId, catalogCode: p.catalogCode, + catalogName: p.catalogName, color: p.color, minMeterage: p.minMeterage ?? 30, orderMultiplier: p.orderMultiplier ?? 10, @@ -87,7 +89,12 @@ export const useCrmStore = defineStore('crm', () => { return data } - async function loadBrowseProducts(query?: { categoryId?: string; season?: string }) { + async function loadBrowseProducts(query?: { + categoryId?: string + season?: string + catalogId?: string + companyId?: string + }) { const list = await fetchBrowseProducts(query) browseProducts.value = list.map(mapProduct) return browseProducts.value @@ -101,6 +108,7 @@ export const useCrmStore = defineStore('crm', () => { companyId?: string catalogId?: string catalogCode?: string + catalogName?: string color?: string minMeterage?: number orderMultiplier?: number diff --git a/src/types/crm.ts b/src/types/crm.ts index c4819f4..cedb2c7 100644 --- a/src/types/crm.ts +++ b/src/types/crm.ts @@ -92,6 +92,7 @@ export interface CatalogProductCard { companyId?: string catalogId?: string catalogCode?: string + catalogName?: string color?: string minMeterage?: number orderMultiplier?: number diff --git a/src/utils/navigation.ts b/src/utils/navigation.ts index 75bbac6..bb72fc0 100644 --- a/src/utils/navigation.ts +++ b/src/utils/navigation.ts @@ -34,9 +34,10 @@ export const DESKTOP_NAV_ITEMS: NavItem[] = [ { name: 'profile', path: '/profile', label: 'پروفایل', icon: IconProfile }, ] -export function getOrderingPath(activeCompanyId: string | null | undefined): string { - if (activeCompanyId) return `/companies/${activeCompanyId}/catalogs` - return '/companies' +export const SHOP_BROWSE_PATH = '/categories' + +export function getOrderingPath(_activeCompanyId?: string | null): string { + return SHOP_BROWSE_PATH } const CATALOG_PATHS = [ @@ -51,7 +52,12 @@ const CATALOG_PATHS = [ export function isNavItemActive(name: string, path: string, currentPath: string): boolean { if (name === 'ordering') { - return currentPath.startsWith('/companies/') + return ( + currentPath.startsWith('/categories') || + currentPath.startsWith('/products') || + currentPath.startsWith('/product') || + currentPath.startsWith('/catalogs') + ) } if (name === 'home') { return currentPath === '/' diff --git a/src/views/OrdersView.vue b/src/views/OrdersView.vue index 8c6ac44..12e0198 100644 --- a/src/views/OrdersView.vue +++ b/src/views/OrdersView.vue @@ -88,7 +88,7 @@ const desktopFilterTabs: { id: DesktopOrderFilterId; label: string }[] = [ @set-desktop-filter="setDesktopFilter" @select="goToOrder" @set-page="setPage" - @new-order="router.push('/companies')" + @new-order="router.push('/categories')" /> diff --git a/src/views/auth/LoginView.vue b/src/views/auth/LoginView.vue index 5bd20b8..f1a0986 100644 --- a/src/views/auth/LoginView.vue +++ b/src/views/auth/LoginView.vue @@ -77,7 +77,6 @@ async function submit() {
-
🧵

ورود به سامانه

سامانه سفارش عمده پارچه

diff --git a/src/views/cart/CartView.vue b/src/views/cart/CartView.vue index 939f86f..35e2b3d 100644 --- a/src/views/cart/CartView.vue +++ b/src/views/cart/CartView.vue @@ -24,12 +24,7 @@ const { } = useCartPage() function goToOrdering() { - const companyId = cartStore.selectedCompanyId || cartStore.activeCart?.companyId - if (companyId) { - router.push(`/companies/${companyId}/catalogs`) - return - } - router.push('/companies') + router.push('/categories') } @@ -50,7 +45,7 @@ function goToOrdering() { @back="router.push('/')" @remove="removeItem" @checkout="proceedToCheckout" - @select-company="router.push('/companies')" + @select-company="goToOrdering()" /> diff --git a/src/views/cart/components/DesktopCartPage.vue b/src/views/cart/components/DesktopCartPage.vue index cfb3c4d..6093e63 100644 --- a/src/views/cart/components/DesktopCartPage.vue +++ b/src/views/cart/components/DesktopCartPage.vue @@ -88,13 +88,12 @@ const quickLinks = [

سبد خرید شما خالی است

- برای ثبت سفارش جدید، ابتدا شرکت موردنظر را انتخاب کنید و سپس کالیته و محصولات - را به سبد اضافه کنید. + از دسته‌بندی یا کالیته محصول را انتخاب کنید، جزئیات را ببینید و به سبد اضافه کنید.

- - انتخاب شرکت + + مشاهده محصولات diff --git a/src/views/catalogs/CatalogListView.vue b/src/views/catalogs/CatalogListView.vue index 35ac0d0..b00e88a 100644 --- a/src/views/catalogs/CatalogListView.vue +++ b/src/views/catalogs/CatalogListView.vue @@ -32,7 +32,10 @@ onMounted(load) watch(companyId, load) function openCatalog(catalogId: string) { - router.push(`/companies/${companyId.value}/catalogs/${catalogId}/products`) + router.push({ + path: '/products', + query: { catalogId, companyId: companyId.value }, + }) } function getProductCount(catalogId: string) { diff --git a/src/views/catalogs/CatalogRequestView.vue b/src/views/catalogs/CatalogRequestView.vue index 4c2d2d2..3577bf3 100644 --- a/src/views/catalogs/CatalogRequestView.vue +++ b/src/views/catalogs/CatalogRequestView.vue @@ -38,9 +38,12 @@ onMounted(async () => { error.value = null try { const list = await crm.loadBrowseProducts() - products.value = list - if (preselectId.value) { - quantities.value = { ...quantities.value, [preselectId.value]: 1 } + const selected = preselectId.value + products.value = selected + ? [...list].sort((a, b) => Number(b.id === selected) - Number(a.id === selected)) + : list + if (selected) { + quantities.value = { ...quantities.value, [selected]: 1 } } } catch (e) { error.value = e instanceof Error ? e.message : 'بارگذاری محصولات ناموفق بود.' @@ -79,11 +82,18 @@ async function submit() {
-

محصولات و تعداد اقلام موردنظر را مشخص کنید.

+

+ {{ preselectId ? 'این محصول برای درخواست کالیته انتخاب شده است. در صورت نیاز اقلام دیگر را هم اضافه کنید.' : 'محصولات و تعداد اقلام موردنظر را مشخص کنید.' }} +

{{ error }}