diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 43058f9..ae17da9 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "realt-properties-map-frontend", - "version": "1.0.0", + "version": "1.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "realt-properties-map-frontend", - "version": "1.0.0", + "version": "1.0.2", "license": "Apache-2.0", "dependencies": { "@apollo/client": "^3.9.9", @@ -24,6 +24,7 @@ "@reduxjs/toolkit": "^2.2.2", "axios": "^1.6.8", "axios-cache-interceptor": "^1.5.1", + "dayjs": "^1.11.10", "ethers": "^6.11.1", "graphql": "^16.8.1", "i18next": "^23.10.1", @@ -8764,6 +8765,11 @@ "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==" }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 84f87df..7e6942a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -43,6 +43,7 @@ "@reduxjs/toolkit": "^2.2.2", "axios": "^1.6.8", "axios-cache-interceptor": "^1.5.1", + "dayjs": "^1.11.10", "ethers": "^6.11.1", "graphql": "^16.8.1", "i18next": "^23.10.1", diff --git a/frontend/src/components/Map/PropertyPanel.tsx b/frontend/src/components/Map/PropertyPanel.tsx index 80d350a..4963a89 100644 --- a/frontend/src/components/Map/PropertyPanel.tsx +++ b/frontend/src/components/Map/PropertyPanel.tsx @@ -1,4 +1,4 @@ -import { Button, Divider, Drawer, Grid, Image } from "@mantine/core"; +import { Button, Divider, Drawer, Flex, Grid, Image } from "@mantine/core"; import { AffixBtn } from "../Common/AffixBtn"; import { useAppDispatch, useAppSelector } from "../../hooks/useInitStore"; import { selectedMarker } from "../../store/marker/markerSelector"; @@ -7,6 +7,9 @@ import { Property } from "../../types/property"; import { useEffect } from "react"; import { useCurrencyValue } from "../../hooks/useCurrencyValue"; import { useTranslation } from "react-i18next"; +import date from "../../utils/date"; +import { selectedLanguage } from "../../store/settings/settingsSelector"; +import { selectDifferentiateOwned } from "../../store/mapOptions/mapOptionsSelector"; function toFixedStr(value: number, precision: number = 2) { return value.toFixed(precision).toLowerCase(); @@ -51,6 +54,8 @@ export function PropertyPanelContent({ onClose: () => void; }) { const { t } = useTranslation('common'); + const language = useAppSelector(selectedLanguage); + const differentiateOwned = useAppSelector(selectDifferentiateOwned); const { fullName, @@ -65,10 +70,15 @@ export function PropertyPanelContent({ annualPercentageYield, marketplaceLink, totalInvestment, + rentStartDate, + rentalType, + initialLaunchDate, + neighborhood, } = property; - const yearlyRent = netRentYearPerToken * ownedAmount; - const dailyRent = netRentDayPerToken * ownedAmount; + const consolidatedOwnedAmount = ownedAmount === 0 ? 1 : ownedAmount; + const yearlyRent = netRentYearPerToken * consolidatedOwnedAmount; + const dailyRent = netRentDayPerToken * consolidatedOwnedAmount; const ownedAmountPrice = ownedAmount * tokenPrice; const rentedUnitsPercent = rentedUnits * 100 / totalUnits; @@ -97,21 +107,33 @@ export function PropertyPanelContent({ entry: { label: 'propertyPanel.tokenAmount', value: totalTokens }, }, { - ownedOnly: true, + ownedOnly: false, entry: { label: 'propertyPanel.yield', value: `${toFixedStr(annualPercentageYield)}%` }, }, { - ownedOnly: true, + ownedOnly: false, entry: { label: 'propertyPanel.weeklyRent', value: useCurrencyValue(dailyRent * 7) }, }, { - ownedOnly: true, + ownedOnly: false, entry: { label: 'propertyPanel.yearlyRent', value: useCurrencyValue(yearlyRent) }, }, { ownedOnly: false, entry: { label: 'propertyPanel.rentedUnit', value: `${rentedUnits} / ${totalUnits} (${toFixedStr(rentedUnitsPercent)}%)` }, }, + { + ownedOnly: false, + entry: { label: 'propertyPanel.initialLaunchDate', value: date.utc(initialLaunchDate.date).locale(language).format('LL') }, + }, + { + ownedOnly: false, + entry: { label: 'propertyPanel.rentStart', value: date.utc(rentStartDate.date).locale(language).format('LL') }, + }, + { + ownedOnly: false, + entry: { label: 'propertyPanel.rentalType', value: t(`rentalType.${rentalType}`) }, + }, { ownedOnly: false, entry: { label: 'propertyPanel.assetPrice', value: useCurrencyValue(totalInvestment) }, @@ -127,7 +149,10 @@ export function PropertyPanelContent({ - {fullName} + + {fullName} + { neighborhood && {neighborhood}} + @@ -182,9 +207,18 @@ export function PropertyPanelContent({ + { + (ownedAmount === 0 || !differentiateOwned) && + + +

{t('propertyPanel.notOwned')}

+
+
+ } {entries.map(({ ownedOnly, notOwnedOnly, entry, icon }) => { if ( (ownedOnly && ownedAmount <= 0) || + (ownedOnly && !differentiateOwned) || (notOwnedOnly && ownedAmount > 0) ) { return null; diff --git a/frontend/src/i18next/locales/en/common.json b/frontend/src/i18next/locales/en/common.json index 13fa2e1..2528021 100644 --- a/frontend/src/i18next/locales/en/common.json +++ b/frontend/src/i18next/locales/en/common.json @@ -8,7 +8,15 @@ "weeklyRent": "Weekly Rent", "yearlyRent": "Yearly Rent", "rentedUnit": "Rented Unit", - "assetPrice": "Asset Price" + "initialLaunchDate": "Initial Launch Date", + "rentStart": "Rent Start", + "rentalType": "Rental Type", + "assetPrice": "Asset Price", + "notOwned": "Not owned" + }, + "rentalType": { + "short_term": "Short term", + "long_term": "Long term" }, "propertyType": { "1": "Single Family", diff --git a/frontend/src/i18next/locales/fr/common.json b/frontend/src/i18next/locales/fr/common.json index fe75b4e..7613af0 100644 --- a/frontend/src/i18next/locales/fr/common.json +++ b/frontend/src/i18next/locales/fr/common.json @@ -8,7 +8,15 @@ "weeklyRent": "Loyer hebdomadaire", "yearlyRent": "Loyer annuel", "rentedUnit": "Unité louée", - "assetPrice": "Prix de l'actif" + "initialLaunchDate": "Date de lancement", + "rentStart": "Début de la location", + "rentalType": "Type de location", + "assetPrice": "Prix de l'actif", + "notOwned": "Non possédé" + }, + "rentalType": { + "short_term": "Court terme", + "long_term": "Long terme" }, "propertyType": { "1": "Individuel", diff --git a/frontend/src/utils/date.ts b/frontend/src/utils/date.ts new file mode 100644 index 0000000..b32ca4a --- /dev/null +++ b/frontend/src/utils/date.ts @@ -0,0 +1,10 @@ +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +import localizedFormat from 'dayjs/plugin/localizedFormat'; +import 'dayjs/locale/en'; +import 'dayjs/locale/fr'; + +dayjs.extend(utc); +dayjs.extend(localizedFormat) + +export default dayjs; \ No newline at end of file