1
+ import React from 'react' ;
2
+ import { Button } from "@/components/ui/button" ;
3
+ import { Input } from "@/components/ui/input" ;
4
+ import { Label } from "@/components/ui/label" ;
5
+ import { Info , ChevronDown , ChevronUp } from "lucide-react" ;
6
+
7
+ interface SearchParams {
8
+ startingUrl : string ;
9
+ goal : string ;
10
+ iterations : number ;
11
+ }
12
+
13
+ interface ControlPanelProps {
14
+ searchParams : SearchParams ;
15
+ handleParamChange : ( param : keyof SearchParams , value : string | boolean | number ) => void ;
16
+ handleStart : ( ) => void ;
17
+ disconnect : ( ) => void ;
18
+ isSearching : boolean ;
19
+ connected : boolean ;
20
+ }
21
+
22
+ const ControlPanelMCTS : React . FC < ControlPanelProps > = ( {
23
+ searchParams,
24
+ handleParamChange,
25
+ handleStart,
26
+ disconnect,
27
+ isSearching,
28
+ connected,
29
+ } ) => {
30
+ const [ showParameters , setShowParameters ] = React . useState ( true ) ;
31
+
32
+ return (
33
+ < div className = "bg-white dark:bg-slate-800 shadow-sm border-b sticky top-0 z-10" >
34
+ < div className = "py-3 px-4 max-w-full" >
35
+ < div className = "flex justify-between items-center" >
36
+ < h1 className = "text-2xl font-bold text-sky-950 dark:text-sky-100" > Visual Tree Search: RMCTS</ h1 >
37
+
38
+ < div className = "flex gap-2" >
39
+ < Button
40
+ onClick = { handleStart }
41
+ disabled = { isSearching }
42
+ className = "bg-cyan-600 hover:bg-cyan-700 text-white disabled:bg-cyan-300 dark:disabled:bg-cyan-900"
43
+ >
44
+ Start
45
+ </ Button >
46
+ < Button
47
+ onClick = { disconnect }
48
+ disabled = { ! connected }
49
+ variant = "destructive"
50
+ className = "bg-rose-600 hover:bg-rose-700 text-white"
51
+ >
52
+ End
53
+ </ Button >
54
+ </ div >
55
+ </ div >
56
+
57
+ < div className = "mt-3 bg-sky-50 dark:bg-sky-900/20 border border-sky-200 dark:border-sky-800 rounded-lg overflow-hidden" >
58
+ < div
59
+ className = "p-3 flex justify-between items-center cursor-pointer hover:bg-sky-100 dark:hover:bg-sky-900/30 transition-colors"
60
+ onClick = { ( ) => setShowParameters ( ! showParameters ) }
61
+ >
62
+ < div className = "flex items-start gap-2" >
63
+ < Info className = "h-5 w-5 text-cyan-600 dark:text-cyan-400 flex-shrink-0 mt-0.5" />
64
+ < div >
65
+ < h3 className = "font-medium text-sky-800 dark:text-sky-300" > How to use this playground</ h3 >
66
+ < p className = "text-sm text-sky-700 dark:text-sky-400" >
67
+ Configure your search parameters and visualize web browsing automation with tree search algorithms.
68
+ </ p >
69
+ </ div >
70
+ </ div >
71
+ { showParameters ? < ChevronUp className = "text-cyan-600" /> : < ChevronDown className = "text-cyan-600" /> }
72
+ </ div >
73
+
74
+ { showParameters && (
75
+ < div className = "p-4 border-t border-sky-200 dark:border-sky-800 bg-white/90 dark:bg-slate-800/90" >
76
+ { /* Instructions */ }
77
+ < div className = "mb-4 ml-1 text-sm text-slate-700 dark:text-slate-300" >
78
+ < ol className = "list-decimal list-inside space-y-1" >
79
+ < li > Click the "Start" button above to connect and begin the search.</ li >
80
+ < li > Configure your search parameters below.</ li >
81
+ < li > The tree of possible actions will appear on the right, while the resulting web page will display on the left.</ li >
82
+ < li > You can drag the divider to resize the panels as needed.</ li >
83
+ </ ol >
84
+ </ div >
85
+
86
+ { /* Parameters Grid */ }
87
+ < div className = "grid grid-cols-1 md:grid-cols-4 gap-4 mt-4" >
88
+ < div className = "space-y-2" >
89
+ < Label htmlFor = "startingUrl" className = "text-slate-700 dark:text-slate-300 font-medium" > Starting URL</ Label >
90
+ < Input
91
+ id = "startingUrl"
92
+ value = { searchParams . startingUrl }
93
+ onChange = { ( e ) => handleParamChange ( 'startingUrl' , e . target . value ) }
94
+ className = "border-slate-300 dark:border-slate-600 focus:ring-cyan-500 focus:border-cyan-500"
95
+ />
96
+ </ div >
97
+
98
+ < div className = "space-y-2" >
99
+ < Label htmlFor = "goal" className = "text-slate-700 dark:text-slate-300 font-medium" > Goal</ Label >
100
+ < Input
101
+ id = "goal"
102
+ value = { searchParams . goal }
103
+ onChange = { ( e ) => handleParamChange ( 'goal' , e . target . value ) }
104
+ className = "border-slate-300 dark:border-slate-600 focus:ring-cyan-500 focus:border-cyan-500"
105
+ />
106
+ </ div >
107
+
108
+ < div className = "space-y-2" >
109
+ < Label htmlFor = "iterations" className = "text-slate-700 dark:text-slate-300 font-medium" > Iterations</ Label >
110
+ < Input
111
+ id = "iterations"
112
+ type = "number"
113
+ min = { 1 }
114
+ max = { 10 }
115
+ value = { searchParams . iterations }
116
+ onChange = { ( e ) => handleParamChange ( 'iterations' , parseInt ( e . target . value ) ) }
117
+ className = "border-slate-300 dark:border-slate-600 focus:ring-cyan-500 focus:border-cyan-500"
118
+ />
119
+ </ div >
120
+ </ div >
121
+ </ div >
122
+ ) }
123
+ </ div >
124
+ </ div >
125
+ </ div >
126
+ ) ;
127
+ } ;
128
+
129
+ export default ControlPanelMCTS ;
0 commit comments