diff --git a/client/src/app/quotes/components/QuoteResume.tsx b/client/src/app/quotes/components/QuoteResume.tsx index bec72e4..d6534b2 100644 --- a/client/src/app/quotes/components/QuoteResume.tsx +++ b/client/src/app/quotes/components/QuoteResume.tsx @@ -1,6 +1,6 @@ -import { DownloadIcon, FilePenLineIcon } from "lucide-react"; +import { ArchiveIcon, CopyIcon, DownloadIcon, EditIcon } from "lucide-react"; -import { QuoteStatusBadge } from "@/components"; +import { ButtonGroup } from "@/components"; import { useCustomLocalization } from "@/lib/hooks"; import { cn } from "@/lib/utils"; import { @@ -38,10 +38,12 @@ export const QuoteResume = ({ quoteId, className }: QuoteResumeProps) => { const navigate = useNavigate(); const { toast } = useToast(); - const { useOne, useSetStatus, useSentTo, useDownloader, getQuotePDFFilename } = useQuotes(); + const { useOne, useSetStatus, useSentTo, useDownloader, useDuplicate, getQuotePDFFilename } = + useQuotes(); const { data, status } = useOne(quoteId); const { mutate: setStatusMutation } = useSetStatus(); const { mutate: sentToMutation } = useSentTo(quoteId); + const { mutate: duplicate } = useDuplicate(); const { download, ...downloadProps } = useDownloader(); const { formatCurrency, formatNumber } = useCustomLocalization({ @@ -78,7 +80,7 @@ export const QuoteResume = ({ quoteId, className }: QuoteResumeProps) => { }, [data]); const allowToSent = useMemo(() => data?.status === "accepted" && !data?.date_sent, [data]); - const isSent = useMemo(() => data?.status === "accepted" && data?.date_sent, [data]); + const isSent = useMemo(() => data?.status === "accepted" && !!data?.date_sent, [data]); const handleOnChangeStatus = (newStatus: string) => { setStatusMutation( @@ -88,6 +90,7 @@ export const QuoteResume = ({ quoteId, className }: QuoteResumeProps) => { onSuccess: () => { toast({ description: t("quotes.quote_status_editor.toast_status_changed"), + variant: "success", }); }, } @@ -101,6 +104,7 @@ export const QuoteResume = ({ quoteId, className }: QuoteResumeProps) => { onSuccess: () => { toast({ description: t("quotes.quote_sent_to_editor.toast_status_changed"), + variant: "success", }); }, } @@ -110,6 +114,7 @@ export const QuoteResume = ({ quoteId, className }: QuoteResumeProps) => { const handleFinishDownload = useCallback(() => { toast({ description: t("quotes.downloading_dialog.toast_success"), + variant: "success", }); }, [toast]); @@ -135,6 +140,41 @@ export const QuoteResume = ({ quoteId, className }: QuoteResumeProps) => { ); } + const handleDuplicateQuote = (id: string) => { + duplicate( + { + id, + }, + { + onSuccess(data) { + toast({ + description: t("quotes.duplicate_action.toast_success"), + variant: "success", + }); + + navigate(`/quotes/edit/${data.id}`, { relative: "path" }); + }, + } + ); + }; + + const handleArchiveQuote = (id: string) => { + setStatusMutation( + { id, newStatus: "archived" }, + + { + onSuccess: () => { + toast({ + description: t("quotes.quote_status_editor.toast_status_changed", { + newStatus: t("quotes.status.archived"), + }), + variant: "success", + }); + }, + } + ); + }; + return ( <> @@ -143,74 +183,94 @@ export const QuoteResume = ({ quoteId, className }: QuoteResumeProps) => { {t("quotes.list.resume.title")} - + -
-
- {allowToSent && !isSent && ( - <> - - - - )} +
+
+ + + + + + +

Editar

+
+
- {!isSent && ( - <> - + + + + + +

Duplicar

+
+
- - - )} + + + + + +

Descargar

+
+
- - - - - {t("quotes.list.resume.download_quote")} - + + + + + +

Archivar

+
+
+
- {/* - - - - - - {t("common.more")} - - - - - - {t("quotes.list.preview.download_quote")} - - - */} + + +
diff --git a/client/src/app/quotes/components/QuotesDataTable.tsx b/client/src/app/quotes/components/QuotesDataTable.tsx index ea48f7f..07567cd 100644 --- a/client/src/app/quotes/components/QuotesDataTable.tsx +++ b/client/src/app/quotes/components/QuotesDataTable.tsx @@ -19,7 +19,7 @@ import { useNavigate } from "react-router-dom"; import { useQuotes } from "../hooks"; import { DownloadQuoteDialog } from "./DownloadQuoteDialog"; import { QuoteResume } from "./QuoteResume"; -import { QuoteStatusEditor } from "./editors"; +import { QuoteSentToEditor, QuoteStatusEditor } from "./editors"; export const QuotesDataTable = ({ status = "all", @@ -89,6 +89,23 @@ export const QuotesDataTable = ({ ); }; + const handleArchiveQuote = (id: string) => { + setStatusMutation( + { id, newStatus: "archived" }, + + { + onSuccess: () => { + toast({ + description: t("quotes.quote_status_editor.toast_status_changed", { + newStatus: t("quotes.status.archived"), + }), + variant: "success", + }); + }, + } + ); + }; + const handleOnChangeStatus = (id: string, newStatus: string) => { setStatusMutation( { id, newStatus }, @@ -148,9 +165,7 @@ export const QuotesDataTable = ({ - handleOnChangeStatus(original.id, newStatus) - } + onChangeStatus={(newStatus: string) => handleOnChangeStatus(original.id, newStatus)} /> ), }, @@ -162,12 +177,17 @@ export const QuotesDataTable = ({ ), cell: ({ row: { original } }: { row: { original: IListQuotes_Response_DTO } }) => { const quoteDate = UTCDateValue.create(original.date_sent); + const isSuccess = quoteDate.isSuccess && !quoteDate.object.isEmpty(); + return (
- {quoteDate.isSuccess ? ( - + {isSuccess ? ( + ) : ( - <>- + <> )}
); @@ -217,7 +237,7 @@ export const QuotesDataTable = ({ })}
), - size: 600, + size: 500, }, /*{ @@ -240,86 +260,96 @@ export const QuotesDataTable = ({ cell: ({ row: { original } }: { row: { original: IListQuotes_Response_DTO } }) => { const allowToSent = original?.status === "accepted" && !original?.date_sent; const isSent = original?.status === "accepted" && !!original?.date_sent; + const isArchived = original?.status === "archived"; return ( - - - - - - -

Editar

-
-
+
+ + + + + + +

Editar

+
+
- - - - - -

Duplicar

-
-
+ + + + + +

Duplicar

+
+
- - - - - -

Descargar

-
-
+ + + + + +

Descargar

+
+
- - - - - -

Archivar

-
-
-
+ + + + + +

Archivar

+
+
+ + + null} + disabled={isSent || !allowToSent} + /> + +
); }, }, diff --git a/client/src/app/quotes/components/editors/QuoteSentToEditor.tsx b/client/src/app/quotes/components/editors/QuoteSentToEditor.tsx index 3d67fd2..efee0bb 100644 --- a/client/src/app/quotes/components/editors/QuoteSentToEditor.tsx +++ b/client/src/app/quotes/components/editors/QuoteSentToEditor.tsx @@ -10,26 +10,30 @@ import { AlertDialogTrigger, Button, } from "@/ui"; -import { IGetQuote_Response_DTO } from "@shared/contexts"; import { t } from "i18next"; import { SendIcon } from "lucide-react"; export const QuoteSentToEditor = ({ - quote, + id, onSentTo, + disabled, }: { - quote: IGetQuote_Response_DTO; + id: string; onSentTo: (quoteId: string) => void; + disabled?: boolean; }) => { const handleSentTo = () => { - onSentTo(quote.id); + onSentTo(id); }; return ( - - diff --git a/client/src/components/ColorBadget/ColorBadget.tsx b/client/src/components/ColorBadget/ColorBadget.tsx index 8f9c440..c8d42fd 100644 --- a/client/src/components/ColorBadget/ColorBadget.tsx +++ b/client/src/components/ColorBadget/ColorBadget.tsx @@ -50,7 +50,7 @@ export const ColorBadge = ({ label, className }: ColorBadgeProps) => { const [color, backgroundColor] = stringToColorPair(label); return ( - + {label} );