@@ -16,6 +16,7 @@ import { ScheduledPaymentView } from './views/ScheduledPaymentView';
1616import { TransactionsListView } from './views/TransactionsListView' ;
1717import { CalendarHeatmapView } from './views/CalendarHeatmapView' ;
1818import { CurrencyPerformanceView } from './views/CurrencyPerformanceView' ;
19+ import { InvoiceDigitizeView } from './views/settings/InvoiceDigitizeView' ;
1920import { ScheduledNotificationsView } from './views/ScheduledNotificationsView' ;
2021import { ShoppingListView } from './views/ShoppingListView' ;
2122import { PeopleView } from './views/PeopleView' ;
@@ -31,7 +32,8 @@ import { XPToastContainer } from './components/gamification/XPToast';
3132import { LevelUpModal } from './components/gamification/LevelUpModal' ;
3233import { BadgeEarnedSheet } from './components/gamification/BadgeEarnedSheet' ;
3334import { ThemeProvider } from './contexts/ThemeContext' ;
34- import type { BadgeDefinition , LevelId , GamificationProfile } from '@parity/core' ;
35+ import type { BadgeDefinition , LevelId , GamificationProfile , DailyGoalTier } from '@parity/core' ;
36+ import { createDefaultProfile , toISODate , CHALLENGE_TEMPLATES , offsetDate } from '@parity/core' ;
3537import { getTranslation } from '@parity/i18n' ;
3638import { motion , AnimatePresence } from 'framer-motion' ;
3739import './index.css' ;
@@ -223,7 +225,7 @@ function AppContent() {
223225 const { data : ratesData , refetch : fetchAllRates } = useExchangeRates ( isLoaded ) ;
224226
225227 // Gamification engine
226- const { profile : gamProfile , dispatchEvent : dispatchGamEvent , pendingRewards, clearRewards } = useGamification ( ) ;
228+ const { profile : gamProfile , dispatchEvent : dispatchGamEvent , pendingRewards, clearRewards, buyShopItem , equipOutfit , rerollChallenge , updateDailyGoal } = useGamification ( ) ;
227229 const [ xpToasts , setXpToasts ] = useState < { xpGained : number ; label : string } [ ] > ( [ ] ) ;
228230 const [ levelUpLevel , setLevelUpLevel ] = useState < LevelId | null > ( null ) ;
229231 const [ badgesToShow , setBadgesToShow ] = useState < BadgeDefinition [ ] > ( [ ] ) ;
@@ -1255,7 +1257,15 @@ function AppContent() {
12551257 }
12561258 } ;
12571259
1258- const handleStartFresh = ( data : { profile : Partial < UserProfile > ; displayCurrency : Currency ; isBalanceVisible : boolean ; navbarFavorites : string [ ] } ) => {
1260+ const handleStartFresh = ( data : {
1261+ profile : Partial < UserProfile > ;
1262+ displayCurrency : Currency ;
1263+ isBalanceVisible : boolean ;
1264+ navbarFavorites : string [ ] ;
1265+ dailyGoal : DailyGoalTier ;
1266+ hasDebtsSeed : boolean ;
1267+ attentionGoal : 'saving' | 'budgeting' | 'logging' ;
1268+ } ) => {
12591269 setUserProfile ( prev => ( { ...prev , ...data . profile } ) ) ;
12601270 setDisplayCurrency ( data . displayCurrency ) ;
12611271 localStorage . setItem ( "displayCurrency" , data . displayCurrency ) ;
@@ -1276,6 +1286,61 @@ function AppContent() {
12761286 icon : 'wallet' ,
12771287 } ;
12781288 setAccounts ( [ initialWallet ] ) ;
1289+
1290+ // Create customized initial gamification profile
1291+ const initialGamProfile = createDefaultProfile ( ) ;
1292+ initialGamProfile . dailyGoal = data . dailyGoal ;
1293+ initialGamProfile . placementCompletedAt = new Date ( ) . toISOString ( ) ;
1294+
1295+ // Seed initial challenges based on attentionGoal and hasDebtsSeed
1296+ const today = toISODate ( new Date ( ) ) ;
1297+ const matchedTemplates : string [ ] = [ ] ;
1298+ if ( data . attentionGoal === 'saving' ) {
1299+ matchedTemplates . push ( 'daily_log_today' , 'weekly_save_25' , 'monthly_goal_progress' ) ;
1300+ } else if ( data . attentionGoal === 'budgeting' ) {
1301+ matchedTemplates . push ( 'daily_log_today' , 'weekly_control_food' , 'monthly_all_green' ) ;
1302+ } else {
1303+ matchedTemplates . push ( 'daily_log_today' , 'weekly_no_gaps' , 'monthly_goal_progress' ) ;
1304+ }
1305+
1306+ if ( data . hasDebtsSeed ) {
1307+ matchedTemplates . push ( 'weekly_settle_debt' ) ;
1308+ }
1309+
1310+ for ( const tid of matchedTemplates ) {
1311+ const temp = CHALLENGE_TEMPLATES . find ( t => t . id === tid ) ;
1312+ if ( temp ) {
1313+ let targetVal = 1 ;
1314+ const target = temp . target ;
1315+ if ( target ) {
1316+ if ( 'count' in target ) targetVal = target . count ;
1317+ else if ( 'amount' in target ) targetVal = target . amount ;
1318+ else if ( 'limit' in target ) targetVal = target . limit ;
1319+ else if ( 'envelopeCount' in target ) targetVal = target . envelopeCount ;
1320+ else if ( 'days' in target ) targetVal = target . days ;
1321+ else if ( 'progressPercent' in target ) targetVal = target . progressPercent ;
1322+ }
1323+
1324+ const expiresAt = temp . horizon === 'daily'
1325+ ? today + 'T23:59:59.999Z'
1326+ : temp . horizon === 'weekly'
1327+ ? offsetDate ( today , 7 ) + 'T23:59:59.999Z'
1328+ : offsetDate ( today , 30 ) + 'T23:59:59.999Z' ;
1329+
1330+ initialGamProfile . challengeProgress [ temp . id ] = {
1331+ challengeId : temp . id ,
1332+ assignedAt : today + 'T00:00:00.000Z' ,
1333+ expiresAt,
1334+ current : 0 ,
1335+ target : targetVal ,
1336+ completed : false ,
1337+ completedAt : null ,
1338+ xpClaimed : false ,
1339+ } ;
1340+ }
1341+ }
1342+
1343+ idbService . saveGamificationProfile ( initialGamProfile ) ;
12791344 setIsFirstTime ( false ) ;
12801345 } ;
12811346
@@ -1660,6 +1725,9 @@ function AppContent() {
16601725 onUpdateTransaction = { ( tx ) => setTransactions ( prev => prev . map ( t => t . id === tx . id ? tx : t ) ) }
16611726 initialViewMode = { currentView === 'INVOICES' ? 'INVOICES' : 'LIST' }
16621727 showConfirm = { showConfirm }
1728+ userProfile = { userProfile }
1729+ isDevMode = { isDevMode }
1730+ showAlert = { showAlert }
16631731 />
16641732 ) }
16651733 { currentView === 'HEATMAP' && (
@@ -1687,6 +1755,15 @@ function AppContent() {
16871755 isDevMode = { isDevMode }
16881756 />
16891757 ) }
1758+ { currentView === 'INVOICE_DIGITIZE' && (
1759+ < InvoiceDigitizeView
1760+ onBack = { ( ) => setCurrentView ( 'PROFILE' ) }
1761+ transactions = { filteredTransactions }
1762+ onUpdateTransaction = { ( tx ) => setTransactions ( prev => prev . map ( t => t . id === tx . id ? tx : t ) ) }
1763+ userProfile = { userProfile }
1764+ showAlert = { showAlert }
1765+ />
1766+ ) }
16901767 { currentView === 'SCHEDULED_NOTIFICATIONS' && (
16911768 < ScheduledNotificationsView
16921769 onBack = { ( ) => setCurrentView ( 'PROFILE' ) }
@@ -1779,6 +1856,10 @@ function AppContent() {
17791856 < AcademyView
17801857 profile = { gamProfile }
17811858 onBack = { ( ) => setCurrentView ( 'DASHBOARD' ) }
1859+ onBuyItem = { buyShopItem }
1860+ onEquipOutfit = { equipOutfit }
1861+ onRerollChallenge = { rerollChallenge }
1862+ onUpdateDailyGoal = { updateDailyGoal }
17821863 t = { t }
17831864 />
17841865 ) }
@@ -1819,7 +1900,7 @@ function AppContent() {
18191900
18201901 { /* Bottom Nav (Only visible on Dashboard and Wallet/Profile root) */ }
18211902 { [ 'DASHBOARD' , 'WALLET' , 'PROFILE' , 'ANALYSIS' , 'TRANSACTIONS' , 'BUDGET' , 'SCHEDULED' , 'HEATMAP' , 'CURRENCY_PERF' , 'SHOPPING_LIST' , 'CONTACTS' , 'DEBT_TRACKER' , 'EXPORT' , 'FIN_CALENDAR' , 'IMPORT' , 'PDF_REPORT' , 'SCENARIO_PLANNER' ] . includes ( currentView ) && isNavVisible && ! showAdd && ! showSettings && (
1822- < div className = "h-20 bg-theme-surface/95 backdrop-blur-md border-t border-white/5 flex items-center justify-center gap-4 md:gap-24 px-2 relative z-10 pb-2 flex-shrink-0 w-full transition-all duration-300 animate-in slide-in-from-bottom-full" >
1903+ < div className = "h-20 bg-theme-surface/95 backdrop-blur-md border-t border-white/5 flex items-center justify-center gap-0 md:gap-24 px-2 relative z-10 pb-2 flex-shrink-0 w-full transition-all duration-300 animate-in slide-in-from-bottom-full" >
18231904 { ( ( ) => {
18241905 const NAV_ICON_MAP : Record < string , React . ReactNode > = {
18251906 DASHBOARD : < Home size = { 24 } /> ,
@@ -1934,6 +2015,8 @@ function AppContent() {
19342015 } as Transaction : null ) }
19352016 showAlert = { showAlert }
19362017 contacts = { contacts }
2018+ isDevMode = { isDevMode }
2019+ userProfile = { userProfile }
19372020 />
19382021 ) }
19392022
0 commit comments