11// @ts -nocheck
22import React , { useState , useEffect } from 'react' ;
33import { Button } from '@strapi/design-system' ;
4- import { Filter } from '@strapi/icons' ;
4+ import { Filter , Check } from '@strapi/icons' ;
55import { useNavigate , useLocation } from 'react-router-dom' ;
66import { useFetchClient } from '@strapi/strapi/admin' ;
77import SimpleAdvancedFilterModal from './SimpleAdvancedFilterModal' ;
@@ -12,7 +12,7 @@ const AdvancedFilterButton: React.FC = () => {
1212 const location = useLocation ( ) ;
1313 const { get } = useFetchClient ( ) ;
1414 const [ availableFields , setAvailableFields ] = useState < Array < { name : string ; type : string } > > ( [ ] ) ;
15- const [ availableRelations , setAvailableRelations ] = useState < Array < { name : string } > > ( [ ] ) ;
15+ const [ availableRelations , setAvailableRelations ] = useState < Array < { name : string ; target : string } > > ( [ ] ) ;
1616 const [ hasActiveFilters , setHasActiveFilters ] = useState ( false ) ;
1717
1818 // Check if URL has filters
@@ -34,7 +34,9 @@ const AdvancedFilterButton: React.FC = () => {
3434 return match ? match [ 1 ] : null ;
3535 } ;
3636
37- // Fetch schema for current content type
37+ /**
38+ * Fetches schema for current content type and extracts fields + relations
39+ */
3840 useEffect ( ( ) => {
3941 const fetchSchema = async ( ) => {
4042 const uid = extractContentTypeUid ( ) ;
@@ -46,106 +48,85 @@ const AdvancedFilterButton: React.FC = () => {
4648 try {
4749 console . log ( '[AdvancedFilter] Fetching schema for:' , uid ) ;
4850
49- // Try to get the actual content type schema
50- let schemaData ;
51+ // Step 1: Get the REAL schema from content- type-builder (has correct attribute types)
52+ let realAttributes : Record < string , any > = { } ;
5153 try {
52- const response = await get ( `/content-manager/content-types/${ uid } /configuration` ) ;
53- schemaData = response . data ;
54- console . log ( '[AdvancedFilter] Configuration response:' , schemaData ) ;
54+ const schemaResponse = await get ( `/content-type-builder/content-types/${ uid } ` ) ;
55+ const schemaInfo = schemaResponse . data ?. data ?. schema || schemaResponse . data ?. schema || { } ;
56+ realAttributes = schemaInfo . attributes || { } ;
57+ console . log ( '[AdvancedFilter] Real schema attributes:' , realAttributes ) ;
5558 } catch ( e ) {
56- console . log ( '[AdvancedFilter] Configuration endpoint failed, trying direct strapi schema' ) ;
59+ console . log ( '[AdvancedFilter] Content-type-builder endpoint failed:' , e ) ;
5760 }
5861
59- // Extract attributes from the layout/metadatas
60- // The structure is: response.data.data.contentType
61- const contentTypeData = schemaData ?. data ?. contentType || schemaData ?. contentType || { } ;
62- const metadatas = contentTypeData . metadatas || { } ;
63- const layouts = contentTypeData . layouts || { } ;
64-
65- console . log ( '[AdvancedFilter] Metadatas:' , metadatas ) ;
66- console . log ( '[AdvancedFilter] Layouts:' , layouts ) ;
67-
68- // Get fields from edit layout
69- let allFieldNames = new Set < string > ( ) ;
70-
71- // From metadatas (most reliable)
72- Object . keys ( metadatas ) . forEach ( key => allFieldNames . add ( key ) ) ;
73-
74- // From edit layout
75- if ( layouts . edit ) {
76- layouts . edit . forEach ( ( row : any ) => {
77- row . forEach ( ( field : any ) => {
78- if ( field . name ) allFieldNames . add ( field . name ) ;
79- } ) ;
80- } ) ;
62+ // Step 2: Also get configuration for field metadata (labels, etc.)
63+ let metadatas : Record < string , any > = { } ;
64+ try {
65+ const configResponse = await get ( `/content-manager/content-types/${ uid } /configuration` ) ;
66+ const contentTypeData = configResponse . data ?. data ?. contentType || configResponse . data ?. contentType || { } ;
67+ metadatas = contentTypeData . metadatas || { } ;
68+ console . log ( '[AdvancedFilter] Configuration metadatas:' , metadatas ) ;
69+ } catch ( e ) {
70+ console . log ( '[AdvancedFilter] Configuration endpoint failed:' , e ) ;
8171 }
8272
83- // From list layout
84- if ( layouts . list ) {
85- layouts . list . forEach ( ( fieldName : string ) => allFieldNames . add ( fieldName ) ) ;
86- }
73+ // Step 3: Extract fields and relations from REAL attributes
74+ const fields : Array < { name : string ; type : string } > = [ ] ;
75+ const relations : Array < { name : string ; target : string } > = [ ] ;
76+ const fieldNames = new Set < string > ( ) ;
8777
88- const attributes = { } ;
89- allFieldNames . forEach ( name => {
90- const metadata = metadatas [ name ] ;
91- attributes [ name ] = {
92- type : metadata ?. edit ?. type || 'string' ,
93- } ;
78+ // Process real attributes (this has correct types!)
79+ Object . keys ( realAttributes ) . forEach ( ( key ) => {
80+ const attr = realAttributes [ key ] ;
81+ const attrType = attr . type ;
82+
83+ // Skip internal fields
84+ if ( [ 'createdBy' , 'updatedBy' , 'localizations' , 'locale' ] . includes ( key ) ) {
85+ return ;
86+ }
87+
88+ // Check if it's a relation
89+ if ( attrType === 'relation' ) {
90+ relations . push ( { name : key , target : attr . target } ) ;
91+ console . log ( '[AdvancedFilter] Found relation:' , key , '-> target:' , attr . target ) ;
92+ } else if ( attrType === 'component' || attrType === 'dynamiczone' ) {
93+ // Skip components and dynamic zones for filtering
94+ console . log ( '[AdvancedFilter] Skipping component/dynamiczone:' , key ) ;
95+ } else if ( attrType === 'media' ) {
96+ // Skip media for now (complex filtering)
97+ console . log ( '[AdvancedFilter] Skipping media:' , key ) ;
98+ } else if ( ! fieldNames . has ( key ) ) {
99+ // Regular field
100+ fieldNames . add ( key ) ;
101+ fields . push ( {
102+ name : key ,
103+ type : attrType || 'string'
104+ } ) ;
105+ }
94106 } ) ;
107+
108+ // Add default fields if not already present
109+ [ 'id' , 'documentId' , 'createdAt' , 'updatedAt' ] . forEach ( defaultField => {
110+ if ( ! fieldNames . has ( defaultField ) ) {
111+ let type = 'string' ;
112+ if ( defaultField === 'id' ) type = 'integer' ;
113+ if ( defaultField === 'createdAt' || defaultField === 'updatedAt' ) type = 'datetime' ;
114+ fields . unshift ( { name : defaultField , type } ) ;
115+ }
116+ } ) ;
117+
118+ setAvailableFields ( fields ) ;
119+ setAvailableRelations ( relations ) ;
95120
96- console . log ( '[AdvancedFilter] Reconstructed attributes:' , attributes ) ;
121+ console . log ( '[AdvancedFilter] Final fields:' , fields ) ;
122+ console . log ( '[AdvancedFilter] Final relations:' , relations ) ;
97123
98- if ( attributes && Object . keys ( attributes ) . length > 0 ) {
99- // Extract filterable fields
100- const fields : Array < { name : string ; type : string } > = [ ] ;
101- const relations : Array < { name : string } > = [ ] ;
102- const fieldNames = new Set < string > ( ) ;
103-
104- Object . keys ( attributes ) . forEach ( ( key ) => {
105- const attr = attributes [ key ] ;
106-
107- // Check if it's a relation
108- if ( attr . type === 'relation' ) {
109- relations . push ( { name : key } ) ;
110- } else if ( ! fieldNames . has ( key ) ) {
111- // Regular field - add only once
112- fieldNames . add ( key ) ;
113- fields . push ( {
114- name : key ,
115- type : attr . type || 'string'
116- } ) ;
117- }
118- } ) ;
119-
120- // Add default fields if not already present
121- [ 'id' , 'createdAt' , 'updatedAt' ] . forEach ( defaultField => {
122- if ( ! fieldNames . has ( defaultField ) ) {
123- fields . unshift ( {
124- name : defaultField ,
125- type : defaultField === 'id' ? 'integer' : 'datetime'
126- } ) ;
127- }
128- } ) ;
129-
130- setAvailableFields ( fields ) ;
131- setAvailableRelations ( relations ) ;
132-
133- console . log ( '[AdvancedFilter] Extracted fields:' , fields ) ;
134- console . log ( '[AdvancedFilter] Extracted relations:' , relations ) ;
135- } else {
136- console . warn ( '[AdvancedFilter] No attributes found in schema response' ) ;
137- // Use fallback
138- setAvailableFields ( [
139- { name : 'id' , type : 'integer' } ,
140- { name : 'createdAt' , type : 'datetime' } ,
141- { name : 'updatedAt' , type : 'datetime' } ,
142- ] ) ;
143- }
144124 } catch ( error ) {
145125 console . error ( '[AdvancedFilter] Error fetching schema:' , error ) ;
146126 // Fallback to basic fields
147127 setAvailableFields ( [
148128 { name : 'id' , type : 'integer' } ,
129+ { name : 'documentId' , type : 'string' } ,
149130 { name : 'createdAt' , type : 'datetime' } ,
150131 { name : 'updatedAt' , type : 'datetime' } ,
151132 ] ) ;
@@ -178,8 +159,19 @@ const AdvancedFilterButton: React.FC = () => {
178159 cleanParams . set ( key , value ) ;
179160 } ) ;
180161
181- // Navigate with new query
182- navigate ( `${ currentPath } ?${ cleanParams . toString ( ) } ` ) ;
162+ // Reset to page 1 when applying filters
163+ cleanParams . set ( 'page' , '1' ) ;
164+
165+ const finalUrl = `${ currentPath } ?${ cleanParams . toString ( ) } ` ;
166+ console . log ( '[AdvancedFilter] Final URL:' , finalUrl ) ;
167+
168+ // Navigate first, then reload to ensure Strapi CM picks up the filters
169+ navigate ( finalUrl ) ;
170+
171+ // Small delay then reload to ensure the URL is updated before reload
172+ setTimeout ( ( ) => {
173+ window . location . reload ( ) ;
174+ } , 100 ) ;
183175 } ;
184176
185177 const handleClearFilters = ( ) => {
@@ -194,7 +186,13 @@ const AdvancedFilterButton: React.FC = () => {
194186 }
195187 } ) ;
196188
197- navigate ( `${ currentPath } ${ cleanParams . toString ( ) ? '?' + cleanParams . toString ( ) : '' } ` ) ;
189+ const finalUrl = `${ currentPath } ${ cleanParams . toString ( ) ? '?' + cleanParams . toString ( ) : '' } ` ;
190+ navigate ( finalUrl ) ;
191+
192+ // Small delay then reload
193+ setTimeout ( ( ) => {
194+ window . location . reload ( ) ;
195+ } , 100 ) ;
198196 } ;
199197
200198 // Extract current filters from URL
@@ -213,7 +211,7 @@ const AdvancedFilterButton: React.FC = () => {
213211 onClick = { ( ) => setShowModal ( true ) }
214212 size = "S"
215213 >
216- { hasActiveFilters ? '🔍 Filters Active' : 'Advanced Filters' }
214+ { hasActiveFilters ? 'Filters Active' : 'Advanced Filters' }
217215 </ Button >
218216
219217 { hasActiveFilters && (
0 commit comments