import { WidgetConfig, WidgetProps } from "@medusajs/admin"; import { useAdminCustomPost, useAdminCustomQuery } from "medusa-react"; import React, { useEffect, useState } from "react"; import { useNavigate } from "react-router-dom"; import { OnboardingState } from "../../../models/onboarding"; import { AdminOnboardingUpdateStateReq, OnboardingStateRes, UpdateOnboardingStateInput, } from "../../../types/onboarding"; import OrderDetail from "../../components/onboarding-flow/orders/order-detail"; import OrdersList from "../../components/onboarding-flow/orders/orders-list"; import ProductDetail from "../../components/onboarding-flow/products/product-detail"; import ProductsList from "../../components/onboarding-flow/products/products-list"; import Accordion from "../../components/shared/accordion"; import Button from "../../components/shared/button"; import { Container } from "../../components/shared/container"; import GetStartedIcon from "../../components/shared/icons/get-started-icon"; type STEP_ID = | "create_product" | "preview_product" | "create_order" | "setup_finished"; export type StepContentProps = WidgetProps & { onNext?: Function; isComplete?: boolean; data?: OnboardingState; }; type Step = { id: STEP_ID; title: string; component: React.FC; onNext?: Function; }; const STEP_FLOW: STEP_ID[] = [ "create_product", "preview_product", "create_order", "setup_finished", ]; const QUERY_KEY = ["onboarding_state"]; const OnboardingFlow = (props: WidgetProps) => { const { data, isLoading } = useAdminCustomQuery< undefined, OnboardingStateRes >("/onboarding", QUERY_KEY); const { mutate } = useAdminCustomPost< AdminOnboardingUpdateStateReq, OnboardingStateRes >("/onboarding", QUERY_KEY); const navigate = useNavigate(); const currentStep: STEP_ID | undefined = data?.status ?.current_step as STEP_ID; const [openStep, setOpenStep] = useState(currentStep); const [completed, setCompleted] = useState(false); useEffect(() => { setOpenStep(currentStep); if (currentStep === STEP_FLOW[STEP_FLOW.length - 1]) setCompleted(true); }, [currentStep]); if ( !isLoading && data?.status?.is_complete && !localStorage.getItem("override_onboarding_finish") ) return null; const updateServerState = ( payload: UpdateOnboardingStateInput, onSuccess: () => void = () => {} ) => { mutate(payload, { onSuccess }); }; const onStart = () => { updateServerState({ current_step: STEP_FLOW[0] }); navigate(`/a/products`); }; const setStepComplete = ({ step_id, extraData, onComplete, }: { step_id: STEP_ID; extraData?: UpdateOnboardingStateInput; onComplete?: () => void; }) => { const next = STEP_FLOW[STEP_FLOW.findIndex((step) => step === step_id) + 1]; updateServerState({ current_step: next, ...extraData }, onComplete); }; const goToProductView = (product: any) => { setStepComplete({ step_id: "create_product", extraData: { product_id: product.id }, onComplete: () => navigate(`/a/products/${product.id}`), }); }; const goToOrders = () => { setStepComplete({ step_id: "preview_product", onComplete: () => navigate(`/a/orders`), }); }; const goToOrderView = (order: any) => { setStepComplete({ step_id: "create_order", onComplete: () => navigate(`/a/orders/${order.id}`), }); }; const onComplete = () => { setCompleted(true); }; const onHide = () => { updateServerState({ is_complete: true }); }; const Steps: Step[] = [ { id: "create_product", title: "Create Product", component: ProductsList, onNext: goToProductView, }, { id: "preview_product", title: "Preview Product", component: ProductDetail, onNext: goToOrders, }, { id: "create_order", title: "Create an Order", component: OrdersList, onNext: goToOrderView, }, { id: "setup_finished", title: "Setup Finished: Start developing with Medusa", component: OrderDetail, }, ]; const isStepComplete = (step_id: STEP_ID) => STEP_FLOW.indexOf(currentStep) > STEP_FLOW.indexOf(step_id); return ( <> setOpenStep(value as STEP_ID)} >
{!completed ? ( <>

Get started

Learn the basics of Medusa by creating your first order.

{!!currentStep ? ( <> {currentStep === STEP_FLOW[STEP_FLOW.length - 1] ? ( ) : ( )} ) : ( <> )}
) : ( <>

Thank you for completing the setup guide!

This whole experience was built using our new{" "} widgets feature.
You can find out more details and build your own by following{" "} our guide .

)}
{
{(!completed ? Steps : Steps.slice(-1)).map((step) => { const isComplete = isStepComplete(step.id); const isCurrent = currentStep === step.id; return ( , })} >
); })}
}
); }; export const config: WidgetConfig = { zone: [ "product.list.before", "product.details.before", "order.list.before", "order.details.before", ], }; export default OnboardingFlow;