@deenruv/admin-dashboard 1.0.0
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/LICENSE +23 -0
- package/README.md +30 -0
- package/dist/@types/resources.js +51 -0
- package/dist/DeenruvAdminPanel.js +118 -0
- package/dist/DeenruvDeveloperIndicator.js +57 -0
- package/dist/components/Aexol.js +4 -0
- package/dist/components/BrandLogo.js +22 -0
- package/dist/components/CanLeaveRouteDialog.js +8 -0
- package/dist/components/DataTable.js +13 -0
- package/dist/components/DeleteDialog.js +6 -0
- package/dist/components/DuplicateEntry.js +46 -0
- package/dist/components/GlobalSearch.js +134 -0
- package/dist/components/History/AddEntryForm.js +29 -0
- package/dist/components/History/DeleteEntryDialog.js +25 -0
- package/dist/components/History/EditEntryDialog.js +32 -0
- package/dist/components/History/History.js +13 -0
- package/dist/components/History/ModifyHistoryInfo.js +6 -0
- package/dist/components/History/Timeline.js +53 -0
- package/dist/components/History/index.js +5 -0
- package/dist/components/Menu/ActiveAdmins.js +24 -0
- package/dist/components/Menu/ChannelSwitcher.js +20 -0
- package/dist/components/Menu/LanguagesDropdown.js +26 -0
- package/dist/components/Menu/Navigation.js +270 -0
- package/dist/components/Menu/NavigationFooter.js +12 -0
- package/dist/components/Menu/Notifications.js +90 -0
- package/dist/components/Menu/index.js +67 -0
- package/dist/components/index.js +6 -0
- package/dist/graphql/base.js +95 -0
- package/dist/graphql/collections.js +94 -0
- package/dist/graphql/draft_order.js +307 -0
- package/dist/graphql/orders.js +157 -0
- package/dist/graphql/products.js +230 -0
- package/dist/graphql/scalars.js +22 -0
- package/dist/i18.js +13 -0
- package/dist/index.css +161 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +1 -0
- package/dist/locales/en/admins.json +57 -0
- package/dist/locales/en/assets.json +69 -0
- package/dist/locales/en/channels.json +66 -0
- package/dist/locales/en/collections.json +145 -0
- package/dist/locales/en/common.json +1127 -0
- package/dist/locales/en/countries.json +50 -0
- package/dist/locales/en/customerGroups.json +6 -0
- package/dist/locales/en/customers.json +109 -0
- package/dist/locales/en/dashboard.json +34 -0
- package/dist/locales/en/facets.json +78 -0
- package/dist/locales/en/globalSettings.json +15 -0
- package/dist/locales/en/index.js +52 -0
- package/dist/locales/en/orders.json +932 -0
- package/dist/locales/en/paymentMethods.json +59 -0
- package/dist/locales/en/permissions.json +94 -0
- package/dist/locales/en/products.json +194 -0
- package/dist/locales/en/promotions.json +65 -0
- package/dist/locales/en/roles.json +59 -0
- package/dist/locales/en/sellers.json +41 -0
- package/dist/locales/en/shippingMethods.json +84 -0
- package/dist/locales/en/stockLocations.json +40 -0
- package/dist/locales/en/system.json +41 -0
- package/dist/locales/en/table.json +201 -0
- package/dist/locales/en/taxCategories.json +47 -0
- package/dist/locales/en/taxRates.json +56 -0
- package/dist/locales/en/zones.json +47 -0
- package/dist/locales/index.js +2 -0
- package/dist/locales/pl/admins.json +57 -0
- package/dist/locales/pl/assets.json +69 -0
- package/dist/locales/pl/channels.json +66 -0
- package/dist/locales/pl/collections.json +145 -0
- package/dist/locales/pl/common.json +1128 -0
- package/dist/locales/pl/countries.json +50 -0
- package/dist/locales/pl/customerGroups.json +6 -0
- package/dist/locales/pl/customers.json +109 -0
- package/dist/locales/pl/dashboard.json +34 -0
- package/dist/locales/pl/facets.json +78 -0
- package/dist/locales/pl/globalSettings.json +15 -0
- package/dist/locales/pl/index.js +52 -0
- package/dist/locales/pl/orders.json +932 -0
- package/dist/locales/pl/paymentMethods.json +59 -0
- package/dist/locales/pl/permissions.json +94 -0
- package/dist/locales/pl/products.json +194 -0
- package/dist/locales/pl/promotions.json +65 -0
- package/dist/locales/pl/roles.json +59 -0
- package/dist/locales/pl/sellers.json +41 -0
- package/dist/locales/pl/shippingMethods.json +84 -0
- package/dist/locales/pl/stockLocations.json +40 -0
- package/dist/locales/pl/system.json +41 -0
- package/dist/locales/pl/table.json +201 -0
- package/dist/locales/pl/taxCategories.json +47 -0
- package/dist/locales/pl/taxRates.json +56 -0
- package/dist/locales/pl/zones.json +47 -0
- package/dist/notifications/OrderStatusNotification.js +47 -0
- package/dist/notifications/SystemStatusNotification.js +19 -0
- package/dist/pages/Custom404.js +5 -0
- package/dist/pages/LoginScreen.js +37 -0
- package/dist/pages/Root.js +252 -0
- package/dist/pages/admins/Detail.js +72 -0
- package/dist/pages/admins/List.js +56 -0
- package/dist/pages/admins/_components/AdminDetailView.js +34 -0
- package/dist/pages/admins/_components/RolesCard.js +31 -0
- package/dist/pages/admins/index.js +2 -0
- package/dist/pages/assets/List.js +82 -0
- package/dist/pages/assets/_components/Asset.js +114 -0
- package/dist/pages/assets/_components/AssetListView.js +29 -0
- package/dist/pages/assets/_components/EditAssetDialog.js +85 -0
- package/dist/pages/assets/_components/UploadAssetDialog.js +133 -0
- package/dist/pages/assets/_components/UploadProgress.js +20 -0
- package/dist/pages/assets/index.js +1 -0
- package/dist/pages/channels/Detail.js +149 -0
- package/dist/pages/channels/List.js +46 -0
- package/dist/pages/channels/_components/ChannelDetailView.js +51 -0
- package/dist/pages/channels/_components/DefaultsCard.js +25 -0
- package/dist/pages/channels/index.js +2 -0
- package/dist/pages/collections/Detail.js +61 -0
- package/dist/pages/collections/List.js +135 -0
- package/dist/pages/collections/_components/CollectionDetailView.js +52 -0
- package/dist/pages/collections/_components/CollectionProductVariantsDrawer.js +28 -0
- package/dist/pages/collections/_components/CombinationMode.js +6 -0
- package/dist/pages/collections/_components/ContentsCard.js +43 -0
- package/dist/pages/collections/_components/ContentsTable.js +102 -0
- package/dist/pages/collections/_components/DeleteCollectionsFromChannel.js +36 -0
- package/dist/pages/collections/_components/FacetsSelector.js +30 -0
- package/dist/pages/collections/_components/FiltersCard.js +101 -0
- package/dist/pages/collections/_components/MoveCollectionsToCollections.js +107 -0
- package/dist/pages/collections/_components/MoveEntityToChannels.js +115 -0
- package/dist/pages/collections/_components/PageHeader.js +11 -0
- package/dist/pages/collections/_components/SelectedCollectionsModal.js +22 -0
- package/dist/pages/collections/_components/VariantsSelector.js +43 -0
- package/dist/pages/collections/consts.js +7 -0
- package/dist/pages/collections/index.js +2 -0
- package/dist/pages/countries/Detail.js +57 -0
- package/dist/pages/countries/List.js +47 -0
- package/dist/pages/countries/_components/CountryDetailView.js +28 -0
- package/dist/pages/countries/index.js +2 -0
- package/dist/pages/customer-groups/Detail.js +76 -0
- package/dist/pages/customer-groups/List.js +41 -0
- package/dist/pages/customer-groups/_components/CustomerGroupsDetailView.js +21 -0
- package/dist/pages/customer-groups/index.js +2 -0
- package/dist/pages/customers/Detail.js +75 -0
- package/dist/pages/customers/List.js +60 -0
- package/dist/pages/customers/_components/Address.js +59 -0
- package/dist/pages/customers/_components/AddressDialog.js +56 -0
- package/dist/pages/customers/_components/AddressForm.js +77 -0
- package/dist/pages/customers/_components/AddressesCard.js +9 -0
- package/dist/pages/customers/_components/CustomerDetailSidebar.js +9 -0
- package/dist/pages/customers/_components/CustomerDetailView.js +41 -0
- package/dist/pages/customers/_components/CustomerGroupsCard.js +46 -0
- package/dist/pages/customers/_components/HistoryTab.js +65 -0
- package/dist/pages/customers/_components/OrdersTab.js +46 -0
- package/dist/pages/customers/_components/PersonalDataCard.js +6 -0
- package/dist/pages/customers/_components/VerifiedCard.js +6 -0
- package/dist/pages/customers/index.js +2 -0
- package/dist/pages/dashboard/Dashboard.js +10 -0
- package/dist/pages/dashboard/index.js +1 -0
- package/dist/pages/extensions/Extensions.js +74 -0
- package/dist/pages/extensions/index.js +1 -0
- package/dist/pages/facets/Detail.js +56 -0
- package/dist/pages/facets/List.js +48 -0
- package/dist/pages/facets/_components/AddFacetValueDialog.js +105 -0
- package/dist/pages/facets/_components/ColorSample.js +18 -0
- package/dist/pages/facets/_components/FacetDetailView.js +98 -0
- package/dist/pages/facets/index.js +2 -0
- package/dist/pages/global-settings/GlobalSettingsComponent.js +30 -0
- package/dist/pages/global-settings/index.js +71 -0
- package/dist/pages/index.js +25 -0
- package/dist/pages/orders/Detail.js +21 -0
- package/dist/pages/orders/List.js +132 -0
- package/dist/pages/orders/_components/AddPaymentDialog.js +50 -0
- package/dist/pages/orders/_components/AddressCard.js +260 -0
- package/dist/pages/orders/_components/CancelAndRefundDialog.js +29 -0
- package/dist/pages/orders/_components/ChangesRegister.js +68 -0
- package/dist/pages/orders/_components/ChangesRegisterTable.js +18 -0
- package/dist/pages/orders/_components/CouponCodesCard.js +85 -0
- package/dist/pages/orders/_components/CustomComponent.js +21 -0
- package/dist/pages/orders/_components/CustomerSelectCard.js +117 -0
- package/dist/pages/orders/_components/EditNoteButton.js +10 -0
- package/dist/pages/orders/_components/FulfillmentModal.js +85 -0
- package/dist/pages/orders/_components/LineItem.js +7 -0
- package/dist/pages/orders/_components/ManualOrderChangeModal.js +47 -0
- package/dist/pages/orders/_components/ModifyAcceptModal.js +22 -0
- package/dist/pages/orders/_components/ModifyingCard.js +77 -0
- package/dist/pages/orders/_components/OrderHistory.js +59 -0
- package/dist/pages/orders/_components/OrderLineActionModal/ActionQuantityPrice.js +58 -0
- package/dist/pages/orders/_components/OrderLineActionModal/index.js +7 -0
- package/dist/pages/orders/_components/OrderLineActionModal/types.js +1 -0
- package/dist/pages/orders/_components/OrderLineCustomFields.js +26 -0
- package/dist/pages/orders/_components/OrderSummary.js +10 -0
- package/dist/pages/orders/_components/PaymentMetadata.js +6 -0
- package/dist/pages/orders/_components/Payments.js +113 -0
- package/dist/pages/orders/_components/PossibleOrderStates.js +54 -0
- package/dist/pages/orders/_components/PriceChangedInfo.js +16 -0
- package/dist/pages/orders/_components/ProductsCard.js +308 -0
- package/dist/pages/orders/_components/ProductsTable.js +29 -0
- package/dist/pages/orders/_components/PromotionsList.js +73 -0
- package/dist/pages/orders/_components/RealizationCard.js +98 -0
- package/dist/pages/orders/_components/RefundCard.js +11 -0
- package/dist/pages/orders/_components/RefundPaymentCard.js +13 -0
- package/dist/pages/orders/_components/ShippingMethod.js +112 -0
- package/dist/pages/orders/_components/SpecialLineItem.js +7 -0
- package/dist/pages/orders/_components/SurchargeCard.js +99 -0
- package/dist/pages/orders/_components/SurchargeTable.js +8 -0
- package/dist/pages/orders/_components/TaxSummary.js +11 -0
- package/dist/pages/orders/_components/ToRealizationForm.js +64 -0
- package/dist/pages/orders/_components/TopActions.js +219 -0
- package/dist/pages/orders/_components/index.js +25 -0
- package/dist/pages/orders/index.js +2 -0
- package/dist/pages/payment-methods/Detail.js +67 -0
- package/dist/pages/payment-methods/List.js +41 -0
- package/dist/pages/payment-methods/_components/OptionsCard.js +60 -0
- package/dist/pages/payment-methods/_components/PaymentMethodDetailView.js +53 -0
- package/dist/pages/payment-methods/index.js +2 -0
- package/dist/pages/product-variants/Detail.js +4 -0
- package/dist/pages/product-variants/List.js +76 -0
- package/dist/pages/product-variants/index.js +2 -0
- package/dist/pages/products/Detail.js +75 -0
- package/dist/pages/products/List.js +79 -0
- package/dist/pages/products/_components/AddOptionGroupDialog.js +65 -0
- package/dist/pages/products/_components/AssetsCard.js +35 -0
- package/dist/pages/products/_components/BasicFieldsCard.js +6 -0
- package/dist/pages/products/_components/ChannelsCard.js +6 -0
- package/dist/pages/products/_components/CollectionsCard.js +6 -0
- package/dist/pages/products/_components/Container.js +4 -0
- package/dist/pages/products/_components/DiscountRatingCard.js +6 -0
- package/dist/pages/products/_components/FacetValuesCard.js +6 -0
- package/dist/pages/products/_components/ImagesCard.js +6 -0
- package/dist/pages/products/_components/OptionGroup.js +93 -0
- package/dist/pages/products/_components/OptionValueCard.js +59 -0
- package/dist/pages/products/_components/OptionsCard.js +38 -0
- package/dist/pages/products/_components/OptionsTab.js +40 -0
- package/dist/pages/products/_components/PriceCard.js +27 -0
- package/dist/pages/products/_components/ProductDetailSidebar.js +30 -0
- package/dist/pages/products/_components/ProductDetailView.js +54 -0
- package/dist/pages/products/_components/SettingsCard.js +6 -0
- package/dist/pages/products/_components/StockCard.js +40 -0
- package/dist/pages/products/_components/Variant.js +149 -0
- package/dist/pages/products/_components/VariantsTab.js +46 -0
- package/dist/pages/products/index.js +2 -0
- package/dist/pages/promotions/Detail.js +80 -0
- package/dist/pages/promotions/List.js +38 -0
- package/dist/pages/promotions/_components/ActionsCard.js +67 -0
- package/dist/pages/promotions/_components/BasicFieldsCard.js +6 -0
- package/dist/pages/promotions/_components/ConditionsCard.js +70 -0
- package/dist/pages/promotions/_components/CustomerGroupsSelector.js +25 -0
- package/dist/pages/promotions/_components/EnabledCard.js +6 -0
- package/dist/pages/promotions/_components/OptionsCard.js +6 -0
- package/dist/pages/promotions/_components/PromotionDetailSidebar.js +15 -0
- package/dist/pages/promotions/_components/PromotionDetailView.js +66 -0
- package/dist/pages/promotions/_components/PromotionFieldRender.js +4 -0
- package/dist/pages/promotions/index.js +2 -0
- package/dist/pages/roles/Detail.js +72 -0
- package/dist/pages/roles/List.js +70 -0
- package/dist/pages/roles/_components/PermissionsCard.js +7 -0
- package/dist/pages/roles/_components/PermissionsTable.js +42 -0
- package/dist/pages/roles/_components/RoleDetailView.js +49 -0
- package/dist/pages/roles/index.js +2 -0
- package/dist/pages/sellers/Detail.js +48 -0
- package/dist/pages/sellers/List.js +37 -0
- package/dist/pages/sellers/_components/SellerDetailView.js +20 -0
- package/dist/pages/sellers/index.js +2 -0
- package/dist/pages/shipping-methods/Detail.js +105 -0
- package/dist/pages/shipping-methods/List.js +40 -0
- package/dist/pages/shipping-methods/_components/CalculatorCard.js +79 -0
- package/dist/pages/shipping-methods/_components/CheckerCard.js +76 -0
- package/dist/pages/shipping-methods/_components/Lines.js +20 -0
- package/dist/pages/shipping-methods/_components/ShippingMethodDetailView.js +67 -0
- package/dist/pages/shipping-methods/_components/TestCard.js +62 -0
- package/dist/pages/shipping-methods/index.js +2 -0
- package/dist/pages/status/Status.js +6 -0
- package/dist/pages/status/_components/FilterToolbar.js +29 -0
- package/dist/pages/status/_components/Health.js +21 -0
- package/dist/pages/status/_components/JobResultPopover.js +8 -0
- package/dist/pages/status/_components/Jobs.js +199 -0
- package/dist/pages/status/_components/JsonExplorer.js +44 -0
- package/dist/pages/status/_components/JsonPopup.js +8 -0
- package/dist/pages/status/index.js +1 -0
- package/dist/pages/stock-locations/Detail.js +77 -0
- package/dist/pages/stock-locations/List.js +38 -0
- package/dist/pages/stock-locations/_components/StockLocationDetailView.js +22 -0
- package/dist/pages/stock-locations/index.js +2 -0
- package/dist/pages/tax-categories/Detail.js +85 -0
- package/dist/pages/tax-categories/List.js +46 -0
- package/dist/pages/tax-categories/_components/TaxCategoryDetailView.js +24 -0
- package/dist/pages/tax-categories/index.js +2 -0
- package/dist/pages/tax-rates/Detail.js +62 -0
- package/dist/pages/tax-rates/List.js +64 -0
- package/dist/pages/tax-rates/_components/TaxRateDetailView.js +64 -0
- package/dist/pages/tax-rates/index.js +2 -0
- package/dist/pages/zones/Detail.js +86 -0
- package/dist/pages/zones/List.js +52 -0
- package/dist/pages/zones/_components/ZoneDetailView.js +49 -0
- package/dist/pages/zones/index.js +2 -0
- package/dist/version.js +1 -0
- package/package.json +122 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { TableHeader, TableRow, TableHead, TableBody, TableCell, Table, DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuItem, Dialog, DialogContent, TooltipProvider, TooltipTrigger, TooltipContent, Tooltip, apiClient, cn, useServer, useOrder, CustomCard, ImageWithPreview, useTranslation, priceFormatter, DialogProductPicker, } from '@deenruv/react-ui-devkit';
|
|
4
|
+
import { removeOrderItemsResultSelector, updateOrderItemsSelector, updatedDraftOrderSelector, } from "../../../graphql/draft_order";
|
|
5
|
+
import { EllipsisVertical, InfoIcon, Trash2, ShoppingCart, Package, Tag, Edit } from 'lucide-react';
|
|
6
|
+
import { useCallback, useMemo, useState } from 'react';
|
|
7
|
+
import { toast } from 'sonner';
|
|
8
|
+
import { OrderLineActionModal } from './OrderLineActionModal/index.js';
|
|
9
|
+
import { CustomComponent } from './CustomComponent.js';
|
|
10
|
+
import { OrderLineCustomFields } from './OrderLineCustomFields.js';
|
|
11
|
+
import { SpecialLineItem } from './SpecialLineItem.js';
|
|
12
|
+
export const ProductsCard = () => {
|
|
13
|
+
const { t } = useTranslation('orders');
|
|
14
|
+
const orderLineCustomFields = useServer((p) => p.serverConfig?.entityCustomFields?.find((el) => el.entityName === 'OrderLine')?.customFields || []);
|
|
15
|
+
const { mode, order, setOrder, setModifiedOrder, modifiedOrder, fetchOrder } = useOrder();
|
|
16
|
+
const currentOrder = useMemo(() => (mode === 'update' ? (modifiedOrder ? modifiedOrder : order) : order), [mode, order, modifiedOrder]);
|
|
17
|
+
const [open, setOpen] = useState(false);
|
|
18
|
+
const [selectedVariant, setSelectedVariant] = useState(undefined);
|
|
19
|
+
const [customFields, setCustomFields] = useState({});
|
|
20
|
+
const [quantity, setQuantity] = useState(1);
|
|
21
|
+
const [orderLineId, setOrderLineId] = useState();
|
|
22
|
+
const [orderLineAction, setOrderLineAction] = useState();
|
|
23
|
+
const isLineAddedInModify = (lineId) => order?.lines.findIndex((l) => l.id === lineId) === -1;
|
|
24
|
+
const serializeCustomFields = (customFields) => JSON.stringify(Object.fromEntries(Object.entries(customFields).sort(([a], [b]) => a.localeCompare(b))));
|
|
25
|
+
const addToOrder = async (productVariant, quantity, customFields) => {
|
|
26
|
+
if (!order)
|
|
27
|
+
return;
|
|
28
|
+
try {
|
|
29
|
+
if (mode === 'update' && modifiedOrder) {
|
|
30
|
+
const mockLine = {
|
|
31
|
+
id: productVariant.id,
|
|
32
|
+
quantity,
|
|
33
|
+
discountedLinePrice: productVariant.price * quantity,
|
|
34
|
+
unitPrice: productVariant.price,
|
|
35
|
+
unitPriceWithTax: Math.round(productVariant.price * (1 + order.taxSummary[0].taxRate / 100)),
|
|
36
|
+
linePrice: productVariant.price,
|
|
37
|
+
linePriceWithTax: Math.round(productVariant.price * (1 + order.taxSummary[0].taxRate / 100)),
|
|
38
|
+
discountedLinePriceWithTax: productVariant.priceWithTax * quantity,
|
|
39
|
+
discountedUnitPrice: productVariant.price,
|
|
40
|
+
discountedUnitPriceWithTax: productVariant.priceWithTax,
|
|
41
|
+
productVariant,
|
|
42
|
+
taxRate: order.taxSummary[0].taxRate,
|
|
43
|
+
...(customFields && { customFields }),
|
|
44
|
+
};
|
|
45
|
+
const existingLineIndex = modifiedOrder.lines.findIndex((line) => {
|
|
46
|
+
const sameId = line.id === mockLine.id;
|
|
47
|
+
// if (!customFields) {
|
|
48
|
+
return sameId;
|
|
49
|
+
// }
|
|
50
|
+
// @ts-ignore
|
|
51
|
+
// return sameId && serializeCustomFields(line.customFields) === serializeCustomFields(customFields);
|
|
52
|
+
});
|
|
53
|
+
let newLines;
|
|
54
|
+
if (existingLineIndex !== -1) {
|
|
55
|
+
newLines = modifiedOrder.lines.map((line, index) => index === existingLineIndex ? { ...line, quantity: line.quantity + 1 } : line);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
newLines = [...modifiedOrder.lines, mockLine];
|
|
59
|
+
}
|
|
60
|
+
setModifiedOrder({
|
|
61
|
+
...modifiedOrder,
|
|
62
|
+
lines: newLines,
|
|
63
|
+
});
|
|
64
|
+
toast.success(t('create.productAdded', 'Product added to order'));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const { addItemToDraftOrder } = await apiClient('mutation')({
|
|
68
|
+
addItemToDraftOrder: [
|
|
69
|
+
{
|
|
70
|
+
input: {
|
|
71
|
+
productVariantId: productVariant.id,
|
|
72
|
+
quantity,
|
|
73
|
+
...(customFields && { customFields }),
|
|
74
|
+
},
|
|
75
|
+
orderId: order.id,
|
|
76
|
+
},
|
|
77
|
+
updatedDraftOrderSelector,
|
|
78
|
+
],
|
|
79
|
+
});
|
|
80
|
+
if (addItemToDraftOrder.__typename === 'Order' || addItemToDraftOrder.__typename === 'InsufficientStockError') {
|
|
81
|
+
if (addItemToDraftOrder.__typename === 'Order') {
|
|
82
|
+
setOrder(addItemToDraftOrder);
|
|
83
|
+
toast.success(t('create.productAdded', 'Product added to order'));
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
setOrder(addItemToDraftOrder.order);
|
|
87
|
+
toast.error(t('toasts.insufficientStockError', { value: productVariant.product.name }));
|
|
88
|
+
}
|
|
89
|
+
closeAddVariantDialog();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
toast.error(t('create.addError', 'Failed to add product'));
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const removeLineItem = async (orderLineId) => {
|
|
97
|
+
if (!order)
|
|
98
|
+
return;
|
|
99
|
+
try {
|
|
100
|
+
if (mode === 'update' && modifiedOrder) {
|
|
101
|
+
setModifiedOrder({
|
|
102
|
+
...modifiedOrder,
|
|
103
|
+
lines: modifiedOrder.lines.filter((l) => l.id !== orderLineId),
|
|
104
|
+
});
|
|
105
|
+
toast.success(t('create.productRemoved', 'Product removed from order'));
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const { removeDraftOrderLine } = await apiClient('mutation')({
|
|
109
|
+
removeDraftOrderLine: [{ orderId: order.id, orderLineId }, removeOrderItemsResultSelector],
|
|
110
|
+
});
|
|
111
|
+
if (removeDraftOrderLine.__typename === 'Order') {
|
|
112
|
+
setOrder(removeDraftOrderLine);
|
|
113
|
+
toast.success(t('create.productRemoved', 'Product removed from order'));
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
toast.error(t('create.removeError', 'Failed to remove product'));
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
const onPriceQuantityChangeApprove = async (input) => {
|
|
121
|
+
if (!order)
|
|
122
|
+
return;
|
|
123
|
+
const { lineID, quantityChange } = input;
|
|
124
|
+
try {
|
|
125
|
+
if (mode === 'update' && modifiedOrder) {
|
|
126
|
+
const editedLineIdx = modifiedOrder.lines.findIndex((l) => l.id === lineID);
|
|
127
|
+
const quantity = quantityChange ? quantityChange : modifiedOrder.lines[editedLineIdx].quantity;
|
|
128
|
+
const editedLine = {
|
|
129
|
+
...modifiedOrder.lines[editedLineIdx],
|
|
130
|
+
quantity,
|
|
131
|
+
};
|
|
132
|
+
setModifiedOrder({
|
|
133
|
+
...modifiedOrder,
|
|
134
|
+
lines: modifiedOrder.lines.map((l, i) => (i === editedLineIdx ? editedLine : l)),
|
|
135
|
+
});
|
|
136
|
+
toast.success(t('create.productUpdated', 'Product updated'));
|
|
137
|
+
}
|
|
138
|
+
else if (mode === 'create') {
|
|
139
|
+
const editedLineIdx = order.lines.findIndex((l) => l.id === lineID);
|
|
140
|
+
if (quantityChange) {
|
|
141
|
+
const { adjustDraftOrderLine } = await apiClient('mutation')({
|
|
142
|
+
adjustDraftOrderLine: [
|
|
143
|
+
{
|
|
144
|
+
orderId: order.id,
|
|
145
|
+
input: {
|
|
146
|
+
orderLineId: order.lines[editedLineIdx].id,
|
|
147
|
+
quantity: quantityChange,
|
|
148
|
+
...(Object.keys(customFields || {}).length > 0 && { customFields }),
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
updateOrderItemsSelector,
|
|
152
|
+
],
|
|
153
|
+
});
|
|
154
|
+
if (adjustDraftOrderLine.__typename === 'Order' ||
|
|
155
|
+
adjustDraftOrderLine.__typename === 'InsufficientStockError') {
|
|
156
|
+
if (adjustDraftOrderLine.__typename === 'Order') {
|
|
157
|
+
setOrder(adjustDraftOrderLine);
|
|
158
|
+
toast.success(t('create.productUpdated', 'Product updated'));
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
setOrder(adjustDraftOrderLine.order);
|
|
162
|
+
toast.error(t('toasts.insufficientStockError', { value: order.lines[editedLineIdx].productVariant.product.name }));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
fetchOrder(order.id);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
toast.error(t('create.updateError', 'Failed to update product'));
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
const adjustLineItem = async (orderLineId, quantity, customFields) => {
|
|
174
|
+
if (!order)
|
|
175
|
+
return;
|
|
176
|
+
try {
|
|
177
|
+
if (mode === 'update' && modifiedOrder) {
|
|
178
|
+
const editedLineIdx = modifiedOrder.lines.findIndex((l) => l.id === orderLineId);
|
|
179
|
+
const editedLine = {
|
|
180
|
+
...modifiedOrder.lines[editedLineIdx],
|
|
181
|
+
quantity,
|
|
182
|
+
customFields,
|
|
183
|
+
};
|
|
184
|
+
setModifiedOrder({
|
|
185
|
+
...modifiedOrder,
|
|
186
|
+
lines: modifiedOrder.lines.map((l, i) => (i === editedLineIdx ? editedLine : l)),
|
|
187
|
+
});
|
|
188
|
+
setOpen(false);
|
|
189
|
+
toast.success(t('create.productUpdated', 'Product updated'));
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
const { adjustDraftOrderLine } = await apiClient('mutation')({
|
|
193
|
+
adjustDraftOrderLine: [
|
|
194
|
+
{
|
|
195
|
+
orderId: order.id,
|
|
196
|
+
input: { orderLineId, quantity, ...(Object.keys(customFields || {}).length > 0 && { customFields }) },
|
|
197
|
+
},
|
|
198
|
+
updateOrderItemsSelector,
|
|
199
|
+
],
|
|
200
|
+
});
|
|
201
|
+
if (adjustDraftOrderLine.__typename === 'Order' || adjustDraftOrderLine.__typename === 'InsufficientStockError') {
|
|
202
|
+
if (adjustDraftOrderLine.__typename === 'Order') {
|
|
203
|
+
setOrder(adjustDraftOrderLine);
|
|
204
|
+
toast.success(t('create.productUpdated', 'Product updated'));
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
setOrder(adjustDraftOrderLine.order);
|
|
208
|
+
toast.error(t('toasts.insufficientStockError', { value: 'product' }));
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
catch (error) {
|
|
213
|
+
toast.error(t('create.updateError', 'Failed to update product'));
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
const openAddVariantDialog = (input) => {
|
|
217
|
+
setOpen(true);
|
|
218
|
+
setOrderLineId(input.orderLineId ? input.orderLineId : undefined);
|
|
219
|
+
setSelectedVariant(input.variant);
|
|
220
|
+
setCustomFields({
|
|
221
|
+
attributes: input.customFields?.attributes,
|
|
222
|
+
discountBy: input.customFields?.discountBy,
|
|
223
|
+
});
|
|
224
|
+
setQuantity(input.quantity ? input.quantity : 1);
|
|
225
|
+
};
|
|
226
|
+
const closeAddVariantDialog = () => {
|
|
227
|
+
setOpen(false);
|
|
228
|
+
setSelectedVariant(undefined);
|
|
229
|
+
setOrderLineId(undefined);
|
|
230
|
+
};
|
|
231
|
+
const onOrderLineActionModalOpenChange = (isOpen) => {
|
|
232
|
+
if (isOpen)
|
|
233
|
+
return;
|
|
234
|
+
setOrderLineAction(undefined);
|
|
235
|
+
};
|
|
236
|
+
const handleNewVariantAdd = async (customFields) => {
|
|
237
|
+
if (orderLineId) {
|
|
238
|
+
await adjustLineItem(orderLineId, quantity, customFields);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
else if (selectedVariant) {
|
|
242
|
+
await addToOrder(selectedVariant, quantity, customFields);
|
|
243
|
+
}
|
|
244
|
+
closeAddVariantDialog();
|
|
245
|
+
};
|
|
246
|
+
const renderLineQuantity = useCallback((lineId, quantity) => {
|
|
247
|
+
const allRefundLines = order?.payments?.flatMap((payment) => payment.refunds)?.flatMap((refund) => refund.lines);
|
|
248
|
+
const lineInRefunds = allRefundLines?.find((line) => line.orderLineId === lineId);
|
|
249
|
+
if (!lineInRefunds)
|
|
250
|
+
return quantity;
|
|
251
|
+
else
|
|
252
|
+
return (_jsxs("div", { className: "flex gap-2", children: [_jsx("span", { className: "text-red-500 line-through", children: lineInRefunds.quantity }), quantity] }));
|
|
253
|
+
}, [order?.lines, order?.payments]);
|
|
254
|
+
if (!order)
|
|
255
|
+
return null;
|
|
256
|
+
return (_jsxs(_Fragment, { children: [_jsx(Dialog, { open: open, onOpenChange: (e) => (!e ? closeAddVariantDialog() : setOpen(true)), children: _jsx(DialogContent, { className: "bg-background max-h-[90vh] min-h-[60vh] max-w-[65vw] overflow-auto", children: selectedVariant ? (_jsxs("div", { className: "flex size-full flex-col justify-between", children: [_jsx("h3", { className: "text-primary pb-4 text-xl font-semibold", children: t('create.addVariant') }), _jsx("div", { className: "flex h-full flex-col gap-8", children: _jsx("div", { className: "flex size-full flex-col items-center gap-2", children: _jsxs("div", { className: "flex size-full justify-between gap-4", children: [_jsx(SpecialLineItem, { variant: { ...selectedVariant, quantity: 1 } }), _jsx(CustomComponent, { onVariantAdd: handleNewVariantAdd, orderLine: selectedVariant })] }) }) })] })) : (_jsx("div", { className: "text-muted-foreground flex items-center justify-center p-8", children: t('create.somethingWrong') })) }) }), _jsx(CustomCard, { color: "blue", description: t(mode === 'view' ? 'create.viewHeader' : mode === 'update' ? 'create.editHeader' : 'create.addHeader'), title: t(mode === 'view' ? 'create.viewTitle' : mode === 'update' ? 'create.editTitle' : 'create.addTitle'), icon: _jsx(ShoppingCart, {}), children: _jsxs("div", { className: "grid gap-6", children: [mode !== 'view' && (_jsx(DialogProductPicker, { initialValue: '', mode: "variant", onSubmit: async (selectedProduct) => {
|
|
257
|
+
const payload = {
|
|
258
|
+
variant: {
|
|
259
|
+
id: selectedProduct.productVariantId,
|
|
260
|
+
price: selectedProduct.price.__typename === 'SinglePrice'
|
|
261
|
+
? selectedProduct.price.value
|
|
262
|
+
: selectedProduct.price.min,
|
|
263
|
+
priceWithTax: selectedProduct.priceWithTax.__typename === 'SinglePrice'
|
|
264
|
+
? selectedProduct.priceWithTax.value
|
|
265
|
+
: selectedProduct.priceWithTax.min,
|
|
266
|
+
sku: selectedProduct.sku,
|
|
267
|
+
currencyCode: selectedProduct.currencyCode,
|
|
268
|
+
name: selectedProduct.productVariantName,
|
|
269
|
+
productId: selectedProduct.productId,
|
|
270
|
+
stockLevels: [{ stockOnHand: 0 }],
|
|
271
|
+
product: {
|
|
272
|
+
id: selectedProduct.productId,
|
|
273
|
+
name: selectedProduct.productName,
|
|
274
|
+
slug: selectedProduct.slug,
|
|
275
|
+
featuredAsset: selectedProduct.productAsset,
|
|
276
|
+
},
|
|
277
|
+
featuredAsset: selectedProduct.productVariantAsset,
|
|
278
|
+
},
|
|
279
|
+
quantity: 1,
|
|
280
|
+
customFields: {},
|
|
281
|
+
};
|
|
282
|
+
const variant = await apiClient('query')({
|
|
283
|
+
productVariant: [
|
|
284
|
+
{ id: selectedProduct.productVariantId },
|
|
285
|
+
{ id: true, stockLevels: { id: true, stockOnHand: true } },
|
|
286
|
+
],
|
|
287
|
+
});
|
|
288
|
+
if (variant?.productVariant?.customFields) {
|
|
289
|
+
const customFields = variant?.productVariant?.customFields;
|
|
290
|
+
payload.customFields = customFields;
|
|
291
|
+
}
|
|
292
|
+
if (variant?.productVariant?.stockLevels) {
|
|
293
|
+
payload.variant.stockLevels = variant.productVariant.stockLevels;
|
|
294
|
+
}
|
|
295
|
+
if (orderLineCustomFields.length) {
|
|
296
|
+
openAddVariantDialog(payload);
|
|
297
|
+
}
|
|
298
|
+
else {
|
|
299
|
+
addToOrder(payload.variant, payload.quantity, payload.customFields);
|
|
300
|
+
}
|
|
301
|
+
} })), _jsx("div", { className: "border-border rounded-lg border-0 shadow-sm", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { noHover: true, className: "hover:bg-transparent", children: [_jsx(TableHead, { className: "py-3 font-semibold", children: t('create.product', 'Product') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('create.sku', 'SKU') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('create.customFields', 'Custom Fields') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('create.price', 'Price') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('create.priceWithTax', 'Price with Tax') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('create.quantity', 'Quantity') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('create.perUnit', 'Per Unit') }), (mode === 'create' || mode === 'update') && (_jsx(TableHead, { className: "py-3 text-right font-semibold", children: t('create.actions', 'Actions') }))] }) }), _jsx(TableBody, { children: currentOrder.lines.length ? (_jsxs(_Fragment, { children: [currentOrder.lines.map((line) => (_jsxs(TableRow, { className: "hover:bg-muted/20", children: [_jsx(TableCell, { className: "py-3", children: _jsxs("div", { className: "flex w-max items-center gap-3", children: [_jsx(ImageWithPreview, { imageClassName: "aspect-square w-12 h-12 rounded-md object-cover border border-border", src: line.productVariant.featuredAsset?.preview ||
|
|
302
|
+
line.productVariant.product?.featuredAsset?.preview ||
|
|
303
|
+
'/placeholder.svg' }), _jsx("div", { className: "text-primary font-medium", children: line.productVariant.product.name })] }) }), _jsx(TableCell, { className: "text-muted-foreground min-w-[200px] py-3 font-mono text-sm", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Tag, { className: "size-4 text-blue-500 dark:text-blue-400" }), line.productVariant.sku] }) }), _jsx(TableCell, { className: "py-3", children: _jsx(OrderLineCustomFields, { line: line, order: currentOrder, mode: mode }) }), _jsx(TableCell, { className: "py-3 font-medium", children: priceFormatter(line.linePrice, line.productVariant.currencyCode) }), _jsx(TableCell, { className: "py-3 font-medium", children: priceFormatter(line.linePriceWithTax, line.productVariant.currencyCode) }), _jsx(TableCell, { className: "py-3 text-center font-semibold", children: renderLineQuantity(line.id, line.quantity) }), _jsx(TableCell, { className: "py-3", children: _jsxs("div", { className: "flex flex-col", children: [_jsx("span", { children: priceFormatter(line.unitPrice, line.productVariant.currencyCode) }), _jsxs("span", { className: "text-muted-foreground text-sm", children: ["(", priceFormatter(line.unitPriceWithTax, line.productVariant.currencyCode), ")"] })] }) }), (mode === 'create' || mode === 'update') && (_jsx(TableCell, { className: "py-3 text-right", children: _jsxs("div", { className: "flex items-center justify-end gap-3", children: [_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { className: "hover:bg-muted flex size-8 items-center justify-center rounded-md", children: _jsx(EllipsisVertical, { className: "size-5" }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsx(DropdownMenuLabel, { children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Edit, { className: "size-4 text-blue-500" }), t('editOptions', 'Edit Options')] }) }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { disabled: isLineAddedInModify(line.id), onClick: () => !isLineAddedInModify(line.id) && setOrderLineAction({ line }), className: cn('flex cursor-pointer justify-between', {
|
|
304
|
+
'text-muted-foreground': isLineAddedInModify(line.id),
|
|
305
|
+
}), children: [_jsx("span", { children: t('orderLineActionModal.actionType.quantity-price', 'Adjust Quantity & Price') }), isLineAddedInModify(line.id) && (_jsx(TooltipProvider, { children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(InfoIcon, { className: "text-muted-foreground size-4" }) }), _jsx(TooltipContent, { children: _jsx("p", { children: t('modify.disclaimer', 'Cannot modify items added in previous sessions') }) })] }) }))] })] })] }), (mode === 'create' || isLineAddedInModify(line.id)) && (_jsx("button", { className: "flex size-8 items-center justify-center rounded-md text-red-500 hover:bg-red-50 hover:text-red-600", onClick: () => removeLineItem(line.id), children: _jsx(Trash2, { className: "size-4" }) }))] }) }))] }, line.id))), currentOrder?.surcharges.map((surcharge) => (_jsxs(TableRow, { className: "bg-muted/10 hover:bg-muted/20", children: [_jsx(TableCell, { className: "text-primary py-3 font-medium", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Package, { className: "size-4 text-blue-500 dark:text-blue-400" }), surcharge.description] }) }), _jsx(TableCell, { className: "text-muted-foreground min-w-[200px] py-3 font-mono text-sm", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Tag, { className: "size-4 text-blue-500 dark:text-blue-400" }), surcharge.sku] }) }), _jsx(TableCell, { className: "py-3" }), _jsx(TableCell, { className: "text-nowrap py-3 font-medium", children: priceFormatter(surcharge.price, order.currencyCode) }), _jsx(TableCell, { className: "text-nowrap py-3 font-medium", children: priceFormatter(surcharge.priceWithTax, order.currencyCode) }), _jsx(TableCell, { className: "py-3" }), _jsx(TableCell, { className: "py-3 font-medium", children: priceFormatter(surcharge.priceWithTax, order.currencyCode) }), (mode === 'create' || mode === 'update') && _jsx(TableCell, { className: "py-3" })] }, surcharge.sku)))] })) : (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: 8, children: _jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [_jsx("div", { className: "mb-4 rounded-full bg-blue-100 p-3 dark:bg-blue-900/30", children: _jsx(ShoppingCart, { className: "size-6 text-blue-500 dark:text-blue-400" }) }), _jsx("span", { className: "text-muted-foreground text-lg font-medium", children: t('create.noItems', 'No products in this order') }), mode !== 'view' && (_jsx("span", { className: "text-muted-foreground mt-2 text-sm", children: t('create.searchPlaceholder', 'Use the search above to add products') }))] }) }) })) })] }) }), _jsx("div", { className: "mt-6 border-t pt-4", children: _jsx("div", { className: "bg-card rounded-lg border p-4 shadow-sm", children: _jsxs("div", { className: "space-y-2", children: [_jsxs("div", { className: "flex justify-between", children: [_jsx("span", { className: "text-base font-semibold", children: t('total') }), _jsx("span", { className: "text-primary text-base font-bold", children: priceFormatter(currentOrder?.totalWithTax || 0, currentOrder?.currencyCode) })] }), _jsx("div", { className: "text-muted-foreground mt-2 text-xs", children: _jsxs("div", { className: "flex items-center gap-1", children: [_jsx(InfoIcon, { className: "size-3" }), _jsx("span", { children: t('totalItems', {
|
|
306
|
+
value: currentOrder?.lines.reduce((acc, line) => acc + line.quantity, 0) || 0,
|
|
307
|
+
}) })] }) })] }) }) }), _jsx(OrderLineActionModal, { onPriceQuantityChangeApprove: onPriceQuantityChangeApprove, onOpenChange: onOrderLineActionModalOpenChange, ...orderLineAction })] }) })] }));
|
|
308
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { OrderLineCustomFields } from "./OrderLineCustomFields.js";
|
|
3
|
+
import { Checkbox, ImageWithPreview, Input, Label, priceFormatter, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, useOrder, } from '@deenruv/react-ui-devkit';
|
|
4
|
+
import { Tag } from 'lucide-react';
|
|
5
|
+
import { useCallback } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
export const ProductsTable = ({ setRefundLines, refundLines }) => {
|
|
8
|
+
const { t } = useTranslation('orders');
|
|
9
|
+
const { mode, currentOrder } = useOrder();
|
|
10
|
+
const handleLineChange = useCallback((lineId, quantity) => {
|
|
11
|
+
const existingLineIdx = refundLines.findIndex((l) => l.orderLineId === lineId);
|
|
12
|
+
console.log('EL', existingLineIdx);
|
|
13
|
+
setRefundLines((prev) => {
|
|
14
|
+
const newState = [...prev];
|
|
15
|
+
if (existingLineIdx !== -1) {
|
|
16
|
+
newState[existingLineIdx].quantity = quantity;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
newState.push({ orderLineId: lineId, quantity });
|
|
20
|
+
}
|
|
21
|
+
return newState;
|
|
22
|
+
});
|
|
23
|
+
}, [refundLines]);
|
|
24
|
+
return (_jsx("div", { className: "border-border rounded-lg border-0 shadow-sm", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { noHover: true, className: "hover:bg-transparent", children: [_jsx(TableHead, { className: "py-3 font-semibold", children: t('create.product', 'Product') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('create.sku', 'SKU') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('create.customFields', 'Custom Fields') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('create.price', 'Price') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('create.priceWithTax', 'Price with Tax') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('cancelAndRefund.refund') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('cancelAndRefund.returnToStock') })] }) }), _jsx(TableBody, { children: currentOrder.lines.map((line) => (_jsxs(TableRow, { className: "hover:bg-muted/20", children: [_jsx(TableCell, { className: "py-3", children: _jsxs("div", { className: "flex w-max items-center gap-3", children: [_jsx(ImageWithPreview, { imageClassName: "aspect-square w-12 h-12 rounded-md object-cover border border-border", src: line.productVariant.featuredAsset?.preview ||
|
|
25
|
+
line.productVariant.product?.featuredAsset?.preview ||
|
|
26
|
+
'/placeholder.svg' }), _jsx("div", { className: "text-primary font-medium", children: line.productVariant.product.name })] }) }), _jsx(TableCell, { className: "text-muted-foreground min-w-[200px] py-3 font-mono text-sm", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Tag, { className: "h-4 w-4 text-blue-500 dark:text-blue-400" }), line.productVariant.sku] }) }), _jsx(TableCell, { className: "py-3", children: _jsx(OrderLineCustomFields, { line: line, order: currentOrder, mode: mode }) }), _jsx(TableCell, { className: "py-3 font-medium", children: priceFormatter(line.linePrice, line.productVariant.currencyCode) }), _jsx(TableCell, { className: "py-3 font-medium", children: priceFormatter(line.linePriceWithTax, line.productVariant.currencyCode) }), _jsx(TableCell, { className: "py-3", children: _jsx(Input, { type: "number", wrapperClassName: "w-24", endAdornment: '/' + line.quantity, defaultValue: 0, max: line.quantity, onChange: (e) => {
|
|
27
|
+
handleLineChange(line.id, +e.target.value);
|
|
28
|
+
} }) }), _jsx(TableCell, { className: "py-3", children: _jsxs("div", { className: "flex gap-2", children: [_jsx(Checkbox, {}), _jsx(Label, { children: t('cancelAndRefund.returnToStock') })] }) })] }, line.id))) })] }) }));
|
|
29
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useOrder, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, Badge, ScrollArea, EmptyState, CustomCard, useTranslation, Button, useMutation, CardDescription, useLazyQuery, Input, OrderDetailSelector, priceFormatter, } from '@deenruv/react-ui-devkit';
|
|
4
|
+
import { BadgePercent, Gift, Tag, CreditCard, Trash, Plus } from 'lucide-react';
|
|
5
|
+
import { $, scalars, typedGql } from '@deenruv/admin-types';
|
|
6
|
+
import { toast } from 'sonner';
|
|
7
|
+
import { useEffect, useState } from 'react';
|
|
8
|
+
const ToggleExcludePromotionMutation = typedGql('mutation', { scalars })({
|
|
9
|
+
toggleExcludePromotionInOrder: [
|
|
10
|
+
{ orderId: $('orderId', 'ID!'), promotionId: $('promotionId', 'ID!') },
|
|
11
|
+
OrderDetailSelector,
|
|
12
|
+
],
|
|
13
|
+
});
|
|
14
|
+
const ExcludedPromotionsQuery = typedGql('query', { scalars })({
|
|
15
|
+
promotions: [{ options: { filter: { id: { in: $('ids', '[String!]') } } } }, { items: { name: true, id: true } }],
|
|
16
|
+
});
|
|
17
|
+
const ApplyCouponCodeMutation = typedGql('mutation', { scalars })({
|
|
18
|
+
applyCouponCodeToDraftOrder: [
|
|
19
|
+
{ orderId: $('orderId', 'ID!'), couponCode: $('couponCode', 'String!') },
|
|
20
|
+
{ '...on CouponCodeExpiredError': { message: true }, __typename: true, '...on Order': OrderDetailSelector },
|
|
21
|
+
],
|
|
22
|
+
});
|
|
23
|
+
const RemoveCouponCodeMutation = typedGql('mutation', { scalars })({
|
|
24
|
+
removeCouponCodeFromDraftOrder: [
|
|
25
|
+
{ orderId: $('orderId', 'ID!'), couponCode: $('couponCode', 'String!') },
|
|
26
|
+
OrderDetailSelector,
|
|
27
|
+
],
|
|
28
|
+
});
|
|
29
|
+
export const PromotionsList = () => {
|
|
30
|
+
const { order, setOrder } = useOrder();
|
|
31
|
+
const { t } = useTranslation('orders');
|
|
32
|
+
const [togglePromotionExclusion, { loading: exclusionLoading }] = useMutation(ToggleExcludePromotionMutation);
|
|
33
|
+
const [removeCoupon, { loading: removeCouponLoading }] = useMutation(RemoveCouponCodeMutation);
|
|
34
|
+
const [applyCoupon] = useMutation(ApplyCouponCodeMutation);
|
|
35
|
+
const [fetchExcludedPromotions, { data: excludedData }] = useLazyQuery(ExcludedPromotionsQuery);
|
|
36
|
+
const excluded = excludedData?.promotions?.items ?? [];
|
|
37
|
+
const loading = exclusionLoading || removeCouponLoading;
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
fetchExcludedPromotions({
|
|
40
|
+
ids: order?.excludedPromotionIds || [],
|
|
41
|
+
});
|
|
42
|
+
}, [order?.excludedPromotionIds]);
|
|
43
|
+
const [couponCode, setCouponCode] = useState('');
|
|
44
|
+
if (!order)
|
|
45
|
+
return null;
|
|
46
|
+
const removeExcludePromotionHandler = async ({ id, couponCode, }) => {
|
|
47
|
+
let res;
|
|
48
|
+
if (!couponCode) {
|
|
49
|
+
res = await togglePromotionExclusion({ orderId: order.id, promotionId: id });
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
res = await removeCoupon({ orderId: order.id, couponCode: couponCode });
|
|
53
|
+
}
|
|
54
|
+
if ('removeCouponCodeFromDraftOrder' in res) {
|
|
55
|
+
setOrder(res.removeCouponCodeFromDraftOrder);
|
|
56
|
+
}
|
|
57
|
+
else if ('toggleExcludePromotionInOrder' in res) {
|
|
58
|
+
setOrder(res.toggleExcludePromotionInOrder);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const addCouponHandler = async () => {
|
|
62
|
+
const resp = await applyCoupon({ couponCode: couponCode, orderId: order.id });
|
|
63
|
+
if (resp.applyCouponCodeToDraftOrder.__typename === 'Order') {
|
|
64
|
+
setOrder(resp.applyCouponCodeToDraftOrder);
|
|
65
|
+
setCouponCode('');
|
|
66
|
+
toast.success(t('couponCodes.addToastSuccess'));
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
toast.error('could not add coupon code');
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
return (_jsxs("div", { className: "grid w-full grid-cols-1 gap-4 md:grid-cols-6 lg:grid-cols-12", children: [_jsx(CustomCard, { notCollapsible: true, color: "blue", description: t('promotions.description', 'Active order promotions'), title: t('promotions.title', 'Promotions'), wrapperClassName: "col-span-1 h-full md:col-span-2 lg:col-span-6", icon: _jsx(Gift, {}), upperRight: _jsxs("div", { className: "flex gap-2 py-2", children: [_jsx(Input, { placeholder: t('couponCodes.placeholder'), value: couponCode, onChange: (e) => setCouponCode(e.target.value) }), _jsx(Button, { size: 'icon', className: "w-14", onClick: addCouponHandler, children: _jsx(Plus, {}) })] }), children: _jsxs(ScrollArea, { className: "h-[280px]", children: [_jsxs(Table, { className: "h-full", children: [_jsx(TableHeader, { children: _jsxs(TableRow, { noHover: true, className: "border-border border-b", children: [_jsx(TableHead, { className: "py-3", children: t('taxSummary.description') }), _jsx(TableHead, { className: "py-3", children: t('couponCodes.title') }), _jsx(TableHead, { align: "right", style: { textAlign: 'right' }, children: t('table.actions') })] }) }), _jsx(TableBody, { className: "h-[232px]", children: order.promotions.length ? (order.promotions.map(({ name, couponCode, id }) => (_jsxs(TableRow, { noHover: true, className: "group", children: [_jsx(TableCell, { className: "py-3 font-medium", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Tag, { className: "size-4 text-blue-500 dark:text-blue-400" }), _jsx("span", { className: "capitalize", children: name })] }) }), _jsx(TableCell, { className: "py-3", children: couponCode ? (_jsx(Badge, { variant: "outline", className: "font-mono text-xs", children: couponCode })) : (_jsx("span", { className: "text-muted-foreground", children: "\u2014" })) }), _jsx(TableCell, { align: "right", children: _jsx(Button, { size: "icon", variant: "destructive", disabled: loading, onClick: () => removeExcludePromotionHandler({ couponCode, id }), children: _jsx(Trash, { size: 16 }) }) })] }, name)))) : (_jsx(EmptyState, { columnsLength: 3, title: t('promotions.noPromotions', 'No promotions applied'), color: "blue", icon: _jsx(Gift, {}), small: true })) })] }), !!excluded.length && (_jsxs(_Fragment, { children: [_jsx("hr", { className: "!my-4 border-t-[3px]" }), _jsx(CardDescription, { children: t('promotion.excludedPromotions') }), _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { noHover: true, children: [_jsx(TableHead, { children: t('promotion.name') }), _jsx(TableHead, { align: "right", style: { textAlign: 'right' }, children: t('table.actions') })] }) }), _jsx(TableBody, { children: excluded.map(({ name, id }) => (_jsxs(TableRow, { noHover: true, children: [_jsx(TableCell, { className: "capitalize", children: name }), _jsx(TableCell, { align: "right", children: _jsx(Button, { size: "icon", variant: "destructive", onClick: () => removeExcludePromotionHandler({ id }), children: _jsx(Trash, { size: 16 }) }) })] }, name))) })] })] }))] }) }), _jsx(CustomCard, { notCollapsible: true, description: t('discounts.description', 'Applied order discounts'), title: t('discounts.title', 'Discounts'), icon: _jsx(BadgePercent, { className: "size-5 text-green-500 dark:text-green-400" }), wrapperClassName: "col-span-1 h-full md:col-span-2 lg:col-span-6", color: "green", children: _jsx(ScrollArea, { className: "h-[280px]", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsxs(TableRow, { noHover: true, className: "border-border border-b", children: [_jsx(TableHead, { className: "py-3", children: t('taxSummary.description') }), _jsx(TableHead, { className: "py-3", children: t('taxSummary.taxRate', 'Type') }), _jsx(TableHead, { className: "py-3", children: t('taxSummary.taxBase', 'Amount') }), _jsx(TableHead, { className: "py-3", children: t('taxSummary.taxTotal', 'With Tax') }), _jsx(TableHead, { className: "py-3", children: t('discounts.source', 'Source') })] }) }), _jsx(TableBody, { className: "h-[232px]", children: order.discounts.length ? (order.discounts.map(({ adjustmentSource, amount, amountWithTax, description, type }, index) => (_jsxs(TableRow, { noHover: true, className: "group", children: [_jsx(TableCell, { className: "py-3 font-medium", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(CreditCard, { className: "size-4 text-green-500 dark:text-green-400" }), _jsx("span", { className: "capitalize", children: description })] }) }), _jsx(TableCell, { className: "py-3", children: _jsx(Badge, { variant: "secondary", className: "font-medium", children: type }) }), _jsx(TableCell, { className: "py-3 font-mono text-sm", children: priceFormatter(amount, order.currencyCode) }), _jsx(TableCell, { className: "py-3 font-mono text-sm", children: priceFormatter(amountWithTax, order.currencyCode) }), _jsx(TableCell, { className: "py-3", children: _jsx(Badge, { variant: "outline", className: "capitalize", children: adjustmentSource }) })] }, index)))) : (_jsx(EmptyState, { columnsLength: 5, title: t('discounts.emptyState'), color: "green", icon: _jsx(BadgePercent, {}), small: true })) })] }) }) })] }));
|
|
73
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { TableHeader, TableRow, TableHead, TableBody, TableCell, Table, apiClient, useOrder, OrderDetailSelector, Badge, ScrollArea, CustomCard, ContextMenu, DropdownMenuItem, ConfirmationDialog, Button, useTranslation, } from '@deenruv/react-ui-devkit';
|
|
4
|
+
import { AnimatePresence, motion } from 'framer-motion';
|
|
5
|
+
import { useCallback, useState } from 'react';
|
|
6
|
+
import { toast } from 'sonner';
|
|
7
|
+
import { ORDER_STATE } from "../../../graphql/base";
|
|
8
|
+
import { Package, Truck, CheckCircle, XCircle, AlertCircle, ClipboardCheck } from 'lucide-react';
|
|
9
|
+
export const RealizationCard = () => {
|
|
10
|
+
const { order, setOrder, fetchOrderHistory, cancelFulfillment } = useOrder();
|
|
11
|
+
const { t } = useTranslation('orders');
|
|
12
|
+
const [processingFulfillments, setProcessingFulfillments] = useState({});
|
|
13
|
+
const markAsDelivered = async (fulfillmentId) => {
|
|
14
|
+
if (!order)
|
|
15
|
+
return;
|
|
16
|
+
setProcessingFulfillments((prev) => ({ ...prev, [fulfillmentId]: true }));
|
|
17
|
+
try {
|
|
18
|
+
const { transitionFulfillmentToState } = await apiClient('mutation')({
|
|
19
|
+
transitionFulfillmentToState: [
|
|
20
|
+
{ id: fulfillmentId, state: 'Delivered' },
|
|
21
|
+
{
|
|
22
|
+
__typename: true,
|
|
23
|
+
'...on Fulfillment': {
|
|
24
|
+
id: true,
|
|
25
|
+
},
|
|
26
|
+
'...on FulfillmentStateTransitionError': {
|
|
27
|
+
errorCode: true,
|
|
28
|
+
fromState: true,
|
|
29
|
+
message: true,
|
|
30
|
+
toState: true,
|
|
31
|
+
transitionError: true,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
if (transitionFulfillmentToState.__typename === 'Fulfillment') {
|
|
37
|
+
const resp = await apiClient('query')({ order: [{ id: order.id }, OrderDetailSelector] });
|
|
38
|
+
setOrder(resp.order);
|
|
39
|
+
fetchOrderHistory();
|
|
40
|
+
toast.success(t('fulfillments.deliveredSuccess', 'Fulfillment marked as delivered'));
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const errorMessage = transitionFulfillmentToState?.message || t('fulfillments.error', 'Something went wrong');
|
|
44
|
+
toast.error(errorMessage);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
toast.error(t('fulfillments.error', 'Something went wrong'));
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
setProcessingFulfillments((prev) => ({ ...prev, [fulfillmentId]: false }));
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
const handleCancelFulfillment = async (fulfillmentId) => {
|
|
55
|
+
if (!order)
|
|
56
|
+
return;
|
|
57
|
+
setProcessingFulfillments((prev) => ({ ...prev, [fulfillmentId]: true }));
|
|
58
|
+
try {
|
|
59
|
+
cancelFulfillment(fulfillmentId);
|
|
60
|
+
}
|
|
61
|
+
finally {
|
|
62
|
+
setProcessingFulfillments((prev) => ({ ...prev, [fulfillmentId]: false }));
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
const markAllAsDelivered = useCallback(async () => {
|
|
66
|
+
const shippedIds = order?.fulfillments?.filter((f) => f.state === ORDER_STATE.SHIPPED).map((f) => f.id);
|
|
67
|
+
shippedIds?.forEach((id) => {
|
|
68
|
+
markAsDelivered(id);
|
|
69
|
+
});
|
|
70
|
+
}, []);
|
|
71
|
+
const getFulfillmentStateBadge = (state) => {
|
|
72
|
+
switch (state) {
|
|
73
|
+
case ORDER_STATE.CREATED:
|
|
74
|
+
return { variant: 'secondary', icon: _jsx(Package, { className: "mr-1 size-3.5" }) };
|
|
75
|
+
case ORDER_STATE.SHIPPED:
|
|
76
|
+
return { variant: 'outline', icon: _jsx(Truck, { className: "mr-1 size-3.5 text-blue-500" }) };
|
|
77
|
+
case ORDER_STATE.DELIVERED:
|
|
78
|
+
return { variant: 'success', icon: _jsx(CheckCircle, { className: "mr-1 size-3.5" }) };
|
|
79
|
+
case ORDER_STATE.CANCELLED:
|
|
80
|
+
return { variant: 'destructive', icon: _jsx(XCircle, { className: "mr-1 size-3.5" }) };
|
|
81
|
+
default:
|
|
82
|
+
return { variant: 'outline', icon: _jsx(AlertCircle, { className: "mr-1 size-3.5" }) };
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
if (!order)
|
|
86
|
+
return null;
|
|
87
|
+
if (!order.fulfillments?.length)
|
|
88
|
+
return null;
|
|
89
|
+
return (_jsx(AnimatePresence, { children: _jsx(motion.div, { initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.4, ease: 'easeInOut' }, children: _jsx(CustomCard, { title: t('fulfillments.title', 'Order Fulfillments'), description: t('fulfillments.description', 'Track and manage the delivery status of this order'), icon: _jsx(ClipboardCheck, {}), color: "rose", upperRight: _jsxs(Button, { variant: order.state === ORDER_STATE.SHIPPED ? 'action' : 'ghost', size: "sm", disabled: order.state !== ORDER_STATE.SHIPPED, className: "gap-2", onClick: markAllAsDelivered, children: [_jsx(CheckCircle, { className: "size-4" }), order?.fulfillments?.filter((f) => f.state === ORDER_STATE.SHIPPED).length > 0
|
|
90
|
+
? t('fulfillments.markAllAsDelivered')
|
|
91
|
+
: t('fulfillments.allDelivered')] }), children: _jsx(ScrollArea, { className: "max-h-[350px]", children: _jsxs(Table, { children: [_jsx(TableHeader, { className: "bg-muted/30", children: _jsxs(TableRow, { noHover: true, className: "hover:bg-transparent", children: [_jsx(TableHead, { className: "py-3 font-semibold", children: t('fulfillments.method', 'Method') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('fulfillments.state', 'Status') }), _jsx(TableHead, { className: "py-3 font-semibold", children: t('fulfillments.trackingCode', 'Tracking Code') }), _jsx(TableHead, { className: "py-3 text-right font-semibold", children: t('fulfillments.actions', 'Actions') })] }) }), _jsx(TableBody, { children: order.fulfillments.map((fulfillment) => {
|
|
92
|
+
const stateBadge = getFulfillmentStateBadge(fulfillment.state);
|
|
93
|
+
const isProcessing = processingFulfillments[fulfillment.id];
|
|
94
|
+
console.log('FLF', fulfillment);
|
|
95
|
+
return (_jsxs(TableRow, { className: "hover:bg-muted/20", children: [_jsx(TableCell, { className: "py-3", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Truck, { className: "size-4 text-green-500 dark:text-green-400" }), _jsx("span", { className: "font-medium", children: fulfillment.method })] }) }), _jsx(TableCell, { className: "py-3", children: _jsxs(Badge, { variant: stateBadge.variant, className: "flex w-fit items-center gap-1", children: [stateBadge.icon, t('fulfillments.states.' + fulfillment.state.toLowerCase())] }) }), _jsx(TableCell, { className: "py-3", children: fulfillment.trackingCode ? (_jsx("div", { className: "flex items-center gap-2", children: _jsx("code", { className: "bg-muted rounded px-2 py-1 font-mono text-xs", children: fulfillment.trackingCode }) })) : (_jsx("span", { className: "text-muted-foreground", children: "\u2014" })) }), _jsx(TableCell, { className: "py-3 text-right", children: _jsxs(ContextMenu, { disabled: fulfillment.state === ORDER_STATE.CANCELLED, children: [fulfillment.state === ORDER_STATE.SHIPPED && (_jsxs(DropdownMenuItem, { onClick: () => markAsDelivered(fulfillment.id), disabled: isProcessing, className: "flex cursor-pointer items-center gap-2", children: [_jsx(CheckCircle, { className: "size-3.5 text-green-500" }), t('fulfillments.markAsDelivered', 'Mark as Delivered')] }, 'set')), (fulfillment.state === ORDER_STATE.DELIVERED ||
|
|
96
|
+
fulfillment.state === ORDER_STATE.SHIPPED) && (_jsx(ConfirmationDialog, { onConfirm: () => handleCancelFulfillment(fulfillment.id), children: _jsxs(DropdownMenuItem, { disabled: isProcessing, className: "flex cursor-pointer items-center gap-2 text-red-500", onSelect: (e) => e.preventDefault(), children: [_jsx(XCircle, { size: 16 }), t('fulfillments.cancel', 'Cancel')] }, 'cancel') }))] }) })] }, fulfillment.id));
|
|
97
|
+
}) })] }) }) }) }) }));
|
|
98
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation, cn, priceFormatter, Textarea, useOrder } from '@deenruv/react-ui-devkit';
|
|
3
|
+
import { CreditCard, FileText } from 'lucide-react';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
export const RefundCard = ({ priceDifference, refundReason, setRefundReason }) => {
|
|
6
|
+
const { t } = useTranslation('orders');
|
|
7
|
+
const { modifiedOrder } = useOrder();
|
|
8
|
+
const currentPayment = modifiedOrder?.payments?.[0];
|
|
9
|
+
const [activeTab, setActiveTab] = useState('details');
|
|
10
|
+
return (_jsxs("div", { className: "border-border bg-muted/20 space-y-4 rounded-md border p-4", children: [_jsxs("div", { className: "flex items-center gap-6", children: [_jsxs("div", { className: cn('flex cursor-pointer items-center gap-2', activeTab === 'details' ? 'opacity-100' : 'opacity-60 hover:opacity-80'), onClick: () => setActiveTab('details'), children: [_jsx("div", { className: "flex size-8 items-center justify-center rounded-full bg-blue-100 dark:bg-blue-900/30", children: _jsx(CreditCard, { className: "size-4 text-blue-500 dark:text-blue-400" }) }), _jsx("h4", { className: "font-medium", children: t('refund.details', 'Refund Details') })] }), _jsxs("div", { className: cn('flex cursor-pointer items-center gap-2', activeTab === 'note' ? 'opacity-100' : 'opacity-60 hover:opacity-80'), onClick: () => setActiveTab('note'), children: [_jsx("div", { className: "flex size-8 items-center justify-center rounded-full bg-blue-100 dark:bg-blue-900/30", children: _jsx(FileText, { className: "size-4 text-blue-500 dark:text-blue-400" }) }), _jsx("h4", { className: "font-medium", children: t('refund.note', 'Refund Note') })] })] }), activeTab === 'details' && (_jsxs("div", { className: "grid gap-6", children: [_jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsx("p", { className: "text-muted-foreground text-sm", children: t('refund.method') }), _jsx("p", { className: "font-medium", children: currentPayment?.method })] }), _jsxs("div", { children: [_jsx("p", { className: "text-muted-foreground text-sm", children: t('refund.id') }), _jsx("p", { className: "font-medium", children: currentPayment?.transactionId })] })] }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsx("p", { className: "text-muted-foreground text-sm", children: t('refund.amount') }), _jsx("p", { className: "font-medium", children: priceFormatter(currentPayment?.amount ?? 0, modifiedOrder?.currencyCode) })] }), _jsxs("div", { children: [_jsx("p", { className: "text-muted-foreground text-sm", children: t('refund.refund') }), _jsx("p", { className: "font-medium", children: priceFormatter(priceDifference * -1, modifiedOrder?.currencyCode) })] })] })] })), activeTab === 'note' && (_jsx("div", { className: "space-y-2", children: _jsx(Textarea, { id: "note", placeholder: t('notePlaceholder', 'Enter optional info of the reason'), value: refundReason, onChange: (e) => setRefundReason(e.target.value), className: "min-h-[60px] resize-y" }) }))] }));
|
|
11
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Checkbox, CustomCard, Input, Label, priceFormatter, Textarea, useOrder } from '@deenruv/react-ui-devkit';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
export const RefundPaymentCard = ({ refundReason, setRefundReason, cancelShipping, setCancelShipping, refundAmount, setRefundAmount, }) => {
|
|
5
|
+
const { t } = useTranslation('orders');
|
|
6
|
+
const { modifiedOrder } = useOrder();
|
|
7
|
+
const currentPayment = modifiedOrder?.payments?.[0];
|
|
8
|
+
return (_jsxs("div", { className: "mt-8 grid grid-cols-2 gap-4", children: [_jsx(CustomCard, { title: t('refund.details', 'Refund Details'), notCollapsible: true, children: _jsxs("div", { className: "grid gap-6", children: [_jsx("div", { className: "grid grid-cols-2 gap-4", children: _jsxs("div", { className: "flex gap-2", children: [_jsx(Checkbox, { checked: cancelShipping, onCheckedChange: (e) => setCancelShipping(!!e) }), _jsx(Label, { children: t('cancelAndRefund.refundShipping') })] }) }), _jsxs("div", { className: "grid grid-cols-2 gap-4", children: [_jsxs("div", { children: [_jsx("p", { className: "text-muted-foreground text-sm", children: t('refund.method') }), _jsx("p", { className: "font-medium", children: currentPayment?.method })] }), _jsxs("div", { children: [_jsx("p", { className: "text-muted-foreground text-sm", children: t('refund.id') }), _jsx("p", { className: "font-medium", children: currentPayment?.transactionId })] })] }), _jsx("div", { className: "grid grid-cols-2 gap-4", children: _jsxs("div", { children: [_jsx("p", { className: "text-muted-foreground text-sm", children: t('refund.amount') }), _jsx("p", { className: "font-medium", children: priceFormatter(currentPayment?.amount ?? 0, modifiedOrder?.currencyCode) })] }) }), _jsx("div", { className: "grid grid-cols-2 gap-4", children: _jsxs("div", { children: [_jsx("p", { className: "text-muted-foreground text-sm", children: t('refund.refund') }), _jsx(Input
|
|
9
|
+
// type="currency"
|
|
10
|
+
, {
|
|
11
|
+
// type="currency"
|
|
12
|
+
startAdornment: modifiedOrder?.currencyCode, adornmentPlain: true, value: refundAmount, onChange: (e) => setRefundAmount(+e.target.value) })] }) })] }) }), _jsx(CustomCard, { title: t('refund.note', 'Refund Note'), notCollapsible: true, children: _jsx(Textarea, { id: "note", placeholder: t('notePlaceholder', 'Enter optional info of the reason'), value: refundReason, onChange: (e) => setRefundReason(e.target.value), className: "min-h-[60px] resize-y", rows: 8 }) })] }));
|
|
13
|
+
};
|