diff --git a/src/languages/de.ts b/src/languages/de.ts index aedea660fac21..df9ceda71b688 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -544,6 +544,7 @@ const translations: TranslationDeepObject = { vacationDelegate: 'Urlaubsvertretung', expensifyLogo: 'Expensify-Logo', duplicateReport: 'Duplizierten Bericht', + explain: 'Erklären', }, socials: { podcast: 'Folgen Sie uns auf Podcast', @@ -1534,7 +1535,6 @@ const translations: TranslationDeepObject = { amountTooLargeError: 'Der Gesamtbetrag ist zu hoch. Verringere die Stunden oder reduziere den Satz.', }, correctRateError: 'Beheben Sie den Kursfehler und versuchen Sie es erneut.', - AskToExplain: `. Erklären ✨`, duplicateNonDefaultWorkspacePerDiemError: 'Sie können Per-Diem-Ausgaben nicht über mehrere Workspaces hinweg duplizieren, da sich die Sätze zwischen den Workspaces unterscheiden können.', rulesModifiedFields: { diff --git a/src/languages/en.ts b/src/languages/en.ts index 5b017f3ac526a..fd4fca5aee8c9 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -563,6 +563,7 @@ const translations = { quarter: 'Quarter', vacationDelegate: 'Vacation delegate', expensifyLogo: 'Expensify logo', + explain: 'Explain', }, socials: { podcast: 'Follow us on Podcast', @@ -1552,7 +1553,6 @@ const translations = { amountTooLargeError: 'The total amount is too large. Lower the hours or reduce the rate.', }, correctRateError: 'Fix the rate error and try again.', - AskToExplain: `. Explain ✨`, rulesModifiedFields: { reimbursable: (value: boolean) => (value ? 'marked the expense as "reimbursable"' : 'marked the expense as "non-reimbursable"'), billable: (value: boolean) => (value ? 'marked the expense as "billable"' : 'marked the expense as "non-billable"'), diff --git a/src/languages/es.ts b/src/languages/es.ts index a4facc31ed902..816a977fed56b 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -408,6 +408,7 @@ const translations: TranslationDeepObject = { quarter: 'Trimestre', vacationDelegate: 'Delegado de vacaciones', expensifyLogo: 'Logo de Expensify', + explain: 'Explicar', }, socials: { podcast: 'Síguenos en Podcast', @@ -1386,7 +1387,6 @@ const translations: TranslationDeepObject = { amountTooLargeError: 'El importe total es demasiado alto. Reduce las horas o disminuye la tasa.', }, correctRateError: 'Corrige el error de la tasa y vuelve a intentarlo.', - AskToExplain: `. Explicar ✨`, rulesModifiedFields: { reimbursable: (value: boolean) => (value ? 'marcó el gasto como "reembolsable"' : 'marcó el gasto como "no reembolsable"'), billable: (value: boolean) => (value ? 'marcó el gasto como "facturable"' : 'marcó el gasto como "no facturable"'), diff --git a/src/languages/fr.ts b/src/languages/fr.ts index aee4ae6479811..3d7cebea36d66 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -544,6 +544,7 @@ const translations: TranslationDeepObject = { vacationDelegate: 'Délégué de vacances', expensifyLogo: 'Logo Expensify', duplicateReport: 'Note de frais en double', + explain: 'Expliquer', }, socials: { podcast: 'Suivez-nous sur Podcast', @@ -1539,7 +1540,6 @@ const translations: TranslationDeepObject = { amountTooLargeError: 'Le montant total est trop élevé. Réduisez le nombre d’heures ou diminuez le taux.', }, correctRateError: 'Corrigez l’erreur de taux et réessayez.', - AskToExplain: `. Expliquer ✨`, duplicateNonDefaultWorkspacePerDiemError: 'Vous ne pouvez pas dupliquer les indemnités journalières entre plusieurs espaces de travail, car les taux peuvent différer d’un espace de travail à l’autre.', rulesModifiedFields: { diff --git a/src/languages/it.ts b/src/languages/it.ts index eb2a6519ee6a3..f417d35acc4ce 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -544,6 +544,7 @@ const translations: TranslationDeepObject = { vacationDelegate: 'Delega ferie', expensifyLogo: 'Logo Expensify', duplicateReport: 'Report duplicato', + explain: 'Spiega', }, socials: { podcast: 'Seguici su Podcast', @@ -1531,7 +1532,6 @@ const translations: TranslationDeepObject = { amountTooLargeError: 'L’importo totale è troppo alto. Riduci le ore o abbassa la tariffa.', }, correctRateError: "Correggi l'errore di tariffa e riprova.", - AskToExplain: `. Spiega ✨`, duplicateNonDefaultWorkspacePerDiemError: 'Non puoi duplicare le spese di diaria tra diversi spazi di lavoro perché le tariffe potrebbero essere diverse tra gli spazi di lavoro.', rulesModifiedFields: { reimbursable: (value: boolean) => (value ? 'ha contrassegnato la spesa come "rimborsabile"' : 'ha contrassegnato la spesa come "non rimborsabile"'), diff --git a/src/languages/ja.ts b/src/languages/ja.ts index d8aca9949443b..439f4841c8bd1 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -543,6 +543,7 @@ const translations: TranslationDeepObject = { vacationDelegate: '休暇代理人', expensifyLogo: 'Expensifyロゴ', duplicateReport: 'レポートを複製', + explain: '説明', }, socials: { podcast: 'ポッドキャストでフォロー', @@ -1521,7 +1522,6 @@ const translations: TranslationDeepObject = { amountTooLargeError: '合計金額が大きすぎます。時間を減らすか、レートを下げてください。', }, correctRateError: 'レートのエラーを修正して、もう一度お試しください。', - AskToExplain: `・説明 ✨`, duplicateNonDefaultWorkspacePerDiemError: 'ワークスペースごとに日当レートが異なる場合があるため、日当経費をワークスペース間で複製することはできません。', rulesModifiedFields: { reimbursable: (value: boolean) => (value ? '経費を「精算対象」に指定しました' : '経費を「精算対象外」にマークしました'), diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 78bea5291bbe7..6b41f7e9cd417 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -543,6 +543,7 @@ const translations: TranslationDeepObject = { vacationDelegate: 'Vertegenwoordiger tijdens vakantie', expensifyLogo: 'Expensify-logo', duplicateReport: 'Dubbel rapport', + explain: 'Uitleggen', }, socials: { podcast: 'Volg ons op Podcast', @@ -1529,7 +1530,6 @@ const translations: TranslationDeepObject = { amountTooLargeError: 'Het totale bedrag is te hoog. Verlaag het aantal uren of verlaag het tarief.', }, correctRateError: 'Los de tarieffout op en probeer het opnieuw.', - AskToExplain: `. Uitleggen ✨`, duplicateNonDefaultWorkspacePerDiemError: 'Je kunt dagvergoedingen niet dupliceren tussen werkruimtes, omdat de tarieven per werkruimte kunnen verschillen.', rulesModifiedFields: { reimbursable: (value: boolean) => (value ? 'markeerde de uitgave als „terugbetaalbaar”' : 'heeft de uitgave als ‘niet-vergoedbaar’ gemarkeerd'), diff --git a/src/languages/pl.ts b/src/languages/pl.ts index f412409be10e5..9e66c278a975c 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -543,6 +543,7 @@ const translations: TranslationDeepObject = { vacationDelegate: 'Zastępca urlopowy', expensifyLogo: 'Logo Expensify', duplicateReport: 'Zduplikowany raport', + explain: 'Wyjaśnij', }, socials: { podcast: 'Śledź nas na Podcast', @@ -1528,7 +1529,6 @@ const translations: TranslationDeepObject = { amountTooLargeError: 'Łączna kwota jest zbyt wysoka. Zmniejsz liczbę godzin lub obniż stawkę.', }, correctRateError: 'Napraw błąd stawki i spróbuj ponownie.', - AskToExplain: `. Wyjaśnij ✨`, duplicateNonDefaultWorkspacePerDiemError: 'Nie możesz duplikować wydatków z tytułu diet między przestrzeniami roboczymi, ponieważ stawki mogą się różnić między poszczególnymi przestrzeniami.', rulesModifiedFields: { diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 7e5d279f46b0e..0b533fa52476c 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -542,6 +542,7 @@ const translations: TranslationDeepObject = { vacationDelegate: 'Delegado de férias', expensifyLogo: 'Logo da Expensify', duplicateReport: 'Duplicar relatório', + explain: 'Explicar', }, socials: { podcast: 'Siga-nos no Podcast', @@ -1526,7 +1527,6 @@ const translations: TranslationDeepObject = { amountTooLargeError: 'O valor total é muito alto. Diminua as horas ou reduza a tarifa.', }, correctRateError: 'Corrija o erro de taxa e tente novamente.', - AskToExplain: `. Explicar ✨`, duplicateNonDefaultWorkspacePerDiemError: 'Você não pode duplicar despesas de diárias entre espaços de trabalho porque as tarifas podem variar entre eles.', rulesModifiedFields: { reimbursable: (value: boolean) => (value ? 'marcou a despesa como "reembolsável"' : 'marcou a despesa como “não reembolsável”'), diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index d17ca0bd7e0b8..79bf7eeb1b988 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -539,6 +539,7 @@ const translations: TranslationDeepObject = { vacationDelegate: '休假代理', expensifyLogo: 'Expensify徽标', duplicateReport: '重复报销单', + explain: '说明', }, socials: { podcast: '在播客上关注我们', @@ -1500,7 +1501,6 @@ const translations: TranslationDeepObject = { amountTooLargeError: '总金额过大。请减少工时或降低费率。', }, correctRateError: '修复费率错误后请重试。', - AskToExplain: `。说明 ✨`, duplicateNonDefaultWorkspacePerDiemError: '您无法在不同工作区之间复制每日津贴报销,因为各工作区的补贴标准可能不同。', rulesModifiedFields: { reimbursable: (value: boolean) => (value ? '将该报销单标记为“可报销”' : '将该报销单标记为“不可报销”'), diff --git a/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx b/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx index ad6629117fcc2..67325f1f2b840 100644 --- a/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx +++ b/src/pages/inbox/report/ReportActionItemMessageWithExplain.tsx @@ -1,14 +1,20 @@ import React from 'react'; -import type {GestureResponderEvent} from 'react-native'; +import {View} from 'react-native'; import type {OnyxEntry} from 'react-native-onyx'; +import Icon from '@components/Icon'; import RenderHTML from '@components/RenderHTML'; +import TextBlock from '@components/TextBlock'; +import TextLinkBlock from '@components/TextLinkBlock'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useEnvironment from '@hooks/useEnvironment'; +import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; import {openLink} from '@libs/actions/Link'; import {explain} from '@libs/actions/Report'; import {hasReasoning} from '@libs/ReportActionsUtils'; -import CONST from '@src/CONST'; +import variables from '@styles/variables'; import type {Report, ReportAction} from '@src/types/onyx'; import ReportActionItemBasicMessage from './ReportActionItemBasicMessage'; @@ -31,31 +37,49 @@ type ReportActionItemMessageWithExplainProps = { * if the action has reasoning. */ function ReportActionItemMessageWithExplain({message, action, childReport, originalReport}: ReportActionItemMessageWithExplainProps) { + const theme = useTheme(); + const styles = useThemeStyles(); const {translate} = useLocalize(); const personalDetail = useCurrentUserPersonalDetails(); + const icons = useMemoizedLazyExpensifyIcons(['Sparkles']); const {environmentURL} = useEnvironment(); const actionHasReasoning = hasReasoning(action); - const computedMessage = actionHasReasoning ? `${message}${translate('iou.AskToExplain')}` : message; - const handleLinkPress = (event: GestureResponderEvent | KeyboardEvent, href: string) => { - // Handle the special "Explain" link - if (href.endsWith(CONST.CONCIERGE_EXPLAIN_LINK_PATH)) { - explain(childReport, originalReport, action, translate, personalDetail.accountID, personalDetail?.timezone); - return; - } - - // For all other links, use the default link handler - openLink(href, environmentURL); - }; + if (!actionHasReasoning) { + return ( + + ${message}`} + onLinkPress={(event, href) => { + openLink(href, environmentURL); + }} + /> + + ); + } return ( - ${computedMessage}`} - isSelectable={false} - onLinkPress={handleLinkPress} - /> + + + + explain(childReport, originalReport, action, translate, personalDetail.accountID, personalDetail?.timezone)} + style={[styles.chatItemMessage, styles.link, styles.mrHalf]} + text={translate('common.explain')} + /> + + + ); } diff --git a/src/styles/utils/spacing.ts b/src/styles/utils/spacing.ts index 743dd3e5be826..05fb18d95dc00 100644 --- a/src/styles/utils/spacing.ts +++ b/src/styles/utils/spacing.ts @@ -143,6 +143,10 @@ export default { marginRight: 0, }, + mrHalf: { + marginRight: 2, + }, + mr1: { marginRight: 4, },