11// src/components/Sidebar.tsx
22"use client" ;
3- import { useEffect , useState , ChangeEvent , useCallback , useRef } from "react" ;
3+ import { useEffect , useState , useCallback , useRef } from "react" ;
44import { generateRandomPoint } from "@/lib/utils/randomPoint" ;
55import { SidebarProps , ShapeType } from "@/types" ;
66import { theme } from "@/lib/theme" ;
77import Image from "next/image" ;
88import TestMode from "./TestMode" ;
9+ import { Button } from "@/components/ui/button" ;
10+ import { Slider } from "@/components/ui/slider" ;
911
1012export default function Sidebar ( {
1113 shapeState,
@@ -59,13 +61,10 @@ export default function Sidebar({
5961 [ shapeType , updateShapeState , setIsDrawingPolygon ] ,
6062 ) ;
6163
62- // Handle value changes with debouncing
63- const handleValueChange = useCallback (
64- (
65- e : ChangeEvent < HTMLInputElement > ,
66- valueType : "radiusX" | "radiusY" | "rotation" ,
67- ) => {
68- const value = e . target . value ;
64+ // Handle slider value changes
65+ const handleSliderChange = useCallback (
66+ ( values : number [ ] , valueType : "radiusX" | "radiusY" | "rotation" ) => {
67+ const value = values [ 0 ] . toString ( ) ;
6968
7069 // Update local input state
7170 if ( valueType === "radiusX" ) {
@@ -145,7 +144,7 @@ export default function Sidebar({
145144 } ;
146145
147146 return (
148- < div className = "w-80 bg-black shadow-md p-4 overflow-auto h-screen text-white" >
147+ < div className = "w-80 bg-background shadow-md p-4 overflow-auto h-screen text-white" >
149148 < div className = "flex flex-col items-center justify-center select-none" >
150149 < Image
151150 src = "/PickRandomSpot/logo.svg"
@@ -178,12 +177,9 @@ export default function Sidebar({
178177 < div className = "mb-4" >
179178 < h2 className = "text-lg font-semibold mb-2" > Shape Type</ h2 >
180179 < div className = "grid grid-cols-3 gap-2" >
181- < button
182- className = { `px-2 py-1 rounded transition-colors ${
183- shapeType === "ellipse"
184- ? "bg-emerald-600 text-white"
185- : "bg-gray-700 hover:bg-gray-600"
186- } `}
180+ < Button
181+ className = { shapeType === "ellipse" ? "text-white" : "" }
182+ variant = { shapeType === "ellipse" ? "default" : "outline" }
187183 style = {
188184 shapeType === "ellipse"
189185 ? { backgroundColor : theme . shapes . ellipse . color }
@@ -192,13 +188,10 @@ export default function Sidebar({
192188 onClick = { ( ) => handleShapeTypeChange ( "ellipse" ) }
193189 >
194190 Ellipse
195- </ button >
196- < button
197- className = { `px-2 py-1 rounded transition-colors ${
198- shapeType === "rectangle"
199- ? "bg-amber-600 text-white"
200- : "bg-gray-700 hover:bg-gray-600"
201- } `}
191+ </ Button >
192+ < Button
193+ className = { shapeType === "rectangle" ? "text-white" : "" }
194+ variant = { shapeType === "rectangle" ? "default" : "outline" }
202195 style = {
203196 shapeType === "rectangle"
204197 ? { backgroundColor : theme . shapes . rectangle . color }
@@ -207,13 +200,10 @@ export default function Sidebar({
207200 onClick = { ( ) => handleShapeTypeChange ( "rectangle" ) }
208201 >
209202 Rectangle
210- </ button >
211- < button
212- className = { `px-2 py-1 rounded transition-colors ${
213- shapeType === "polygon"
214- ? "bg-purple-600 text-white"
215- : "bg-gray-700 hover:bg-gray-600"
216- } `}
203+ </ Button >
204+ < Button
205+ className = { shapeType === "polygon" ? "text-white" : "" }
206+ variant = { shapeType === "polygon" ? "default" : "outline" }
217207 style = {
218208 shapeType === "polygon"
219209 ? { backgroundColor : theme . shapes . polygon . color }
@@ -222,7 +212,7 @@ export default function Sidebar({
222212 onClick = { ( ) => handleShapeTypeChange ( "polygon" ) }
223213 >
224214 Polygon
225- </ button >
215+ </ Button >
226216 </ div >
227217 </ div >
228218
@@ -238,43 +228,45 @@ export default function Sidebar({
238228 </ p >
239229 { points . length > 2 && (
240230 < p className = "mb-2" >
241- { /* Remove reference to clicking near first point */ }
242231 Click "Complete Drawing" when you're finished
243232 adding points.
244233 </ p >
245234 ) }
246- < button
247- className = "px-2 py-1 rounded bg-green-600 hover:bg-green-700 text-white mt-2 mr-2"
235+ < Button
236+ variant = "default"
237+ className = "mr-2 mt-2"
248238 onClick = { ( ) => {
249239 // Complete the polygon instead of canceling
250240 setIsDrawingPolygon ( false ) ;
251241 } }
252242 disabled = { points . length < 3 }
253243 >
254244 Complete Drawing
255- </ button >
256- < button
257- className = "px-2 py-1 rounded bg-red-600 hover:bg-red-700 text-white mt-2"
245+ </ Button >
246+ < Button
247+ variant = "destructive"
248+ className = "mt-2"
258249 onClick = { ( ) => {
259250 updateShapeState ( { points : [ ] } ) ;
260251 setIsDrawingPolygon ( false ) ;
261252 } }
262253 >
263254 Cancel Drawing
264- </ button >
255+ </ Button >
265256 </ div >
266257 ) : points . length > 2 ? (
267258 < div >
268259 < p className = "mb-2" > Polygon with { points . length } points</ p >
269- < button
270- className = "px-2 py-1 rounded bg-blue-600 hover:bg-blue-700 text-white mt-2"
260+ < Button
261+ variant = "default"
262+ className = "mt-2"
271263 onClick = { ( ) => {
272264 // Keep existing points when redrawing
273265 setIsDrawingPolygon ( true ) ;
274266 } }
275267 >
276268 Redraw Polygon
277- </ button >
269+ </ Button >
278270 </ div >
279271 ) : (
280272 < p className = "text-gray-400" >
@@ -296,54 +288,54 @@ export default function Sidebar({
296288
297289 { /* Width/Radius X */ }
298290 < div className = "mb-4" >
299- < label className = "block text-sm font-medium mb-1" >
291+ < label className = "select-none block text-sm font-medium mb-1" >
300292 { shapeType === "rectangle" ? "Width" : "Radius X" } (km):{ " " }
301293 { radiusXInput }
302294 </ label >
303- < input
304- type = "range"
305- min = "0.1"
306- max = "100"
307- step = "0.1"
308- value = { radiusXInput }
309- onChange = { ( e ) => handleValueChange ( e , "radiusX" ) }
310- className = "w-full"
295+ < Slider
296+ min = { 0.1 }
297+ max = { 100 }
298+ step = { 0.1 }
299+ value = { [ parseFloat ( radiusXInput ) ] }
300+ onValueChange = { ( values ) =>
301+ handleSliderChange ( values , "radiusX" )
302+ }
311303 />
312304 </ div >
313305
314306 { /* Height/Radius Y (only for ellipse and rectangle) */ }
315307 { ( shapeType === "ellipse" || shapeType === "rectangle" ) && (
316308 < div className = "mb-4" >
317- < label className = "block text-sm font-medium mb-1" >
309+ < label className = "select-none block text-sm font-medium mb-1" >
318310 { shapeType === "rectangle" ? "Height" : "Radius Y" } (km):{ " " }
319311 { radiusYInput }
320312 </ label >
321- < input
322- type = "range"
323- min = "0.1"
324- max = "100"
325- step = "0.1"
326- value = { radiusYInput }
327- onChange = { ( e ) => handleValueChange ( e , "radiusY" ) }
328- className = "w-full"
313+ < Slider
314+ min = { 0.1 }
315+ max = { 100 }
316+ step = { 0.1 }
317+ value = { [ parseFloat ( radiusYInput ) ] }
318+ onValueChange = { ( values ) =>
319+ handleSliderChange ( values , "radiusY" )
320+ }
329321 />
330322 </ div >
331323 ) }
332324
333325 { /* Rotation (only for ellipse and rectangle) */ }
334326 { ( shapeType === "ellipse" || shapeType === "rectangle" ) && (
335327 < div className = "mb-4" >
336- < label className = "block text-sm font-medium mb-1" >
328+ < label className = "select-none block text-sm font-medium mb-1" >
337329 Rotation (°): { rotationInput }
338330 </ label >
339- < input
340- type = "range"
341- min = "0"
342- max = "360"
343- step = "1"
344- value = { rotationInput }
345- onChange = { ( e ) => handleValueChange ( e , "rotation" ) }
346- className = "w-full"
331+ < Slider
332+ min = { 0 }
333+ max = { 360 }
334+ step = { 1 }
335+ value = { [ parseFloat ( rotationInput ) ] }
336+ onValueChange = { ( values ) =>
337+ handleSliderChange ( values , "rotation" )
338+ }
347339 />
348340 </ div >
349341 ) }
@@ -356,9 +348,9 @@ export default function Sidebar({
356348 </ div >
357349
358350 < div className = "space-y-2" >
359- < button
360- className = "bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded w-full transition-colors disabled:opacity-50 disabled:cursor-not-allowed "
361- style = { { backgroundColor : theme . colors . primary } }
351+ < Button
352+ variant = "default "
353+ className = "w-full"
362354 onClick = { generateRandomSpot }
363355 disabled = {
364356 ( shapeState . shapeType === "polygon" &&
@@ -367,14 +359,11 @@ export default function Sidebar({
367359 }
368360 >
369361 Generate Random Point
370- </ button >
362+ </ Button >
371363
372- < button
373- className = "border border-gray-500 hover:bg-gray-700 px-4 py-2 rounded w-full transition-colors"
374- onClick = { clearSelection }
375- >
364+ < Button variant = "outline" className = "w-full" onClick = { clearSelection } >
376365 Clear Selection
377- </ button >
366+ </ Button >
378367 </ div >
379368
380369 { randomLat !== null && randomLng !== null && (
0 commit comments