Browse Source

refactor(dashboard): Simplify useChannel hook

Removes duplication
Michael Bromley 4 months ago
parent
commit
d56f9453b9

+ 7 - 7
packages/dashboard/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx

@@ -1,15 +1,15 @@
 import { useQueryClient } from '@tanstack/react-query';
-import { useState } from 'react';
 import { FolderTree } from 'lucide-react';
+import { useState } from 'react';
 
-import { Trans } from '@/vdb/lib/trans.js';
+import { DataTableBulkActionItem } from '@/vdb/components/data-table/data-table-bulk-action-item.js';
 import { AssignToChannelBulkAction } from '@/vdb/components/shared/assign-to-channel-bulk-action.js';
+import { usePaginatedList } from '@/vdb/components/shared/paginated-list-data-table.js';
 import { RemoveFromChannelBulkAction } from '@/vdb/components/shared/remove-from-channel-bulk-action.js';
-import { api } from '@/vdb/graphql/api.js';
 import { BulkActionComponent } from '@/vdb/framework/extension-api/types/data-table.js';
+import { api } from '@/vdb/graphql/api.js';
 import { useChannel } from '@/vdb/hooks/use-channel.js';
-import { DataTableBulkActionItem } from '@/vdb/components/data-table/data-table-bulk-action-item.js';
-import { usePaginatedList } from '@/vdb/components/shared/paginated-list-data-table.js';
+import { Trans } from '@/vdb/lib/trans.js';
 import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
 import { DuplicateBulkAction } from '../../../../common/duplicate-bulk-action.js';
 import {
@@ -41,7 +41,7 @@ export const AssignCollectionsToChannelBulkAction: BulkActionComponent<any> = ({
 };
 
 export const RemoveCollectionsFromChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
-    const { selectedChannel } = useChannel();
+    const { activeChannel } = useChannel();
     const queryClient = useQueryClient();
 
     return (
@@ -53,7 +53,7 @@ export const RemoveCollectionsFromChannelBulkAction: BulkActionComponent<any> =
             requiredPermissions={['UpdateCatalog', 'UpdateCollection']}
             buildInput={() => ({
                 collectionIds: selection.map(s => s.id),
-                channelId: selectedChannel?.id,
+                channelId: activeChannel?.id,
             })}
             onSuccess={() => {
                 queryClient.invalidateQueries({ queryKey: ['childCollections'] });

+ 3 - 3
packages/dashboard/src/app/routes/_authenticated/_facets/components/facet-bulk-actions.tsx

@@ -2,9 +2,9 @@ import { toast } from 'sonner';
 
 import { AssignToChannelBulkAction } from '@/vdb/components/shared/assign-to-channel-bulk-action.js';
 import { RemoveFromChannelBulkAction } from '@/vdb/components/shared/remove-from-channel-bulk-action.js';
+import { BulkActionComponent } from '@/vdb/framework/extension-api/types/data-table.js';
 import { api } from '@/vdb/graphql/api.js';
 import { ResultOf } from '@/vdb/graphql/graphql.js';
-import { BulkActionComponent } from '@/vdb/framework/extension-api/types/data-table.js';
 import { useChannel } from '@/vdb/hooks/use-channel.js';
 import { useLingui } from '@/vdb/lib/trans.js';
 import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
@@ -45,7 +45,7 @@ export const AssignFacetsToChannelBulkAction: BulkActionComponent<any> = ({ sele
 };
 
 export const RemoveFacetsFromChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
-    const { selectedChannel } = useChannel();
+    const { activeChannel } = useChannel();
     const { i18n } = useLingui();
 
     return (
@@ -57,7 +57,7 @@ export const RemoveFacetsFromChannelBulkAction: BulkActionComponent<any> = ({ se
             requiredPermissions={['UpdateCatalog', 'UpdateFacet']}
             buildInput={() => ({
                 facetIds: selection.map(s => s.id),
-                channelId: selectedChannel?.id,
+                channelId: activeChannel?.id,
             })}
             onSuccess={result => {
                 const typedResult = result as ResultOf<typeof removeFacetsFromChannelDocument>;

+ 2 - 2
packages/dashboard/src/app/routes/_authenticated/_payment-methods/components/payment-method-bulk-actions.tsx

@@ -40,7 +40,7 @@ export const AssignPaymentMethodsToChannelBulkAction: BulkActionComponent<any> =
 };
 
 export const RemovePaymentMethodsFromChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
-    const { selectedChannel } = useChannel();
+    const { activeChannel } = useChannel();
 
     return (
         <RemoveFromChannelBulkAction
@@ -51,7 +51,7 @@ export const RemovePaymentMethodsFromChannelBulkAction: BulkActionComponent<any>
             requiredPermissions={['UpdatePaymentMethod']}
             buildInput={() => ({
                 paymentMethodIds: selection.map(s => s.id),
-                channelId: selectedChannel?.id,
+                channelId: activeChannel?.id,
             })}
         />
     );

+ 4 - 4
packages/dashboard/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx

@@ -4,11 +4,11 @@ import { useState } from 'react';
 import { DataTableBulkActionItem } from '@/vdb/components/data-table/data-table-bulk-action-item.js';
 import { AssignToChannelBulkAction } from '@/vdb/components/shared/assign-to-channel-bulk-action.js';
 import { usePriceFactor } from '@/vdb/components/shared/assign-to-channel-dialog.js';
+import { usePaginatedList } from '@/vdb/components/shared/paginated-list-data-table.js';
 import { RemoveFromChannelBulkAction } from '@/vdb/components/shared/remove-from-channel-bulk-action.js';
-import { api } from '@/vdb/graphql/api.js';
 import { BulkActionComponent } from '@/vdb/framework/extension-api/types/data-table.js';
+import { api } from '@/vdb/graphql/api.js';
 import { useChannel } from '@/vdb/hooks/use-channel.js';
-import { usePaginatedList } from '@/vdb/components/shared/paginated-list-data-table.js';
 import { Trans } from '@/vdb/lib/trans.js';
 import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
 
@@ -58,7 +58,7 @@ export const RemoveProductVariantsFromChannelBulkAction: BulkActionComponent<any
     selection,
     table,
 }) => {
-    const { selectedChannel } = useChannel();
+    const { activeChannel } = useChannel();
 
     return (
         <RemoveFromChannelBulkAction
@@ -69,7 +69,7 @@ export const RemoveProductVariantsFromChannelBulkAction: BulkActionComponent<any
             requiredPermissions={['UpdateCatalog', 'UpdateProduct']}
             buildInput={() => ({
                 productVariantIds: selection.map(s => s.id),
-                channelId: selectedChannel?.id,
+                channelId: activeChannel?.id,
             })}
         />
     );

+ 2 - 2
packages/dashboard/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx

@@ -55,7 +55,7 @@ export const AssignProductsToChannelBulkAction: BulkActionComponent<any> = ({ se
 };
 
 export const RemoveProductsFromChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
-    const { selectedChannel } = useChannel();
+    const { activeChannel } = useChannel();
 
     return (
         <RemoveFromChannelBulkAction
@@ -66,7 +66,7 @@ export const RemoveProductsFromChannelBulkAction: BulkActionComponent<any> = ({
             requiredPermissions={['UpdateCatalog', 'UpdateProduct']}
             buildInput={() => ({
                 productIds: selection.map(s => s.id),
-                channelId: selectedChannel?.id,
+                channelId: activeChannel?.id,
             })}
         />
     );

+ 2 - 2
packages/dashboard/src/app/routes/_authenticated/_promotions/components/promotion-bulk-actions.tsx

@@ -41,7 +41,7 @@ export const AssignPromotionsToChannelBulkAction: BulkActionComponent<any> = ({
 };
 
 export const RemovePromotionsFromChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
-    const { selectedChannel } = useChannel();
+    const { activeChannel } = useChannel();
 
     return (
         <RemoveFromChannelBulkAction
@@ -52,7 +52,7 @@ export const RemovePromotionsFromChannelBulkAction: BulkActionComponent<any> = (
             requiredPermissions={['UpdatePromotion']}
             buildInput={() => ({
                 promotionIds: selection.map(s => s.id),
-                channelId: selectedChannel?.id,
+                channelId: activeChannel?.id,
             })}
         />
     );

+ 2 - 2
packages/dashboard/src/app/routes/_authenticated/_shipping-methods/components/shipping-method-bulk-actions.tsx

@@ -43,7 +43,7 @@ export const RemoveShippingMethodsFromChannelBulkAction: BulkActionComponent<any
     selection,
     table,
 }) => {
-    const { selectedChannel } = useChannel();
+    const { activeChannel } = useChannel();
 
     return (
         <RemoveFromChannelBulkAction
@@ -54,7 +54,7 @@ export const RemoveShippingMethodsFromChannelBulkAction: BulkActionComponent<any
             requiredPermissions={['UpdateShippingMethod']}
             buildInput={() => ({
                 shippingMethodIds: selection.map(s => s.id),
-                channelId: selectedChannel?.id,
+                channelId: activeChannel?.id,
             })}
         />
     );

+ 3 - 3
packages/dashboard/src/app/routes/_authenticated/_stock-locations/components/stock-location-bulk-actions.tsx

@@ -1,7 +1,7 @@
 import { AssignToChannelBulkAction } from '@/vdb/components/shared/assign-to-channel-bulk-action.js';
 import { RemoveFromChannelBulkAction } from '@/vdb/components/shared/remove-from-channel-bulk-action.js';
-import { api } from '@/vdb/graphql/api.js';
 import { BulkActionComponent } from '@/vdb/framework/extension-api/types/data-table.js';
+import { api } from '@/vdb/graphql/api.js';
 import { useChannel } from '@/vdb/hooks/use-channel.js';
 import { DeleteBulkAction } from '../../../../common/delete-bulk-action.js';
 
@@ -40,7 +40,7 @@ export const AssignStockLocationsToChannelBulkAction: BulkActionComponent<any> =
 };
 
 export const RemoveStockLocationsFromChannelBulkAction: BulkActionComponent<any> = ({ selection, table }) => {
-    const { selectedChannel } = useChannel();
+    const { activeChannel } = useChannel();
 
     return (
         <RemoveFromChannelBulkAction
@@ -51,7 +51,7 @@ export const RemoveStockLocationsFromChannelBulkAction: BulkActionComponent<any>
             requiredPermissions={['UpdateStockLocation']}
             buildInput={() => ({
                 stockLocationIds: selection.map(s => s.id),
-                channelId: selectedChannel?.id,
+                channelId: activeChannel?.id,
             })}
         />
     );

+ 6 - 4
packages/dashboard/src/lib/components/layout/channel-switcher.tsx

@@ -19,7 +19,7 @@ import { useServerConfig } from '@/vdb/hooks/use-server-config.js';
 import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
 import { Trans } from '@/vdb/lib/trans.js';
 import { Link } from '@tanstack/react-router';
-import { useState } from 'react';
+import { useEffect, useState } from 'react';
 import { ManageLanguagesDialog } from './manage-languages-dialog.js';
 
 /**
@@ -44,7 +44,7 @@ function getChannelInitialsFromCode(code: string) {
 
 export function ChannelSwitcher() {
     const { isMobile } = useSidebar();
-    const { channels, activeChannel, selectedChannel, setSelectedChannel } = useChannel();
+    const { channels, activeChannel, setActiveChannel } = useChannel();
     const serverConfig = useServerConfig();
     const { formatLanguageName } = useLocalFormat();
     const {
@@ -54,7 +54,7 @@ export function ChannelSwitcher() {
     const [showManageLanguagesDialog, setShowManageLanguagesDialog] = useState(false);
 
     // Use the selected channel if available, otherwise fall back to the active channel
-    const displayChannel = selectedChannel || activeChannel;
+    const displayChannel = activeChannel || activeChannel;
 
     // Get available languages from server config
     const availableLanguages = serverConfig?.availableLanguages || [];
@@ -65,6 +65,8 @@ export function ChannelSwitcher() {
         ? [displayChannel, ...channels.filter(ch => ch.id !== displayChannel.id)]
         : channels;
 
+    useEffect(() => {}, []);
+
     return (
         <>
             <SidebarMenu>
@@ -109,7 +111,7 @@ export function ChannelSwitcher() {
                             {orderedChannels.map((channel, index) => (
                                 <div key={channel.code}>
                                     <DropdownMenuItem
-                                        onClick={() => setSelectedChannel(channel.id)}
+                                        onClick={() => setActiveChannel(channel.id)}
                                         className="gap-2 p-2"
                                     >
                                         <div className="flex size-8 items-center justify-center rounded border">

+ 2 - 2
packages/dashboard/src/lib/components/layout/manage-languages-dialog.tsx

@@ -96,11 +96,11 @@ interface ManageLanguagesDialogProps {
 
 export function ManageLanguagesDialog({ open, onClose }: ManageLanguagesDialogProps) {
     const { formatLanguageName } = useLocalFormat();
-    const { activeChannel, selectedChannel } = useChannel();
+    const { activeChannel } = useChannel();
     const { hasPermissions } = usePermissions();
     const queryClient = useQueryClient();
 
-    const displayChannel = selectedChannel || activeChannel;
+    const displayChannel = activeChannel;
 
     // Permission checks
     const canReadGlobalSettings = hasPermissions(['ReadSettings']) || hasPermissions(['ReadGlobalSettings']);

+ 2 - 2
packages/dashboard/src/lib/components/shared/assign-to-channel-dialog.tsx

@@ -56,10 +56,10 @@ export function AssignToChannelDialog({
 }: Readonly<AssignToChannelDialogProps>) {
     const { i18n } = useLingui();
     const [selectedChannelId, setSelectedChannelId] = useState<string>('');
-    const { channels, selectedChannel } = useChannel();
+    const { channels, activeChannel } = useChannel();
 
     // Filter out the currently selected channel from available options
-    const availableChannels = channels.filter(channel => channel.id !== selectedChannel?.id);
+    const availableChannels = channels.filter(channel => channel.id !== activeChannel?.id);
 
     const { mutate, isPending } = useMutation({
         mutationFn,

+ 2 - 2
packages/dashboard/src/lib/components/shared/remove-from-channel-bulk-action.tsx

@@ -42,7 +42,7 @@ export function RemoveFromChannelBulkAction({
     errorMessage,
 }: Readonly<RemoveFromChannelBulkActionProps>) {
     const { refetchPaginatedList } = usePaginatedList();
-    const { selectedChannel } = useChannel();
+    const { activeChannel } = useChannel();
     const { i18n } = useLingui();
     const { mutate } = useMutation({
         mutationFn,
@@ -63,7 +63,7 @@ export function RemoveFromChannelBulkAction({
         },
     });
 
-    if (!selectedChannel) {
+    if (!activeChannel) {
         return null;
     }
 

+ 4 - 4
packages/dashboard/src/lib/hooks/use-permissions.ts

@@ -18,18 +18,18 @@ import { useChannel } from './use-channel.js';
  */
 export function usePermissions() {
     const { channels } = useAuth();
-    const { selectedChannelId } = useChannel();
+    const { activeChannel } = useChannel();
 
     function hasPermissions(permissions: string[]) {
         if (permissions.length === 0) {
             return true;
         }
         // Use the selected channel instead of settings.activeChannelId
-        const activeChannel = (channels ?? []).find(channel => channel.id === selectedChannelId);
-        if (!activeChannel) {
+        const selectedChannel = (channels ?? []).find(channel => channel.id === activeChannel?.id);
+        if (!selectedChannel) {
             return false;
         }
-        return permissions.some(permission => activeChannel.permissions.includes(permission as Permission));
+        return permissions.some(permission => selectedChannel.permissions.includes(permission as Permission));
     }
 
     return { hasPermissions };

+ 7 - 13
packages/dashboard/src/lib/providers/channel-provider.tsx

@@ -51,12 +51,10 @@ type Channel = ResultOf<typeof channelFragment>;
  * @since 3.3.0
  */
 export interface ChannelContext {
-    activeChannel: ActiveChannel | undefined;
-    channels: Channel[];
-    selectedChannelId: string | undefined;
-    selectedChannel: Channel | undefined;
     isLoading: boolean;
-    setSelectedChannel: (channelId: string) => void;
+    channels: Channel[];
+    activeChannel: ActiveChannel | undefined;
+    setActiveChannel: (channelId: string) => void;
     refreshChannels: () => void;
 }
 
@@ -122,6 +120,7 @@ export function ChannelProvider({ children }: Readonly<{ children: React.ReactNo
                     localStorage.setItem(SELECTED_CHANNEL_KEY, channelId);
                     localStorage.setItem(SELECTED_CHANNEL_TOKEN_KEY, channel.token);
                     setSelectedChannelId(channelId);
+
                     queryClient.invalidateQueries();
                 }
             } catch (e) {
@@ -160,13 +159,10 @@ export function ChannelProvider({ children }: Readonly<{ children: React.ReactNo
         }
     }, [selectedChannelId, channels]);
 
-    const activeChannel = channelsData?.activeChannel;
     const isLoading = isChannelsLoading;
 
     // Find the selected channel from the list of channels
-    const selectedChannel = React.useMemo(() => {
-        return channels.find(channel => channel.id === selectedChannelId);
-    }, [channels, selectedChannelId]);
+    const selectedChannel = channelsData?.activeChannel;
 
     const refreshChannels = () => {
         refreshCurrentUser();
@@ -176,12 +172,10 @@ export function ChannelProvider({ children }: Readonly<{ children: React.ReactNo
     };
 
     const contextValue: ChannelContext = {
-        activeChannel,
         channels,
-        selectedChannelId,
-        selectedChannel,
+        activeChannel: selectedChannel,
         isLoading,
-        setSelectedChannel,
+        setActiveChannel: setSelectedChannel,
         refreshChannels,
     };