mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-17 13:20:31 +00:00
feat: wip import resource UI
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { Ref, useCallback } from 'react';
|
||||
import clsx from 'classnames';
|
||||
import {
|
||||
Accept,
|
||||
@@ -226,6 +227,7 @@ export const Dropzone = (_props: DropzoneProps) => {
|
||||
});
|
||||
|
||||
const isIdle = !isDragAccept && !isDragReject;
|
||||
assignRef(openRef, open);
|
||||
|
||||
return (
|
||||
<DropzoneProvider
|
||||
@@ -264,3 +266,26 @@ Dropzone.displayName = '@mantine/dropzone/Dropzone';
|
||||
Dropzone.Accept = DropzoneAccept;
|
||||
Dropzone.Idle = DropzoneIdle;
|
||||
Dropzone.Reject = DropzoneReject;
|
||||
|
||||
|
||||
|
||||
|
||||
type PossibleRef<T> = Ref<T> | undefined;
|
||||
|
||||
export function assignRef<T>(ref: PossibleRef<T>, value: T) {
|
||||
if (typeof ref === 'function') {
|
||||
ref(value);
|
||||
} else if (typeof ref === 'object' && ref !== null && 'current' in ref) {
|
||||
(ref as React.MutableRefObject<T>).current = value;
|
||||
}
|
||||
}
|
||||
|
||||
export function mergeRefs<T>(...refs: PossibleRef<T>[]) {
|
||||
return (node: T | null) => {
|
||||
refs.forEach((ref) => assignRef(ref, node));
|
||||
};
|
||||
}
|
||||
|
||||
export function useMergedRef<T>(...refs: PossibleRef<T>[]) {
|
||||
return useCallback(mergeRefs(...refs), refs);
|
||||
}
|
||||
@@ -30,7 +30,7 @@ export function Stack(props: StackProps) {
|
||||
const StackStyled = styled(Box)`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: align;
|
||||
align-items: ${(props: StackProps) => props.align};
|
||||
justify-content: justify;
|
||||
gap: ${(props: StackProps) => props.spacing}px;
|
||||
`;
|
||||
|
||||
@@ -81,8 +81,8 @@ export function Stepper({
|
||||
active > _children.length - 1 ? completedContent : stepContent;
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<StepsItems>{items}</StepsItems>
|
||||
<Box className={classNames?.root}>
|
||||
<StepsItems className={classNames?.items}>{items}</StepsItems>
|
||||
<StepsContent className={classNames?.content}>{content} </StepsContent>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -1,42 +1,20 @@
|
||||
// @ts-nocheck
|
||||
import { Button } from '@blueprintjs/core';
|
||||
import { Field } from 'formik';
|
||||
import { Box, Group, Icon, Stack } from '@/components';
|
||||
import { Dropzone } from '@/components/Dropzone';
|
||||
import { MIME_TYPES } from '@/components/Dropzone/mine-types';
|
||||
import { Box, Group, Stack } from '@/components';
|
||||
import styles from './ImportDropzone.module.css';
|
||||
import { ImportDropzoneField } from './ImportDropzoneFile';
|
||||
|
||||
export function ImportDropzone() {
|
||||
return (
|
||||
<Stack spacing={0}>
|
||||
<Field id={'file'} name={'file'} type="file">
|
||||
{({ form: { setFieldValue } }) => (
|
||||
<Dropzone
|
||||
onDrop={(files) => setFieldValue('file', files[0])}
|
||||
onReject={(files) => console.log('rejected files', files)}
|
||||
maxSize={5 * 1024 ** 2}
|
||||
accept={[MIME_TYPES.csv, MIME_TYPES.xls, MIME_TYPES.xlsx]}
|
||||
classNames={{ content: styles.dropzoneContent }}
|
||||
>
|
||||
<Stack spacing={10} className={styles.content}>
|
||||
<Box className={styles.iconWrap}>
|
||||
<Icon icon="download" iconSize={26} />
|
||||
</Box>
|
||||
<Stack spacing={4}>
|
||||
<h4 className={styles.title}>
|
||||
Drag images here or click to select files
|
||||
</h4>
|
||||
<span className={styles.subtitle}>
|
||||
Drag and Drop file here or Choose file
|
||||
</span>
|
||||
</Stack>
|
||||
<Box>
|
||||
<Button intent="none" minimal outlined>
|
||||
Upload File
|
||||
</Button>
|
||||
</Box>
|
||||
</Stack>
|
||||
</Dropzone>
|
||||
{({ form }) => (
|
||||
<ImportDropzoneField
|
||||
value={form.file}
|
||||
onChange={(file) => {
|
||||
form.setFieldValue('file', file);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Field>
|
||||
|
||||
|
||||
80
packages/webapp/src/containers/Import/ImportDropzoneFile.tsx
Normal file
80
packages/webapp/src/containers/Import/ImportDropzoneFile.tsx
Normal file
@@ -0,0 +1,80 @@
|
||||
// @ts-nocheck
|
||||
import { useRef } from 'react';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { Box, Icon, Stack } from '@/components';
|
||||
import { Dropzone, DropzoneProps } from '@/components/Dropzone';
|
||||
import { MIME_TYPES } from '@/components/Dropzone/mine-types';
|
||||
import styles from './ImportDropzone.module.css';
|
||||
import { useUncontrolled } from '@/hooks/useUncontrolled';
|
||||
|
||||
interface ImportDropzoneFieldProps {
|
||||
initialValue?: File;
|
||||
value?: File;
|
||||
onChange?: (file: File) => void;
|
||||
dropzoneProps?: DropzoneProps;
|
||||
}
|
||||
|
||||
export function ImportDropzoneField({
|
||||
initialValue,
|
||||
value,
|
||||
onChange,
|
||||
dropzoneProps,
|
||||
}: ImportDropzoneFieldProps) {
|
||||
const [localValue, handleChange] = useUncontrolled({
|
||||
value,
|
||||
initialValue,
|
||||
finalValue: null,
|
||||
onChange,
|
||||
});
|
||||
const openRef = useRef<() => void>(null);
|
||||
|
||||
const handleRemove = () => {
|
||||
handleChange(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<Dropzone
|
||||
onDrop={(files) => handleChange(files[0])}
|
||||
onReject={(files) => console.log('rejected files', files)}
|
||||
maxSize={5 * 1024 ** 2}
|
||||
accept={[MIME_TYPES.csv, MIME_TYPES.xls, MIME_TYPES.xlsx]}
|
||||
classNames={{ content: styles.dropzoneContent }}
|
||||
activateOnClick={false}
|
||||
openRef={openRef}
|
||||
{...dropzoneProps}
|
||||
>
|
||||
<Stack spacing={12} align="center" className={styles.content}>
|
||||
<Box className={styles.iconWrap}>
|
||||
<Icon icon="download" iconSize={26} />
|
||||
</Box>
|
||||
{localValue ? (
|
||||
<Stack spacing={6} justify="center" align="center">
|
||||
<h4 className={styles.title}>{localValue.name}</h4>
|
||||
<Button small minimal intent={Intent.DANGER} onClick={handleRemove}>
|
||||
Remove
|
||||
</Button>
|
||||
</Stack>
|
||||
) : (
|
||||
<Stack spacing={4} align="center">
|
||||
<h4 className={styles.title}>
|
||||
Drag images here or click to select files
|
||||
</h4>
|
||||
<span className={styles.subtitle}>
|
||||
Drag and Drop file here or Choose file
|
||||
</span>
|
||||
</Stack>
|
||||
)}
|
||||
|
||||
<Button
|
||||
intent="none"
|
||||
onClick={() => openRef.current?.()}
|
||||
style={{ pointerEvents: 'all' }}
|
||||
minimal
|
||||
outlined
|
||||
>
|
||||
{localValue ? 'Replace File' : 'Upload File'}
|
||||
</Button>
|
||||
</Stack>
|
||||
</Dropzone>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
|
||||
|
||||
.root{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import styles from './ImportFileUploadStep.module.scss';
|
||||
|
||||
interface ImportFileContainerProps {
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
export function ImportFileContainer({ children }: ImportFileContainerProps) {
|
||||
return <div className={styles.content}>{children}</div>;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// @ts-nocheck
|
||||
import clsx from 'classnames';
|
||||
import { Group } from '@/components';
|
||||
import { CLASSES } from '@/constants';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import styles from './ImportFileActions.module.scss';
|
||||
import { useImportFileContext } from './ImportFileProvider';
|
||||
|
||||
export function ImportFileUploadFooterActions() {
|
||||
const { isSubmitting } = useFormikContext();
|
||||
const { setStep } = useImportFileContext();
|
||||
|
||||
const handleCancelBtnClick = () => {};
|
||||
|
||||
return (
|
||||
<div className={clsx(CLASSES.PAGE_FORM_FLOATING_ACTIONS, styles.root)}>
|
||||
<Group spacing={10}>
|
||||
<Button onClick={handleCancelBtnClick}>Cancel</Button>
|
||||
<Button type="submit" intent={Intent.PRIMARY} loading={isSubmitting}>
|
||||
Next
|
||||
</Button>
|
||||
</Group>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
.table {
|
||||
width: 100%;
|
||||
margin-top: 1.8rem;
|
||||
margin-top: 1.4rem;
|
||||
|
||||
th.label,
|
||||
td.label{
|
||||
width: 32% !important;
|
||||
}
|
||||
|
||||
thead{
|
||||
th{
|
||||
@@ -8,14 +13,19 @@
|
||||
padding-top: 8px;
|
||||
padding-bottom: 8px;
|
||||
color: #738091;
|
||||
}
|
||||
th.label{
|
||||
width: 32%;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
tbody{
|
||||
tr td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
tr td{
|
||||
:global(.bp4-popover-target .bp4-button){
|
||||
max-width: 250px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,32 +1,36 @@
|
||||
import { useMemo } from 'react';
|
||||
import clsx from 'classnames';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { FSelect, Group } from '@/components';
|
||||
import { ImportFileMappingForm } from './ImportFileMappingForm';
|
||||
import { useImportFileContext } from './ImportFileProvider';
|
||||
import styles from './ImportFileMapping.module.scss';
|
||||
import { CLASSES } from '@/constants';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { ImportFileContainer } from './ImportFileContainer';
|
||||
import styles from './ImportFileMapping.module.scss';
|
||||
import { ImportStepperStep } from './_types';
|
||||
|
||||
export function ImportFileMapping() {
|
||||
return (
|
||||
<ImportFileMappingForm>
|
||||
<p>
|
||||
Review and map the column headers in your csv/xlsx file with the
|
||||
Bigcapital fields.
|
||||
</p>
|
||||
<ImportFileContainer>
|
||||
<p>
|
||||
Review and map the column headers in your csv/xlsx file with the
|
||||
Bigcapital fields.
|
||||
</p>
|
||||
|
||||
<table className={clsx('bp4-html-table', styles.table)}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className={'label'}>Bigcapital Fields</th>
|
||||
<th className={'field'}>Sheet Column Headers</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<ImportFileMappingFields />
|
||||
</tbody>
|
||||
</table>
|
||||
<table className={clsx('bp4-html-table', styles.table)}>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className={styles.label}>Bigcapital Fields</th>
|
||||
<th className={styles.field}>Sheet Column Headers</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<ImportFileMappingFields />
|
||||
</tbody>
|
||||
</table>
|
||||
</ImportFileContainer>
|
||||
|
||||
<ImportFileMappingFloatingActions />
|
||||
</ImportFileMappingForm>
|
||||
@@ -43,14 +47,14 @@ function ImportFileMappingFields() {
|
||||
|
||||
const columns = entityColumns.map((column, index) => (
|
||||
<tr key={index}>
|
||||
<td className={'label'}>{column.name}</td>
|
||||
<td className={'field'}>
|
||||
<td className={styles.label}>{column.name}</td>
|
||||
<td className={styles.field}>
|
||||
<FSelect
|
||||
name={column.key}
|
||||
items={items}
|
||||
fill
|
||||
popoverProps={{ minimal: false }}
|
||||
minimal={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
minimal={true}
|
||||
fill={true}
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -60,14 +64,19 @@ function ImportFileMappingFields() {
|
||||
|
||||
function ImportFileMappingFloatingActions() {
|
||||
const { isSubmitting } = useFormikContext();
|
||||
const { setStep } = useImportFileContext();
|
||||
|
||||
const handleCancelBtnClick = () => {
|
||||
setStep(ImportStepperStep.Upload);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={clsx(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||
<Group>
|
||||
<Group spacing={10}>
|
||||
<Button onClick={handleCancelBtnClick}>Cancel</Button>
|
||||
<Button type="submit" intent={Intent.PRIMARY} loading={isSubmitting}>
|
||||
Next
|
||||
</Button>
|
||||
<Button>Cancel</Button>
|
||||
</Group>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import { Button, Callout, Intent, Text } from '@blueprintjs/core';
|
||||
import clsx from 'classnames';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import {
|
||||
ImportFilePreviewBootProvider,
|
||||
useImportFilePreviewBootContext,
|
||||
@@ -9,7 +10,7 @@ import { useImportFileContext } from './ImportFileProvider';
|
||||
import { AppToaster, Card, Group } from '@/components';
|
||||
import { useImportFileProcess } from '@/hooks/query/import';
|
||||
import { CLASSES } from '@/constants';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { ImportStepperStep } from './_types';
|
||||
|
||||
export function ImportFilePreview() {
|
||||
const { importId } = useImportFileContext();
|
||||
@@ -81,7 +82,7 @@ function ImportFilePreviewContent() {
|
||||
}
|
||||
|
||||
function ImportFilePreviewFloatingActions() {
|
||||
const { importId } = useImportFileContext();
|
||||
const { importId, setStep } = useImportFileContext();
|
||||
const { importPreview } = useImportFilePreviewBootContext();
|
||||
const { mutateAsync: importFile, isLoading: isImportFileLoading } =
|
||||
useImportFileProcess();
|
||||
@@ -102,9 +103,14 @@ function ImportFilePreviewFloatingActions() {
|
||||
})
|
||||
.catch((error) => {});
|
||||
};
|
||||
const handleCancelBtnClick = () => {
|
||||
setStep(ImportStepperStep.Mapping);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={clsx(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||
<Group>
|
||||
<Group spacing={10}>
|
||||
<Button onClick={handleCancelBtnClick}>Cancel</Button>
|
||||
<Button
|
||||
type="submit"
|
||||
intent={Intent.PRIMARY}
|
||||
@@ -114,7 +120,6 @@ function ImportFilePreviewFloatingActions() {
|
||||
>
|
||||
Import
|
||||
</Button>
|
||||
<Button>Cancel</Button>
|
||||
</Group>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Intent } from '@blueprintjs/core';
|
||||
import { Formik, Form, FormikHelpers } from 'formik';
|
||||
import * as Yup from 'yup';
|
||||
import { useImportFileContext } from './ImportFileProvider';
|
||||
import { ImportStepperStep } from './_types';
|
||||
|
||||
const initialValues = {
|
||||
file: null,
|
||||
@@ -22,9 +23,14 @@ interface ImportFileUploadValues {
|
||||
file: File | null;
|
||||
}
|
||||
|
||||
export function ImportFileUploadForm({ children }: ImportFileUploadFormProps) {
|
||||
export function ImportFileUploadForm({
|
||||
children,
|
||||
formikProps,
|
||||
formProps,
|
||||
}: ImportFileUploadFormProps) {
|
||||
const { mutateAsync: uploadImportFile } = useImportFileUpload();
|
||||
const { setStep, setSheetColumns, setEntityColumns, setImportId } = useImportFileContext();
|
||||
const { setStep, setSheetColumns, setEntityColumns, setImportId } =
|
||||
useImportFileContext();
|
||||
|
||||
const handleSubmit = (
|
||||
values: ImportFileUploadValues,
|
||||
@@ -42,7 +48,7 @@ export function ImportFileUploadForm({ children }: ImportFileUploadFormProps) {
|
||||
setImportId(data.import.import_id);
|
||||
setSheetColumns(data.sheet_columns);
|
||||
setEntityColumns(data.resource_columns);
|
||||
setStep(1);
|
||||
setStep(ImportStepperStep.Mapping);
|
||||
setSubmitting(false);
|
||||
})
|
||||
.catch((error) => {
|
||||
@@ -55,8 +61,9 @@ export function ImportFileUploadForm({ children }: ImportFileUploadFormProps) {
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validationSchema={validationSchema}
|
||||
{...formikProps}
|
||||
>
|
||||
<Form>{children}</Form>
|
||||
<Form {...formProps}>{children}</Form>
|
||||
</Formik>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
.root {
|
||||
margin-top: 2.2rem
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
padding: 32px 20px;
|
||||
min-width: 660px;
|
||||
max-width: 760px;
|
||||
width: 75%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.form {
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
.root {
|
||||
margin-top: 2.2rem
|
||||
}
|
||||
@@ -1,40 +1,26 @@
|
||||
// @ts-nocheck
|
||||
import clsx from 'classnames';
|
||||
import { Group, Stack } from '@/components';
|
||||
import { Stack } from '@/components';
|
||||
import { ImportDropzone } from './ImportDropzone';
|
||||
import { ImportSampleDownload } from './ImportSampleDownload';
|
||||
import { CLASSES } from '@/constants';
|
||||
import { Button, Intent } from '@blueprintjs/core';
|
||||
import { ImportFileUploadForm } from './ImportFileUploadForm';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { ImportFileUploadFooterActions } from './ImportFileFooterActions';
|
||||
import { ImportFileContainer } from './ImportFileContainer';
|
||||
|
||||
export function ImportFileUploadStep() {
|
||||
return (
|
||||
<ImportFileUploadForm>
|
||||
<p style={{ marginBottom: 18 }}>
|
||||
Download a sample file and compare it to your import file to ensure you
|
||||
have the file perfect for the import.
|
||||
</p>
|
||||
<ImportFileContainer>
|
||||
<p style={{ marginBottom: 18 }}>
|
||||
Download a sample file and compare it to your import file to ensure
|
||||
you have the file perfect for the import.
|
||||
</p>
|
||||
<Stack spacing={40}>
|
||||
<ImportDropzone />
|
||||
<ImportSampleDownload />
|
||||
</Stack>
|
||||
</ImportFileContainer>
|
||||
|
||||
<Stack spacing={40}>
|
||||
<ImportDropzone />
|
||||
<ImportSampleDownload />
|
||||
</Stack>
|
||||
<ImportFileUploadFooterActions />
|
||||
</ImportFileUploadForm>
|
||||
);
|
||||
}
|
||||
|
||||
function ImportFileUploadFooterActions() {
|
||||
const { isSubmitting } = useFormikContext();
|
||||
return (
|
||||
<div className={clsx(CLASSES.PAGE_FORM_FLOATING_ACTIONS)}>
|
||||
<Group spacing={10}>
|
||||
<Button type="submit" intent={Intent.PRIMARY} loading={isSubmitting}>
|
||||
Next
|
||||
</Button>
|
||||
<Button>Cancel</Button>
|
||||
</Group>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
.root{
|
||||
padding: 32px 40px;
|
||||
min-width: 700px;
|
||||
max-width: 800px;
|
||||
width: 75%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
|
||||
}
|
||||
.rootWrap {
|
||||
max-width: 1800px;
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
// @ts-nocheck
|
||||
import { ImportStepper } from './ImportStepper';
|
||||
import { Box, DashboardInsider } from '@/components';
|
||||
import styles from './ImportPage.module.scss';
|
||||
import { ImportFileProvider } from './ImportFileProvider';
|
||||
import styles from './ImportPage.module.scss';
|
||||
|
||||
|
||||
export default function ImportPage() {
|
||||
return (
|
||||
<DashboardInsider>
|
||||
<Box className={styles.rootWrap}>
|
||||
<Box className={styles.root}>
|
||||
<ImportFileProvider resource="account">
|
||||
<ImportStepper />
|
||||
</ImportFileProvider>
|
||||
</Box>
|
||||
<Box className={styles.root}>
|
||||
<ImportFileProvider resource="account">
|
||||
<ImportStepper />
|
||||
</ImportFileProvider>
|
||||
</Box>
|
||||
</DashboardInsider>
|
||||
);
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
.content {
|
||||
margin-top: 2.4rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
border-top: 1px solid #DCE0E5;
|
||||
}
|
||||
|
||||
.root {
|
||||
|
||||
}
|
||||
|
||||
.items {
|
||||
padding: 32px 20px;
|
||||
min-width: 660px;
|
||||
max-width: 760px;
|
||||
width: 75%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
@@ -2,16 +2,22 @@
|
||||
|
||||
import { Stepper } from '@/components/Stepper';
|
||||
import { ImportFileUploadStep } from './ImportFileUploadStep';
|
||||
import styles from './ImportStepper.module.scss';
|
||||
import { useImportFileContext } from './ImportFileProvider';
|
||||
import { ImportFileMapping } from './ImportFileMapping';
|
||||
import { ImportFilePreview } from './ImportFilePreview';
|
||||
import styles from './ImportStepper.module.scss';
|
||||
|
||||
export function ImportStepper() {
|
||||
const { step } = useImportFileContext();
|
||||
|
||||
return (
|
||||
<Stepper active={step} classNames={{ content: styles.content }}>
|
||||
<Stepper
|
||||
active={step}
|
||||
classNames={{
|
||||
content: styles.content,
|
||||
items: styles.items,
|
||||
}}
|
||||
>
|
||||
<Stepper.Step label={'File Upload'}>
|
||||
<ImportFileUploadStep />
|
||||
</Stepper.Step>
|
||||
|
||||
5
packages/webapp/src/containers/Import/_types.ts
Normal file
5
packages/webapp/src/containers/Import/_types.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
export enum ImportStepperStep {
|
||||
Upload = 0,
|
||||
Mapping = 1,
|
||||
Preview = 2,
|
||||
}
|
||||
Reference in New Issue
Block a user