From fe68b5c0f24c1a4d7528deb722302f516d283ad7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Frane=20Poli=C4=87?= <16856471+fPolic@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:38:52 +0200 Subject: [PATCH] refactor(dashboard): refresh domains (#7087) --- .../public/locales/en-US/translation.json | 35 +++++++- .../dashboard/src/types/api-responses.ts | 1 + .../adjust-inventory-drawer.tsx | 2 +- .../components/adjust-inventory-form.tsx | 24 +++-- .../components/edit-item-attributes-form.tsx | 17 +++- .../edit-item-attributes-drawer.tsx | 2 +- .../components/edit-item-form.tsx | 15 +++- .../edit-inventory-item/edit-item-drawer.tsx | 2 +- .../inventory-item-general-section.tsx | 10 +-- .../inventory-item-location-levels.tsx | 1 - .../location-list-table.tsx | 15 ++-- .../components/location-item.tsx | 2 +- .../components/manage-locations-form.tsx | 41 +++++---- .../manage-locations-drawer.tsx | 2 +- .../reservation-list-table.tsx | 15 ++-- .../inventory/inventory-detail/index.ts | 2 +- .../inventory-detail/inventory-detail.tsx | 19 ++-- .../components/inventory-list-table.tsx | 16 ++-- .../dashboard/src/v2-routes/invite/invite.tsx | 12 ++- .../create-location-form.tsx | 27 +++--- .../location-sales-channel-section.tsx | 22 +++-- .../location-detail/location-detail.tsx | 7 +- .../edit-location-form/edit-location-form.tsx | 26 +++--- .../locations/location-edit/location-edit.tsx | 12 +-- .../locations-list-table.tsx | 20 +++-- .../use-location-table-query.tsx | 3 +- .../dashboard/src/v2-routes/login/login.tsx | 57 ++++++------ .../profile/profile-detail/profile-detail.tsx | 4 +- .../edit-profile-form/edit-profile-form.tsx | 33 ++++--- .../profile/profile-edit/profile-edit.tsx | 2 +- .../add-products-to-sales-channel-form.tsx | 19 +++- .../sales-channel-add-products.tsx | 7 +- .../create-sales-channel-form.tsx | 19 +++- .../sales-channel-general-section.tsx | 29 +++++-- .../sales-channel-product-section.tsx | 44 ++++++++-- .../sales-channel-detail.tsx | 2 +- .../edit-sales-channel-form.tsx | 12 ++- .../sales-channel-edit/sales-channel-edit.tsx | 7 +- .../components/sales-channel-list-table.tsx | 30 +++++-- .../add-currencies-form.tsx | 40 +++++---- .../store-add-currencies.tsx | 2 +- .../store-currency-section.tsx | 66 ++++++++++---- .../store-general-section.tsx | 18 ++++ .../store/store-detail/store-detail.tsx | 7 +- .../edit-store-form/edit-store-form.tsx | 87 +++++++++++++++++-- .../v2-routes/store/store-edit/store-edit.tsx | 2 +- .../steps/delete-stock-locations.ts | 6 +- packages/currency/src/models/currency.ts | 8 +- .../src/api-v2/admin/currencies/validators.ts | 1 + 49 files changed, 624 insertions(+), 228 deletions(-) diff --git a/packages/admin-next/dashboard/public/locales/en-US/translation.json b/packages/admin-next/dashboard/public/locales/en-US/translation.json index 0ff378766f..c4eb3d41b8 100644 --- a/packages/admin-next/dashboard/public/locales/en-US/translation.json +++ b/packages/admin-next/dashboard/public/locales/en-US/translation.json @@ -280,7 +280,12 @@ "manageInventoryLabel": "Manage inventory", "manageInventoryHint": "When enabled the inventory level will be regulated when orders and returns are created.", "allowBackordersLabel": "Allow backorders", - "allowBackordersHint": "When enabled the variant can be sold even if the inventory level is below zero." + "allowBackordersHint": "When enabled the variant can be sold even if the inventory level is below zero.", + "toast": { + "levelsBatch": "Inventory levels updated.", + "update": "Inventory item updated successfully", + "updateLevel": "Inventory level updated successfully" + } } }, "options": { @@ -1018,6 +1023,9 @@ "languageHint": "The language you want to use in the admin dashboard. This will not change the language of your store.", "languagePlaceholder": "Select language", "usageInsightsHint": "Share usage insights and help us improve Medusa. You can read more about what we collect and how we use it in our <0>documentation." + }, + "toast": { + "edit": "Profiles changes saved" } }, "users": { @@ -1051,6 +1059,7 @@ "manageYourStoresDetails": "Manage your store's details", "editStore": "Edit store", "defaultCurrency": "Default currency", + "defaultRegion": "Default region", "swapLinkTemplate": "Swap link template", "paymentLinkTemplate": "Payment link template", "inviteLinkTemplate": "Invite link template", @@ -1061,6 +1070,11 @@ "currencyAlreadyAdded": "The currency has already been added to your store.", "edit": { "header": "Edit Store" + }, + "toast": { + "update": "Store successfully updated", + "currenciesUpdated": "Currencies updated successfully", + "currenciesRemoved": "Removed currencies from the store successfully" } }, "regions": { @@ -1171,7 +1185,12 @@ "selectLocations": "Select locations that stock the item.", "deleteLocationWarning": "You are about to delete the location {{name}}. This action cannot be undone.", "removeSalesChannelsWarning_one": "You are about to remove {{count}} sales channel from the location.", - "removeSalesChannelsWarning_other": "You are about to remove {{count}} sales channels from the location." + "removeSalesChannelsWarning_other": "You are about to remove {{count}} sales channels from the location.", + "toast": { + "create": "Location created sucessfully", + "update": "Location updated sucessfully", + "removeChannel": "Sales channel removed sucessfully" + } }, "reservations": { "domain": "Reservations", @@ -1187,7 +1206,12 @@ "addProducts": "Add Products", "editSalesChannel": "Edit sales channel", "productAlreadyAdded": "The product has already been added to the sales channel.", - "deleteSalesChannelWarning": "You are about to delete the sales channel {{name}}. This action cannot be undone." + "deleteSalesChannelWarning": "You are about to delete the sales channel {{name}}. This action cannot be undone.", + "toast": { + "create": "Sales channel created successfully", + "update": "Sales channel updated successfully", + "delete": "Sales channel deleted successfully" + } }, "apiKeyManagement": { "domain": { @@ -1279,7 +1303,10 @@ "successAction": "Sign in to start using Medusa", "invalidTokenTitle": "Your invite token is invalid", "invalidTokenHint": "Try requesting a new invite link.", - "passwordMismatch": "Passwords do not match" + "passwordMismatch": "Passwords do not match", + "toast": { + "accepted": "Invite successfully accepted" + } }, "resetPassword": { "title": "Reset password", diff --git a/packages/admin-next/dashboard/src/types/api-responses.ts b/packages/admin-next/dashboard/src/types/api-responses.ts index 214d9f8547..280ba3b8d3 100644 --- a/packages/admin-next/dashboard/src/types/api-responses.ts +++ b/packages/admin-next/dashboard/src/types/api-responses.ts @@ -167,6 +167,7 @@ export type InventoryItemRes = { stocked_quantity: number reserved_quantity: number location_levels?: InventoryNext.InventoryLevelDTO[] + variant?: ProductVariantDTO | ProductVariantDTO[] } } diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/adjust-inventory/adjust-inventory-drawer.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/adjust-inventory/adjust-inventory-drawer.tsx index 1580fe4b5d..6e6509212a 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/adjust-inventory/adjust-inventory-drawer.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/adjust-inventory/adjust-inventory-drawer.tsx @@ -13,7 +13,7 @@ export const AdjustInventoryDrawer = () => { const { inventory_item: inventoryItem, - isLoading, + isPending: isLoading, isError, error, } = useInventoryItem(id!) diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/adjust-inventory/components/adjust-inventory-form.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/adjust-inventory/components/adjust-inventory-form.tsx index 93be5b78ea..a55010ffa6 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/adjust-inventory/components/adjust-inventory-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/adjust-inventory/components/adjust-inventory-form.tsx @@ -1,6 +1,6 @@ import * as zod from "zod" -import { Button, Input, Text } from "@medusajs/ui" +import { Button, Input, Text, toast } from "@medusajs/ui" import { InventoryLevelDTO, StockLocationDTO } from "@medusajs/types" import { RouteDrawer, @@ -61,7 +61,7 @@ export const AdjustInventoryForm = ({ const stockedQuantityUpdate = form.watch("stocked_quantity") - const { mutateAsync } = useUpdateInventoryItemLevel( + const { mutateAsync, isPending: isLoading } = useUpdateInventoryItemLevel( item.id, level.location_id ) @@ -71,9 +71,21 @@ export const AdjustInventoryForm = ({ return handleSuccess() } - await mutateAsync({ - stocked_quantity: value.stocked_quantity, - }) + try { + await mutateAsync({ + stocked_quantity: value.stocked_quantity, + }) + + toast.success(t("general.success"), { + description: t("inventory.toast.updateLevel"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } return handleSuccess() }) @@ -141,7 +153,7 @@ export const AdjustInventoryForm = ({ {t("actions.cancel")} - diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item-attributes/components/edit-item-attributes-form.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item-attributes/components/edit-item-attributes-form.tsx index 023ad3313a..9083b0235f 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item-attributes/components/edit-item-attributes-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item-attributes/components/edit-item-attributes-form.tsx @@ -1,6 +1,6 @@ import * as zod from "zod" -import { Button, Input } from "@medusajs/ui" +import { Button, Input, toast } from "@medusajs/ui" import { RouteDrawer, useRouteModal, @@ -52,13 +52,22 @@ export const EditInventoryItemAttributesForm = ({ resolver: zodResolver(EditInventoryItemAttributesSchema), }) - const { mutateAsync } = useUpdateInventoryItem(item.id) + const { mutateAsync, isPending: isLoading } = useUpdateInventoryItem(item.id) const handleSubmit = form.handleSubmit(async (values) => { - mutateAsync(values, { + await mutateAsync(values, { onSuccess: () => { + toast.success(t("general.success"), { + description: t("inventory.toast.update"), + dismissLabel: t("actions.close"), + }) handleSuccess() }, + onError: (error) => + toast.error(t("general.error"), { + description: error.message, + dismissLabel: t("actions.close"), + }), }) }) @@ -241,7 +250,7 @@ export const EditInventoryItemAttributesForm = ({ {t("actions.cancel")} - diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item-attributes/edit-item-attributes-drawer.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item-attributes/edit-item-attributes-drawer.tsx index 82c7172488..fe9f4eb9c3 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item-attributes/edit-item-attributes-drawer.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item-attributes/edit-item-attributes-drawer.tsx @@ -11,7 +11,7 @@ export const InventoryItemAttributesEdit = () => { const { inventory_item: inventoryItem, - isLoading, + isPending: isLoading, isError, error, } = useInventoryItem(id!) diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item/components/edit-item-form.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item/components/edit-item-form.tsx index f2f98206ae..c86649eba4 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item/components/edit-item-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item/components/edit-item-form.tsx @@ -1,6 +1,6 @@ import * as zod from "zod" -import { Button, Input } from "@medusajs/ui" +import { Button, Input, toast } from "@medusajs/ui" import { RouteDrawer, useRouteModal, @@ -39,13 +39,22 @@ export const EditInventoryItemForm = ({ item }: EditInventoryItemFormProps) => { resolver: zodResolver(EditInventoryItemSchema), }) - const { mutateAsync } = useUpdateInventoryItem(item.id) + const { mutateAsync, isPending: isLoading } = useUpdateInventoryItem(item.id) const handleSubmit = form.handleSubmit(async (values) => { mutateAsync(values as any, { onSuccess: () => { + toast.success(t("general.success"), { + description: t("inventory.toast.update"), + dismissLabel: t("actions.close"), + }) handleSuccess() }, + onError: (e) => + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }), }) }) @@ -94,7 +103,7 @@ export const EditInventoryItemForm = ({ item }: EditInventoryItemFormProps) => { {t("actions.cancel")} - diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item/edit-item-drawer.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item/edit-item-drawer.tsx index b966ec1024..7d4996f2b7 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item/edit-item-drawer.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/edit-inventory-item/edit-item-drawer.tsx @@ -11,7 +11,7 @@ export const InventoryItemEdit = () => { const { inventory_item: inventoryItem, - isLoading, + isPending: isLoading, isError, error, } = useInventoryItem(id!) diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/inventory-item-general-section.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/inventory-item-general-section.tsx index d757174d90..f1001db847 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/inventory-item-general-section.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/inventory-item-general-section.tsx @@ -1,5 +1,5 @@ -import { Container, Heading, Text } from "@medusajs/ui" -import { InventoryNext, ProductVariantDTO } from "@medusajs/types" +import { Container, Heading } from "@medusajs/ui" +import { ProductVariantDTO } from "@medusajs/types" import { ActionMenu } from "../../../../components/common/action-menu" import { InventoryItemRes } from "../../../../types/api-responses" @@ -52,7 +52,7 @@ export const InventoryItemGeneralSection = ({ title={t("fields.inStock")} value={getQuantityFormat( inventoryItem.stocked_quantity, - inventoryItem.location_levels.length + inventoryItem.location_levels?.length )} /> @@ -60,14 +60,14 @@ export const InventoryItemGeneralSection = ({ title={t("inventory.reserved")} value={getQuantityFormat( inventoryItem.reserved_quantity, - inventoryItem.location_levels.length + inventoryItem.location_levels?.length )} /> diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/inventory-item-location-levels.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/inventory-item-location-levels.tsx index f58e5e9b65..993daf33d0 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/inventory-item-location-levels.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/inventory-item-location-levels.tsx @@ -3,7 +3,6 @@ import { Button, Container, Heading } from "@medusajs/ui" import { InventoryItemRes } from "../../../../types/api-responses" import { ItemLocationListTable } from "./location-levels-table/location-list-table" import { Link } from "react-router-dom" -import { ReservationItemTable } from "./reservations-table/reservation-list-table" import { useTranslation } from "react-i18next" type InventoryItemLocationLevelsSectionProps = { diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/location-levels-table/location-list-table.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/location-levels-table/location-list-table.tsx index 234d4af19f..605be52607 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/location-levels-table/location-list-table.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/location-levels-table/location-list-table.tsx @@ -15,11 +15,16 @@ export const ItemLocationListTable = ({ pageSize: PAGE_SIZE, }) - const { inventory_levels, count, isLoading, isError, error } = - useInventoryItemLevels(inventory_item_id, { - ...searchParams, - fields: "*stock_locations", - }) + const { + inventory_levels, + count, + isPending: isLoading, + isError, + error, + } = useInventoryItemLevels(inventory_item_id, { + ...searchParams, + fields: "*stock_locations", + }) const columns = useLocationListTableColumns() diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/components/location-item.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/components/location-item.tsx index 60bd656232..4c079ae382 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/components/location-item.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/components/location-item.tsx @@ -15,7 +15,7 @@ export const LocationItem = ({ }: LocationItemProps) => { return (
onSelect(!selected)} diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/components/manage-locations-form.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/components/manage-locations-form.tsx index 6822a937c7..904751a412 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/components/manage-locations-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/components/manage-locations-form.tsx @@ -1,14 +1,11 @@ import * as zod from "zod" -import { Button, Table, Text } from "@medusajs/ui" +import { Button, Text, toast } from "@medusajs/ui" import { RouteDrawer, useRouteModal, } from "../../../../../../components/route-modal" -import { - useBatchInventoryItemLevels, - useUpdateInventoryItem, -} from "../../../../../../hooks/api/inventory" +import { useBatchInventoryItemLevels } from "../../../../../../hooks/api/inventory" import { useFieldArray, useForm } from "react-hook-form" import { InventoryItemRes } from "../../../../../../types/api-responses" @@ -35,13 +32,13 @@ const EditInventoryItemAttributesSchema = z.object({ const getDefaultValues = ( allLocations: StockLocationDTO[], - existinLevels: Set + existingLevels: Set ) => { return { locations: allLocations.map((location) => ({ ...location, location_id: location.id, - selected: existinLevels.has(location.id), + selected: existingLevels.has(location.id), })), } } @@ -97,14 +94,26 @@ export const ManageLocationsForm = ({ return handleSuccess() } - await mutateAsync({ - creates: selectedLocations.map((location_id) => ({ - location_id, - })), - deletes: unselectedLocations, - }) + try { + await mutateAsync({ + creates: selectedLocations.map((location_id) => ({ + location_id, + })), + deletes: unselectedLocations, + }) - return handleSuccess() + handleSuccess() + + toast.success(t("general.success"), { + description: t("inventory.toast.update"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } }) return ( @@ -114,7 +123,7 @@ export const ManageLocationsForm = ({ className="flex flex-1 flex-col overflow-hidden" > -
+
{t("fields.title")} @@ -136,7 +145,7 @@ export const ManageLocationsForm = ({ {t("locations.domain")} -
+
{t("locations.selectLocations")} diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/manage-locations-drawer.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/manage-locations-drawer.tsx index 1c372d334a..6145c737b1 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/manage-locations-drawer.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/manage-locations/manage-locations-drawer.tsx @@ -12,7 +12,7 @@ export const ManageLocationsDrawer = () => { const { inventory_item: inventoryItem, - isLoading, + isPending: isLoading, isError, error, } = useInventoryItem(id!) diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/reservations-table/reservation-list-table.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/reservations-table/reservation-list-table.tsx index 358e55e68b..f5d086148d 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/reservations-table/reservation-list-table.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/components/reservations-table/reservation-list-table.tsx @@ -16,11 +16,16 @@ export const ReservationItemTable = ({ pageSize: PAGE_SIZE, }) - const { reservations, count, isLoading, isError, error } = - useReservationItems({ - ...searchParams, - inventory_item_id: [inventoryItem.id], - }) + const { + reservations, + count, + isPending: isLoading, + isError, + error, + } = useReservationItems({ + ...searchParams, + inventory_item_id: [inventoryItem.id], + }) const columns = useInventoryTableColumns({ sku: inventoryItem.sku! }) diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/index.ts b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/index.ts index 7360293637..730d046ba4 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/index.ts +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/index.ts @@ -1,2 +1,2 @@ -export { InventoryDeatil as Component } from "./inventory-detail" +export { InventoryDetail as Component } from "./inventory-detail" export { inventoryItemLoader as loader } from "./loader" diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/inventory-detail.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/inventory-detail.tsx index 1e0e75c397..46fb6dea70 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/inventory-detail.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-detail/inventory-detail.tsx @@ -5,19 +5,26 @@ import { InventoryItemGeneralSection } from "./components/inventory-item-general import { InventoryItemLocationLevelsSection } from "./components/inventory-item-location-levels" import { InventoryItemReservationsSection } from "./components/inventory-item-reservations" import { JsonViewSection } from "../../../components/common/json-view-section" -import { inventoryItemLoader } from "./loader" import { useInventoryItem } from "../../../hooks/api/inventory" +import { inventoryItemLoader } from "./loader" -export const InventoryDeatil = () => { +export const InventoryDetail = () => { const { id } = useParams() const initialData = useLoaderData() as Awaited< ReturnType > - const { inventory_item, isLoading, isError, error } = useInventoryItem( + const { + inventory_item, + isPending: isLoading, + isError, + error, + } = useInventoryItem( id!, - {}, + { + fields: "*variants", + }, { initialData, } @@ -38,7 +45,7 @@ export const InventoryDeatil = () => { return (
-
+
@@ -47,7 +54,7 @@ export const InventoryDeatil = () => {
-
+
diff --git a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-list/components/inventory-list-table.tsx b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-list/components/inventory-list-table.tsx index dd00724ce8..e308f277da 100644 --- a/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-list/components/inventory-list-table.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/inventory/inventory-list/components/inventory-list-table.tsx @@ -1,7 +1,7 @@ import { Container, Heading } from "@medusajs/ui" +import { InventoryNext } from "@medusajs/types" import { DataTable } from "../../../../components/table/data-table" -import { InventoryNext } from "@medusajs/types" import { useDataTable } from "../../../../hooks/use-data-table" import { useInventoryItems } from "../../../../hooks/api/inventory" import { useInventoryTableColumns } from "./use-inventory-table-columns" @@ -17,10 +17,16 @@ export const InventoryListTable = () => { const { searchParams, raw } = useInventoryTableQuery({ pageSize: PAGE_SIZE, }) - const { inventory_items, count, isLoading, isError, error } = - useInventoryItems({ - ...searchParams, - }) + + const { + inventory_items, + count, + isPending: isLoading, + isError, + error, + } = useInventoryItems({ + ...searchParams, + }) const filters = useInventoryTableFilters() const columns = useInventoryTableColumns() diff --git a/packages/admin-next/dashboard/src/v2-routes/invite/invite.tsx b/packages/admin-next/dashboard/src/v2-routes/invite/invite.tsx index 9a8dc73b9c..87ceb5cd37 100644 --- a/packages/admin-next/dashboard/src/v2-routes/invite/invite.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/invite/invite.tsx @@ -1,6 +1,6 @@ import { zodResolver } from "@hookform/resolvers/zod" import { UserRoles } from "@medusajs/medusa" -import { Alert, Button, Heading, Input, Text } from "@medusajs/ui" +import { Alert, Button, Heading, Input, Text, toast } from "@medusajs/ui" import { AnimatePresence, motion } from "framer-motion" import { Trans, useTranslation } from "react-i18next" import { Link, useSearchParams } from "react-router-dom" @@ -49,7 +49,7 @@ export const Invite = () => { const isValidInvite = invite && validateDecodedInvite(invite) return ( -
+
{ @@ -228,6 +228,10 @@ const CreateView = ({ token: authToken, }) onSuccess() + toast.success(t("general.success"), { + description: t("invite.toast.accepted"), + dismissLabel: t("actions.close"), + }) } catch (error) { if (isAxiosError(error) && error.response?.status === 400) { form.setError("root", { diff --git a/packages/admin-next/dashboard/src/v2-routes/locations/location-create/components/create-location-form/create-location-form.tsx b/packages/admin-next/dashboard/src/v2-routes/locations/location-create/components/create-location-form/create-location-form.tsx index 45e64cecd6..739461ff5c 100644 --- a/packages/admin-next/dashboard/src/v2-routes/locations/location-create/components/create-location-form/create-location-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/locations/location-create/components/create-location-form/create-location-form.tsx @@ -1,5 +1,5 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { Button, Heading, Input, Text } from "@medusajs/ui" +import { Button, Heading, Input, Text, toast } from "@medusajs/ui" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import * as zod from "zod" @@ -49,17 +49,24 @@ export const CreateLocationForm = () => { const { mutateAsync, isPending } = useCreateStockLocation() const handleSubmit = form.handleSubmit(async (values) => { - mutateAsync( - { + try { + await mutateAsync({ name: values.name, address: values.address, - }, - { - onSuccess: () => { - handleSuccess("/settings/locations") - }, - } - ) + }) + + handleSuccess("/settings/locations") + + toast.success(t("general.success"), { + description: t("locations.toast.create"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } }) return ( diff --git a/packages/admin-next/dashboard/src/v2-routes/locations/location-detail/components/location-sales-channel-section/location-sales-channel-section.tsx b/packages/admin-next/dashboard/src/v2-routes/locations/location-detail/components/location-sales-channel-section/location-sales-channel-section.tsx index 19acd8cf9c..dc46cd1308 100644 --- a/packages/admin-next/dashboard/src/v2-routes/locations/location-detail/components/location-sales-channel-section/location-sales-channel-section.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/locations/location-detail/components/location-sales-channel-section/location-sales-channel-section.tsx @@ -1,6 +1,6 @@ import { PencilSquare, Trash } from "@medusajs/icons" import { SalesChannelDTO } from "@medusajs/types" -import { Button, Container, Heading, usePrompt } from "@medusajs/ui" +import { Button, Container, Heading, toast, usePrompt } from "@medusajs/ui" import { createColumnHelper } from "@tanstack/react-table" import { useAdminRemoveLocationFromSalesChannel } from "medusa-react" import { useMemo } from "react" @@ -82,10 +82,22 @@ const SalesChannelActions = ({ return } - await mutateAsync({ - location_id: locationId, - sales_channel_id: salesChannel.id, - }) + try { + await mutateAsync({ + location_id: locationId, + sales_channel_id: salesChannel.id, + }) + + toast.success(t("general.success"), { + description: t("locations.toast.removeChannel"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } } return ( diff --git a/packages/admin-next/dashboard/src/v2-routes/locations/location-detail/location-detail.tsx b/packages/admin-next/dashboard/src/v2-routes/locations/location-detail/location-detail.tsx index b3a0289575..7722b82265 100644 --- a/packages/admin-next/dashboard/src/v2-routes/locations/location-detail/location-detail.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/locations/location-detail/location-detail.tsx @@ -7,7 +7,12 @@ import { LocationSalesChannelSection } from "./components/location-sales-channel export const LocationDetail = () => { const { id } = useParams() - const { stock_location, isLoading, isError, error } = useStockLocation(id!, { + const { + stock_location, + isPending: isLoading, + isError, + error, + } = useStockLocation(id!, { fields: "*address,*sales_channels", }) diff --git a/packages/admin-next/dashboard/src/v2-routes/locations/location-edit/components/edit-location-form/edit-location-form.tsx b/packages/admin-next/dashboard/src/v2-routes/locations/location-edit/components/edit-location-form/edit-location-form.tsx index 76979bc915..a5dd5771d5 100644 --- a/packages/admin-next/dashboard/src/v2-routes/locations/location-edit/components/edit-location-form/edit-location-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/locations/location-edit/components/edit-location-form/edit-location-form.tsx @@ -1,5 +1,5 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { Button, Input } from "@medusajs/ui" +import { Button, Input, toast } from "@medusajs/ui" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import * as zod from "zod" @@ -55,17 +55,23 @@ export const EditLocationForm = ({ location }: EditLocationFormProps) => { const { mutateAsync, isPending } = useUpdateStockLocation(location.id) const handleSubmit = form.handleSubmit(async (values) => { - mutateAsync( - { + try { + await mutateAsync({ name: values.name, address: values.address, - }, - { - onSuccess: () => { - handleSuccess() - }, - } - ) + }) + handleSuccess() + + toast.success(t("general.success"), { + description: t("locations.toast.update"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } }) return ( diff --git a/packages/admin-next/dashboard/src/v2-routes/locations/location-edit/location-edit.tsx b/packages/admin-next/dashboard/src/v2-routes/locations/location-edit/location-edit.tsx index c3b4ce3b81..c19047552e 100644 --- a/packages/admin-next/dashboard/src/v2-routes/locations/location-edit/location-edit.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/locations/location-edit/location-edit.tsx @@ -2,14 +2,18 @@ import { Heading } from "@medusajs/ui" import { useTranslation } from "react-i18next" import { useParams } from "react-router-dom" import { RouteDrawer } from "../../../components/route-modal" -import { useStockLocations } from "../../../hooks/api/stock-locations" +import { useStockLocation } from "../../../hooks/api/stock-locations" import { EditLocationForm } from "./components/edit-location-form" export const LocationEdit = () => { const { id } = useParams() - const { stock_locations, isLoading, isError, error } = useStockLocations({ - id, + const { + stock_location, + isPending: isLoading, + isError, + error, + } = useStockLocation(id, { fields: "*address", }) @@ -19,8 +23,6 @@ export const LocationEdit = () => { throw error } - const stock_location = stock_locations?.[0] - return ( diff --git a/packages/admin-next/dashboard/src/v2-routes/locations/location-list/components/locations-list-table/locations-list-table.tsx b/packages/admin-next/dashboard/src/v2-routes/locations/location-list/components/locations-list-table/locations-list-table.tsx index 7634b4108e..58d89e6b62 100644 --- a/packages/admin-next/dashboard/src/v2-routes/locations/location-list/components/locations-list-table/locations-list-table.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/locations/location-list/components/locations-list-table/locations-list-table.tsx @@ -19,16 +19,21 @@ export const LocationsListTable = () => { * Note: The endpoint is bugged and does not return count, causing the table to not render * any rows. */ - const { stock_locations, count, isLoading, isError, error } = - useStockLocations({ - ...searchParams, - fields: "*address", - }) + const { + stock_locations = [], + count, + isLoading, + isError, + error, + } = useStockLocations({ + ...searchParams, + fields: "*address", + }) const columns = useLocationTableColumns() const { table } = useDataTable({ - data: stock_locations ?? [], + data: stock_locations, columns, count, enablePagination: true, @@ -56,7 +61,8 @@ export const LocationsListTable = () => { count={count || 1} columns={columns} navigateTo={(row) => row.id} - isLoading={isLoading} + // TODO: revisit loader - on query change this will cause unmounting of the table, rendering loader briefly and again rendering table which will make search input unfocused + // isLoading={isLoading} queryObject={raw} pagination search diff --git a/packages/admin-next/dashboard/src/v2-routes/locations/location-list/components/locations-list-table/use-location-table-query.tsx b/packages/admin-next/dashboard/src/v2-routes/locations/location-list/components/locations-list-table/use-location-table-query.tsx index 54e99aefb1..8ff0d519df 100644 --- a/packages/admin-next/dashboard/src/v2-routes/locations/location-list/components/locations-list-table/use-location-table-query.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/locations/location-list/components/locations-list-table/use-location-table-query.tsx @@ -7,11 +7,12 @@ export const useLocationTableQuery = ({ pageSize?: number prefix?: string }) => { - const raw = useQueryParams(["offset"], prefix) + const raw = useQueryParams(["q", "offset"], prefix) const searchParams = { limit: pageSize, offset: raw.offset, + q: raw.q, } return { diff --git a/packages/admin-next/dashboard/src/v2-routes/login/login.tsx b/packages/admin-next/dashboard/src/v2-routes/login/login.tsx index b473925723..acaee136a8 100644 --- a/packages/admin-next/dashboard/src/v2-routes/login/login.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/login/login.tsx @@ -1,5 +1,5 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { Button, Heading, Input, Text } from "@medusajs/ui" +import { Alert, Button, Heading, Input, Text } from "@medusajs/ui" import { useForm } from "react-hook-form" import { Trans, useTranslation } from "react-i18next" import { Link, useLocation, useNavigate } from "react-router-dom" @@ -34,40 +34,38 @@ export const Login = () => { const { mutateAsync, isPending } = useEmailPassLogin() const handleSubmit = form.handleSubmit(async ({ email, password }) => { - await mutateAsync( - { + try { + await mutateAsync({ email, password, - }, - { - onSuccess: () => { - navigate(from, { replace: true }) - }, - onError: (error) => { - if (isAxiosError(error)) { - if (error.response?.status === 401) { - form.setError("email", { - type: "manual", - }) + }) - form.setError("password", { - type: "manual", - message: t("errors.invalidCredentials"), - }) - - return - } - } - - form.setError("root.serverError", { + navigate(from, { replace: true }) + } catch (error) { + if (isAxiosError(error)) { + if (error.response?.status === 401) { + form.setError("email", { type: "manual", - message: t("errors.serverError"), }) - }, + + form.setError("password", { + type: "manual", + message: t("errors.invalidCredentials"), + }) + + return + } } - ) + + form.setError("root.serverError", { + type: "manual", + message: t("errors.serverError"), + }) + } }) + const serverError = form.formState.errors?.root?.serverError?.message + return (
@@ -123,6 +121,11 @@ export const Login = () => { {t("actions.continue")} + {serverError && ( + + {serverError} + + )}
diff --git a/packages/admin-next/dashboard/src/v2-routes/profile/profile-detail/profile-detail.tsx b/packages/admin-next/dashboard/src/v2-routes/profile/profile-detail/profile-detail.tsx index b1547cf4e1..d9eab157e8 100644 --- a/packages/admin-next/dashboard/src/v2-routes/profile/profile-detail/profile-detail.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/profile/profile-detail/profile-detail.tsx @@ -3,7 +3,7 @@ import { useMe } from "../../../hooks/api/users" import { ProfileGeneralSection } from "./components/profile-general-section" export const ProfileDetail = () => { - const { user, isLoading, isError, error } = useMe() + const { user, isPending: isLoading, isError, error } = useMe() if (isLoading) { return
Loading...
@@ -14,7 +14,7 @@ export const ProfileDetail = () => { throw error } - throw json("An unknown error has occured", 500) + throw json("An unknown error has occurred", 500) } return ( diff --git a/packages/admin-next/dashboard/src/v2-routes/profile/profile-edit/components/edit-profile-form/edit-profile-form.tsx b/packages/admin-next/dashboard/src/v2-routes/profile/profile-edit/components/edit-profile-form/edit-profile-form.tsx index e428b9358d..188e55df45 100644 --- a/packages/admin-next/dashboard/src/v2-routes/profile/profile-edit/components/edit-profile-form/edit-profile-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/profile/profile-edit/components/edit-profile-form/edit-profile-form.tsx @@ -1,5 +1,5 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { Button, Input, Select, Switch } from "@medusajs/ui" +import { Button, Input, Select, Switch, toast } from "@medusajs/ui" import { useForm } from "react-hook-form" import { Trans, useTranslation } from "react-i18next" import * as zod from "zod" @@ -39,8 +39,8 @@ export const EditProfileForm = ({ user, usageInsights }: EditProfileProps) => { resolver: zodResolver(EditProfileSchema), }) - const changeLanguage = (code: string) => { - i18n.changeLanguage(code) + const changeLanguage = async (code: string) => { + await i18n.changeLanguage(code) } const sortedLanguages = languages.sort((a, b) => @@ -50,21 +50,26 @@ export const EditProfileForm = ({ user, usageInsights }: EditProfileProps) => { const { mutateAsync, isPending } = useUpdateUser(user.id!) const handleSubmit = form.handleSubmit(async (values) => { - await mutateAsync( - { + try { + await mutateAsync({ first_name: values.first_name, last_name: values.last_name, - }, - { - onError: () => { - return - }, - } - ) + }) - changeLanguage(values.language) + await changeLanguage(values.language) - handleSuccess() + handleSuccess() + + toast.success(t("general.success"), { + description: t("profile.toast.edit"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } }) return ( diff --git a/packages/admin-next/dashboard/src/v2-routes/profile/profile-edit/profile-edit.tsx b/packages/admin-next/dashboard/src/v2-routes/profile/profile-edit/profile-edit.tsx index 6a1fdc95dd..1658f0a4ef 100644 --- a/packages/admin-next/dashboard/src/v2-routes/profile/profile-edit/profile-edit.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/profile/profile-edit/profile-edit.tsx @@ -5,7 +5,7 @@ import { useMe } from "../../../hooks/api/users" import { EditProfileForm } from "./components/edit-profile-form/edit-profile-form" export const ProfileEdit = () => { - const { user, isLoading, isError, error } = useMe() + const { user, isPending: isLoading, isError, error } = useMe() const { t } = useTranslation() diff --git a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-add-products/components/add-products-to-sales-channel-form.tsx b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-add-products/components/add-products-to-sales-channel-form.tsx index 1e922c029b..202da96c67 100644 --- a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-add-products/components/add-products-to-sales-channel-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-add-products/components/add-products-to-sales-channel-form.tsx @@ -1,6 +1,6 @@ import { zodResolver } from "@hookform/resolvers/zod" import { SalesChannelDTO } from "@medusajs/types" -import { Button, Checkbox, Hint, Tooltip } from "@medusajs/ui" +import { Button, Checkbox, Hint, toast, Tooltip } from "@medusajs/ui" import { keepPreviousData } from "@tanstack/react-query" import { OnChangeFn, @@ -67,7 +67,13 @@ export const AddProductsToSalesChannelForm = ({ } const { searchParams, raw } = useProductTableQuery({ pageSize: PAGE_SIZE }) - const { products, count, isLoading, isError, error } = useProducts( + const { + products, + count, + isPending: isLoading, + isError, + error, + } = useProducts( { expand: "variants,sales_channels", ...searchParams, @@ -108,8 +114,17 @@ export const AddProductsToSalesChannelForm = ({ }, { onSuccess: () => { + toast.success(t("general.success"), { + description: t("salesChannels.toast.update"), + dismissLabel: t("actions.close"), + }) handleSuccess() }, + onError: (error) => + toast.error(t("general.error"), { + description: error.message, + dismissLabel: t("actions.close"), + }), } ) }) diff --git a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-add-products/sales-channel-add-products.tsx b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-add-products/sales-channel-add-products.tsx index 1c68da5d53..1e88d02780 100644 --- a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-add-products/sales-channel-add-products.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-add-products/sales-channel-add-products.tsx @@ -5,7 +5,12 @@ import { AddProductsToSalesChannelForm } from "./components" export const SalesChannelAddProducts = () => { const { id } = useParams() - const { sales_channel, isLoading, isError, error } = useSalesChannel(id!) + const { + sales_channel, + isPending: isLoading, + isError, + error, + } = useSalesChannel(id!) if (isError) { throw error diff --git a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-create/components/create-sales-channel-form/create-sales-channel-form.tsx b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-create/components/create-sales-channel-form/create-sales-channel-form.tsx index 69d724c8c5..e93fb1d305 100644 --- a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-create/components/create-sales-channel-form/create-sales-channel-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-create/components/create-sales-channel-form/create-sales-channel-form.tsx @@ -1,5 +1,13 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { Button, Heading, Input, Switch, Text, Textarea } from "@medusajs/ui" +import { + Button, + Heading, + Input, + Switch, + Text, + Textarea, + toast, +} from "@medusajs/ui" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import * as zod from "zod" @@ -40,8 +48,17 @@ export const CreateSalesChannelForm = () => { }, { onSuccess: ({ sales_channel }) => { + toast.success(t("general.success"), { + description: t("salesChannels.toast.create"), + dismissLabel: t("actions.close"), + }) handleSuccess(`../${sales_channel.id}`) }, + onError: (error) => + toast.success(t("general.success"), { + description: error.message, + dismissLabel: t("actions.close"), + }), } ) }) diff --git a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/components/sales-channel-general-section/sales-channel-general-section.tsx b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/components/sales-channel-general-section/sales-channel-general-section.tsx index 6d9893b6b2..c0bfb19293 100644 --- a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/components/sales-channel-general-section/sales-channel-general-section.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/components/sales-channel-general-section/sales-channel-general-section.tsx @@ -1,5 +1,12 @@ import { PencilSquare, Trash } from "@medusajs/icons" -import { Container, Heading, StatusBadge, Text, usePrompt } from "@medusajs/ui" +import { + Container, + Heading, + StatusBadge, + Text, + toast, + usePrompt, +} from "@medusajs/ui" import { useTranslation } from "react-i18next" import { SalesChannelDTO } from "@medusajs/types" @@ -36,11 +43,21 @@ export const SalesChannelGeneralSection = ({ return } - await mutateAsync(undefined, { - onSuccess: () => { - navigate("/settings/sales-channels", { replace: true }) - }, - }) + try { + await mutateAsync() + + navigate("/settings/sales-channels", { replace: true }) + + toast.success(t("general.success"), { + description: t("salesChannels.toast.delete"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } } return ( diff --git a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/components/sales-channel-product-section/sales-channel-product-section.tsx b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/components/sales-channel-product-section/sales-channel-product-section.tsx index a066320532..b042123b07 100644 --- a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/components/sales-channel-product-section/sales-channel-product-section.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/components/sales-channel-product-section/sales-channel-product-section.tsx @@ -1,5 +1,12 @@ import { PencilSquare, Trash } from "@medusajs/icons" -import { Button, Checkbox, Container, Heading, usePrompt } from "@medusajs/ui" +import { + Button, + Checkbox, + Container, + Heading, + toast, + usePrompt, +} from "@medusajs/ui" import { RowSelectionState, createColumnHelper } from "@tanstack/react-table" import { useMemo, useState } from "react" import { useTranslation } from "react-i18next" @@ -29,7 +36,13 @@ export const SalesChannelProductSection = ({ const [rowSelection, setRowSelection] = useState({}) const { searchParams, raw } = useProductTableQuery({ pageSize: PAGE_SIZE }) - const { products, count, isLoading, isError, error } = useProducts( + const { + products, + count, + isPending: isLoading, + isError, + error, + } = useProducts( { ...searchParams, sales_channel_id: [salesChannel.id], @@ -87,8 +100,18 @@ export const SalesChannelProductSection = ({ }, { onSuccess: () => { + toast.success(t("general.success"), { + description: t("salesChannels.toast.update"), + dismissLabel: t("actions.close"), + }) setRowSelection({}) }, + onError: (error) => { + toast.error(t("general.error"), { + description: error.message, + dismissLabel: t("actions.close"), + }) + }, } ) } @@ -199,9 +222,20 @@ const ProductListCellActions = ({ const { mutateAsync } = useSalesChannelRemoveProducts(salesChannelId) const onRemove = async () => { - await mutateAsync({ - product_ids: [productId], - }) + try { + await mutateAsync({ + product_ids: [productId], + }) + toast.success(t("general.success"), { + description: t("salesChannels.toast.update"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } } return ( diff --git a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/sales-channel-detail.tsx b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/sales-channel-detail.tsx index 30448f72f7..c10ad910ab 100644 --- a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/sales-channel-detail.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-detail/sales-channel-detail.tsx @@ -12,7 +12,7 @@ export const SalesChannelDetail = () => { > const { id } = useParams() - const { sales_channel, isLoading } = useSalesChannel(id!, { + const { sales_channel, isPending: isLoading } = useSalesChannel(id!, { initialData, }) diff --git a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-edit/components/edit-sales-channel-form/edit-sales-channel-form.tsx b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-edit/components/edit-sales-channel-form/edit-sales-channel-form.tsx index edbfe32133..ee450f3eac 100644 --- a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-edit/components/edit-sales-channel-form/edit-sales-channel-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-edit/components/edit-sales-channel-form/edit-sales-channel-form.tsx @@ -1,5 +1,5 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { Button, Input, Switch, Textarea } from "@medusajs/ui" +import { Button, Input, Switch, Textarea, toast } from "@medusajs/ui" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import * as zod from "zod" @@ -48,8 +48,18 @@ export const EditSalesChannelForm = ({ }, { onSuccess: () => { + toast.success(t("general.success"), { + description: t("salesChannels.toast.update"), + dismissLabel: t("actions.close"), + }) handleSuccess() }, + onError: (error) => { + toast.error(t("general.error"), { + description: error.message, + dismissLabel: t("actions.close"), + }) + }, } ) }) diff --git a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-edit/sales-channel-edit.tsx b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-edit/sales-channel-edit.tsx index be3129ccee..36641ea6da 100644 --- a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-edit/sales-channel-edit.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-edit/sales-channel-edit.tsx @@ -10,7 +10,12 @@ export const SalesChannelEdit = () => { const { id } = useParams() const { t } = useTranslation() - const { sales_channel, isLoading, isError, error } = useSalesChannel(id!) + const { + sales_channel, + isPending: isLoading, + isError, + error, + } = useSalesChannel(id!) if (isError) { throw error diff --git a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-list/components/sales-channel-list-table.tsx b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-list/components/sales-channel-list-table.tsx index 59946ff27b..9e33e52ad2 100644 --- a/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-list/components/sales-channel-list-table.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/sales-channels/sales-channel-list/components/sales-channel-list-table.tsx @@ -1,6 +1,6 @@ import { PencilSquare, Trash } from "@medusajs/icons" import { SalesChannelDTO } from "@medusajs/types" -import { Button, Container, Heading, usePrompt } from "@medusajs/ui" +import { Button, Container, Heading, toast, usePrompt } from "@medusajs/ui" import { keepPreviousData } from "@tanstack/react-query" import { createColumnHelper } from "@tanstack/react-table" import { useMemo } from "react" @@ -24,12 +24,15 @@ export const SalesChannelListTable = () => { const { raw, searchParams } = useSalesChannelTableQuery({ pageSize: PAGE_SIZE, }) - const { sales_channels, count, isLoading, isError, error } = useSalesChannels( - searchParams, - { - placeholderData: keepPreviousData, - } - ) + const { + sales_channels, + count, + isPending: isLoading, + isError, + error, + } = useSalesChannels(searchParams, { + placeholderData: keepPreviousData, + }) const columns = useColumns() @@ -97,7 +100,18 @@ const SalesChannelActions = ({ return } - await mutateAsync() + try { + await mutateAsync() + toast.success(t("general.success"), { + description: t("salesChannels.toast.delete"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } } return ( diff --git a/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/components/add-currencies-form/add-currencies-form.tsx b/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/components/add-currencies-form/add-currencies-form.tsx index 0655537f7b..e26e484bcd 100644 --- a/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/components/add-currencies-form/add-currencies-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/components/add-currencies-form/add-currencies-form.tsx @@ -1,5 +1,5 @@ import { Currency } from "@medusajs/medusa" -import { Button, Checkbox, Hint, Tooltip } from "@medusajs/ui" +import { Button, Checkbox, Hint, toast, Tooltip } from "@medusajs/ui" import { OnChangeFn, RowSelectionState, @@ -68,12 +68,15 @@ export const AddCurrenciesForm = ({ store }: AddCurrenciesFormProps) => { prefix: PREFIX, }) - const { currencies, count, isLoading, isError, error } = useCurrencies( - searchParams, - { - placeholderData: keepPreviousData, - } - ) + const { + currencies, + count, + isPending: isLoading, + isError, + error, + } = useCurrencies(searchParams, { + placeholderData: keepPreviousData, + }) const preSelectedRows = store.supported_currency_codes.map((c) => c) @@ -101,16 +104,21 @@ export const AddCurrenciesForm = ({ store }: AddCurrenciesFormProps) => { new Set([...data.currencies, ...preSelectedRows]) ) as string[] - await mutateAsync( - { + try { + await mutateAsync({ supported_currency_codes: currencies, - }, - { - onSuccess: () => { - handleSuccess() - }, - } - ) + }) + toast.success(t("general.success"), { + description: t("store.toast.currenciesUpdated"), + dismissLabel: t("actions.close"), + }) + handleSuccess() + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } }) if (isError) { diff --git a/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/store-add-currencies.tsx b/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/store-add-currencies.tsx index 52f3837d04..63677fa164 100644 --- a/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/store-add-currencies.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/store/store-add-currencies/store-add-currencies.tsx @@ -3,7 +3,7 @@ import { useStore } from "../../../hooks/api/store" import { AddCurrenciesForm } from "./components/add-currencies-form/add-currencies-form" export const StoreAddCurrencies = () => { - const { store, isLoading, isError, error } = useStore() + const { store, isPending: isLoading, isError, error } = useStore() if (isError) { throw error diff --git a/packages/admin-next/dashboard/src/v2-routes/store/store-detail/components/store-currency-section/store-currencies-section.tsx/store-currency-section.tsx b/packages/admin-next/dashboard/src/v2-routes/store/store-detail/components/store-currency-section/store-currencies-section.tsx/store-currency-section.tsx index 8cb7a64d99..e05e1a0043 100644 --- a/packages/admin-next/dashboard/src/v2-routes/store/store-detail/components/store-currency-section/store-currencies-section.tsx/store-currency-section.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/store/store-detail/components/store-currency-section/store-currencies-section.tsx/store-currency-section.tsx @@ -5,6 +5,7 @@ import { CommandBar, Container, Heading, + toast, usePrompt, } from "@medusajs/ui" import { keepPreviousData } from "@tanstack/react-query" @@ -31,7 +32,13 @@ export const StoreCurrencySection = ({ store }: StoreCurrencySectionProps) => { const { searchParams, raw } = useCurrenciesTableQuery({ pageSize: PAGE_SIZE }) - const { currencies, count, isLoading, isError, error } = useCurrencies( + const { + currencies, + count, + isPending: isLoading, + isError, + error, + } = useCurrencies( { code: store.supported_currency_codes, ...searchParams, @@ -56,8 +63,9 @@ export const StoreCurrencySection = ({ store }: StoreCurrencySectionProps) => { enableRowSelection: true, pageSize: PAGE_SIZE, meta: { - currencyCodes: store.supported_currency_codes, storeId: store.id, + currencyCodes: store.supported_currency_codes, + defaultCurrencyCode: store.default_currency_code, }, }) @@ -81,18 +89,24 @@ export const StoreCurrencySection = ({ store }: StoreCurrencySectionProps) => { return } - await mutateAsync( - { + try { + await mutateAsync({ supported_currency_codes: store.supported_currency_codes.filter( (c) => !ids.includes(c) ), - }, - { - onSuccess: () => { - setRowSelection({}) - }, - } - ) + }) + setRowSelection({}) + + toast.success(t("general.success"), { + description: t("store.toast.currenciesRemoved"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } } if (isError) { @@ -151,10 +165,12 @@ const CurrencyActions = ({ storeId, currency, currencyCodes, + defaultCurrencyCode, }: { storeId: string currency: CurrencyDTO currencyCodes: string[] + defaultCurrencyCode: string }) => { const { mutateAsync } = useUpdateStore(storeId) @@ -177,11 +193,23 @@ const CurrencyActions = ({ return } - await mutateAsync({ - supported_currency_codes: currencyCodes.filter( - (c) => c !== currency.code - ), - }) + try { + await mutateAsync({ + supported_currency_codes: currencyCodes.filter( + (c) => c !== currency.code + ), + }) + + toast.success(t("general.success"), { + description: t("store.toast.currenciesRemoved"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } } return ( @@ -193,6 +221,7 @@ const CurrencyActions = ({ icon: , label: t("actions.remove"), onClick: handleRemove, + disabled: currency.code === defaultCurrencyCode, }, ], }, @@ -240,9 +269,11 @@ const useColumns = () => { columnHelper.display({ id: "actions", cell: ({ row, table }) => { - const { currencyCodes, storeId } = table.options.meta as { + const { currencyCodes, storeId, defaultCurrencyCode } = table.options + .meta as { currencyCodes: string[] storeId: string + defaultCurrencyCode: string } return ( @@ -250,6 +281,7 @@ const useColumns = () => { storeId={storeId} currency={row.original} currencyCodes={currencyCodes} + defaultCurrencyCode={defaultCurrencyCode} /> ) }, diff --git a/packages/admin-next/dashboard/src/v2-routes/store/store-detail/components/store-general-section/store-general-section.tsx b/packages/admin-next/dashboard/src/v2-routes/store/store-detail/components/store-general-section/store-general-section.tsx index dcf8821efa..449b0bca2c 100644 --- a/packages/admin-next/dashboard/src/v2-routes/store/store-detail/components/store-general-section/store-general-section.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/store/store-detail/components/store-general-section/store-general-section.tsx @@ -3,6 +3,7 @@ import { Badge, Container, Heading, Text } from "@medusajs/ui" import { useTranslation } from "react-i18next" import { ActionMenu } from "../../../../../components/common/action-menu" import { ExtendedStoreDTO } from "../../../../../types/api-responses" +import { useRegion } from "../../../../../hooks/api/regions" type StoreGeneralSectionProps = { store: ExtendedStoreDTO @@ -11,6 +12,10 @@ type StoreGeneralSectionProps = { export const StoreGeneralSection = ({ store }: StoreGeneralSectionProps) => { const { t } = useTranslation() + const { region } = useRegion(store.default_region_id, undefined, { + enabled: !!store.default_region_id, + }) + return (
@@ -57,6 +62,19 @@ export const StoreGeneralSection = ({ store }: StoreGeneralSectionProps) => {
)} + + {region && ( +
+ + {t("store.defaultRegion")} + +
+ + {region.name} + +
+
+ )} ) } diff --git a/packages/admin-next/dashboard/src/v2-routes/store/store-detail/store-detail.tsx b/packages/admin-next/dashboard/src/v2-routes/store/store-detail/store-detail.tsx index c028740ebc..7dffc6c3bb 100644 --- a/packages/admin-next/dashboard/src/v2-routes/store/store-detail/store-detail.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/store/store-detail/store-detail.tsx @@ -9,7 +9,12 @@ import { storeLoader } from "./loader" export const StoreDetail = () => { const initialData = useLoaderData() as Awaited> - const { store, isLoading, isError, error } = useStore({ + const { + store, + isPending: isLoading, + isError, + error, + } = useStore({ initialData, }) diff --git a/packages/admin-next/dashboard/src/v2-routes/store/store-edit/components/edit-store-form/edit-store-form.tsx b/packages/admin-next/dashboard/src/v2-routes/store/store-edit/components/edit-store-form/edit-store-form.tsx index 4dc5c1e736..df9999953e 100644 --- a/packages/admin-next/dashboard/src/v2-routes/store/store-edit/components/edit-store-form/edit-store-form.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/store/store-edit/components/edit-store-form/edit-store-form.tsx @@ -1,5 +1,5 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { Button, Input } from "@medusajs/ui" +import { Button, Input, Select, toast } from "@medusajs/ui" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import { z } from "zod" @@ -11,6 +11,7 @@ import { } from "../../../../../components/route-modal" import { useUpdateStore } from "../../../../../hooks/api/store" import { ExtendedStoreDTO } from "../../../../../types/api-responses" +import { useRegions } from "../../../../../hooks/api/regions" type EditStoreFormProps = { store: ExtendedStoreDTO @@ -18,8 +19,8 @@ type EditStoreFormProps = { const EditStoreSchema = z.object({ name: z.string().min(1), - // default_currency_code: z.string().optional(), - // default_region_id: z.string().optional(), + default_currency_code: z.string().optional(), + default_region_id: z.string().optional(), // default_location_id: z.string().optional(), }) @@ -30,18 +31,32 @@ export const EditStoreForm = ({ store }: EditStoreFormProps) => { const form = useForm>({ defaultValues: { name: store.name, + default_region_id: store.default_region_id || undefined, + default_currency_code: store.default_currency_code || undefined, }, resolver: zodResolver(EditStoreSchema), }) const { mutateAsync, isPending } = useUpdateStore(store.id) + const { regions, isPending: isRegionsLoading } = useRegions({ limit: 999 }) + const handleSubmit = form.handleSubmit(async (values) => { - mutateAsync(values, { - onSuccess: () => { - handleSuccess() - }, - }) + try { + await mutateAsync(values) + + handleSuccess() + + toast.success(t("general.success"), { + description: t("store.toast.update"), + dismissLabel: t("actions.close"), + }) + } catch (e) { + toast.error(t("general.error"), { + description: e.message, + dismissLabel: t("actions.close"), + }) + } }) return ( @@ -62,7 +77,61 @@ export const EditStoreForm = ({ store }: EditStoreFormProps) => { )} /> - {/* TODO: Add comboboxes for default region, location, and currency. `q` is currently missing on all v2 endpoints */} + {/* TODO: Add comboboxes for default sales channel and location */} + { + return ( + + {t("store.defaultCurrency")} + + + + + ) + }} + /> + { + return ( + + {t("store.defaultRegion")} + + + + + ) + }} + />
diff --git a/packages/admin-next/dashboard/src/v2-routes/store/store-edit/store-edit.tsx b/packages/admin-next/dashboard/src/v2-routes/store/store-edit/store-edit.tsx index 044cf004fe..380d27f7ec 100644 --- a/packages/admin-next/dashboard/src/v2-routes/store/store-edit/store-edit.tsx +++ b/packages/admin-next/dashboard/src/v2-routes/store/store-edit/store-edit.tsx @@ -6,7 +6,7 @@ import { EditStoreForm } from "./components/edit-store-form/edit-store-form" export const StoreEdit = () => { const { t } = useTranslation() - const { store, isLoading, isError, error } = useStore() + const { store, isPending: isLoading, isError, error } = useStore() if (isError) { throw error diff --git a/packages/core-flows/src/stock-location/steps/delete-stock-locations.ts b/packages/core-flows/src/stock-location/steps/delete-stock-locations.ts index 06b3b85a22..23f21a1d86 100644 --- a/packages/core-flows/src/stock-location/steps/delete-stock-locations.ts +++ b/packages/core-flows/src/stock-location/steps/delete-stock-locations.ts @@ -12,12 +12,12 @@ export const deleteStockLocationsStep = createStep( return new StepResponse(void 0, input) }, - async (deletedLocaitonIds, { container }) => { - if (!deletedLocaitonIds?.length) { + async (deletedLocationIds, { container }) => { + if (!deletedLocationIds?.length) { return } const service = container.resolve(ModuleRegistrationName.STOCK_LOCATION) - await service.restore(deletedLocaitonIds) + await service.restore(deletedLocationIds) } ) diff --git a/packages/currency/src/models/currency.ts b/packages/currency/src/models/currency.ts index bb503992af..0ba5d969f2 100644 --- a/packages/currency/src/models/currency.ts +++ b/packages/currency/src/models/currency.ts @@ -1,9 +1,14 @@ import { BigNumberRawValue } from "@medusajs/types" -import { BigNumber, MikroOrmBigNumberProperty } from "@medusajs/utils" +import { + BigNumber, + MikroOrmBigNumberProperty, + Searchable, +} from "@medusajs/utils" import { Entity, PrimaryKey, Property } from "@mikro-orm/core" @Entity({ tableName: "currency" }) class Currency { + @Searchable() @PrimaryKey({ columnType: "text" }) code!: string @@ -13,6 +18,7 @@ class Currency { @Property({ columnType: "text" }) symbol_native: string + @Searchable() @Property({ columnType: "text" }) name: string diff --git a/packages/medusa/src/api-v2/admin/currencies/validators.ts b/packages/medusa/src/api-v2/admin/currencies/validators.ts index 28ac593507..1d989f51ec 100644 --- a/packages/medusa/src/api-v2/admin/currencies/validators.ts +++ b/packages/medusa/src/api-v2/admin/currencies/validators.ts @@ -11,6 +11,7 @@ export const AdminGetCurrenciesParams = createFindParams({ limit: 50, }).merge( z.object({ + q: z.string().optional(), code: z.union([z.string(), z.array(z.string())]).optional(), $and: z.lazy(() => AdminGetCurrenciesParams.array()).optional(), $or: z.lazy(() => AdminGetCurrenciesParams.array()).optional(),