@@ -4,15 +4,13 @@ import {Button} from './components/ui/button';
44import Upload from "@/components/Upload.tsx" ;
55import GraphvizParent from "@/components/GraphvizParent.tsx" ;
66import FilterComponent from './components/FilterComponent.tsx' ;
7- import Slider from '@/components/slider.tsx' ;
87import SequenceSelector from "@/components/SequenceSelector.tsx" ;
98import { Context , SequenceCount } from "@/Context.tsx" ;
109import {
1110 Popover ,
1211 PopoverContent ,
1312 PopoverTrigger ,
1413} from "@/components/ui/popover"
15- import { Input } from "@/components/ui/input"
1614
1715import Loading from './components/Loading.tsx' ;
1816import Switch from "./components/switch.tsx" ;
@@ -69,8 +67,8 @@ const getFileTypeIcon = (filename: string): string => {
6967function App ( ) {
7068 // State to hold the uploaded CSV data as a string
7169 // const [csvData, setCsvData] = useState<string>('');
72- // State to manage the filter value for filtering the graph data
73- const [ filter , setFilter ] = useState < string > ( '' ) ;
70+ // State to manage the filter values for filtering the graph data (can show multiple)
71+ const [ filters , setFilters ] = useState < string [ ] > ( [ ] ) ;
7472 // State to toggle whether self-loops (transitions back to the same node) should be included
7573 const [ selfLoops , setSelfLoops ] = useState < boolean > ( true ) ;
7674 const [ errorMode , setErrorMode ] = useState < boolean > ( false ) ;
@@ -178,16 +176,6 @@ function App() {
178176 */
179177 const handleToggleUniqueStudentMode = ( ) => setUniqueStudentMode ( ! uniqueStudentMode ) ;
180178
181-
182- /**
183- * Updates the minimum visits for edges in the graph when the slider is moved.
184- *
185- * @param {number } value - The new value for minimum visits.
186- */
187- const handleSlider = ( value : number ) => {
188- setMinVisitsPercentage ( value ) ;
189- } ;
190-
191179 /**
192180 * Updates the `csvData` state with the uploaded CSV data when the file is processed.
193181 *
@@ -202,22 +190,9 @@ function App() {
202190 }
203191 } ;
204192
205- // Calculate actual min visits from percentage
193+ // Calculate actual min visits from percentage (still needed for GraphvizParent)
206194 const minVisits = Math . round ( ( minVisitsPercentage / 100 ) * maxEdgeCount ) ;
207195
208- /**
209- * Updates the minimum visits percentage when the input value changes.
210- *
211- * @param {string } value - The new value from the input.
212- */
213- const handleInputChange = ( value : string ) => {
214- const numValue = parseInt ( value ) ;
215- if ( ! isNaN ( numValue ) ) {
216- const percentage = Math . min ( 100 , Math . max ( 0 , ( numValue / maxEdgeCount ) * 100 ) ) ;
217- setMinVisitsPercentage ( percentage ) ;
218- }
219- } ;
220-
221196 /**
222197 * Updates the loading state when the file upload or processing begins or ends.
223198 *
@@ -230,17 +205,6 @@ function App() {
230205 < header className = "bg-white shadow-sm border-b border-gray-200 px-4 py-3 mb-4" >
231206 < div className = "max-w-7xl mx-auto flex items-center justify-between" >
232207 < h1 className = "text-2xl text-gray-900" > Path Analysis Tool</ h1 >
233- < div className = "flex items-center space-x-4" >
234- < Button
235- variant = "destructive"
236- onClick = { ( ) => {
237- resetData ( ) ;
238- setFileInfo ( null ) ;
239- } }
240- >
241- Reset
242- </ Button >
243- </ div >
244208 </ div >
245209 </ header >
246210 { ! showControls && < Upload onDataProcessed = { handleDataProcessed } /> }
@@ -260,8 +224,8 @@ function App() {
260224 showControls && (
261225 < div className = "p-5 m-2 flex flex-col gap-3" >
262226
263- < div className = "selected-sequence-bar flex justify-between bg-gray-200 p-4 mb-4" >
264- < h2 className = "text-lg font-semibold" > Selected Sequence:</ h2 >
227+ < div className = "selected-sequence-bar flex items-center bg-gray-200 p-4 mb-4" >
228+ < h2 className = "text-lg font-semibold whitespace-nowrap " > Selected Sequence:</ h2 >
265229 { selectedSequence && (
266230 < h2 className = "flex-1 text-sm break-words whitespace-normal ml-2" >
267231 { selectedSequence . toString ( ) . split ( ',' ) . join ( ' → ' ) }
@@ -290,16 +254,17 @@ function App() {
290254 </ div >
291255 </ div >
292256 ) }
293- { /* Properties Button */ }
294- < Popover >
295- < PopoverTrigger
296- className = "w-fit bg-slate-500 p-3 rounded-lg text-white" > Properties</ PopoverTrigger >
297- < PopoverContent className = "w-96 bg-white rounded-lg shadow-lg p-6 border border-gray-200 mx-10" >
257+ { /* Properties and Reset Buttons */ }
258+ < div className = "flex items-center gap-2" >
259+ < Popover >
260+ < PopoverTrigger
261+ className = "w-fit bg-slate-500 p-3 rounded-lg text-white" > Properties</ PopoverTrigger >
262+ < PopoverContent className = "w-96 bg-white rounded-lg shadow-lg p-6 border border-gray-200 mx-10" >
298263 < div className = "flex flex-col space-y-6" >
299264 { /* Filter Section */ }
300265 < div className = "space-y-2" >
301266 < h3 className = "text-lg font-semibold text-gray-900" > Filters</ h3 >
302- < FilterComponent onFilterChange = { setFilter } currentFilter = { filter } />
267+ < FilterComponent onFilterChange = { setFilters } currentFilters = { filters } />
303268 </ div >
304269
305270 { /* Sequence Section */ }
@@ -340,62 +305,22 @@ function App() {
340305 </ label >
341306 < Switch isOn = { uniqueStudentMode } handleToggle = { handleToggleUniqueStudentMode } />
342307 </ div >
343-
344-
345- < div className = "space-y-2" >
346- < label className = "text-sm font-medium text-gray-700" >
347- { uniqueStudentMode ? 'Minimum Students' : 'Minimum Visits' }
348- </ label >
349- < div className = "space-y-4" >
350- < div >
351- < div className = "flex justify-between mb-1" >
352- { /* <span className="text-sm text-gray-500">Percentage</span>
353- <span className="text-sm text-gray-500">{minVisitsPercentage}%</span> */ }
354- </ div >
355- < div className = "flex items-center gap-2" >
356- < Slider
357- step = { 1 }
358- min = { 0 }
359- max = { maxMinEdgeCount > 0 ? Math . round ( ( maxMinEdgeCount / maxEdgeCount ) * 100 ) : 100 }
360- value = { minVisitsPercentage }
361- onChange = { handleSlider }
362- maxEdgeCount = { maxEdgeCount }
363- uniqueStudentMode = { uniqueStudentMode }
364- />
365- < span className = "text-sm text-gray-500" > %</ span >
366- </ div >
367- </ div >
368- < div >
369- < div className = "flex justify-between mb-1" >
370- < span className = "text-sm text-gray-500" >
371- { uniqueStudentMode ? 'Students' : 'Visits' }
372- </ span >
373- </ div >
374- < Input
375- type = "number"
376- value = { minVisits }
377- onChange = { ( e ) => handleInputChange ( e . target . value ) }
378- className = "w-full"
379- min = { 0 }
380- max = { maxEdgeCount }
381- />
382- </ div >
383- </ div >
384- < div className = "space-y-1" >
385- < p className = "text-xs text-gray-500" >
386- Controls the "All Students, All Paths" graph visibility
387- </ p >
388- < p className = "text-xs text-gray-500" >
389- Maximum threshold before any node becomes
390- disconnected: { maxMinEdgeCount } { uniqueStudentMode ? 'students' : 'visits' }
391- </ p >
392- </ div >
393- </ div >
394308 </ div >
395309 </ div >
396310 </ PopoverContent >
397311 </ Popover >
398312
313+ < Button
314+ variant = "destructive"
315+ onClick = { ( ) => {
316+ resetData ( ) ;
317+ setFileInfo ( null ) ;
318+ } }
319+ className = "p-3"
320+ >
321+ Reset
322+ </ Button >
323+ </ div >
399324
400325 { /* Graph and Data Display */ }
401326 { ! loading && csvData && (
@@ -405,13 +330,14 @@ function App() {
405330 { /* GraphvizParent component generates and displays the graph based on the CSV data */ }
406331 < GraphvizParent
407332 csvData = { csvData }
408- filter = { filter }
333+ filters = { filters }
409334 selfLoops = { uniqueStudentMode ? false : selfLoops }
410335 minVisits = { minVisits }
411336 onMaxEdgeCountChange = { setMaxEdgeCount }
412337 onMaxMinEdgeCountChange = { setMaxMinEdgeCount }
413338 errorMode = { errorMode }
414339 uniqueStudentMode = { uniqueStudentMode }
340+ problemName = { fileInfo ?. filename . replace ( / \. ( c s v | C S V ) $ / , '' ) || 'unknown' }
415341 />
416342 </ div >
417343 </ div >
0 commit comments