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 (
+
+ {__( + '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} + ++ {__('You do not need to categorize all of them.')} +
+