import { useCallback, useEffect, useState } from 'react' import { Label } from '../../../lib/networking/fragments/labelFragment' import { showErrorToast } from '../../../lib/toastHelpers' import { SpanBox, VStack } from '../../elements/LayoutPrimitives' import { ModalRoot, ModalOverlay, ModalContent, ModalTitleBar, } from '../../elements/ModalPrimitives' import { LabelsProvider, SetLabelsControl } from './SetLabelsControl' type SetLabelsModalProps = { provider: LabelsProvider onLabelsUpdated?: (labels: Label[]) => void onOpenChange: (open: boolean) => void save: (labels: Label[]) => Promise } export function SetLabelsModal(props: SetLabelsModalProps): JSX.Element { const [previousSelectedLabels, setPreviousSelectedLabels] = useState( props.provider.labels ?? [] ) const [selectedLabels, setSelectedLabels] = useState( props.provider.labels ?? [] ) const labelsEqual = (left: Label[], right: Label[]) => { if (left.length !== right.length) { return false } for (const label of left) { if (!right.find((r) => label.id == r.id)) { return false } } return true } const onOpenChange = useCallback( async (open: boolean) => { // Only make API call if the labels have been modified if (!labelsEqual(selectedLabels, previousSelectedLabels)) { const result = await props.save(selectedLabels) if (props.onLabelsUpdated) { props.onLabelsUpdated(selectedLabels) } if (!result) { showErrorToast('Error updating labels') } } props.onOpenChange(open) }, [props, selectedLabels, previousSelectedLabels, setSelectedLabels] ) useEffect(() => { if (labelsEqual(selectedLabels, previousSelectedLabels)) { return } props .save(selectedLabels) .then((result) => { setPreviousSelectedLabels(result ?? []) }) .catch((err) => { console.log('error saving labels: ', err) }) }, [selectedLabels, setPreviousSelectedLabels]) return ( { event.preventDefault() onOpenChange(false) }} > ) }