mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-15 12:20:31 +00:00
feat: validate the given imported sheet whether is empty
This commit is contained in:
53
packages/webapp/src/containers/Import/AlertsManager.tsx
Normal file
53
packages/webapp/src/containers/Import/AlertsManager.tsx
Normal file
@@ -0,0 +1,53 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { useState, createContext, useContext } from 'react';
|
||||
|
||||
interface AlertsManagerContextValue {
|
||||
alerts: (string | number)[];
|
||||
showAlert: (alert: string | number) => void;
|
||||
hideAlert: (alert: string | number) => void;
|
||||
|
||||
hideAlerts: () => void;
|
||||
isAlertActive: (alert: string | number) => boolean;
|
||||
findAlert: (alert: string | number) => string | number | undefined;
|
||||
}
|
||||
|
||||
const AlertsManagerContext = createContext<AlertsManagerContextValue>(
|
||||
{} as AlertsManagerContextValue,
|
||||
);
|
||||
|
||||
export function AlertsManager({ children }: { children: ReactNode }) {
|
||||
const [alerts, setAlerts] = useState<(string | number)[]>([]);
|
||||
|
||||
const showAlert = (type: string | number): void => {
|
||||
setAlerts([...alerts, type]);
|
||||
};
|
||||
const hideAlert = (type: string | number): void => {
|
||||
alerts.filter((t) => t !== type);
|
||||
};
|
||||
const hideAlerts = (): void => {
|
||||
setAlerts([]);
|
||||
};
|
||||
const isAlertActive = (type: string | number): boolean => {
|
||||
return alerts.some((t) => t === type);
|
||||
};
|
||||
const findAlert = (type: string | number): number | string | undefined => {
|
||||
return alerts.find((t) => t === type);
|
||||
};
|
||||
|
||||
return (
|
||||
<AlertsManagerContext.Provider
|
||||
value={{
|
||||
alerts,
|
||||
showAlert,
|
||||
hideAlert,
|
||||
hideAlerts,
|
||||
isAlertActive,
|
||||
findAlert,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</AlertsManagerContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
export const useAlertsManager = () => useContext(AlertsManagerContext);
|
||||
@@ -3,8 +3,11 @@ import { Field } from 'formik';
|
||||
import { Box, Group, Stack } from '@/components';
|
||||
import styles from './ImportDropzone.module.css';
|
||||
import { ImportDropzoneField } from './ImportDropzoneFile';
|
||||
import { useAlertsManager } from './AlertsManager';
|
||||
|
||||
export function ImportDropzone() {
|
||||
const { hideAlerts } = useAlertsManager();
|
||||
|
||||
return (
|
||||
<Stack spacing={0}>
|
||||
<Field id={'file'} name={'file'} type="file">
|
||||
@@ -12,6 +15,7 @@ export function ImportDropzone() {
|
||||
<ImportDropzoneField
|
||||
value={form.file}
|
||||
onChange={(file) => {
|
||||
hideAlerts();
|
||||
form.setFieldValue('file', file);
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -5,7 +5,8 @@ import { Intent } from '@blueprintjs/core';
|
||||
import { Formik, Form, FormikHelpers } from 'formik';
|
||||
import * as Yup from 'yup';
|
||||
import { useImportFileContext } from './ImportFileProvider';
|
||||
import { ImportStepperStep } from './_types';
|
||||
import { ImportAlert, ImportStepperStep } from './_types';
|
||||
import { useAlertsManager } from './AlertsManager';
|
||||
|
||||
const initialValues = {
|
||||
file: null,
|
||||
@@ -28,6 +29,7 @@ export function ImportFileUploadForm({
|
||||
formikProps,
|
||||
formProps,
|
||||
}: ImportFileUploadFormProps) {
|
||||
const { showAlert, hideAlerts } = useAlertsManager();
|
||||
const { mutateAsync: uploadImportFile } = useImportFileUpload();
|
||||
const {
|
||||
resource,
|
||||
@@ -42,6 +44,7 @@ export function ImportFileUploadForm({
|
||||
values: ImportFileUploadValues,
|
||||
{ setSubmitting }: FormikHelpers<ImportFileUploadValues>,
|
||||
) => {
|
||||
hideAlerts();
|
||||
if (!values.file) return;
|
||||
|
||||
setSubmitting(true);
|
||||
@@ -69,6 +72,9 @@ export function ImportFileUploadForm({
|
||||
message: 'The extenstion of uploaded file is not supported.',
|
||||
});
|
||||
}
|
||||
if (data.errors.find((er) => er.type === 'IMPORTED_SHEET_EMPTY')) {
|
||||
showAlert(ImportAlert.IMPORTED_SHEET_EMPTY);
|
||||
}
|
||||
setSubmitting(false);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import { Classes } from '@blueprintjs/core';
|
||||
import { Callout, Classes, Intent } from '@blueprintjs/core';
|
||||
import { Stack } from '@/components';
|
||||
import { ImportDropzone } from './ImportDropzone';
|
||||
import { ImportSampleDownload } from './ImportSampleDownload';
|
||||
@@ -7,29 +7,50 @@ import { ImportFileUploadForm } from './ImportFileUploadForm';
|
||||
import { ImportFileUploadFooterActions } from './ImportFileFooterActions';
|
||||
import { ImportFileContainer } from './ImportFileContainer';
|
||||
import { useImportFileContext } from './ImportFileProvider';
|
||||
import { AlertsManager, useAlertsManager } from './AlertsManager';
|
||||
import { ImportAlert } from './_types';
|
||||
|
||||
function ImportFileUploadCallouts() {
|
||||
const { isAlertActive } = useAlertsManager();
|
||||
return (
|
||||
<>
|
||||
{isAlertActive(ImportAlert.IMPORTED_SHEET_EMPTY) && (
|
||||
<Callout intent={Intent.DANGER} icon={null}>
|
||||
The imported sheet is empty.
|
||||
</Callout>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function ImportFileUploadStep() {
|
||||
const { exampleDownload } = useImportFileContext();
|
||||
|
||||
return (
|
||||
<ImportFileUploadForm>
|
||||
<ImportFileContainer>
|
||||
<p
|
||||
className={Classes.TEXT_MUTED}
|
||||
style={{ marginBottom: 18, lineHeight: 1.6 }}
|
||||
>
|
||||
Download a sample file and compare it with your import file to ensure
|
||||
it is properly formatted. It's not necessary for the columns to be in
|
||||
the same order, you can map them later.
|
||||
</p>
|
||||
<AlertsManager>
|
||||
<ImportFileUploadForm>
|
||||
<ImportFileContainer>
|
||||
<p
|
||||
className={Classes.TEXT_MUTED}
|
||||
style={{ marginBottom: 18, lineHeight: 1.6 }}
|
||||
>
|
||||
Download a sample file and compare it with your import file to
|
||||
ensure it is properly formatted. It's not necessary for the columns
|
||||
to be in the same order, you can map them later.
|
||||
</p>
|
||||
|
||||
<Stack spacing={40}>
|
||||
<ImportDropzone />
|
||||
{exampleDownload && <ImportSampleDownload />}
|
||||
</Stack>
|
||||
</ImportFileContainer>
|
||||
<Stack>
|
||||
<ImportFileUploadCallouts />
|
||||
|
||||
<ImportFileUploadFooterActions />
|
||||
</ImportFileUploadForm>
|
||||
<Stack spacing={40}>
|
||||
<ImportDropzone />
|
||||
{exampleDownload && <ImportSampleDownload />}
|
||||
</Stack>
|
||||
</Stack>
|
||||
</ImportFileContainer>
|
||||
|
||||
<ImportFileUploadFooterActions />
|
||||
</ImportFileUploadForm>
|
||||
</AlertsManager>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -3,3 +3,7 @@ export enum ImportStepperStep {
|
||||
Mapping = 1,
|
||||
Preview = 2,
|
||||
}
|
||||
|
||||
export enum ImportAlert {
|
||||
IMPORTED_SHEET_EMPTY = 'IMPORTED_SHEET_EMPTY'
|
||||
}
|
||||
Reference in New Issue
Block a user