1- import { useQuery } from "@apollo/client" ;
21import { parseAsString , useQueryState } from "nuqs" ;
3- import { toast } from "react-toastify" ;
42
53import { QSP } from "@/config/qsp" ;
64
7- import { Button , type ButtonProps } from "@/shared/components/buttons/button-primitive" ;
85import ErrorScreen from "@/shared/components/errors/error-screen" ;
9- import { ALERT_TYPES , Alert } from "@/shared/components/ui/alert" ;
10- import { classNames } from "@/shared/utils/common" ;
116
12- import { DIFF_STATUS } from "@/entities/diff/node-diff/types" ;
13- import { DiffBadge } from "@/entities/diff/node-diff/utils" ;
7+ import type { GetDiffSummaryParams } from "@/entities/diff/domain/get-diff-summary" ;
8+ import { useGetDiffSummary } from "@/entities/diff/domain/get-diff-summary.query" ;
9+ import { DIFF_STATUS , type DiffStatus } from "@/entities/diff/node-diff/types" ;
10+ import { DiffSummarySkeleton } from "@/entities/proposed-changes/ui/diff-summary/diff-summary-skeleton" ;
1411import {
15- CloseBadgeAdded ,
16- CloseBadgeConflict ,
17- CloseBadgeRemoved ,
18- CloseBadgeUpdated ,
19- } from "@/entities/diff/ui/diff-badge" ;
20- import { getProposedChangesDiffSummary } from "@/entities/proposed-changes/api/getProposedChangesDiffSummary" ;
12+ DiffSummaryTag ,
13+ DiffSummaryTagGroup ,
14+ } from "@/entities/proposed-changes/ui/diff-summary/diff-summary-tag-group" ;
2115
22- export type DiffFilter = {
23- namespace ?: {
24- excludes ?: string [ ] ;
25- includes ?: string [ ] ;
26- } ;
27- status ?: {
28- excludes ?: string [ ] ;
29- includes ?: string [ ] ;
30- } ;
31- } ;
32-
33- type ProposedChangeDiffFilterProps = {
34- branch : string ;
35- filters ?: DiffFilter ;
36- } ;
37-
38- export const ProposedChangeDiffFilter = ( { branch, filters } : ProposedChangeDiffFilterProps ) => {
39- const [ qsp , setQsp ] = useQueryState ( QSP . STATUS , parseAsString . withOptions ( { shallow : false } ) ) ;
16+ type DiffFilterProps = GetDiffSummaryParams ;
4017
41- const { error, data = { } } = useQuery ( getProposedChangesDiffSummary , {
42- skip : ! branch ,
43- variables : { branch, filters } ,
44- context : {
45- processErrorMessage : ( message : string ) => {
46- // If the branch is not found, then do not display alert
47- if ( message . includes ( "not found" ) ) return ;
18+ export function DiffFilter ( { branch, filters } : DiffFilterProps ) {
19+ const [ statusFilterQSP , setQsp ] = useQueryState (
20+ QSP . STATUS ,
21+ parseAsString . withOptions ( { shallow : false } )
22+ ) ;
4823
49- toast ( < Alert type = { ALERT_TYPES . ERROR } message = { message } /> , {
50- toastId : "alert-error" ,
51- } ) ;
52- } ,
53- } ,
54- } ) ;
24+ const { error, data, isPending } = useGetDiffSummary ( { branch, filters } ) ;
5525
56- const handleFilter = ( value : string ) => {
57- setQsp ( value === qsp ? null : value ) ;
26+ const handleFilter = ( value : DiffStatus ) => {
27+ setQsp ( value === statusFilterQSP ? null : value ) ;
5828 } ;
5929
30+ if ( isPending ) {
31+ return < DiffSummarySkeleton /> ;
32+ }
33+
6034 if ( error ) {
6135 return (
6236 < ErrorScreen
@@ -67,69 +41,40 @@ export const ProposedChangeDiffFilter = ({ branch, filters }: ProposedChangeDiff
6741 ) ;
6842 }
6943
44+ if ( ! data ) {
45+ return null ;
46+ }
47+
7048 return (
71- < div className = "flex shrink-0 items-center gap-2" >
72- < FilterButton
73- status = { DIFF_STATUS . ADDED }
74- count = { data ?. DiffTreeSummary ?. num_added }
75- currentFilter = { qsp }
76- onFilter = { handleFilter }
49+ < DiffSummaryTagGroup selectionMode = "single" >
50+ < DiffSummaryTag
51+ variant = "added"
52+ count = { data . num_added }
53+ isMuted = { ! ! statusFilterQSP && statusFilterQSP !== DIFF_STATUS . ADDED }
54+ isClosable = { statusFilterQSP === DIFF_STATUS . ADDED }
55+ onPress = { ( ) => handleFilter ( DIFF_STATUS . ADDED ) }
7756 />
78- < FilterButton
79- status = { DIFF_STATUS . REMOVED }
80- count = { data ?. DiffTreeSummary ?. num_removed }
81- currentFilter = { qsp }
82- onFilter = { handleFilter }
57+ < DiffSummaryTag
58+ variant = "removed"
59+ count = { data . num_removed }
60+ isMuted = { ! ! statusFilterQSP && statusFilterQSP !== DIFF_STATUS . REMOVED }
61+ isClosable = { statusFilterQSP === DIFF_STATUS . REMOVED }
62+ onPress = { ( ) => handleFilter ( DIFF_STATUS . REMOVED ) }
8363 />
84- < FilterButton
85- status = { DIFF_STATUS . UPDATED }
86- count = { data ?. DiffTreeSummary ?. num_updated }
87- currentFilter = { qsp }
88- onFilter = { handleFilter }
64+ < DiffSummaryTag
65+ variant = "updated"
66+ count = { data . num_updated }
67+ isMuted = { ! ! statusFilterQSP && statusFilterQSP !== DIFF_STATUS . UPDATED }
68+ isClosable = { statusFilterQSP === DIFF_STATUS . UPDATED }
69+ onPress = { ( ) => handleFilter ( DIFF_STATUS . UPDATED ) }
8970 />
90- < FilterButton
91- status = { DIFF_STATUS . CONFLICT }
92- count = { data ?. DiffTreeSummary ?. num_conflicts }
93- currentFilter = { qsp }
94- onFilter = { handleFilter }
71+ < DiffSummaryTag
72+ variant = "conflicts"
73+ count = { data . num_conflicts }
74+ isMuted = { ! ! statusFilterQSP && statusFilterQSP !== DIFF_STATUS . CONFLICT }
75+ isClosable = { statusFilterQSP === DIFF_STATUS . CONFLICT }
76+ onPress = { ( ) => handleFilter ( DIFF_STATUS . CONFLICT ) }
9577 />
96- </ div >
78+ </ DiffSummaryTagGroup >
9779 ) ;
98- } ;
99-
100- interface FilterButtonProps extends ButtonProps {
101- status : string ;
102- count : number ;
103- currentFilter : string | null | undefined ;
104- onFilter : ( value : string ) => void ;
10580}
106-
107- const FilterButton = ( { status, count, currentFilter, onFilter, ...props } : FilterButtonProps ) => {
108- const isMuted = ! ! currentFilter && currentFilter !== status ;
109- const isDisabled = ! count && currentFilter !== status ;
110-
111- const CloseBadge =
112- status === DIFF_STATUS . ADDED
113- ? CloseBadgeAdded
114- : status === DIFF_STATUS . REMOVED
115- ? CloseBadgeRemoved
116- : status === DIFF_STATUS . UPDATED
117- ? CloseBadgeUpdated
118- : status === DIFF_STATUS . CONFLICT
119- ? CloseBadgeConflict
120- : null ;
121-
122- return (
123- < Button
124- { ...props }
125- variant = "ghost"
126- className = { classNames ( "relative h-auto rounded-full p-0" , isMuted && "opacity-60" ) }
127- onClick = { ( ) => onFilter ( status ) }
128- disabled = { isDisabled }
129- data-testid = { `diff-filters-button-${ status . toLowerCase ( ) } ` }
130- >
131- < DiffBadge status = { status } > { count } </ DiffBadge >
132- { currentFilter === status && CloseBadge && < CloseBadge /> }
133- </ Button >
134- ) ;
135- } ;
0 commit comments