chore: Reroute to new onboarding flow
This commit is contained in:
parent
41da624986
commit
839c960034
@ -4,7 +4,6 @@
|
||||
"version": "0.6.6",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"ios:iphone16": "react-native run-ios --simulator=\"iPhone 16 (iOS 18.6)\"",
|
||||
"dev": "vite --port 1422",
|
||||
"build": "tsc -b && vite build",
|
||||
"lint": "eslint .",
|
||||
|
||||
@ -2,16 +2,18 @@ import { useEffect, useState } from 'react'
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
interface SplashScreenProps {
|
||||
onComplete: () => void
|
||||
onComplete?: () => void
|
||||
}
|
||||
|
||||
export function SplashScreen({ onComplete }: SplashScreenProps) {
|
||||
export function SplashScreen({ onComplete }: SplashScreenProps = {}) {
|
||||
const [isVisible, setIsVisible] = useState(true)
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setTimeout(() => {
|
||||
setIsVisible(false)
|
||||
setTimeout(onComplete, 300) // Wait for fade out animation
|
||||
if (onComplete) {
|
||||
setTimeout(onComplete, 300) // Wait for fade out animation
|
||||
}
|
||||
}, 2000)
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
|
||||
@ -12,6 +12,8 @@
|
||||
|
||||
import { Route as rootRoute } from './routes/__root'
|
||||
import { Route as SettingsImport } from './routes/settings'
|
||||
import { Route as OnboardingImport } from './routes/onboarding'
|
||||
import { Route as ChatImport } from './routes/chat'
|
||||
import { Route as IndexImport } from './routes/index'
|
||||
|
||||
// Create/Update Routes
|
||||
@ -22,6 +24,18 @@ const SettingsRoute = SettingsImport.update({
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const OnboardingRoute = OnboardingImport.update({
|
||||
id: '/onboarding',
|
||||
path: '/onboarding',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const ChatRoute = ChatImport.update({
|
||||
id: '/chat',
|
||||
path: '/chat',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any)
|
||||
|
||||
const IndexRoute = IndexImport.update({
|
||||
id: '/',
|
||||
path: '/',
|
||||
@ -39,6 +53,20 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof IndexImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/chat': {
|
||||
id: '/chat'
|
||||
path: '/chat'
|
||||
fullPath: '/chat'
|
||||
preLoaderRoute: typeof ChatImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/onboarding': {
|
||||
id: '/onboarding'
|
||||
path: '/onboarding'
|
||||
fullPath: '/onboarding'
|
||||
preLoaderRoute: typeof OnboardingImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/settings': {
|
||||
id: '/settings'
|
||||
path: '/settings'
|
||||
@ -53,36 +81,46 @@ declare module '@tanstack/react-router' {
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexRoute
|
||||
'/chat': typeof ChatRoute
|
||||
'/onboarding': typeof OnboardingRoute
|
||||
'/settings': typeof SettingsRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesByTo {
|
||||
'/': typeof IndexRoute
|
||||
'/chat': typeof ChatRoute
|
||||
'/onboarding': typeof OnboardingRoute
|
||||
'/settings': typeof SettingsRoute
|
||||
}
|
||||
|
||||
export interface FileRoutesById {
|
||||
__root__: typeof rootRoute
|
||||
'/': typeof IndexRoute
|
||||
'/chat': typeof ChatRoute
|
||||
'/onboarding': typeof OnboardingRoute
|
||||
'/settings': typeof SettingsRoute
|
||||
}
|
||||
|
||||
export interface FileRouteTypes {
|
||||
fileRoutesByFullPath: FileRoutesByFullPath
|
||||
fullPaths: '/' | '/settings'
|
||||
fullPaths: '/' | '/chat' | '/onboarding' | '/settings'
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to: '/' | '/settings'
|
||||
id: '__root__' | '/' | '/settings'
|
||||
to: '/' | '/chat' | '/onboarding' | '/settings'
|
||||
id: '__root__' | '/' | '/chat' | '/onboarding' | '/settings'
|
||||
fileRoutesById: FileRoutesById
|
||||
}
|
||||
|
||||
export interface RootRouteChildren {
|
||||
IndexRoute: typeof IndexRoute
|
||||
ChatRoute: typeof ChatRoute
|
||||
OnboardingRoute: typeof OnboardingRoute
|
||||
SettingsRoute: typeof SettingsRoute
|
||||
}
|
||||
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
IndexRoute: IndexRoute,
|
||||
ChatRoute: ChatRoute,
|
||||
OnboardingRoute: OnboardingRoute,
|
||||
SettingsRoute: SettingsRoute,
|
||||
}
|
||||
|
||||
@ -97,12 +135,20 @@ export const routeTree = rootRoute
|
||||
"filePath": "__root.tsx",
|
||||
"children": [
|
||||
"/",
|
||||
"/chat",
|
||||
"/onboarding",
|
||||
"/settings"
|
||||
]
|
||||
},
|
||||
"/": {
|
||||
"filePath": "index.tsx"
|
||||
},
|
||||
"/chat": {
|
||||
"filePath": "chat.tsx"
|
||||
},
|
||||
"/onboarding": {
|
||||
"filePath": "onboarding.tsx"
|
||||
},
|
||||
"/settings": {
|
||||
"filePath": "settings.tsx"
|
||||
}
|
||||
|
||||
@ -1,15 +1,55 @@
|
||||
import { createRootRoute, Outlet } from '@tanstack/react-router'
|
||||
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
|
||||
import { Toaster } from 'sonner'
|
||||
import { useState, useEffect } from 'react'
|
||||
|
||||
export const Route = createRootRoute({
|
||||
component: () => (
|
||||
<div className="h-full flex flex-col overflow-hidden">
|
||||
component: RootLayout,
|
||||
})
|
||||
|
||||
function RootLayout() {
|
||||
const [isInitialized, setIsInitialized] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
// Initialize mobile app
|
||||
setIsInitialized(true)
|
||||
}, [])
|
||||
|
||||
if (!isInitialized) {
|
||||
return (
|
||||
<div className="h-full flex items-center justify-center bg-background">
|
||||
<div className="text-center">
|
||||
<div className="w-16 h-16 mx-auto mb-4">
|
||||
<svg className="animate-spin h-16 w-16 text-primary" viewBox="0 0 24 24">
|
||||
<circle
|
||||
className="opacity-25"
|
||||
cx="12"
|
||||
cy="12"
|
||||
r="10"
|
||||
stroke="currentColor"
|
||||
strokeWidth="4"
|
||||
fill="none"
|
||||
/>
|
||||
<path
|
||||
className="opacity-75"
|
||||
fill="currentColor"
|
||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<p className="text-muted-foreground">Loading Jan Mobile...</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col overflow-hidden bg-background">
|
||||
<Outlet />
|
||||
<Toaster position="top-center" />
|
||||
{process.env.NODE_ENV === 'development' && (
|
||||
<TanStackRouterDevtools position="bottom-right" />
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
})
|
||||
)
|
||||
}
|
||||
10
mobile-app/src/routes/chat.tsx
Normal file
10
mobile-app/src/routes/chat.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { ChatScreen } from '@/components/ChatScreen'
|
||||
|
||||
export const Route = createFileRoute('/chat')({
|
||||
component: ChatPage,
|
||||
})
|
||||
|
||||
function ChatPage() {
|
||||
return <ChatScreen />
|
||||
}
|
||||
@ -1,6 +1,56 @@
|
||||
import { createFileRoute } from '@tanstack/react-router'
|
||||
import { App } from '@/components/App'
|
||||
import { createFileRoute, useNavigate } from '@tanstack/react-router'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { SplashScreen } from '@/components/SplashScreen'
|
||||
import { ChatScreen } from '@/components/ChatScreen'
|
||||
|
||||
export const Route = createFileRoute('/')({
|
||||
component: App,
|
||||
})
|
||||
component: HomePage,
|
||||
})
|
||||
|
||||
function HomePage() {
|
||||
const [showSplash, setShowSplash] = useState(true)
|
||||
const [isNavigating, setIsNavigating] = useState(false)
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(() => {
|
||||
// Check if user has completed onboarding
|
||||
const hasCompletedOnboarding = localStorage.getItem('jan_onboarding_completed')
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
setShowSplash(false)
|
||||
if (!hasCompletedOnboarding) {
|
||||
setIsNavigating(true)
|
||||
navigate({ to: '/onboarding' })
|
||||
}
|
||||
}, 2300)
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
}, [navigate])
|
||||
|
||||
if (showSplash) {
|
||||
return <SplashScreen />
|
||||
}
|
||||
|
||||
if (isNavigating) {
|
||||
return (
|
||||
<div className="h-full flex items-center justify-center bg-background">
|
||||
<div className="text-center">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary mx-auto"></div>
|
||||
<p className="mt-4 text-muted-foreground">Setting up...</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const hasCompletedOnboarding = localStorage.getItem('jan_onboarding_completed')
|
||||
|
||||
if (!hasCompletedOnboarding) {
|
||||
return (
|
||||
<div className="h-full flex items-center justify-center bg-background">
|
||||
<p className="text-muted-foreground">Redirecting to onboarding...</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return <ChatScreen />
|
||||
}
|
||||
17
mobile-app/src/routes/onboarding.tsx
Normal file
17
mobile-app/src/routes/onboarding.tsx
Normal file
@ -0,0 +1,17 @@
|
||||
import { createFileRoute, useNavigate } from '@tanstack/react-router'
|
||||
import { OnboardingScreen } from '@/components/OnboardingScreen'
|
||||
|
||||
export const Route = createFileRoute('/onboarding')({
|
||||
component: OnboardingPage,
|
||||
})
|
||||
|
||||
function OnboardingPage() {
|
||||
const navigate = useNavigate()
|
||||
|
||||
const handleOnboardingComplete = () => {
|
||||
localStorage.setItem('jan_onboarding_completed', 'true')
|
||||
navigate({ to: '/' })
|
||||
}
|
||||
|
||||
return <OnboardingScreen onComplete={handleOnboardingComplete} />
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user