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 b5961098ae..e5b8b9b75d 100644 --- a/packages/admin-next/dashboard/public/locales/en-US/translation.json +++ b/packages/admin-next/dashboard/public/locales/en-US/translation.json @@ -618,7 +618,10 @@ "addCurrencies": "Add currencies", "removeCurrencyWarning_one": "You are about to remove {{count}} currency from your store. Ensure that you have removed all prices using the currency before proceeding.", "removeCurrencyWarning_other": "You are about to remove {{count}} currencies from your store. Ensure that you have removed all prices using the currencies before proceeding.", - "currencyAlreadyAdded": "The currency has already been added to your store." + "currencyAlreadyAdded": "The currency has already been added to your store.", + "edit": { + "header": "Edit Store" + } }, "regions": { "domain": "Regions", @@ -1002,4 +1005,4 @@ "seconds_one": "Second", "seconds_other": "Seconds" } -} \ No newline at end of file +} diff --git a/packages/admin-next/dashboard/src/hooks/use-combobox-data.tsx b/packages/admin-next/dashboard/src/hooks/use-combobox-data.tsx new file mode 100644 index 0000000000..afb9ce12fb --- /dev/null +++ b/packages/admin-next/dashboard/src/hooks/use-combobox-data.tsx @@ -0,0 +1,71 @@ +import { QueryKey, useInfiniteQuery } from "@tanstack/react-query" +import debounce from "lodash/debounce" +import { useCallback, useEffect, useState } from "react" + +type Params = { + q: string + limit: number + offset: number +} + +type Page = { + count: number + offset: number + limit: number +} + +type UseComboboxDataProps = { + fetcher: (params: TParams) => Promise + params?: Omit + queryKey: QueryKey +} + +/** + * Hook for fetching infinite data for a combobox. + */ +export const useComboboxData = ({ + fetcher, + params, + queryKey, +}: UseComboboxDataProps) => { + const [query, setQuery] = useState("") + const [debouncedQuery, setDebouncedQuery] = useState("") + + // eslint-disable-next-line react-hooks/exhaustive-deps + const debouncedUpdate = useCallback( + debounce((query) => setDebouncedQuery(query), 300), + [] + ) + + useEffect(() => { + debouncedUpdate(query) + + return () => debouncedUpdate.cancel() + }, [query, debouncedUpdate]) + + const data = useInfiniteQuery( + [...queryKey, debouncedQuery], + async ({ pageParam = 0 }) => { + const res = await fetcher({ + q: debouncedQuery, + limit: 10, + offset: pageParam, + ...params, + } as TParams) + return res + }, + { + getNextPageParam: (lastPage) => { + const morePages = lastPage.count > lastPage.offset + lastPage.limit + return morePages ? lastPage.offset + lastPage.limit : undefined + }, + keepPreviousData: true, + } + ) + + return { + ...data, + query, + setQuery, + } +} diff --git a/packages/admin-next/dashboard/src/lib/api-v2/currencies.ts b/packages/admin-next/dashboard/src/lib/api-v2/currencies.ts new file mode 100644 index 0000000000..1abfc5c2c3 --- /dev/null +++ b/packages/admin-next/dashboard/src/lib/api-v2/currencies.ts @@ -0,0 +1,37 @@ +import { CurrencyDTO } from "@medusajs/types" +import { adminCurrenciesKeys, useAdminCustomQuery } from "medusa-react" +import { V2ListRes } from "./types/common" + +// TODO: Add types once we export V2 API types +export const useV2Currencies = (query?: any, options?: any) => { + const { data, ...rest } = useAdminCustomQuery( + `/admin/currencies`, + adminCurrenciesKeys.list(query), + query, + options + ) + + const typedData: { + currencies: CurrencyDTO[] | undefined + } & V2ListRes = { + currencies: data?.currencies, + count: data?.count, + offset: data?.offset, + limit: data?.limit, + } + + return { ...typedData, ...rest } +} + +export const useV2Currency = (id: string, options?: any) => { + const { data, ...rest } = useAdminCustomQuery( + `/admin/currencies/${id}`, + adminCurrenciesKeys.detail(id), + undefined, + options + ) + + const currency: CurrencyDTO | undefined = data?.currency + + return { currency, ...rest } +} diff --git a/packages/admin-next/dashboard/src/lib/api-v2/region.ts b/packages/admin-next/dashboard/src/lib/api-v2/region.ts new file mode 100644 index 0000000000..333c523334 --- /dev/null +++ b/packages/admin-next/dashboard/src/lib/api-v2/region.ts @@ -0,0 +1,23 @@ +import { RegionDTO } from "@medusajs/types" +import { adminRegionKeys, useAdminCustomQuery } from "medusa-react" +import { V2ListRes } from "./types/common" + +export const useV2Regions = (query?: any, options?: any) => { + const { data, ...rest } = useAdminCustomQuery( + "/regions", + adminRegionKeys.list(query), + query, + options + ) + + const typedData: { + regions: RegionDTO[] | undefined + } & V2ListRes = { + regions: data?.regions, + count: data?.count, + offset: data?.offset, + limit: data?.limit, + } + + return { ...typedData, ...rest } +} diff --git a/packages/admin-next/dashboard/src/lib/api-v2/store.ts b/packages/admin-next/dashboard/src/lib/api-v2/store.ts index 536d7fc5ce..b318a5c170 100644 --- a/packages/admin-next/dashboard/src/lib/api-v2/store.ts +++ b/packages/admin-next/dashboard/src/lib/api-v2/store.ts @@ -1,18 +1,32 @@ -import { adminStoreKeys, useAdminCustomQuery } from "medusa-react" +import { + adminStoreKeys, + useAdminCustomPost, + useAdminCustomQuery, +} from "medusa-react" +import { Store } from "./types/store" -export const useV2Store = ({ initialData }: { initialData?: any }) => { - const { data, isLoading, isError, error } = useAdminCustomQuery( +// TODO: Add types once we export V2 API types +export const useV2Store = (options?: any) => { + const { data, isLoading, isError, error, ...rest } = useAdminCustomQuery( "/admin/stores", adminStoreKeys.details(), - {}, - { initialData } + undefined, + options ) - const store = data?.stores[0] + const store = data?.stores[0] as Store | undefined + + let hasError = isError + let err: Error | null = error if (!isLoading && !isError && typeof store === "undefined") { - throw new Error("Store does not exist") + hasError = true + err = new Error("Store not found") } - return { store, isLoading, isError, error } + return { store, isLoading, isError: hasError, error: err, ...rest } +} + +export const useV2UpdateStore = (id: string) => { + return useAdminCustomPost(`/admin/stores/${id}`, adminStoreKeys.detail(id)) } diff --git a/packages/admin-next/dashboard/src/lib/api-v2/types/common.ts b/packages/admin-next/dashboard/src/lib/api-v2/types/common.ts new file mode 100644 index 0000000000..3a90c4ec98 --- /dev/null +++ b/packages/admin-next/dashboard/src/lib/api-v2/types/common.ts @@ -0,0 +1,5 @@ +export type V2ListRes = { + count: number | undefined + offset: number | undefined + limit: number | undefined +} diff --git a/packages/admin-next/dashboard/src/lib/api-v2/types/store.ts b/packages/admin-next/dashboard/src/lib/api-v2/types/store.ts new file mode 100644 index 0000000000..df47f8788a --- /dev/null +++ b/packages/admin-next/dashboard/src/lib/api-v2/types/store.ts @@ -0,0 +1,5 @@ +import { CurrencyDTO, StoreDTO } from "@medusajs/types" + +export type Store = StoreDTO & { + default_currency: CurrencyDTO | null +} diff --git a/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx b/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx index 93c5685e97..52fd2b40de 100644 --- a/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx +++ b/packages/admin-next/dashboard/src/providers/router-provider/v2.tsx @@ -5,10 +5,9 @@ import { SettingsLayout } from "../../components/layout/settings-layout" import { Outlet } from "react-router-dom" import { Spinner } from "@medusajs/icons" +import { SalesChannelDTO, UserDTO } from "@medusajs/types" import { ErrorBoundary } from "../../components/error/error-boundary" import { useV2Session } from "../../lib/api-v2" -import { SalesChannelDTO } from "@medusajs/types" -import { UserDTO } from "@medusajs/types" import { SearchProvider } from "../search-provider" import { SidebarProvider } from "../sidebar-provider" @@ -135,7 +134,7 @@ export const v2Routes: RouteObject[] = [ lazy: () => import("../../v2-routes/store/store-edit"), }, { - path: "add-currencies", + path: "currencies", lazy: () => import("../../v2-routes/store/store-add-currencies"), }, diff --git a/packages/admin-next/dashboard/src/v2-routes/store/common/hooks/use-currencies-table-columns.tsx b/packages/admin-next/dashboard/src/v2-routes/store/common/hooks/use-currencies-table-columns.tsx new file mode 100644 index 0000000000..f6c458a743 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/store/common/hooks/use-currencies-table-columns.tsx @@ -0,0 +1,24 @@ +import { CurrencyDTO } from "@medusajs/types" +import { createColumnHelper } from "@tanstack/react-table" +import { useMemo } from "react" +import { useTranslation } from "react-i18next" + +const columnHelper = createColumnHelper() + +export const useCurrenciesTableColumns = () => { + const { t } = useTranslation() + + return useMemo( + () => [ + columnHelper.accessor("code", { + header: t("fields.code"), + cell: ({ getValue }) => getValue().toUpperCase(), + }), + columnHelper.accessor("name", { + header: t("fields.name"), + cell: ({ getValue }) => getValue(), + }), + ], + [t] + ) +} diff --git a/packages/admin-next/dashboard/src/v2-routes/store/common/hooks/use-currencies-table-query.tsx b/packages/admin-next/dashboard/src/v2-routes/store/common/hooks/use-currencies-table-query.tsx new file mode 100644 index 0000000000..ca7454f279 --- /dev/null +++ b/packages/admin-next/dashboard/src/v2-routes/store/common/hooks/use-currencies-table-query.tsx @@ -0,0 +1,21 @@ +import { useQueryParams } from "../../../../hooks/use-query-params" + +export const useCurrenciesTableQuery = ({ + pageSize = 10, + prefix, +}: { + pageSize?: number + prefix?: string +}) => { + const raw = useQueryParams(["order", "q", "offset"], prefix) + + const { offset, ...rest } = raw + + const searchParams = { + limit: pageSize, + offset: offset ? parseInt(offset) : 0, + ...rest, + } + + return { searchParams, raw } +} 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 13d52a0dc2..3654ac6ce9 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,43 +1,27 @@ import { Currency } from "@medusajs/medusa" +import { Button, Checkbox, Hint, Tooltip } from "@medusajs/ui" import { - Badge, - Button, - Checkbox, - Hint, - StatusBadge, - Table, - Tooltip, - clx, -} from "@medusajs/ui" -import { - PaginationState, + OnChangeFn, RowSelectionState, createColumnHelper, - flexRender, - getCoreRowModel, - useReactTable, } from "@tanstack/react-table" -import { - adminCurrenciesKeys, - adminStoreKeys, - useAdminCustomPost, - useAdminCustomQuery, -} from "medusa-react" -import { useEffect, useMemo, useState } from "react" +import { adminCurrenciesKeys, useAdminCustomQuery } from "medusa-react" +import { useMemo, useState } from "react" import { useTranslation } from "react-i18next" import * as zod from "zod" import { zodResolver } from "@hookform/resolvers/zod" +import { CurrencyDTO, StoreDTO } from "@medusajs/types" import { useForm } from "react-hook-form" -import { OrderBy } from "../../../../../components/filtering/order-by" -import { LocalizedTablePagination } from "../../../../../components/localization/localized-table-pagination" import { RouteFocusModal, useRouteModal, } from "../../../../../components/route-modal" -import { useHandleTableScroll } from "../../../../../hooks/use-handle-table-scroll" -import { useQueryParams } from "../../../../../hooks/use-query-params" -import { StoreDTO } from "@medusajs/types" +import { DataTable } from "../../../../../components/table/data-table" +import { useDataTable } from "../../../../../hooks/use-data-table" +import { useV2UpdateStore } from "../../../../../lib/api-v2" +import { useCurrenciesTableColumns } from "../../../common/hooks/use-currencies-table-columns" +import { useCurrenciesTableQuery } from "../../../common/hooks/use-currencies-table-query" type AddCurrenciesFormProps = { store: StoreDTO @@ -48,6 +32,7 @@ const AddCurrenciesSchema = zod.object({ }) const PAGE_SIZE = 50 +const PREFIX = "ac" export const AddCurrenciesForm = ({ store }: AddCurrenciesFormProps) => { const { t } = useTranslation() @@ -62,68 +47,55 @@ export const AddCurrenciesForm = ({ store }: AddCurrenciesFormProps) => { const { setValue } = form - const [{ pageIndex, pageSize }, setPagination] = useState({ - pageIndex: 0, - pageSize: PAGE_SIZE, - }) - - const pagination = useMemo( - () => ({ - pageIndex, - pageSize, - }), - [pageIndex, pageSize] - ) - const [rowSelection, setRowSelection] = useState({}) - useEffect(() => { - const ids = Object.keys(rowSelection) + const updater: OnChangeFn = (fn) => { + const updated = typeof fn === "function" ? fn(rowSelection) : fn + + const ids = Object.keys(updated) + setValue("currencies", ids, { shouldDirty: true, shouldTouch: true, }) - }, [rowSelection, setValue]) - const params = useQueryParams(["order"]) - const filter = { - limit: PAGE_SIZE, - offset: pageIndex * PAGE_SIZE, - ...params, + setRowSelection(updated) } - // @ts-ignore - const { data, count, isError, error } = useAdminCustomQuery( + + const { raw, searchParams } = useCurrenciesTableQuery({ + pageSize: 50, + prefix: PREFIX, + }) + + const { data, isLoading, isError, error } = useAdminCustomQuery( "/admin/currencies", - adminCurrenciesKeys.list(filter), - filter + adminCurrenciesKeys.list(raw), + searchParams, + { + keepPreviousData: true, + } ) const preSelectedRows = store.supported_currency_codes.map((c) => c) const columns = useColumns() - const table = useReactTable({ - data: data?.currencies ?? [], + const { table } = useDataTable({ + data: (data?.currencies ?? []) as CurrencyDTO[], columns, - pageCount: Math.ceil((count ?? 0) / PAGE_SIZE), - state: { - pagination, - rowSelection, - }, + count: data?.count, getRowId: (row) => row.code, - onPaginationChange: setPagination, - onRowSelectionChange: setRowSelection, - getCoreRowModel: getCoreRowModel(), enableRowSelection: (row) => !preSelectedRows.includes(row.original.code), - manualPagination: true, + enablePagination: true, + pageSize: PAGE_SIZE, + prefix: PREFIX, + rowSelection: { + state: rowSelection, + updater, + }, }) - const { mutateAsync, isLoading: isMutating } = useAdminCustomPost( - `/admin/stores/${store.id}`, - adminStoreKeys.details() - ) - - const { handleScroll, isScrolled, tableContainerRef } = useHandleTableScroll() + const { mutateAsync, isLoading: isMutating } = useV2UpdateStore(store.id) const handleSubmit = form.handleSubmit(async (data) => { const currencies = Array.from( @@ -174,87 +146,19 @@ export const AddCurrenciesForm = ({ store }: AddCurrenciesFormProps) => { -
-
-
- -
-
-
- - - {table.getHeaderGroups().map((headerGroup) => { - return ( - - {headerGroup.headers.map((header) => { - return ( - - {flexRender( - header.column.columnDef.header, - header.getContext() - )} - - ) - })} - - ) - })} - - - {table.getRowModel().rows.map((row) => ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender( - cell.column.columnDef.cell, - cell.getContext() - )} - - ))} - - ))} - -
-
-
- -
+
@@ -265,6 +169,7 @@ const columnHelper = createColumnHelper() const useColumns = () => { const { t } = useTranslation() + const base = useCurrenciesTableColumns() return useMemo( () => [ @@ -310,29 +215,8 @@ const useColumns = () => { return Component }, }), - columnHelper.accessor("name", { - header: t("fields.name"), - cell: ({ getValue }) => getValue(), - }), - columnHelper.accessor("code", { - header: t("fields.code"), - cell: ({ getValue }) => ( - {getValue().toUpperCase()} - ), - }), - columnHelper.accessor("includes_tax", { - header: t("fields.taxInclusivePricing"), - cell: ({ getValue }) => { - const value = getValue() - - return ( - - {value ? t("general.enabled") : t("general.disabled")} - - ) - }, - }), + ...base, ], - [t] + [t, base] ) } 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 9d63c87c18..a092e9202d 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 @@ -1,72 +1,66 @@ -import { Trash } from "@medusajs/icons" -import { Currency } from "@medusajs/medusa" +import { Plus, Trash } from "@medusajs/icons" +import { CurrencyDTO, StoreDTO } from "@medusajs/types" import { - Button, Checkbox, CommandBar, Container, Heading, - StatusBadge, - Table, - clx, usePrompt, } from "@medusajs/ui" -import { - RowSelectionState, - createColumnHelper, - flexRender, - getCoreRowModel, - getPaginationRowModel, - useReactTable, -} from "@tanstack/react-table" -import { - adminStoreKeys, - useAdminCustomPost, - useAdminCustomQuery, -} from "medusa-react" +import { RowSelectionState, createColumnHelper } from "@tanstack/react-table" +import { adminStoreKeys, useAdminCustomPost } from "medusa-react" import { useMemo, useState } from "react" import { useTranslation } from "react-i18next" -import { Link } from "react-router-dom" import { ActionMenu } from "../../../../../../components/common/action-menu" -import { LocalizedTablePagination } from "../../../../../../components/localization/localized-table-pagination" -import { StoreDTO } from "@medusajs/types" +import { DataTable } from "../../../../../../components/table/data-table" +import { useDataTable } from "../../../../../../hooks/use-data-table" +import { useV2UpdateStore } from "../../../../../../lib/api-v2" +import { useV2Currencies } from "../../../../../../lib/api-v2/currencies" +import { useCurrenciesTableColumns } from "../../../../common/hooks/use-currencies-table-columns" +import { useCurrenciesTableQuery } from "../../../../common/hooks/use-currencies-table-query" type StoreCurrencySectionProps = { store: StoreDTO } -const PAGE_SIZE = 20 +const PAGE_SIZE = 10 export const StoreCurrencySection = ({ store }: StoreCurrencySectionProps) => { const [rowSelection, setRowSelection] = useState({}) - const { data } = useAdminCustomQuery( - `/admin/currencies?code[]=${store.supported_currency_codes.join(",")}`, - adminStoreKeys.details() + + const { searchParams, raw } = useCurrenciesTableQuery({ pageSize: PAGE_SIZE }) + + const { currencies, count, isLoading, isError, error } = useV2Currencies( + { + code: store.supported_currency_codes, + ...searchParams, + }, + { + keepPreviousData: true, + } ) const columns = useColumns() - const table = useReactTable({ - data: data?.currencies ?? [], + const { table } = useDataTable({ + data: currencies ?? [], columns, - getCoreRowModel: getCoreRowModel(), - getPaginationRowModel: getPaginationRowModel(), - onRowSelectionChange: setRowSelection, + count: count, getRowId: (row) => row.code, - pageCount: Math.ceil(store.supported_currency_codes.length / PAGE_SIZE), - state: { - rowSelection, + rowSelection: { + state: rowSelection, + updater: setRowSelection, }, + enablePagination: true, + enableRowSelection: true, + pageSize: PAGE_SIZE, meta: { currencyCodes: store.supported_currency_codes, storeId: store.id, }, }) - const { mutateAsync } = useAdminCustomPost( - `/admin/stores/${store.id}`, - adminStoreKeys.details() - ) + const { mutateAsync } = useV2UpdateStore(store.id) const { t } = useTranslation() const prompt = usePrompt() @@ -100,67 +94,38 @@ export const StoreCurrencySection = ({ store }: StoreCurrencySectionProps) => { ) } + if (isError) { + throw error + } + return ( - +
{t("store.currencies")} -
- - - -
+ , + label: t("actions.add"), + to: "currencies", + }, + ], + }, + ]} + />
- - - {table.getHeaderGroups().map((headerGroup) => { - return ( - - {headerGroup.headers.map((header) => { - return ( - - {flexRender( - header.column.columnDef.header, - header.getContext() - )} - - ) - })} - - ) - })} - - - {table.getRowModel().rows.map((row) => ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - ))} - -
- @@ -187,7 +152,7 @@ const CurrencyActions = ({ currencyCodes, }: { storeId: string - currency: Currency + currency: CurrencyDTO currencyCodes: string[] }) => { const { mutateAsync } = useAdminCustomPost( @@ -238,10 +203,10 @@ const CurrencyActions = ({ ) } -const columnHelper = createColumnHelper() +const columnHelper = createColumnHelper() const useColumns = () => { - const { t } = useTranslation() + const base = useCurrenciesTableColumns() return useMemo( () => [ @@ -273,25 +238,7 @@ const useColumns = () => { ) }, }), - columnHelper.accessor("code", { - header: t("fields.code"), - cell: ({ getValue }) => getValue().toUpperCase(), - }), - columnHelper.accessor("name", { - header: t("fields.name"), - cell: ({ getValue }) => getValue(), - }), - columnHelper.accessor("includes_tax", { - header: "Tax Inclusive Prices", - cell: ({ getValue }) => { - const value = getValue() - const text = value ? t("general.enabled") : t("general.disabled") - - return ( - {text} - ) - }, - }), + ...base, columnHelper.display({ id: "actions", cell: ({ row, table }) => { @@ -310,6 +257,6 @@ const useColumns = () => { }, }), ], - [t] + [base] ) } 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 ccc4f022de..7cebda57eb 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 @@ -1,7 +1,8 @@ -import { Store } from "@medusajs/medusa" -import { Badge, Button, Container, Copy, Heading, Text } from "@medusajs/ui" +import { PencilSquare } from "@medusajs/icons" +import { Badge, Container, Heading, Text } from "@medusajs/ui" import { useTranslation } from "react-i18next" -import { Link } from "react-router-dom" +import { ActionMenu } from "../../../../../components/common/action-menu" +import { Store } from "../../../../../lib/api-v2/types/store" type StoreGeneralSectionProps = { store: Store @@ -19,11 +20,19 @@ export const StoreGeneralSection = ({ store }: StoreGeneralSectionProps) => { {t("store.manageYourStoresDetails")} - - - + , + label: t("actions.edit"), + to: "edit", + }, + ], + }, + ]} + />
@@ -33,82 +42,21 @@ export const StoreGeneralSection = ({ store }: StoreGeneralSectionProps) => { {store.name}
-
- - {t("store.defaultCurrency")} - -
- - {store.default_currency_code.toUpperCase()} - - - {store.default_currency.name} + {store.default_currency && ( +
+ + {t("store.defaultCurrency")} +
+ + {store.default_currency.code.toUpperCase()} + + + {store.default_currency.name} + +
-
-
- - {t("store.swapLinkTemplate")} - - {store.swap_link_template ? ( -
- - {store.swap_link_template} - - -
- ) : ( - - - - - )} -
-
- - {t("store.paymentLinkTemplate")} - - {store.payment_link_template ? ( -
- - {store.payment_link_template} - - -
- ) : ( - - - - - )} -
-
- - {t("store.inviteLinkTemplate")} - - {store.invite_link_template ? ( -
- - {store.invite_link_template} - - -
- ) : ( - - - - - )} -
+ )} ) } diff --git a/packages/admin-next/dashboard/src/v2-routes/store/store-detail/loader.ts b/packages/admin-next/dashboard/src/v2-routes/store/store-detail/loader.ts index 4060a8000c..bc63c69330 100644 --- a/packages/admin-next/dashboard/src/v2-routes/store/store-detail/loader.ts +++ b/packages/admin-next/dashboard/src/v2-routes/store/store-detail/loader.ts @@ -1,14 +1,14 @@ -import { AdminExtendedStoresRes } from "@medusajs/medusa" import { Response } from "@medusajs/medusa-js" import { adminStoreKeys } from "medusa-react" import { redirect } from "react-router-dom" +import { StoreDTO } from "@medusajs/types" import { FetchQueryOptions } from "@tanstack/react-query" import { medusa, queryClient } from "../../../lib/medusa" const storeDetailQuery = () => ({ queryKey: adminStoreKeys.details(), - queryFn: async () => medusa.client.request("GET", "/admin/stores"), + queryFn: async () => medusa.admin.custom.get("/stores"), }) const fetchQuery = async ( @@ -31,7 +31,7 @@ export const storeLoader = async () => { const query = storeDetailQuery() return ( - queryClient.getQueryData>( + queryClient.getQueryData>( query.queryKey ) ?? (await fetchQuery(query)) ) 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 1b9e0a2b65..919d2967c7 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 @@ -1,10 +1,10 @@ import { Outlet, useLoaderData } from "react-router-dom" -import { JsonViewSection } from "../../../components/common/json-view-section/json-view-section.tsx" -import { StoreCurrencySection } from "./components/store-currency-section/store-currencies-section.tsx/index.ts" -import { StoreGeneralSection } from "./components/store-general-section/index.ts" -import { storeLoader } from "./loader.ts" -import { useV2Store } from "../../../lib/api-v2/index.ts" +import { JsonViewSection } from "../../../components/common/json-view-section" +import { useV2Store } from "../../../lib/api-v2" +import { StoreCurrencySection } from "./components/store-currency-section/store-currencies-section.tsx" +import { StoreGeneralSection } from "./components/store-general-section" +import { storeLoader } from "./loader" export const StoreDetail = () => { const initialData = useLoaderData() as Awaited> @@ -13,16 +13,12 @@ export const StoreDetail = () => { initialData: initialData, }) - if (isLoading) { + if (isLoading || !store) { return
Loading...
} - if (isError || !store) { - if (error) { - throw error - } - - return
{JSON.stringify(error, null, 2)}
+ if (isError) { + throw error } return ( 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 e9f8257149..4b4ee72463 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,63 +1,47 @@ import { zodResolver } from "@hookform/resolvers/zod" -import type { Store } from "@medusajs/medusa" +import { StoreDTO } from "@medusajs/types" import { Button, Input } from "@medusajs/ui" -import { adminStoreKeys, useAdminCustomPost } from "medusa-react" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" -import * as zod from "zod" +import { z } from "zod" + import { Form } from "../../../../../components/common/form" import { RouteDrawer, useRouteModal, } from "../../../../../components/route-modal" +import { useV2UpdateStore } from "../../../../../lib/api-v2" type EditStoreFormProps = { - store: Store + store: StoreDTO } -const EditStoreSchema = zod.object({ - name: zod.string().optional(), - swap_link_template: zod.union([zod.literal(""), zod.string().trim().url()]), - payment_link_template: zod.union([ - zod.literal(""), - zod.string().trim().url(), - ]), - invite_link_template: zod.union([zod.literal(""), zod.string().trim().url()]), +const EditStoreSchema = z.object({ + name: z.string().min(1), + // default_currency_code: z.string().optional(), + // default_region_id: z.string().optional(), + // default_location_id: z.string().optional(), }) export const EditStoreForm = ({ store }: EditStoreFormProps) => { const { t } = useTranslation() const { handleSuccess } = useRouteModal() - const form = useForm>({ + const form = useForm>({ defaultValues: { name: store.name, - swap_link_template: store.swap_link_template ?? "", - payment_link_template: store.payment_link_template ?? "", - invite_link_template: store.invite_link_template ?? "", }, resolver: zodResolver(EditStoreSchema), }) - const { mutateAsync, isLoading } = useAdminCustomPost( - `/admin/stores/${store.id}`, - adminStoreKeys.details() - ) + const { mutateAsync, isLoading } = useV2UpdateStore(store.id) const handleSubmit = form.handleSubmit(async (values) => { - mutateAsync( - { - name: values.name, - // invite_link_template: values.invite_link_template || undefined, - // swap_link_template: values.swap_link_template || undefined, - // payment_link_template: values.payment_link_template || undefined, + mutateAsync(values, { + onSuccess: () => { + handleSuccess() }, - { - onSuccess: () => { - handleSuccess() - }, - } - ) + }) }) return ( @@ -72,63 +56,13 @@ export const EditStoreForm = ({ store }: EditStoreFormProps) => { {t("fields.name")} - - - - - )} - /> - ( - - {t("store.swapLinkTemplate")} - - - - - - )} - /> - ( - - {t("store.paymentLinkTemplate")} - - - - - - )} - /> - ( - - {t("store.inviteLinkTemplate")} - - + )} /> + {/* TODO: Add comboboxes for default region, location, and currency. `q` is currently missing on all v2 endpoints */}
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 fe4d8daa74..a1412d944c 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 @@ -1,28 +1,25 @@ import { Heading } from "@medusajs/ui" import { useTranslation } from "react-i18next" -import { json } from "react-router-dom" import { RouteDrawer } from "../../../components/route-modal" -import { EditStoreForm } from "./components/edit-store-form/edit-store-form" import { useV2Store } from "../../../lib/api-v2" +import { EditStoreForm } from "./components/edit-store-form/edit-store-form" export const StoreEdit = () => { const { t } = useTranslation() - const { store, isLoading, isError, error } = useV2Store({}) + const { store, isLoading, isError, error } = useV2Store() if (isError) { throw error } - if (!store && !isLoading) { - throw json("An unknown error has occured", 500) - } + const ready = !!store && !isLoading return ( - {t("store.editStore")} + {t("store.edit.header")} - {store && } + {ready && } ) }