En el filtro de la búsqueda del catálogo, poner filtros complejos compuestos por AND
This commit is contained in:
parent
560fe06a08
commit
53ea788142
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@uecko-presupuestador/client",
|
||||
"private": true,
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.8",
|
||||
"author": "Rodax Software <dev@rodax-software.com>",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Container, FormTextField } from "@/components";
|
||||
import { FormSubmitButton } from "@/components/Forms/FormSubmitButton";
|
||||
import { UeckoLogo } from "@/components/UeckoLogo/UeckoLogo";
|
||||
import { useLogin } from "@/lib/hooks";
|
||||
import { useIsLoggedIn, useLogin } from "@/lib/hooks";
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
@ -42,6 +42,9 @@ const languages = [
|
||||
|
||||
export const LoginPageWithLanguageSelector = () => {
|
||||
const { t, i18n } = useTranslation();
|
||||
|
||||
const { isSuccess: isLoggedInSuccess, data: { authenticated = false } = {} } = useIsLoggedIn();
|
||||
|
||||
const [language, setLanguage] = useState(i18n.language);
|
||||
const navigate = useNavigate();
|
||||
const { toast } = useToast();
|
||||
@ -54,6 +57,12 @@ export const LoginPageWithLanguageSelector = () => {
|
||||
}
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (isLoggedInSuccess && authenticated) {
|
||||
navigate("/quotes", { replace: true });
|
||||
}
|
||||
}, [isLoggedInSuccess, authenticated]);
|
||||
|
||||
const changeLanguage = (lng: string) => {
|
||||
i18n.changeLanguage(lng);
|
||||
setLanguage(lng);
|
||||
|
||||
@ -4,18 +4,16 @@ import { ButtonGroup } from "@/components";
|
||||
import { DataTableFilterField, useDataTableContext } from "@/lib/hooks";
|
||||
import { Badge, Button, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/ui";
|
||||
import { t } from "i18next";
|
||||
import { PlusIcon, XIcon } from "lucide-react";
|
||||
import { PlusIcon, SearchIcon, XIcon } from "lucide-react";
|
||||
import React from "react";
|
||||
|
||||
interface CatalogDataTableFilterProps<TData> extends React.HTMLAttributes<HTMLDivElement> {
|
||||
table: Table<TData>;
|
||||
filterFields?: DataTableFilterField<TData>[];
|
||||
fullWidthFilter?: boolean;
|
||||
}
|
||||
|
||||
export function CatalogDataTableFilter<TData>({
|
||||
table,
|
||||
fullWidthFilter,
|
||||
className,
|
||||
children,
|
||||
...props
|
||||
@ -54,9 +52,10 @@ export function CatalogDataTableFilter<TData>({
|
||||
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<div className='space-y-2'>
|
||||
<div className='relative p-2 border rounded-md border-input'>
|
||||
<div className='flex flex-wrap items-center gap-2'>
|
||||
<div className='w-full space-y-2'>
|
||||
<div className='relative flex items-center flex-1 p-2 space-x-2 border rounded-md border-input'>
|
||||
<SearchIcon className='w-4 h-4 text-gray-500' />
|
||||
<div className='flex flex-wrap items-center flex-1 gap-2'>
|
||||
{globalFilter &&
|
||||
globalFilter.map((filterTerm) => (
|
||||
<Badge
|
||||
@ -75,10 +74,10 @@ export function CatalogDataTableFilter<TData>({
|
||||
<XIcon className='w-4 h-4' />
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Quitar este término del filtro</p>
|
||||
<p>{t("catalog.filter.badget_remove_tooltip")}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<span className='sr-only'>Eliminar filtro {filterTerm}</span>
|
||||
<span className='sr-only'>{t("catalog.filter.badget_remove_tooltip")}</span>
|
||||
</Button>
|
||||
</Badge>
|
||||
))}
|
||||
@ -88,7 +87,7 @@ export function CatalogDataTableFilter<TData>({
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder='Escribe aquí para filtrar...'
|
||||
placeholder={t("common.filter.input_placeholder")}
|
||||
className='flex-1 w-full h-8 bg-transparent outline-none placeholder:text-muted-foreground'
|
||||
/>
|
||||
<ButtonGroup>
|
||||
@ -101,11 +100,11 @@ export function CatalogDataTableFilter<TData>({
|
||||
className='h-8 px-2 transition-all lg:px-3'
|
||||
>
|
||||
<XIcon className='w-4 h-4 mr-2' />
|
||||
{t("common.reset_filter")}
|
||||
{t("common.filter.reset_filter")}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Quitar todos los términos del filtro</p>
|
||||
<p>{t("common.filter.reset_filter")}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
)}
|
||||
@ -118,22 +117,18 @@ export function CatalogDataTableFilter<TData>({
|
||||
className='w-8 h-8 p-0 hover:bg-muted'
|
||||
>
|
||||
<PlusIcon className='w-4 h-4' />
|
||||
<span className='sr-only'>Añadir término al filtro</span>
|
||||
<span className='sr-only'>{t("common.filter.button_add_term")}</span>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Añadir término al filtro (o pulsa Enter)</p>
|
||||
<p>{t("common.filter.button_add_term_tooltip")}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className='text-sm text-muted-foreground'>
|
||||
Presiona Enter o haz clic en el botón + para añadir un término al filtro. Usa múltiples
|
||||
términos para una búsqueda más amplia.
|
||||
</p>
|
||||
<p className='text-sm text-muted-foreground'>{t("common.filter.help_text")}</p>
|
||||
</div>
|
||||
</TooltipProvider>
|
||||
);
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { DataTableSkeleton, ErrorOverlay, SimpleEmptyState } from "@/components";
|
||||
|
||||
import { CatalogDataTableFilter } from "@/app/catalog/components/CatalogDataTableFilter";
|
||||
import { useCatalogList } from "@/app/catalog/hooks";
|
||||
import { DataTable } from "@/components";
|
||||
import { DataTableToolbar } from "@/components/DataTable/DataTableToolbar";
|
||||
import { useDataTable, useDataTableContext } from "@/lib/hooks";
|
||||
import { Button } from "@/ui";
|
||||
import { IListArticles_Response_DTO, MoneyValue } from "@shared/contexts";
|
||||
@ -141,7 +141,7 @@ export const CatalogPickerDataTable = ({
|
||||
paginationOptions={{ visible: true, enablePageSizeSelector: false }}
|
||||
footerClassName='px-10 pt-2 border-t'
|
||||
>
|
||||
<DataTableToolbar fullWidthFilter={true} table={table} />
|
||||
<CatalogDataTableFilter table={table} />
|
||||
</DataTable>
|
||||
);
|
||||
};
|
||||
|
||||
@ -215,7 +215,6 @@ export const QuoteDetailsCardEditor = ({
|
||||
|
||||
const handleAppendCatalogArticle = useCallback(
|
||||
(article: any, quantity: number = 1) => {
|
||||
console.log(article);
|
||||
fieldActions.append({
|
||||
...article,
|
||||
quantity: {
|
||||
|
||||
@ -86,7 +86,6 @@ export default function SupportModal() {
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
console.log("handleClose", incidenceValue.trim());
|
||||
if (incidenceValue.trim()) {
|
||||
setShowConfirmDialog(true);
|
||||
} else {
|
||||
|
||||
@ -6,6 +6,7 @@ import { cn } from "@/lib/utils";
|
||||
import { Button, Input } from "@/ui";
|
||||
import { t } from "i18next";
|
||||
import { SearchIcon, XIcon } from "lucide-react";
|
||||
import { ChangeEvent } from "react";
|
||||
import { DataTableColumnOptions } from "./DataTableColumnOptions";
|
||||
|
||||
interface DataTableToolbarProps<TData> extends React.HTMLAttributes<HTMLDivElement> {
|
||||
@ -21,6 +22,15 @@ export function DataTableToolbar<TData>({
|
||||
}: DataTableToolbarProps<TData>) {
|
||||
const { globalFilter, isFiltered, setGlobalFilter, resetGlobalFilter } = useDataTableContext();
|
||||
|
||||
const handleOnChange = (event: ChangeEvent<HTMLInputElement>) => {
|
||||
const value = String(event.target.value);
|
||||
if (value === "") {
|
||||
resetGlobalFilter();
|
||||
} else {
|
||||
setGlobalFilter([value]);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
@ -33,9 +43,9 @@ export function DataTableToolbar<TData>({
|
||||
<SearchIcon className='w-4 h-4 text-gray-500' />
|
||||
<Input
|
||||
key='global-filter'
|
||||
placeholder={t("common.filter_placeholder")}
|
||||
placeholder={t("common.filter.input_placeholder")}
|
||||
value={globalFilter}
|
||||
onChange={(event) => setGlobalFilter(String(event.target.value))}
|
||||
onChange={handleOnChange}
|
||||
className={cn("h-8 w-full transition-all")}
|
||||
/>
|
||||
|
||||
@ -46,7 +56,7 @@ export function DataTableToolbar<TData>({
|
||||
className='h-8 px-2 transition-all lg:px-3'
|
||||
>
|
||||
<XIcon className='w-4 h-4 mr-2' />
|
||||
{t("common.reset_filter")}
|
||||
{t("common.filter.reset_filter")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -206,12 +206,6 @@ export function SortableDataTable({ columns, data, actions }: SortableDataTableP
|
||||
updateItem: (rowIndex: number, rowData: any, fieldName: string, value: unknown) => {
|
||||
// Skip page index reset until after next rerender
|
||||
// skipAutoResetPageIndex();
|
||||
console.log({
|
||||
rowIndex,
|
||||
rowData,
|
||||
fieldName,
|
||||
value,
|
||||
});
|
||||
|
||||
actions.update(rowIndex, { ...rowData, [`${fieldName}`]: value });
|
||||
},
|
||||
|
||||
@ -127,7 +127,7 @@ export const createAxiosDataProvider = (
|
||||
const formData = new FormData();
|
||||
formData.append(key || "file", file);
|
||||
|
||||
console.log(file);
|
||||
//console.log(file);
|
||||
|
||||
const response = await httpClient.post<R>(url, formData, {
|
||||
headers: {
|
||||
@ -181,7 +181,7 @@ export const createAxiosDataProvider = (
|
||||
throw new Error('"url" or "path" param is missing');
|
||||
}
|
||||
|
||||
console.log(apiUrl, path, url, requestUrl.toString());
|
||||
//console.log(apiUrl, path, url, requestUrl.toString());
|
||||
|
||||
// Preparar la respuesta personalizada
|
||||
let customResponse;
|
||||
|
||||
@ -153,7 +153,7 @@ export function useDataTable<TData, TValue>({
|
||||
const sortingUpdater: OnChangeFn<SortingState> = (updater) => {
|
||||
if (typeof updater === "function") {
|
||||
const newSorting = updater(sorting);
|
||||
console.log(newSorting);
|
||||
//console.log(newSorting);
|
||||
//setSorting(newSorting);
|
||||
}
|
||||
};
|
||||
|
||||
@ -35,7 +35,7 @@ export const UnsavedWarnProvider = ({ children }: PropsWithChildren) => {
|
||||
<CustomDialog
|
||||
//type='warning'
|
||||
onCancel={() => {
|
||||
console.log("onCancel");
|
||||
//console.log("onCancel");
|
||||
onCancel();
|
||||
}}
|
||||
onConfirm={() => onConfirm()}
|
||||
|
||||
@ -29,8 +29,6 @@
|
||||
"go_to_prev_page": "Go to previous page",
|
||||
"go_to_next_page": "Go to next page",
|
||||
"go_to_last_page": "Go to last page",
|
||||
"filter_placeholder": "Type here to filter...",
|
||||
"reset_filter": "Reset filter",
|
||||
"error": "Error",
|
||||
"actions": "Actions",
|
||||
"open_menu": "Open menu",
|
||||
@ -57,7 +55,16 @@
|
||||
"duplicate": "Duplicate",
|
||||
"print": "Print",
|
||||
"disable_preview": "Disable preview",
|
||||
"enable_preview": "Enable preview"
|
||||
"enable_preview": "Enable preview",
|
||||
"filter": {
|
||||
"reset_filter": "Reset filter",
|
||||
"badget_remove_tooltip": "Remove this filter term",
|
||||
"input_placeholder": "Type here to filter...",
|
||||
"button_add_term": "Add filter term",
|
||||
"button_add_term_tooltip": "Add filter term (or press Enter)",
|
||||
"button_remove_all": "Remove all terms from filter",
|
||||
"help_text": "Press Enter or click the + button to add a term to the filter. Use multiple terms for a broader search."
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"loading_indicator": {
|
||||
|
||||
@ -29,8 +29,6 @@
|
||||
"go_to_prev_page": "Ir a la página anterior",
|
||||
"go_to_next_page": "Ir a la página siguiente",
|
||||
"go_to_last_page": "Ir a la última página",
|
||||
"filter_placeholder": "Escribe aquí para filtrar...",
|
||||
"reset_filter": "Quitar el filtro",
|
||||
"error": "Error",
|
||||
"actions": "Acciones",
|
||||
"open_menu": "Abrir el menú",
|
||||
@ -57,7 +55,16 @@
|
||||
"duplicate": "Duplicar",
|
||||
"print": "Imprimir",
|
||||
"disable_preview": "Ocultar vista previa",
|
||||
"enable_preview": "Mostrar vista previa"
|
||||
"enable_preview": "Mostrar vista previa",
|
||||
"filter": {
|
||||
"reset_filter": "Quitar el filtro",
|
||||
"badget_remove_tooltip": "Quitar este término del filtro",
|
||||
"input_placeholder": "Escribe aquí para filtrar...",
|
||||
"button_add_term": "Añadir término al filtro",
|
||||
"button_add_term_tooltip": "Añadir término al filtro (o pulsa Enter)",
|
||||
"button_remove_all": "Quitar todos los términos del filtro",
|
||||
"help_text": "Presiona Enter o haz clic en el botón + para añadir un término al filtro. Usa múltiples términos para una búsqueda más amplia."
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"LoadingIndicator": {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "uecko-presupuestador",
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.8",
|
||||
"author": "Rodax Software <dev@rodax-software.com>",
|
||||
"license": "ISC",
|
||||
"private": true,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@uecko-presupuestador/server",
|
||||
"private": true,
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.8",
|
||||
"author": "Rodax Software <dev@rodax-software.com>",
|
||||
"main": "./src/index.ts",
|
||||
"scripts": {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@uecko-presupuestador/shared",
|
||||
"private": false,
|
||||
"version": "1.0.6",
|
||||
"version": "1.0.8",
|
||||
"main": "./index.ts",
|
||||
"author": "Rodax Software <dev@rodax-software.com>",
|
||||
"license": "ISC",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user