1. Top
  2. ブログ一覧
  3. Shopify Admin blockを条件に応じて非表示にする方法
Eコマース

Shopify Admin blockを条件に応じて非表示にする方法

公開日

2024.12.18

Shopify Admin blockを条件に応じて非表示にする方法のサムネイル

Shopify Admin拡張機能(Admin block)を利用すると、管理画面に独自の要素を表示できます。しかし、常に表示しておくと運用のノイズとなる場合や、一部条件下でのみ有効なUIが不要な場面があります。たとえば、データが存在しない場合や特定ステータス下でのみ有効な機能を提供したい場合には、その要素を一時的に非表示にしたいでしょう。

※ 今回ご紹介する機能は2025-01バージョンでリリース予定であり、現在の2024-10バージョンでは利用できません。

Admin blockの表示制御

Admin blockは不要であれば非表示に、参照する機会の少ない場合は折りたたみ表示にするなど、表示制御を行うことができます。この記事では、条件に応じてAdmin blockを非表示にする方法を解説します。

Admin blockを非表示にする方法

shopify.extension.tomlに表示すべきかを[extensions.targeting.should_render]として定義します。また、判定する関数を指定しその関数の返り値をfalseにすることで、Admin blockを非表示にすることができます。

api_version = "2024-10"

[[extensions]]
name = "t:name"
handle = "issue-tracker-conditional-action"
type = "ui_extension"

[[extensions.targeting]]
module = "./src/ActionExtension.jsx"
target = "admin.product-details.action.render"

[extensions.targeting.should_render]
module = "./src/condition/ShouldRender.js"

[extensions.targeting.should_render]に指定したShouldRender.jsは、たとえば次のように記述します。

import { getProductVariants } from "../utils";

const TARGET = "admin.product-details.action.should-render";

export default shopify.extend(TARGET, ({ data }) => {
  const shouldDisplay = getProductVariants(data).then(
    (variants) => variants.length > 1
  );

  return { display: shouldDisplay };
});

shouldDisplayの返り値がfalseの場合、Admin blockは非表示になります。

Admin blockを折りたたみ表示にする方法

Admin blockを折りたたみ表示にする場合は、AdminBlockコンポーネントにcollapsedSummaryプロパティを記述します。
そして子コンポーネントにコンテンツを記述することで、折りたたみ表示を実現できます。

前回紹介したShopify Admin blockで管理画面に好きなコンテンツを追加しようでのコードを参考にしたコード例です。

import { useEffect, useState } from "react";
import {
  AdminBlock,
  BlockStack,
  Box,
  InlineStack,
  ProgressIndicator,
  Text,
  Paragraph,
} from "@shopify/ui-extensions-react/admin";
import { getProductSkus, getSalesData } from "./utils";

const TARGET = "admin.product-details.block.render";

export default reactExtension(TARGET, () => <SalesReportApp />);

function SalesReportApp() {
  const { data } = useApi(TARGET);
  const [loading, setLoading] = useState(true);
  const [salesData, setSalesData] = useState([]);
  const [error, setError] = useState(null);
  const [shouldRender, setShouldRender] = useState(false);

  const productId = data?.selected?.[0]?.id;

  useEffect(() => {
    async function fetchData() {
      try {
        setLoading(true);
        setError(null);

        if (!productId) {
          throw new Error("商品が選択されていません。");
        }

        // 商品のSKUを取得
        const skuResponse = await getProductSkus(productId);
        const skus =
          skuResponse?.data?.product?.variants?.edges?.map(
            (node) => node.node.sku
          ) || [];

        if (skus.length === 0) {
          setSalesData([]); // SKUがない場合、売上データも空
          setShouldRender(false);
          return;
        }

        // SKUに基づく売上データを取得
        const salesResponse = await getSalesData(skus);
        const salesByDate = {};

        salesResponse?.data?.orders?.edges?.forEach(({ node }) => {
          const date = new Date(node.createdAt).toLocaleDateString("ja-JP");
          const amount = parseFloat(node.totalPriceSet.shopMoney.amount);
          salesByDate[date] = (salesByDate[date] || 0) + amount;
        });

        const formattedSales = Object.entries(salesByDate)
          .map(([date, sales]) => ({ date, sales }))
          .sort((a, b) => new Date(b.date) - new Date(a.date));

        setSalesData(formattedSales);
        setShouldRender(true);
      } catch (err) {
        setError(err.message || "データの取得中にエラーが発生しました");
        console.error("Error:", err);
        setShouldRender(false);
      } finally {
        setLoading(false);
      }
    }

    fetchData();
  }, [productId]);

  const blockMarkup = loading ? (
    <InlineStack blockAlignment="center" inlineAlignment="center">
      <ProgressIndicator size="large-100" />
    </InlineStack>
  ) : error ? (
    <Text tone="critical">エラーが発生しました: {error}</Text>
  ) : salesData.length === 0 ? (
    <Box padding="base">
      <Text>この期間の売上データはありません。</Text>
    </Box>
  ) : (
    <BlockStack spacing="base">
      {salesData.map((data) => (
        <Box padding="base" key={data.date}>
          <Paragraph><Text fontWeight="bold">{data.date}</Text> の売り上げ:{" "}
            <Text fontWeight="bold">
              {data.sales.toLocaleString("ja-JP")}
            </Text>{" "}
            円
          </Paragraph>
        </Box>
      ))}
    </BlockStack>
  );

  return (
    <AdminBlock
      title="1週間の売り上げレポート"
      collapsedSummary={
        !shouldRender ? "表示するデータがありません。" : null
      }
    >
      {shouldRender ? blockMarkup : null}
    </AdminBlock>
  );
}

まとめ

Shopify Admin拡張機能を利用する際、条件に応じてAdmin blockを非表示にする方法を解説しました。Admin blockを折りたたみ表示にすることで、管理画面の見やすさを向上させることができます。ぜひ、ご活用ください。

参考