1- import React , { useRef } from "react" ;
1+ import React , { useCallback , useMemo , useRef } from "react" ;
22import { ConnectOprtator , FilterItem , FilterKey , FilterOperator } from "../types/FilterItem" ;
33import { Chip } from './Chip' ;
44import { Menu } from 'primereact/menu' ;
5+ import { gql , useQuery } from "@apollo/client" ;
6+ import { Tag } from "../types/Tag" ;
7+
8+ const GET_TAGS = gql `
9+ query GetTags {
10+ tag {
11+ nodes {
12+ id,
13+ name,
14+ description,
15+ note,
16+ tagType
17+ }
18+ }
19+ }
20+ ` ;
521
622export interface FilterProps {
723 item : FilterItem ;
@@ -10,6 +26,23 @@ export interface FilterProps {
1026}
1127
1228export const Filter : React . FC < FilterProps > = ( props ) => {
29+ const { data : raw , loading, error } = useQuery ( GET_TAGS ) ;
30+
31+ const data = useMemo ( ( ) => {
32+ if ( raw ?. tag ?. nodes ) {
33+ return raw . tag . nodes . filter ( ( item : Tag ) => item . description !== '測試' ) ;
34+ }
35+ return [ ] ;
36+ } , [ raw ] ) ;
37+
38+ const photographers = useMemo ( ( ) => {
39+ return data . filter ( ( item : Tag ) => item . tagType === 'photographer' )
40+ } , [ data ] ) ;
41+
42+ const categories = useMemo ( ( ) => {
43+ return data . filter ( ( item : Tag ) => item . tagType === 'category' )
44+ } , [ data ] ) ;
45+
1346 const onConnectChange = ( value : ConnectOprtator ) => {
1447 props . setPayloads ( ( prev ) => {
1548 const updated = prev . map ( ( item ) => {
@@ -59,6 +92,44 @@ export const Filter: React.FC<FilterProps> = (props) => {
5992 { label : '包含' , value : FilterOperator . IN , command : ( ) => onOperatorChange ( FilterOperator . IN ) } ,
6093 { label : '不包含' , value : FilterOperator . NOT_IN , command : ( ) => onOperatorChange ( FilterOperator . NOT_IN ) } ,
6194 ]
95+ const onValueChange = ( value : string ) => {
96+ props . setPayloads ( ( prev ) => {
97+ const updated = prev . map ( ( item ) => {
98+ if ( item . id === props . item . id ) {
99+ if ( item . values . includes ( value ) ) {
100+ const values = item . values . filter ( ( v ) => v !== value ) ;
101+ return { ...item , values } ;
102+ } else {
103+ const values = item . values . concat ( value ) ;
104+ return { ...item , values } ;
105+ }
106+ }
107+ return item ;
108+ } ) ;
109+ return updated ;
110+ } ) ;
111+ }
112+ const makeValueeOption = useCallback ( ( value : string , selecteds : string [ ] ) => {
113+ return { label : value , icon : selecteds . includes ( value ) ? 'pi pi-check' : '' , value, command : ( ) => onValueChange ( value ) } ;
114+ // eslint-disable-next-line react-hooks/exhaustive-deps
115+ } , [ ] ) ;
116+ const valueMenu = useRef < Menu | null > ( null ) ;
117+ const valueOptions = useMemo ( ( ) => {
118+ switch ( props . item . label ) {
119+ case FilterKey . REACTIONS :
120+ return [ '正向' , '負向' ] . map ( ( item ) => makeValueeOption ( item , props . item . values ) ) ;
121+ case FilterKey . AUTHORS :
122+ return photographers . map ( ( item : Tag ) => makeValueeOption ( item . name , props . item . values ) ) ;
123+ case FilterKey . CATEGORIES :
124+ return categories . map ( ( item : Tag ) => makeValueeOption ( item . name , props . item . values ) ) ;
125+ default :
126+ return [ ] ;
127+ }
128+ } , [ props . item , photographers , categories , makeValueeOption ] ) ;
129+
130+ if ( loading ) return < div > Loading...</ div > ;
131+ if ( error ) return < div > Error: { error . message } </ div > ;
132+
62133 return (
63134 < >
64135 { props . showConnect && (
@@ -80,7 +151,11 @@ export const Filter: React.FC<FilterProps> = (props) => {
80151 onClick = { ( event ) => operatorMenu ?. current ?. toggle ( event ) }
81152 />
82153 < Menu popup ref = { operatorMenu } model = { operatorOptions } />
83- < Chip label = { props . item . values . join ( ', ' ) } />
154+ < Chip
155+ label = { props . item . values . join ( ', ' ) }
156+ onClick = { ( event ) => valueMenu ?. current ?. toggle ( event ) }
157+ />
158+ < Menu popup ref = { valueMenu } model = { valueOptions } />
84159 < Chip label = 'x' onClick = { ( ) => {
85160 props . setPayloads ( ( prev ) => {
86161 const removed = prev . filter ( ( item ) => item . id !== props . item . id ) ;
0 commit comments