1
+ 'use client'
2
+
3
+ import { useEffect , useState } from "react" ;
4
+ import usePageContext from "@/store/usePageContext" ;
5
+ import { Form , useForm } from "@mantine/form" ;
6
+ import { CommitModel , DataProductPostParam } from "@/server/types" ;
7
+ import { RepoApi } from "@/server/RepoApi" ;
8
+ import { AppWrite } from "@/server/Client" ;
9
+ import { Box , Button , Divider , Input , InputLabel , LoadingOverlay , Select } from "@mantine/core" ;
10
+ import { notifications } from "@mantine/notifications" ;
11
+ import { ProductApi } from "@/server/ProductApi" ;
12
+
13
+ export default function ProductPostPage ( ) {
14
+ const context = usePageContext ( ) ;
15
+ const [ Parma , setParma ] = useState < { owner : string , repo : string } | undefined > ( ) ;
16
+ const [ Heads , setHeads ] = useState < CommitModel [ ] > ( [ ] ) ;
17
+ const [ Publishing , setPublishing ] = useState ( false ) ;
18
+ const repo_api = new RepoApi ( ) ;
19
+ const product_api = new ProductApi ( ) ;
20
+ useEffect ( ( ) => {
21
+ if ( context . repoCtx ) {
22
+ const { owner, repoName} = context . repoCtx ;
23
+ setParma ( { owner, repo : repoName } )
24
+ for ( const idx in context . repoCtx . branches ) {
25
+ const branch = context . repoCtx . branches [ idx ] ;
26
+ repo_api . OneCommit ( owner , repoName , branch . name , branch . head )
27
+ . then ( ( res ) => {
28
+ if ( res . status === 200 ) {
29
+ const json :AppWrite < CommitModel > = JSON . parse ( res . data ) ;
30
+ if ( json . code === 200 && json . data ) {
31
+ setHeads ( ( prev ) => {
32
+ if ( prev . find ( ( item ) => item . id === json . data ! . id ) ) {
33
+ return prev ;
34
+ } else {
35
+ return [ ...prev , json . data ! ] ;
36
+ }
37
+ } ) ;
38
+ }
39
+ }
40
+ } )
41
+ }
42
+ }
43
+ } , [ ] ) ;
44
+ const form = useForm ( {
45
+ mode : "uncontrolled" ,
46
+ initialValues : {
47
+ name : '' ,
48
+ description : '' ,
49
+ license : '' ,
50
+ price : 0 ,
51
+ hash : '' ,
52
+ type : '' ,
53
+ } ,
54
+ validate : {
55
+ name : ( value ) => {
56
+ if ( ! value ) {
57
+ return "Name is required" ;
58
+ }
59
+ if ( value . length > 100 ) {
60
+ return "Name is too long" ;
61
+ }
62
+ if ( value . includes ( "/" ) ) {
63
+ return "Name is invalid" ;
64
+ }
65
+ return null ;
66
+ } ,
67
+ license : ( value ) => {
68
+ if ( ! value ) {
69
+ return "License is required" ;
70
+ }
71
+ return null ;
72
+ } ,
73
+ hash : ( value ) => {
74
+ if ( ! value ) {
75
+ return "Hash is required" ;
76
+ }
77
+ return null ;
78
+ } ,
79
+ type : ( value ) => {
80
+ if ( ! value ) {
81
+ return "Type is required" ;
82
+ }
83
+ return null ;
84
+ } ,
85
+ price : ( value ) => {
86
+ if ( ! value ) {
87
+ return "Price is required" ;
88
+ }
89
+ if ( value < 0 ) {
90
+ return "Price is invalid, it is eqt 0" ;
91
+ }
92
+ } ,
93
+ }
94
+ } ) ;
95
+ const onSubmit = ( ) => {
96
+ if ( Publishing ) return ;
97
+ setPublishing ( true ) ;
98
+ form . validate ( ) ;
99
+ if ( ! form . isValid ( ) ) {
100
+ notifications
101
+ . show ( {
102
+ message : "Please fill in all required fields" ,
103
+ color : "red" ,
104
+ } )
105
+ setPublishing ( false )
106
+ return ;
107
+ }
108
+ const param :DataProductPostParam = {
109
+ name : form . getValues ( ) . name ,
110
+ description : form . getValues ( ) . description ,
111
+ license : form . getValues ( ) . license ,
112
+ price : form . getValues ( ) . price ,
113
+ hash : form . getValues ( ) . hash ,
114
+ type : form . getValues ( ) . type ,
115
+ }
116
+ product_api . Post ( Parma ! . owner , Parma ! . repo , param )
117
+ . then ( ( res ) => {
118
+ if ( res . status === 200 ) {
119
+ const json :AppWrite < string > = JSON . parse ( res . data ) ;
120
+ if ( json . code === 200 && json . data ) {
121
+ notifications . show ( {
122
+ title : "Success" ,
123
+ message : "Post success"
124
+ } )
125
+ setTimeout ( ( ) => {
126
+ window . location . href = "/r/" + Parma ! . owner + "/" + Parma ! . repo ;
127
+ } , 1000 ) ;
128
+ }
129
+ }
130
+ } )
131
+
132
+ setPublishing ( false ) ;
133
+
134
+ }
135
+
136
+ return (
137
+ < div className = "post" >
138
+ < h1 >
139
+ POST
140
+ </ h1 >
141
+ < Box pos = "relative" >
142
+ < LoadingOverlay visible = { Publishing } loaderProps = { { children : 'Forking...' } } />
143
+ < Form
144
+ form = { form }
145
+ id = "LayoutModelRepositoryPOST"
146
+ >
147
+ < Select
148
+ name = { "hash" }
149
+ label = "hash"
150
+ title = "Select hash"
151
+ withAsterisk
152
+ key = { form . key ( "hash" ) }
153
+ data = {
154
+ Heads . map ( ( item ) => {
155
+ return {
156
+ value : item . id ,
157
+ label : item . id + " " + item . message + " " + item . author + " " + new Date ( item . time * 1000 ) . toISOString ( )
158
+ }
159
+ } )
160
+ }
161
+ { ...form . getInputProps ( "owner" ) }
162
+ />
163
+ < InputLabel className = "w-full" >
164
+ name< a style = { { color : 'red' } } > *</ a >
165
+ < Input
166
+ name = "name"
167
+ placeholder = "Enter product name"
168
+ type = "tel"
169
+ aria-autocomplete = { "none" }
170
+ key = { form . key ( "name" ) }
171
+ { ...form . getInputProps ( "name" ) }
172
+ />
173
+ </ InputLabel >
174
+
175
+ < InputLabel className = "w-full" >
176
+ description(optional)
177
+ < Input
178
+ name = "description"
179
+ placeholder = "Enter product descrition"
180
+ type = "tel"
181
+ aria-autocomplete = { "none" }
182
+ key = { form . key ( "description" ) }
183
+ { ...form . getInputProps ( "description" ) }
184
+ />
185
+ </ InputLabel >
186
+
187
+ < InputLabel className = "w-full" >
188
+ license< a style = { { color : 'red' } } > *</ a >
189
+ < Input
190
+ name = "license"
191
+ placeholder = "Enter product license"
192
+ type = "tel"
193
+ aria-autocomplete = { "none" }
194
+ key = { form . key ( "license" ) }
195
+ { ...form . getInputProps ( "license" ) }
196
+ />
197
+ </ InputLabel >
198
+ < InputLabel className = "w-full" >
199
+ price< a style = { { color : 'red' } } > *</ a >
200
+ < Input
201
+ name = "price"
202
+ placeholder = "Enter product price"
203
+ type = "number"
204
+ aria-autocomplete = { "none" }
205
+ key = { form . key ( "price" ) }
206
+ { ...form . getInputProps ( "price" ) }
207
+ />
208
+ </ InputLabel >
209
+ < InputLabel className = "w-full" >
210
+ type< a style = { { color : 'red' } } > *</ a >
211
+ < Input
212
+ name = "type"
213
+ placeholder = "Enter product type"
214
+ type = "tel"
215
+ aria-autocomplete = { "none" }
216
+ key = { form . key ( "type" ) }
217
+ { ...form . getInputProps ( "type" ) }
218
+ />
219
+ </ InputLabel >
220
+ < Divider />
221
+ < div style = { {
222
+ display : "flex" ,
223
+ justifyContent : "flex-end" ,
224
+ alignItems : "center" ,
225
+ gap : "1rem" ,
226
+ marginRight : "auto"
227
+ } } >
228
+ < Button color = "green" type = "submit" onClick = { onSubmit } >
229
+ Publish
230
+ </ Button >
231
+ </ div >
232
+ </ Form >
233
+ </ Box >
234
+ </ div >
235
+ )
236
+
237
+ }
0 commit comments