@revenexx/cover 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/components/cart/position/CartPosition.vue +6 -1
- package/app/components/cart/view/CartListHeader.vue +6 -1
- package/app/components/cart/view/CartView.vue +10 -4
- package/app/components/layout/footer/Footer.vue +8 -1
- package/app/components/layout/header/AppBar.vue +5 -0
- package/app/components/layout/header/MainNav.vue +6 -1
- package/app/components/layout/header/TopBar.vue +5 -1
- package/package.json +1 -1
- package/server/utils/b2bService.ts +27 -9
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
// app.config feature switch — lean storefronts ship without order lists.
|
|
3
|
+
const featureOrderLists = computed(() =>
|
|
4
|
+
((useAppConfig().features ?? {}) as Record<string, boolean>).orderLists !== false,
|
|
5
|
+
);
|
|
6
|
+
|
|
2
7
|
import { slugify } from "../../../composables/useProducts";
|
|
3
8
|
import type { CalculatedCartLine } from "../../../interfaces/cart-calculation";
|
|
4
9
|
import type { CartItem } from "../../../interfaces/cart-item";
|
|
@@ -339,7 +344,7 @@ const hintColor = (type: string) =>
|
|
|
339
344
|
class="flex flex-col gap-0.5 shrink-0"
|
|
340
345
|
>
|
|
341
346
|
<UTooltip
|
|
342
|
-
v-if="role"
|
|
347
|
+
v-if="role && featureOrderLists"
|
|
343
348
|
:text="t('cart.bulk.saveToList')"
|
|
344
349
|
>
|
|
345
350
|
<UButton
|
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
// app.config feature switch — lean storefronts ship without order lists.
|
|
3
|
+
const featureOrderLists = computed(() =>
|
|
4
|
+
((useAppConfig().features ?? {}) as Record<string, boolean>).orderLists !== false,
|
|
5
|
+
);
|
|
6
|
+
|
|
2
7
|
/**
|
|
3
8
|
* Sticky cart list header: three-state multi-selector and the bulk action
|
|
4
9
|
* bar (visible from one selected position). The bulk actions mirror the
|
|
@@ -63,7 +68,7 @@ function bulkDelete(): void {
|
|
|
63
68
|
@click="actions.open('texts', selection.selected.value)"
|
|
64
69
|
/>
|
|
65
70
|
<UButton
|
|
66
|
-
v-if="role"
|
|
71
|
+
v-if="role && featureOrderLists"
|
|
67
72
|
:icon="icon('bookmark')"
|
|
68
73
|
color="neutral"
|
|
69
74
|
variant="ghost"
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
// Storefront feature switches (app.config `features`, default on).
|
|
3
|
+
const features = computed(() => (useAppConfig().features ?? {}) as Record<string, boolean>);
|
|
4
|
+
|
|
2
5
|
import CartExportModal from "../actions/CartExportModal.vue";
|
|
3
6
|
import CartCostCenterModal from "../actions/CartCostCenterModal.vue";
|
|
4
7
|
import CartPositionTextsModal from "../actions/CartPositionTextsModal.vue";
|
|
@@ -100,7 +103,7 @@ const messageColor = (severity: string) =>
|
|
|
100
103
|
<CartSwitcher class="print:hidden" />
|
|
101
104
|
</div>
|
|
102
105
|
<UButton
|
|
103
|
-
v-if="!isEmpty"
|
|
106
|
+
v-if="!isEmpty && features.directOrder !== false"
|
|
104
107
|
:icon="icon('direct-order')"
|
|
105
108
|
color="neutral"
|
|
106
109
|
variant="outline"
|
|
@@ -205,6 +208,7 @@ const messageColor = (severity: string) =>
|
|
|
205
208
|
tabindex="0"
|
|
206
209
|
/>
|
|
207
210
|
<UButton
|
|
211
|
+
v-if="features.directOrder !== false"
|
|
208
212
|
color="neutral"
|
|
209
213
|
variant="outline"
|
|
210
214
|
:icon="icon('direct-order')"
|
|
@@ -213,6 +217,7 @@ const messageColor = (severity: string) =>
|
|
|
213
217
|
tabindex="0"
|
|
214
218
|
/>
|
|
215
219
|
<UButton
|
|
220
|
+
v-if="features.orderLists !== false"
|
|
216
221
|
color="neutral"
|
|
217
222
|
variant="outline"
|
|
218
223
|
:icon="icon('order-list')"
|
|
@@ -226,7 +231,7 @@ const messageColor = (severity: string) =>
|
|
|
226
231
|
|
|
227
232
|
<!-- The fastest paths back to an order -->
|
|
228
233
|
<div class="mt-8 space-y-8">
|
|
229
|
-
<CartReorderStrip />
|
|
234
|
+
<CartReorderStrip v-if="features.reorderStrip !== false" />
|
|
230
235
|
<CartCrossSell popular />
|
|
231
236
|
</div>
|
|
232
237
|
</template>
|
|
@@ -266,7 +271,7 @@ const messageColor = (severity: string) =>
|
|
|
266
271
|
|
|
267
272
|
<!-- Revenue strips: fast reorder + cross-sell -->
|
|
268
273
|
<div class="mt-8 space-y-8">
|
|
269
|
-
<CartReorderStrip />
|
|
274
|
+
<CartReorderStrip v-if="features.reorderStrip !== false" />
|
|
270
275
|
<CartCrossSell />
|
|
271
276
|
</div>
|
|
272
277
|
</template>
|
|
@@ -283,7 +288,7 @@ const messageColor = (severity: string) =>
|
|
|
283
288
|
@update:open="actions.close()"
|
|
284
289
|
/>
|
|
285
290
|
<CartSaveToListModal
|
|
286
|
-
:open="actions.action.value.type === 'save'"
|
|
291
|
+
:open="features.orderLists !== false && actions.action.value.type === 'save'"
|
|
287
292
|
:line-keys="actions.action.value.lineKeys"
|
|
288
293
|
@update:open="actions.close()"
|
|
289
294
|
/>
|
|
@@ -294,6 +299,7 @@ const messageColor = (severity: string) =>
|
|
|
294
299
|
|
|
295
300
|
<!-- Quick entry: the full direct-order toolset in a wide lightbox -->
|
|
296
301
|
<UModal
|
|
302
|
+
v-if="features.directOrder !== false"
|
|
297
303
|
v-model:open="quickAddOpen"
|
|
298
304
|
:title="t('directOrder.title')"
|
|
299
305
|
:description="t('directOrder.description')"
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { footerLinks, legalLinks, shopContact } from "../../../config/navigation";
|
|
2
|
+
import { footerLinks as defaultFooterLinks, legalLinks as defaultLegalLinks, shopContact } from "../../../config/navigation";
|
|
3
|
+
|
|
4
|
+
// Consumers can replace the footer link columns / legal links via
|
|
5
|
+
// app.config (`footerLinks`, `legalLinks`) — a lean storefront points
|
|
6
|
+
// them at pages it actually ships instead of the demo's full sitemap.
|
|
7
|
+
const appConfig = useAppConfig();
|
|
8
|
+
const footerLinks = computed(() => (appConfig.footerLinks as typeof defaultFooterLinks | undefined) ?? defaultFooterLinks);
|
|
9
|
+
const legalLinks = computed(() => (appConfig.legalLinks as typeof defaultLegalLinks | undefined) ?? defaultLegalLinks);
|
|
3
10
|
|
|
4
11
|
const { icon } = useIcons();
|
|
5
12
|
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
// Storefront feature switches (app.config `features`, default: everything
|
|
3
|
+
// on) — lean themes turn off the surfaces their MVP does not ship.
|
|
4
|
+
const features = computed(() => (useAppConfig().features ?? {}) as Record<string, boolean>);
|
|
5
|
+
|
|
2
6
|
const { icon } = useIcons();
|
|
3
7
|
|
|
4
8
|
const { t } = useI18n();
|
|
@@ -59,6 +63,7 @@ const { navigateToSearch } = useSearch();
|
|
|
59
63
|
|
|
60
64
|
<template #right>
|
|
61
65
|
<LayoutHeaderActionItem
|
|
66
|
+
v-if="features.directOrder !== false"
|
|
62
67
|
:icon="icon('direct-order')"
|
|
63
68
|
:label="t('topbar.directOrder')"
|
|
64
69
|
:to="localePath('/account/direct-order')"
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { mainNavigation, mainNavigationSecondary } from "../../../config/navigation";
|
|
2
|
+
import { mainNavigation as defaultMainNav, mainNavigationSecondary as defaultSecondaryNav } from "../../../config/navigation";
|
|
3
|
+
|
|
4
|
+
// app.config override: lean storefronts link only to pages they ship.
|
|
5
|
+
const appConfig = useAppConfig();
|
|
6
|
+
const mainNavigation = computed(() => (appConfig.mainNavigation as typeof defaultMainNav | undefined) ?? defaultMainNav);
|
|
7
|
+
const mainNavigationSecondary = computed(() => (appConfig.mainNavigationSecondary as typeof defaultSecondaryNav | undefined) ?? defaultSecondaryNav);
|
|
3
8
|
|
|
4
9
|
const { t } = useI18n();
|
|
5
10
|
const localePath = useLocalePath();
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { topbarQuickLinks, topbarUsps } from "../../../config/navigation";
|
|
2
|
+
import { topbarQuickLinks as defaultQuickLinks, topbarUsps } from "../../../config/navigation";
|
|
3
|
+
|
|
4
|
+
// app.config override: lean storefronts link only to pages they ship.
|
|
5
|
+
const appConfig = useAppConfig();
|
|
6
|
+
const topbarQuickLinks = computed(() => (appConfig.topbarQuickLinks as typeof defaultQuickLinks | undefined) ?? defaultQuickLinks);
|
|
3
7
|
|
|
4
8
|
const { icon } = useIcons();
|
|
5
9
|
const { t } = useI18n();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revenexx/cover",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "Cover \u2014 revenexx design system for Nuxt. Distributed as a Nuxt layer: generic UI components, theming tokens and stores shared by the demo shop, custom storefronts and the Blokkli theme.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./nuxt.config.ts",
|
|
@@ -15,19 +15,37 @@ import { MockCartCalculationService } from "../services/MockCartCalculationServi
|
|
|
15
15
|
export const ORG_SETTINGS_COOKIE = "cover-org-settings";
|
|
16
16
|
|
|
17
17
|
export function resolveOrgSettingsOverride(event?: H3Event): Partial<OrganizationSettings> | undefined {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
// Base layer: the app's own organization defaults (app.config
|
|
19
|
+
// `orgSettings`) — a lean storefront ships simple B2C-ish settings
|
|
20
|
+
// (no cost centers/approvals, no minimum order value) without giving
|
|
21
|
+
// up the demo data. The dev-panel cookie still wins on top.
|
|
22
|
+
const appDefaults = useAppConfig().orgSettings as Partial<OrganizationSettings> | undefined;
|
|
23
|
+
|
|
24
|
+
let cookieOverride: Partial<OrganizationSettings> | undefined;
|
|
25
|
+
const raw = event ? getCookie(event, ORG_SETTINGS_COOKIE) : undefined;
|
|
26
|
+
if (raw) {
|
|
27
|
+
try {
|
|
28
|
+
cookieOverride = JSON.parse(raw) as Partial<OrganizationSettings>;
|
|
29
|
+
}
|
|
30
|
+
catch { /* ignore malformed cookie */ }
|
|
20
31
|
}
|
|
21
|
-
|
|
22
|
-
if (!
|
|
23
|
-
return
|
|
32
|
+
|
|
33
|
+
if (!appDefaults) {
|
|
34
|
+
return cookieOverride;
|
|
24
35
|
}
|
|
25
|
-
|
|
26
|
-
return
|
|
36
|
+
if (!cookieOverride) {
|
|
37
|
+
return appDefaults;
|
|
27
38
|
}
|
|
28
|
-
|
|
29
|
-
|
|
39
|
+
// Section-wise merge (the settings object is one level of sections
|
|
40
|
+
// with scalar leaves) — cookie sections win over app defaults.
|
|
41
|
+
const merged: Record<string, unknown> = { ...appDefaults };
|
|
42
|
+
for (const [key, value] of Object.entries(cookieOverride)) {
|
|
43
|
+
const base = (merged as Record<string, unknown>)[key];
|
|
44
|
+
merged[key] = (value && typeof value === "object" && base && typeof base === "object")
|
|
45
|
+
? { ...base, ...value }
|
|
46
|
+
: value;
|
|
30
47
|
}
|
|
48
|
+
return merged as Partial<OrganizationSettings>;
|
|
31
49
|
}
|
|
32
50
|
|
|
33
51
|
export function getB2BContextService(event?: H3Event): IB2BContextService {
|