Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucasbeneston committed Oct 17, 2024
1 parent 375a932 commit c69ba91
Show file tree
Hide file tree
Showing 10 changed files with 111 additions and 22 deletions.
44 changes: 44 additions & 0 deletions src/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# TODO

## Links

- [PC-TicketNumber](https://passculture.atlassian.net/browse/PC-TicketNumber)
- [MobTime](https://mobtime.hadrienmp.fr/mob/pass-culture)

---

## Tasks

- [ ] CAS 0 : Utilisation de `formatToFrenchDecimal()`
- [ ] Modifier `formatToFrenchDecimal()` pour qu'il fasse la conversion en XPF


- [ ] CAS 1 : Prix en dur dans le code :
- [ ] 1.1 : Crédits par âges
- [ ] Utiliser `useDepositAmountsByAge()` lorsque le crédit est marqué en dur car il utilise directement `formatToFrenchDecimal()`:
- [ ] `300\u00a0€`
- [ ] `30\u00a0€`
- [ ] `20\u00a0€`
- [ ] 1.2 : Crédit par seuil comme la part pour les offres numériques (plus tard le spectacle vivant)
- [ ] Utiliser `formatToFrenchDecimal(NUMERIC_AMOUNT)`
- [ ] Créer une constante la part du crédit pour les offres numériques. ex: const NUMERIC_AMOUNT = 10.000.


- [ ] CAS 2 : Utilisation de `useMaxPrice()` (ex `${maxPrice}\u00a0€ ...`)
- [ ] Utiliser des centimes plutôt que des euros dans `useMaxPrice()` ?


- [ ] CAS 3 : Utilisation de `getDisplayPrice()` (ex: `dès 15,60\u00a0€` (tableau de prix))


- [ ] CAS 4 : Utilisation de `formatPriceInEuroToDisplayPrice()`


- [ ] CAS 5 : Mention de "€" (ex: `en €`)
- [ ] Créer une fonction qui ne gère pas les crédits mais juste les devises

---

## Tasks for another US

- [ ]
8 changes: 5 additions & 3 deletions src/features/birthdayNotifications/pages/EighteenBirthday.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,18 @@ import { ClockFilled } from 'ui/svg/icons/ClockFilled'
import { Spacer } from 'ui/theme'
import { CaptionNeutralInfo, Typo } from 'ui/theme/typography'
import { getHeadingAttrs } from 'ui/theme/typographyAttrs/getHeadingAttrs'
import { formatToFrenchDecimal } from 'libs/parsers/getDisplayPrice'

Check failure on line 15 in src/features/birthdayNotifications/pages/EighteenBirthday.tsx

View workflow job for this annotation

GitHub Actions / yarn-linter / yarn_lint

`libs/parsers/getDisplayPrice` import should occur before import of `libs/storage`
import { useDepositAmountsByAge } from 'shared/user/useDepositAmountsByAge'

Check failure on line 16 in src/features/birthdayNotifications/pages/EighteenBirthday.tsx

View workflow job for this annotation

GitHub Actions / yarn-linter / yarn_lint

`shared/user/useDepositAmountsByAge` import should occur before import of `ui/animations/eighteen_birthday.json`

const getPageWording = (userRequiresIdCheck?: boolean) => {
if (userRequiresIdCheck) {
return {
text: 'Vérifie ton identité pour débloquer tes 300\u00a0€.',
text: `Vérifie ton identité pour débloquer tes ${useDepositAmountsByAge().eighteenYearsOldDeposit}.`,

Check failure on line 21 in src/features/birthdayNotifications/pages/EighteenBirthday.tsx

View workflow job for this annotation

GitHub Actions / yarn-linter / yarn_lint

React Hook "useDepositAmountsByAge" is called in function "getPageWording" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use"
buttonText: 'Vérifier mon identité',
}
}
return {
text: 'Confirme tes informations personnelles pour débloquer tes 300\u00a0€.',
text: `Confirme tes informations personnelles pour débloquer tes ${useDepositAmountsByAge().eighteenYearsOldDeposit}.`,

Check failure on line 26 in src/features/birthdayNotifications/pages/EighteenBirthday.tsx

View workflow job for this annotation

GitHub Actions / yarn-linter / yarn_lint

React Hook "useDepositAmountsByAge" is called in function "getPageWording" that is neither a React function component nor a custom React Hook function. React component names must start with an uppercase letter. React Hook names must start with the word "use"
buttonText: 'Confirmer mes informations',
}
}
Expand All @@ -39,7 +41,7 @@ export function EighteenBirthday() {
<StyledTitle>{pageWording.text}</StyledTitle>
<Spacer.Column numberOfSpaces={4} />
<StyledCaptionNeutralInfo>
Ton crédit précédent a été remis à 0&nbsp;€.
Ton crédit précédent a été remis à {formatToFrenchDecimal(0)}.
</StyledCaptionNeutralInfo>
<Spacer.Column numberOfSpaces={8} />
<InternalTouchableLink
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function BeneficiaryAccountCreated() {
const { actions } = useCreditStore()
const { shareAppTrigger } = useRemoteConfigContext()

const subtitle = `${maxPrice}\u00a0€ viennent d’être crédités sur ton compte pass Culture`
const subtitle = `${formatPriceInEuroToDisplayPrice(maxPrice)} viennent d’être crédités sur ton compte pass Culture`
const text = isUnderageBeneficiary
? 'Tu as jusqu’à la veille de tes 18 ans pour profiter de ton budget.'
: 'Tu as deux ans pour profiter de ton budget.'
Expand Down
10 changes: 10 additions & 0 deletions src/features/search/helpers/useMaxPrice/useGetMaxPrice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { MAX_PRICE } from 'features/search/helpers/reducer.helpers'
import { useLocation } from 'libs/location'
import { EURO_TO_XPF_RATE } from 'libs/parsers/pricesConversion'

export const useGetMaxPrice = (): number => {
const { selectedPlace } = useLocation()
const isNewCaledonianLocation = selectedPlace?.info === 'Nouvelle-Calédonie'

return isNewCaledonianLocation ? MAX_PRICE * EURO_TO_XPF_RATE : MAX_PRICE
}
7 changes: 4 additions & 3 deletions src/features/search/helpers/useMaxPrice/useMaxPrice.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { useAuthContext } from 'features/auth/context/AuthContext'
import { isUserExBeneficiary } from 'features/profile/helpers/isUserExBeneficiary'
import { MAX_PRICE } from 'features/search/helpers/reducer.helpers'
import { useGetMaxPrice } from 'features/search/helpers/useMaxPrice/useGetMaxPrice'
import { convertCentsToEuros } from 'libs/parsers/pricesConversion'

export const useMaxPrice = (): number => {
const maxPrice = useGetMaxPrice()
const { user } = useAuthContext()

const initialCredit = user?.domainsCredit?.all.initial

if (!user || !initialCredit) return MAX_PRICE
if (!user || !initialCredit) return maxPrice

if (isUserExBeneficiary(user) || initialCredit === 0) return MAX_PRICE
if (isUserExBeneficiary(user) || initialCredit === 0) return maxPrice

return convertCentsToEuros(initialCredit)
}
11 changes: 7 additions & 4 deletions src/features/search/pages/modals/PriceModal/PriceModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import { SearchCustomModalHeader } from 'features/search/components/SearchCustom
import { SearchFixedModalBottom } from 'features/search/components/SearchFixedModalBottom'
import { useSearch } from 'features/search/context/SearchWrapper'
import { FilterBehaviour } from 'features/search/enums'
import { MAX_PRICE } from 'features/search/helpers/reducer.helpers'
import { makeSearchPriceSchema } from 'features/search/helpers/schema/makeSearchPriceSchema/makeSearchPriceSchema'
import { SearchState } from 'features/search/types'
import { formatToFrenchDecimal } from 'libs/parsers/getDisplayPrice'
Expand All @@ -26,6 +25,8 @@ import { Separator } from 'ui/components/Separator'
import { Close } from 'ui/svg/icons/Close'
import { Error } from 'ui/svg/icons/Error'
import { getSpacing, Spacer } from 'ui/theme'
import { useGetMaxPrice } from 'features/search/helpers/useMaxPrice/useGetMaxPrice'

Check failure on line 28 in src/features/search/pages/modals/PriceModal/PriceModal.tsx

View workflow job for this annotation

GitHub Actions / yarn-linter / yarn_lint

`features/search/helpers/useMaxPrice/useGetMaxPrice` import should occur before import of `features/search/types`
import { useCurrencyToDisplay } from 'features/search/pages/modals/PriceModal/useCurrencyToDisplay'

Check failure on line 29 in src/features/search/pages/modals/PriceModal/PriceModal.tsx

View workflow job for this annotation

GitHub Actions / yarn-linter / yarn_lint

`features/search/pages/modals/PriceModal/useCurrencyToDisplay` import should occur before import of `features/search/types`

type PriceModalFormData = {
minPrice: string
Expand Down Expand Up @@ -55,6 +56,8 @@ export const PriceModal: FunctionComponent<PriceModalProps> = ({
filterBehaviour,
onClose,
}) => {
const currency = useCurrencyToDisplay()
const MAX_PRICE = useGetMaxPrice()
const { searchState, dispatch } = useSearch()
const { isLoggedIn, user } = useAuthContext()
const availableCredit = useAvailableCredit()
Expand Down Expand Up @@ -301,7 +304,7 @@ export const PriceModal: FunctionComponent<PriceModalProps> = ({
autoCapitalize="none"
isError={error && value.length > 0}
keyboardType="numeric"
label="Prix minimum (en&nbsp;€)"
label={`Prix minimum (en\u00a0${currency})`}
value={value}
onChangeText={onChange}
onBlur={onBlur}
Expand Down Expand Up @@ -331,7 +334,7 @@ export const PriceModal: FunctionComponent<PriceModalProps> = ({
autoCapitalize="none"
isError={error && value.length > 0}
keyboardType="numeric"
label="Prix maximum (en&nbsp;€)"
label={`Prix maximum (en\u00a0${currency})`}
value={value}
onChangeText={(value) => {
onChange(value)
Expand All @@ -341,7 +344,7 @@ export const PriceModal: FunctionComponent<PriceModalProps> = ({
textContentType="none" // disable autofill on iOS
accessibilityDescribedBy={maxPriceInputId}
testID="Entrée pour le prix maximum"
rightLabel={`max\u00a0: ${formatInitialCredit}\u00a0`}
rightLabel={`max\u00a0: ${formatInitialCredit}\u00a0${currency}`}
placeholder={`${formatInitialCredit}`}
disabled={getValues('isLimitCreditSearch') || getValues('isOnlyFreeOffersSearch')}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { useLocation } from 'libs/location'

export const useCurrencyToDisplay = () => {
const { selectedPlace } = useLocation()
const isNewCaledonianLocation = selectedPlace?.info === 'Nouvelle-Calédonie'

return isNewCaledonianLocation ? 'CSP' : '€'
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@ import { BicolorNumeric } from 'ui/svg/icons/bicolor/Numeric'
import { BicolorClock } from 'ui/svg/icons/BicolorClock'
import { BicolorLock } from 'ui/svg/icons/BicolorLock'
import { Spacer, Typo } from 'ui/theme'
import { formatToFrenchDecimal } from 'libs/parsers/getDisplayPrice'

Check failure on line 13 in src/features/tutorial/components/profileTutorial/EighteenBlockDescription.tsx

View workflow job for this annotation

GitHub Actions / yarn-linter / yarn_lint

`libs/parsers/getDisplayPrice` import should occur before import of `ui/components/accessibility/AccessibleUnorderedList`

type Props = {
ongoingCredit?: boolean
}

const NUMERIC_AMOUNT = 10000

export const EighteenBlockDescription: FunctionComponent<Props> = ({ ongoingCredit = false }) => {
const { isLoggedIn, user } = useAuthContext()

Expand All @@ -32,7 +35,7 @@ export const EighteenBlockDescription: FunctionComponent<Props> = ({ ongoingCred
<BlockDescriptionItem
key={3}
icon={<SmallNumeric bicolor={ongoingCredit} />}
text="La limite de 100&nbsp;€ est là pour t’encourager à tester des offres culturelles variées."
text={`La limite de ${formatToFrenchDecimal(NUMERIC_AMOUNT)} est là pour t’encourager à tester des offres culturelles variées.`}
/>,
]
const items =
Expand All @@ -43,7 +46,7 @@ export const EighteenBlockDescription: FunctionComponent<Props> = ({ ongoingCred
<CreditProgressBar progress={1} />
<Spacer.Column numberOfSpaces={2} />
<StyledCaption>
dont 100&nbsp;€ en offres numériques (streaming, presse en ligne, …)
{`dont ${formatToFrenchDecimal(NUMERIC_AMOUNT)} en offres numériques (streaming, presse en ligne, …)`}
</StyledCaption>
<Spacer.Column numberOfSpaces={4} />
<AccessibleUnorderedList Separator={<Spacer.Column numberOfSpaces={4} />} items={items} />
Expand Down
35 changes: 26 additions & 9 deletions src/libs/parsers/getDisplayPrice.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,42 @@
import { CENTS_IN_EURO, convertEuroToCents } from 'libs/parsers/pricesConversion'
import { CENTS_IN_EURO, EURO_TO_XPF_RATE, convertEuroToCents } from 'libs/parsers/pricesConversion'

type FormatPriceOptions = {
fractionDigits?: number
}

/**
* Takes a price in cents (ex: 5.5€ = 550 cents) and returns a string with the
* price in euros in the French format, ex: "5,50 €"
* @param {number} priceInCents
* Takes a price in cents (for EUR) and returns a string with the
* price in the appropriate format, ex: "5,50 €" or "11933 XPF"
* based on the value of isNewCaledonianLocation
* @param {number} priceInCents - price in euros (in cents)
*/

export const formatToFrenchDecimal = (priceInCents: number, options?: FormatPriceOptions) => {
const euros = priceInCents / CENTS_IN_EURO
const fractionDigits = options?.fractionDigits ?? (euros === Math.floor(euros) ? 0 : 2)
const isNewCaledonianLocation = true
// const { selectedPlace } = useLocation()
// const isNewCaledonianLocation = selectedPlace?.info === 'Nouvelle-Calédonie'

const priceInEuros = priceInCents / CENTS_IN_EURO
let price: number
let unit: string
let fractionDigits: number

if (isNewCaledonianLocation) {
price = priceInEuros * EURO_TO_XPF_RATE
unit = 'CFP'
fractionDigits = 0
} else {
price = priceInEuros
unit = '€'
fractionDigits = options?.fractionDigits ?? (price === Math.floor(price) ? 0 : 2)
}

const formatter = new Intl.NumberFormat('fr-FR', {
style: 'currency',
currency: 'EUR',
minimumFractionDigits: fractionDigits,
maximumFractionDigits: fractionDigits,
})

return formatter.format(euros)
return `${formatter.format(price)}\u00A0${unit}`
}

export const formatPriceInEuroToDisplayPrice = (priceInEuro: number) =>
Expand Down
1 change: 1 addition & 0 deletions src/libs/parsers/pricesConversion.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export const CENTS_IN_EURO = 100
export const EURO_TO_XPF_RATE = 119.48

export const convertEuroToCents = (p: number): number => {
return Math.floor(Number((p * CENTS_IN_EURO).toFixed(2)))
Expand Down

0 comments on commit c69ba91

Please sign in to comment.