.
This commit is contained in:
parent
2b6a8cf204
commit
b97f51206e
66
client/src/app/quotes/components/DownloadQuoteDialog.tsx
Normal file
66
client/src/app/quotes/components/DownloadQuoteDialog.tsx
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Dialog,
|
||||||
|
DialogClose,
|
||||||
|
DialogContent,
|
||||||
|
DialogDescription,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
Label,
|
||||||
|
Progress,
|
||||||
|
} from "@/ui";
|
||||||
|
import { t } from "i18next";
|
||||||
|
import { useEffect } from "react";
|
||||||
|
import { UseDownloader } from "react-use-downloader/dist/types";
|
||||||
|
|
||||||
|
type DownloadQuoteDialogProps = Omit<UseDownloader, "download"> & {
|
||||||
|
onFinishDownload: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DownloadQuoteDialog = (props: DownloadQuoteDialogProps) => {
|
||||||
|
const { percentage, cancel, error, isInProgress, onFinishDownload } = props;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isInProgress && !error && percentage === 100) {
|
||||||
|
if (onFinishDownload) {
|
||||||
|
onFinishDownload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [percentage, isInProgress, error, onFinishDownload]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog open={isInProgress}>
|
||||||
|
<DialogContent className='sm:max-w-md'>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>{t("quotes.downloading_dialog.title")}</DialogTitle>
|
||||||
|
<DialogDescription>{t("quotes.downloading_dialog.description")}</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className='mb-4 space-y-2'>
|
||||||
|
<Label>
|
||||||
|
{t("quotes.downloading_dialog.progress.label", {
|
||||||
|
status: t(
|
||||||
|
isInProgress
|
||||||
|
? "quotes.downloading_dialog.progress.status_in_progress"
|
||||||
|
: "quotes.downloading_dialog.progress.status_stopped"
|
||||||
|
),
|
||||||
|
})}
|
||||||
|
</Label>
|
||||||
|
<Progress
|
||||||
|
value={percentage}
|
||||||
|
max={100}
|
||||||
|
getValueLabel={() => t("quotes.downloading_dialog.progress.label", {})}
|
||||||
|
/>
|
||||||
|
{error && <p>Error: {JSON.stringify(error)}</p>}
|
||||||
|
</div>
|
||||||
|
<DialogFooter className='sm:justify-end'>
|
||||||
|
<DialogClose asChild>
|
||||||
|
<Button type='button' variant='secondary' onClick={() => cancel()}>
|
||||||
|
{t("quotes.downloading_dialog.cancel_button")}
|
||||||
|
</Button>
|
||||||
|
</DialogClose>
|
||||||
|
</DialogFooter>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
@ -2,7 +2,6 @@ import {
|
|||||||
ColorBadge,
|
ColorBadge,
|
||||||
DataTable,
|
DataTable,
|
||||||
DataTableSkeleton,
|
DataTableSkeleton,
|
||||||
DownloadDialog,
|
|
||||||
ErrorOverlay,
|
ErrorOverlay,
|
||||||
SimpleEmptyState,
|
SimpleEmptyState,
|
||||||
} from "@/components";
|
} from "@/components";
|
||||||
@ -24,14 +23,16 @@ import {
|
|||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/ui";
|
} from "@/ui";
|
||||||
|
import { useToast } from "@/ui/use-toast";
|
||||||
import { IListQuotes_Response_DTO, MoneyValue, UTCDateValue } from "@shared/contexts";
|
import { IListQuotes_Response_DTO, MoneyValue, UTCDateValue } from "@shared/contexts";
|
||||||
import { ColumnDef, Row } from "@tanstack/react-table";
|
import { ColumnDef, Row } from "@tanstack/react-table";
|
||||||
import { t } from "i18next";
|
import { t } from "i18next";
|
||||||
import { FilePenLineIcon, MoreVerticalIcon } from "lucide-react";
|
import { FilePenLineIcon, MoreVerticalIcon } from "lucide-react";
|
||||||
import { useEffect, useMemo, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import useDownloader from "react-use-downloader";
|
import useDownloader from "react-use-downloader";
|
||||||
import { useQuotes } from "../hooks";
|
import { useQuotes } from "../hooks";
|
||||||
|
import { DownloadQuoteDialog } from "./DownloadQuoteDialog";
|
||||||
import { QuotePDFPreview } from "./QuotePDFPreview";
|
import { QuotePDFPreview } from "./QuotePDFPreview";
|
||||||
|
|
||||||
export const QuotesDataTable = ({
|
export const QuotesDataTable = ({
|
||||||
@ -42,6 +43,7 @@ export const QuotesDataTable = ({
|
|||||||
preview?: boolean;
|
preview?: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const { toast } = useToast();
|
||||||
const { pagination, globalFilter, isFiltered } = useDataTableContext();
|
const { pagination, globalFilter, isFiltered } = useDataTableContext();
|
||||||
|
|
||||||
const [activeRow, setActiveRow] = useState<Row<IListQuotes_Response_DTO> | undefined>(undefined);
|
const [activeRow, setActiveRow] = useState<Row<IListQuotes_Response_DTO> | undefined>(undefined);
|
||||||
@ -164,7 +166,6 @@ export const QuotesDataTable = ({
|
|||||||
<DropdownMenuItem>Edit</DropdownMenuItem>
|
<DropdownMenuItem>Edit</DropdownMenuItem>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.preventDefault();
|
|
||||||
download(row.original.id, getQuotePDFFilename(row.original));
|
download(row.original.id, getQuotePDFFilename(row.original));
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -204,6 +205,13 @@ export const QuotesDataTable = ({
|
|||||||
}
|
}
|
||||||
}, [data, table]);
|
}, [data, table]);
|
||||||
|
|
||||||
|
const handleFinishDownload = useCallback(() => {
|
||||||
|
console.log("Download success!!");
|
||||||
|
toast({
|
||||||
|
description: t("quotes.downloading_dialog.toast_success"),
|
||||||
|
});
|
||||||
|
}, [toast]);
|
||||||
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
return <ErrorOverlay subtitle={(error as Error).message} />;
|
return <ErrorOverlay subtitle={(error as Error).message} />;
|
||||||
}
|
}
|
||||||
@ -258,7 +266,7 @@ export const QuotesDataTable = ({
|
|||||||
</ResizablePanel>
|
</ResizablePanel>
|
||||||
)}
|
)}
|
||||||
</ResizablePanelGroup>
|
</ResizablePanelGroup>
|
||||||
<DownloadDialog {...downloadProps} />
|
<DownloadQuoteDialog {...downloadProps} onFinishDownload={handleFinishDownload} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,44 +0,0 @@
|
|||||||
import {
|
|
||||||
Button,
|
|
||||||
Dialog,
|
|
||||||
DialogClose,
|
|
||||||
DialogContent,
|
|
||||||
DialogDescription,
|
|
||||||
DialogFooter,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
Label,
|
|
||||||
} from "@/ui";
|
|
||||||
import { UseDownloader } from "react-use-downloader/dist/types";
|
|
||||||
|
|
||||||
export const DownloadDialog = (props: Omit<UseDownloader, "download">) => {
|
|
||||||
const { size, elapsed, percentage, cancel, error, isInProgress } = props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Dialog defaultOpen>
|
|
||||||
<DialogContent className='sm:max-w-md'>
|
|
||||||
<DialogHeader>
|
|
||||||
<DialogTitle>Share link</DialogTitle>
|
|
||||||
<DialogDescription>Anyone who has this link will be able to view this.</DialogDescription>
|
|
||||||
</DialogHeader>
|
|
||||||
<div>
|
|
||||||
<p>Download is in {isInProgress ? "in progress" : "stopped"}</p>
|
|
||||||
|
|
||||||
<button onClick={() => cancel()}>Cancel the download</button>
|
|
||||||
<p>Download size in bytes {size}</p>
|
|
||||||
<Label>Downloading progress:</Label>
|
|
||||||
<progress id='file' value={percentage} max='100' />
|
|
||||||
<p>Elapsed time in seconds {elapsed}</p>
|
|
||||||
{error && <p>possible error {JSON.stringify(error)}</p>}
|
|
||||||
</div>
|
|
||||||
<DialogFooter className='sm:justify-start'>
|
|
||||||
<DialogClose asChild>
|
|
||||||
<Button type='button' variant='secondary'>
|
|
||||||
Close
|
|
||||||
</Button>
|
|
||||||
</DialogClose>
|
|
||||||
</DialogFooter>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
@ -1 +0,0 @@
|
|||||||
export * from "./DownloadDialog";
|
|
||||||
@ -5,7 +5,6 @@ export * from "./Container";
|
|||||||
export * from "./CustomButtons";
|
export * from "./CustomButtons";
|
||||||
export * from "./CustomDialog";
|
export * from "./CustomDialog";
|
||||||
export * from "./DataTable";
|
export * from "./DataTable";
|
||||||
export * from "./DownloadDialog";
|
|
||||||
export * from "./EmptyState";
|
export * from "./EmptyState";
|
||||||
export * from "./ErrorOverlay";
|
export * from "./ErrorOverlay";
|
||||||
export * from "./Forms";
|
export * from "./Forms";
|
||||||
|
|||||||
@ -161,6 +161,18 @@
|
|||||||
"edit": {
|
"edit": {
|
||||||
"title": "Quote"
|
"title": "Quote"
|
||||||
},
|
},
|
||||||
|
"downloading_dialog": {
|
||||||
|
"title": "Downloading quote",
|
||||||
|
"description": "Please wait while your quotation is generated and downloaded in PDF format...",
|
||||||
|
"progress": {
|
||||||
|
"label": "Download is in {{status}}",
|
||||||
|
"status_in_progress": "in progress",
|
||||||
|
"status_stopped": "stopped",
|
||||||
|
"value_label": "Elapsed time in seconds {{elapsed}}"
|
||||||
|
},
|
||||||
|
"cancel_button": "Cancel the download",
|
||||||
|
"toast_success": "Quote downloaded"
|
||||||
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"draft": "Draft"
|
"draft": "Draft"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -158,6 +158,18 @@
|
|||||||
"edit": {
|
"edit": {
|
||||||
"title": "Cotización"
|
"title": "Cotización"
|
||||||
},
|
},
|
||||||
|
"downloading_dialog": {
|
||||||
|
"title": "Descargando cotización",
|
||||||
|
"description": "Espere mientras se genera la cotización y se descarga en formato PDF...",
|
||||||
|
"progress": {
|
||||||
|
"label": "La descarga está {{status}}",
|
||||||
|
"status_in_progress": "en marcha",
|
||||||
|
"status_stopped": "parada",
|
||||||
|
"value_label": "Elapsed time in seconds {{elapsed}}"
|
||||||
|
},
|
||||||
|
"cancel_button": "Cancelar la descarga",
|
||||||
|
"toast_success": "Quote downloaded"
|
||||||
|
},
|
||||||
"status": {
|
"status": {
|
||||||
"draft": "Borrador"
|
"draft": "Borrador"
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user