diff --git a/lang/es.json b/lang/es.json index cc2d168d..84cbb937 100644 --- a/lang/es.json +++ b/lang/es.json @@ -52,6 +52,8 @@ "Not doable": "No viable", "In progress": "En proceso", "Done": "Hecho", + "Done! You can continue now, or keep categorizing if you want.": "¡Listo! Ya puedes continuar, o seguir categorizando si quieres.", + "You do not need to categorize all of them.": "No necesitas categorizarlas todas.", "Something went wrong.": "Algo salió mal.", "Integration requests": "Solicitudes de integración", "Request integration": "Solicitar integración", diff --git a/resources/js/app.tsx b/resources/js/app.tsx index 46c2daa1..adb1fe31 100644 --- a/resources/js/app.tsx +++ b/resources/js/app.tsx @@ -11,7 +11,7 @@ import { OctagonXIcon, TriangleAlertIcon, } from 'lucide-react'; -import { StrictMode, useEffect } from 'react'; +import { StrictMode, useEffect, useState } from 'react'; import { createRoot } from 'react-dom/client'; import { toast, Toaster } from 'sonner'; import { EncryptionKeyProvider } from './contexts/encryption-key-context'; @@ -134,6 +134,35 @@ const getProgressBarColor = () => { return isDark ? '#EEE' : '#4B5563'; // gray-400 for dark mode, gray-600 for light mode }; +const isOnboardingPath = () => + typeof window !== 'undefined' && + window.location.pathname.startsWith('/onboarding'); + +// Onboarding has no bottom navigation bar, so toasts sit flush at the bottom +// center instead of being lifted to clear the (absent) mobile tab bar. +function AppToaster() { + const [isOnboarding, setIsOnboarding] = useState(isOnboardingPath); + + useEffect(() => { + return router.on('navigate', () => setIsOnboarding(isOnboardingPath())); + }, []); + + return ( + , + info: , + warning: , + error: , + loading: , + }} + /> + ); +} + createInertiaApp({ title: (title) => (title ? `${title} - ${appName}` : appName), resolve: (name) => @@ -228,23 +257,7 @@ createInertiaApp({ initialExpiredConnections } /> - - ), - info: , - warning: ( - - ), - error: , - loading: ( - - ), - }} - /> + diff --git a/resources/js/components/onboarding/step-categorize-transactions.tsx b/resources/js/components/onboarding/step-categorize-transactions.tsx index 631616d1..8d492712 100644 --- a/resources/js/components/onboarding/step-categorize-transactions.tsx +++ b/resources/js/components/onboarding/step-categorize-transactions.tsx @@ -52,7 +52,6 @@ export function StepCategorizeTransactions({ isComplete, uncategorizedTransactions, currentTransaction, - remainingCount, animationState, lastSelectedCategory, sortedCategories, @@ -79,8 +78,6 @@ export function StepCategorizeTransactions({ categorizedCount >= minimumRequired || totalAvailable === 0; - const hasReachedMinimum = categorizedCount >= minimumRequired; - // Show rules hint after first categorization, only once useEffect(() => { if (categorizedCount === 1 && !hasSeenHint) { @@ -262,6 +259,51 @@ export function StepCategorizeTransactions({ return (
+ {/* Progress banner: makes the "categorize at least N" goal obvious */} +
+ {canContinue ? ( +
+ +

+ {__( + 'Done! You can continue now, or keep categorizing if you want.', + )} +

+
+ ) : ( +
+
+

+ {__( + 'To continue, you need to categorize at least :count transactions.', + { count: minimumRequired }, + )} +

+ + {categorizedCount}/{minimumRequired} + +
+
+ {Array.from({ length: minimumRequired }).map( + (_, i) => ( +
+ ), + )} +
+

+ {__('You do not need to categorize all of them.')} +

+
+ )} +
+ {/* Header row */}
{}}> @@ -322,27 +364,14 @@ export function StepCategorizeTransactions({ size="sm" onClick={onComplete} disabled={!canContinue} + className={ + canContinue + ? 'ring-2 ring-primary ring-offset-2 ring-offset-background' + : undefined + } > {__('Continue')} - - - {hasReachedMinimum ? ( - <> - - {remainingCount} - {' '} - {__('remaining')} - - ) : ( - <> - - {categorizedCount} - - /{minimumRequired} - - )} -
diff --git a/resources/js/layouts/onboarding-layout.tsx b/resources/js/layouts/onboarding-layout.tsx index 999abe94..a60c82bd 100644 --- a/resources/js/layouts/onboarding-layout.tsx +++ b/resources/js/layouts/onboarding-layout.tsx @@ -55,7 +55,7 @@ export default function OnboardingLayout({