@acvl/frontend-components 0.0.34 → 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 = () => {
@@ -25777,7 +25777,7 @@ const typeSwitch = ({ base_object, base_key, response, submitData, useLabel, dat
25777
25777
  break;
25778
25778
  }
25779
25779
  };
25780
- const formParser = ({ type, submitData, data, useLabel, props, }) => {
25780
+ const formParser = ({ type, submitData, data, useLabel, props }) => {
25781
25781
  const t = type || "json";
25782
25782
  const response = t === "json" ? {} : new FormData();
25783
25783
  Object.entries(submitData).forEach(([key, value]) => {
@@ -25798,9 +25798,27 @@ const formParser = ({ type, submitData, data, useLabel, props, }) => {
25798
25798
  };
25799
25799
  // ==============================|| ERRORS ||============================== //
25800
25800
  const setErrors = (form, error) => {
25801
+ const iterateDeep = (obj) => {
25802
+ if (Array.isArray(obj.reason)) {
25803
+ if (obj.reason.every((item) => typeof item === "object" && item !== null && !Array.isArray(item))) {
25804
+ obj.reason.forEach((obj2, index) => {
25805
+ Object.entries(obj2).forEach(([key3, val3]) => {
25806
+ form.setError(`${obj.name}.${index}.${key3}`, { message: val3.join(", ") });
25807
+ });
25808
+ });
25809
+ }
25810
+ else {
25811
+ form.setError(obj.name, { message: obj.reason.join(", ") });
25812
+ }
25813
+ }
25814
+ else {
25815
+ form.setError(obj.name, { message: obj.reason });
25816
+ }
25817
+ };
25801
25818
  if ("invalid_params" in error.data) {
25802
25819
  Object.values(error.data.invalid_params).forEach((entry) => {
25803
- form.setError(entry.name, { message: entry.reason.join(", ") });
25820
+ iterateDeep(entry);
25821
+ // form.setError(entry.name, { message: entry.reason.join(", ") });
25804
25822
  });
25805
25823
  }
25806
25824
  };
@@ -26534,6 +26552,161 @@ const ControlledSlider = (props) => {
26534
26552
  } }));
26535
26553
  };
26536
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
+
26537
26710
  const DeleteConfirmationDialog = (props) => {
26538
26711
  const notifications = core.useNotifications();
26539
26712
  const { pathname } = reactRouterDom.useLocation();
@@ -27657,7 +27830,12 @@ const CreateGridWrapper = (props) => {
27657
27830
  }), jsxRuntime.jsxs(MenuItem, { onClick: () => {
27658
27831
  navigate(props.navigation ? `${props.navigation}crear` : `crear`);
27659
27832
  handleClose();
27660
- }, 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 })] }));
27661
27839
  };
27662
27840
 
27663
27841
  const Base = (props) => {
@@ -28109,12 +28287,11 @@ const EditToolbar = (props) => {
28109
28287
  const FieldArrayField = (props) => {
28110
28288
  const detail = React.useMemo(() => props.pageType === "detail", [props.pageType]);
28111
28289
  const { fields, append, remove, update } = reactHookForm.useFieldArray({
28112
- control: props.form.control,
28290
+ control: props.form?.control,
28113
28291
  name: props.name,
28114
28292
  keyName: "_id",
28115
28293
  });
28116
- // console.log(props.form?.watch(props.name));
28117
- // console.log(fields);
28294
+ const errors = props.form.formState.errors;
28118
28295
  const getIndex = React.useCallback((id) => lodash.findIndex(fields, function (field) {
28119
28296
  return field._id == id;
28120
28297
  }), [fields]);
@@ -28170,9 +28347,18 @@ const FieldArrayField = (props) => {
28170
28347
  },
28171
28348
  },
28172
28349
  getRowId: (row) => row._id,
28173
- getRowClassName: (params) => params.indexRelativeToCurrentPage % 2 === 0 ? "even" : "odd",
28350
+ getRowClassName: (params) => {
28351
+ const hasError = !!(errors &&
28352
+ props.name in errors &&
28353
+ errors[props.name][getIndex(params.row._id)]);
28354
+ return hasError
28355
+ ? "row-error"
28356
+ : params.indexRelativeToCurrentPage % 2 === 0
28357
+ ? "even"
28358
+ : "odd";
28359
+ },
28174
28360
  density: "compact",
28175
- onRowClick: props.pageType == "edit" ? handleRowClick : undefined,
28361
+ onRowClick: props.pageType != "detail" ? handleRowClick : undefined,
28176
28362
  }, props.dataGridProps);
28177
28363
  return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(MainDrawer, { open: drawer.open, drawerToggle: handleCancel, title: "Trailer", slots: {
28178
28364
  button: (jsxRuntime.jsx(SaveCancelButton, { slotProps: {
@@ -28730,67 +28916,70 @@ function themeTypography() {
28730
28916
  // ==============================|| PERSONALIZADO DE COMPONENTES DE MUI ||============================== //
28731
28917
  /**
28732
28918
  * Cambia el diseño default de ciertos componentes de Material UI
28733
- **/
28919
+ **/
28734
28920
  function componentStyleOverrides(theme) {
28735
28921
  return {
28736
28922
  MuiAlert: {
28737
28923
  defaultProps: {
28738
- variant: 'filled'
28924
+ variant: "filled",
28739
28925
  },
28740
28926
  },
28741
28927
  MuiListItemButton: {
28742
28928
  styleOverrides: {
28743
28929
  root: {
28744
- '&:hover': {
28930
+ "&:hover": {
28745
28931
  backgroundColor: `${theme.palette.primary.main} !important`,
28746
- '& .MuiTypography-root': {
28747
- color: 'white !important',
28932
+ "& .MuiTypography-root": {
28933
+ color: "white !important",
28748
28934
  },
28749
- '& .MuiSvgIcon-root': {
28750
- color: 'white !important'
28751
- }
28752
- }
28753
- }
28754
- }
28935
+ "& .MuiSvgIcon-root": {
28936
+ color: "white !important",
28937
+ },
28938
+ },
28939
+ },
28940
+ },
28755
28941
  },
28756
28942
  MuiDataGrid: {
28757
28943
  styleOverrides: {
28758
28944
  columnHeader: {
28759
- '& .MuiDataGrid-columnHeaderTitle': {
28760
- fontWeight: 'bold'
28945
+ "& .MuiDataGrid-columnHeaderTitle": {
28946
+ fontWeight: "bold",
28761
28947
  },
28762
- '&:focus': {
28763
- outline: 'none',
28948
+ "&:focus": {
28949
+ outline: "none",
28764
28950
  },
28765
28951
  },
28766
28952
  row: {
28953
+ [`&.row-error`]: {
28954
+ backgroundColor: colors.red[100],
28955
+ },
28767
28956
  [`&.even`]: {
28768
28957
  backgroundColor: colors.grey[50],
28769
28958
  },
28770
- '&:hover': {
28959
+ "&:hover": {
28771
28960
  backgroundColor: material.alpha(theme.palette.primary.main, 0.2),
28772
- '@media (hover: none)': {
28773
- backgroundColor: 'transparent',
28961
+ "@media (hover: none)": {
28962
+ backgroundColor: "transparent",
28774
28963
  },
28775
- }
28964
+ },
28776
28965
  },
28777
28966
  cell: {
28778
- '& .MuiOutlinedInput-notchedOutline': {
28779
- border: 'none',
28967
+ "& .MuiOutlinedInput-notchedOutline": {
28968
+ border: "none",
28780
28969
  },
28781
- '&.MuiDataGrid-cell--editing': {
28782
- backgroundColor: 'rgb(217 243 190)',
28783
- '& .MuiInputBase-root': {
28784
- height: '100%',
28970
+ "&.MuiDataGrid-cell--editing": {
28971
+ backgroundColor: "rgb(217 243 190)",
28972
+ "& .MuiInputBase-root": {
28973
+ height: "100%",
28785
28974
  },
28786
28975
  },
28787
- '& .Mui-error': {
28788
- backgroundColor: 'rgba(234,27,43,0.2)',
28789
- color: '#ef1a2b',
28790
- fontWeight: 'bold',
28976
+ "& .Mui-error": {
28977
+ backgroundColor: "rgba(234,27,43,0.2)",
28978
+ color: "#ef1a2b",
28979
+ fontWeight: "bold",
28791
28980
  },
28792
28981
  },
28793
- }
28982
+ },
28794
28983
  },
28795
28984
  };
28796
28985
  }
@@ -28855,6 +29044,7 @@ exports.ControlledToggleButtons = ControlledToggleButtons;
28855
29044
  exports.CoverPage = CoverPage;
28856
29045
  exports.CreateButtonBase = CreateButtonBase;
28857
29046
  exports.CreateButtonWithMenuOptions = CreateButtonWithMenuOptions;
29047
+ exports.CrudDropdown = CrudDropdown;
28858
29048
  exports.DeleteButton = DeleteButton;
28859
29049
  exports.DeleteConfirmationDialog = DeleteConfirmationDialog;
28860
29050
  exports.DetailPage = DetailPage;