Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions messages/en.context.json
Original file line number Diff line number Diff line change
Expand Up @@ -3098,6 +3098,7 @@
"app-onboarding-name-step-title": "Used in app onboarding details wizard. Role: step title. Translate for UI; keep Capgo product names, code, and placeholders unchanged.",
"app-onboarding-remove-icon": "Used in app onboarding details wizard. Role: button label. Translate for UI; keep Capgo product names, code, and placeholders unchanged.",
"app-onboarding-skip-app-id": "Used in app onboarding details wizard. Role: button label that accepts Capgo's generated App ID. Translate for UI; keep Capgo product names, code, and placeholders unchanged.",
"app-onboarding-skip-icon": "Used in app onboarding details wizard. Role: button label that continues without an optional app icon. Translate for UI; keep Capgo product names, code, and placeholders unchanged.",
"app-onboarding-toast-store-icon-error": "Used in app onboarding details wizard. Role: error toast. Translate for UI; keep Capgo product names, code, and placeholders unchanged.",
"app-onboarding-use-different-icon": "Used in app onboarding details wizard. Role: section label. Translate for UI; keep Capgo product names, code, and placeholders unchanged.",
"app-onboarding-use-imported-icon": "Used in app onboarding details wizard. Role: button label. Translate for UI; keep Capgo product names, code, and placeholders unchanged.",
Expand Down
1 change: 1 addition & 0 deletions messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -518,6 +518,7 @@
"app-onboarding-store-link-placeholder": "https://apps.apple.com/... or https://play.google.com/store/apps/details?id=com.example.app",
"app-onboarding-store-screenshot-alt": "Store screenshot preview",
"app-onboarding-skip-app-id": "Skip",
"app-onboarding-skip-icon": "Skip",
Comment thread
WcaleNieWolny marked this conversation as resolved.
"app-onboarding-subtitle": "The app is created immediately in Capgo. From there you can either connect your real project in the CLI or explore the dashboard with temporary demo data.",
"app-onboarding-summary-method": "Setup method",
"app-onboarding-summary-source": "Starting point",
Expand Down
17 changes: 10 additions & 7 deletions src/components/dashboard/AppOnboardingFlow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,15 @@ const suggestedAppId = computed(() => {
})
const generatedAppId = computed(() => createdApp.value?.app_id || manualAppId.value.trim() || suggestedAppId.value)
const hasProvidedAppId = computed(() => Boolean(manualAppId.value.trim() || importedStoreAppId.value.trim()))
const appDetailsPrimaryActionLabel = computed(() => {
if (appDetailsStep.value === 'icon')
return iconPreview.value ? t('app-onboarding-continue') : t('app-onboarding-skip-icon')

if (appDetailsStep.value === 'app_id' && !hasProvidedAppId.value)
return t('app-onboarding-skip-app-id')

return t('app-onboarding-continue')
})
const appNameInitial = computed(() => Array.from(appName.value.trim())[0]?.toLocaleUpperCase() ?? '')
const selectedAppIdSource = computed<NonNullable<OnboardingDetailsEventProperties['app_id_source']>>(() => {
if (manualAppId.value.trim())
Expand Down Expand Up @@ -2446,13 +2455,7 @@ defineExpose({
@click="continueFromCurrentAppDetailsStep"
>
<IconLoader v-if="isSubmitting" class="h-4 w-4 animate-spin" />
<span v-else>{{ appDetailsStep === 'icon'
? props.preOrg
? t('app-onboarding-continue')
: t('app-onboarding-finish-details')
: appDetailsStep === 'app_id' && !hasProvidedAppId
? t('app-onboarding-skip-app-id')
: t('app-onboarding-continue') }}</span>
<span v-else>{{ appDetailsPrimaryActionLabel }}</span>
<IconArrowRight v-if="!isSubmitting" class="h-4 w-4" />
</button>
</div>
Expand Down
10 changes: 2 additions & 8 deletions src/components/dashboard/AppOnboardingWelcome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ const { t } = useI18n()
.onboarding-welcome {
isolation: isolate;
background:
radial-gradient(circle at 50% 40%, rgb(59 130 246 / 12%), transparent 29rem),
linear-gradient(180deg, #fff 0%, #f8fafc 58%, #f1f5f9 100%);
radial-gradient(circle at 50% 40%, rgb(59 130 246 / 14%), transparent 29rem),
linear-gradient(180deg, var(--color-base-100) 0%, var(--color-base-200) 58%, var(--color-base-300) 100%);
}

.onboarding-welcome::before,
Expand Down Expand Up @@ -177,12 +177,6 @@ const { t } = useI18n()
z-index: 1;
}

:global(.dark) .onboarding-welcome {
background:
radial-gradient(circle at 50% 40%, rgb(59 130 246 / 18%), transparent 29rem),
linear-gradient(180deg, #020617 0%, #0f172a 58%, #111827 100%);
}

@keyframes onboarding-status-pulse {
0%,
34% {
Expand Down
15 changes: 12 additions & 3 deletions tests/app-onboarding-v3.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'

const onboardingSource = readFileSync(new URL('../src/components/dashboard/AppOnboardingFlow.vue', import.meta.url), 'utf8')
const iconInputSource = readFileSync(new URL('../src/components/dashboard/AppOnboardingIconInput.vue', import.meta.url), 'utf8')
const messages = JSON.parse(readFileSync(new URL('../messages/en.json', import.meta.url), 'utf8')) as Record<string, string>

function sliceBetween(source: string, startMarker: string, endMarker: string) {
const start = source.indexOf(startMarker)
Expand Down Expand Up @@ -152,9 +153,17 @@ describe('pre-organization onboarding v3', () => {
expect(onboardingSource.match(/:disabled="isAppDetailsNavigationPending"/g)).toHaveLength(2)
})

it.concurrent('continues to organization creation after the pre-org icon step', () => {
expect(onboardingSource).toContain("t('app-onboarding-continue')")
expect(onboardingSource).toContain("t('app-onboarding-finish-details')")
it.concurrent('labels the icon action as skip until an icon is provided', () => {
const iconAction = sliceBetween(onboardingSource, ':data-test="appDetailsStep === \'app_id\'', '<IconArrowRight v-if="!isSubmitting"')
const primaryActionLabel = sliceBetween(onboardingSource, 'const appDetailsPrimaryActionLabel = computed(() => {', 'const appNameInitial = computed')

expect(messages['app-onboarding-skip-icon']).toBe('Skip')
expect(primaryActionLabel).toContain("if (appDetailsStep.value === 'icon')")
expect(primaryActionLabel).toContain("return iconPreview.value ? t('app-onboarding-continue') : t('app-onboarding-skip-icon')")
expect(primaryActionLabel).toContain("if (appDetailsStep.value === 'app_id' && !hasProvidedAppId.value)")
expect(primaryActionLabel).toContain("return t('app-onboarding-skip-app-id')")
expect(iconAction).toContain('{{ appDetailsPrimaryActionLabel }}')
expect(iconAction).not.toContain("t('app-onboarding-finish-details')")
})

it.concurrent('does not send raw onboarding field values to analytics', () => {
Expand Down
11 changes: 11 additions & 0 deletions tests/app-onboarding-welcome.unit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ describe('app onboarding welcome', () => {
expect(source).not.toContain('Takes about')
})

it.concurrent('uses DaisyUI theme colors for the welcome canvas', async () => {
const source = await readFile(new URL('../src/components/dashboard/AppOnboardingWelcome.vue', import.meta.url), 'utf8')
const welcomeRule = source.match(/\.onboarding-welcome\s*\{([\s\S]*?)\n\}/)?.[1] ?? ''
const backgroundDeclaration = welcomeRule.match(/background:\s*([\s\S]*?);/)?.[1] ?? ''

expect(backgroundDeclaration).toContain('var(--color-base-100)')
expect(backgroundDeclaration).toContain('var(--color-base-200)')
expect(backgroundDeclaration).toContain('var(--color-base-300)')
expect(source).not.toContain(':global(.dark) .onboarding-welcome')
})
Comment thread
coderabbitai[bot] marked this conversation as resolved.

it.concurrent('shows only for fresh or restarted desktop pre-organization onboarding', async () => {
const source = await readFile(new URL('../src/components/dashboard/AppOnboardingFlow.vue', import.meta.url), 'utf8')
const resumeFlow = source.slice(
Expand Down
Loading