1
- import { Dialog , Transition } from '@headlessui/react' ;
1
+ import { Dialog } from '@headlessui/react' ;
2
2
import prettier from 'prettier' ;
3
3
import babelParser from 'prettier/parser-babel' ;
4
- import React , { useRef , useState } from 'react' ;
4
+ import React , { useState } from 'react' ;
5
+ import Modal from '../Modal' ;
5
6
import CopyButton from './CopyButton' ;
6
- import parse , { parsers } from './parsers/parse' ;
7
- async function getHtml ( url : string ) : Promise < string > {
8
- const res = await fetch ( '/api/fetch-html' , {
9
- method : 'POST' ,
10
- headers : {
11
- 'Content-Type' : 'application/json' ,
12
- } ,
13
- body : JSON . stringify ( { url } ) ,
14
- } ) . then ( res => res . json ( ) ) ;
15
- return res . data ;
16
- }
17
7
async function addProblem (
18
8
url : string ,
19
9
setMetadata : ( metadata : string ) => void ,
20
- setStatus : ( status : string ) => void
10
+ setStatus : ( status : 'Get Metadata' | 'Fetching metadata...' ) => void
21
11
) {
22
12
try {
23
13
setStatus ( 'Fetching metadata...' ) ;
24
- const html = await getHtml ( url ) ;
25
- const parsed = parse ( url , html ) ;
14
+ const parsed = (
15
+ await fetch ( '/api/fetch-metadata' , {
16
+ method : 'POST' ,
17
+ headers : {
18
+ 'Content-Type' : 'application/json' ,
19
+ } ,
20
+ body : JSON . stringify ( { url } ) ,
21
+ } ) . then ( res => res . json ( ) )
22
+ ) . data ;
26
23
const metadata = {
27
24
uniqueId : parsed . uniqueId ,
28
25
name : parsed . name ,
@@ -33,96 +30,63 @@ async function addProblem(
33
30
tags : [ 'Add Tags' ] ,
34
31
solutionMetadata : parsed . solutionMetadata ,
35
32
} ;
36
- console . log ( metadata ) ;
37
33
setMetadata (
38
- await prettier . format ( JSON . stringify ( metadata ) , {
34
+ await prettier . format ( JSON . stringify ( metadata , null , 2 ) , {
39
35
parser : 'json' ,
40
36
plugins : [ babelParser ] ,
41
37
} )
42
38
) ;
43
39
setStatus ( 'Get Metadata' ) ;
44
40
} catch ( e ) {
45
- setMetadata (
46
- `No parser found for this url.
47
- Available parsers:
48
- ${ Object . keys ( parsers )
49
- . map ( key => ` - ${ key } ` )
50
- . join ( '\n' ) } `
51
- ) ;
41
+ setMetadata ( e . toString ( ) ) ;
52
42
setStatus ( 'Get Metadata' ) ;
53
43
}
54
44
}
55
- export default function AddProblemModal ( { isOpen, onClose } ) {
56
- const linkRef = useRef < HTMLInputElement > ( null ) ;
45
+ export default function AddProblemModal ( props : {
46
+ isOpen : boolean ;
47
+ onClose : ( ) => void ;
48
+ } ) {
49
+ const [ link , setLink ] = useState ( '' ) ;
57
50
const [ metadata , setMetadata ] = useState ( '// metadata will appear here' ) ;
58
- const [ status , setStatus ] = useState ( 'Get Metadata' ) ;
51
+ const [ status , setStatus ] = useState < 'Get Metadata' | 'Fetching metadata...' > (
52
+ 'Get Metadata'
53
+ ) ;
59
54
return (
60
- < Transition appear show = { isOpen } as = { React . Fragment } >
61
- < Dialog as = "div" className = "relative z-10" onClose = { onClose } >
62
- < Transition . Child
63
- as = { React . Fragment }
64
- enter = "ease-out duration-300"
65
- enterFrom = "opacity-0"
66
- enterTo = "opacity-100"
67
- leave = "ease-in duration-200"
68
- leaveFrom = "opacity-100"
69
- leaveTo = "opacity-0"
70
- >
71
- < div className = "fixed inset-0 bg-black/25" />
72
- </ Transition . Child >
73
-
74
- < div className = "fixed inset-0 overflow-y-auto" >
75
- < div className = "flex min-h-full items-center justify-center p-4 text-center" >
76
- < Transition . Child
77
- as = { React . Fragment }
78
- enter = "ease-out duration-300"
79
- enterFrom = "opacity-0 scale-95"
80
- enterTo = "opacity-100 scale-100"
81
- leave = "ease-in duration-200"
82
- leaveFrom = "opacity-100 scale-100"
83
- leaveTo = "opacity-0 scale-95"
84
- >
85
- < Dialog . Panel className = "w-full max-w-md transform overflow-hidden rounded-2xl bg-black text-white p-6 text-left align-middle shadow-xl transition-all" >
86
- < Dialog . Title as = "h3" className = "text-lg font-medium leading-6" >
87
- Add Problem
88
- </ Dialog . Title >
89
- < div className = "mt-2 relative rounded-md shadow-sm" >
90
- < input
91
- type = "text"
92
- className = "shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md dark:bg-gray-900 dark:border-gray-700"
93
- placeholder = "Enter Problem URL"
94
- onChange = { e => console . log ( e . target . value ) }
95
- ref = { linkRef }
96
- />
97
- </ div >
55
+ < Modal { ...props } >
56
+ < Dialog . Panel className = "w-full max-w-2xl transform overflow-hidden rounded-2xl bg-black text-white p-6 text-left align-middle shadow-xl transition-all" >
57
+ < Dialog . Title as = "h3" className = "text-lg font-medium leading-6" >
58
+ Add Problem
59
+ </ Dialog . Title >
60
+ < div className = "mt-2 relative rounded-md shadow-sm" >
61
+ < input
62
+ type = "text"
63
+ className = "shadow-sm focus:ring-blue-500 focus:border-blue-500 block w-full sm:text-sm border-gray-300 rounded-md dark:bg-gray-900 dark:border-gray-700"
64
+ placeholder = "Enter Problem URL"
65
+ onChange = { e => setLink ( e . target . value ) }
66
+ />
67
+ </ div >
98
68
99
- < div className = "mt-4" >
100
- < button
101
- className = "btn"
102
- onClick = { ( ) =>
103
- linkRef . current &&
104
- addProblem ( linkRef . current . value , setMetadata , setStatus )
105
- }
106
- >
107
- { status }
108
- </ button >
109
- </ div >
110
- < div className = "mt-4 relative" >
111
- < pre className = "bg-gray-900 p-4 rounded-md text-white text-xs whitespace-pre-wrap" >
112
- { metadata }
113
- </ pre >
114
- < CopyButton
115
- className = "btn absolute top-2 right-2"
116
- onClick = { ( ) => {
117
- navigator . clipboard . writeText ( metadata ) ;
118
- } }
119
- />
120
- </ div >
121
- </ Dialog . Panel >
122
- </ Transition . Child >
123
- </ div >
69
+ < div className = "mt-4" >
70
+ < button
71
+ className = "btn"
72
+ disabled = { status === 'Fetching metadata...' }
73
+ onClick = { ( ) => addProblem ( link , setMetadata , setStatus ) }
74
+ >
75
+ { status }
76
+ </ button >
77
+ </ div >
78
+ < div className = "mt-4 relative" >
79
+ < pre className = "bg-gray-900 p-4 rounded-md text-white text-sm whitespace-pre-wrap" >
80
+ { metadata }
81
+ </ pre >
82
+ < CopyButton
83
+ className = "btn absolute top-2 right-2"
84
+ onClick = { ( ) => {
85
+ navigator . clipboard . writeText ( metadata ) ;
86
+ } }
87
+ />
124
88
</ div >
125
- </ Dialog >
126
- </ Transition >
89
+ </ Dialog . Panel >
90
+ </ Modal >
127
91
) ;
128
92
}
0 commit comments