Skip to content

Commit

Permalink
added realtime calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
VV committed Dec 4, 2023
1 parent 3c040a3 commit efb99ca
Show file tree
Hide file tree
Showing 10 changed files with 181 additions and 24 deletions.
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

53 changes: 52 additions & 1 deletion src/components/layouts/SettingsMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
import { useDisclosure } from '@mantine/hooks'
import {
IconCash,
IconClock,
IconClockOff,
IconLanguage,
IconMoon,
IconSettings,
Expand All @@ -26,10 +28,15 @@ import { setCookie } from 'cookies-next'

import {
selectUserCurrency,
selectUserRentCalculation,
selectVersion,
} from 'src/store/features/settings/settingsSelector'
import { userCurrencyChanged } from 'src/store/features/settings/settingsSlice'
import {
userCurrencyChanged,
userRentCalculationChanged,
} from 'src/store/features/settings/settingsSlice'
import { Currency } from 'src/types/Currencies'
import { RentCalculation } from 'src/types/RentCalculation'
import { expiresLocalStorageCaches } from 'src/utils/useCache'

const ColorSchemeMenuItem: FC = () => {
Expand Down Expand Up @@ -69,6 +76,48 @@ const ColorSchemeMenuItem: FC = () => {
)
}

const RealtimeRentMenuItem: FC = () => {
const dispatch = useDispatch()
const rentCalculation = useSelector(selectUserRentCalculation)

function setUserRentCalculation(rentCalculation: RentCalculation) {
dispatch(userRentCalculationChanged(rentCalculation))
}

const { t } = useTranslation('common', { keyPrefix: 'settings' })

return (
<Box px={5}>
<SegmentedControl
color={'brand'}
fullWidth={true}
value={rentCalculation}
onChange={(value) => setUserRentCalculation(value as RentCalculation)}
data={[
{
value: 'realtime',
label: (
<Center>
<IconClock size={16} />
<Box ml={'xs'}>{t('realtime')}</Box>
</Center>
),
},
{
value: 'global',
label: (
<Center>
<IconClockOff size={16} />
<Box ml={'xs'}>{t('global')}</Box>
</Center>
),
},
]}
/>
</Box>
)
}

const LanguageSelect: FC = () => {
const { i18n, t } = useTranslation('common', { keyPrefix: 'settings' })

Expand Down Expand Up @@ -163,6 +212,8 @@ export const SettingsMenu: FC = () => {
<Menu.Divider />
<CurrencySelect />
<Menu.Divider />
<RealtimeRentMenuItem />
<Menu.Divider />
<ColorSchemeMenuItem />
<Menu.Divider />
<RefreshDataButton />
Expand Down
4 changes: 3 additions & 1 deletion src/i18next/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"chf": "Swiss franc (CHF)",
"light": "Light",
"dark": "Dark",
"refreshDataButton": "Refresh data"
"refreshDataButton": "Refresh data",
"realtime":"Realtime",
"global":"Global"
},
"walletButton": {
"connectWallet": "Connect wallet",
Expand Down
4 changes: 3 additions & 1 deletion src/i18next/locales/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"chf": "Franc suisse (CHF)",
"light": "Clair",
"dark": "Sombre",
"refreshDataButton": "Actualiser les données"
"refreshDataButton": "Actualiser les données",
"realtime":"Temps réel",
"global":"Global"
},
"walletButton": {
"connectWallet": "Connecter mon portefeuille",
Expand Down
4 changes: 4 additions & 0 deletions src/store/features/settings/settingsSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,9 @@ export const selectUserCurrency = (state: RootState): string =>
export const selectUser = (state: RootState): User | undefined =>
state.settings.user

export const selectUserRentCalculation = (
state: RootState
): string | undefined => state.settings.rentCalculation

export const selectVersion = (state: RootState): string | undefined =>
state.settings.version
22 changes: 20 additions & 2 deletions src/store/features/settings/settingsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import { t } from 'i18next'
import { UserRepository } from 'src/repositories/user.repository'
import { AppDispatch } from 'src/store/store'
import { Currency } from 'src/types/Currencies'
import { RentCalculation } from 'src/types/RentCalculation'

const USER_LS_KEY = 'store:settings/user'
const USER_CURRENCY_LS_KEY = 'store:settings/userCurrency'
const USER_RENT_CALCULATION_LS_KEY = 'store:settings/userRentCalculation'

export interface User {
id: string
Expand All @@ -22,26 +24,33 @@ interface SettingsInitialStateType {
user?: User
userCurrency: Currency
isInitialized: boolean
rentCalculation: RentCalculation
version?: string
}

const settingsInitialState: SettingsInitialStateType = {
user: undefined,
userCurrency: Currency.USD,
rentCalculation: RentCalculation.Global,
isInitialized: false,
}

// DISPATCH TYPE
export const initializeSettingsDispatchType = 'settings/initialize'
export const userChangedDispatchType = 'settings/userChanged'
export const userCurrencyChangedDispatchType = 'settings/userCurrencyChanged'
export const userRentCalculationChangedDispatchType =
'settings/userRentCalculationChanged'

// ACTIONS
export const initializeSettings = createAction(initializeSettingsDispatchType)
export const userChanged = createAction<User>(userChangedDispatchType)
export const userCurrencyChanged = createAction<Currency>(
userCurrencyChangedDispatchType
)
export const userRentCalculationChanged = createAction<RentCalculation>(
userRentCalculationChangedDispatchType
)

// THUNKS
export function setUserAddress(address: string) {
Expand Down Expand Up @@ -86,14 +95,23 @@ export const settingsReducers = createReducer(
state.userCurrency = action.payload
localStorage.setItem(USER_CURRENCY_LS_KEY, action.payload)
})
.addCase(userRentCalculationChanged, (state, action) => {
;(state.rentCalculation = action.payload),
localStorage.setItem(USER_RENT_CALCULATION_LS_KEY, action.payload)
})
.addCase(initializeSettings, (state) => {
const user = localStorage.getItem(USER_LS_KEY)
const userCurrency = localStorage.getItem(USER_CURRENCY_LS_KEY)
const userRentCalculation = localStorage.getItem(
USER_RENT_CALCULATION_LS_KEY
)
state.user = user ? JSON.parse(user) : undefined
state.userCurrency = userCurrency
? (userCurrency as Currency)
: Currency.USD

state.rentCalculation = userRentCalculation
? (userRentCalculation as RentCalculation)
: RentCalculation.Global
const { publicRuntimeConfig } = getConfig() as {
publicRuntimeConfig?: { version: string }
}
Expand All @@ -104,4 +122,4 @@ export const settingsReducers = createReducer(
state.isInitialized = true
})
}
)
)
75 changes: 65 additions & 10 deletions src/store/features/wallets/walletsSelector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import { createSelector } from '@reduxjs/toolkit'

import _mapValues from 'lodash/mapValues'
import _sumBy from 'lodash/sumBy'
import moment from 'moment'

import { WalletBalances, WalletType } from 'src/repositories'
import { RootState } from 'src/store/store'
import { RentCalculation } from 'src/types/RentCalculation'
import { numberOfDaysIn } from 'src/utils/date'

import { Realtoken, selectRealtokens } from '../realtokens/realtokensSelector'
import { selectUserRentCalculation } from '../settings/settingsSelector'

export interface UserRealtoken extends Realtoken {
id: string
Expand Down Expand Up @@ -83,17 +87,68 @@ export const selectOwnedRealtokensValue = createSelector(
)

export const selectOwnedRealtokensRents = createSelector(
selectUserRentCalculation,
selectOwnedRealtokens,
(realtokens) =>
realtokens.reduce(
(acc, item) => ({
daily: acc.daily + item.netRentDayPerToken * item.amount,
weekly: acc.weekly + item.netRentDayPerToken * 7 * item.amount,
monthly: acc.monthly + item.netRentMonthPerToken * item.amount,
yearly: acc.yearly + item.netRentYearPerToken * item.amount,
}),
{ daily: 0, weekly: 0, monthly: 0, yearly: 0 }
)
(rentCalculation, realtokens) => {
const rents = { daily: 0, weekly: 0, monthly: 0, yearly: 0 }

if (rentCalculation === RentCalculation.Global) {
return realtokens.reduce(
(acc, item) => ({
daily: acc.daily + item.netRentDayPerToken * item.amount,
weekly: acc.weekly + item.netRentDayPerToken * 7 * item.amount,
monthly: acc.monthly + item.netRentMonthPerToken * item.amount,
yearly: acc.yearly + item.netRentYearPerToken * item.amount,
}),
rents
)
}

const now = moment(new Date().toUTCString())
const rentDay = 'Monday'
const oneMonthLater = now.clone().add(1, 'M')
const oneYearLater = now.clone().add(1, 'y')
const oneWeekLater = now.clone().add(1, 'w')
const nbMondaysInMonth = numberOfDaysIn(now, oneMonthLater, now, rentDay)
const nbMondaysInYear = numberOfDaysIn(now, oneYearLater, now, rentDay)

for (const item of realtokens) {
const rentStartDate = moment(item.rentStartDate.date)
const daysDiff = rentStartDate.diff(now, 'days')
const rentPerWeek = item.netRentDayPerToken * 7 * item.amount

if (daysDiff > 0) {
const nbDayLeftInWeek = numberOfDaysIn(
now,
oneWeekLater,
rentStartDate,
rentDay
)
const nbDayLeftInMonth = numberOfDaysIn(
now,
oneMonthLater,
rentStartDate,
rentDay
)
const nbDayLeftInYear = numberOfDaysIn(
now,
oneYearLater,
rentStartDate,
rentDay
)

rents.weekly += !nbDayLeftInWeek ? 0 : rentPerWeek
rents.monthly += !nbDayLeftInMonth ? 0 : rentPerWeek * nbDayLeftInMonth
rents.yearly += !nbDayLeftInYear ? 0 : rentPerWeek * nbDayLeftInYear

This comment has been minimized.

Copy link
@NandyBa

NandyBa Dec 4, 2023

Member

Great, better than expected using remaining days to calculate the rent

This comment has been minimized.

Copy link
@NandyBa

NandyBa Dec 4, 2023

Member

Please consider renaming variables nbDayLeftInMonth, nbDayLeftInWeek, nbDayLeftInYear to nbMondayLeft{periode} to avoid ambiguity

This comment has been minimized.

Copy link
@JSmithOner

JSmithOner Dec 4, 2023

Collaborator

I named them this way to says that there is a "number of Mondays in Week/Month/Year" do you still want me to change them. I'm not used to make pull requests every day on another project than mine so apologize me if I make some mistakes.

This comment has been minimized.

Copy link
@JSmithOner

JSmithOner Dec 4, 2023

Collaborator

I think I get what you mean

} else {
rents.daily += item.netRentDayPerToken * item.amount
rents.weekly += rentPerWeek
rents.monthly += rentPerWeek * nbMondaysInMonth
rents.yearly += rentPerWeek * nbMondaysInYear
}
}
return rents
}
)

export const selectOwnedRealtokensAPY = createSelector(
Expand Down
4 changes: 4 additions & 0 deletions src/types/RentCalculation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export enum RentCalculation {
Realtime = 'realtime',
Global = 'global',
}
16 changes: 16 additions & 0 deletions src/utils/date.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import moment from 'moment'

export const numberOfDaysIn = (
startDate: moment.Moment,
endDate: moment.Moment,
afterDate: moment.Moment,
day: string
) => {
let nbDays = 0
for (let m = startDate.clone(); m.isBefore(endDate); m.add(1, 'day')) {
if (m.isSameOrAfter(afterDate) && m.clone().format('dddd') === day) {
nbDays++
}
}
return nbDays
}
21 changes: 13 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2746,9 +2746,9 @@
dependencies:
"glob" "7.1.7"

"@next/swc-win32-x64-msvc@12.1.5":
"integrity" "sha512-/SoXW1Ntpmpw3AXAzfDRaQidnd8kbZ2oSni8u5z0yw6t4RwJvmdZy1eOaAADRThWKV+2oU90++LSnXJIwBRWYQ=="
"resolved" "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.1.5.tgz"
"@next/swc-darwin-arm64@12.1.5":
"integrity" "sha512-y8mhldb/WFZ6lFeowkGfi0cO/lBdiBqDk4T4LZLvCpoQp4Or/NzUN6P5NzBQZ5/b4oUHM/wQICEM+1wKA4qIVw=="
"resolved" "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.1.5.tgz"
"version" "12.1.5"

"@noble/curves@~1.2.0", "@noble/[email protected]":
Expand Down Expand Up @@ -2794,6 +2794,11 @@
"@nodelib/fs.scandir" "2.1.5"
"fastq" "^1.6.0"

"@parcel/[email protected]":
"integrity" "sha512-mKY+oijI4ahBMc/GygVGvEdOq0L4DxhYgwQqYAz/7yPzuGi79oXrZG52WdpGA1wLBPrYb0T8uBaGFo7I6rvSKw=="
"resolved" "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.3.0.tgz"
"version" "2.3.0"

"@parcel/[email protected]":
"integrity" "sha512-ejBAX8H0ZGsD8lSICDNyMbSEtPMWgDL0WFCt/0z7hyf5v8Imz4rAM8xY379mBsECkq/Wdqa5WEDLqtjZ+6NxfA=="
"resolved" "https://registry.npmjs.org/@parcel/watcher-wasm/-/watcher-wasm-2.3.0.tgz"
Expand All @@ -2803,11 +2808,6 @@
"micromatch" "^4.0.5"
"napi-wasm" "^1.1.0"

"@parcel/[email protected]":
"integrity" "sha512-dLx+0XRdMnVI62kU3wbXvbIRhLck4aE28bIGKbRGS7BJNt54IIj9+c/Dkqb+7DJEbHUZAX1bwaoM8PqVlHJmCA=="
"resolved" "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.3.0.tgz"
"version" "2.3.0"

"@parcel/watcher@^2.3.0":
"integrity" "sha512-pW7QaFiL11O0BphO+bq3MgqeX/INAk9jgBldVDYjlQPO4VddoZnF22TcF9onMhnLVHuNqBJeRf+Fj7eezi/+rQ=="
"resolved" "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.3.0.tgz"
Expand Down Expand Up @@ -7154,6 +7154,11 @@
"resolved" "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
"version" "1.0.0"

"fsevents@^2.3.2", "fsevents@~2.3.2":
"integrity" "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="
"resolved" "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz"
"version" "2.3.2"

"function-bind@^1.1.1":
"integrity" "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
"resolved" "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz"
Expand Down

0 comments on commit efb99ca

Please sign in to comment.