function Visas()

in next-demo/next-pages/src/pages/demoForm.tsx [600:781]


function Visas({
    lens,
    countriesDS,
}: {
    lens: ILens<PersonDetails['travelVisas']>;
    countriesDS: AsyncDataSource<Country, string, unknown>;
}) {
    const svc = useUuiContext<TApi, UuiContexts>();
    const visasLens = lens.prop('visas').default([emptyInfo.visa]);
    const scansLens = Lens.onEditable(lens.prop('scans').toProps()).default([]);

    const uploadFile = (files: File[], lens: ILens<Attachment[]>) => {
        let tempIdCounter = 0;
        const attachments = lens.default([]).get();

        const updateAttachment = (newFile: Attachment, id: number) => {
            lens.set(attachments.map((i) => (i.id === id ? newFile : i)));
        };

        const trackProgress = (progress: number, id: number) => {
            const file = attachments.find((i) => i.id === id);
            if (!file || !file.id) return;
            file.progress = progress;
            updateAttachment(file, file.id);
        };

        files.map((file) => {
            const tempId = --tempIdCounter;
            const fileToAttach = {
                id: tempId,
                name: file.name,
                size: file.size,
                progress: 0,
            };

            attachments.push(fileToAttach);
            svc.uuiApi
                .uploadFile('/uploadFileMock', file, {
                    onProgress: (progress) => trackProgress(progress, tempId),
                })
                .then((res) => {
                    updateAttachment(
                        {
                            ...res,
                            progress: 100,
                        },
                        tempId
                    );
                });
        });

        lens.set(attachments);
    };

    return (
        <>
            <RichTextView>
                <h3>Travel Visas</h3>
            </RichTextView>

            {visasLens.get().map((value, index) => {
                const isClearable = index !== 0 || value.country || value.term;
                return (
                    <FlexRow
                        key={index}
                        vPadding='12'
                        spacing='18'
                        alignItems='top'
                    >
                        <FlexCell minWidth={324}>
                            <LabeledInput
                                htmlFor={`travelVisasCountry-${index}`}
                                label='Country'
                                {...visasLens
                                    .index(index)
                                    .prop('country')
                                    .toProps()}
                            >
                                <PickerInput
                                    {...visasLens
                                        .index(index)
                                        .prop('country')
                                        .toProps()}
                                    dataSource={countriesDS}
                                    selectionMode='single'
                                    valueType='id'
                                    rawProps={{
                                        input: {
                                            id: `travelVisasCountry-${index}`,
                                        },
                                    }}
                                    placeholder='Select Country'
                                />
                            </LabeledInput>
                        </FlexCell>
                        <FlexCell minWidth={294}>
                            <LabeledInput
                                label='Term'
                                {...visasLens
                                    .index(index)
                                    .prop('term')
                                    .toProps()}
                            >
                                <RangeDatePicker
                                    {...visasLens
                                        .index(index)
                                        .prop('term')
                                        .toProps()}
                                />
                            </LabeledInput>
                        </FlexCell>
                        <FlexRow
                            size='48'
                            alignItems='bottom'
                            cx={css.clearButtonWrapper}
                        >
                            {isClearable && (
                                <IconButton
                                    icon={clearIcon}
                                    onClick={() =>
                                        removeLensItemHandler<PersonTravelVisa>(
                                            visasLens,
                                            index
                                        )
                                    }
                                />
                            )}
                        </FlexRow>
                    </FlexRow>
                );
            })}
            <FlexRow vPadding='12'>
                <Button
                    onClick={() =>
                        addLensItemHandler<PersonTravelVisa>(
                            visasLens,
                            emptyInfo.visa
                        )
                    }
                    caption='Add One More'
                    icon={addIcon}
                    fill='none'
                />
            </FlexRow>
            <FlexRow
                vPadding='12'
                spacing='18'
            >
                <FlexCell width='100%'>
                    <LabeledInput label='Scans'>
                        <DropSpot
                            infoText='Up to 20 files. Limit for 1 file is 5 MB'
                            onUploadFiles={(files) =>
                                uploadFile(files, scansLens)
                            }
                        />
                        <div
                            className={
                                scansLens.get().length
                                    ? css.attachmentContainer
                                    : ''
                            }
                        >
                            {scansLens.get().map((i, index) => (
                                <FileCard
                                    key={index}
                                    file={i}
                                    onClick={() =>
                                        removeLensItemHandler<Attachment>(
                                            scansLens,
                                            index
                                        )
                                    }
                                />
                            ))}
                        </div>
                    </LabeledInput>
                </FlexCell>
            </FlexRow>
        </>
    );
}