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>
</>
);
}