From 1d4b59d7d52f81b6ad8c14ee0c3e75feb636837d Mon Sep 17 00:00:00 2001 From: Deni Date: Sat, 31 Dec 2022 12:54:33 +0300 Subject: [PATCH] Dont allow editing stat value without stat type chosen and dont allow setting stat type with any value(s) entered, when deleting stat type show info about entries that used it, fix bug with improving PBs + some UI, UX and DX improvements --- .../app/src/main/assets/index.android.bundle | 4 +- app/components/StatTypeModal.tsx | 21 +++- app/redux/mainSlice.ts | 115 ++++++++++-------- app/screens/AddEditEntry.tsx | 41 +++---- app/shared/GlobalFunctions.ts | 25 ++-- app/shared/GlobalStyles.ts | 8 +- app/shared/StorageManager.ts | 36 +++--- package.json | 5 +- 8 files changed, 146 insertions(+), 109 deletions(-) diff --git a/android/app/src/main/assets/index.android.bundle b/android/app/src/main/assets/index.android.bundle index 3c0f2eb..2cbe6a1 100644 --- a/android/app/src/main/assets/index.android.bundle +++ b/android/app/src/main/assets/index.android.bundle @@ -382,8 +382,8 @@ __d(function(g,r,i,a,m,_e,d){'use strict';function t(){if("undefined"==typeof Re __d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.DynamicColorIOS=void 0;e.DynamicColorIOS=function(o){throw new Error('DynamicColorIOS is not available on this platform.')}},376,[]); __d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;r(d[0])(r(d[1]));var t=r(d[2]),n=r(d[0])(r(d[3])),o=r(d[0])(r(d[4])),l=r(d[0])(r(d[5])),c=r(d[0])(r(d[6])),u=r(d[0])(r(d[7])),s=r(d[0])(r(d[8])),f=r(d[0])(r(d[9])),S=(0,r(d[10]).createNativeStackNavigator)(),h=function(){return(0,r(d[11]).jsx)(r(d[12]).Provider,{store:n.default,children:(0,r(d[11]).jsx)(t.View,{style:{flex:1},onStartShouldSetResponder:function(){return t.Keyboard.dismiss()},children:(0,r(d[11]).jsx)(r(d[13]).NavigationContainer,{children:(0,r(d[11]).jsxs)(S.Navigator,{initialRouteName:"Menu",screenOptions:{headerStyle:{backgroundColor:'red'},headerTintColor:'white',headerTitleStyle:{color:'white',fontWeight:'bold',fontSize:24},headerTitleAlign:'center'},children:[(0,r(d[11]).jsx)(S.Screen,{name:"Menu",component:o.default}),(0,r(d[11]).jsx)(S.Screen,{name:"Home",component:l.default}),(0,r(d[11]).jsx)(S.Screen,{name:"AddEditEntry",component:c.default}),(0,r(d[11]).jsx)(S.Screen,{name:"AddEditStatType",component:u.default}),(0,r(d[11]).jsx)(S.Screen,{name:"ImportExport",component:s.default}),(0,r(d[11]).jsx)(S.Screen,{name:"About",component:f.default})]})})})})};e.default=h},377,[3,124,1,378,399,547,550,558,561,562,563,177,417,452]); __d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0;var t=r(d[0])(r(d[1])),u=r(d[0])(r(d[2])),o=(0,r(d[3]).configureStore)({reducer:{main:t.default,importExport:u.default}});e.default=o},378,[3,379,398,390]); -__d(function(g,r,_i,_a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.setStatCategory=e.reorderStatTypes=e.initStatCategories=e.initLastCategoryId=e.editStatType=e.editStatCategory=e.editEntry=e.deleteStatType=e.deleteStatCategory=e.deleteEntry=e.default=e.addStatType=e.addStatCategory=e.addEntry=void 0;var t=r(d[0])(r(d[1])),a=(function(t,a){if(!a&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};var i=s(a);if(i&&i.has(t))return i.get(t);var l={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in t)if("default"!==o&&Object.prototype.hasOwnProperty.call(t,o)){var y=n?Object.getOwnPropertyDescriptor(t,o):null;y&&(y.get||y.set)?Object.defineProperty(l,o,y):l[o]=t[o]}l.default=t,i&&i.set(t,l);return l})(r(d[2]));function s(t){if("function"!=typeof WeakMap)return null;var a=new WeakMap,i=new WeakMap;return(s=function(t){return t?i:a})(t)}var i=function(t,a,s){var i=!1,l=s.stats.find(function(t){return t.type===a.id});if(l)if(a.multipleValues)if(a.pbs){var n=a.pbs.allTime.result,o=function(t){return'best'===t?a.higherIsBetter?'high':'low':t};['best','avg','sum'].forEach(function(y){(null===n[y]||l.multiValueStats[o(y)]>n[y]&&a.higherIsBetter||l.multiValueStats[o(y)]a.pbs.allTime.result&&a.higherIsBetter||l.values[0]=0;s--)i(t,a,t.entries[s])},n=function(t,s,n){var o=!1,y=function(a){if(a.trackPBs&&a.variant===r(d[4]).StatTypeVariant.NUMBER){var y=!1;if('delete'!==n&&(y=i(t,a,s)||y),'add'!==n&&(!y||a.multipleValues)){var p=!1,u=Object.assign({},a,{pbs:{allTime:{entryId:Object.assign({},a.pbs.allTime.entryId),result:Object.assign({},a.pbs.allTime.result)}}});a.multipleValues||a.pbs.allTime.entryId!==s.id?a.multipleValues&&['best','avg','sum'].forEach(function(t){a.pbs.allTime.entryId[t]===s.id&&(p=!0,u.pbs.allTime.entryId[t]=null,u.pbs.allTime.result[t]=null)}):(p=!0,u.pbs=null),p&&(l(t,u),u.multipleValues?null===u.pbs.allTime.entryId.best?(y=!0,delete a.pbs):['best','avg','sum'].find(function(t){return u.pbs.allTime.entryId[t]!==a.pbs.allTime.entryId[t]||u.pbs.allTime.result[t]!==a.pbs.allTime.result[t]})&&(y=!0,a.pbs=u.pbs):null===u.pbs?(y=!0,delete a.pbs):u.pbs.allTime.result===a.pbs.allTime.result&&u.pbs.allTime.entryId===a.pbs.allTime.entryId||(y=!0,a.pbs=u.pbs)),o=y||o}}};for(var p of t.statTypes)y(p);o&&a.setData(t.statCategory.id,'statTypes',t.statTypes)},o=(0,r(d[5]).createSlice)({name:'main-slice',initialState:{statCategories:[],statCategory:null,lastCategoryId:0,entries:[],statTypes:[]},reducers:{initStatCategories:function(t,a){t.statCategories=a.payload},initLastCategoryId:function(t,a){t.lastCategoryId=a.payload},addStatCategory:function(t,s){t.statCategories.unshift(s.payload),a.setStatCategories(t.statCategories),t.lastCategoryId++,a.setLastCategoryId(t.lastCategoryId)},editStatCategory:function(t,s){t.statCategories=t.statCategories.map(function(t){return t.id===s.payload.id?s.payload:t}),a.setStatCategories(t.statCategories)},deleteStatCategory:function(t,s){t.statCategories=t.statCategories.filter(function(t){return t.id!==s.payload.id}),a.deleteStatCategory(s.payload,t.statCategories)},setStatCategory:function(s,i){s.statCategory=i.payload.statCategory,s.statTypes=i.payload.statTypes,s.entries=i.payload.entries,s.statCategory.id!==s.statCategories[0].id&&(s.statCategories=[s.statCategory].concat((0,t.default)(s.statCategories.filter(function(t){return t.id!==s.statCategory.id}))),a.setStatCategories(s.statCategories))},addEntry:function(t,s){t.entries.unshift(s.payload),a.setData(t.statCategory.id,'entries',t.entries),n(t,s.payload,'add'),t.statCategory.lastEntryId++,t.statCategory.totalEntries++,t.statCategories=t.statCategories.map(function(a){return a.id===t.statCategory.id?t.statCategory:a}),a.setStatCategories(t.statCategories)},editEntry:function(t,s){t.entries=t.entries.map(function(t){return t.id===s.payload.id?s.payload:t}),a.setData(t.statCategory.id,'entries',t.entries),n(t,s.payload,'edit')},deleteEntry:function(t,s){t.entries=t.entries.filter(function(t){return t.id!==s.payload.id}),0===t.entries.length?a.deleteData(t.statCategory.id,'entries'):a.setData(t.statCategory.id,'entries',t.entries),n(t,s.payload,'delete'),t.statCategory.totalEntries=t.entries.length,t.statCategories=t.statCategories.map(function(a){return a.id===t.statCategory.id?t.statCategory:a}),a.setStatCategories(t.statCategories)},addStatType:function(t,s){t.statTypes.push(s.payload),a.setData(t.statCategory.id,'statTypes',t.statTypes),t.statCategory.lastStatTypeId++,t.statCategories=t.statCategories.map(function(a){return a.id===t.statCategory.id?t.statCategory:a}),a.setStatCategories(t.statCategories)},editStatType:function(t,s){t.statTypes=t.statTypes.map(function(i){return i.id===s.payload.id?(console.log('ST',JSON.stringify(s.payload),JSON.stringify(i)),i.trackPBs&&!s.payload.trackPBs?delete s.payload.pbs:!s.payload.trackPBs||i.trackPBs&&s.payload.higherIsBetter===i.higherIsBetter||l(t,s.payload),a.setData(t.statCategory.id,'statTypes',t.statTypes),s.payload):i}),a.setData(t.statCategory.id,'statTypes',t.statTypes)},reorderStatTypes:function(t,s){var i=s.payload,l=i.statType,n=i.up;t.statTypes=t.statTypes.map(function(t){var a=n&&t.id===l.id||!n&&t.order===l.order+1,s=!n&&t.id===l.id||n&&t.order===l.order-1;return a||s?Object.assign({},t,{order:t.order+(a?-1:1)}):t}).sort(function(t,a){return t.order-a.order}),a.setData(t.statCategory.id,'statTypes',t.statTypes)},deleteStatType:function(t,s){t.statTypes=t.statTypes.filter(function(t){return t.id!==s.payload}).map(function(t,a){return Object.assign({},t,{order:a+1})}),0===t.statTypes.length?a.deleteData(t.statCategory.id,'statTypes'):a.setData(t.statCategory.id,'statTypes',t.statTypes)}}}),y=o.actions,p=y.initStatCategories,u=y.initLastCategoryId,C=y.addStatCategory,f=y.editStatCategory,c=y.deleteStatCategory,T=y.setStatCategory,S=y.addEntry,b=y.editEntry,h=y.deleteEntry,I=y.addStatType,v=y.editStatType,E=y.reorderStatTypes,O=y.deleteStatType;e.deleteStatType=O,e.reorderStatTypes=E,e.editStatType=v,e.addStatType=I,e.deleteEntry=h,e.editEntry=b,e.addEntry=S,e.setStatCategory=T,e.deleteStatCategory=c,e.editStatCategory=f,e.addStatCategory=C,e.initLastCategoryId=u,e.initStatCategories=p;var B=o.reducer;e.default=B},379,[3,6,380,389,388,390]); -__d(function(g,r,_i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.setStatCategories=e.setLastCategoryId=e.setData=e.importData=e.getStatCategories=e.getLastCategoryId=e.getData=e.exportData=e.deleteStatCategory=e.deleteData=void 0;var t=r(d[0])(r(d[1])),o=r(d[0])(r(d[2])),n=(function(t,o){if(!o&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};var n=i(o);if(n&&n.has(t))return n.get(t);var l={},s=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var c in t)if("default"!==c&&Object.prototype.hasOwnProperty.call(t,c)){var u=s?Object.getOwnPropertyDescriptor(t,c):null;u&&(u.get||u.set)?Object.defineProperty(l,c,u):l[c]=t[c]}l.default=t,n&&n.set(t,l);return l})(r(d[3]));function i(t){if("function"!=typeof WeakMap)return null;var o=new WeakMap,n=new WeakMap;return(i=function(t){return t?n:o})(t)}var l,s=(l=(0,t.default)(function*(t,n){var i=t+'_'+n;try{console.log("Getting data for key "+i);var l=yield o.default.getItem(i),s=JSON.parse(l);if(console.log(l),s)return s;throw new Error('Retrieved data is invalid')}catch(t){console.log("Error while searching for key "+i+":"),console.log(t)}return null}),function(t,o){return l.apply(this,arguments)});e.getData=s;var c,u=(c=(0,t.default)(function*(t,n,i){var l=t+'_'+n;try{var s=JSON.stringify(i);console.log("Setting data for key "+l+":"),console.log(s),yield o.default.setItem(l,s)}catch(t){console.log("Error while setting data for key "+l+":"),console.log(t)}}),function(t,o,n){return c.apply(this,arguments)});e.setData=u;var f,y=(f=(0,t.default)(function*(t,n){var i=t+'_'+n;try{console.log("Deleting data for key "+i),yield o.default.removeItem(i)}catch(t){console.log("Error while deleting data at key "+i+":"),console.log(t)}}),function(t,o){return f.apply(this,arguments)});e.deleteData=y;var p,v=(p=(0,t.default)(function*(){try{console.log('Getting statCategories');var t=JSON.parse(yield o.default.getItem('statCategories'));if(console.log(t),(null==t?void 0:t.length)>0&&'number'==typeof t[0].id)return t}catch(t){console.log("Error while retrieving stat categories: "+t)}return null}),function(){return p.apply(this,arguments)});e.getStatCategories=v;var h,k=(h=(0,t.default)(function*(){try{console.log('Getting lastCategoryId');var t=yield o.default.getItem('lastCategoryId');return null===t?(console.error('lastCategoryId not found'),null):(console.log(t),Number(t))}catch(t){console.error("Error while retrieving lastCategoryId: "+t)}return null}),function(){return h.apply(this,arguments)});e.getLastCategoryId=k;var C,I=(C=(0,t.default)(function*(t){try{console.log("Setting lastCategoryId to "+t),yield o.default.setItem('lastCategoryId',String(t))}catch(t){console.error("Error while incrementing lastCategoryId: "+t)}}),function(t){return C.apply(this,arguments)});e.setLastCategoryId=I;var S,b=(S=(0,t.default)(function*(t){try{console.log('Setting statCategories to:'),console.log(t),yield o.default.setItem('statCategories',JSON.stringify(t))}catch(t){console.log("Error while setting stat categories: "+t)}}),function(t){return S.apply(this,arguments)});e.setStatCategories=b;var w,D=(w=(0,t.default)(function*(t,o){try{for(var n of(console.log("Deleting stat category "+t.name),r(d[4]).dataPoints))yield y(t.id,n);yield b(o)}catch(o){console.log("Error while deleting stat category "+t.name+":"),console.log(o)}}),function(t,o){return w.apply(this,arguments)});e.deleteStatCategory=D;var O,E=(O=(0,t.default)(function*(t,o){try{console.log('Importing backup file');var i=yield n.openDocument(!0,'utf8');console.log('Backup file data:',i.data);var l=JSON.parse(i.data);if(l.lastCategoryId>o&&I(l.lastCategoryId),l.statCategories){var s='Successfully imported backup',c=[];for(var f of(t.length&&console.log("Ignoring stat categories: "+t),l.statCategories=l.statCategories.filter(function(o){return!t.find(function(t){return t.id===o.id||t.name===o.name})||(c.push(o.name),!1)}),c.length>0&&(s+=', but these stat categories in the backup were skipped due to the IDs or names overlapping with one of your existing stat categories: ',c.forEach(function(t){return s+=t+", "}),s=s.slice(0,-2)),b(l.statCategories),r(d[4]).dataPoints))for(var y of l.statCategories)u(y.id,f,l[f][y.id]);return{message:s,error:''}}return{error:'Backup file is invalid',message:''}}catch(t){return{error:"Error while importing backup file: "+t,message:''}}}),function(t,o){return O.apply(this,arguments)});e.importData=E;var P,_=(P=(0,t.default)(function*(){try{console.log('Exporting backup file');var t=yield J();if(t){var o='Stat_Tracker_Backup_'+(0,r(d[5]).formatDate)(new Date,!1),i={statCategories:(yield v())||[],lastCategoryId:yield k(),statTypes:{},entries:{}};for(var l of i.statCategories)for(var c of r(d[4]).dataPoints)i[c][l.id]=yield s(l.id,c);return console.log('Data to be exported:',JSON.stringify(i)),yield n.writeFile(t.uri,JSON.stringify(i),o,'application/json','utf8'),{message:"Successfully exported backup file as "+o+".json",error:''}}return{error:'Error while getting permission to backup directory',message:''}}catch(t){return{error:String(t),message:''}}}),function(){return P.apply(this,arguments)});e.exportData=_;var N,J=(N=(0,t.default)(function*(){var t=JSON.parse(yield o.default.getItem('backupDirectory')),i=yield n.getPersistedUriPermissions(),l=!1;if(console.log('Backup directory info:',t),console.log('Persisted URIs info:',i),t)try{var s=yield n.listFiles(t.uri);console.log('Files in backup directory:',s)}catch(t){console.log('Backup directory does not exist'),l=!0}else console.log('Backup directory not in async storage'),l=!0;if(l||i.find(function(o){return t.uri.includes(o)})||(console.log('Backup directory not in persisted URIs'),l=!0),l){if(console.log('Requesting new backup directory'),!(t=yield n.openDocumentTree(!0)))return console.log('Still no backup directory available'),null;console.log("Setting backup directory to "+JSON.stringify(t)),yield o.default.setItem('backupDirectory',JSON.stringify(t))}return t}),function(){return N.apply(this,arguments)})},380,[3,267,381,387,388,389]); +__d(function(g,r,_i,_a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.setStatCategory=e.reorderStatTypes=e.initStatCategories=e.initLastCategoryId=e.editStatType=e.editStatCategory=e.editEntry=e.deleteStatType=e.deleteStatCategory=e.deleteEntry=e.default=e.addStatType=e.addStatCategory=e.addEntry=void 0;var t=r(d[0])(r(d[1])),a=(function(t,a){if(!a&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};var i=s(a);if(i&&i.has(t))return i.get(t);var n={},l=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in t)if("default"!==o&&Object.prototype.hasOwnProperty.call(t,o)){var y=l?Object.getOwnPropertyDescriptor(t,o):null;y&&(y.get||y.set)?Object.defineProperty(n,o,y):n[o]=t[o]}n.default=t,i&&i.set(t,n);return n})(r(d[2]));function s(t){if("function"!=typeof WeakMap)return null;var a=new WeakMap,i=new WeakMap;return(s=function(t){return t?i:a})(t)}var i=function(t,a,s){console.log("Checking if entry "+s.id+" has the PB for stat type "+a.name);var i=!1,n=s.stats.find(function(t){return t.type===a.id});if(n)if(a.multipleValues)if(a.pbs){var l=a.pbs.allTime.result,o=function(t){return'best'===t?a.higherIsBetter?'high':'low':t};['best','avg','sum'].forEach(function(y){(null===l[y]||n.multiValueStats[o(y)]>l[y]&&a.higherIsBetter||n.multiValueStats[o(y)]a.pbs.allTime.result&&a.higherIsBetter||n.values[0]=0;s--)i(t,a,t.entries[s])},l=function(t,s,l){var o=!1,y=function(a){if(a.trackPBs&&a.variant===r(d[4]).StatTypeVariant.NUMBER){console.log("Updating PB for stat type "+a.name);var y=!1;if('delete'!==l&&(y=i(t,a,s)||y),'add'!==l&&(!y||a.multipleValues)){var p=!1,u=Object.assign({},a,{pbs:{allTime:{entryId:Object.assign({},a.pbs.allTime.entryId),result:Object.assign({},a.pbs.allTime.result)}}});a.multipleValues||a.pbs.allTime.entryId!==s.id?a.multipleValues&&['best','avg','sum'].forEach(function(t){a.pbs.allTime.entryId[t]===s.id&&(p=!0,u.pbs.allTime.entryId[t]=null,u.pbs.allTime.result[t]=null)}):(p=!0,u.pbs=null),p&&(n(t,u),u.multipleValues?null===u.pbs.allTime.entryId.best?(y=!0,delete a.pbs):['best','avg','sum'].find(function(t){return u.pbs.allTime.entryId[t]!==a.pbs.allTime.entryId[t]||u.pbs.allTime.result[t]!==a.pbs.allTime.result[t]})&&(y=!0,a.pbs=u.pbs):null===u.pbs?(y=!0,delete a.pbs):u.pbs.allTime.result===a.pbs.allTime.result&&u.pbs.allTime.entryId===a.pbs.allTime.entryId||(y=!0,a.pbs=u.pbs)),o=y||o}}};for(var p of t.statTypes)y(p);o&&a.setData(t.statCategory.id,'statTypes',t.statTypes)},o=(0,r(d[5]).createSlice)({name:'main-slice',initialState:{statCategories:[],statCategory:null,lastCategoryId:0,entries:[],statTypes:[]},reducers:{initStatCategories:function(t,a){t.statCategories=a.payload},initLastCategoryId:function(t,a){t.lastCategoryId=a.payload},addStatCategory:function(t,s){t.statCategories.unshift(s.payload),a.setStatCategories(t.statCategories),t.lastCategoryId++,a.setLastCategoryId(t.lastCategoryId)},editStatCategory:function(t,s){t.statCategories=t.statCategories.map(function(t){return t.id===s.payload.id?s.payload:t}),a.setStatCategories(t.statCategories)},deleteStatCategory:function(t,s){t.statCategories=t.statCategories.filter(function(t){return t.id!==s.payload.id}),a.deleteStatCategory(s.payload,t.statCategories)},setStatCategory:function(s,i){s.statCategory=i.payload.statCategory,s.statTypes=i.payload.statTypes,s.entries=i.payload.entries,s.statCategory.id!==s.statCategories[0].id&&(s.statCategories=[s.statCategory].concat((0,t.default)(s.statCategories.filter(function(t){return t.id!==s.statCategory.id}))),a.setStatCategories(s.statCategories))},addEntry:function(t,s){t.entries.unshift(s.payload),a.setData(t.statCategory.id,'entries',t.entries),l(t,s.payload,'add'),t.statCategory.lastEntryId++,t.statCategory.totalEntries++,t.statCategories=t.statCategories.map(function(a){return a.id===t.statCategory.id?t.statCategory:a}),a.setStatCategories(t.statCategories)},editEntry:function(t,s){t.entries=t.entries.map(function(t){return t.id===s.payload.id?s.payload:t}),a.setData(t.statCategory.id,'entries',t.entries),l(t,s.payload,'edit')},deleteEntry:function(t,s){t.entries=t.entries.filter(function(t){return t.id!==s.payload.id}),0===t.entries.length?a.deleteData(t.statCategory.id,'entries'):a.setData(t.statCategory.id,'entries',t.entries),l(t,s.payload,'delete'),t.statCategory.totalEntries=t.entries.length,t.statCategories=t.statCategories.map(function(a){return a.id===t.statCategory.id?t.statCategory:a}),a.setStatCategories(t.statCategories)},addStatType:function(t,s){t.statTypes.push(s.payload),a.setData(t.statCategory.id,'statTypes',t.statTypes),t.statCategory.lastStatTypeId++,t.statCategories=t.statCategories.map(function(a){return a.id===t.statCategory.id?t.statCategory:a}),a.setStatCategories(t.statCategories)},editStatType:function(t,s){t.statTypes=t.statTypes.map(function(i){return i.id===s.payload.id?(i.trackPBs&&!s.payload.trackPBs?delete s.payload.pbs:!s.payload.trackPBs||i.trackPBs&&s.payload.higherIsBetter===i.higherIsBetter||n(t,s.payload),a.setData(t.statCategory.id,'statTypes',t.statTypes),s.payload):i}),a.setData(t.statCategory.id,'statTypes',t.statTypes)},reorderStatTypes:function(t,s){var i=s.payload,n=i.statType,l=i.up;t.statTypes=t.statTypes.map(function(t){var a=l&&t.id===n.id||!l&&t.order===n.order+1,s=!l&&t.id===n.id||l&&t.order===n.order-1;return a||s?Object.assign({},t,{order:t.order+(a?-1:1)}):t}).sort(function(t,a){return t.order-a.order}),a.setData(t.statCategory.id,'statTypes',t.statTypes)},deleteStatType:function(t,s){t.statTypes=t.statTypes.filter(function(t){return t.id!==s.payload}).map(function(t,a){return Object.assign({},t,{order:a+1})}),0===t.statTypes.length?a.deleteData(t.statCategory.id,'statTypes'):a.setData(t.statCategory.id,'statTypes',t.statTypes)}}}),y=o.actions,p=y.initStatCategories,u=y.initLastCategoryId,C=y.addStatCategory,f=y.editStatCategory,c=y.deleteStatCategory,T=y.setStatCategory,b=y.addEntry,S=y.editEntry,h=y.deleteEntry,I=y.addStatType,v=y.editStatType,E=y.reorderStatTypes,B=y.deleteStatType;e.deleteStatType=B,e.reorderStatTypes=E,e.editStatType=v,e.addStatType=I,e.deleteEntry=h,e.editEntry=S,e.addEntry=b,e.setStatCategory=T,e.deleteStatCategory=c,e.editStatCategory=f,e.addStatCategory=C,e.initLastCategoryId=u,e.initStatCategories=p;var O=o.reducer;e.default=O},379,[3,6,380,389,388,390]); +__d(function(g,r,_i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.setStatCategories=e.setLastCategoryId=e.setData=e.importData=e.getStatCategories=e.getLastCategoryId=e.getData=e.exportData=e.deleteStatCategory=e.deleteData=void 0;var t=r(d[0])(r(d[1])),i=r(d[0])(r(d[2])),o=(function(t,i){if(!i&&t&&t.__esModule)return t;if(null===t||"object"!=typeof t&&"function"!=typeof t)return{default:t};var o=n(i);if(o&&o.has(t))return o.get(t);var l={},s=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var u in t)if("default"!==u&&Object.prototype.hasOwnProperty.call(t,u)){var c=s?Object.getOwnPropertyDescriptor(t,u):null;c&&(c.get||c.set)?Object.defineProperty(l,u,c):l[u]=t[u]}l.default=t,o&&o.set(t,l);return l})(r(d[3]));function n(t){if("function"!=typeof WeakMap)return null;var i=new WeakMap,o=new WeakMap;return(n=function(t){return t?o:i})(t)}var l,s=(l=(0,t.default)(function*(t,o){var n=t+'_'+o;try{var l=yield i.default.getItem(n),s=JSON.parse(l);if(s)return s;throw new Error('Retrieved data is invalid')}catch(t){console.log("Error while searching for key "+n+":"),console.log(t)}return null}),function(t,i){return l.apply(this,arguments)});e.getData=s;var u,c=(u=(0,t.default)(function*(t,o,n){var l=t+'_'+o;try{var s=JSON.stringify(n);yield i.default.setItem(l,s)}catch(t){console.log("Error while setting data for key "+l+":"),console.log(t)}}),function(t,i,o){return u.apply(this,arguments)});e.setData=c;var f,y=(f=(0,t.default)(function*(t,o){var n=t+'_'+o;try{yield i.default.removeItem(n)}catch(t){console.log("Error while deleting data at key "+n+":"),console.log(t)}}),function(t,i){return f.apply(this,arguments)});e.deleteData=y;var p,h=(p=(0,t.default)(function*(){try{var t=JSON.parse(yield i.default.getItem('statCategories'));if((null==t?void 0:t.length)>0&&'number'==typeof t[0].id)return t}catch(t){console.log("Error while retrieving stat categories: "+t)}return null}),function(){return p.apply(this,arguments)});e.getStatCategories=h;var v,C=(v=(0,t.default)(function*(){try{var t=yield i.default.getItem('lastCategoryId');return null===t?(console.error('lastCategoryId not found'),null):Number(t)}catch(t){console.error("Error while retrieving lastCategoryId: "+t)}return null}),function(){return v.apply(this,arguments)});e.getLastCategoryId=C;var I,w=(I=(0,t.default)(function*(t){try{yield i.default.setItem('lastCategoryId',String(t))}catch(t){console.error("Error while incrementing lastCategoryId: "+t)}}),function(t){return I.apply(this,arguments)});e.setLastCategoryId=w;var D,S=(D=(0,t.default)(function*(t){try{yield i.default.setItem('statCategories',JSON.stringify(t))}catch(t){console.log("Error while setting stat categories: "+t)}}),function(t){return D.apply(this,arguments)});e.setStatCategories=S;var b,k=(b=(0,t.default)(function*(t,i){try{for(var o of r(d[4]).dataPoints)yield y(t.id,o);yield S(i)}catch(i){console.log("Error while deleting stat category "+t.name+":"),console.log(i)}}),function(t,i){return b.apply(this,arguments)});e.deleteStatCategory=k;var O,E=(O=(0,t.default)(function*(t,i){try{var n=yield o.openDocument(!0,'utf8'),l=JSON.parse(n.data);if(l.lastCategoryId>i&&w(l.lastCategoryId),l.statCategories){var s='Successfully imported backup',u=[];for(var f of(l.statCategories=l.statCategories.filter(function(i){return!t.find(function(t){return t.id===i.id||t.name===i.name})||(u.push(i.name),!1)}),u.length>0&&(s+=', but these stat categories in the backup were skipped due to the IDs or names overlapping with one of your existing stat categories: ',u.forEach(function(t){return s+=t+", "}),s=s.slice(0,-2)),S(l.statCategories),r(d[4]).dataPoints))for(var y of l.statCategories)c(y.id,f,l[f][y.id]);return{message:s,error:''}}return{error:'Backup file is invalid',message:''}}catch(t){return{error:"Error while importing backup file: "+t,message:''}}}),function(t,i){return O.apply(this,arguments)});e.importData=E;var _,P=(_=(0,t.default)(function*(){try{var t=yield N();if(t){var i='Stat_Tracker_Backup_'+(0,r(d[5]).formatDate)(new Date,!1),n={statCategories:(yield h())||[],lastCategoryId:yield C(),statTypes:{},entries:{}};for(var l of n.statCategories)for(var u of r(d[4]).dataPoints)n[u][l.id]=yield s(l.id,u);return yield o.writeFile(t.uri,JSON.stringify(n),i,'application/json','utf8'),{message:"Successfully exported backup file as "+i+".json",error:''}}return{error:'Error while getting permission to backup directory',message:''}}catch(t){return{error:String(t),message:''}}}),function(){return _.apply(this,arguments)});e.exportData=P;var j,N=(j=(0,t.default)(function*(){var t=JSON.parse(yield i.default.getItem('backupDirectory')),n=yield o.getPersistedUriPermissions(),l=!1;if(t)try{yield o.listFiles(t.uri)}catch(t){l=!0}else l=!0;if(l||n.find(function(i){return t.uri.includes(i)})||(l=!0),l){if(!(t=yield o.openDocumentTree(!0)))return null;yield i.default.setItem('backupDirectory',JSON.stringify(t))}return t}),function(){return j.apply(this,arguments)})},380,[3,267,381,387,388,389]); __d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.default=void 0,Object.defineProperty(e,"useAsyncStorage",{enumerable:!0,get:function(){return r(d[0]).useAsyncStorage}});var t=r(d[1])(r(d[2])).default;e.default=t},381,[382,3,383]); __d(function(g,r,i,a,m,e,d){Object.defineProperty(e,"__esModule",{value:!0}),e.useAsyncStorage=function(n){return{getItem:function(){for(var u=arguments.length,f=new Array(u),o=0;o void; }> = ({ modalOpen, setStatModalOpen, filteredStatTypes, selectStatType, onAddStatType, onEditStatType }) => { const dispatch = useDispatch(); - const { statTypes } = useSelector((state: RootState) => state.main); + const { statTypes, entries } = useSelector((state: RootState) => state.main); const [reordering, setReordering] = useState(false); @@ -28,7 +29,19 @@ const ChooseStatModal: React.FC<{ }; const onDeleteStatType = (statType: IStatType) => { - Alert.alert('Confirmation', `Are you sure you want to delete the stat type ${statType.name}?`, [ + let message = `Are you sure you want to delete the stat type ${statType.name}?`; + const orphanEntries = entries.filter((el) => !!el.stats.find((st) => st.type === statType.id)); + + if (orphanEntries.length > 0) { + message += ` You have ${orphanEntries.length} entries that use it! They were made on these dates: `; + const iterations = Math.min(3, orphanEntries.length); + for (let i = 0; i < iterations; i++) { + message += formatIDate(orphanEntries[i].date); + message += i !== iterations - 1 ? ', ' : ' ...'; + } + } + + Alert.alert(orphanEntries.length === 0 ? 'Confirmation' : 'WARNING!', message, [ { text: 'Cancel' }, { text: 'Ok', @@ -36,9 +49,7 @@ const ChooseStatModal: React.FC<{ dispatch(deleteStatType(statType.id)); // -1, because it won't be updated until the next tick - if (statTypes.length - 1 === 0) { - setStatModalOpen(false); - } + if (statTypes.length - 1 === 0) setStatModalOpen(false); }, }, ]); diff --git a/app/redux/mainSlice.ts b/app/redux/mainSlice.ts index 6866ca8..14dc133 100644 --- a/app/redux/mainSlice.ts +++ b/app/redux/mainSlice.ts @@ -10,7 +10,7 @@ import { StatTypeVariant, } from '../shared/DataStructure'; -const verbose = true; +const verbose = false; //////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// @@ -127,70 +127,83 @@ const updatePBs = (state: any, entry: IEntry, mode: 'add' | 'edit' | 'delete') = // Update PB if it could have gotten worse // Skip checking PB if it was already updated and the stat type only has single values if (mode !== 'add' && (!pbUpdated || statType.multipleValues)) { - let isPrevPB = false; - const tempStatType: IStatType = { - ...statType, - pbs: { - allTime: { - entryId: { ...statType.pbs.allTime.entryId }, - result: { ...statType.pbs.allTime.result }, + if (statType.pbs) { + let isPrevPB = false; + const tempStatType: IStatType = { + ...statType, + pbs: { + allTime: { + entryId: { ...statType.pbs.allTime.entryId }, + result: { ...statType.pbs.allTime.result }, + }, }, - }, - }; + }; + + if (!statType.multipleValues && statType.pbs.allTime.entryId === entry.id) { + isPrevPB = true; + tempStatType.pbs = null; + } else if (statType.multipleValues) { + ['best', 'avg', 'sum'].forEach((key) => { + if (statType.pbs.allTime.entryId[key] === entry.id) { + isPrevPB = true; + tempStatType.pbs.allTime.entryId[key] = null; + tempStatType.pbs.allTime.result[key] = null; + } + }); + } - if (!statType.multipleValues && statType.pbs.allTime.entryId === entry.id) { - isPrevPB = true; - tempStatType.pbs = null; - } else if (statType.multipleValues) { - ['best', 'avg', 'sum'].forEach((key) => { - if (statType.pbs.allTime.entryId[key] === entry.id) { - isPrevPB = true; - tempStatType.pbs.allTime.entryId[key] = null; - tempStatType.pbs.allTime.result[key] = null; - } - }); - } + if (isPrevPB) { + checkPBFromScratch(state, tempStatType); - if (isPrevPB) { - checkPBFromScratch(state, tempStatType); - - if (!tempStatType.multipleValues) { - // If this is null, that means no entries are left with this stat type - if (tempStatType.pbs === null) { - pbUpdated = true; - delete statType.pbs; - } else if ( - tempStatType.pbs.allTime.result !== statType.pbs.allTime.result || - tempStatType.pbs.allTime.entryId !== statType.pbs.allTime.entryId - ) { - pbUpdated = true; - statType.pbs = tempStatType.pbs; - } - } else { - // If this is null, that means no entries are left with this stat type. - // It doesn't have to be best, because avg and sum would also be null if best is null. - if (tempStatType.pbs.allTime.entryId['best'] === null) { - pbUpdated = true; - delete statType.pbs; - } else { - if ( - !!['best', 'avg', 'sum'].find( - (key) => - tempStatType.pbs.allTime.entryId[key] !== statType.pbs.allTime.entryId[key] || - tempStatType.pbs.allTime.result[key] !== statType.pbs.allTime.result[key], - ) + if (!tempStatType.multipleValues) { + // If this is null, that means no entries are left with this stat type + if (tempStatType.pbs === null) { + pbUpdated = true; + delete statType.pbs; + } else if ( + tempStatType.pbs.allTime.result !== statType.pbs.allTime.result || + tempStatType.pbs.allTime.entryId !== statType.pbs.allTime.entryId ) { pbUpdated = true; statType.pbs = tempStatType.pbs; } + } else { + // If this is null, that means no entries are left with this stat type. + // It doesn't have to be best, because avg and sum would also be null if best is null. + if (tempStatType.pbs.allTime.entryId['best'] === null) { + pbUpdated = true; + delete statType.pbs; + } else { + if ( + !!['best', 'avg', 'sum'].find( + (key) => + tempStatType.pbs.allTime.entryId[key] !== statType.pbs.allTime.entryId[key] || + tempStatType.pbs.allTime.result[key] !== statType.pbs.allTime.result[key], + ) + ) { + pbUpdated = true; + statType.pbs = tempStatType.pbs; + } + } } } + } else { + console.error('Stat type has no PB, which cannot be the case!'); } + } + + PBsUpdated = pbUpdated || PBsUpdated; - PBsUpdated = pbUpdated || PBsUpdated; + if (verbose) { + if (pbUpdated) { + console.log('PB updated to: ', JSON.stringify(statType.pbs, null, 2)); + } else { + console.log('PB not updated'); + } } } } + console.log(PBsUpdated); if (PBsUpdated) SM.setData(state.statCategory.id, 'statTypes', state.statTypes); }; diff --git a/app/screens/AddEditEntry.tsx b/app/screens/AddEditEntry.tsx index ab477b1..fcc2901 100644 --- a/app/screens/AddEditEntry.tsx +++ b/app/screens/AddEditEntry.tsx @@ -22,7 +22,7 @@ const AddEditEntry = ({ navigation, route }) => { // Stat choice from the list of filtered stat types const [selectedStatType, setSelectedStatType] = useState(statTypes[0] || null); // The type here is different from the type of values in IStat - const [statValues, setStatValues] = useState>(['']); + const [statValues, setStatValues] = useState(['']); const [comment, setComment] = useState(''); const [date, setDate] = useState(new Date()); const [textDate, setTextDate] = useState(''); @@ -87,7 +87,7 @@ const AddEditEntry = ({ navigation, route }) => { return false; } else if ( selectedStatType.variant === StatTypeVariant.NUMBER && - statValues.find((el: string | number) => isNaN(Number(el))) !== undefined + !!statValues.find((el: string) => isNaN(Number(el))) ) { if (showAlerts) { const error = selectedStatType.multipleValues @@ -100,10 +100,8 @@ const AddEditEntry = ({ navigation, route }) => { }; const updateStatValues = (index: number, value: string) => { - setStatValues((prevStatValues) => { - const newStatValues = prevStatValues.map((prevValue: string | number, i) => - i === index ? value : prevValue, - ); + setStatValues((prevStatValues: string[]) => { + const newStatValues = prevStatValues.map((prevValue, i) => (i === index ? value : prevValue)); // Add extra value input, if no empty ones are left and the stat type allows multiple values if (selectedStatType?.multipleValues && newStatValues.findIndex((val) => val === '') === -1) { @@ -116,11 +114,11 @@ const AddEditEntry = ({ navigation, route }) => { // Assumes the new stat is valid const getNewStats = (prevStats = stats): IStat[] => { - let formatted; + let formatted = statValues.filter((val) => val !== '') as string[] | number[]; const mvs = {} as IMultiValueStat; if (selectedStatType.variant === StatTypeVariant.NUMBER) { - formatted = statValues.filter((val) => val !== '').map((val) => Number(val)) as number[]; + formatted = formatted.map((val) => Number(val)); if (selectedStatType.multipleValues) { mvs.sum = formatted.reduce((acc, val) => acc + val, 0); @@ -128,8 +126,6 @@ const AddEditEntry = ({ navigation, route }) => { mvs.high = Math.max(...formatted); mvs.avg = Math.round((mvs.sum / formatted.length + Number.EPSILON) * 100) / 100; } - } else { - formatted = statValues.filter((val) => val !== '').map((val) => String(val)) as string[]; } const newStat: IStat = { @@ -161,7 +157,7 @@ const AddEditEntry = ({ navigation, route }) => { const newValues = statTypes.find((el) => el.id === stat.type)?.multipleValues ? [...stat.values, ''] : stat.values; - setStatValues(newValues); + setStatValues(newValues.map((el) => String(el))); selectStatType(stat.type); } }; @@ -250,28 +246,31 @@ const AddEditEntry = ({ navigation, route }) => { {/* Stat */} {selectedStatType ? ( - + {selectedStatType.name} {selectedStatType.unit ? ` (${selectedStatType.unit})` : ''} ) : ( - Stat - )} - {filteredStatTypes.length === 0 ? ( -