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 && (
+
+
+ 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 && (
+
+
+ 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
-
+ {completed ? "Restart" : "Start tour"}
+
) : (