@@ -11,8 +11,13 @@ import {
1111 MenuItem ,
1212} from "@mui/material" ;
1313import { useHomepage } from "Contexts/HomepageContext" ;
14- import { useState } from "react" ;
14+ import { useState , useEffect } from "react" ;
1515import { useAcademyTheme } from "Contexts/AcademyThemeContext" ;
16+ import { Filters } from "src/types/exercises" ;
17+
18+ // SessionStorage keys
19+ const FILTER_STORAGE_KEY = "ra_home_filters_v1" ;
20+ const SEARCH_STORAGE_KEY = "ra_home_search_v1" ;
1621
1722// Estilos
1823const Search = styled ( "div" ) ( ( { roundness } : { roundness : number } ) => ( {
@@ -85,13 +90,67 @@ const StyledMenu = styled(Menu)(
8590 } )
8691) ;
8792
88- // Componente FilterMenu
93+ // Filter persistence structure
94+ type FilterState = {
95+ tags : boolean ;
96+ description : boolean ;
97+ status : boolean ;
98+ } ;
99+
100+ const DEFAULT_FILTER_STATE : FilterState = {
101+ tags : true ,
102+ description : false ,
103+ status : false ,
104+ } ;
105+
106+ const filtersFromState = ( state : FilterState ) : Filters [ ] => {
107+ const list : Filters [ ] = [ "name" ] ; // name is always active
108+ if ( state . tags ) list . push ( "tags" ) ;
109+ if ( state . description ) list . push ( "description" ) ;
110+ if ( state . status ) list . push ( "status" ) ;
111+ return list ;
112+ } ;
113+
89114const FilterMenu = ( ) => {
90- const { appendFilterItem } = useHomepage ( ) ;
115+ const { appendFilterItem, setFilterItemsList } = useHomepage ( ) ;
91116 const theme = useAcademyTheme ( ) ;
92117 const [ anchorEl , setAnchorEl ] = useState < null | HTMLElement > ( null ) ;
93118 const open : boolean = Boolean ( anchorEl ) ;
94119
120+ const [ filterState , setFilterState ] =
121+ useState < FilterState > ( DEFAULT_FILTER_STATE ) ;
122+
123+ // Restore session filter state
124+ useEffect ( ( ) => {
125+ if ( typeof window === "undefined" ) return ;
126+
127+ try {
128+ const raw = window . sessionStorage . getItem ( FILTER_STORAGE_KEY ) ;
129+ if ( ! raw ) return ;
130+
131+ const parsed = JSON . parse ( raw ) as Partial < FilterState > ;
132+ const persisted : FilterState = {
133+ tags :
134+ typeof parsed . tags === "boolean"
135+ ? parsed . tags
136+ : DEFAULT_FILTER_STATE . tags ,
137+ description :
138+ typeof parsed . description === "boolean"
139+ ? parsed . description
140+ : DEFAULT_FILTER_STATE . description ,
141+ status :
142+ typeof parsed . status === "boolean"
143+ ? parsed . status
144+ : DEFAULT_FILTER_STATE . status ,
145+ } ;
146+
147+ setFilterState ( persisted ) ;
148+ setFilterItemsList ( filtersFromState ( persisted ) ) ;
149+ } catch ( err ) {
150+ console . error ( "Failed to restore filter state" , err ) ;
151+ }
152+ } , [ setFilterItemsList ] ) ;
153+
95154 const handleClick = ( event : React . MouseEvent < HTMLButtonElement > ) => {
96155 setAnchorEl ( event . currentTarget ) ;
97156 } ;
@@ -100,9 +159,31 @@ const FilterMenu = () => {
100159 setAnchorEl ( null ) ;
101160 } ;
102161
103- const handleFilterList = ( e : any ) => {
104- const item = e . target . name ;
105- appendFilterItem ( item ) ;
162+ // Toggle and persist filter values
163+ const handleFilterCheckboxChange = (
164+ e : React . ChangeEvent < HTMLInputElement >
165+ ) => {
166+ const name = e . target . name as keyof FilterState ;
167+
168+ setFilterState ( ( prev ) => {
169+ const updated : FilterState = {
170+ ...prev ,
171+ [ name ] : ! prev [ name ] ,
172+ } ;
173+
174+ try {
175+ window . sessionStorage . setItem (
176+ FILTER_STORAGE_KEY ,
177+ JSON . stringify ( updated )
178+ ) ;
179+ } catch ( err ) {
180+ console . error ( "Failed to save filter state" , err ) ;
181+ }
182+
183+ return updated ;
184+ } ) ;
185+
186+ appendFilterItem ( name as Filters ) ;
106187 } ;
107188
108189 return (
@@ -127,44 +208,77 @@ const FilterMenu = () => {
127208 checkboxColor = { theme . palette . text ! }
128209 roundness = { theme . roundness ! }
129210 >
211+ { /* Name always active and not persisted */ }
130212 < MenuItem >
131213 < Checkbox defaultChecked disabled size = "small" name = "name" />
132214 Name
133215 </ MenuItem >
134216 < MenuItem >
135217 < Checkbox
136- defaultChecked
137218 size = "small"
138- onClick = { handleFilterList }
139219 name = "tags"
220+ checked = { filterState . tags }
221+ onChange = { handleFilterCheckboxChange }
140222 />
141223 Tags
142224 </ MenuItem >
143225 < MenuItem >
144226 < Checkbox
145227 size = "small"
146- onClick = { handleFilterList }
147228 name = "description"
229+ checked = { filterState . description }
230+ onChange = { handleFilterCheckboxChange }
148231 />
149232 Description
150233 </ MenuItem >
151234 < MenuItem >
152- < Checkbox size = "small" onClick = { handleFilterList } name = "status" />
235+ < Checkbox
236+ size = "small"
237+ name = "status"
238+ checked = { filterState . status }
239+ onChange = { handleFilterCheckboxChange }
240+ />
153241 Status
154242 </ MenuItem >
155243 </ StyledMenu >
156244 </ >
157245 ) ;
158246} ;
159247
160- // Componente principal SearchBar
161248const SearchBar = ( ) => {
162249 const { setSearchBarText } = useHomepage ( ) ;
163250 const theme = useAcademyTheme ( ) ;
164251
252+ const [ searchValue , setSearchValue ] = useState < string > ( "" ) ;
253+
254+ // Restore session search text
255+ useEffect ( ( ) => {
256+ if ( typeof window === "undefined" ) return ;
257+
258+ try {
259+ const saved = window . sessionStorage . getItem ( SEARCH_STORAGE_KEY ) ;
260+ if ( saved ) {
261+ setSearchValue ( saved ) ;
262+ setSearchBarText ( saved . toLowerCase ( ) ) ;
263+ }
264+ } catch ( err ) {
265+ console . error ( "Failed to restore search text" , err ) ;
266+ }
267+ } , [ setSearchBarText ] ) ;
268+
269+ // Update sessionStorage + context
165270 const inputHandler = ( e : React . ChangeEvent < HTMLInputElement > ) => {
166- const lowerCase = e . target . value . toLowerCase ( ) ;
271+ const value = e . target . value ;
272+ setSearchValue ( value ) ;
273+
274+ const lowerCase = value . toLowerCase ( ) ;
167275 setSearchBarText ( lowerCase ) ;
276+
277+ try {
278+ window . sessionStorage . setItem ( SEARCH_STORAGE_KEY , value ) ;
279+ } catch ( err ) {
280+ console . error ( "Failed to save search text" , err ) ;
281+ }
168282 } ;
169283
170284 return (
@@ -181,6 +295,7 @@ const SearchBar = () => {
181295 </ SearchIconWrapper >
182296 < StyledInputBase
183297 placeholder = "Search…"
298+ value = { searchValue }
184299 onChange = { inputHandler }
185300 textColor = { theme . palette . text ! }
186301 inputProps = { { "aria-label" : "search" } }
@@ -192,3 +307,4 @@ const SearchBar = () => {
192307} ;
193308
194309export default SearchBar ;
310+
0 commit comments