fix: habits statistics
This commit is contained in:
parent
ca122e9fce
commit
e15a3982fd
@ -1,4 +1,5 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"conventions",
|
||||
"plugin:react/recommended",
|
||||
@ -15,9 +16,6 @@
|
||||
"version": "detect"
|
||||
}
|
||||
},
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"react/react-in-jsx-scope": "off",
|
||||
"react/prop-types": "off",
|
||||
@ -35,8 +33,9 @@
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"rules": {
|
||||
"@typescript-eslint/member-delimiter-style": "off"
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
@ -45,7 +45,7 @@ const TabLayout: React.FC = () => {
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="habits/stats"
|
||||
name="habits/statistics"
|
||||
options={{
|
||||
title: "Statistics",
|
||||
tabBarIcon: ({ color }) => {
|
||||
|
23
app/application/habits/statistics.tsx
Normal file
23
app/application/habits/statistics.tsx
Normal file
@ -0,0 +1,23 @@
|
||||
import { SafeAreaView } from "react-native-safe-area-context"
|
||||
|
||||
import { HabitsStatistics } from "@/presentation/react-native/components/HabitsStatistics"
|
||||
import { useHabitsTracker } from "@/presentation/react/contexts/HabitsTracker"
|
||||
|
||||
const StatisticsPage: React.FC = () => {
|
||||
const { habitsTracker } = useHabitsTracker()
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
style={[
|
||||
{
|
||||
flex: 1,
|
||||
backgroundColor: "white",
|
||||
},
|
||||
]}
|
||||
>
|
||||
<HabitsStatistics habitsTracker={habitsTracker} />
|
||||
</SafeAreaView>
|
||||
)
|
||||
}
|
||||
|
||||
export default StatisticsPage
|
@ -1,10 +0,0 @@
|
||||
import { Stats } from "@/presentation/react/components/Stats/Stats"
|
||||
import { useHabitsTracker } from "@/presentation/react/contexts/HabitsTracker"
|
||||
|
||||
const StatsPage: React.FC = () => {
|
||||
const { habitsTracker } = useHabitsTracker()
|
||||
|
||||
return <Stats habitsTracker={habitsTracker} />
|
||||
}
|
||||
|
||||
export default StatsPage
|
@ -11,6 +11,12 @@ export const GOAL_FREQUENCIES = GOAL_FREQUENCIES_ZOD.map((frequency) => {
|
||||
})
|
||||
export type GoalFrequency = (typeof GOAL_FREQUENCIES)[number]
|
||||
|
||||
export const GOAL_FREQUENCIES_TYPES = {
|
||||
daily: "day",
|
||||
weekly: "week",
|
||||
monthly: "month",
|
||||
} as const
|
||||
|
||||
export const GOAL_TYPES_ZOD = [
|
||||
z.literal("boolean"),
|
||||
z.literal("numeric"),
|
||||
|
@ -96,4 +96,29 @@ export class HabitsTracker implements HabitsTrackerData {
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
public getHabitsStatisticsByDateAndFrequency({
|
||||
selectedDate,
|
||||
frequency,
|
||||
}: {
|
||||
selectedDate: Date
|
||||
frequency: GoalFrequency
|
||||
}): {
|
||||
totalGoalsSuccess: number
|
||||
totalGoals: number
|
||||
} {
|
||||
const habitsHistory = this.getHabitsHistoriesByDate({
|
||||
selectedDate,
|
||||
frequency,
|
||||
})
|
||||
let totalGoalsSuccess = 0
|
||||
const totalGoals = habitsHistory.length
|
||||
for (const habitHistory of habitsHistory) {
|
||||
const goalProgress = habitHistory.getGoalProgressByDate(selectedDate)
|
||||
if (goalProgress.isCompleted()) {
|
||||
totalGoalsSuccess++
|
||||
}
|
||||
}
|
||||
return { totalGoalsSuccess, totalGoals }
|
||||
}
|
||||
}
|
||||
|
539
package-lock.json
generated
539
package-lock.json
generated
@ -13,7 +13,7 @@
|
||||
"@fortawesome/fontawesome-svg-core": "6.5.2",
|
||||
"@fortawesome/free-solid-svg-icons": "6.5.2",
|
||||
"@fortawesome/react-native-fontawesome": "0.3.1",
|
||||
"@hookform/resolvers": "3.4.0",
|
||||
"@hookform/resolvers": "3.4.2",
|
||||
"@react-native-async-storage/async-storage": "1.23.1",
|
||||
"@react-navigation/native": "6.1.17",
|
||||
"@supabase/supabase-js": "2.43.2",
|
||||
@ -28,7 +28,7 @@
|
||||
"lottie-react-native": "6.7.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-hook-form": "7.51.4",
|
||||
"react-hook-form": "7.51.5",
|
||||
"react-native": "0.74.1",
|
||||
"react-native-calendars": "1.1305.0",
|
||||
"react-native-circular-progress-indicator": "4.4.2",
|
||||
@ -57,21 +57,21 @@
|
||||
"@types/node": "20.12.12",
|
||||
"@types/react": "18.2.79",
|
||||
"@types/react-test-renderer": "18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.9.0",
|
||||
"@typescript-eslint/parser": "7.9.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.10.0",
|
||||
"@typescript-eslint/parser": "7.10.0",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-conventions": "14.1.0",
|
||||
"eslint-config-conventions": "14.2.0",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"eslint-plugin-react": "7.34.1",
|
||||
"eslint-plugin-react-hooks": "4.6.2",
|
||||
"eslint-plugin-react-native": "4.1.0",
|
||||
"eslint-plugin-unicorn": "51.0.1",
|
||||
"eslint-plugin-unicorn": "53.0.0",
|
||||
"husky": "9.0.11",
|
||||
"jest": "29.7.0",
|
||||
"jest-expo": "51.0.2",
|
||||
"jest-junit": "16.0.0",
|
||||
"lint-staged": "15.2.2",
|
||||
"lint-staged": "15.2.4",
|
||||
"prettier": "3.2.5",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"supabase": "1.167.4",
|
||||
@ -4362,9 +4362,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@hookform/resolvers": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.4.0.tgz",
|
||||
"integrity": "sha512-+oAqK3okmoEDnvUkJ3N/mvNMeeMv5Apgy1jkoRmlaaAF4vBgcJs9tHvtXU7VE4DvPosvAUUkPOaNFunzt1dbgA==",
|
||||
"version": "3.4.2",
|
||||
"resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-3.4.2.tgz",
|
||||
"integrity": "sha512-1m9uAVIO8wVf7VCDAGsuGA0t6Z3m6jVGAN50HkV9vYLl0yixKK/Z1lr01vaRvYCkIKGoy1noVRxMzQYb4y/j1Q==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"react-hook-form": "^7.0.0"
|
||||
@ -8751,9 +8751,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@types/babel__traverse": {
|
||||
"version": "7.20.5",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.5.tgz",
|
||||
"integrity": "sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==",
|
||||
"version": "7.20.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz",
|
||||
"integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -8966,17 +8966,17 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@typescript-eslint/eslint-plugin": {
|
||||
"version": "7.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.9.0.tgz",
|
||||
"integrity": "sha512-6e+X0X3sFe/G/54aC3jt0txuMTURqLyekmEHViqyA2VnxhLMpvA6nqmcjIy+Cr9tLDHPssA74BP5Mx9HQIxBEA==",
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.10.0.tgz",
|
||||
"integrity": "sha512-PzCr+a/KAef5ZawX7nbyNwBDtM1HdLIT53aSA2DDlxmxMngZ43O8SIePOeX8H5S+FHXeI6t97mTt/dDdzY4Fyw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/regexpp": "^4.10.0",
|
||||
"@typescript-eslint/scope-manager": "7.9.0",
|
||||
"@typescript-eslint/type-utils": "7.9.0",
|
||||
"@typescript-eslint/utils": "7.9.0",
|
||||
"@typescript-eslint/visitor-keys": "7.9.0",
|
||||
"@typescript-eslint/scope-manager": "7.10.0",
|
||||
"@typescript-eslint/type-utils": "7.10.0",
|
||||
"@typescript-eslint/utils": "7.10.0",
|
||||
"@typescript-eslint/visitor-keys": "7.10.0",
|
||||
"graphemer": "^1.4.0",
|
||||
"ignore": "^5.3.1",
|
||||
"natural-compare": "^1.4.0",
|
||||
@ -9000,16 +9000,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/parser": {
|
||||
"version": "7.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.9.0.tgz",
|
||||
"integrity": "sha512-qHMJfkL5qvgQB2aLvhUSXxbK7OLnDkwPzFalg458pxQgfxKDfT1ZDbHQM/I6mDIf/svlMkj21kzKuQ2ixJlatQ==",
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.10.0.tgz",
|
||||
"integrity": "sha512-2EjZMA0LUW5V5tGQiaa2Gys+nKdfrn2xiTIBLR4fxmPmVSvgPcKNW+AE/ln9k0A4zDUti0J/GZXMDupQoI+e1w==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "7.9.0",
|
||||
"@typescript-eslint/types": "7.9.0",
|
||||
"@typescript-eslint/typescript-estree": "7.9.0",
|
||||
"@typescript-eslint/visitor-keys": "7.9.0",
|
||||
"@typescript-eslint/scope-manager": "7.10.0",
|
||||
"@typescript-eslint/types": "7.10.0",
|
||||
"@typescript-eslint/typescript-estree": "7.10.0",
|
||||
"@typescript-eslint/visitor-keys": "7.10.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
@ -9029,14 +9029,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "7.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.9.0.tgz",
|
||||
"integrity": "sha512-ZwPK4DeCDxr3GJltRz5iZejPFAAr4Wk3+2WIBaj1L5PYK5RgxExu/Y68FFVclN0y6GGwH8q+KgKRCvaTmFBbgQ==",
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.10.0.tgz",
|
||||
"integrity": "sha512-7L01/K8W/VGl7noe2mgH0K7BE29Sq6KAbVmxurj8GGaPDZXPr8EEQ2seOeAS+mEV9DnzxBQB6ax6qQQ5C6P4xg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.9.0",
|
||||
"@typescript-eslint/visitor-keys": "7.9.0"
|
||||
"@typescript-eslint/types": "7.10.0",
|
||||
"@typescript-eslint/visitor-keys": "7.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@ -9047,14 +9047,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/type-utils": {
|
||||
"version": "7.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.9.0.tgz",
|
||||
"integrity": "sha512-6Qy8dfut0PFrFRAZsGzuLoM4hre4gjzWJB6sUvdunCYZsYemTkzZNwF1rnGea326PHPT3zn5Lmg32M/xfJfByA==",
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.10.0.tgz",
|
||||
"integrity": "sha512-D7tS4WDkJWrVkuzgm90qYw9RdgBcrWmbbRkrLA4d7Pg3w0ttVGDsvYGV19SH8gPR5L7OtcN5J1hTtyenO9xE9g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/typescript-estree": "7.9.0",
|
||||
"@typescript-eslint/utils": "7.9.0",
|
||||
"@typescript-eslint/typescript-estree": "7.10.0",
|
||||
"@typescript-eslint/utils": "7.10.0",
|
||||
"debug": "^4.3.4",
|
||||
"ts-api-utils": "^1.3.0"
|
||||
},
|
||||
@ -9075,9 +9075,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "7.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.9.0.tgz",
|
||||
"integrity": "sha512-oZQD9HEWQanl9UfsbGVcZ2cGaR0YT5476xfWE0oE5kQa2sNK2frxOlkeacLOTh9po4AlUT5rtkGyYM5kew0z5w==",
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.10.0.tgz",
|
||||
"integrity": "sha512-7fNj+Ya35aNyhuqrA1E/VayQX9Elwr8NKZ4WueClR3KwJ7Xx9jcCdOrLW04h51de/+gNbyFMs+IDxh5xIwfbNg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -9089,14 +9089,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "7.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.9.0.tgz",
|
||||
"integrity": "sha512-zBCMCkrb2YjpKV3LA0ZJubtKCDxLttxfdGmwZvTqqWevUPN0FZvSI26FalGFFUZU/9YQK/A4xcQF9o/VVaCKAg==",
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.10.0.tgz",
|
||||
"integrity": "sha512-LXFnQJjL9XIcxeVfqmNj60YhatpRLt6UhdlFwAkjNc6jSUlK8zQOl1oktAP8PlWFzPQC1jny/8Bai3/HPuvN5g==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.9.0",
|
||||
"@typescript-eslint/visitor-keys": "7.9.0",
|
||||
"@typescript-eslint/types": "7.10.0",
|
||||
"@typescript-eslint/visitor-keys": "7.10.0",
|
||||
"debug": "^4.3.4",
|
||||
"globby": "^11.1.0",
|
||||
"is-glob": "^4.0.3",
|
||||
@ -9131,16 +9131,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/utils": {
|
||||
"version": "7.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.9.0.tgz",
|
||||
"integrity": "sha512-5KVRQCzZajmT4Ep+NEgjXCvjuypVvYHUW7RHlXzNPuak2oWpVoD1jf5xCP0dPAuNIchjC7uQyvbdaSTFaLqSdA==",
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.10.0.tgz",
|
||||
"integrity": "sha512-olzif1Fuo8R8m/qKkzJqT7qwy16CzPRWBvERS0uvyc+DHd8AKbO4Jb7kpAvVzMmZm8TrHnI7hvjN4I05zow+tg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@typescript-eslint/scope-manager": "7.9.0",
|
||||
"@typescript-eslint/types": "7.9.0",
|
||||
"@typescript-eslint/typescript-estree": "7.9.0"
|
||||
"@typescript-eslint/scope-manager": "7.10.0",
|
||||
"@typescript-eslint/types": "7.10.0",
|
||||
"@typescript-eslint/typescript-estree": "7.10.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || >=20.0.0"
|
||||
@ -9154,13 +9154,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "7.9.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.9.0.tgz",
|
||||
"integrity": "sha512-iESPx2TNLDNGQLyjKhUvIKprlP49XNEK+MvIf9nIO7ZZaZdbnfWKHnXAgufpxqfA0YryH8XToi4+CjBgVnFTSQ==",
|
||||
"version": "7.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.10.0.tgz",
|
||||
"integrity": "sha512-9ntIVgsi6gg6FIq9xjEO4VQJvwOqA3jaBFQJ/6TK5AvEup2+cECI6Fh7QiBxmfMHXU0V0J4RyPeOU1VDNzl9cg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "7.9.0",
|
||||
"@typescript-eslint/types": "7.10.0",
|
||||
"eslint-visitor-keys": "^3.4.3"
|
||||
},
|
||||
"engines": {
|
||||
@ -9978,9 +9978,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/babel-plugin-react-native-web": {
|
||||
"version": "0.19.11",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.19.11.tgz",
|
||||
"integrity": "sha512-0sHf8GgDhsRZxGwlwHHdfL3U8wImFaLw4haEa60U9M3EiO3bg6u3BJ+1vXhwgrevqSq76rMb5j1HJs+dNvMj5g==",
|
||||
"version": "0.19.12",
|
||||
"resolved": "https://registry.npmjs.org/babel-plugin-react-native-web/-/babel-plugin-react-native-web-0.19.12.tgz",
|
||||
"integrity": "sha512-eYZ4+P6jNcB37lObWIg0pUbi7+3PKoU1Oie2j0C8UF3cXyXoR74tO2NBjI/FORb2LJyItJZEAmjU5pSaJYEL1w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/babel-plugin-transform-flow-enums": {
|
||||
@ -10189,12 +10189,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@ -10345,13 +10345,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/cacache/node_modules/glob": {
|
||||
"version": "10.3.15",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz",
|
||||
"integrity": "sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==",
|
||||
"version": "10.3.16",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.16.tgz",
|
||||
"integrity": "sha512-JDKXl1DiuuHJ6fVS2FXjownaavciiHNUU4mOvV/B793RLh05vZL1rcPnCSaOgv1hDT6RDlY7AB7ZUvFYAtPgAw==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^2.3.6",
|
||||
"jackspeak": "^3.1.2",
|
||||
"minimatch": "^9.0.1",
|
||||
"minipass": "^7.0.4",
|
||||
"path-scurry": "^1.11.0"
|
||||
@ -10446,9 +10446,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001620",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz",
|
||||
"integrity": "sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==",
|
||||
"version": "1.0.30001621",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001621.tgz",
|
||||
"integrity": "sha512-+NLXZiviFFKX0fk8Piwv3PfLPGtRqJeq2TiNoUff/qB5KJgwecJTvCXDpmlyP/eCI/GUEmp/h/y5j0yckiiZrA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@ -11992,9 +11992,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/electron-to-chromium": {
|
||||
"version": "1.4.774",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.774.tgz",
|
||||
"integrity": "sha512-132O1XCd7zcTkzS3FgkAzKmnBuNJjK8WjcTtNuoylj7MYbqw5eXehjQ5OK91g0zm7OTKIPeaAG4CPoRfD9M1Mg==",
|
||||
"version": "1.4.777",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.777.tgz",
|
||||
"integrity": "sha512-n02NCwLJ3wexLfK/yQeqfywCblZqLcXphzmid5e8yVPdtEcida7li0A5WQKghHNG0FeOMCzeFOzEbtAh5riXFw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/emittery": {
|
||||
@ -12392,20 +12392,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-config-conventions": {
|
||||
"version": "14.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-conventions/-/eslint-config-conventions-14.1.0.tgz",
|
||||
"integrity": "sha512-oJOQcUfXD874XuJOCtoRmjuVKAJ+6TG92So0VDgwvsBx3R2pVAc34CmuvAhqamFeaNOkLTSFu/mVrnmZggzgIw==",
|
||||
"version": "14.2.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-config-conventions/-/eslint-config-conventions-14.2.0.tgz",
|
||||
"integrity": "sha512-f6BY4d5ibQfNY4MYRN5jat/bCZW/m/6lRXAca5cc3Q84DnTYwimby1GutBvnKfiA+/ZhIUcgqbFZozLOldBIhQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=10.0.0"
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-promise": "^6.1.1",
|
||||
"eslint-plugin-unicorn": "^51.0.1"
|
||||
"eslint-plugin-unicorn": "^51.0.1 || ^52.0.0 || ^53.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-import-resolver-node": {
|
||||
@ -12672,18 +12671,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn": {
|
||||
"version": "51.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-51.0.1.tgz",
|
||||
"integrity": "sha512-MuR/+9VuB0fydoI0nIn2RDA5WISRn4AsJyNSaNKLVwie9/ONvQhxOBbkfSICBPnzKrB77Fh6CZZXjgTt/4Latw==",
|
||||
"version": "53.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-53.0.0.tgz",
|
||||
"integrity": "sha512-kuTcNo9IwwUCfyHGwQFOK/HjJAYzbODHN3wP0PgqbW+jbXqpNWxNVpVhj2tO9SixBwuAdmal8rVcWKBxwFnGuw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/helper-validator-identifier": "^7.22.20",
|
||||
"@babel/helper-validator-identifier": "^7.24.5",
|
||||
"@eslint-community/eslint-utils": "^4.4.0",
|
||||
"@eslint/eslintrc": "^2.1.4",
|
||||
"@eslint/eslintrc": "^3.0.2",
|
||||
"ci-info": "^4.0.0",
|
||||
"clean-regexp": "^1.0.0",
|
||||
"core-js-compat": "^3.34.0",
|
||||
"core-js-compat": "^3.37.0",
|
||||
"esquery": "^1.5.0",
|
||||
"indent-string": "^4.0.0",
|
||||
"is-builtin-module": "^3.2.1",
|
||||
@ -12692,11 +12691,11 @@
|
||||
"read-pkg-up": "^7.0.1",
|
||||
"regexp-tree": "^0.1.27",
|
||||
"regjsparser": "^0.10.0",
|
||||
"semver": "^7.5.4",
|
||||
"semver": "^7.6.1",
|
||||
"strip-indent": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
"node": ">=18.18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1"
|
||||
@ -12705,6 +12704,102 @@
|
||||
"eslint": ">=8.56.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn/node_modules/@eslint/eslintrc": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz",
|
||||
"integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^6.12.4",
|
||||
"debug": "^4.3.2",
|
||||
"espree": "^10.0.1",
|
||||
"globals": "^14.0.0",
|
||||
"ignore": "^5.2.0",
|
||||
"import-fresh": "^3.2.1",
|
||||
"js-yaml": "^4.1.0",
|
||||
"minimatch": "^3.1.2",
|
||||
"strip-json-comments": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn/node_modules/ajv": {
|
||||
"version": "6.12.6",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
"json-schema-traverse": "^0.4.1",
|
||||
"uri-js": "^4.2.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn/node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn/node_modules/eslint-visitor-keys": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz",
|
||||
"integrity": "sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn/node_modules/espree": {
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/espree/-/espree-10.0.1.tgz",
|
||||
"integrity": "sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"acorn": "^8.11.3",
|
||||
"acorn-jsx": "^5.3.2",
|
||||
"eslint-visitor-keys": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn/node_modules/globals": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
|
||||
"integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn/node_modules/jsesc": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
|
||||
@ -12718,6 +12813,26 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn/node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn/node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-unicorn/node_modules/semver": {
|
||||
"version": "7.6.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
|
||||
@ -13725,9 +13840,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
@ -14075,6 +14190,20 @@
|
||||
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
@ -15638,9 +15767,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/jackspeak": {
|
||||
"version": "2.3.6",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
|
||||
"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.1.2.tgz",
|
||||
"integrity": "sha512-kWmLKn2tRtfYMF/BakihVVRzBKOxz4gJMiL2Rj91WnAB5TPZumSH99R/Yf1qE1u4uRimvCSJfm6hnxohXeEXjQ==",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
@ -18378,6 +18507,106 @@
|
||||
"lightningcss-win32-x64-msvc": "1.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-arm64": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.19.0.tgz",
|
||||
"integrity": "sha512-wIJmFtYX0rXHsXHSr4+sC5clwblEMji7HHQ4Ub1/CznVRxtCFha6JIt5JZaNf8vQrfdZnBxLLC6R8pC818jXqg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-darwin-x64": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.19.0.tgz",
|
||||
"integrity": "sha512-Lif1wD6P4poaw9c/4Uh2z+gmrWhw/HtXFoeZ3bEsv6Ia4tt8rOJBdkfVaUJ6VXmpKHALve+iTyP2+50xY1wKPw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm-gnueabihf": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.19.0.tgz",
|
||||
"integrity": "sha512-P15VXY5682mTXaiDtbnLYQflc8BYb774j2R84FgDLJTN6Qp0ZjWEFyN1SPqyfTj2B2TFjRHRUvQSSZ7qN4Weig==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm64-gnu": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.19.0.tgz",
|
||||
"integrity": "sha512-zwXRjWqpev8wqO0sv0M1aM1PpjHz6RVIsBcxKszIG83Befuh4yNysjgHVplF9RTU7eozGe3Ts7r6we1+Qkqsww==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-arm64-musl": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.19.0.tgz",
|
||||
"integrity": "sha512-vSCKO7SDnZaFN9zEloKSZM5/kC5gbzUjoJQ43BvUpyTFUX7ACs/mDfl2Eq6fdz2+uWhUh7vf92c4EaaP4udEtA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-linux-x64-gnu": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.19.0.tgz",
|
||||
@ -18418,14 +18647,37 @@
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss-win32-x64-msvc": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.19.0.tgz",
|
||||
"integrity": "sha512-C+VuUTeSUOAaBZZOPT7Etn/agx/MatzJzGRkeV+zEABmPuntv1zihncsi+AyGmjkkzq3wVedEy7h0/4S84mUtg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"license": "MPL-2.0",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">= 12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/parcel"
|
||||
}
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz",
|
||||
"integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz",
|
||||
"integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antonk52"
|
||||
}
|
||||
},
|
||||
"node_modules/lines-and-columns": {
|
||||
@ -18435,22 +18687,22 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lint-staged": {
|
||||
"version": "15.2.2",
|
||||
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz",
|
||||
"integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==",
|
||||
"version": "15.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.4.tgz",
|
||||
"integrity": "sha512-3F9KRQIS2fVDGtCkBp4Bx0jswjX7zUcKx6OF0ZeY1prksUyKPRIIUqZhIUYAstJfvj6i48VFs4dwVIbCYwvTYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "5.3.0",
|
||||
"commander": "11.1.0",
|
||||
"commander": "12.1.0",
|
||||
"debug": "4.3.4",
|
||||
"execa": "8.0.1",
|
||||
"lilconfig": "3.0.0",
|
||||
"listr2": "8.0.1",
|
||||
"micromatch": "4.0.5",
|
||||
"lilconfig": "3.1.1",
|
||||
"listr2": "8.2.1",
|
||||
"micromatch": "4.0.6",
|
||||
"pidtree": "0.6.0",
|
||||
"string-argv": "0.3.2",
|
||||
"yaml": "2.3.4"
|
||||
"yaml": "2.4.2"
|
||||
},
|
||||
"bin": {
|
||||
"lint-staged": "bin/lint-staged.js"
|
||||
@ -18476,19 +18728,46 @@
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/commander": {
|
||||
"version": "11.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
|
||||
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
|
||||
"version": "12.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/micromatch": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.6.tgz",
|
||||
"integrity": "sha512-Y4Ypn3oujJYxJcMacVgcs92wofTHxp9FzfDpQON4msDefoC0lb3ETvQLOdLcbhSwU1bz8HrL/1sygfBIHudrkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"braces": "^3.0.3",
|
||||
"picomatch": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.6"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/picomatch": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz",
|
||||
"integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==",
|
||||
"version": "8.2.1",
|
||||
"resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.1.tgz",
|
||||
"integrity": "sha512-irTfvpib/rNiD637xeevjO2l3Z5loZmuaRi0L0YE5LfijwVY96oyVn0DFD3o/teAok7nfobMG1THvvcHh/BP6g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -18496,7 +18775,7 @@
|
||||
"colorette": "^2.0.20",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"log-update": "^6.0.0",
|
||||
"rfdc": "^1.3.0",
|
||||
"rfdc": "^1.3.1",
|
||||
"wrap-ansi": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@ -19741,12 +20020,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.5",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
|
||||
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
|
||||
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"braces": "^3.0.2",
|
||||
"braces": "^3.0.3",
|
||||
"picomatch": "^2.3.1"
|
||||
},
|
||||
"engines": {
|
||||
@ -20743,6 +21022,7 @@
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz",
|
||||
"integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==",
|
||||
"deprecated": "This package is no longer supported.",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"os-homedir": "^1.0.0",
|
||||
@ -21565,9 +21845,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/react-hook-form": {
|
||||
"version": "7.51.4",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.4.tgz",
|
||||
"integrity": "sha512-V14i8SEkh+V1gs6YtD0hdHYnoL4tp/HX/A45wWQN15CYr9bFRmmRdYStSO5L65lCCZRF+kYiSKhm9alqbcdiVA==",
|
||||
"version": "7.51.5",
|
||||
"resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.51.5.tgz",
|
||||
"integrity": "sha512-J2ILT5gWx1XUIJRETiA7M19iXHlG74+6O3KApzvqB/w8S5NQR7AbU8HVZrMALdmDgWpRPYiZJl0zx8Z4L2mP6Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.22.0"
|
||||
@ -23910,14 +24190,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/supabase/node_modules/glob": {
|
||||
"version": "10.3.15",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz",
|
||||
"integrity": "sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==",
|
||||
"version": "10.3.16",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.16.tgz",
|
||||
"integrity": "sha512-JDKXl1DiuuHJ6fVS2FXjownaavciiHNUU4mOvV/B793RLh05vZL1rcPnCSaOgv1hDT6RDlY7AB7ZUvFYAtPgAw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^2.3.6",
|
||||
"jackspeak": "^3.1.2",
|
||||
"minimatch": "^9.0.1",
|
||||
"minipass": "^7.0.4",
|
||||
"path-scurry": "^1.11.0"
|
||||
@ -24798,9 +25078,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici": {
|
||||
"version": "6.17.0",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.17.0.tgz",
|
||||
"integrity": "sha512-fs13QiDjPIzJ7gFAOal9CSG0c92rT2xw6MuMUJ4H30Eg5GCauLWYCCZA1tInjd6M4y+JZjVCCFr9pFpbhcC64w==",
|
||||
"version": "6.18.1",
|
||||
"resolved": "https://registry.npmjs.org/undici/-/undici-6.18.1.tgz",
|
||||
"integrity": "sha512-/0BWqR8rJNRysS5lqVmfc7eeOErcOP4tZpATVjJOojjHZ71gSYVAtFhEmadcIjwMIUehh5NFyKGsXCnXIajtbA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.17"
|
||||
@ -25640,10 +25920,13 @@
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.3.4",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz",
|
||||
"integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==",
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz",
|
||||
"integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
|
14
package.json
14
package.json
@ -24,7 +24,7 @@
|
||||
"@fortawesome/fontawesome-svg-core": "6.5.2",
|
||||
"@fortawesome/free-solid-svg-icons": "6.5.2",
|
||||
"@fortawesome/react-native-fontawesome": "0.3.1",
|
||||
"@hookform/resolvers": "3.4.0",
|
||||
"@hookform/resolvers": "3.4.2",
|
||||
"@react-native-async-storage/async-storage": "1.23.1",
|
||||
"@react-navigation/native": "6.1.17",
|
||||
"@supabase/supabase-js": "2.43.2",
|
||||
@ -39,7 +39,7 @@
|
||||
"lottie-react-native": "6.7.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-hook-form": "7.51.4",
|
||||
"react-hook-form": "7.51.5",
|
||||
"react-native": "0.74.1",
|
||||
"react-native-calendars": "1.1305.0",
|
||||
"react-native-circular-progress-indicator": "4.4.2",
|
||||
@ -68,21 +68,21 @@
|
||||
"@types/node": "20.12.12",
|
||||
"@types/react": "18.2.79",
|
||||
"@types/react-test-renderer": "18.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.9.0",
|
||||
"@typescript-eslint/parser": "7.9.0",
|
||||
"@typescript-eslint/eslint-plugin": "7.10.0",
|
||||
"@typescript-eslint/parser": "7.10.0",
|
||||
"eslint": "8.57.0",
|
||||
"eslint-config-conventions": "14.1.0",
|
||||
"eslint-config-conventions": "14.2.0",
|
||||
"eslint-plugin-import": "2.29.1",
|
||||
"eslint-plugin-promise": "6.1.1",
|
||||
"eslint-plugin-react": "7.34.1",
|
||||
"eslint-plugin-react-hooks": "4.6.2",
|
||||
"eslint-plugin-react-native": "4.1.0",
|
||||
"eslint-plugin-unicorn": "51.0.1",
|
||||
"eslint-plugin-unicorn": "53.0.0",
|
||||
"husky": "9.0.11",
|
||||
"jest": "29.7.0",
|
||||
"jest-expo": "51.0.2",
|
||||
"jest-junit": "16.0.0",
|
||||
"lint-staged": "15.2.2",
|
||||
"lint-staged": "15.2.4",
|
||||
"prettier": "3.2.5",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"supabase": "1.167.4",
|
||||
|
@ -6,7 +6,7 @@ import { Divider, List, Text } from "react-native-paper"
|
||||
import { GOAL_FREQUENCIES, type GoalFrequency } from "@/domain/entities/Goal"
|
||||
import type { HabitHistory } from "@/domain/entities/HabitHistory"
|
||||
import type { HabitsTracker } from "@/domain/entities/HabitsTracker"
|
||||
import { capitalize } from "@/utils/strings"
|
||||
import { LOCALE, capitalize } from "@/utils/strings"
|
||||
import confettiJSON from "../../../assets/confetti.json"
|
||||
import { HabitCard } from "./HabitCard"
|
||||
|
||||
@ -96,7 +96,7 @@ export const HabitsList: React.FC<HabitsListProps> = (props) => {
|
||||
marginTop: 20,
|
||||
}}
|
||||
>
|
||||
{selectedDate.toLocaleDateString("en-US", {
|
||||
{selectedDate.toLocaleDateString(LOCALE, {
|
||||
weekday: "long",
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
|
110
presentation/react-native/components/HabitsStatistics.tsx
Normal file
110
presentation/react-native/components/HabitsStatistics.tsx
Normal file
@ -0,0 +1,110 @@
|
||||
import { Card, Divider, Text } from "react-native-paper"
|
||||
import CircularProgress from "react-native-circular-progress-indicator"
|
||||
import { Agenda } from "react-native-calendars"
|
||||
import { useState } from "react"
|
||||
|
||||
import { getNowDateUTC, getISODate } from "@/utils/dates"
|
||||
import type { HabitsTracker } from "@/domain/entities/HabitsTracker"
|
||||
import { LOCALE } from "@/utils/strings"
|
||||
import {
|
||||
GOAL_FREQUENCIES,
|
||||
GOAL_FREQUENCIES_TYPES,
|
||||
} from "@/domain/entities/Goal"
|
||||
import { calculateRatio } from "@/utils/maths"
|
||||
|
||||
export interface HabitsStatisticsProps {
|
||||
habitsTracker: HabitsTracker
|
||||
}
|
||||
|
||||
export const HabitsStatistics: React.FC<HabitsStatisticsProps> = (props) => {
|
||||
const { habitsTracker } = props
|
||||
|
||||
const today = getNowDateUTC()
|
||||
const todayISO = getISODate(today)
|
||||
|
||||
const [selectedDate, setSelectedDate] = useState<Date>(today)
|
||||
const selectedDateISO = getISODate(selectedDate)
|
||||
|
||||
return (
|
||||
<Agenda
|
||||
firstDay={1}
|
||||
showClosingKnob
|
||||
onDayPress={(date) => {
|
||||
setSelectedDate(new Date(date.dateString))
|
||||
}}
|
||||
markedDates={{
|
||||
[todayISO]: { marked: true, today: true },
|
||||
}}
|
||||
maxDate={todayISO}
|
||||
selected={selectedDateISO}
|
||||
renderList={() => {
|
||||
return (
|
||||
<>
|
||||
<Divider />
|
||||
|
||||
<Text
|
||||
style={{
|
||||
fontWeight: "bold",
|
||||
fontSize: 22,
|
||||
textAlign: "center",
|
||||
marginVertical: 10,
|
||||
}}
|
||||
>
|
||||
{selectedDate.toLocaleDateString(LOCALE, {
|
||||
weekday: "long",
|
||||
year: "numeric",
|
||||
month: "long",
|
||||
day: "numeric",
|
||||
})}
|
||||
</Text>
|
||||
|
||||
{GOAL_FREQUENCIES.map((frequency) => {
|
||||
const { totalGoalsSuccess, totalGoals } =
|
||||
habitsTracker.getHabitsStatisticsByDateAndFrequency({
|
||||
selectedDate,
|
||||
frequency,
|
||||
})
|
||||
const percentage =
|
||||
calculateRatio(totalGoalsSuccess, totalGoals) * 100
|
||||
return {
|
||||
totalGoalsSuccess,
|
||||
totalGoals,
|
||||
percentage,
|
||||
frequency,
|
||||
}
|
||||
})
|
||||
.filter(({ totalGoals }) => {
|
||||
return totalGoals > 0
|
||||
})
|
||||
.map(
|
||||
({ frequency, totalGoals, totalGoalsSuccess, percentage }) => {
|
||||
return (
|
||||
<Card
|
||||
key={frequency}
|
||||
mode="elevated"
|
||||
style={{ marginVertical: 8, marginHorizontal: 10 }}
|
||||
>
|
||||
<Card.Content>
|
||||
<Text variant="bodyMedium">
|
||||
{totalGoalsSuccess} achieved goals in the{" "}
|
||||
{GOAL_FREQUENCIES_TYPES[frequency]} out of{" "}
|
||||
{totalGoals}.
|
||||
</Text>
|
||||
<CircularProgress
|
||||
value={percentage}
|
||||
progressValueColor={"#ecf0f1"}
|
||||
circleBackgroundColor="black"
|
||||
titleColor="white"
|
||||
title="%"
|
||||
/>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
)
|
||||
},
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
@ -1,167 +0,0 @@
|
||||
import { Card, Text } from "react-native-paper"
|
||||
import CircularProgress from "react-native-circular-progress-indicator"
|
||||
import { Agenda } from "react-native-calendars"
|
||||
import { useState } from "react"
|
||||
|
||||
import { getNowDateUTC, getISODate } from "@/utils/dates"
|
||||
import type { HabitsTracker } from "@/domain/entities/HabitsTracker"
|
||||
|
||||
export interface StatsProps {
|
||||
habitsTracker: HabitsTracker
|
||||
}
|
||||
|
||||
export const Stats: React.FC<StatsProps> = (props) => {
|
||||
const { habitsTracker } = props
|
||||
|
||||
const today = getNowDateUTC()
|
||||
const todayISO = getISODate(today)
|
||||
|
||||
const [selectedDate, setSelectedDate] = useState<Date>(today)
|
||||
const selectedDateISO = getISODate(selectedDate)
|
||||
|
||||
const habitsHistory = habitsTracker.getAllHabitsHistory()
|
||||
|
||||
let goalDays = 0
|
||||
let totalGoalDays = 0
|
||||
const dailyHabits = habitsHistory.filter((el) => {
|
||||
return (
|
||||
el.habit.goal.frequency === "daily" && el.habit.startDate <= selectedDate
|
||||
)
|
||||
})
|
||||
let displayDaily = true
|
||||
if (dailyHabits.length === 0) {
|
||||
displayDaily = false
|
||||
} else {
|
||||
for (const el of dailyHabits) {
|
||||
totalGoalDays++
|
||||
if (
|
||||
el.getProgressesByDate(selectedDate)[0]?.goalProgress.isCompleted() ??
|
||||
false
|
||||
) {
|
||||
goalDays++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let goalWeek = 0
|
||||
let totalGoalWeek = 0
|
||||
const weeklyHabits = habitsHistory.filter((el) => {
|
||||
return (
|
||||
el.habit.goal.frequency === "weekly" && el.habit.startDate <= selectedDate
|
||||
)
|
||||
})
|
||||
|
||||
let displayWeekly = true
|
||||
if (weeklyHabits.length === 0) {
|
||||
displayWeekly = false
|
||||
} else {
|
||||
for (const el of weeklyHabits) {
|
||||
totalGoalWeek++
|
||||
if (
|
||||
el.getProgressesByDate(selectedDate)[0]?.goalProgress.isCompleted() ??
|
||||
false
|
||||
) {
|
||||
goalWeek++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let goalMonth = 0
|
||||
let totalGoalMonth = 0
|
||||
const monthlyHabits = habitsHistory.filter((el) => {
|
||||
return (
|
||||
el.habit.goal.frequency === "monthly" &&
|
||||
el.habit.startDate <= selectedDate
|
||||
)
|
||||
})
|
||||
|
||||
let displayMonthly = true
|
||||
if (monthlyHabits.length === 0) {
|
||||
displayMonthly = false
|
||||
} else {
|
||||
for (const el of monthlyHabits) {
|
||||
totalGoalMonth++
|
||||
if (
|
||||
el.getProgressesByDate(selectedDate)[0]?.goalProgress.isCompleted() ??
|
||||
false
|
||||
) {
|
||||
goalMonth++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Agenda
|
||||
firstDay={1}
|
||||
showClosingKnob
|
||||
onDayPress={(date) => {
|
||||
setSelectedDate(new Date(date.dateString))
|
||||
}}
|
||||
markedDates={{
|
||||
[todayISO]: { marked: true, today: true },
|
||||
}}
|
||||
maxDate={todayISO}
|
||||
selected={selectedDateISO}
|
||||
renderList={() => {
|
||||
return (
|
||||
<>
|
||||
{displayDaily ? (
|
||||
<Card key="statsDay" mode="outlined">
|
||||
<Card.Title title="Sucess Day" />
|
||||
<Card.Content>
|
||||
<Text variant="bodyMedium">
|
||||
{goalDays} but réussi dans la journée sur {totalGoalDays}
|
||||
</Text>
|
||||
<CircularProgress
|
||||
value={(goalDays / totalGoalDays) * 100}
|
||||
activeStrokeWidth={12}
|
||||
progressValueColor={"#ecf0f1"}
|
||||
circleBackgroundColor="black"
|
||||
titleColor="white"
|
||||
title="%"
|
||||
/>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
) : null}
|
||||
{displayWeekly ? (
|
||||
<Card key="statsWeek" mode="outlined">
|
||||
<Card.Title title="Sucess Week" />
|
||||
<Card.Content>
|
||||
<Text variant="bodyMedium">
|
||||
{goalWeek} but réussi dans la semaine sur {totalGoalWeek}
|
||||
</Text>
|
||||
<CircularProgress
|
||||
value={(goalWeek / totalGoalWeek) * 100}
|
||||
activeStrokeWidth={12}
|
||||
progressValueColor={"#ecf0f1"}
|
||||
circleBackgroundColor="black"
|
||||
titleColor="white"
|
||||
title="%"
|
||||
/>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
) : null}
|
||||
{displayMonthly ? (
|
||||
<Card key="statsMonth" mode="outlined">
|
||||
<Card.Title title="Sucess Month" />
|
||||
<Card.Content>
|
||||
<Text variant="bodyMedium">
|
||||
{goalMonth} but réussi dans le mois sur {totalGoalMonth}
|
||||
</Text>
|
||||
<CircularProgress
|
||||
value={(goalMonth / totalGoalMonth) * 100}
|
||||
activeStrokeWidth={12}
|
||||
progressValueColor={"#ecf0f1"}
|
||||
circleBackgroundColor="black"
|
||||
titleColor="white"
|
||||
title="%"
|
||||
/>
|
||||
</Card.Content>
|
||||
</Card>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
83
utils/__tests__/maths.test.ts
Normal file
83
utils/__tests__/maths.test.ts
Normal file
@ -0,0 +1,83 @@
|
||||
import { calculateRatio } from "../maths"
|
||||
|
||||
describe("utils/maths", () => {
|
||||
describe("calculateRatio", () => {
|
||||
it("should calculate the ratio of a value to a total", () => {
|
||||
// Arrange - Given
|
||||
const value = 3
|
||||
const total = 10
|
||||
|
||||
// Act - When
|
||||
const result = calculateRatio(value, total)
|
||||
|
||||
// Assert - Then
|
||||
const expected = 0.3
|
||||
expect(result).toEqual(expected)
|
||||
})
|
||||
|
||||
it("should return 0 if the total is 0", () => {
|
||||
// Arrange - Given
|
||||
const value = 3
|
||||
const total = 0
|
||||
|
||||
// Act - When
|
||||
const result = calculateRatio(value, total)
|
||||
|
||||
// Assert - Then
|
||||
const expected = 0
|
||||
expect(result).toEqual(expected)
|
||||
})
|
||||
|
||||
it("should return 0 if the total is negative", () => {
|
||||
// Arrange - Given
|
||||
const value = 3
|
||||
const total = -1
|
||||
|
||||
// Act - When
|
||||
const result = calculateRatio(value, total)
|
||||
|
||||
// Assert - Then
|
||||
const expected = 0
|
||||
expect(result).toEqual(expected)
|
||||
})
|
||||
|
||||
it("should return 0 if the value is 0", () => {
|
||||
// Arrange - Given
|
||||
const value = 0
|
||||
const total = 10
|
||||
|
||||
// Act - When
|
||||
const result = calculateRatio(value, total)
|
||||
|
||||
// Assert - Then
|
||||
const expected = 0
|
||||
expect(result).toEqual(expected)
|
||||
})
|
||||
|
||||
it("should return 1 if the value is equal to the total", () => {
|
||||
// Arrange - Given
|
||||
const value = 10
|
||||
const total = 10
|
||||
|
||||
// Act - When
|
||||
const result = calculateRatio(value, total)
|
||||
|
||||
// Assert - Then
|
||||
const expected = 1
|
||||
expect(result).toEqual(expected)
|
||||
})
|
||||
|
||||
it("should return 1 if the value is greater than the total", () => {
|
||||
// Arrange - Given
|
||||
const value = 11
|
||||
const total = 10
|
||||
|
||||
// Act - When
|
||||
const result = calculateRatio(value, total)
|
||||
|
||||
// Assert - Then
|
||||
const expected = 1
|
||||
expect(result).toEqual(expected)
|
||||
})
|
||||
})
|
||||
})
|
9
utils/maths.ts
Normal file
9
utils/maths.ts
Normal file
@ -0,0 +1,9 @@
|
||||
export const calculateRatio = (value: number, total: number): number => {
|
||||
if (total <= 0) {
|
||||
return 0
|
||||
}
|
||||
if (value >= total) {
|
||||
return 1
|
||||
}
|
||||
return value / total
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
export const LOCALE = "en-US"
|
||||
|
||||
export const capitalize = (string: string): string => {
|
||||
return string.charAt(0).toUpperCase() + string.slice(1)
|
||||
}
|
||||
|
Reference in New Issue
Block a user