chore: Reroute to new onboarding flow
This commit is contained in:
parent
41da624986
commit
839c960034
@ -4,7 +4,6 @@
|
|||||||
"version": "0.6.6",
|
"version": "0.6.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"ios:iphone16": "react-native run-ios --simulator=\"iPhone 16 (iOS 18.6)\"",
|
|
||||||
"dev": "vite --port 1422",
|
"dev": "vite --port 1422",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
"lint": "eslint .",
|
"lint": "eslint .",
|
||||||
|
|||||||
@ -2,16 +2,18 @@ import { useEffect, useState } from 'react'
|
|||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
|
||||||
interface SplashScreenProps {
|
interface SplashScreenProps {
|
||||||
onComplete: () => void
|
onComplete?: () => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SplashScreen({ onComplete }: SplashScreenProps) {
|
export function SplashScreen({ onComplete }: SplashScreenProps = {}) {
|
||||||
const [isVisible, setIsVisible] = useState(true)
|
const [isVisible, setIsVisible] = useState(true)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
setIsVisible(false)
|
setIsVisible(false)
|
||||||
|
if (onComplete) {
|
||||||
setTimeout(onComplete, 300) // Wait for fade out animation
|
setTimeout(onComplete, 300) // Wait for fade out animation
|
||||||
|
}
|
||||||
}, 2000)
|
}, 2000)
|
||||||
|
|
||||||
return () => clearTimeout(timer)
|
return () => clearTimeout(timer)
|
||||||
|
|||||||
@ -12,6 +12,8 @@
|
|||||||
|
|
||||||
import { Route as rootRoute } from './routes/__root'
|
import { Route as rootRoute } from './routes/__root'
|
||||||
import { Route as SettingsImport } from './routes/settings'
|
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'
|
import { Route as IndexImport } from './routes/index'
|
||||||
|
|
||||||
// Create/Update Routes
|
// Create/Update Routes
|
||||||
@ -22,6 +24,18 @@ const SettingsRoute = SettingsImport.update({
|
|||||||
getParentRoute: () => rootRoute,
|
getParentRoute: () => rootRoute,
|
||||||
} as any)
|
} 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({
|
const IndexRoute = IndexImport.update({
|
||||||
id: '/',
|
id: '/',
|
||||||
path: '/',
|
path: '/',
|
||||||
@ -39,6 +53,20 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof IndexImport
|
preLoaderRoute: typeof IndexImport
|
||||||
parentRoute: typeof rootRoute
|
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': {
|
'/settings': {
|
||||||
id: '/settings'
|
id: '/settings'
|
||||||
path: '/settings'
|
path: '/settings'
|
||||||
@ -53,36 +81,46 @@ declare module '@tanstack/react-router' {
|
|||||||
|
|
||||||
export interface FileRoutesByFullPath {
|
export interface FileRoutesByFullPath {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
|
'/chat': typeof ChatRoute
|
||||||
|
'/onboarding': typeof OnboardingRoute
|
||||||
'/settings': typeof SettingsRoute
|
'/settings': typeof SettingsRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileRoutesByTo {
|
export interface FileRoutesByTo {
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
|
'/chat': typeof ChatRoute
|
||||||
|
'/onboarding': typeof OnboardingRoute
|
||||||
'/settings': typeof SettingsRoute
|
'/settings': typeof SettingsRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileRoutesById {
|
export interface FileRoutesById {
|
||||||
__root__: typeof rootRoute
|
__root__: typeof rootRoute
|
||||||
'/': typeof IndexRoute
|
'/': typeof IndexRoute
|
||||||
|
'/chat': typeof ChatRoute
|
||||||
|
'/onboarding': typeof OnboardingRoute
|
||||||
'/settings': typeof SettingsRoute
|
'/settings': typeof SettingsRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface FileRouteTypes {
|
export interface FileRouteTypes {
|
||||||
fileRoutesByFullPath: FileRoutesByFullPath
|
fileRoutesByFullPath: FileRoutesByFullPath
|
||||||
fullPaths: '/' | '/settings'
|
fullPaths: '/' | '/chat' | '/onboarding' | '/settings'
|
||||||
fileRoutesByTo: FileRoutesByTo
|
fileRoutesByTo: FileRoutesByTo
|
||||||
to: '/' | '/settings'
|
to: '/' | '/chat' | '/onboarding' | '/settings'
|
||||||
id: '__root__' | '/' | '/settings'
|
id: '__root__' | '/' | '/chat' | '/onboarding' | '/settings'
|
||||||
fileRoutesById: FileRoutesById
|
fileRoutesById: FileRoutesById
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RootRouteChildren {
|
export interface RootRouteChildren {
|
||||||
IndexRoute: typeof IndexRoute
|
IndexRoute: typeof IndexRoute
|
||||||
|
ChatRoute: typeof ChatRoute
|
||||||
|
OnboardingRoute: typeof OnboardingRoute
|
||||||
SettingsRoute: typeof SettingsRoute
|
SettingsRoute: typeof SettingsRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
const rootRouteChildren: RootRouteChildren = {
|
const rootRouteChildren: RootRouteChildren = {
|
||||||
IndexRoute: IndexRoute,
|
IndexRoute: IndexRoute,
|
||||||
|
ChatRoute: ChatRoute,
|
||||||
|
OnboardingRoute: OnboardingRoute,
|
||||||
SettingsRoute: SettingsRoute,
|
SettingsRoute: SettingsRoute,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,12 +135,20 @@ export const routeTree = rootRoute
|
|||||||
"filePath": "__root.tsx",
|
"filePath": "__root.tsx",
|
||||||
"children": [
|
"children": [
|
||||||
"/",
|
"/",
|
||||||
|
"/chat",
|
||||||
|
"/onboarding",
|
||||||
"/settings"
|
"/settings"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"/": {
|
"/": {
|
||||||
"filePath": "index.tsx"
|
"filePath": "index.tsx"
|
||||||
},
|
},
|
||||||
|
"/chat": {
|
||||||
|
"filePath": "chat.tsx"
|
||||||
|
},
|
||||||
|
"/onboarding": {
|
||||||
|
"filePath": "onboarding.tsx"
|
||||||
|
},
|
||||||
"/settings": {
|
"/settings": {
|
||||||
"filePath": "settings.tsx"
|
"filePath": "settings.tsx"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,55 @@
|
|||||||
import { createRootRoute, Outlet } from '@tanstack/react-router'
|
import { createRootRoute, Outlet } from '@tanstack/react-router'
|
||||||
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
|
import { TanStackRouterDevtools } from '@tanstack/router-devtools'
|
||||||
import { Toaster } from 'sonner'
|
import { Toaster } from 'sonner'
|
||||||
|
import { useState, useEffect } from 'react'
|
||||||
|
|
||||||
export const Route = createRootRoute({
|
export const Route = createRootRoute({
|
||||||
component: () => (
|
component: RootLayout,
|
||||||
<div className="h-full flex flex-col overflow-hidden">
|
})
|
||||||
|
|
||||||
|
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 />
|
<Outlet />
|
||||||
<Toaster position="top-center" />
|
<Toaster position="top-center" />
|
||||||
{process.env.NODE_ENV === 'development' && (
|
{process.env.NODE_ENV === 'development' && (
|
||||||
<TanStackRouterDevtools position="bottom-right" />
|
<TanStackRouterDevtools position="bottom-right" />
|
||||||
)}
|
)}
|
||||||
</div>
|
</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 { createFileRoute, useNavigate } from '@tanstack/react-router'
|
||||||
import { App } from '@/components/App'
|
import { useEffect, useState } from 'react'
|
||||||
|
import { SplashScreen } from '@/components/SplashScreen'
|
||||||
|
import { ChatScreen } from '@/components/ChatScreen'
|
||||||
|
|
||||||
export const Route = createFileRoute('/')({
|
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