[Home Page] Add a simple onboarding slot to Home, focused on "manage my team" intent#86663
Conversation
|
Hey, I noticed you changed If you want to automatically generate translations for other locales, an Expensify employee will have to:
Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running: npx ts-node ./scripts/generateTranslations.ts --helpTypically, you'd want to translate only what you changed by running |
|
@ZhenjaHorbach Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 86257b0e54
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
src/pages/home/GettingStartedSection/utils/isWithinGettingStartedPeriod.ts
Outdated
Show resolved
Hide resolved
|
@adamgrzybowski @grgia |
🦜 Polyglot Parrot! 🦜Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues: View the translation diffdiff --git a/src/languages/de.ts b/src/languages/de.ts
index d1773b88..c0487851 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -1056,6 +1056,14 @@ const translations: TranslationDeepObject<typeof en> = {
inDays: () => ({one: 'In 1 Tag', other: (count: number) => `In ${count} Tagen`}),
today: 'Heute',
},
+ gettingStartedSection: {
+ title: 'Erste Schritte',
+ createWorkspace: 'Workspace erstellen',
+ connectAccounting: ({integrationName}: {integrationName: string}) => `Mit ${integrationName} verbinden`,
+ customizeCategories: 'Buchhaltungskategorien anpassen',
+ linkCompanyCards: 'Firmenkarten verknüpfen',
+ setupRules: 'Ausgabelimits einrichten',
+ },
},
allSettingsScreen: {
subscription: 'Abonnement',
@@ -7442,7 +7450,14 @@ Fordern Sie Spesendetails wie Belege und Beschreibungen an, legen Sie Limits und
searchIn: 'Suchen in',
searchPlaceholder: 'Nach etwas suchen',
suggestions: 'Vorschläge',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Vorschläge verfügbar${query ? ` für ${query}` : ''}. ${count} Ergebnis.`,
other: (resultCount: number) => `Vorschläge verfügbar${query ? ` für ${query}` : ''}. ${resultCount} Ergebnisse.`,
}),
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 0038fe53..44863588 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -1059,6 +1059,14 @@ const translations: TranslationDeepObject<typeof en> = {
inDays: () => ({one: 'Dans 1 jour', other: (count: number) => `Dans ${count} jours`}),
today: 'Aujourd’hui',
},
+ gettingStartedSection: {
+ title: 'Premiers pas',
+ createWorkspace: 'Créer un espace de travail',
+ connectAccounting: ({integrationName}: {integrationName: string}) => `Se connecter à ${integrationName}`,
+ customizeCategories: 'Personnaliser les catégories comptables',
+ linkCompanyCards: 'Lier des cartes d’entreprise',
+ setupRules: 'Configurer les règles de dépense',
+ },
},
allSettingsScreen: {
subscription: 'Abonnement',
@@ -7466,7 +7474,14 @@ Rendez obligatoires des informations de dépense comme les reçus et les descrip
searchIn: 'Rechercher dans',
searchPlaceholder: 'Rechercher quelque chose',
suggestions: 'Suggestions',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Suggestions disponibles${query ? ` pour ${query}` : ''}. ${count} résultat.`,
other: (resultCount: number) => `Suggestions disponibles${query ? ` pour ${query}` : ''}. ${resultCount} résultats.`,
}),
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 3cdcd967..66f08e95 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -1056,6 +1056,14 @@ const translations: TranslationDeepObject<typeof en> = {
inDays: () => ({one: 'Tra 1 giorno', other: (count: number) => `Tra ${count} giorni`}),
today: 'Oggi',
},
+ gettingStartedSection: {
+ title: 'Per iniziare',
+ createWorkspace: 'Crea uno spazio di lavoro',
+ connectAccounting: ({integrationName}: {integrationName: string}) => `Connetti a ${integrationName}`,
+ customizeCategories: 'Personalizza le categorie contabili',
+ linkCompanyCards: 'Collega carte aziendali',
+ setupRules: 'Configura le regole di spesa',
+ },
},
allSettingsScreen: {
subscription: 'Abbonamento',
@@ -7430,7 +7438,14 @@ Richiedi dettagli sulle spese come ricevute e descrizioni, imposta limiti e valo
searchIn: 'Cerca in',
searchPlaceholder: 'Cerca qualcosa',
suggestions: 'Suggerimenti',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Suggerimenti disponibili${query ? ` per ${query}` : ''}. ${count} risultato.`,
other: (resultCount: number) => `Suggerimenti disponibili${query ? ` per ${query}` : ''}. ${resultCount} risultati.`,
}),
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index d8d6b48c..1fa10b8e 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -1039,6 +1039,14 @@ const translations: TranslationDeepObject<typeof en> = {
inDays: () => ({one: '1日後', other: (count: number) => `${count}日後`}),
today: '今日',
},
+ gettingStartedSection: {
+ title: 'はじめに',
+ createWorkspace: 'ワークスペースを作成',
+ connectAccounting: ({integrationName}: {integrationName: string}) => `${integrationName}に接続する`,
+ customizeCategories: '会計カテゴリをカスタマイズする',
+ linkCompanyCards: '会社カードを連携',
+ setupRules: '支出ルールを設定',
+ },
},
allSettingsScreen: {
subscription: 'サブスクリプション',
@@ -7338,7 +7346,14 @@ ${reportName}
searchIn: '検索対象',
searchPlaceholder: '何かを検索',
suggestions: '提案',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `候補があります${query ? `: ${query}` : ''}。${count}件の結果。`,
other: (resultCount: number) => `候補があります${query ? `: ${query}` : ''}。${resultCount}件の結果。`,
}),
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 6c8670a9..cc6170ab 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -1055,6 +1055,14 @@ const translations: TranslationDeepObject<typeof en> = {
inDays: () => ({one: 'Over 1 dag', other: (count: number) => `Over ${count} dagen`}),
today: 'Vandaag',
},
+ gettingStartedSection: {
+ title: 'Aan de slag',
+ createWorkspace: 'Maak een werkruimte',
+ connectAccounting: ({integrationName}: {integrationName: string}) => `Verbind met ${integrationName}`,
+ customizeCategories: 'Boekhoudcategorieën aanpassen',
+ linkCompanyCards: 'Bedrijfspassen koppelen',
+ setupRules: 'Uitgavenregels instellen',
+ },
},
allSettingsScreen: {
subscription: 'Abonnement',
@@ -7396,7 +7404,14 @@ Vereis onkostendetails zoals bonnen en beschrijvingen, stel limieten en standaar
searchIn: 'Zoeken in',
searchPlaceholder: 'Zoek iets',
suggestions: 'Suggesties',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Suggesties beschikbaar${query ? ` voor ${query}` : ''}. ${count} resultaat.`,
other: (resultCount: number) => `Suggesties beschikbaar${query ? ` voor ${query}` : ''}. ${resultCount} resultaten.`,
}),
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index 1a80b954..d4c17d24 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -1056,6 +1056,14 @@ const translations: TranslationDeepObject<typeof en> = {
inDays: () => ({one: 'Za 1 dzień', other: (count: number) => `Za ${count} dni`}),
today: 'Dzisiaj',
},
+ gettingStartedSection: {
+ title: 'Pierwsze kroki',
+ createWorkspace: 'Utwórz przestrzeń roboczą',
+ connectAccounting: ({integrationName}: {integrationName: string}) => `Połącz z ${integrationName}`,
+ customizeCategories: 'Dostosuj kategorie księgowe',
+ linkCompanyCards: 'Połącz firmowe karty',
+ setupRules: 'Skonfiguruj zasady wydatków',
+ },
},
allSettingsScreen: {
subscription: 'Subskrypcja',
@@ -7397,7 +7405,14 @@ Wymagaj szczegółów wydatków, takich jak paragony i opisy, ustawiaj limity i
searchIn: 'Szukaj w',
searchPlaceholder: 'Wyszukaj coś',
suggestions: 'Sugestie',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Dostępne sugestie${query ? ` dla ${query}` : ''}. ${count} wynik.`,
other: (resultCount: number) => `Dostępne sugestie${query ? ` dla ${query}` : ''}. ${resultCount} wyniki.`,
}),
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index 6226e66c..81f0b135 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -1054,6 +1054,14 @@ const translations: TranslationDeepObject<typeof en> = {
inDays: () => ({one: 'Em 1 dia', other: (count: number) => `Em ${count} dias`}),
today: 'Hoje',
},
+ gettingStartedSection: {
+ title: 'Introdução',
+ createWorkspace: 'Criar um workspace',
+ connectAccounting: ({integrationName}: {integrationName: string}) => `Conectar ao ${integrationName}`,
+ customizeCategories: 'Personalizar categorias contábeis',
+ linkCompanyCards: 'Vincular cartões corporativos',
+ setupRules: 'Configurar regras de gasto',
+ },
},
allSettingsScreen: {
subscription: 'Assinatura',
@@ -7384,7 +7392,14 @@ Exija dados de despesas como recibos e descrições, defina limites e padrões e
searchIn: 'Pesquisar em',
searchPlaceholder: 'Pesquisar algo',
suggestions: 'Sugestões',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `Sugestões disponíveis${query ? ` para ${query}` : ''}. ${count} resultado.`,
other: (resultCount: number) => `Sugestões disponíveis${query ? ` para ${query}` : ''}. ${resultCount} resultados.`,
}),
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 8ed909dd..19dc0e20 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -1022,6 +1022,14 @@ const translations: TranslationDeepObject<typeof en> = {
inDays: () => ({one: '1 天后', other: (count: number) => `在 ${count} 天后`}),
today: '今天',
},
+ gettingStartedSection: {
+ title: '入门',
+ createWorkspace: '创建工作区',
+ connectAccounting: ({integrationName}: {integrationName: string}) => `连接到 ${integrationName}`,
+ customizeCategories: '自定义会计类别',
+ linkCompanyCards: '关联公司卡',
+ setupRules: '设置消费规则',
+ },
},
allSettingsScreen: {
subscription: '订阅',
@@ -7214,7 +7222,14 @@ ${reportName}
searchIn: '搜索范围',
searchPlaceholder: '搜索内容',
suggestions: '建议',
- suggestionsAvailable: ({count}: {count: number}, query = '') => ({
+ suggestionsAvailable: (
+ {
+ count,
+ }: {
+ count: number;
+ },
+ query = '',
+ ) => ({
one: `有可用建议${query ? `:${query}` : ''}。共${count}条结果。`,
other: (resultCount: number) => `有可用建议${query ? `:${query}` : ''}。共${resultCount}条结果。`,
}),
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
… add useLocalize mock to hook tests
|
🚧 @mountiny has triggered a test Expensify/App build. You can view the workflow run here. |
|
🚧 @JmillsExpensify has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
Looks good, let's ship it! |
|
Switching product approver since Jason has already reviewed |
mountiny
left a comment
There was a problem hiding this comment.
Left couple comments that can be handled in a follow up
| const hasCustomRules = !!policy.customRules && policy.customRules.trim().length > 0; | ||
|
|
||
| const {rules} = policy; | ||
| const hasApprovalRules = !!rules?.approvalRules && rules.approvalRules.length > 0; | ||
| const hasExpenseRules = !!rules?.expenseRules && rules.expenseRules.length > 0; | ||
| const hasCodingRules = !!rules?.codingRules && Object.keys(rules.codingRules).length > 0; | ||
|
|
||
| return hasCustomRules || hasApprovalRules || hasExpenseRules || hasCodingRules; |
There was a problem hiding this comment.
super minor thing, but you could return early for the hasCustomRules before we spread the policy to get rules
| * Checks if a policy has any non-default rules configured. | ||
| * Defaults are: no approval/expense/coding rules and no custom rules text. | ||
| */ | ||
| function hasNonDefaultRules(policy: OnyxEntry<Policy>): boolean { |
There was a problem hiding this comment.
Can you add unit test for this?
There was a problem hiding this comment.
Could you add specific test for this utility method?
|
🚧 @mountiny has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to staging by https://github.com/mountiny in version: 9.3.58-0 🚀
Bundle Size Analysis (Sentry): |
|
Yes, help site changes are needed. The Expensify Home Overview article lists all sections that appear on the Home page but does not include the new Getting started checklist section. I've created a draft PR with the update: #87572 Changes made:
No other help site articles require changes — the existing workspace setup guides ( |
|
Deploy Blocker #87607 was identified to be related to this PR. |
|
Deploy Blocker #87621 was identified to be related to this PR. |
|
Deploy Blocker #87729 was identified to be related to this PR. |
|
Deploy Blocker #87730 was identified to be related to this PR. |
|
🚀 Deployed to production by https://github.com/AndrewGable in version: 9.3.58-9 🚀
|
|
🚀 Deployed to production by https://github.com/AndrewGable in version: 9.3.58-9 🚀
|
Explanation of Change
Adds a "Getting started" onboarding checklist widget to the Home page for users with the "manage my team" onboarding intent. The section appears in the right column on desktop and guides new users through key setup steps with a checkbox-style UI.
Visibility rules:
Checklist items (up to 4):
Each row is fully clickable and navigates to the relevant workspace editor route. Completed items show a filled checkmark; incomplete items show an empty checkbox with an arrow icon.
Fixed Issues
$ #86288
Tests
/accountingin the workspace editor/categoriesOffline tests
QA Steps
Same as Tests.
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Screen.Recording.2026-03-30.at.17.44.21.mov