diff --git a/bun.lock b/bun.lock index 6753ba0..1be1bb3 100644 --- a/bun.lock +++ b/bun.lock @@ -37,17 +37,21 @@ "@trpc/client": "^11.0.0", "@trpc/react-query": "^11.0.0", "@trpc/server": "^11.0.0", + "@types/js-cookie": "^3.0.6", "@types/ws": "^8.18.1", "bcryptjs": "^3.0.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", + "driver.js": "^1.4.0", "drizzle-orm": "^0.41.0", + "js-cookie": "^3.0.5", "lucide-react": "^0.536.0", "minio": "^8.0.6", "next": "^16.0.10", "next-auth": "^5.0.0-beta.29", + "next-themes": "^0.4.6", "postgres": "^3.4.4", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -631,6 +635,8 @@ "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + "@types/js-cookie": ["@types/js-cookie@3.0.6", "", {}, "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ=="], + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], @@ -845,6 +851,8 @@ "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], + "driver.js": ["driver.js@1.4.0", "", {}, "sha512-Gm64jm6PmcU+si21sQhBrTAM1JvUrR0QhNmjkprNLxohOBzul9+pNHXgQaT9lW84gwg9GMLB3NZGuGolsz5uew=="], + "drizzle-kit": ["drizzle-kit@0.30.6", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.19.7", "esbuild-register": "^3.5.0", "gel": "^2.0.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-U4wWit0fyZuGuP7iNmRleQyK2V8wCuv57vf5l3MnG4z4fzNTjY/U13M8owyQ5RavqvqxBifWORaR3wIUzlN64g=="], "drizzle-orm": ["drizzle-orm@0.41.0", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-7A4ZxhHk9gdlXmTdPj/lREtP+3u8KvZ4yEN6MYVxBzZGex5Wtdc+CWSbu7btgF6TB0N+MNPrvW7RKBbxJchs/Q=="], @@ -1085,6 +1093,8 @@ "jose": ["jose@6.0.12", "", {}, "sha512-T8xypXs8CpmiIi78k0E+Lk7T2zlK4zDyg+o1CZ4AkOHgDg98ogdP2BeZ61lTFKFyoEwJ9RgAgN+SdM3iPgNonQ=="], + "js-cookie": ["js-cookie@3.0.5", "", {}, "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw=="], + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="], @@ -1185,6 +1195,8 @@ "next-auth": ["next-auth@5.0.0-beta.29", "", { "dependencies": { "@auth/core": "0.40.0" }, "peerDependencies": { "@simplewebauthn/browser": "^9.0.1", "@simplewebauthn/server": "^9.0.2", "next": "^14.0.0-0 || ^15.0.0-0", "nodemailer": "^6.6.5", "react": "^18.2.0 || ^19.0.0-0" }, "optionalPeers": ["@simplewebauthn/browser", "@simplewebauthn/server", "nodemailer"] }, "sha512-Ukpnuk3NMc/LiOl32njZPySk7pABEzbjhMUFd5/n10I0ZNC7NCuVv8IY2JgbDek2t/PUOifQEoUiOOTLy4os5A=="], + "next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="], + "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], diff --git a/package.json b/package.json index 607d970..adf5f0a 100755 --- a/package.json +++ b/package.json @@ -55,17 +55,21 @@ "@trpc/client": "^11.0.0", "@trpc/react-query": "^11.0.0", "@trpc/server": "^11.0.0", + "@types/js-cookie": "^3.0.6", "@types/ws": "^8.18.1", "bcryptjs": "^3.0.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "cmdk": "^1.1.1", "date-fns": "^4.1.0", + "driver.js": "^1.4.0", "drizzle-orm": "^0.41.0", + "js-cookie": "^3.0.5", "lucide-react": "^0.536.0", "minio": "^8.0.6", "next": "^16.0.10", "next-auth": "^5.0.0-beta.29", + "next-themes": "^0.4.6", "postgres": "^3.4.4", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/src/app/(dashboard)/layout.tsx b/src/app/(dashboard)/layout.tsx index 4be18b2..830f52a 100755 --- a/src/app/(dashboard)/layout.tsx +++ b/src/app/(dashboard)/layout.tsx @@ -13,6 +13,7 @@ import { BreadcrumbDisplay, } from "~/components/ui/breadcrumb-provider"; import { StudyProvider } from "~/lib/study-context"; +import { TourProvider } from "~/components/onboarding/TourProvider"; interface DashboardLayoutProps { children: React.ReactNode; @@ -41,23 +42,25 @@ export default async function DashboardLayout({ return ( - - - - -
-
- - - + + + + + +
+
+ + + +
+
+
+ {children}
-
-
- {children} -
-
-
-
+ + + +
); } diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx index a27f097..2b1c5fa 100755 --- a/src/app/dashboard/page.tsx +++ b/src/app/dashboard/page.tsx @@ -11,6 +11,7 @@ import { Calendar, CheckCircle2, Clock, + HelpCircle, LayoutDashboard, MoreHorizontal, Play, @@ -47,8 +48,10 @@ import { import { Badge } from "~/components/ui/badge"; import { ScrollArea } from "~/components/ui/scroll-area"; import { api } from "~/trpc/react"; +import { useTour } from "~/components/onboarding/TourProvider"; export default function DashboardPage() { + const { startTour } = useTour(); const [studyFilter, setStudyFilter] = React.useState(null); // --- Data Fetching --- @@ -81,7 +84,7 @@ export default function DashboardPage() { return (
{/* Header Section */} -
+

Dashboard

@@ -90,6 +93,9 @@ export default function DashboardPage() {

+ -
{/* Stats Cards */} -
+
{/* Scheduled Trials */} - +
@@ -252,7 +258,7 @@ export default function DashboardPage() {
{/* Recent Activity */} - + Recent Activity diff --git a/src/components/dashboard/app-sidebar.tsx b/src/components/dashboard/app-sidebar.tsx index 712295a..52e643e 100755 --- a/src/components/dashboard/app-sidebar.tsx +++ b/src/components/dashboard/app-sidebar.tsx @@ -276,7 +276,7 @@ export function AppSidebar({ - + {selectedStudy?.name ?? "Select Study"} @@ -325,7 +325,7 @@ export function AppSidebar({ ) : ( - + {selectedStudy?.name ?? "Select Study"} @@ -383,7 +383,11 @@ export function AppSidebar({ (item.url !== "/dashboard" && pathname.startsWith(item.url)); const menuButton = ( - + {item.title} @@ -425,7 +429,11 @@ export function AppSidebar({ pathname.startsWith(item.url)); const menuButton = ( - + {item.title} diff --git a/src/components/experiments/designer/DesignerRoot.tsx b/src/components/experiments/designer/DesignerRoot.tsx index 73e0aa4..af82a87 100755 --- a/src/components/experiments/designer/DesignerRoot.tsx +++ b/src/components/experiments/designer/DesignerRoot.tsx @@ -8,10 +8,11 @@ import React, { useState, } from "react"; import { toast } from "sonner"; -import { Play, RefreshCw } from "lucide-react"; +import { Play, RefreshCw, HelpCircle } from "lucide-react"; import { cn } from "~/lib/utils"; import { PageHeader } from "~/components/ui/page-header"; +import { useTour } from "~/components/onboarding/TourProvider"; import { Button } from "~/components/ui/button"; import { api } from "~/trpc/react"; @@ -151,6 +152,8 @@ export function DesignerRoot({ autoCompile = true, onPersist, }: DesignerRootProps) { + const { startTour } = useTour(); + /* ----------------------------- Remote Experiment ------------------------- */ const { data: experiment, @@ -899,18 +902,25 @@ export function DesignerRoot({ /* ------------------------------- Panels ---------------------------------- */ const leftPanel = useMemo( () => ( -
+
), [], ); - const centerPanel = useMemo(() => , []); + const centerPanel = useMemo( + () => ( +
+ +
+ ), + [], + ); const rightPanel = useMemo( () => ( -
+
+