@acvl/frontend-components 0.0.35 → 0.0.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cjs/index.js CHANGED
@@ -69,8 +69,8 @@ var iconsMaterial = require('@mui/icons-material');
69
69
  var merge$1 = require('lodash/merge');
70
70
  var UploadFileIcon = require('@mui/icons-material/UploadFile');
71
71
  var ClearIcon$1 = require('@mui/icons-material/Clear');
72
- var SaveIcon = require('@mui/icons-material/Save');
73
72
  var AddIcon = require('@mui/icons-material/Add');
73
+ var SaveIcon = require('@mui/icons-material/Save');
74
74
  var KeyboardArrowDownIcon = require('@mui/icons-material/KeyboardArrowDown');
75
75
  var LinearProgress = require('@mui/material/LinearProgress');
76
76
  var AttachFileIcon = require('@mui/icons-material/AttachFile');
@@ -25514,8 +25514,8 @@ const useHasPermission = (path) => {
25514
25514
  };
25515
25515
 
25516
25516
  const APIContext = React.createContext(null);
25517
- const APIProvider = ({ children, hooks }) => {
25518
- return (jsxRuntime.jsx(APIContext.Provider, { value: hooks, children: children }));
25517
+ const APIProvider = ({ children, hooks, }) => {
25518
+ return jsxRuntime.jsx(APIContext.Provider, { value: hooks, children: children });
25519
25519
  };
25520
25520
 
25521
25521
  const useAPI = () => {
@@ -26552,6 +26552,161 @@ const ControlledSlider = (props) => {
26552
26552
  } }));
26553
26553
  };
26554
26554
 
26555
+ const CREATE_OPTION = { value: "__create__", label: "" };
26556
+ const CrudDropdown = (props) => {
26557
+ const { name, label, control, fieldProps, extraProps: { queryArgs, crudExtraArgs = {}, labelField = "nombre", disableHT }, } = props;
26558
+ const [inputValue, setInputValue] = React.useState("");
26559
+ const [options, setOptions] = React.useState([]);
26560
+ const [open, setOpen] = React.useState(false);
26561
+ const [createOpen, setCreateOpen] = React.useState(false);
26562
+ const [editOpen, setEditOpen] = React.useState(false);
26563
+ const [deleteOpen, setDeleteOpen] = React.useState(false);
26564
+ const [activeOption, setActiveOption] = React.useState(null);
26565
+ const [dialogInput, setDialogInput] = React.useState("");
26566
+ const formValueRef = React.useRef(null);
26567
+ const formOnChangeRef = React.useRef(() => { });
26568
+ const api = useAPI();
26569
+ const [getOpciones, { isLoading, isFetching, isError }] = api.useLazyGetComoOpcionesQuery();
26570
+ const [genericCrud, { isLoading: isMutating }] = api.useGenericCrudMutation();
26571
+ const notifications = core.useNotifications();
26572
+ const args = React.useMemo(() => ({
26573
+ ...queryArgs,
26574
+ filters: { ...queryArgs.filters, nombre__icontains: inputValue },
26575
+ }), [inputValue, queryArgs]);
26576
+ const fetchOptions = React.useCallback(lodash.debounce((fetchArgs, cb) => {
26577
+ setOptions([]);
26578
+ getOpciones(fetchArgs)
26579
+ .unwrap()
26580
+ .then(cb)
26581
+ .catch(() => { });
26582
+ }, 500), []);
26583
+ const refreshOptions = () => {
26584
+ getOpciones(args, false)
26585
+ .unwrap()
26586
+ .then((fresh) => setOptions(fresh))
26587
+ .catch(() => { });
26588
+ };
26589
+ React.useEffect(() => {
26590
+ if (open)
26591
+ fetchOptions(args, setOptions);
26592
+ }, [args, fetchOptions, open]);
26593
+ const handleCreate = () => {
26594
+ genericCrud({
26595
+ endpoint: props.extraProps.queryArgs.endpoint,
26596
+ method: "POST",
26597
+ body: { [labelField]: dialogInput, ...crudExtraArgs },
26598
+ })
26599
+ .unwrap()
26600
+ .then(() => {
26601
+ notifications.show("Opción creada.", { severity: "success" });
26602
+ setCreateOpen(false);
26603
+ setDialogInput("");
26604
+ refreshOptions();
26605
+ })
26606
+ .catch(() => notifications.show("Error al crear.", { severity: "error" }));
26607
+ };
26608
+ const handleEdit = () => {
26609
+ if (!activeOption)
26610
+ return;
26611
+ genericCrud({
26612
+ endpoint: props.extraProps.queryArgs.endpoint,
26613
+ method: "PATCH",
26614
+ id: activeOption.value,
26615
+ body: { [labelField]: dialogInput, ...crudExtraArgs },
26616
+ })
26617
+ .unwrap()
26618
+ .then(() => {
26619
+ if (formValueRef.current?.value === activeOption.value) {
26620
+ formOnChangeRef.current({ value: activeOption.value, label: dialogInput });
26621
+ }
26622
+ notifications.show("Opción actualizada.", { severity: "success" });
26623
+ setEditOpen(false);
26624
+ setDialogInput("");
26625
+ setActiveOption(null);
26626
+ refreshOptions();
26627
+ })
26628
+ .catch(() => notifications.show("Error al actualizar.", { severity: "error" }));
26629
+ };
26630
+ const handleDelete = () => {
26631
+ if (!activeOption)
26632
+ return;
26633
+ genericCrud({
26634
+ endpoint: props.extraProps.queryArgs.endpoint,
26635
+ method: "DELETE",
26636
+ id: activeOption.value,
26637
+ })
26638
+ .unwrap()
26639
+ .then(() => {
26640
+ if (formValueRef.current?.value === activeOption.value) {
26641
+ formOnChangeRef.current(null);
26642
+ }
26643
+ notifications.show("Opción eliminada.", { severity: "success" });
26644
+ setDeleteOpen(false);
26645
+ setActiveOption(null);
26646
+ refreshOptions();
26647
+ })
26648
+ .catch(() => notifications.show("Error al eliminar.", { severity: "error" }));
26649
+ };
26650
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(reactHookForm.Controller, { name: name, control: control, render: ({ field: { value, onChange }, fieldState: { error } }) => {
26651
+ formValueRef.current = value;
26652
+ formOnChangeRef.current = onChange;
26653
+ const handleChange = (_event, newValue) => {
26654
+ if (newValue?.value === "__create__") {
26655
+ setDialogInput("");
26656
+ setCreateOpen(true);
26657
+ return;
26658
+ }
26659
+ onChange(newValue);
26660
+ };
26661
+ return (jsxRuntime.jsx(material.Autocomplete, { id: name, open: open, onOpen: () => setOpen(true), onClose: () => setOpen(false), options: options, loading: isLoading || isFetching, value: value, onChange: handleChange, inputValue: inputValue, onInputChange: (_event, newInputValue) => setInputValue(newInputValue), isOptionEqualToValue: (option, val) => option.value === val.value, filterOptions: (x) => [CREATE_OPTION, ...x], getOptionLabel: (option) => option.value === "__create__" ? "" : option.label || "", fullWidth: true, size: "small", disabled: isError, renderOption: (optionProps, option) => {
26662
+ const { key, ...rest } = optionProps;
26663
+ if (option.value === "__create__") {
26664
+ return (jsxRuntime.jsxs(material.Box, { component: "li", ...rest, onClick: () => {
26665
+ setDialogInput("");
26666
+ setCreateOpen(true);
26667
+ }, sx: {
26668
+ justifyContent: "center !important",
26669
+ color: "primary.main",
26670
+ borderBottom: "1px solid",
26671
+ borderColor: "divider",
26672
+ py: "6px !important",
26673
+ gap: 0.5,
26674
+ }, children: [jsxRuntime.jsx(AddIcon, { fontSize: "small" }), jsxRuntime.jsx(material.Typography, { variant: "body2", children: "Agregar nuevo" })] }, key));
26675
+ }
26676
+ return (jsxRuntime.jsxs(material.Box, { component: "li", ...rest, sx: {
26677
+ display: "flex",
26678
+ alignItems: "center",
26679
+ pr: "4px !important",
26680
+ }, children: [jsxRuntime.jsx(material.Box, { sx: {
26681
+ flex: 1,
26682
+ overflow: "hidden",
26683
+ textOverflow: "ellipsis",
26684
+ }, children: option.label }), jsxRuntime.jsx(material.IconButton, { size: "small", tabIndex: -1, onMouseDown: (e) => {
26685
+ e.stopPropagation();
26686
+ e.preventDefault();
26687
+ }, onClick: (e) => {
26688
+ e.stopPropagation();
26689
+ setActiveOption(option);
26690
+ setDialogInput(option.label);
26691
+ setEditOpen(true);
26692
+ }, children: jsxRuntime.jsx(EditIcon, { fontSize: "inherit" }) }), jsxRuntime.jsx(material.IconButton, { size: "small", tabIndex: -1, onMouseDown: (e) => {
26693
+ e.stopPropagation();
26694
+ e.preventDefault();
26695
+ }, onClick: (e) => {
26696
+ e.stopPropagation();
26697
+ setActiveOption(option);
26698
+ setDeleteOpen(true);
26699
+ }, children: jsxRuntime.jsx(DeleteIcon, { fontSize: "inherit" }) })] }, key));
26700
+ }, renderInput: (params) => (jsxRuntime.jsx(material.TextField, { ...params, label: label, error: !!error, helperText: error ? error.message : disableHT ? "" : " ", slotProps: {
26701
+ input: {
26702
+ ...params.InputProps,
26703
+ endAdornment: (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [isLoading || isFetching ? (jsxRuntime.jsx(material.CircularProgress, { color: "inherit", size: 20 })) : null, params.InputProps.endAdornment] })),
26704
+ },
26705
+ } })), ...fieldProps }));
26706
+ } }), jsxRuntime.jsxs(material.Dialog, { open: createOpen, onClose: () => setCreateOpen(false), maxWidth: "xs", fullWidth: true, children: [jsxRuntime.jsx(material.DialogTitle, { children: "Agregar opci\u00F3n" }), jsxRuntime.jsx(material.DialogContent, { children: jsxRuntime.jsx(material.TextField, { autoFocus: true, fullWidth: true, size: "small", label: label, value: dialogInput, onChange: (e) => setDialogInput(e.target.value), onKeyDown: (e) => e.key === "Enter" && !!dialogInput && handleCreate(), sx: { mt: 1 } }) }), jsxRuntime.jsxs(material.DialogActions, { children: [jsxRuntime.jsx(material.Button, { color: "error", onClick: () => setCreateOpen(false), children: "Cancelar" }), jsxRuntime.jsx(material.Button, { color: "secondary", disabled: !dialogInput, loading: isMutating, onClick: handleCreate, children: "Guardar" })] })] }), jsxRuntime.jsxs(material.Dialog, { open: editOpen, onClose: () => setEditOpen(false), maxWidth: "xs", fullWidth: true, children: [jsxRuntime.jsx(material.DialogTitle, { children: "Editar opci\u00F3n" }), jsxRuntime.jsx(material.DialogContent, { children: jsxRuntime.jsx(material.TextField, { autoFocus: true, fullWidth: true, size: "small", label: label, value: dialogInput, onChange: (e) => setDialogInput(e.target.value), onKeyDown: (e) => e.key === "Enter" && !!dialogInput && handleEdit(), sx: { mt: 1 } }) }), jsxRuntime.jsxs(material.DialogActions, { children: [jsxRuntime.jsx(material.Button, { color: "error", onClick: () => setEditOpen(false), children: "Cancelar" }), jsxRuntime.jsx(material.Button, { color: "secondary", disabled: !dialogInput, loading: isMutating, onClick: handleEdit, children: "Guardar" })] })] }), jsxRuntime.jsxs(material.Dialog, { open: deleteOpen, onClose: () => setDeleteOpen(false), maxWidth: "xs", fullWidth: true, children: [jsxRuntime.jsx(material.DialogTitle, { children: "Eliminar opci\u00F3n" }), jsxRuntime.jsx(material.DialogContent, { children: jsxRuntime.jsxs(material.Typography, { children: ["\u00BFEliminar ", jsxRuntime.jsx("strong", { children: activeOption?.label }), "?"] }) }), jsxRuntime.jsxs(material.DialogActions, { children: [jsxRuntime.jsx(material.Button, { onClick: () => setDeleteOpen(false), children: "Cancelar" }), jsxRuntime.jsx(material.Button, { color: "error", loading: isMutating, onClick: handleDelete, children: "Eliminar" })] })] })] }));
26707
+ };
26708
+ CrudDropdown.displayName = "CrudDropdown";
26709
+
26555
26710
  const DeleteConfirmationDialog = (props) => {
26556
26711
  const notifications = core.useNotifications();
26557
26712
  const { pathname } = reactRouterDom.useLocation();
@@ -27675,7 +27830,12 @@ const CreateGridWrapper = (props) => {
27675
27830
  }), jsxRuntime.jsxs(MenuItem, { onClick: () => {
27676
27831
  navigate(props.navigation ? `${props.navigation}crear` : `crear`);
27677
27832
  handleClose();
27678
- }, disableRipple: true, children: [jsxRuntime.jsx(material.ListItemIcon, { children: jsxRuntime.jsx(DrawIcon, {}) }), "Manual"] })] }), props.csv_upload?.enable && (jsxRuntime.jsx(CSVUpload, { open: csv.open, drawerToggle: handleToggleClose, data: csv.data })), props.renderFunction({ dataGridProps: createGridProps })] }));
27833
+ }, disableRipple: true, children: [jsxRuntime.jsx(material.ListItemIcon, { children: jsxRuntime.jsx(DrawIcon, {}) }), "Manual"] }), props.extraOptions?.map((option, index) => {
27834
+ return (jsxRuntime.jsxs(MenuItem, { onClick: () => {
27835
+ option.onClick();
27836
+ handleClose();
27837
+ }, disableRipple: true, children: [jsxRuntime.jsx(material.ListItemIcon, { children: option.icon }), option.title] }, index));
27838
+ })] }), props.csv_upload?.enable && (jsxRuntime.jsx(CSVUpload, { open: csv.open, drawerToggle: handleToggleClose, data: csv.data })), props.renderFunction({ dataGridProps: createGridProps })] }));
27679
27839
  };
27680
27840
 
27681
27841
  const Base = (props) => {
@@ -28884,6 +29044,7 @@ exports.ControlledToggleButtons = ControlledToggleButtons;
28884
29044
  exports.CoverPage = CoverPage;
28885
29045
  exports.CreateButtonBase = CreateButtonBase;
28886
29046
  exports.CreateButtonWithMenuOptions = CreateButtonWithMenuOptions;
29047
+ exports.CrudDropdown = CrudDropdown;
28887
29048
  exports.DeleteButton = DeleteButton;
28888
29049
  exports.DeleteConfirmationDialog = DeleteConfirmationDialog;
28889
29050
  exports.DetailPage = DetailPage;