Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added realtime calculation #26

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
} 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
Loading