1
1
import { useCallback , useMemo } from 'react'
2
2
3
+ import {
4
+ Genre ,
5
+ HashId ,
6
+ Mood ,
7
+ PremiumConditionsFollowUserId ,
8
+ PremiumConditionsNFTCollection ,
9
+ PremiumConditionsTipUserId
10
+ } from '@audius/sdk'
3
11
import {
4
12
HarmonyButton ,
5
13
HarmonyButtonType ,
@@ -9,7 +17,8 @@ import {
9
17
import cn from 'classnames'
10
18
import { Form , Formik , FormikProps , useField } from 'formik'
11
19
import moment from 'moment'
12
- import * as Yup from 'yup'
20
+ import { z } from 'zod'
21
+ import { toFormikValidationSchema } from 'zod-formik-adapter'
13
22
14
23
import { ReactComponent as IconCaretLeft } from 'assets/img/iconCaretLeft.svg'
15
24
import layoutStyles from 'components/layout/layout.module.css'
@@ -32,7 +41,11 @@ const messages = {
32
41
multiTrackCount : ( index : number , total : number ) =>
33
42
`TRACK ${ index } of ${ total } ` ,
34
43
prev : 'Prev' ,
35
- next : 'Next Track'
44
+ next : 'Next Track' ,
45
+ titleRequiredError : 'Your track must have a name' ,
46
+ artworkRequiredError : 'Artwork is required' ,
47
+ genreRequiredError : 'Genre is required' ,
48
+ invalidReleaseDateError : 'Release date should no be in the future'
36
49
}
37
50
38
51
type EditPageProps = {
@@ -41,27 +54,115 @@ type EditPageProps = {
41
54
onContinue : ( ) => void
42
55
}
43
56
44
- const EditTrackSchema = Yup . object ( ) . shape ( {
45
- title : Yup . string ( ) . required ( messages . titleError ) ,
46
- artwork : Yup . object ( {
47
- url : Yup . string ( )
48
- } ) . required ( messages . artworkError ) ,
49
- trackArtwork : Yup . string ( ) . nullable ( ) ,
50
- genre : Yup . string ( ) . required ( messages . genreError ) ,
51
- description : Yup . string ( ) . max ( 1000 ) . nullable ( )
52
- } )
57
+ // TODO: KJ - Need to update the schema in sdk and then import here
58
+ const createUploadTrackMetadataSchema = ( ) =>
59
+ z . object ( {
60
+ aiAttributionUserId : z . optional ( HashId ) ,
61
+ description : z . optional ( z . string ( ) . max ( 1000 ) ) ,
62
+ download : z . optional (
63
+ z
64
+ . object ( {
65
+ cid : z . string ( ) ,
66
+ isDownloadable : z . boolean ( ) ,
67
+ requiresFollow : z . boolean ( )
68
+ } )
69
+ . strict ( )
70
+ . nullable ( )
71
+ ) ,
72
+ fieldVisibility : z . optional (
73
+ z . object ( {
74
+ mood : z . optional ( z . boolean ( ) ) ,
75
+ tags : z . optional ( z . boolean ( ) ) ,
76
+ genre : z . optional ( z . boolean ( ) ) ,
77
+ share : z . optional ( z . boolean ( ) ) ,
78
+ playCount : z . optional ( z . boolean ( ) ) ,
79
+ remixes : z . optional ( z . boolean ( ) )
80
+ } )
81
+ ) ,
82
+ genre : z
83
+ . enum ( Object . values ( Genre ) as [ Genre , ...Genre [ ] ] )
84
+ . nullable ( )
85
+ . refine ( ( val ) => val !== null , {
86
+ message : messages . genreRequiredError
87
+ } ) ,
88
+ isPremium : z . optional ( z . boolean ( ) ) ,
89
+ isrc : z . optional ( z . string ( ) . nullable ( ) ) ,
90
+ isUnlisted : z . optional ( z . boolean ( ) ) ,
91
+ iswc : z . optional ( z . string ( ) . nullable ( ) ) ,
92
+ license : z . optional ( z . string ( ) . nullable ( ) ) ,
93
+ mood : z
94
+ . optional ( z . enum ( Object . values ( Mood ) as [ Mood , ...Mood [ ] ] ) )
95
+ . nullable ( ) ,
96
+ premiumConditions : z . optional (
97
+ z . union ( [
98
+ PremiumConditionsNFTCollection ,
99
+ PremiumConditionsFollowUserId ,
100
+ PremiumConditionsTipUserId
101
+ ] )
102
+ ) ,
103
+ releaseDate : z . optional (
104
+ z . date ( ) . max ( new Date ( ) , { message : messages . invalidReleaseDateError } )
105
+ ) ,
106
+ remixOf : z . optional (
107
+ z
108
+ . object ( {
109
+ tracks : z
110
+ . array (
111
+ z . object ( {
112
+ parentTrackId : HashId
113
+ } )
114
+ )
115
+ . min ( 1 )
116
+ } )
117
+ . strict ( )
118
+ ) ,
119
+ tags : z . optional ( z . string ( ) ) ,
120
+ title : z . string ( {
121
+ required_error : messages . titleRequiredError
122
+ } ) ,
123
+ previewStartSeconds : z . optional ( z . number ( ) ) ,
124
+ audioUploadId : z . optional ( z . string ( ) ) ,
125
+ previewCid : z . optional ( z . string ( ) )
126
+ } )
127
+
128
+ const createTrackMetadataSchema = ( ) => {
129
+ return createUploadTrackMetadataSchema ( )
130
+ . merge (
131
+ z . object ( {
132
+ artwork : z
133
+ . object ( {
134
+ url : z . string ( )
135
+ } )
136
+ . nullable ( )
137
+ } )
138
+ )
139
+ . refine ( ( form ) => form . artwork !== null , {
140
+ message : messages . artworkRequiredError ,
141
+ path : [ 'artwork' ]
142
+ } )
143
+ }
144
+
145
+ export type TrackMetadataValues = z . input <
146
+ ReturnType < typeof createTrackMetadataSchema >
147
+ >
148
+
149
+ const EditFormValidationSchema = ( ) =>
150
+ z . object ( {
151
+ trackMetadatas : z . array ( createTrackMetadataSchema ( ) )
152
+ } )
53
153
54
154
export const EditPageNew = ( props : EditPageProps ) => {
55
155
const { tracks, setTracks, onContinue } = props
56
156
157
+ // @ts -ignore - Slight differences in the sdk vs common track metadata types
57
158
const initialValues : TrackEditFormValues = useMemo (
58
159
( ) => ( {
59
160
trackMetadatasIndex : 0 ,
60
161
trackMetadatas : tracks . map ( ( track ) => ( {
61
162
...track . metadata ,
62
163
artwork : null ,
63
164
description : '' ,
64
- releaseDate : moment ( ) . startOf ( 'day' ) ,
165
+ releaseDate : new Date ( moment ( ) . startOf ( 'day' ) . toString ( ) ) ,
65
166
tags : '' ,
66
167
field_visibility : {
67
168
...defaultHiddenFields ,
@@ -93,7 +194,8 @@ export const EditPageNew = (props: EditPageProps) => {
93
194
< Formik < TrackEditFormValues >
94
195
initialValues = { initialValues }
95
196
onSubmit = { onSubmit }
96
- validationSchema = { EditTrackSchema }
197
+ // @ts -ignore - There are slight mismatches between the sdk and common track metadata types
198
+ validationSchema = { toFormikValidationSchema ( EditFormValidationSchema ( ) ) }
97
199
>
98
200
{ TrackEditForm }
99
201
</ Formik >
0 commit comments