@mohasinac/appkit 3.3.2 → 3.3.4
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/dist/_internal/client/features/lottery/LotteryAdminSlotView.js +1 -1
- package/dist/_internal/server/features/cart/actions.js +1 -1
- package/dist/_internal/server/features/lottery/data.d.ts +2 -3
- package/dist/_internal/server/features/products/actions.js +1 -1
- package/dist/client/api/surface-error.js +6 -6
- package/dist/features/admin/components/AdminSectionsView.js +7 -4
- package/dist/features/admin/constants/filter-tabs.js +11 -0
- package/dist/features/auctions/columns/index.js +1 -1
- package/dist/features/auctions/schemas/index.d.ts +2 -2
- package/dist/features/auth/hooks/useRBAC.js +6 -1
- package/dist/features/blog/columns/index.js +1 -1
- package/dist/features/categories/schemas/firestore.d.ts +1 -1
- package/dist/features/contact/email.js +0 -1
- package/dist/features/faq/actions/faq-actions.d.ts +6 -6
- package/dist/features/faq/schemas/index.d.ts +4 -4
- package/dist/features/forms/Slider.js +4 -1
- package/dist/features/forms/Toggle.js +4 -1
- package/dist/features/homepage/components/NewsletterBanner.js +1 -1
- package/dist/features/layout/BottomActions.js +27 -0
- package/dist/features/layout/BottomActionsContext.d.ts +36 -0
- package/dist/features/layout/BottomActionsContext.js +36 -0
- package/dist/features/orders/schemas/index.d.ts +2 -2
- package/dist/features/payments/schemas/index.d.ts +4 -4
- package/dist/features/products/repository/products.repository.js +1 -1
- package/dist/features/products/schemas/product-features.validators.d.ts +6 -6
- package/dist/features/promotions/repository/claimed-coupons.repository.js +1 -1
- package/dist/features/reviews/columns/index.js +1 -1
- package/dist/features/search/schemas/index.d.ts +2 -2
- package/dist/features/seller/actions/seller-actions.d.ts +2 -2
- package/dist/features/seller/components/SellerOrdersView.js +4 -1
- package/dist/features/seller/components/SellerProductsView.js +35 -31
- package/dist/features/seller/components/SellerReviewsView.js +1 -1
- package/dist/features/seller/schemas/index.d.ts +2 -2
- package/dist/features/stores/columns/index.js +1 -1
- package/dist/features/stores/components/StoresIndexListing.js +20 -15
- package/dist/features/support/schemas/index.d.ts +2 -2
- package/dist/features/wishlist/actions/wishlist-actions.js +1 -1
- package/dist/next/components/NotFoundView.js +17 -0
- package/dist/next/components/UnauthorizedView.js +13 -0
- package/dist/schemas/registry.d.ts +145 -146
- package/dist/schemas/webhooks/razorpay.d.ts +136 -136
- package/dist/ui/columns/column-renderers.js +1 -1
- package/dist/ui/components/Accordion.js +10 -6
- package/dist/ui/components/ListingLayout.js +6 -2
- package/dist/validation/schemas.d.ts +4 -4
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* (src/actions/seller.actions.ts) alongside the other seller server actions.
|
|
10
10
|
*/
|
|
11
11
|
import type { JsonValue } from "../../../schemas/types";
|
|
12
|
-
import type { SellerPayoutDetails
|
|
12
|
+
import type { SellerPayoutDetails } from "../../auth/schemas/firestore";
|
|
13
13
|
import type { StoreDocument } from "../../stores/schemas/firestore";
|
|
14
14
|
import type { ProductDocument } from "../../products/schemas/firestore";
|
|
15
15
|
import type { OrderDocument } from "../../orders/schemas/firestore";
|
|
@@ -115,7 +115,7 @@ export declare function requestPayout(userId: string, userName: string, userEmai
|
|
|
115
115
|
export declare function bulkSellerOrder(userId: string, userRole: string, userDisplayName: string, userEmail: string, orderIds: string[]): Promise<BulkSellerOrderResult>;
|
|
116
116
|
export declare function createSellerProduct(userId: string, userName: string, userEmail: string, input: Record<string, JsonValue>): Promise<void>;
|
|
117
117
|
export declare function getSellerStore(userId: string): Promise<StoreDocument | null>;
|
|
118
|
-
export declare function getSellerShipping(userId: string): Promise<SellerShippingConfig | null>;
|
|
118
|
+
export declare function getSellerShipping(userId: string): Promise<import("../../auth").SellerShippingConfig | null>;
|
|
119
119
|
export declare function getSellerPayoutSettings(userId: string): Promise<SellerPayoutDetails | {
|
|
120
120
|
method: string;
|
|
121
121
|
isConfigured: boolean;
|
|
@@ -358,9 +358,12 @@ export function SellerOrdersView({ orderDetailApiBase = SELLER_ENDPOINTS.ORDERS,
|
|
|
358
358
|
buildBulkAction(ACTIONS.STORE["set-location"], () => setSetLocationOpen(true), { icon: _jsx(MapPin, { className: "w-4 h-4" }) }),
|
|
359
359
|
buildBulkAction(ACTIONS.STORE["request-payout"], () => void requestPayoutForSelection(), { variant: "primary" }),
|
|
360
360
|
];
|
|
361
|
+
// useBottomActions must run unconditionally on every render — it was
|
|
362
|
+
// previously called after the `hasChildren` early return below, which
|
|
363
|
+
// skips the hook call in passthrough mode, violating the Rules of Hooks.
|
|
364
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
|
|
361
365
|
if (hasChildren) {
|
|
362
366
|
return _jsx(ListingLayout, { portal: "seller", ...props, children: children });
|
|
363
367
|
}
|
|
364
|
-
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
|
|
365
368
|
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search by order ID or buyer name", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set("sort", v); }, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState }), totalPages > 1 && (_jsx(Row, { border: "bottom", className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 backdrop-blur-sm", surface: "default", padding: "toolbar", justify: "center", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedIds.length > 0 && (_jsx(Div, { border: "default", paddingX: "x-sm-md", className: "sticky top-[calc(var(--header-height,0px)+88px)] z-20 backdrop-blur-sm border-b", surface: "default", padding: "y-xs", children: _jsx(BulkActionBar, { selectedCount: selection.selectedIds.length, onClearSelection: selection.clearSelection, actions: bulkActions }) })), _jsxs(Div, { paddingX: "x-sm-md", padding: "y-md", children: [errorMessage && (_jsx(Div, { textSize: "sm", className: "mb-4 border border-error/20", color: "error", surface: "danger-surface", padding: "inline", rounded: "xl", children: errorMessage })), _jsx(DataTable, { rows: rows, columns: columns, isLoading: isLoading, emptyLabel: "No orders yet", selectedIds: selection.selectedIdSet, onToggleSelect: selection.toggle, onToggleSelectAll: () => selection.toggleAll(), renderRowActions: renderRowActions })] }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: activeFilterCount, children: _jsx(FilterChipGroup, { label: "Status", tabs: STATUS_OPTIONS, value: pendingFilters.status ?? "", onChange: (id) => setPendingFilters((p) => ({ ...p, status: id })) }) }), selectedOrderId && (_jsx(OrderDetailDrawer, { orderId: selectedOrderId, apiBase: orderDetailApiBase, onClose: () => setSelectedOrderId(null) })), setLocationOpen && (_jsx(PhysicalLocationModal, { count: selection.selectedIds.length, onSave: handleSetLocation, onClose: () => setSetLocationOpen(false) }))] }));
|
|
366
369
|
}
|
|
@@ -214,6 +214,41 @@ export function SellerProductsView({ onDeleteProduct, onCreateClick, children, .
|
|
|
214
214
|
.filter((r) => !deletedIds.has(r.id))
|
|
215
215
|
.map((r) => statusOverrides.has(r.id) ? { ...r, status: statusOverrides.get(r.id) } : r);
|
|
216
216
|
const selection = useBulkSelection({ items: visibleRows, keyExtractor: (r) => r.id });
|
|
217
|
+
// handleBulkPrintLabels/handleSetLocation (useCallback) and useBottomActions
|
|
218
|
+
// must run unconditionally on every render — they were previously declared
|
|
219
|
+
// after the `hasChildren` early return below, which skips these hook calls
|
|
220
|
+
// in passthrough mode, violating the Rules of Hooks.
|
|
221
|
+
const handleBulkPrintLabels = useCallback(() => {
|
|
222
|
+
const ids = selection.selectedIds.join(",");
|
|
223
|
+
void dispatch({
|
|
224
|
+
type: "NAVIGATE",
|
|
225
|
+
href: `${String(ROUTES.STORE.INVENTORY_PRINT)}?type=product&ids=${ids}&autoprint=1`,
|
|
226
|
+
});
|
|
227
|
+
}, [selection.selectedIds, dispatch]);
|
|
228
|
+
const handleSetLocation = useCallback(async (loc) => {
|
|
229
|
+
try {
|
|
230
|
+
const res = await fetch(SELLER_ENDPOINTS.PRODUCTS_BULK_LOCATION, {
|
|
231
|
+
method: "PATCH",
|
|
232
|
+
headers: { "Content-Type": "application/json" },
|
|
233
|
+
body: JSON.stringify({ productIds: selection.selectedIds, physicalLocation: loc }),
|
|
234
|
+
});
|
|
235
|
+
if (!res.ok) {
|
|
236
|
+
const body = await res.json().catch(() => null);
|
|
237
|
+
throw new Error(body?.error ?? "Failed to update location");
|
|
238
|
+
}
|
|
239
|
+
showToast("Location updated.", "success");
|
|
240
|
+
setSetLocationOpen(false);
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
void normalizeError(err);
|
|
244
|
+
showToast(err instanceof Error ? err.message : "Failed to update location.", "error");
|
|
245
|
+
}
|
|
246
|
+
}, [selection.selectedIds, showToast]);
|
|
247
|
+
const bulkActions = [
|
|
248
|
+
buildBulkAction(ACTIONS.STORE["print-labels"], handleBulkPrintLabels, { icon: _jsx(Printer, { className: "w-4 h-4" }) }),
|
|
249
|
+
buildBulkAction(ACTIONS.STORE["set-location"], () => setSetLocationOpen(true), { icon: _jsx(MapPin, { className: "w-4 h-4" }) }),
|
|
250
|
+
];
|
|
251
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
|
|
217
252
|
if (hasChildren) {
|
|
218
253
|
return (_jsx(ListingLayout, { portal: "seller", ...props, children: children }));
|
|
219
254
|
}
|
|
@@ -262,37 +297,6 @@ export function SellerProductsView({ onDeleteProduct, onCreateClick, children, .
|
|
|
262
297
|
setPublishingId(null);
|
|
263
298
|
}
|
|
264
299
|
};
|
|
265
|
-
const handleBulkPrintLabels = useCallback(() => {
|
|
266
|
-
const ids = selection.selectedIds.join(",");
|
|
267
|
-
void dispatch({
|
|
268
|
-
type: "NAVIGATE",
|
|
269
|
-
href: `${String(ROUTES.STORE.INVENTORY_PRINT)}?type=product&ids=${ids}&autoprint=1`,
|
|
270
|
-
});
|
|
271
|
-
}, [selection.selectedIds, dispatch]);
|
|
272
|
-
const handleSetLocation = useCallback(async (loc) => {
|
|
273
|
-
try {
|
|
274
|
-
const res = await fetch(SELLER_ENDPOINTS.PRODUCTS_BULK_LOCATION, {
|
|
275
|
-
method: "PATCH",
|
|
276
|
-
headers: { "Content-Type": "application/json" },
|
|
277
|
-
body: JSON.stringify({ productIds: selection.selectedIds, physicalLocation: loc }),
|
|
278
|
-
});
|
|
279
|
-
if (!res.ok) {
|
|
280
|
-
const body = await res.json().catch(() => null);
|
|
281
|
-
throw new Error(body?.error ?? "Failed to update location");
|
|
282
|
-
}
|
|
283
|
-
showToast("Location updated.", "success");
|
|
284
|
-
setSetLocationOpen(false);
|
|
285
|
-
}
|
|
286
|
-
catch (err) {
|
|
287
|
-
void normalizeError(err);
|
|
288
|
-
showToast(err instanceof Error ? err.message : "Failed to update location.", "error");
|
|
289
|
-
}
|
|
290
|
-
}, [selection.selectedIds, showToast]);
|
|
291
|
-
const bulkActions = [
|
|
292
|
-
buildBulkAction(ACTIONS.STORE["print-labels"], handleBulkPrintLabels, { icon: _jsx(Printer, { className: "w-4 h-4" }) }),
|
|
293
|
-
buildBulkAction(ACTIONS.STORE["set-location"], () => setSetLocationOpen(true), { icon: _jsx(MapPin, { className: "w-4 h-4" }) }),
|
|
294
|
-
];
|
|
295
|
-
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: bulkActions } } : {});
|
|
296
300
|
return (_jsxs(_Fragment, { children: [_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search products by name\u2026", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get("sort") || DEFAULT_SORT, sortOptions: SORT_OPTIONS, onSortChange: (v) => { table.set("sort", v); }, showTableView: true, view: view, onViewChange: (v) => setView(v), onResetAll: resetAll, hasActiveState: hasActiveState, toggles: [
|
|
297
301
|
{ label: "Show sold", active: showSold, onChange: (next) => table.set("showSold", next ? "true" : "") },
|
|
298
302
|
], extra: onCreateClick ? (_jsx(Button, { variant: "primary", size: "sm", onClick: onCreateClick, children: "+ New Listing" })) : null }), _jsx(TypeDropdown, { active: listingKind, onChange: handleKindChange }), totalPages > 1 && (_jsx(Row, { className: "sticky top-[calc(var(--header-height,0px)+44px)] z-10 bg-[var(--appkit-color-surface)]/95 backdrop-blur-sm border-b border-[var(--appkit-color-border)] py-[0.375rem]", padding: "x-sm", justify: "center", children: _jsx(Pagination, { currentPage: currentPage, totalPages: totalPages, onPageChange: (p) => table.setPage(p) }) })), selection.selectedIds.length > 0 && (_jsx(Div, { paddingX: "x-sm-lg-md", className: "sticky top-[calc(var(--header-height,0px)+88px)] z-20 bg-[var(--appkit-color-surface)]/95 backdrop-blur-sm border-b border-[var(--appkit-color-border)]", padding: "y-xs", children: _jsx(BulkActionBar, { selectedCount: selection.selectedIds.length, onClearSelection: selection.clearSelection, actions: bulkActions }) })), _jsxs(Div, { paddingX: "x-sm-lg-md", padding: "y-md", children: [errorMessage && (_jsx(Alert, { variant: "error", className: "mb-4", children: errorMessage })), view !== "table" && (_jsx(SellerProductsCards, { view: view, rows: visibleRows, isLoading: isLoading, listingKind: listingKind, selectedIds: selection.selectedIdSet, toggle: selection.toggle, onEdit: handleEdit, onDuplicate: (row) => void handleDuplicate(row), onDelete: onDeleteProduct ? (row) => void handleDelete(row) : undefined })), view === "table" && (_jsx(DataTable, { columns: PRODUCT_COLUMNS, rows: visibleRows, isLoading: isLoading, emptyLabel: listingKind !== "all"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { normalizeError } from "../../../errors/normalize";
|
|
4
4
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
|
5
|
-
import { Alert, Badge, BulkActionBar, Button, Checkbox, Div, Modal, Row, Select, SideDrawer, Span, Stack, Text, Textarea
|
|
5
|
+
import { Alert, Badge, BulkActionBar, Button, Checkbox, Div, Modal, Row, Select, SideDrawer, Span, Stack, Text, Textarea } from "../../../ui";
|
|
6
6
|
import { StackedViewShell } from "../../../ui";
|
|
7
7
|
import { useBottomActions } from "../../layout";
|
|
8
8
|
import { ACTIONS } from "../../../_internal/shared/actions/action-registry";
|
|
@@ -167,8 +167,8 @@ export declare const payoutRecordSchema: z.ZodObject<{
|
|
|
167
167
|
createdAt: z.ZodString;
|
|
168
168
|
updatedAt: z.ZodString;
|
|
169
169
|
}, "strip", z.ZodTypeAny, {
|
|
170
|
-
status: "pending" | "paid" | "failed" | "processing";
|
|
171
170
|
currency: string;
|
|
171
|
+
status: "pending" | "paid" | "failed" | "processing";
|
|
172
172
|
createdAt: string;
|
|
173
173
|
id: string;
|
|
174
174
|
updatedAt: string;
|
|
@@ -184,8 +184,8 @@ export declare const payoutRecordSchema: z.ZodObject<{
|
|
|
184
184
|
sellerId: string;
|
|
185
185
|
processedAt?: string | undefined;
|
|
186
186
|
}, {
|
|
187
|
-
status: "pending" | "paid" | "failed" | "processing";
|
|
188
187
|
currency: string;
|
|
188
|
+
status: "pending" | "paid" | "failed" | "processing";
|
|
189
189
|
createdAt: string;
|
|
190
190
|
id: string;
|
|
191
191
|
updatedAt: string;
|
|
@@ -121,6 +121,26 @@ export function StoresIndexListing({ initialData }) {
|
|
|
121
121
|
filters: filterParts.length > 0 ? filterParts.join(",") : undefined,
|
|
122
122
|
}, { initialData });
|
|
123
123
|
const selection = useBulkSelection({ items: stores, keyExtractor: (s) => s.id ?? s.storeSlug });
|
|
124
|
+
// useBottomActions must run unconditionally on every render, once per
|
|
125
|
+
// component — it was previously mis-placed inside the grid view's
|
|
126
|
+
// `stores.map(...)` callback below, which fired it once per store in the
|
|
127
|
+
// list (a severe Rules-of-Hooks violation) instead of once for the whole
|
|
128
|
+
// bulk-selection bar.
|
|
129
|
+
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
130
|
+
{
|
|
131
|
+
id: ACTION_ID.COMPARE,
|
|
132
|
+
label: "Compare",
|
|
133
|
+
variant: "secondary",
|
|
134
|
+
onClick: () => { selection.clearSelection(); },
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
id: "visit",
|
|
138
|
+
label: "Visit Store",
|
|
139
|
+
variant: "primary",
|
|
140
|
+
disabled: selection.selectedCount !== 1,
|
|
141
|
+
onClick: () => { selection.clearSelection(); },
|
|
142
|
+
},
|
|
143
|
+
] } } : {});
|
|
124
144
|
return (_jsxs(Div, { className: "min-h-screen", children: [_jsx(ListingToolbar, { filterCount: activeFilterCount, onFiltersClick: openFilters, searchValue: searchInput, searchPlaceholder: "Search stores...", onSearchChange: setSearchInput, onSearchCommit: commitSearch, sortValue: table.get(TABLE_KEYS.SORT) || DEFAULT_SORT, sortOptions: STORE_SORT_OPTIONS, onSortChange: (v) => { table.set(TABLE_KEYS.SORT, v); }, view: view, onViewChange: handleViewToggle, onResetAll: resetAll, hasActiveState: hasActiveState, bulkMode: selection.isSelecting, bulkSelectedCount: selection.selectedCount, bulkTotalCount: stores.length, onBulkSelectAll: selection.toggleAll, onBulkClear: selection.clearSelection }), _jsx(BulkActionBar, { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
125
145
|
{
|
|
126
146
|
id: ACTION_ID.COMPARE,
|
|
@@ -140,21 +160,6 @@ export function StoresIndexListing({ initialData }) {
|
|
|
140
160
|
return (_jsx(InteractiveStoreCard, { store: store, href: String(ROUTES.PUBLIC.STORE_DETAIL(storeKey)), selectable: selection.isSelecting, isSelected: selection.isSelected(store.id ?? store.storeSlug), onSelect: (id, sel) => { void sel; selection.toggle(id); } }, storeKey));
|
|
141
161
|
}) })) : (_jsx(Div, { layout: "grid", gap: "6", className: "grid-cols-1 sm:grid-cols-2 lg:grid-cols-3", children: stores.map((store) => {
|
|
142
162
|
const storeKey = store.storeSlug ?? store.id;
|
|
143
|
-
useBottomActions(selection.selectedCount > 0 ? { bulk: { selectedCount: selection.selectedCount, onClearSelection: selection.clearSelection, actions: [
|
|
144
|
-
{
|
|
145
|
-
id: ACTION_ID.COMPARE,
|
|
146
|
-
label: "Compare",
|
|
147
|
-
variant: "secondary",
|
|
148
|
-
onClick: () => { selection.clearSelection(); },
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
id: "visit",
|
|
152
|
-
label: "Visit Store",
|
|
153
|
-
variant: "primary",
|
|
154
|
-
disabled: selection.selectedCount !== 1,
|
|
155
|
-
onClick: () => { selection.clearSelection(); },
|
|
156
|
-
},
|
|
157
|
-
] } } : {});
|
|
158
163
|
return (_jsx(InteractiveStoreCard, { store: store, href: String(ROUTES.PUBLIC.STORE_DETAIL(storeKey)), selectable: selection.isSelecting, isSelected: selection.isSelected(store.id ?? store.storeSlug), onSelect: (id, sel) => { void sel; selection.toggle(id); } }, storeKey));
|
|
159
164
|
}) })) }), _jsx(ListingFilterDrawer, { open: filterOpen, onClose: () => setFilterOpen(false), onApply: applyFilters, onClear: clearFilters, activeCount: pendingFilterCount, children: _jsx(StoreFilters, { table: pendingTable }) })] }));
|
|
160
165
|
}
|
|
@@ -159,8 +159,8 @@ export declare const supportTicketFirestoreSchema: z.ZodObject<{
|
|
|
159
159
|
updatedAt: string | Date | z.objectOutputType<{
|
|
160
160
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
161
161
|
}, z.ZodTypeAny, "passthrough">;
|
|
162
|
+
priority: "high" | "low" | "normal" | "urgent";
|
|
162
163
|
userId: string;
|
|
163
|
-
priority: "normal" | "high" | "low" | "urgent";
|
|
164
164
|
messages: {
|
|
165
165
|
createdAt: string | Date | z.objectOutputType<{
|
|
166
166
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
@@ -202,8 +202,8 @@ export declare const supportTicketFirestoreSchema: z.ZodObject<{
|
|
|
202
202
|
updatedAt: string | Date | z.objectInputType<{
|
|
203
203
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
204
204
|
}, z.ZodTypeAny, "passthrough">;
|
|
205
|
+
priority: "high" | "low" | "normal" | "urgent";
|
|
205
206
|
userId: string;
|
|
206
|
-
priority: "normal" | "high" | "low" | "urgent";
|
|
207
207
|
messages: {
|
|
208
208
|
createdAt: string | Date | z.objectInputType<{
|
|
209
209
|
toDate: z.ZodFunction<z.ZodTuple<[], z.ZodUnknown>, z.ZodDate>;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Auth, rate-limiting, and Next.js specifics are handled by the consumer.
|
|
6
6
|
*/
|
|
7
7
|
import { ValidationError } from "../../../errors";
|
|
8
|
-
import { wishlistRepository
|
|
8
|
+
import { wishlistRepository } from "../repository/user-wishlist.repository";
|
|
9
9
|
import { productRepository } from "../../products/repository/products.repository";
|
|
10
10
|
export { WishlistFullError } from "../repository/user-wishlist.repository";
|
|
11
11
|
export async function addToWishlist(userSlug, productId, extras) {
|
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* NotFoundView — Next.js not-found.tsx template.
|
|
4
|
+
*
|
|
5
|
+
* Rendered when `notFound()` is called inside a route segment, or when a
|
|
6
|
+
* route is not matched.
|
|
7
|
+
* @see https://nextjs.org/docs/app/api-reference/file-conventions/not-found
|
|
8
|
+
*
|
|
9
|
+
* Usage in your app:
|
|
10
|
+
* // app/[locale]/not-found.tsx
|
|
11
|
+
* export { NotFoundView as default } from "@mohasinac/appkit/next";
|
|
12
|
+
*
|
|
13
|
+
* // Or with customisation:
|
|
14
|
+
* import { NotFoundView } from "@mohasinac/appkit/next";
|
|
15
|
+
* export default function NotFound() {
|
|
16
|
+
* return <NotFoundView heading="Page not found" homeHref="/en" />;
|
|
17
|
+
* }
|
|
18
|
+
*/
|
|
2
19
|
import { Heading, Text } from "../../ui/components/Typography";
|
|
3
20
|
import { TextLink } from "../../ui/components/TextLink";
|
|
4
21
|
import { DEFAULT_ROUTE_MAP } from "../routing/route-map";
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* UnauthorizedView — 401 page template.
|
|
4
|
+
*
|
|
5
|
+
* Render this when a user tries to access a resource they are not
|
|
6
|
+
* authenticated for. Wire up the `loginHref` prop to your sign-in route.
|
|
7
|
+
*
|
|
8
|
+
* Usage in your app:
|
|
9
|
+
* // app/[locale]/unauthorized/page.tsx
|
|
10
|
+
* import { UnauthorizedView } from "@mohasinac/appkit/next";
|
|
11
|
+
* export default function UnauthorizedPage() {
|
|
12
|
+
* return <UnauthorizedView loginHref="/en/auth/login" />;
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
2
15
|
import { Row } from "../../ui/components/Layout";
|
|
3
16
|
import { Heading, Text } from "../../ui/components/Typography";
|
|
4
17
|
import { TextLink } from "../../ui/components/TextLink";
|