From 9585c4f0277e6501c350e66ed4bfe2092d5c3976 Mon Sep 17 00:00:00 2001 From: Camiel van Schoonhoven Date: Thu, 11 Jun 2026 18:08:03 -0700 Subject: [PATCH] feat: Guided Tours Completion Metrics --- react-compiler.config.js | 1 + src/components/Learn/FeaturedTours.tsx | 85 ++++++++---- src/components/Learn/ToursLibrary.tsx | 21 ++- .../TourProvider/TourTelemetryBridge.test.tsx | 118 +++++++++++++++++ .../TourProvider/TourTelemetryBridge.tsx | 82 ++++++++++++ .../TourProvider/tourCompletion.test.tsx | 109 ++++++++++++++++ src/providers/TourProvider/tourCompletion.ts | 123 ++++++++++++++++++ .../Dashboard/Learn/LearnHomeView.test.tsx | 4 + src/routes/Dashboard/Learn/Tour.tsx | 14 +- 9 files changed, 522 insertions(+), 35 deletions(-) create mode 100644 src/providers/TourProvider/TourTelemetryBridge.test.tsx create mode 100644 src/providers/TourProvider/TourTelemetryBridge.tsx create mode 100644 src/providers/TourProvider/tourCompletion.test.tsx create mode 100644 src/providers/TourProvider/tourCompletion.ts diff --git a/react-compiler.config.js b/react-compiler.config.js index 0f9e98dcf..c0d19b382 100644 --- a/react-compiler.config.js +++ b/react-compiler.config.js @@ -70,6 +70,7 @@ export const REACT_COMPILER_ENABLED_DIRS = [ "src/components/ui/typography.tsx", "src/providers/DialogProvider", + "src/providers/TourProvider/tourCompletion.ts", "src/routes/EditorV2", // 11-20 useCallback/useMemo diff --git a/src/components/Learn/FeaturedTours.tsx b/src/components/Learn/FeaturedTours.tsx index 4c440c9af..febdb6c0f 100644 --- a/src/components/Learn/FeaturedTours.tsx +++ b/src/components/Learn/FeaturedTours.tsx @@ -6,6 +6,7 @@ import { Button } from "@/components/ui/button"; import { Icon } from "@/components/ui/icon"; import { BlockStack, InlineStack } from "@/components/ui/layout"; import { Heading, Paragraph, Text } from "@/components/ui/typography"; +import { useTourCompletion } from "@/providers/TourProvider/tourCompletion"; import { resetAllTourPipelineState } from "@/providers/TourProvider/tourPipelineStorage/resetAllTourPipelineState"; import { APP_ROUTES } from "@/routes/router"; import { tracking } from "@/utils/tracking"; @@ -80,33 +81,11 @@ export function FeaturedTours() { {featured.map((tour) => ( - + tour={tour} + onStart={() => startTour(tour.id)} + /> ))} @@ -114,7 +93,53 @@ export function FeaturedTours() { ); } -function FeaturedTourLabel({ tour }: { tour: FeaturedTour }) { +function FeaturedTourButton({ + tour, + onStart, +}: { + tour: FeaturedTour; + onStart: () => void; +}) { + const completed = useTourCompletion(tour.id); + + return ( + + ); +} + +function FeaturedTourLabel({ + tour, + completed, +}: { + tour: FeaturedTour; + completed: boolean; +}) { return ( @@ -130,6 +155,12 @@ function FeaturedTourLabel({ tour }: { tour: FeaturedTour }) { {tour.tag} )} + {completed && ( + + + )} {!tour.available && ( Coming soon diff --git a/src/components/Learn/ToursLibrary.tsx b/src/components/Learn/ToursLibrary.tsx index 5ab007c90..3bf8c3c79 100644 --- a/src/components/Learn/ToursLibrary.tsx +++ b/src/components/Learn/ToursLibrary.tsx @@ -13,6 +13,7 @@ import { import { Icon } from "@/components/ui/icon"; import { BlockStack, InlineStack } from "@/components/ui/layout"; import { Heading, Paragraph, Text } from "@/components/ui/typography"; +import { useTourCompletion } from "@/providers/TourProvider/tourCompletion"; import { resetAllTourPipelineState } from "@/providers/TourProvider/tourPipelineStorage/resetAllTourPipelineState"; import { APP_ROUTES } from "@/routes/router"; import { tracking } from "@/utils/tracking"; @@ -30,6 +31,7 @@ import { getTour } from "./tours/registry"; function TourCard({ tour }: { tour: Tour }) { const isAvailable = getTour(tour.id) !== undefined; + const completed = useTourCompletion(tour.id); const navigate = useNavigate(); const queryClient = useQueryClient(); @@ -55,6 +57,12 @@ function TourCard({ tour }: { tour: Tour }) { {tour.area} + {completed && ( + + + )} {tour.duration} @@ -64,10 +72,17 @@ function TourCard({ tour }: { tour: Tour }) { size="sm" variant="ghost" onClick={startTour} - {...tracking("learning_hub.tours.start", { tour_id: tour.id })} + {...tracking("learning_hub.tours.start", { + tour_id: tour.id, + is_restart: completed, + })} > - Start tour -