1+ import React , { useState } from "react" ;
2+ import { Toaster , toast } from "react-hot-toast" ;
3+ import StackVisualizer from "../../components/dataStructure/stack.jsx" ;
4+ import { stackOp } from "../../algorithms/dataStructure/stack.js" ;
5+
6+ export default function StackPage ( ) {
7+ const [ array , setArray ] = useState ( [ ] ) ;
8+ const [ input , setInput ] = useState ( "" ) ;
9+ const [ highlight , setHighlight ] = useState ( null ) ;
10+ const [ isRunning , setIsRunning ] = useState ( false ) ;
11+
12+ const delay = ( ms ) => new Promise ( ( r ) => setTimeout ( r , ms ) ) ;
13+
14+ const runAction = async ( action ) => {
15+ if ( isRunning ) return ;
16+ setIsRunning ( true ) ;
17+
18+ const gen = stackOp ( array , action ) ;
19+ for ( let step of gen ) {
20+ setHighlight ( step ) ;
21+ if ( step . array ) setArray ( [ ...step . array ] ) ;
22+ await delay ( 400 ) ;
23+ }
24+
25+ await delay ( 150 ) ;
26+ setHighlight ( null ) ;
27+ setIsRunning ( false ) ;
28+ } ;
29+
30+ const handlePush = async ( ) => {
31+ if ( ! input . trim ( ) ) {
32+ toast . error ( "Enter a value to push" ) ;
33+ return ;
34+ }
35+ const parsed = input . trim ( ) ;
36+ const value = parsed . length && ! Number . isNaN ( Number ( parsed ) ) ? Number ( parsed ) : parsed ;
37+ await runAction ( { type : "push" , value } ) ;
38+ setInput ( "" ) ;
39+ } ;
40+
41+ const handlePop = async ( ) => {
42+ await runAction ( { type : "pop" } ) ;
43+ } ;
44+
45+ const handlePeek = async ( ) => {
46+ await runAction ( { type : "peek" } ) ;
47+ } ;
48+
49+ const handleClear = async ( ) => {
50+ await runAction ( { type : "clear" } ) ;
51+ } ;
52+
53+ const handleReset = ( ) => {
54+ setArray ( [ ] ) ;
55+ setInput ( "" ) ;
56+ setHighlight ( null ) ;
57+ } ;
58+
59+ const sampleLoad = ( ) => {
60+ setArray ( [ "X" , "Y" , "Z" ] ) ;
61+ setHighlight ( { type : "done" , array : [ "X" , "Y" , "Z" ] } ) ;
62+ } ;
63+
64+ return (
65+ < div className = "min-h-screen bg-black text-gray-200 flex flex-col items-center p-4 sm:p-6" >
66+ < Toaster position = "top-center" />
67+ < h1 className = "text-3xl sm:text-4xl font-extrabold mb-6 sm:mb-8 text-indigo-400 drop-shadow-lg text-center" >
68+ Stack Visualizer
69+ </ h1 >
70+
71+ < div className = "w-full max-w-2xl" >
72+ < div className = "bg-gray-900/40 rounded-lg p-4 sm:p-6 shadow-md" >
73+ < div className = "flex flex-col sm:flex-row sm:items-center gap-3 sm:gap-4" >
74+ < input
75+ value = { input }
76+ onChange = { ( e ) => setInput ( e . target . value ) }
77+ placeholder = "Value to push (number or string)"
78+ className = "flex-1 w-full sm:w-auto border-2 border-indigo-500 bg-gray-900 text-indigo-200 rounded-lg p-3 text-center outline-none shadow-inner"
79+ />
80+ < button
81+ onClick = { handlePush }
82+ disabled = { isRunning }
83+ className = { `w-full sm:w-auto ${
84+ isRunning ? "bg-indigo-700 cursor-not-allowed" : "bg-indigo-600 hover:bg-indigo-500"
85+ } px-4 py-2 rounded text-white font-semibold`}
86+ >
87+ Push
88+ </ button >
89+ </ div >
90+
91+ < div className = "mt-4 grid grid-cols-1 sm:grid-cols-5 gap-3" >
92+ < button
93+ onClick = { handlePop }
94+ disabled = { isRunning }
95+ className = { `col-span-1 w-full ${
96+ isRunning ? "bg-gray-700 cursor-not-allowed" : "bg-rose-600 hover:bg-rose-500"
97+ } px-4 py-2 rounded text-white font-semibold`}
98+ >
99+ Pop
100+ </ button >
101+
102+ < button
103+ onClick = { handlePeek }
104+ disabled = { isRunning }
105+ className = { `col-span-1 w-full ${
106+ isRunning ? "bg-gray-700 cursor-not-allowed" : "bg-yellow-500 hover:bg-yellow-400"
107+ } px-4 py-2 rounded text-white font-semibold`}
108+ >
109+ Peek
110+ </ button >
111+
112+ < button
113+ onClick = { handleClear }
114+ disabled = { isRunning }
115+ className = { `col-span-1 w-full ${
116+ isRunning ? "bg-gray-700 cursor-not-allowed" : "bg-gray-700 hover:bg-gray-600"
117+ } px-4 py-2 rounded text-white font-semibold`}
118+ >
119+ Clear
120+ </ button >
121+
122+ < button
123+ onClick = { handleReset }
124+ className = "col-span-1 w-full bg-gray-600 hover:bg-gray-500 px-4 py-2 rounded text-white font-semibold"
125+ >
126+ Reset
127+ </ button >
128+
129+ < button
130+ onClick = { sampleLoad }
131+ className = "col-span-1 w-full bg-indigo-500 hover:bg-indigo-400 px-4 py-2 rounded text-white font-semibold"
132+ >
133+ Load Demo
134+ </ button >
135+ </ div >
136+ </ div >
137+
138+ < div className = "mt-6" >
139+ < StackVisualizer array = { array } highlight = { highlight } />
140+ </ div >
141+
142+ < div className = "mt-4 text-sm text-slate-400 text-center" >
143+ Tip: top of stack is shown at the top (index 0). Push adds to top; Pop removes the top (LIFO).
144+ </ div >
145+ </ div >
146+ </ div >
147+ ) ;
148+ }
0 commit comments