Presupuestador_web/client/src/app/quotes/list.tsx

158 lines
5.3 KiB
TypeScript
Raw Normal View History

2024-06-29 19:39:25 +00:00
import { DataTableProvider } from "@/lib/hooks";
import { Trans } from "react-i18next";
import { QuotesDataTable } from "./components";
2024-06-09 20:22:22 +00:00
2024-09-23 15:56:15 +00:00
import { HelpButton } from "@/components";
2024-09-16 09:13:06 +00:00
import {
Button,
2024-09-23 15:56:15 +00:00
Label,
ScrollArea,
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
2024-09-16 09:13:06 +00:00
Tabs,
TabsContent,
TabsList,
TabsTrigger,
Toggle,
} from "@/ui";
2024-08-20 11:44:04 +00:00
import { useToggle } from "@wojtekmaj/react-hooks";
2024-07-03 18:05:26 +00:00
import { t } from "i18next";
2024-09-23 15:56:15 +00:00
import { EyeIcon, EyeOffIcon, PlusIcon } from "lucide-react";
import { useState } from "react";
2024-07-01 17:12:15 +00:00
import { useNavigate } from "react-router-dom";
export const QuotesList = () => {
const navigate = useNavigate();
2024-09-23 15:56:15 +00:00
const [status, setStatus] = useState("all");
2024-08-26 18:29:41 +00:00
const [enabledPreview, toggleEnabledPreview] = useToggle(true);
2024-07-01 17:12:15 +00:00
2024-09-23 15:56:15 +00:00
const quoteStatuses = [
{ value: "all", label: t("quotes.list.tabs.all") },
{ value: "draft", label: t("quotes.list.tabs.draft") },
{ value: "ready", label: t("quotes.list.tabs.ready") },
{ value: "delivered", label: t("quotes.list.tabs.delivered") },
{ value: "accepted", label: t("quotes.list.tabs.delivered") },
{ value: "rejected", label: t("quotes.list.tabs.rejected") },
{ value: "archived", label: t("quotes.list.tabs.archived") },
];
2024-07-01 17:12:15 +00:00
return (
<DataTableProvider>
<div className='flex items-center justify-between space-y-2'>
<div>
<h2 className='text-2xl font-bold tracking-tight'>
<Trans i18nKey='quotes.list.title' />
</h2>
2024-07-11 18:31:01 +00:00
<p className='text-muted-foreground'>
<Trans i18nKey='quotes.list.subtitle' />
</p>
2024-07-01 17:12:15 +00:00
</div>
2024-07-03 18:05:26 +00:00
<div className='flex items-center space-x-2'>
2024-08-24 09:32:52 +00:00
<Button onClick={() => navigate("/quotes/add")}>
<PlusIcon className='w-4 h-4 mr-2' />
{t("quotes.create.title")}
</Button>
2024-07-03 18:05:26 +00:00
</div>
2024-07-01 17:12:15 +00:00
</div>
2024-09-23 15:56:15 +00:00
<Tabs value={status} onValueChange={setStatus}>
<div className='flex flex-col items-start justify-between mb-4 sm:flex-row sm:items-center'>
<div className='w-full mb-4 sm:w-auto sm:mb-0'>
<TabsList className='hidden sm:flex'>
{quoteStatuses.map((s) => (
<TabsTrigger key={s.value} value={s.value}>
{s.label}
</TabsTrigger>
))}
</TabsList>
<div className='flex items-center w-full space-x-2 sm:hidden'>
<Label>{t("quotes.list.tabs_title")}</Label>
<Select value={status} onValueChange={setStatus}>
<SelectTrigger>
<SelectValue placeholder='Seleccionar estado' />
</SelectTrigger>
<SelectContent>
{quoteStatuses.map((s) => (
<SelectItem key={s.value} value={s.value}>
{s.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
2024-09-16 17:31:41 +00:00
<div className='flex items-baseline justify-center mr-4 font-medium'>
2024-09-23 15:56:15 +00:00
<HelpButton
buttonText='Ayuda'
title='Ayuda sobre el Estado de Cotizaciones'
content={HelpContent}
/>
2024-09-16 09:13:06 +00:00
</div>
2024-08-20 11:44:04 +00:00
<div className='flex items-center gap-2 ml-auto'>
<Toggle
aria-label='Show quote preview'
variant={"outline"}
defaultPressed={false}
pressed={enabledPreview}
onPressedChange={toggleEnabledPreview}
>
2024-08-26 13:58:31 +00:00
{enabledPreview ? (
<>
<EyeOffIcon className='w-4 h-4 mr-2' />
{t("common.disable_preview")}
</>
) : (
<>
<EyeIcon className='w-4 h-4 mr-2' />
{t("common.enable_preview")}
</>
)}
2024-08-20 11:44:04 +00:00
</Toggle>
</div>
2024-07-11 18:31:01 +00:00
</div>
2024-09-23 15:56:15 +00:00
{quoteStatuses.map((s) => (
<TabsContent key={s.value} value={s.value}>
<QuotesDataTable status={s.value} preview={enabledPreview} />
</TabsContent>
))}
2024-07-11 18:31:01 +00:00
</Tabs>
2024-07-01 17:12:15 +00:00
</DataTableProvider>
);
};
2024-09-23 15:56:15 +00:00
const HelpContent = (
<ScrollArea className='grid gap-4 py-4'>
<p>El estado de una cotización indica su posición actual en el proceso de negocio.</p>
<p>Los estados posibles son:</p>
<ul className='pl-6 space-y-2 list-disc'>
<li>
<strong>Borrador:</strong> La cotización está en proceso de creación o edición.
</li>
<li>
<strong>Preparado:</strong> La cotización está lista para ser enviada al cliente.
</li>
<li>
<strong>Entregado:</strong> La cotización ha sido enviada al cliente.
</li>
<li>
<strong>Aceptado:</strong> El cliente ha aprobado la cotización.
</li>
<li>
<strong>Rechazado:</strong> El cliente no ha aceptado la cotización.
</li>
<li>
<strong>Arcivado:</strong> La cotización ha sido guardada para referencia futura y ya no
está activa.
</li>
</ul>
<p>
Utiliza estos estados para hacer un seguimiento eficiente de tus cotizaciones y optimizar tu
proceso de ventas. El estado <strong>Archivado</strong> es útil para mantener un historial de
cotizaciones pasadas sin que interfieran con las cotizaciones activas.
</p>
</ScrollArea>
);