Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
60 changes: 60 additions & 0 deletions src/components/Rule/RuleCategoriesDisabledEmptyState.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Button from '@components/ButtonComposed';
import FixedFooter from '@components/FixedFooter';
import WorkspaceEmptyStateSection from '@components/WorkspaceEmptyStateSection';

import {useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import usePolicyData from '@hooks/usePolicyData';
import useThemeStyles from '@hooks/useThemeStyles';

import {enablePolicyCategories, openPolicyCategoriesPage} from '@libs/actions/Policy/Category';

import CONST from '@src/CONST';

import React from 'react';
import {View} from 'react-native';

type RuleCategoriesDisabledEmptyStateProps = {
/** ID of the policy the rule belongs to */
policyID: string;
};

function RuleCategoriesDisabledEmptyState({policyID}: RuleCategoriesDisabledEmptyStateProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const illustrations = useMemoizedLazyIllustrations(['FolderOpen']);
const policyData = usePolicyData(policyID);

const enableCategories = () => {
enablePolicyCategories(policyData, true, false);

// The categories collection is empty while the feature is disabled, and enabling it only merges the
// categories we already know about, so the collection has to be fetched for the picker to have rows.
openPolicyCategoriesPage(policyID);
};

return (
<View style={[styles.flex1]}>
<WorkspaceEmptyStateSection
shouldStyleAsCard={false}
icon={illustrations.FolderOpen}
title={translate('workspace.rules.categoriesDisabledEmptyState.title')}
subtitle={translate('workspace.rules.categoriesDisabledEmptyState.subtitle')}
containerStyle={[styles.flex1, styles.justifyContentCenter]}
/>
<FixedFooter style={[styles.mtAuto, styles.pt5]}>
<Button
variant={CONST.BUTTON_VARIANT.SUCCESS}
size={CONST.BUTTON_SIZE.LARGE}
style={[styles.w100]}
onPress={enableCategories}
>
<Button.KeyboardShortcut />
<Button.Text>{translate('workspace.categories.enableCategories')}</Button.Text>
</Button>
</FixedFooter>
</View>
);
}

export default RuleCategoriesDisabledEmptyState;
59 changes: 36 additions & 23 deletions src/components/Rule/RuleSelectionBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,17 @@ type RuleSelectionBaseProps = {
/** Test ID for the screen wrapper */
testID: string;

/** Callback to go back */
onBack: () => void;

/** Optional hash for rule not found validation */
hash?: string;

/** Page content */
children: React.ReactNode;
};

type RuleSelectionPickerProps = {
/** The currently selected item */
selectedItem?: SelectionItem;

Expand All @@ -41,18 +52,12 @@ type RuleSelectionBaseProps = {
/** Callback when a value is selected */
onSave: (value?: string) => void;

/** Callback to go back */
onBack: () => void;

/** The route to navigate back to */
backToRoute: RuleSelectionBackToRoute;

/** When true, shows a "None" option in the picker */
allowNoneOption?: boolean;

/** Optional hash for rule not found validation */
hash?: string;

/** Set at parents whose Save is `pressOnEnter` so an auto-save selection can't leave the row re-focused and hijack the next Enter. */
shouldSkipFocusRestoreOnSave?: boolean;
};
Expand All @@ -61,15 +66,10 @@ function resolveBackToRoute(backToRoute: RuleSelectionBackToRoute, selectedValue
return typeof backToRoute === 'function' ? backToRoute(selectedValue) : backToRoute;
}

function RuleSelectionBase({titleKey, title, testID, selectedItem, items, onSave, onBack, backToRoute, allowNoneOption = true, hash, shouldSkipFocusRestoreOnSave}: RuleSelectionBaseProps) {
function RuleSelectionBaseComponent({titleKey, title, testID, onBack, hash, children}: RuleSelectionBaseProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();

const handleSaveSelection = (value?: string) => {
onSave(value);
Navigation.goBack(resolveBackToRoute(backToRoute, value), {shouldSkipFocusRestore: shouldSkipFocusRestoreOnSave});
};

return (
<RuleNotFoundPageWrapper hash={hash}>
<ScreenWrapper
Expand All @@ -81,20 +81,33 @@ function RuleSelectionBase({titleKey, title, testID, selectedItem, items, onSave
title={title ?? translate(titleKey)}
onBackButtonPress={onBack}
/>
<View style={[styles.flex1]}>
<SearchSingleSelectionPicker
initiallySelectedItem={selectedItem}
items={items}
onSaveSelection={handleSaveSelection}
shouldAutoSave
shouldNavigateOnSave={false}
allowNoneOption={allowNoneOption}
shouldSkipFocusRestoreOnSave={shouldSkipFocusRestoreOnSave}
/>
</View>
<View style={[styles.flex1]}>{children}</View>
</ScreenWrapper>
</RuleNotFoundPageWrapper>
);
}

function RuleSelectionPicker({selectedItem, items, onSave, backToRoute, allowNoneOption = true, shouldSkipFocusRestoreOnSave}: RuleSelectionPickerProps) {
const handleSaveSelection = (value?: string) => {
onSave(value);
Navigation.goBack(resolveBackToRoute(backToRoute, value), {shouldSkipFocusRestore: shouldSkipFocusRestoreOnSave});
};

return (
<SearchSingleSelectionPicker
initiallySelectedItem={selectedItem}
items={items}
onSaveSelection={handleSaveSelection}
shouldAutoSave
shouldNavigateOnSave={false}
allowNoneOption={allowNoneOption}
shouldSkipFocusRestoreOnSave={shouldSkipFocusRestoreOnSave}
/>
);
}

const RuleSelectionBase = Object.assign(RuleSelectionBaseComponent, {
Picker: RuleSelectionPicker,
});

export default RuleSelectionBase;
1 change: 1 addition & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8027,6 +8027,7 @@ Fügen Sie weitere Ausgabelimits hinzu, um den Cashflow Ihres Unternehmens zu sc
subtitle: 'Erstellen Sie eine Regel, um Ihre Arbeitsbereichsrichtlinien zu automatisieren.',
cta: 'KI-Regel hinzufügen',
},
categoriesDisabledEmptyState: {title: 'Kategorien sind nicht aktiviert', subtitle: 'Aktivieren Sie Kategorien, um Ihre Ausgaben besser zu kontrollieren.'},
},
planTypePage: {
planTypes: {
Expand Down
4 changes: 4 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7944,6 +7944,10 @@ const translations = {
subtitle: 'Require or waive expense fields for specific categories.',
cta: 'Create field requirement rule',
},
categoriesDisabledEmptyState: {
title: 'Categories are not enabled',
subtitle: 'Enable categories to gain more control of your spend.',
},
Comment thread
Krishna2323 marked this conversation as resolved.
requireFieldsRule: {
title: 'Field requirements',
subtitle: 'Require specific expense fields or waive requiring them.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7934,6 +7934,7 @@ El plan Controlar empieza en 9 $ por miembro activo al mes.`,
subtitle: 'Crea una regla para automatizar las políticas de tu espacio de trabajo.',
cta: 'Añadir regla de IA',
},
categoriesDisabledEmptyState: {title: 'Las categorías no están habilitadas', subtitle: 'Habilita las categorías para tener más control sobre tus gastos.'},
},
emptyDomain: {
title: 'Mejora tu seguridad con dominios',
Expand Down
1 change: 1 addition & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8055,6 +8055,7 @@ Ajoutez davantage de règles de dépenses pour protéger la trésorerie de l’e
subtitle: 'Créez une règle pour automatiser les politiques de votre espace de travail.',
cta: 'Ajouter une règle IA',
},
categoriesDisabledEmptyState: {title: 'Les catégories ne sont pas activées', subtitle: 'Activez les catégories pour mieux contrôler vos dépenses.'},
},
planTypePage: {
planTypes: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7996,6 +7996,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
thenFlagForReview: 'Poi segnala per revisione quando:',
},
agentRulesEmptyState: {title: 'Nessuna regola agente aggiunta', subtitle: 'Crea una regola per automatizzare le policy del tuo workspace.', cta: 'Aggiungi regola IA'},
categoriesDisabledEmptyState: {title: 'Le categorie non sono abilitate', subtitle: 'Attiva le categorie per avere un maggiore controllo sulle tue spese.'},
},
planTypePage: {
planTypes: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7900,6 +7900,7 @@ ${reportName}`,
thenFlagForReview: '次の条件で確認フラグを付けます:',
},
agentRulesEmptyState: {title: 'エージェントルールが追加されていません', subtitle: 'ワークスペースのポリシーを自動化するルールを作成します。', cta: 'AIルールを追加'},
categoriesDisabledEmptyState: {title: 'カテゴリが有効になっていません', subtitle: 'カテゴリを有効にして、支出をより細かく管理しましょう。'},
},
planTypePage: {
planTypes: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7977,6 +7977,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
thenFlagForReview: 'Vlag dan voor controle wanneer:',
},
agentRulesEmptyState: {title: 'Geen agentregels toegevoegd', subtitle: 'Maak een regel om je werkruimtebeleid te automatiseren.', cta: 'AI-regel toevoegen'},
categoriesDisabledEmptyState: {title: 'Categorieën zijn niet ingeschakeld', subtitle: 'Schakel categorieën in om meer controle te krijgen over je uitgaven.'},
},
planTypePage: {
planTypes: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7957,6 +7957,7 @@ Dodaj więcej zasad wydatków, żeby chronić płynność finansową firmy.`,
thenFlagForReview: 'Następnie oznacz do przejrzenia, gdy:',
},
agentRulesEmptyState: {title: 'Nie dodano reguł agenta', subtitle: 'Utwórz regułę, żeby zautomatyzować zasady swojego workspace’u.', cta: 'Dodaj regułę AI'},
categoriesDisabledEmptyState: {title: 'Kategorie nie są włączone', subtitle: 'Włącz kategorie, żeby mieć większą kontrolę nad wydatkami.'},
},
planTypePage: {
planTypes: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7974,6 +7974,7 @@ Adicione mais regras de gasto para proteger o fluxo de caixa da empresa.`,
thenFlagForReview: 'Então sinalizar para revisão quando:',
},
agentRulesEmptyState: {title: 'Nenhuma regra de agente adicionada', subtitle: 'Crie uma regra para automatizar as políticas do seu workspace.', cta: 'Adicionar regra de IA'},
categoriesDisabledEmptyState: {title: 'Categorias não estão ativadas', subtitle: 'Ative categorias para ter mais controle sobre seus gastos.'},
},
planTypePage: {
planTypes: {
Expand Down
1 change: 1 addition & 0 deletions src/languages/zh-hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7710,6 +7710,7 @@ ${reportName}`,
thenFlagForReview: '然后在以下情况下标记为待审核:',
},
agentRulesEmptyState: {title: '未添加代理规则', subtitle: '创建规则以自动化您的工作区策略。', cta: '添加 AI 规则'},
categoriesDisabledEmptyState: {title: '类别未启用', subtitle: '启用类别以更好地控制您的支出。'},
},
planTypePage: {
planTypes: {
Expand Down
13 changes: 8 additions & 5 deletions src/pages/settings/Rules/Fields/AddCategoryPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,16 @@ function AddCategoryPage({route}: AddCategoryPageProps) {
<RuleSelectionBase
titleKey="common.category"
testID="AddCategoryPage"
selectedItem={selectedCategoryItem}
items={categoryItems()}
onSave={onSave}
onBack={() => Navigation.goBack(backToRoute)}
backToRoute={backToRoute}
hash={hash}
/>
>
<RuleSelectionBase.Picker
selectedItem={selectedCategoryItem}
items={categoryItems()}
onSave={onSave}
backToRoute={backToRoute}
/>
</RuleSelectionBase>
);
}

Expand Down
15 changes: 9 additions & 6 deletions src/pages/settings/Rules/Fields/AddTagPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,16 @@ function AddTagPage({route}: AddTagPageProps) {
titleKey="common.tag"
title={tagList?.name}
testID="AddTagPage"
selectedItem={selectedTagItem}
items={tagItems}
onSave={onSave}
onBack={() => Navigation.goBack(backToRoute)}
backToRoute={backToRoute}
hash={hash}
/>
onBack={() => Navigation.goBack(backToRoute)}
>
<RuleSelectionBase.Picker
selectedItem={selectedTagItem}
items={tagItems}
onSave={onSave}
backToRoute={backToRoute}
/>
</RuleSelectionBase>
);
}

Expand Down
13 changes: 8 additions & 5 deletions src/pages/settings/Rules/Fields/AddTaxRatePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,16 @@ function AddTaxRatePage({route}: AddTaxRatePageProps) {
<RuleSelectionBase
titleKey="common.tax"
testID="AddTaxRatePage"
selectedItem={selectedTaxItem}
items={taxItems}
onSave={onSave}
onBack={() => Navigation.goBack(backToRoute)}
backToRoute={backToRoute}
hash={hash}
/>
>
<RuleSelectionBase.Picker
selectedItem={selectedTaxItem}
items={taxItems}
onSave={onSave}
backToRoute={backToRoute}
/>
</RuleSelectionBase>
);
}

Expand Down
Loading
Loading