@@ -31,6 +31,9 @@ import { GoogleIcon } from '@dailydotdev/shared/src/components/icons/Google';
3131import { MiniCloseIcon } from '@dailydotdev/shared/src/components/icons/MiniClose' ;
3232import { PhoneIcon } from '@dailydotdev/shared/src/components/icons/Phone' ;
3333import { ArrowIcon } from '@dailydotdev/shared/src/components/icons/Arrow' ;
34+ import { EditTag } from '@dailydotdev/shared/src/components/onboarding/EditTag' ;
35+ import { REQUIRED_TAGS_THRESHOLD } from '@dailydotdev/shared/src/components/onboarding/common' ;
36+ import useFeedSettings from '@dailydotdev/shared/src/hooks/useFeedSettings' ;
3437import {
3538 useViewSize ,
3639 ViewSize ,
@@ -145,6 +148,7 @@ export type OnboardingStep =
145148 | 'chooser'
146149 | 'auth'
147150 | 'importing'
151+ | 'tags'
148152 | 'extension'
149153 | 'complete' ;
150154
@@ -204,13 +208,15 @@ const FINISHING_ANIMATION_MS = 1500;
204208
205209export const OnboardingV2 = ( ) : ReactElement => {
206210 const router = useRouter ( ) ;
207- const { showLogin, isLoggedIn, isAuthReady, isAndroidApp } = useAuthContext ( ) ;
211+ const { showLogin, isLoggedIn, isAuthReady, isAndroidApp, user } =
212+ useAuthContext ( ) ;
208213 const { applyThemeMode } = useSettingsContext ( ) ;
209214 const { completeAction } = useActions ( ) ;
210215 const { isOnboardingComplete, isOnboardingActionsReady } =
211216 useOnboardingActions ( ) ;
212217 const [ step , setStep ] = useState < OnboardingStep > ( 'hero' ) ;
213218 const { onEnablePush } = usePushNotificationMutation ( ) ;
219+ const { feedSettings } = useFeedSettings ( ) ;
214220 const isLaptop = useViewSize ( ViewSize . Laptop ) ;
215221 const isNativeApp = isIOSNative ( ) || ! ! isAndroidApp ;
216222 const mobileStoreUrl = useMemo ( ( ) => {
@@ -318,10 +324,24 @@ export const OnboardingV2 = (): ReactElement => {
318324 setSignupContext ( null ) ;
319325 }
320326
327+ const hasNoTags =
328+ apiResult . status !== 'fulfilled' || ! apiResult . value ?. length ;
329+
330+ if ( hasNoTags ) {
331+ setAiPrompt ( '' ) ;
332+ setSignupContext ( null ) ;
333+ router . replace ( {
334+ pathname : `${ webappUrl } onboarding` ,
335+ query : { step : 'tags' } ,
336+ } ) ;
337+ setStep ( 'tags' ) ;
338+ return ;
339+ }
340+
321341 setImportProgress ( 68 ) ;
322342 setImportPhase ( 'awaitingSeniority' ) ;
323343 } ,
324- [ clearImportTimers , aiPrompt , setAiPrompt , setSignupContext ] ,
344+ [ clearImportTimers , aiPrompt , setAiPrompt , setSignupContext , router ] ,
325345 ) ;
326346
327347 const startImportFlowGithub = useCallback ( ( ) => {
@@ -415,14 +435,29 @@ export const OnboardingV2 = (): ReactElement => {
415435 if (
416436 ! isAuthReady ||
417437 (
418- [ 'auth' , 'importing' , 'extension' , 'complete' ] as OnboardingStep [ ]
438+ [
439+ 'auth' ,
440+ 'importing' ,
441+ 'tags' ,
442+ 'extension' ,
443+ 'complete' ,
444+ ] as OnboardingStep [ ]
419445 ) . includes ( step )
420446 ) {
421447 return ;
422448 }
423449
424450 const urlStep = router . query . step as string | undefined ;
425451
452+ if ( urlStep === 'tags' ) {
453+ if ( ! isLoggedIn ) {
454+ router . replace ( `${ webappUrl } onboarding` ) ;
455+ return ;
456+ }
457+ setStep ( 'tags' ) ;
458+ return ;
459+ }
460+
426461 if ( urlStep === 'complete' ) {
427462 if ( ! isLoggedIn ) {
428463 router . replace ( `${ webappUrl } onboarding` ) ;
@@ -1567,6 +1602,52 @@ export const OnboardingV2 = (): ReactElement => {
15671602 </ div >
15681603 ) }
15691604
1605+ { /* ── Tag Selection Fallback ── */ }
1606+ { step === 'tags' && (
1607+ < div
1608+ className = "fixed inset-0 z-modal flex items-end tablet:items-center tablet:justify-center tablet:p-4"
1609+ role = "dialog"
1610+ aria-modal = "true"
1611+ aria-label = "Select your tags"
1612+ >
1613+ < div className = "bg-black/70 absolute inset-0 backdrop-blur-sm" />
1614+ < div className = "relative z-1 flex max-h-[90dvh] w-full flex-col overflow-y-auto rounded-t-24 border border-white/[0.08] bg-background-default p-6 shadow-[0_32px_90px_rgba(0,0,0,0.58)] tablet:max-w-2xl tablet:rounded-24" >
1615+ < EditTag
1616+ feedSettings = { feedSettings }
1617+ userId = { user ?. id || '' }
1618+ headline = "Pick tags that are relevant to you"
1619+ hidePreview
1620+ />
1621+ < button
1622+ type = "button"
1623+ disabled = {
1624+ ( feedSettings ?. includeTags ?. length || 0 ) <
1625+ REQUIRED_TAGS_THRESHOLD
1626+ }
1627+ onClick = { ( ) => {
1628+ completeAction ( ActionType . CompletedOnboarding ) ;
1629+ completeAction ( ActionType . EditTag ) ;
1630+ completeAction ( ActionType . ContentTypes ) ;
1631+ router . replace ( {
1632+ pathname : `${ webappUrl } onboarding` ,
1633+ query : { step : 'complete' } ,
1634+ } ) ;
1635+ setStep ( showExtensionCta ? 'extension' : 'complete' ) ;
1636+ } }
1637+ className = "mx-auto mt-6 rounded-14 bg-white px-8 py-3 font-bold text-black transition-all duration-200 typo-callout hover:-translate-y-0.5 hover:shadow-[0_8px_28px_rgba(255,255,255,0.12)] disabled:cursor-not-allowed disabled:opacity-40"
1638+ >
1639+ { ( feedSettings ?. includeTags ?. length || 0 ) >=
1640+ REQUIRED_TAGS_THRESHOLD
1641+ ? 'Continue'
1642+ : `Select ${
1643+ REQUIRED_TAGS_THRESHOLD -
1644+ ( feedSettings ?. includeTags ?. length || 0 )
1645+ } more tags`}
1646+ </ button >
1647+ </ div >
1648+ </ div >
1649+ ) }
1650+
15701651 { /* ── Extension Promotion Overlay ── */ }
15711652 { step === 'extension' && (
15721653 < div
0 commit comments