import clsx from "clsx" import { useEffect, useMemo, useRef, useState } from "react" import { SalesChannel } from "@medusajs/medusa" import { useAdminDeleteSalesChannel, useAdminSalesChannels, useAdminStore, useAdminUpdateSalesChannel, } from "medusa-react" import { useTranslation } from "react-i18next" import { useNavigate, useParams } from "react-router-dom" import BackButton from "../../../components/atoms/back-button" import Fade from "../../../components/atoms/fade-wrapper" import Spacer from "../../../components/atoms/spacer" import CrossIcon from "../../../components/fundamentals/icons/cross-icon" import EditIcon from "../../../components/fundamentals/icons/edit-icon" import PlusIcon from "../../../components/fundamentals/icons/plus-icon" import SearchIcon from "../../../components/fundamentals/icons/search-icon" import TrashIcon from "../../../components/fundamentals/icons/trash-icon" import Actionables, { ActionType, } from "../../../components/molecules/actionables" import StatusSelector from "../../../components/molecules/status-selector" import useImperativeDialog from "../../../hooks/use-imperative-dialog" import useToggleState from "../../../hooks/use-toggle-state" import AddSalesChannelModal from "../form/add-sales-channel" import EditSalesChannel from "../form/edit-sales-channel" import { SalesChannelProductsSelectModal, SalesChannelProductsTable, } from "../tables/product" type ListIndicatorProps = { isActive: boolean } /** * Sales channels list indicator component. */ function ListIndicator(props: ListIndicatorProps) { const { isActive } = props return (
{isActive && (
)}
) } /** * List indicator for disabled SC. */ function DisabledLabel() { const { t } = useTranslation() return (
{t("pages-draft", "Draft")}
) } type SalesChannelTileProps = { salesChannel: SalesChannel isSelected: boolean isDisabled: boolean onClick: () => void } /** * Sales channels list tile component. */ function SalesChannelTile(props: SalesChannelTileProps) { const { salesChannel, isSelected, onClick, isDisabled } = props return (

{salesChannel.name}

{salesChannel.description}
{isDisabled && (
)}
) } type SalesChannelsHeaderProps = { openCreateModal: () => void filterText?: string setFilterText: (text: string) => void } /** * Sales channel header. */ function SalesChannelsHeader(props: SalesChannelsHeaderProps) { const { openCreateModal, filterText, setFilterText } = props const [showFilter, setShowFilter] = useState(false) const inputRef = useRef() const { t } = useTranslation() const classes = { "translate-y-[-50px]": showFilter, "translate-y-[0px]": !showFilter, } const hideFilter = () => { setShowFilter(false) setFilterText("") } return (

{t("pages-sales-channels", "Sales channels")}

setShowFilter(true)} className="cursor-pointer" />
{t( "pages-control-which-products-are-available-in-which-channels", "Control which products are available in which channels" )}
setFilterText(e.target.value)} placeholder={t( "pages-search-by-title-or-description", "Search by title or description" )} className="remove-number-spinner leading-base text-grey-90 caret-violet-60 placeholder-grey-40 w-full bg-inherit font-normal outline-none outline-0" onBlur={() => setShowFilter(!!filterText)} autoComplete="off" />
) } type SalesChannelsListProps = { activeChannelId: string openCreateModal: () => void filterText?: string setFilterText: (text: string) => void salesChannels: SalesChannel[] setActiveSalesChannelId: (salesChannelId: string) => void } /** * Sales channels list. */ function SalesChannelsList(props: SalesChannelsListProps) { const { activeChannelId, openCreateModal, setActiveSalesChannelId, salesChannels, filterText, setFilterText, } = props return (
{salesChannels?.map((s) => ( setActiveSalesChannelId(s.id)} /> ))}
) } type SalesChannelDetailsHeaderProps = { salesChannel: SalesChannel openUpdateModal: () => void resetDetails: () => void showProductsAdd: () => void isDefault: boolean } /** * Sales channels details header. */ function SalesChannelDetailsHeader(props: SalesChannelDetailsHeaderProps) { const { isDefault, salesChannel, openUpdateModal, resetDetails, showProductsAdd, } = props const { t } = useTranslation() const { mutate: deleteSalesChannel } = useAdminDeleteSalesChannel( salesChannel.id ) const { mutate: updateSalesChannel } = useAdminUpdateSalesChannel( salesChannel.id ) const confirmation = useImperativeDialog() const onDelete = async () => { const confirmed = await confirmation({ text: t( "pages-confirm-delete-sales-channel", "Are you sure you want to delete this sales channel? The setup you made will be gone forever." ), heading: t("pages-delete-channel-heading", "Delete Channel"), extraConfirmation: true, entityName: salesChannel.name, }) if (confirmed) { deleteSalesChannel() resetDetails() } } const actions = useMemo(() => { const _actions: ActionType[] = [ { label: t("pages-edit-general-info", "Edit general info"), icon: , onClick: openUpdateModal, }, { label: t("pages-add-products", "Add products"), icon: , onClick: () => showProductsAdd(), }, ] if (!isDefault) { _actions.push({ label: t("pages-delete-channel", "Delete channel"), icon: , variant: "danger", onClick: onDelete, }) } return _actions }, [openUpdateModal]) return (

{salesChannel.name}

updateSalesChannel({ is_disabled: !salesChannel.is_disabled }) } isDraft={salesChannel.is_disabled} draftState={t("pages-disabled", "Disabled")} activeState={t("pages-enabled", "Enabled")} />
) } type SalesChannelDetailsProps = { salesChannel: SalesChannel resetDetails: () => void isDefault: boolean } /** * Sales channels details container. */ function SalesChannelDetails(props: SalesChannelDetailsProps) { const { resetDetails, salesChannel, isDefault } = props const [showUpdateModal, openUpdateModal, closeUpdateModal] = useToggleState(false) const [showAddProducts, showProductsAdd, hideProductsAdd] = useToggleState(false) return (
{showUpdateModal && ( )} {showAddProducts && ( )}
) } /** * Sales channels details page container. */ function Details() { const { id: routeSalesChannelId } = useParams() const { t } = useTranslation() const [filterText, setFilterText] = useState() const [showCreateModal, setShowCreateModal] = useState(false) const [activeSalesChannel, setActiveSalesChannel] = useState() const navigate = useNavigate() const { store } = useAdminStore() const { sales_channels } = useAdminSalesChannels() const setActiveSalesChannelId = (scId: string) => { navigate(`/a/sales-channels/${scId}`) } useEffect(() => { if (sales_channels && store) { if (!activeSalesChannel) { setActiveSalesChannelId(store.default_sales_channel_id) } else { setActiveSalesChannelId(activeSalesChannel.id) } } }, [sales_channels, store, activeSalesChannel?.id]) useEffect(() => { if (routeSalesChannelId !== activeSalesChannel?.id) { const activeChannel = sales_channels?.find( (sc) => sc.id === routeSalesChannelId ) setActiveSalesChannel(activeChannel) } }, [routeSalesChannelId, activeSalesChannel, sales_channels]) const openCreateModal = () => setShowCreateModal(true) const closeCreateModal = (scId: string) => { setActiveSalesChannelId(scId) setShowCreateModal(false) } const resetDetails = () => { setActiveSalesChannelId(store!.default_sales_channel_id) } function defaultChannelsSorter(sc1, sc2) { if (sc1.id === store?.default_sales_channel_id) { return -1 } if (sc2.id === store?.default_sales_channel_id) { return 1 } return sc1.name.localeCompare(sc2.name) } function filterSalesChannels(channels: SalesChannel[]) { if (!filterText) { return channels } return channels.filter((ch) => { const filter = filterText.toLowerCase() return ( !!ch.name.toLowerCase().match(filter) || !!ch.description?.toLowerCase().match(filter) ) }) } if (!sales_channels || !activeSalesChannel) { return null } return (
{activeSalesChannel && ( sc.id === activeSalesChannel.id)! } resetDetails={resetDetails} /> )}
) } export default Details