Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
Fix validation on access and sale modal (#3981)
Browse files Browse the repository at this point in the history
  • Loading branch information
amendelsohn authored Aug 30, 2023
1 parent a2b0890 commit 7493cff
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 63 deletions.
1 change: 1 addition & 0 deletions packages/common/src/models/Track.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export type PremiumConditionsUSDCPurchase = {
}

export type PremiumConditions =
| {}
| PremiumConditionsCollectibleGated
| PremiumConditionsFollowGated
| PremiumConditionsTipGated
Expand Down
8 changes: 7 additions & 1 deletion packages/common/src/utils/dogEarUtils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { isEmpty } from 'lodash'

import { DogEarType } from 'models/DogEar'
import { PremiumConditions } from 'models/Track'

Expand Down Expand Up @@ -33,7 +35,11 @@ export const getDogEarType = ({
}

// Show premium variants for track owners or if user does not yet have access
if ((isOwner || !doesUserHaveAccess) && premiumConditions != null) {
if (
(isOwner || !doesUserHaveAccess) &&
premiumConditions != null &&
!isEmpty(premiumConditions)
) {
if ('usdc_purchase' in premiumConditions) {
return DogEarType.USDC_PURCHASE
} else if ('nft_collection' in premiumConditions) {
Expand Down
70 changes: 30 additions & 40 deletions packages/web/src/components/data-entry/AccessAndSaleModalLegacy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ import {
IconSpecialAccess,
IconVisibilityPublic
} from '@audius/stems'
import { set, isEmpty, get } from 'lodash'
import { z } from 'zod'
import { set, get } from 'lodash'
import { toFormikValidationSchema } from 'zod-formik-adapter'

import { TrackMetadataState } from 'components/track-availability-modal/types'
import { defaultFieldVisibility } from 'pages/track-page/utils'
import {
AVAILABILITY_TYPE,
AccessAndSaleFormSchema,
AccessAndSaleFormValues,
AccessAndSaleMenuFields,
FIELD_VISIBILITY,
Expand Down Expand Up @@ -54,37 +54,16 @@ const messages = {
errors: {
price: {
tooLow: 'Price must be at least $0.99',
tooHigh: 'Price must be less than $9.99'
tooHigh: 'Price must be less than $9999.99'
},
preview: {
tooEarly: 'Preview must start during the track',
tooLate:
'Preview must start at lest 15 seconds before the end of the track'
'Preview must start at least 30 seconds before the end of the track'
}
}
}

const AccessAndSaleFormSchema = (trackLength: number) =>
z.object({
[PREMIUM_CONDITIONS]: z.nullable(
z.object({
// TODO: there are other types
usdc_purchase: z.object({
price: z
.number()
.lte(999, messages.errors.price.tooHigh)
.gte(99, messages.errors.price.tooLow)
})
})
),
[PREVIEW]: z.optional(
z
.number()
.gte(0, messages.errors.preview.tooEarly)
.lte(trackLength - 15, messages.errors.preview.tooLate)
)
})

type AccessAndSaleModalLegacyProps = {
isRemix: boolean
isUpload: boolean
Expand Down Expand Up @@ -155,30 +134,42 @@ export const AccessAndSaleModalLegacy = (

const onSubmit = (values: AccessAndSaleFormValues) => {
let newState = {
...metadataState,
is_premium: !isEmpty(values[PREMIUM_CONDITIONS]),
premium_conditions: values[PREMIUM_CONDITIONS],
unlisted: values.is_unlisted,
preview_start_seconds: values[PREVIEW] ?? 0
...metadataState
}

if (
get(values, AVAILABILITY_TYPE) === TrackAvailabilityType.USDC_PURCHASE
) {
newState.is_premium = true
const price = Math.round(get(values, PRICE))
newState.premium_conditions = {
// @ts-ignore splits get added in saga
usdc_purchase: {
price
const availabilityType = get(values, AVAILABILITY_TYPE)
switch (availabilityType) {
case TrackAvailabilityType.PUBLIC: {
newState.is_premium = false
newState.unlisted = false
newState.premium_conditions = {}
break
}
case TrackAvailabilityType.USDC_PURCHASE: {
newState.is_premium = true
const price = Math.round(get(values, PRICE))
newState.premium_conditions = {
// @ts-ignore splits get added in saga
usdc_purchase: {
price
}
}
newState.preview_start_seconds = get(values, PREVIEW) ?? 0
break
}
case TrackAvailabilityType.COLLECTIBLE_GATED:
case TrackAvailabilityType.SPECIAL_ACCESS: {
newState.is_premium = true
newState.premium_conditions = get(values, PREMIUM_CONDITIONS)
break
}
}

if (get(values, AVAILABILITY_TYPE) === TrackAvailabilityType.HIDDEN) {
newState = {
...newState,
...(get(values, FIELD_VISIBILITY) ?? undefined),
premium_conditions: {},
unlisted: true
}
} else {
Expand Down Expand Up @@ -218,7 +209,6 @@ export const AccessAndSaleModalLegacy = (
initialValues={initialValues}
onSubmit={onSubmit}
validationSchema={toFormikValidationSchema(
// @ts-ignore
AccessAndSaleFormSchema(trackLength)
)}
menuFields={
Expand Down
72 changes: 50 additions & 22 deletions packages/web/src/pages/upload-page/fields/AccessAndSaleField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ const messages = {
errors: {
price: {
tooLow: 'Price must be at least $0.99.',
tooHigh: 'Price must be less than $9.99.'
tooHigh: 'Price must be less than $9999.99.'
},
preview: {
tooEarly: 'Preview must start during the track.',
tooLate:
'Preview must start at lest 15 seconds before the end of the track.'
'Preview must start at least 30 seconds before the end of the track.'
}
}
}
Expand All @@ -140,26 +140,47 @@ export type AccessAndSaleFormValues = {
[PREVIEW]?: number
}

const AccessAndSaleFormSchema = (trackLength: number) =>
z.object({
[PREMIUM_CONDITIONS]: z.nullable(
z.object({
// TODO: there are other types
usdc_purchase: z.object({
price: z
.number()
.lte(999, messages.errors.price.tooHigh)
.gte(99, messages.errors.price.tooLow)
export const AccessAndSaleFormSchema = (trackLength: number) =>
z
.object({
[PREMIUM_CONDITIONS]: z.nullable(
z.object({
// TODO: there are other types
usdc_purchase: z.optional(
z.object({
price: z
.number()
.lte(999999, messages.errors.price.tooHigh)
.gte(99, messages.errors.price.tooLow)
})
)
})
})
),
[PREVIEW]: z.optional(
z
.number()
.gte(0, messages.errors.preview.tooEarly)
.lte(trackLength - 15, messages.errors.preview.tooLate)
),
[PREVIEW]: z.optional(z.nullable(z.number()))
})
.refine(
(values) => {
const formValues = values as AccessAndSaleFormValues
if (isPremiumContentUSDCPurchaseGated(formValues[PREMIUM_CONDITIONS])) {
return formValues[PREVIEW] !== undefined && formValues[PREVIEW] >= 0
}
return true
},
{ message: messages.errors.preview.tooEarly, path: [PREVIEW] }
)
.refine(
(values) => {
const formValues = values as AccessAndSaleFormValues
if (isPremiumContentUSDCPurchaseGated(formValues[PREMIUM_CONDITIONS])) {
return (
formValues[PREVIEW] === undefined ||
(formValues[PREVIEW] >= 0 && formValues[PREVIEW] < trackLength - 30)
)
}
return true
},
{ message: messages.errors.preview.tooLate, path: [PREVIEW] }
)
})

type AccessAndSaleFieldProps = {
isUpload?: boolean
Expand Down Expand Up @@ -470,8 +491,14 @@ export const AccessAndSaleMenuFields = (props: AccesAndSaleMenuFieldsProps) => {
}
case TrackAvailabilityType.USDC_PURCHASE: {
if (!isPremiumContentUSDCPurchaseGated(premiumConditionsValue)) {
setPremiumConditionsValue(null)
setPremiumConditionsValue({
// @ts-ignore splits added in saga
usdc_purchase: {
price: 0
}
})
}

if (!previewValue) {
setPreviewValue(0)
}
Expand All @@ -492,9 +519,10 @@ export const AccessAndSaleMenuFields = (props: AccesAndSaleMenuFieldsProps) => {
isPremiumContentCollectibleGated(premiumConditionsValue)
)
break
setPremiumConditionsValue(null)
setPremiumConditionsValue({})
break
case TrackAvailabilityType.HIDDEN:
setPremiumConditionsValue({})
if (!fieldVisibilityValue) break
setfieldVisibilityValue({
...fieldVisibilityValue,
Expand Down

0 comments on commit 7493cff

Please sign in to comment.