teableio/teable

View on GitHub
apps/nextjs-app/src/features/app/blocks/import-table/UrlPanel.tsx

Summary

Maintainability
A
0 mins
Test Coverage
import type { UseMutateAsyncFunction } from '@tanstack/react-query';
import type { FieldType } from '@teable/core';
import type { SUPPORTEDTYPE } from '@teable/openapi';
import { importTypeMap } from '@teable/openapi';
import { Input, Button, Spin } from '@teable/ui-lib';
import type { AxiosResponse } from 'axios';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { z } from 'zod';

interface IUrlPanel {
  fileType: SUPPORTEDTYPE;
  analyzeFn: UseMutateAsyncFunction<
    AxiosResponse<
      {
        worksheets: Record<
          string,
          {
            name: string;
            columns: {
              name: string;
              type: FieldType;
            }[];
          }
        >;
      },
      unknown
    >,
    unknown,
    {
      fileType: SUPPORTEDTYPE;
      attachmentUrl: string;
    },
    unknown
  >;
  isFinished: boolean;
}

const UrlPanel = (props: IUrlPanel) => {
  const { fileType, analyzeFn, isFinished } = props;
  const [linkUrl, setLinkUrl] = useState('');
  const [errorMessage, setErrorMessage] = useState('');
  const { t } = useTranslation(['table']);

  return (
    <div className="flex h-32 w-full flex-col items-start px-2">
      <h4 className="m-2 text-sm">{t('table:import.title.linkUrlInputTitle')}</h4>
      <div className="flex w-full">
        <Input
          type="url"
          placeholder={importTypeMap[fileType].exampleUrl}
          className="mr-2 w-full"
          value={linkUrl}
          onChange={(e) => {
            const { value } = e.target;
            setLinkUrl(value);
          }}
        />
        <Button
          variant="outline"
          disabled={isFinished || !linkUrl}
          onClick={() => {
            if (!linkUrl) {
              setErrorMessage(t('table:import.form.error.urlEmptyTip'));
              return;
            }
            if (!z.string().url().safeParse(linkUrl).success) {
              setErrorMessage(t('table:import.form.error.urlValidateTip'));
              return;
            }
            analyzeFn({
              attachmentUrl: linkUrl,
              fileType,
            });
          }}
        >
          {isFinished && <Spin className="mr-1 size-4" />}
          {t('table:import.title.upload')}
        </Button>
      </div>
      {errorMessage && <p className="p-2 text-sm text-red-500">{errorMessage}</p>}
    </div>
  );
};

export { UrlPanel };