Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 48 additions & 3 deletions src/components/layout/containers/AttributeContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Skeleton,
Stack,
Typography,
Button,
} from '@mui/material'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import { ButtonNaked } from '@pagopa/mui-italia'
Expand All @@ -21,7 +22,9 @@ import { InformationContainer } from '@pagopa/interop-fe-commons'
import { useTranslation } from 'react-i18next'
import { useQuery, useQueryClient } from '@tanstack/react-query'

type AttributeContainerProps<TAttribute extends { id: string; name: string }> = {
type AttributeContainerProps<
TAttribute extends { id: string; name: string; dailyCallsPerConsumer?: number },
> = {
attribute: TAttribute
actions?: Array<{
label: React.ReactNode
Expand All @@ -31,14 +34,18 @@ type AttributeContainerProps<TAttribute extends { id: string; name: string }> =
chipLabel?: string
checked?: boolean
onRemove?: (id: string, name: string) => void
onCustomizeThreshold?: VoidFunction
}

export const AttributeContainer = <TAttribute extends { id: string; name: string }>({
export const AttributeContainer = <
TAttribute extends { id: string; name: string; dailyCallsPerConsumer?: number },
>({
attribute,
actions,
chipLabel,
checked,
onRemove,
onCustomizeThreshold,
}: AttributeContainerProps<TAttribute>) => {
const { t } = useTranslation('shared-components', { keyPrefix: 'attributeContainer' })
const panelContentId = React.useId()
Expand Down Expand Up @@ -83,7 +90,45 @@ export const AttributeContainer = <TAttribute extends { id: string; name: string
aria-controls={panelContentId}
id={headerId}
>
<Typography fontWeight={600}>{attribute.name}</Typography>
<Stack>
<Typography fontWeight={600}>{attribute.name}</Typography>
{onCustomizeThreshold && (
<Stack direction={'row'} spacing={2} alignItems={'center'}>
{attribute.dailyCallsPerConsumer && (
<Stack direction={'row'} spacing={1}>
<Typography
sx={{
fontSize: 16,
}}
>
{t('thresholdLabel')}
</Typography>
<Typography
sx={{
fontSize: 16,
fontWeight: 700,
}}
>
{attribute.dailyCallsPerConsumer}
</Typography>
</Stack>
)}
<Button
sx={{
justifyContent: 'start',
px: 1,
width: 'fit-content',
}}
onClick={(e) => {
e.stopPropagation()
onCustomizeThreshold()
}}
>
{attribute.dailyCallsPerConsumer ? t('changeBtn') : t('customizeBtn')}
</Button>
</Stack>
)}
</Stack>
</AccordionSummary>
<AccordionDetails>
{hasExpandedOnce && <AttributeDetails attributeId={attribute.id} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,25 @@ import { SectionContainer } from '@/components/layout/containers'
import { Box, Button, Link, Stack } from '@mui/material'
import { attributesHelpLink } from '@/config/constants'
import { AttributeGroup } from './AttributeGroup'
import type { CreateStepAttributesFormValues } from '@/pages/ProviderEServiceCreatePage/components/EServiceCreateStepAttributes'
import { type CreateStepThresholdsFormValues } from '@/pages/ProviderEServiceCreatePage/components/EServiceCreateStepThresholds'

export type AddAttributesToFormProps = {
attributeKey: AttributeKey
readOnly: boolean
withThreshold?: boolean
openCreateAttributeDrawer?: VoidFunction
}

export const AddAttributesToForm: React.FC<AddAttributesToFormProps> = ({
attributeKey,
readOnly,
withThreshold,
openCreateAttributeDrawer,
}) => {
const { t } = useTranslation('eservice', { keyPrefix: `create.step3` })
const { t: tAttribute } = useTranslation('attribute')

const { watch, setValue } = useFormContext<CreateStepAttributesFormValues>()
const { watch, setValue } = useFormContext<CreateStepThresholdsFormValues>()

const attributeGroups = watch(`attributes.${attributeKey}`)

Expand Down Expand Up @@ -68,6 +70,7 @@ export const AddAttributesToForm: React.FC<AddAttributesToFormProps> = ({
group={group}
attributeKey={attributeKey}
readOnly={readOnly}
withThreshold={withThreshold}
onRemoveAttributesGroup={handleRemoveAttributesGroup}
onRemoveAttributeFromGroup={handleRemoveAttributeFromGroup}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ import { AttributeAutocomplete } from '../AttributeAutocomplete'
import type { DescriptorAttribute } from '@/api/api.generatedTypes'
import { useFormContext } from 'react-hook-form'
import type { CreateStepAttributesFormValues } from '@/pages/ProviderEServiceCreatePage/components/EServiceCreateStepAttributes'
import { useCustomizeThresholdDrawer } from '../CustomizeThresholdDrawer'

export type AttributeGroupProps = {
group: Array<DescriptorAttribute>
groupIndex: number
attributeKey: AttributeKey
readOnly: boolean
withThreshold?: boolean
onRemoveAttributesGroup: (groupIndex: number) => void
onRemoveAttributeFromGroup: (attributeId: string, groupIndex: number) => void
}
Expand All @@ -24,11 +26,13 @@ export const AttributeGroup: React.FC<AttributeGroupProps> = ({
groupIndex,
attributeKey,
readOnly,
withThreshold,
onRemoveAttributesGroup,
onRemoveAttributeFromGroup,
}) => {
const { t } = useTranslation('attribute', { keyPrefix: 'group' })
const [isAttributeAutocompleteShown, setIsAttributeAutocompleteShown] = React.useState(false)
const { open } = useCustomizeThresholdDrawer()

const handleDeleteAttributesGroup = () => {
onRemoveAttributesGroup(groupIndex)
Expand Down Expand Up @@ -63,6 +67,7 @@ export const AttributeGroup: React.FC<AttributeGroupProps> = ({
onRemove={
!readOnly ? handleDeleteAttributeFromGroup.bind(null, attribute.id) : undefined
}
onCustomizeThreshold={withThreshold ? () => open(attribute, groupIndex) : undefined}
/>
</Box>
))}
Expand Down
193 changes: 193 additions & 0 deletions src/components/shared/CustomizeThresholdDrawer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
import React, { useEffect } from 'react'
import { FormProvider, type SubmitHandler, useForm } from 'react-hook-form'
import { Drawer } from '@/components/shared/Drawer'
import { Alert, Stack, Button, Typography } from '@mui/material'
import { RHFTextField } from './react-hook-form-inputs'
import { useTranslation } from 'react-i18next'
import { type DescriptorAttribute } from '@/api/api.generatedTypes'
import { WarningAmber } from '@mui/icons-material'
import { create } from 'zustand'
import { isEmpty } from 'lodash'

export type CustomizeThresholdDrawerProps = {
dailyCallsPerConsumer?: number
dailyCallsTotal?: number
onSubmit: (threshold: number) => void
}

type CustomizeThresholdDrawerStore = {
isOpen: boolean
open: (attribute: DescriptorAttribute, attributeGroupIndex: number) => void
close: VoidFunction
attribute?: DescriptorAttribute
attributeGroupIndex?: number
}

export const useCustomizeThresholdDrawer = create<CustomizeThresholdDrawerStore>((set) => ({
isOpen: false,
open: (attribute, attributeGroupIndex) => set({ attribute, attributeGroupIndex, isOpen: true }),
close: () => set({ isOpen: false }),
}))

type CustomizeThresholdFormValues = {
threshold: number
}

export const CustomizeThresholdDrawer: React.FC<CustomizeThresholdDrawerProps> = ({
onSubmit,
dailyCallsPerConsumer,
dailyCallsTotal,
}) => {
const { isOpen, close, attribute } = useCustomizeThresholdDrawer()
const { t } = useTranslation('eservice', {
keyPrefix: 'create.step2.attributes.customizeThresholdDrawer',
})
const formMethods = useForm<CustomizeThresholdFormValues>({
defaultValues: {
threshold: attribute?.dailyCallsPerConsumer,

Check failure on line 47 in src/components/shared/CustomizeThresholdDrawer.tsx

View workflow job for this annotation

GitHub Actions / Build and Test (ubuntu-latest, 18.15.0)

Property 'dailyCallsPerConsumer' does not exist on type 'DescriptorAttribute'.
},
})

const handleFormSubmit: SubmitHandler<CustomizeThresholdFormValues> = (values) => {
onSubmit(values.threshold)
}

useEffect(() => {
if (isOpen) {
formMethods.reset({
threshold: attribute?.dailyCallsPerConsumer,

Check failure on line 58 in src/components/shared/CustomizeThresholdDrawer.tsx

View workflow job for this annotation

GitHub Actions / Build and Test (ubuntu-latest, 18.15.0)

Property 'dailyCallsPerConsumer' does not exist on type 'DescriptorAttribute'.
})
}
}, [isOpen, formMethods, attribute])

return (
<FormProvider {...formMethods}>
<Drawer
isOpen={isOpen}
title={t('title')}
subtitle={t('subtitle', { name: attribute?.name })}
onTransitionExited={formMethods.reset}
onClose={close}
>
<Stack
justifyContent={'space-between'}
sx={{ height: '100%', pb: 5 }}
component={'form'}
noValidate
onSubmit={formMethods.handleSubmit(handleFormSubmit)}
id="threshold-form"
>
<Stack spacing={5}>
<RHFTextField
sx={{ mt: 2, mb: 0 }}
name="threshold"
label={t('field.placeholder')}
infoLabel={t('field.info')}
type="number"
rules={{
required: true,
min: 1,
}}
/>
<Alert icon={false} color="info">
<Stack>
<Typography
sx={{
fontSize: 14,
fontWeight: 700,
textTransform: 'uppercase',
}}
>
{t('limitAlert.title')}
</Typography>
<Stack
direction={'row'}
alignItems={'center'}
justifyContent={'space-between'}
gap={2}
>
<Typography
sx={{
fontSize: 16,
}}
>
{t('limitAlert.totalLimit')}
</Typography>
{dailyCallsTotal ? (
<Typography
sx={{
fontSize: 16,
fontWeight: 600,
}}
>
{t('limitAlert.label', { threshold: dailyCallsTotal })}
</Typography>
) : (
<Stack direction={'row'} alignItems={'center'} spacing={1}>
<WarningAmber color="warning" />
<Typography
sx={{
fontSize: 16,
fontWeight: 600,
}}
>
{t('limitAlert.toInsert')}
</Typography>
</Stack>
)}
</Stack>
<Stack
direction={'row'}
alignItems={'center'}
justifyContent={'space-between'}
gap={2}
>
<Typography
sx={{
fontSize: 16,
}}
>
{t('limitAlert.consumerLimit')}
</Typography>
{dailyCallsPerConsumer ? (
<Typography
sx={{
fontSize: 16,
fontWeight: 600,
}}
>
{t('limitAlert.label', { threshold: dailyCallsPerConsumer })}
</Typography>
) : (
<Stack direction={'row'} alignItems={'center'} spacing={1}>
<WarningAmber color="warning" />
<Typography
sx={{
fontSize: 16,
fontWeight: 600,
}}
>
{t('limitAlert.toInsert')}
</Typography>
</Stack>
)}
</Stack>
</Stack>
</Alert>
</Stack>
<Stack spacing={5}>
<Alert severity="info">{t('alert')}</Alert>
<Button
type={'submit'}
form="threshold-form"
variant="contained"
color={isEmpty(formMethods.formState.errors) ? 'primary' : 'error'}
>
{t('submitBtnLabel')}
</Button>
</Stack>
</Stack>
</Drawer>
</FormProvider>
)
}
Loading
Loading