@amirjalili1374/ui-kit 1.3.22 → 1.3.23

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/ui-kit.es.js CHANGED
@@ -1,4 +1,4 @@
1
- import { capitalize, reactive, watchEffect, toRef, shallowRef, Fragment, camelize, isVNode, Comment, unref, warn, getCurrentInstance as getCurrentInstance$1, ref, computed, provide, inject, defineComponent as defineComponent$1, h, createElementVNode, normalizeStyle, normalizeClass, toValue, resolveDynamicComponent, nextTick, onScopeDispose, createVNode, mergeProps, toRefs, Text, isRef, TransitionGroup, Transition, watch, onBeforeMount, onBeforeUnmount, withDirectives, vShow, toDisplayString, effectScope, toRaw, readonly, createBlock, openBlock, withCtx, createCommentVNode, useId, onMounted, onUpdated, Teleport, createTextVNode, createElementBlock, renderSlot, onDeactivated, cloneVNode, renderList, createSlots, normalizeProps, guardReactiveProps, resolveComponent, onActivated, onBeforeUpdate, withModifiers, withKeys, vModelText, onUnmounted } from "vue";
1
+ import { capitalize, reactive, watchEffect, toRef, shallowRef, Fragment, camelize, isVNode, Comment, unref, warn, getCurrentInstance as getCurrentInstance$1, ref, computed, provide, inject, defineComponent as defineComponent$1, h, createElementVNode, normalizeStyle, normalizeClass, toValue, resolveDynamicComponent, nextTick, onScopeDispose, createVNode, mergeProps, toRefs, Text, isRef, TransitionGroup, Transition, watch, onBeforeMount, onBeforeUnmount, withDirectives, vShow, toDisplayString, effectScope, toRaw, readonly, createBlock, openBlock, withCtx, createCommentVNode, useId, onMounted, onUpdated, Teleport, createTextVNode, createElementBlock, renderSlot, onDeactivated, cloneVNode, renderList, createSlots, normalizeProps, guardReactiveProps, resolveComponent, onActivated, onBeforeUpdate, withModifiers, vModelText, withKeys, onUnmounted } from "vue";
2
2
  import { IconHome, IconArrowBadgeLeft, IconChevronDown, IconChevronRight, IconMinus, IconPlus, IconRefresh, IconChevronLeft, IconDownload, IconPrinter, IconMaximize, IconMinimize, IconX, IconFileText, IconCheck, IconPencil, IconClock } from "@tabler/icons-vue";
3
3
  import axios from "axios";
4
4
  import { useDebounceFn } from "@vueuse/core";
@@ -16656,2172 +16656,2335 @@ const VSnackbar = genericComponent()({
16656
16656
  return forwardRefs({}, overlay);
16657
16657
  }
16658
16658
  });
16659
- const _hoisted_1$9 = {
16660
- key: 0,
16661
- class: "page-title"
16662
- };
16663
- const _hoisted_2$5 = { class: "title-text" };
16664
- const _hoisted_3$4 = { class: "action-buttons" };
16665
- const _hoisted_4$2 = {
16666
- key: 3,
16667
- class: "selection-actions"
16668
- };
16669
- const _hoisted_5$2 = {
16670
- key: 0,
16671
- class: "selected-actions"
16672
- };
16673
- const _hoisted_6$1 = {
16674
- key: 0,
16675
- class: "me-1"
16676
- };
16677
- const _hoisted_7$1 = {
16678
- key: 0,
16679
- class: "me-1"
16680
- };
16681
- const _hoisted_8$1 = ["aria-busy", "aria-live"];
16682
- const _hoisted_9$1 = {
16683
- key: 0,
16684
- class: "grouped-table"
16685
- };
16686
- const _hoisted_10$1 = { class: "group-controls mb-3" };
16687
- const _hoisted_11$1 = { class: "groups-container" };
16688
- const _hoisted_12$1 = ["onClick", "onKeydown", "aria-expanded", "aria-controls", "id"];
16689
- const _hoisted_13$1 = { class: "group-label" };
16690
- const _hoisted_14$1 = ["id", "aria-labelledby"];
16691
- const _hoisted_15$1 = ["tabindex", "onKeydown", "onClick"];
16692
- const _hoisted_16$1 = ["tabindex", "onKeydown", "onClick"];
16693
- const _hoisted_17 = {
16694
- key: 2,
16695
- class: "d-flex justify-center align-center pa-4"
16696
- };
16697
- const _hoisted_18 = {
16698
- key: 2,
16699
- class: "pagination-wrapper"
16700
- };
16701
- const _hoisted_19 = { class: "d-flex justify-space-between align-center pa-4" };
16702
- const _hoisted_20 = { class: "text-subtitle-2" };
16703
- const _sfc_main$f = /* @__PURE__ */ defineComponent$1({
16704
- ...{ inheritAttrs: false },
16705
- __name: "CustomDataTable",
16706
- props: {
16707
- routes: {},
16708
- enableGroupDelete: { type: Boolean },
16709
- apiResource: {},
16710
- headers: {},
16711
- actions: {},
16712
- downloadLink: {},
16713
- formComponent: {},
16714
- customActions: {},
16715
- customButtons: {},
16716
- customButtonsFn: {},
16717
- filterComponent: {},
16718
- autoFetch: { type: Boolean, default: true },
16719
- queryParams: {},
16720
- showPagination: { type: Boolean, default: true },
16721
- height: {},
16722
- pagination: { type: [Object, Boolean] },
16723
- showRefreshButton: { type: Boolean, default: false },
16724
- title: {},
16725
- selectable: { type: Boolean, default: false },
16726
- multiSelect: { type: Boolean, default: false },
16727
- selectedItems: { default: () => [] },
16728
- uniqueKey: { type: [String, Function], default: "id" },
16729
- pageSize: { default: 10 },
16730
- groupBy: {},
16731
- groupHeaderTemplate: {},
16732
- defaultExpanded: { type: Boolean, default: false },
16733
- defaultSelected: {},
16734
- dateWithTimezone: { type: Boolean, default: false },
16735
- bulkMode: { type: Boolean, default: false },
16736
- axiosInstance: {}
16659
+ const makeVTextareaProps = propsFactory({
16660
+ autoGrow: Boolean,
16661
+ autofocus: Boolean,
16662
+ counter: [Boolean, Number, String],
16663
+ counterValue: Function,
16664
+ prefix: String,
16665
+ placeholder: String,
16666
+ persistentPlaceholder: Boolean,
16667
+ persistentCounter: Boolean,
16668
+ noResize: Boolean,
16669
+ rows: {
16670
+ type: [Number, String],
16671
+ default: 5,
16672
+ validator: (v) => !isNaN(parseFloat(v))
16737
16673
  },
16738
- emits: ["update:selectedItems", "selection-change"],
16739
- setup(__props, { expose: __expose, emit: __emit }) {
16740
- const props = __props;
16741
- const emit = __emit;
16742
- const items = ref([]);
16743
- const originalServerData = ref([]);
16744
- const loading = ref(false);
16745
- const error = ref(null);
16746
- const dialog = ref(false);
16747
- const deleteDialog = ref(false);
16748
- const isEditing = ref(false);
16749
- const editedItem = ref(null);
16750
- const formModel = ref({});
16751
- const itemToDelete = ref(null);
16752
- const snackbar = ref(false);
16753
- const snackbarMessage = ref("");
16754
- const router = useRouter$1();
16755
- const itemsPerPage = ref(props.pageSize);
16756
- const totalSize = ref(0);
16757
- const totalPages = ref(0);
16758
- const currentPage = ref(1);
16759
- ref(null);
16760
- const filterDialog = ref(false);
16761
- const filterModel = ref({});
16762
- ref(null);
16763
- const isLoadingMore = ref(false);
16764
- const hasMore = ref(true);
16765
- const selection = useTableSelection(items, {
16766
- multiSelect: props.bulkMode ? false : props.multiSelect,
16767
- // Force single select in bulk mode
16768
- uniqueKey: props.uniqueKey,
16769
- groupBy: props.groupBy,
16770
- defaultExpanded: props.defaultExpanded
16674
+ maxRows: {
16675
+ type: [Number, String],
16676
+ validator: (v) => !isNaN(parseFloat(v))
16677
+ },
16678
+ suffix: String,
16679
+ modelModifiers: Object,
16680
+ ...makeAutocompleteProps(),
16681
+ ...makeVInputProps(),
16682
+ ...makeVFieldProps()
16683
+ }, "VTextarea");
16684
+ const VTextarea = genericComponent()({
16685
+ name: "VTextarea",
16686
+ directives: {
16687
+ vIntersect: Intersect
16688
+ },
16689
+ inheritAttrs: false,
16690
+ props: makeVTextareaProps(),
16691
+ emits: {
16692
+ "click:control": (e) => true,
16693
+ "mousedown:control": (e) => true,
16694
+ "update:focused": (focused) => true,
16695
+ "update:modelValue": (val2) => true,
16696
+ "update:rows": (rows) => true
16697
+ },
16698
+ setup(props, _ref) {
16699
+ let {
16700
+ attrs,
16701
+ emit,
16702
+ slots
16703
+ } = _ref;
16704
+ const model = useProxiedModel(props, "modelValue");
16705
+ const {
16706
+ isFocused,
16707
+ focus,
16708
+ blur
16709
+ } = useFocus(props);
16710
+ const {
16711
+ onIntersect
16712
+ } = useAutofocus(props);
16713
+ const counterValue = computed(() => {
16714
+ return typeof props.counterValue === "function" ? props.counterValue(model.value) : (model.value || "").toString().length;
16771
16715
  });
16772
- const originalToggleSelection = selection.toggleSelection;
16773
- selection.toggleSelection = (item) => {
16774
- if (props.bulkMode) {
16775
- selection.clearSelection();
16776
- selection.selectedItems.value = [item];
16777
- } else {
16778
- originalToggleSelection(item);
16716
+ const max = computed(() => {
16717
+ if (attrs.maxlength) return attrs.maxlength;
16718
+ if (!props.counter || typeof props.counter !== "number" && typeof props.counter !== "string") return void 0;
16719
+ return props.counter;
16720
+ });
16721
+ const vInputRef = ref();
16722
+ const vFieldRef = ref();
16723
+ const controlHeight = shallowRef("");
16724
+ const textareaRef = ref();
16725
+ const autocomplete = useAutocomplete(props);
16726
+ const isActive = computed(() => props.persistentPlaceholder || isFocused.value || props.active);
16727
+ function onFocus() {
16728
+ var _a;
16729
+ if (autocomplete.isSuppressing.value) {
16730
+ autocomplete.update();
16779
16731
  }
16780
- };
16781
- const selectedItems = selection.selectedItems;
16782
- const selectAll = computed({
16783
- get: () => selection.allSelected.value,
16784
- set: (val2) => {
16785
- if (val2) {
16786
- selection.toggleSelectAll();
16787
- } else {
16788
- selection.clearSelection();
16789
- }
16732
+ if (textareaRef.value !== document.activeElement) {
16733
+ (_a = textareaRef.value) == null ? void 0 : _a.focus();
16790
16734
  }
16791
- });
16792
- const groupedItems = selection.groupedItems;
16793
- selection.expandedGroups;
16794
- const hasAnyActions = computed(() => {
16795
- if (props.bulkMode) {
16796
- return false;
16735
+ if (!isFocused.value) focus();
16736
+ }
16737
+ function onControlClick(e) {
16738
+ onFocus();
16739
+ emit("click:control", e);
16740
+ }
16741
+ function onControlMousedown(e) {
16742
+ emit("mousedown:control", e);
16743
+ }
16744
+ function onClear(e) {
16745
+ e.stopPropagation();
16746
+ onFocus();
16747
+ nextTick(() => {
16748
+ model.value = "";
16749
+ callEvent(props["onClick:clear"], e);
16750
+ });
16751
+ }
16752
+ function onInput(e) {
16753
+ var _a;
16754
+ const el = e.target;
16755
+ model.value = el.value;
16756
+ if ((_a = props.modelModifiers) == null ? void 0 : _a.trim) {
16757
+ const caretPosition = [el.selectionStart, el.selectionEnd];
16758
+ nextTick(() => {
16759
+ el.selectionStart = caretPosition[0];
16760
+ el.selectionEnd = caretPosition[1];
16761
+ });
16797
16762
  }
16798
- const hasCrudActions = Array.isArray(props.actions) && props.actions.length > 0;
16799
- const hasRoutes = !!props.routes && (typeof props.routes === "function" || Object.keys(props.routes).length > 0);
16800
- const hasDownloadLinks = !!props.downloadLink && Object.keys(props.downloadLink).length > 0;
16801
- const hasCustomActions = Array.isArray(props.customActions) && props.customActions.length > 0;
16802
- const hasCustomButtons = Array.isArray(props.customButtons) && props.customButtons.length > 0 || !!props.customButtonsFn;
16803
- return hasCrudActions || hasRoutes || hasDownloadLinks || hasCustomActions || hasCustomButtons;
16763
+ }
16764
+ const sizerRef = ref();
16765
+ const rows = ref(Number(props.rows));
16766
+ const isPlainOrUnderlined = computed(() => ["plain", "underlined"].includes(props.variant));
16767
+ watchEffect(() => {
16768
+ if (!props.autoGrow) rows.value = Number(props.rows);
16804
16769
  });
16805
- const getRoutesForItem = (item) => {
16806
- if (!props.routes) return {};
16807
- if (typeof props.routes === "function") {
16808
- return props.routes(item);
16809
- }
16810
- return props.routes;
16811
- };
16812
- const estimateColumnWidth = (header) => {
16813
- const title = header.title || "";
16814
- const basePadding = 32;
16815
- const avgCharWidth = 10;
16816
- const typeExtra = header.type && String(header.type).toLowerCase() === "money" ? 40 : 0;
16817
- const computed2 = basePadding + title.length * avgCharWidth + typeExtra;
16818
- const min = 100;
16819
- const max = 300;
16820
- return Math.min(Math.max(computed2, min), max);
16821
- };
16822
- const autoHeaders = computed(() => {
16823
- return props.headers.map((h2) => ({
16824
- ...h2,
16825
- width: h2.width ?? estimateColumnWidth(h2)
16826
- }));
16827
- });
16828
- const selectionHeader = { title: "", key: "selection", sortable: false, width: 50 };
16829
- const groupedHeaders = computed(() => {
16830
- var _a, _b, _c;
16831
- const base = [...props.selectable ? [selectionHeader] : [], ...autoHeaders.value];
16832
- if (!hasAnyActions.value) {
16833
- return base;
16834
- }
16835
- let totalWidth = 0;
16836
- if (props.actions) {
16837
- props.actions.forEach((action) => {
16838
- switch (action) {
16839
- case "edit":
16840
- totalWidth += 140;
16841
- break;
16842
- case "delete":
16843
- totalWidth += 120;
16844
- break;
16845
- case "view":
16846
- totalWidth += 140;
16847
- break;
16848
- case "create":
16849
- totalWidth += 120;
16850
- break;
16851
- }
16852
- });
16853
- }
16854
- if (props.routes) {
16855
- Object.keys(props.routes).forEach((routeKey) => {
16856
- totalWidth += 120;
16857
- });
16858
- }
16859
- if (props.downloadLink) {
16860
- Object.keys(props.downloadLink).forEach((key2) => {
16861
- totalWidth += 120;
16862
- });
16863
- }
16864
- if (props.customActions) {
16865
- props.customActions.forEach((action) => {
16866
- totalWidth += 140;
16867
- });
16868
- }
16869
- if (props.customButtonsFn) {
16870
- totalWidth += 240;
16871
- } else if (props.customButtons) {
16872
- props.customButtons.forEach((button) => {
16873
- totalWidth += 120;
16874
- });
16875
- }
16876
- const buttonCount = (((_a = props.actions) == null ? void 0 : _a.length) || 0) + (props.routes ? Object.keys(props.routes).length : 0) + (props.downloadLink ? Object.keys(props.downloadLink).length : 0) + (((_b = props.customActions) == null ? void 0 : _b.length) || 0) + (((_c = props.customButtons) == null ? void 0 : _c.length) || (props.customButtonsFn ? 2 : 0));
16877
- const spacingWidth = Math.max(buttonCount - 1, 0) * 8;
16878
- totalWidth += spacingWidth;
16879
- totalWidth += 32;
16880
- const actionWidth = Math.max(totalWidth, 200);
16881
- return [...base, { title: "عملیات", key: "actions", sortable: false, width: actionWidth }];
16882
- });
16883
- const normalHeaders = computed(() => {
16884
- var _a, _b, _c;
16885
- const base = [...props.selectable ? [selectionHeader] : [], ...autoHeaders.value];
16886
- if (!hasAnyActions.value) {
16887
- return base;
16888
- }
16889
- let totalWidth = 0;
16890
- if (props.actions) {
16891
- props.actions.forEach((action) => {
16892
- switch (action) {
16893
- case "edit":
16894
- totalWidth += 140;
16895
- break;
16896
- case "delete":
16897
- totalWidth += 120;
16898
- break;
16899
- case "view":
16900
- totalWidth += 140;
16901
- break;
16902
- case "create":
16903
- totalWidth += 120;
16904
- break;
16905
- }
16906
- });
16907
- }
16908
- if (props.routes) {
16909
- Object.keys(props.routes).forEach((routeKey) => {
16910
- totalWidth += 120;
16911
- });
16912
- }
16913
- if (props.downloadLink) {
16914
- Object.keys(props.downloadLink).forEach((key2) => {
16915
- totalWidth += 120;
16916
- });
16917
- }
16918
- if (props.customActions) {
16919
- props.customActions.forEach((action) => {
16920
- totalWidth += 140;
16921
- });
16922
- }
16923
- if (props.customButtonsFn) {
16924
- totalWidth += 240;
16925
- } else if (props.customButtons) {
16926
- props.customButtons.forEach((button) => {
16927
- totalWidth += 120;
16928
- });
16929
- }
16930
- const buttonCount = (((_a = props.actions) == null ? void 0 : _a.length) || 0) + (props.routes ? Object.keys(props.routes).length : 0) + (props.downloadLink ? Object.keys(props.downloadLink).length : 0) + (((_b = props.customActions) == null ? void 0 : _b.length) || 0) + (((_c = props.customButtons) == null ? void 0 : _c.length) || (props.customButtonsFn ? 2 : 0));
16931
- const spacingWidth = Math.max(buttonCount - 1, 0) * 8;
16932
- totalWidth += spacingWidth;
16933
- totalWidth += 32;
16934
- const actionWidth = Math.max(totalWidth, 200);
16935
- return [...base, { title: "عملیات", key: "actions", sortable: false, width: actionWidth }];
16770
+ function calculateInputHeight() {
16771
+ if (!props.autoGrow) return;
16772
+ nextTick(() => {
16773
+ if (!sizerRef.value || !vFieldRef.value) return;
16774
+ const style = getComputedStyle(sizerRef.value);
16775
+ const fieldStyle = getComputedStyle(vFieldRef.value.$el);
16776
+ const padding = parseFloat(style.getPropertyValue("--v-field-padding-top")) + parseFloat(style.getPropertyValue("--v-input-padding-top")) + parseFloat(style.getPropertyValue("--v-field-padding-bottom"));
16777
+ const height2 = sizerRef.value.scrollHeight;
16778
+ const lineHeight = parseFloat(style.lineHeight);
16779
+ const minHeight = Math.max(parseFloat(props.rows) * lineHeight + padding, parseFloat(fieldStyle.getPropertyValue("--v-input-control-height")));
16780
+ const maxHeight = parseFloat(props.maxRows) * lineHeight + padding || Infinity;
16781
+ const newHeight = clamp(height2 ?? 0, minHeight, maxHeight);
16782
+ rows.value = Math.floor((newHeight - padding) / lineHeight);
16783
+ controlHeight.value = convertToUnit(newHeight);
16784
+ });
16785
+ }
16786
+ onMounted(calculateInputHeight);
16787
+ watch(model, calculateInputHeight);
16788
+ watch(() => props.rows, calculateInputHeight);
16789
+ watch(() => props.maxRows, calculateInputHeight);
16790
+ watch(() => props.density, calculateInputHeight);
16791
+ watch(rows, (val2) => {
16792
+ emit("update:rows", val2);
16936
16793
  });
16937
- const hasAutocomplete = (header) => {
16938
- return Boolean(header.autocompleteItems);
16939
- };
16940
- const resolveAutocompleteItems = (header, context) => {
16941
- const enhancedHeader = header;
16942
- const source = enhancedHeader.autocompleteItems;
16943
- if (!source) return [];
16944
- try {
16945
- if (typeof source === "function") {
16946
- const baseContext = context ?? formModel.value;
16947
- return source(baseContext) ?? [];
16948
- }
16949
- if (isRef(source)) {
16950
- return source.value ?? [];
16951
- }
16952
- const resolved = unref(source);
16953
- return Array.isArray(resolved) ? resolved : [];
16954
- } catch (error2) {
16955
- console.error("Error resolving autocomplete items for header:", header.key, error2);
16956
- return [];
16957
- }
16958
- };
16959
- const resolveHeaderDefaultValue = (header, context) => {
16960
- const rawDefault = header.defaultValue;
16961
- if (rawDefault === void 0) {
16962
- return void 0;
16963
- }
16964
- try {
16965
- if (typeof rawDefault === "function") {
16966
- return rawDefault(context);
16967
- }
16968
- if (isRef(rawDefault)) {
16969
- return unref(rawDefault);
16970
- }
16971
- return rawDefault;
16972
- } catch (error2) {
16973
- console.error("Error resolving default value for header:", header.key, error2);
16974
- return void 0;
16975
- }
16976
- };
16977
- const resolveAutocompleteItemTitle = (header) => {
16978
- return header.autocompleteItemTitle ?? "title";
16979
- };
16980
- const resolveAutocompleteItemValue = (header) => {
16981
- return header.autocompleteItemValue ?? "value";
16982
- };
16983
- const resolveAutocompleteReturnObject = (header) => {
16984
- const value2 = header.autocompleteReturnObject;
16985
- return value2 !== false;
16986
- };
16987
- const resolveAutocompleteMultiple = (header) => {
16988
- return header.autocompleteMultiple === true;
16989
- };
16990
- const formHeaders = computed(() => props.headers);
16991
- const isMoneyHeader = (header) => {
16992
- if (!header || typeof header.type !== "string") {
16993
- return false;
16994
- }
16995
- return header.type.toLowerCase() === "money";
16996
- };
16997
- const getFieldInputType = (header) => {
16998
- return typeof (header == null ? void 0 : header.type) === "string" ? header.type : void 0;
16999
- };
17000
- const resolveHeaderKey = (header) => header.key;
17001
- const resolveHeaderTitle = (header) => header.title;
17002
- const isHeaderDisabled = (header) => header.editable === false;
17003
- const getUniqueValue = (item) => {
17004
- if (typeof props.uniqueKey === "function") {
17005
- return props.uniqueKey(item);
17006
- }
17007
- if (typeof props.uniqueKey === "string") {
17008
- return props.uniqueKey.split(".").reduce((obj, key2) => obj == null ? void 0 : obj[key2], item);
16794
+ let observer;
16795
+ watch(sizerRef, (val2) => {
16796
+ if (val2) {
16797
+ observer = new ResizeObserver(calculateInputHeight);
16798
+ observer.observe(sizerRef.value);
16799
+ } else {
16800
+ observer == null ? void 0 : observer.disconnect();
17009
16801
  }
17010
- return item.id;
17011
- };
17012
- const toggleSelection = (item) => {
17013
- if (!props.selectable) return;
17014
- selection.toggleSelection(item);
17015
- emit("update:selectedItems", selectedItems.value);
17016
- emit("selection-change", selectedItems.value);
17017
- };
17018
- const toggleSelectAll = () => {
17019
- if (!props.selectable || !props.multiSelect) return;
17020
- selection.toggleSelectAll();
17021
- emit("update:selectedItems", selectedItems.value);
17022
- emit("selection-change", selectedItems.value);
17023
- };
17024
- const toggleGroup = (groupKey) => {
17025
- setTimeout(() => {
17026
- selection.toggleGroup(groupKey);
17027
- }, 0);
17028
- };
17029
- const expandAllGroups = () => selection.expandAllGroups();
17030
- const collapseAllGroups = () => selection.collapseAllGroups();
17031
- const isSelected = (item) => selection.isSelected(item);
17032
- const selectedCount = computed(() => selectedItems.value.length);
17033
- const hasSelection = computed(() => selectedItems.value.length > 0);
17034
- const validSelectedItems = computed(() => {
17035
- if (!props.selectable || !props.bulkMode) return selectedItems.value;
17036
- return selectedItems.value.filter((selectedItem) => {
17037
- const uniqueValue = getUniqueValue(selectedItem);
17038
- return items.value.some((item) => getUniqueValue(item) === uniqueValue);
17039
- });
17040
16802
  });
17041
- const hasValidSelection = computed(() => {
17042
- if (!props.selectable || !props.bulkMode) return hasSelection.value;
17043
- return validSelectedItems.value.length > 0;
16803
+ onBeforeUnmount(() => {
16804
+ observer == null ? void 0 : observer.disconnect();
17044
16805
  });
17045
- const clearSelection = () => {
17046
- selection.clearSelection();
17047
- emit("update:selectedItems", selectedItems.value);
17048
- emit("selection-change", selectedItems.value);
17049
- };
17050
- const selectSingleItem = (item) => {
17051
- selection.clearSelection();
17052
- selection.selectedItems.value = [item];
17053
- emit("update:selectedItems", selectedItems.value);
17054
- emit("selection-change", selectedItems.value);
17055
- };
17056
- const radioGroupValue = computed(() => {
17057
- return selectedItems.value.length > 0 ? getUniqueValue(selectedItems.value[0]) : null;
17058
- });
17059
- const cleanFilterModel = computed(() => {
17060
- const model = { ...filterModel.value };
17061
- Object.keys(model).forEach((key2) => {
17062
- if (model[key2] === null || model[key2] === void 0 || model[key2] === "") {
17063
- delete model[key2];
17064
- }
17065
- });
17066
- return model;
17067
- });
17068
- const hasFilterComponent = computed(() => {
17069
- return !!props.filterComponent;
17070
- });
17071
- const fetchData = async (queryParams) => {
17072
- var _a, _b;
17073
- loading.value = true;
17074
- error.value = null;
17075
- let params = {
17076
- ...cleanFilterModel.value,
17077
- ...props.queryParams
16806
+ useRender(() => {
16807
+ const hasCounter = !!(slots.counter || props.counter || props.counterValue);
16808
+ const hasDetails = !!(hasCounter || slots.details);
16809
+ const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
16810
+ const {
16811
+ modelValue: _,
16812
+ ...inputProps
16813
+ } = VInput.filterProps(props);
16814
+ const fieldProps = {
16815
+ ...VField.filterProps(props),
16816
+ "onClick:clear": onClear
17078
16817
  };
17079
- if (queryParams) {
17080
- params = { ...params, ...queryParams };
17081
- }
17082
- try {
17083
- const shouldPaginate = props.showPagination !== false;
17084
- const requestParams = shouldPaginate ? {
17085
- ...params,
17086
- page: currentPage.value - 1,
17087
- size: itemsPerPage.value
17088
- } : params;
17089
- const response = await api.fetch(requestParams);
17090
- const serverRawData = shouldPaginate ? ((_a = response.data) == null ? void 0 : _a.content) ?? [] : response.data ?? [];
17091
- const serverData = Array.isArray(serverRawData) ? serverRawData : [];
17092
- originalServerData.value = serverData;
17093
- items.value = serverData.map((item) => {
17094
- const newItem = { ...item };
17095
- props.headers.forEach((header) => {
17096
- if (header.isDate && newItem[header.key]) {
17097
- try {
17098
- newItem[header.key] = DateConverter.toShamsi(newItem[header.key]);
17099
- } catch (error2) {
17100
- console.error(`Error converting date for field ${header.key}:`, error2);
17101
- }
16818
+ return createVNode(VInput, mergeProps({
16819
+ "ref": vInputRef,
16820
+ "modelValue": model.value,
16821
+ "onUpdate:modelValue": ($event) => model.value = $event,
16822
+ "class": ["v-textarea v-text-field", {
16823
+ "v-textarea--prefixed": props.prefix,
16824
+ "v-textarea--suffixed": props.suffix,
16825
+ "v-text-field--prefixed": props.prefix,
16826
+ "v-text-field--suffixed": props.suffix,
16827
+ "v-textarea--auto-grow": props.autoGrow,
16828
+ "v-textarea--no-resize": props.noResize || props.autoGrow,
16829
+ "v-input--plain-underlined": isPlainOrUnderlined.value
16830
+ }, props.class],
16831
+ "style": props.style
16832
+ }, rootAttrs, inputProps, {
16833
+ "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
16834
+ "focused": isFocused.value
16835
+ }), {
16836
+ ...slots,
16837
+ default: (_ref2) => {
16838
+ let {
16839
+ id,
16840
+ isDisabled,
16841
+ isDirty,
16842
+ isReadonly,
16843
+ isValid,
16844
+ hasDetails: hasDetails2
16845
+ } = _ref2;
16846
+ return createVNode(VField, mergeProps({
16847
+ "ref": vFieldRef,
16848
+ "style": {
16849
+ "--v-textarea-control-height": controlHeight.value
16850
+ },
16851
+ "onClick": onControlClick,
16852
+ "onMousedown": onControlMousedown,
16853
+ "onClick:prependInner": props["onClick:prependInner"],
16854
+ "onClick:appendInner": props["onClick:appendInner"]
16855
+ }, fieldProps, {
16856
+ "id": id.value,
16857
+ "active": isActive.value || isDirty.value,
16858
+ "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
16859
+ "dirty": isDirty.value || props.dirty,
16860
+ "disabled": isDisabled.value,
16861
+ "focused": isFocused.value,
16862
+ "details": hasDetails2.value,
16863
+ "error": isValid.value === false
16864
+ }), {
16865
+ ...slots,
16866
+ default: (_ref3) => {
16867
+ let {
16868
+ props: {
16869
+ class: fieldClass,
16870
+ ...slotProps
16871
+ }
16872
+ } = _ref3;
16873
+ return createElementVNode(Fragment, null, [props.prefix && createElementVNode("span", {
16874
+ "class": "v-text-field__prefix"
16875
+ }, [props.prefix]), withDirectives(createElementVNode("textarea", mergeProps({
16876
+ "ref": textareaRef,
16877
+ "class": fieldClass,
16878
+ "value": model.value,
16879
+ "onInput": onInput,
16880
+ "autofocus": props.autofocus,
16881
+ "readonly": isReadonly.value,
16882
+ "disabled": isDisabled.value,
16883
+ "placeholder": props.placeholder,
16884
+ "rows": props.rows,
16885
+ "name": autocomplete.fieldName.value,
16886
+ "autocomplete": autocomplete.fieldAutocomplete.value,
16887
+ "onFocus": onFocus,
16888
+ "onBlur": blur
16889
+ }, slotProps, inputAttrs), null), [[Intersect, {
16890
+ handler: onIntersect
16891
+ }, null, {
16892
+ once: true
16893
+ }]]), props.autoGrow && withDirectives(createElementVNode("textarea", {
16894
+ "class": normalizeClass([fieldClass, "v-textarea__sizer"]),
16895
+ "id": `${slotProps.id}-sizer`,
16896
+ "onUpdate:modelValue": ($event) => model.value = $event,
16897
+ "ref": sizerRef,
16898
+ "readonly": true,
16899
+ "aria-hidden": "true"
16900
+ }, null), [[vModelText, model.value]]), props.suffix && createElementVNode("span", {
16901
+ "class": "v-text-field__suffix"
16902
+ }, [props.suffix])]);
17102
16903
  }
17103
16904
  });
17104
- return newItem;
17105
- });
17106
- if (shouldPaginate && ((_b = response.data) == null ? void 0 : _b.page)) {
17107
- totalSize.value = response.data.page.totalElements;
17108
- totalPages.value = response.data.page.totalPages;
17109
- hasMore.value = currentPage.value < response.data.page.totalPages;
17110
- } else {
17111
- totalSize.value = serverData.length;
17112
- totalPages.value = 1;
17113
- hasMore.value = false;
17114
- }
17115
- if (props.defaultSelected && items.value.length > 0 && props.defaultSelected in items.value[0]) {
17116
- const defaultSelectedItems = items.value.filter((item) => item[props.defaultSelected] === true);
17117
- selectedItems.value = [...defaultSelectedItems];
17118
- emit("update:selectedItems", selectedItems.value);
17119
- emit("selection-change", selectedItems.value);
17120
- }
17121
- } catch (err) {
17122
- if (err.response) {
17123
- error.value = `خطای سرور: ${err.response.status} - ${err.response.data.message || "خطای ناشناخته"}`;
17124
- } else if (err.request) {
17125
- error.value = "خطای شبکه. لطفا دوباره تلاش کنید.";
17126
- } else {
17127
- error.value = "یک خطای غیرمنتظره رخ داد.";
17128
- }
17129
- console.error(err);
17130
- } finally {
17131
- loading.value = false;
17132
- }
17133
- };
17134
- const debouncedFetchData = useDebounceFn(fetchData, 300);
17135
- watch(
17136
- [cleanFilterModel],
17137
- () => {
17138
- debouncedFetchData();
17139
- },
17140
- { deep: true }
17141
- );
17142
- watch(
17143
- () => props.pageSize,
17144
- (newPageSize) => {
17145
- itemsPerPage.value = newPageSize;
17146
- currentPage.value = 1;
17147
- debouncedFetchData();
17148
- }
17149
- );
17150
- watch(
17151
- () => items.value,
17152
- (newItems) => {
17153
- if (props.selectable && props.bulkMode && selectedItems.value.length > 0) {
17154
- const invalidSelections = selectedItems.value.filter((selectedItem) => {
17155
- const uniqueValue = getUniqueValue(selectedItem);
17156
- return !newItems.some((item) => getUniqueValue(item) === uniqueValue);
17157
- });
17158
- if (invalidSelections.length > 0) {
17159
- const validSelections = selectedItems.value.filter((selectedItem) => {
17160
- const uniqueValue = getUniqueValue(selectedItem);
17161
- return newItems.some((item) => getUniqueValue(item) === uniqueValue);
17162
- });
17163
- selectedItems.value = validSelections;
17164
- emit("update:selectedItems", selectedItems.value);
17165
- emit("selection-change", selectedItems.value);
17166
- }
17167
- }
17168
- },
17169
- { deep: true }
17170
- );
17171
- onBeforeUnmount(() => {
17172
- });
17173
- const componentAxiosInstance = props.axiosInstance || getAxiosInstance();
17174
- const api = apiService(componentAxiosInstance, props.apiResource);
17175
- const customActionDialog = ref(false);
17176
- const customActionComponent = shallowRef(null);
17177
- const customActionItem = ref(null);
17178
- __expose({
17179
- fetchData,
17180
- items,
17181
- selectedItems,
17182
- getSelectedItems: () => selectedItems.value,
17183
- clearSelection: () => {
17184
- selectedItems.value = [];
17185
- selectAll.value = false;
17186
- },
17187
- // Grouping methods (handled by useTableSelection composable)
17188
- groupedItems,
17189
- toggleGroup,
17190
- expandAllGroups,
17191
- collapseAllGroups,
17192
- formModel
16905
+ },
16906
+ details: hasDetails ? (slotProps) => {
16907
+ var _a;
16908
+ return createElementVNode(Fragment, null, [(_a = slots.details) == null ? void 0 : _a.call(slots, slotProps), hasCounter && createElementVNode(Fragment, null, [createElementVNode("span", null, null), createVNode(VCounter, {
16909
+ "active": props.persistentCounter || isFocused.value,
16910
+ "value": counterValue.value,
16911
+ "max": max.value,
16912
+ "disabled": props.disabled
16913
+ }, slots.counter)])]);
16914
+ } : void 0
16915
+ });
17193
16916
  });
17194
- const openDialog = (item) => {
17195
- editedItem.value = item ? { ...item } : {};
17196
- isEditing.value = !!item;
17197
- dialog.value = true;
17198
- if (!isEditing.value) {
17199
- const defaultContext = { ...editedItem.value };
17200
- for (const header of props.headers) {
17201
- if (header.defaultValue === void 0) {
17202
- continue;
17203
- }
17204
- const resolvedDefault = resolveHeaderDefaultValue(header, defaultContext);
17205
- if (resolvedDefault !== void 0) {
17206
- editedItem.value[header.key] = resolvedDefault;
17207
- defaultContext[header.key] = resolvedDefault;
17208
- }
17209
- }
17210
- }
17211
- formModel.value = { ...editedItem.value };
17212
- props.headers.forEach((header) => {
17213
- if (!hasAutocomplete(header)) return;
17214
- const enhancedHeader = header;
17215
- const currentValue = formModel.value[header.key];
17216
- const valueKey = resolveAutocompleteItemValue(header);
17217
- if (enhancedHeader.autocompleteReturnObject === false) {
17218
- if (Array.isArray(currentValue)) {
17219
- formModel.value[header.key] = currentValue.map(
17220
- (item2) => item2 && typeof item2 === "object" ? item2[valueKey] ?? null : item2
17221
- );
17222
- } else if (currentValue && typeof currentValue === "object") {
17223
- formModel.value[header.key] = currentValue[valueKey] ?? null;
17224
- }
17225
- }
17226
- });
17227
- if (isEditing.value) {
17228
- try {
17229
- props.headers.forEach((header) => {
17230
- if (header.isDate) {
17231
- const v = formModel.value[header.key];
17232
- if (typeof v === "string" && v.includes("/")) {
17233
- formModel.value[header.key] = DateConverter.toGregorian(v);
17234
- } else if (typeof v === "string" && v.includes("T")) {
17235
- formModel.value[header.key] = v.split("T")[0];
17236
- }
17237
- }
17238
- });
17239
- } catch (e) {
17240
- console.error("Error normalizing date fields for edit form:", e);
17241
- }
17242
- }
17243
- };
17244
- const openDeleteDialog = (item) => {
17245
- itemToDelete.value = item;
17246
- deleteDialog.value = true;
17247
- };
17248
- const groupDeleteDialog = ref(false);
17249
- const openGroupDeleteDialog = () => {
17250
- groupDeleteDialog.value = true;
17251
- };
17252
- const deleteGroupItems = async () => {
17253
- try {
17254
- const selectedIds = validSelectedItems.value.map((item) => getUniqueValue(item));
17255
- const idsParam = selectedIds.join(",");
17256
- await api.delete(`?ids=${idsParam}`);
17257
- groupDeleteDialog.value = false;
17258
- clearSelection();
17259
- await fetchData();
17260
- snackbarMessage.value = `✅ ${selectedIds.length} آیتم با موفقیت حذف شد`;
17261
- snackbar.value = true;
17262
- } catch (err) {
17263
- console.error("خطا در حذف گروهی اطلاعات", err);
17264
- snackbarMessage.value = "❌ خطا در حذف گروهی اطلاعات!";
17265
- snackbar.value = true;
16917
+ return forwardRefs({}, vInputRef, vFieldRef, textareaRef);
16918
+ }
16919
+ });
16920
+ const _hoisted_1$9 = {
16921
+ key: 0,
16922
+ class: "page-title"
16923
+ };
16924
+ const _hoisted_2$5 = { class: "title-text" };
16925
+ const _hoisted_3$4 = { class: "action-buttons" };
16926
+ const _hoisted_4$2 = {
16927
+ key: 3,
16928
+ class: "selection-actions"
16929
+ };
16930
+ const _hoisted_5$2 = {
16931
+ key: 0,
16932
+ class: "selected-actions"
16933
+ };
16934
+ const _hoisted_6$1 = {
16935
+ key: 0,
16936
+ class: "me-1"
16937
+ };
16938
+ const _hoisted_7$1 = {
16939
+ key: 0,
16940
+ class: "me-1"
16941
+ };
16942
+ const _hoisted_8$1 = ["aria-busy", "aria-live"];
16943
+ const _hoisted_9$1 = {
16944
+ key: 0,
16945
+ class: "grouped-table"
16946
+ };
16947
+ const _hoisted_10$1 = { class: "group-controls mb-3" };
16948
+ const _hoisted_11$1 = { class: "groups-container" };
16949
+ const _hoisted_12$1 = ["onClick", "onKeydown", "aria-expanded", "aria-controls", "id"];
16950
+ const _hoisted_13$1 = { class: "group-label" };
16951
+ const _hoisted_14$1 = ["id", "aria-labelledby"];
16952
+ const _hoisted_15$1 = ["tabindex", "onKeydown", "onClick"];
16953
+ const _hoisted_16$1 = ["onClick"];
16954
+ const _hoisted_17 = { key: 1 };
16955
+ const _hoisted_18 = ["tabindex", "onKeydown", "onClick"];
16956
+ const _hoisted_19 = ["onClick"];
16957
+ const _hoisted_20 = { key: 1 };
16958
+ const _hoisted_21 = {
16959
+ key: 2,
16960
+ class: "d-flex justify-center align-center pa-4"
16961
+ };
16962
+ const _hoisted_22 = {
16963
+ key: 2,
16964
+ class: "pagination-wrapper"
16965
+ };
16966
+ const _hoisted_23 = { class: "d-flex justify-space-between align-center pa-4" };
16967
+ const _hoisted_24 = { class: "text-subtitle-2" };
16968
+ const _sfc_main$f = /* @__PURE__ */ defineComponent$1({
16969
+ ...{ inheritAttrs: false },
16970
+ __name: "CustomDataTable",
16971
+ props: {
16972
+ routes: {},
16973
+ enableGroupDelete: { type: Boolean },
16974
+ apiResource: {},
16975
+ headers: {},
16976
+ actions: {},
16977
+ downloadLink: {},
16978
+ formComponent: {},
16979
+ customActions: {},
16980
+ customButtons: {},
16981
+ customButtonsFn: {},
16982
+ filterComponent: {},
16983
+ autoFetch: { type: Boolean, default: true },
16984
+ queryParams: {},
16985
+ showPagination: { type: Boolean, default: true },
16986
+ height: {},
16987
+ pagination: { type: [Object, Boolean] },
16988
+ showRefreshButton: { type: Boolean, default: false },
16989
+ title: {},
16990
+ selectable: { type: Boolean, default: false },
16991
+ multiSelect: { type: Boolean, default: false },
16992
+ selectedItems: { default: () => [] },
16993
+ uniqueKey: { type: [String, Function], default: "id" },
16994
+ pageSize: { default: 10 },
16995
+ groupBy: {},
16996
+ groupHeaderTemplate: {},
16997
+ defaultExpanded: { type: Boolean, default: false },
16998
+ defaultSelected: {},
16999
+ dateWithTimezone: { type: Boolean, default: false },
17000
+ bulkMode: { type: Boolean, default: false },
17001
+ axiosInstance: {},
17002
+ maxTextLength: { default: 50 }
17003
+ },
17004
+ emits: ["update:selectedItems", "selection-change"],
17005
+ setup(__props, { expose: __expose, emit: __emit }) {
17006
+ const props = __props;
17007
+ const emit = __emit;
17008
+ const items = ref([]);
17009
+ const originalServerData = ref([]);
17010
+ const loading = ref(false);
17011
+ const error = ref(null);
17012
+ const dialog = ref(false);
17013
+ const deleteDialog = ref(false);
17014
+ const isEditing = ref(false);
17015
+ const editedItem = ref(null);
17016
+ const formModel = ref({});
17017
+ const itemToDelete = ref(null);
17018
+ const snackbar = ref(false);
17019
+ const snackbarMessage = ref("");
17020
+ const router = useRouter$1();
17021
+ const itemsPerPage = ref(props.pageSize);
17022
+ const totalSize = ref(0);
17023
+ const totalPages = ref(0);
17024
+ const currentPage = ref(1);
17025
+ ref(null);
17026
+ const filterDialog = ref(false);
17027
+ const filterModel = ref({});
17028
+ ref(null);
17029
+ const isLoadingMore = ref(false);
17030
+ const hasMore = ref(true);
17031
+ const selection = useTableSelection(items, {
17032
+ multiSelect: props.bulkMode ? false : props.multiSelect,
17033
+ // Force single select in bulk mode
17034
+ uniqueKey: props.uniqueKey,
17035
+ groupBy: props.groupBy,
17036
+ defaultExpanded: props.defaultExpanded
17037
+ });
17038
+ const originalToggleSelection = selection.toggleSelection;
17039
+ selection.toggleSelection = (item) => {
17040
+ if (props.bulkMode) {
17041
+ selection.clearSelection();
17042
+ selection.selectedItems.value = [item];
17043
+ } else {
17044
+ originalToggleSelection(item);
17266
17045
  }
17267
17046
  };
17268
- const saveItem = async () => {
17269
- if (!formModel.value) return;
17270
- try {
17271
- const dataToSave = { ...formModel.value };
17272
- props.headers.forEach((header) => {
17273
- if (header.isDate && dataToSave[header.key]) {
17274
- try {
17275
- const raw = dataToSave[header.key];
17276
- if (typeof raw === "string") {
17277
- const toIsoWithOffset = (ymd) => {
17278
- const [y, m, d] = ymd.split("-").map(Number);
17279
- const local = new Date(y, (m || 1) - 1, d || 1, 0, 0, 0, 0);
17280
- const offsetMin = -local.getTimezoneOffset();
17281
- const sign = offsetMin >= 0 ? "+" : "-";
17282
- const abs = Math.abs(offsetMin);
17283
- const hh = String(Math.floor(abs / 60)).padStart(2, "0");
17284
- const mm = String(abs % 60).padStart(2, "0");
17285
- const mm2 = String(m).padStart(2, "0");
17286
- const dd2 = String(d).padStart(2, "0");
17287
- return `${y}-${mm2}-${dd2}T00:00:00${sign}${hh}:${mm}`;
17288
- };
17289
- if (raw.includes("/")) {
17290
- const greg = DateConverter.toGregorian(raw);
17291
- dataToSave[header.key] = props.dateWithTimezone ? toIsoWithOffset(greg) : greg;
17292
- } else if (raw.includes("T")) {
17293
- dataToSave[header.key] = props.dateWithTimezone ? raw : raw.split("T")[0];
17294
- } else {
17295
- dataToSave[header.key] = props.dateWithTimezone ? toIsoWithOffset(raw) : raw;
17296
- }
17297
- }
17298
- } catch (error2) {
17299
- console.error(`Error converting date for field ${header.key}:`, error2);
17300
- }
17301
- }
17302
- });
17303
- if (isEditing.value && dataToSave.id) {
17304
- await api.update(dataToSave);
17305
- snackbarMessage.value = "✅ آیتم با موفقیت بروزرسانی شد!";
17047
+ const selectedItems = selection.selectedItems;
17048
+ const selectAll = computed({
17049
+ get: () => selection.allSelected.value,
17050
+ set: (val2) => {
17051
+ if (val2) {
17052
+ selection.toggleSelectAll();
17306
17053
  } else {
17307
- const response = await api.create(dataToSave);
17308
- snackbarMessage.value = "✅ آیتم با موفقیت ایجاد شد!";
17309
- if (response.data) items.value.push(response.data);
17054
+ selection.clearSelection();
17310
17055
  }
17311
- snackbar.value = true;
17312
- dialog.value = false;
17313
- await fetchData();
17314
- } catch (err) {
17315
- console.error("خطا در ذخیره اطلاعات", err);
17316
- snackbarMessage.value = "❌ خطا در ذخیره اطلاعات!";
17317
- snackbar.value = true;
17318
17056
  }
17319
- };
17320
- const deleteItem = async (id) => {
17321
- try {
17322
- await api.delete(id);
17323
- deleteDialog.value = false;
17324
- items.value = items.value.filter((item) => item.id !== id);
17325
- await fetchData();
17326
- } catch (err) {
17327
- console.error("خطا در حذف اطلاعات", err);
17328
- snackbarMessage.value = "❌ خطا در حذف اطلاعات!";
17329
- snackbar.value = true;
17057
+ });
17058
+ const groupedItems = selection.groupedItems;
17059
+ selection.expandedGroups;
17060
+ const hasAnyActions = computed(() => {
17061
+ if (props.bulkMode) {
17062
+ return false;
17330
17063
  }
17331
- };
17332
- const goToRoute = (key2, item) => {
17333
- const routes = getRoutesForItem(item);
17334
- if (!routes || !routes[key2] || !item) return;
17335
- let routePath = routes[key2];
17336
- const missingParams = [];
17337
- routePath = routePath.replace(/\{(\w+)}/g, (_, field) => {
17338
- if (item[field] !== void 0) {
17339
- return item[field];
17340
- } else {
17341
- missingParams.push(field);
17342
- return `{${field}}`;
17343
- }
17344
- });
17345
- if (missingParams.length > 0) {
17346
- snackbarMessage.value = ` خطا : ${missingParams.join(" , ")} در خروجی نیست `;
17347
- snackbar.value = true;
17348
- return;
17064
+ const hasCrudActions = Array.isArray(props.actions) && props.actions.length > 0;
17065
+ const hasRoutes = !!props.routes && (typeof props.routes === "function" || Object.keys(props.routes).length > 0);
17066
+ const hasDownloadLinks = !!props.downloadLink && Object.keys(props.downloadLink).length > 0;
17067
+ const hasCustomActions = Array.isArray(props.customActions) && props.customActions.length > 0;
17068
+ const hasCustomButtons = Array.isArray(props.customButtons) && props.customButtons.length > 0 || !!props.customButtonsFn;
17069
+ return hasCrudActions || hasRoutes || hasDownloadLinks || hasCustomActions || hasCustomButtons;
17070
+ });
17071
+ const getRoutesForItem = (item) => {
17072
+ if (!props.routes) return {};
17073
+ if (typeof props.routes === "function") {
17074
+ return props.routes(item);
17349
17075
  }
17350
- router.push(routePath);
17076
+ return props.routes;
17351
17077
  };
17352
- const download = async (key2, item) => {
17353
- if (!props.downloadLink || !item) return;
17354
- const fileKey = props.downloadLink[key2];
17355
- const url = item[fileKey];
17356
- if (!url || typeof url !== "string") {
17357
- snackbarMessage.value = `❌ لینک فایل یافت نشد.`;
17358
- snackbar.value = true;
17359
- return;
17078
+ const estimateColumnWidth = (header) => {
17079
+ const title = header.title || "";
17080
+ const basePadding = 32;
17081
+ const avgCharWidth = 10;
17082
+ const typeExtra = header.type && String(header.type).toLowerCase() === "money" ? 40 : 0;
17083
+ const computed2 = basePadding + title.length * avgCharWidth + typeExtra;
17084
+ const min = 100;
17085
+ const max = 300;
17086
+ return Math.min(Math.max(computed2, min), max);
17087
+ };
17088
+ const autoHeaders = computed(() => {
17089
+ return props.headers.map((h2) => ({
17090
+ ...h2,
17091
+ width: h2.width ?? estimateColumnWidth(h2)
17092
+ }));
17093
+ });
17094
+ const selectionHeader = { title: "", key: "selection", sortable: false, width: 50 };
17095
+ const groupedHeaders = computed(() => {
17096
+ var _a, _b, _c;
17097
+ const base = [...props.selectable ? [selectionHeader] : [], ...autoHeaders.value];
17098
+ if (!hasAnyActions.value) {
17099
+ return base;
17360
17100
  }
17361
- const fileUrlString = url;
17362
- try {
17363
- const response = await fetch(fileUrlString, {
17364
- method: "GET",
17365
- headers: {
17366
- Accept: "application/octet-stream,application/pdf,image/*,*/*"
17367
- },
17368
- credentials: "include"
17369
- // Include cookies for authentication
17370
- });
17371
- if (!response.ok) {
17372
- throw new Error(`HTTP error! status: ${response.status}`);
17373
- }
17374
- const contentType = response.headers.get("content-type");
17375
- const contentLength = response.headers.get("content-length");
17376
- console.log("Response headers:", {
17377
- contentType,
17378
- contentLength,
17379
- url: fileUrlString
17380
- });
17381
- if (contentType && contentType.includes("xml")) {
17382
- const errorText = await response.text();
17383
- console.error("Server returned XML error:", errorText);
17384
- snackbarMessage.value = `❌ خطای سرور: فایل در دسترس نیست`;
17385
- snackbar.value = true;
17386
- return;
17387
- }
17388
- if (contentLength && parseInt(contentLength) < 1e3) {
17389
- const responseText = await response.text();
17390
- console.log("Small response:", responseText);
17391
- if (responseText.includes("error") || responseText.includes("Error")) {
17392
- snackbarMessage.value = `❌ خطای سرور: فایل در دسترس نیست`;
17393
- snackbar.value = true;
17394
- return;
17395
- }
17396
- }
17397
- const blob = await response.blob();
17398
- const url2 = window.URL.createObjectURL(blob);
17399
- const link = document.createElement("a");
17400
- link.href = url2;
17401
- const filename = fileUrlString.split("/").pop() || "download";
17402
- link.download = filename;
17403
- document.body.appendChild(link);
17404
- link.click();
17405
- document.body.removeChild(link);
17406
- window.URL.revokeObjectURL(url2);
17407
- snackbarMessage.value = `✅ دانلود شروع شد`;
17408
- snackbar.value = true;
17409
- } catch (error2) {
17410
- console.error("Download error:", error2);
17411
- try {
17412
- const axiosResponse = await componentAxiosInstance.get(fileUrlString, {
17413
- responseType: "blob",
17414
- headers: {
17415
- Accept: "application/octet-stream,application/pdf,image/*,*/*"
17416
- }
17417
- });
17418
- const contentType = axiosResponse.headers["content-type"];
17419
- const contentLength = axiosResponse.headers["content-length"];
17420
- console.log("Axios response headers:", {
17421
- contentType,
17422
- contentLength,
17423
- url: fileUrlString
17424
- });
17425
- if (contentType && contentType.includes("xml")) {
17426
- const textResponse = await componentAxiosInstance.get(fileUrlString, {
17427
- responseType: "text"
17428
- });
17429
- console.error("Server returned XML error:", textResponse.data);
17430
- snackbarMessage.value = `❌ خطای سرور: فایل در دسترس نیست`;
17431
- snackbar.value = true;
17432
- return;
17433
- }
17434
- const blob = new Blob([axiosResponse.data]);
17435
- const url2 = window.URL.createObjectURL(blob);
17436
- const link = document.createElement("a");
17437
- link.href = url2;
17438
- const filename = fileUrlString.split("/").pop() || "download";
17439
- link.download = filename;
17440
- document.body.appendChild(link);
17441
- link.click();
17442
- document.body.removeChild(link);
17443
- window.URL.revokeObjectURL(url2);
17444
- snackbarMessage.value = `✅ دانلود شروع شد`;
17445
- snackbar.value = true;
17446
- } catch (axiosError) {
17447
- console.error("Axios download error:", axiosError);
17448
- if (axiosError.response) {
17449
- try {
17450
- const errorText = await componentAxiosInstance.get(fileUrlString, {
17451
- responseType: "text"
17452
- });
17453
- console.error("Server error response:", errorText.data);
17454
- } catch (textError) {
17455
- console.error("Could not get error text:", textError);
17456
- }
17101
+ let totalWidth = 0;
17102
+ if (props.actions) {
17103
+ props.actions.forEach((action) => {
17104
+ switch (action) {
17105
+ case "edit":
17106
+ totalWidth += 140;
17107
+ break;
17108
+ case "delete":
17109
+ totalWidth += 120;
17110
+ break;
17111
+ case "view":
17112
+ totalWidth += 140;
17113
+ break;
17114
+ case "create":
17115
+ totalWidth += 120;
17116
+ break;
17457
17117
  }
17458
- snackbarMessage.value = `❌ خطا در دانلود فایل`;
17459
- snackbar.value = true;
17460
- }
17461
- }
17462
- };
17463
- const handlePageChange = (newPage) => {
17464
- currentPage.value = newPage;
17465
- debouncedFetchData();
17466
- };
17467
- onMounted(() => {
17468
- if (props.autoFetch) {
17469
- fetchData();
17118
+ });
17470
17119
  }
17471
- });
17472
- const openCustomActionDialog = (action, item) => {
17473
- customActionComponent.value = action.component;
17474
- const originalItem = originalServerData.value.find((originalItem2) => {
17475
- const itemId = typeof props.uniqueKey === "function" ? props.uniqueKey(item) : item[props.uniqueKey];
17476
- const originalId = typeof props.uniqueKey === "function" ? props.uniqueKey(originalItem2) : originalItem2[props.uniqueKey];
17477
- return itemId === originalId;
17478
- });
17479
- customActionItem.value = originalItem ? { ...originalItem } : { ...item };
17480
- customActionDialog.value = true;
17481
- };
17482
- const getColumnStyle = (column, item) => {
17483
- const header = props.headers.find((h2) => h2.key === column.key);
17484
- if (!header) return {};
17485
- const baseStyle = header.style || {};
17486
- if (header.conditionalStyle) {
17487
- const conditionalStyle = header.conditionalStyle(item[column.key], item);
17488
- return { ...baseStyle, ...conditionalStyle };
17120
+ if (props.routes) {
17121
+ Object.keys(props.routes).forEach((routeKey) => {
17122
+ totalWidth += 120;
17123
+ });
17489
17124
  }
17490
- return baseStyle;
17491
- };
17492
- const getNestedValue2 = (obj, path) => {
17493
- return path.split(".").reduce((current, key2) => {
17494
- return current && current[key2] !== void 0 ? current[key2] : null;
17495
- }, obj);
17496
- };
17497
- const getTranslatedValue = (value2, column, item) => {
17498
- const header = props.headers.find((h2) => h2.key === column.key);
17499
- if (!header) return value2;
17500
- if (header.customRenderer) {
17501
- return header.customRenderer(item);
17125
+ if (props.downloadLink) {
17126
+ Object.keys(props.downloadLink).forEach((key2) => {
17127
+ totalWidth += 120;
17128
+ });
17502
17129
  }
17503
- if (header.formatter) {
17504
- return header.formatter(value2, item);
17130
+ if (props.customActions) {
17131
+ props.customActions.forEach((action) => {
17132
+ totalWidth += 140;
17133
+ });
17505
17134
  }
17506
- if (String(header.type).toLowerCase() === "money") {
17507
- try {
17508
- return formatNumberWithCommas(value2 ?? 0, 0);
17509
- } catch (e) {
17510
- return value2;
17511
- }
17135
+ if (props.customButtonsFn) {
17136
+ totalWidth += 240;
17137
+ } else if (props.customButtons) {
17138
+ props.customButtons.forEach((button) => {
17139
+ totalWidth += 120;
17140
+ });
17512
17141
  }
17513
- if (header.translate) {
17514
- if (header.options) {
17515
- const option = header.options.find((opt) => opt.value === value2);
17516
- return (option == null ? void 0 : option.title) || value2;
17517
- }
17518
- return translateValue(value2);
17142
+ const buttonCount = (((_a = props.actions) == null ? void 0 : _a.length) || 0) + (props.routes ? Object.keys(props.routes).length : 0) + (props.downloadLink ? Object.keys(props.downloadLink).length : 0) + (((_b = props.customActions) == null ? void 0 : _b.length) || 0) + (((_c = props.customButtons) == null ? void 0 : _c.length) || (props.customButtonsFn ? 2 : 0));
17143
+ const spacingWidth = Math.max(buttonCount - 1, 0) * 8;
17144
+ totalWidth += spacingWidth;
17145
+ totalWidth += 32;
17146
+ const actionWidth = Math.max(totalWidth, 200);
17147
+ return [...base, { title: "عملیات", key: "actions", sortable: false, width: actionWidth }];
17148
+ });
17149
+ const normalHeaders = computed(() => {
17150
+ var _a, _b, _c;
17151
+ const base = [...props.selectable ? [selectionHeader] : [], ...autoHeaders.value];
17152
+ if (!hasAnyActions.value) {
17153
+ return base;
17519
17154
  }
17520
- return value2;
17155
+ let totalWidth = 0;
17156
+ if (props.actions) {
17157
+ props.actions.forEach((action) => {
17158
+ switch (action) {
17159
+ case "edit":
17160
+ totalWidth += 140;
17161
+ break;
17162
+ case "delete":
17163
+ totalWidth += 120;
17164
+ break;
17165
+ case "view":
17166
+ totalWidth += 140;
17167
+ break;
17168
+ case "create":
17169
+ totalWidth += 120;
17170
+ break;
17171
+ }
17172
+ });
17173
+ }
17174
+ if (props.routes) {
17175
+ Object.keys(props.routes).forEach((routeKey) => {
17176
+ totalWidth += 120;
17177
+ });
17178
+ }
17179
+ if (props.downloadLink) {
17180
+ Object.keys(props.downloadLink).forEach((key2) => {
17181
+ totalWidth += 120;
17182
+ });
17183
+ }
17184
+ if (props.customActions) {
17185
+ props.customActions.forEach((action) => {
17186
+ totalWidth += 140;
17187
+ });
17188
+ }
17189
+ if (props.customButtonsFn) {
17190
+ totalWidth += 240;
17191
+ } else if (props.customButtons) {
17192
+ props.customButtons.forEach((button) => {
17193
+ totalWidth += 120;
17194
+ });
17195
+ }
17196
+ const buttonCount = (((_a = props.actions) == null ? void 0 : _a.length) || 0) + (props.routes ? Object.keys(props.routes).length : 0) + (props.downloadLink ? Object.keys(props.downloadLink).length : 0) + (((_b = props.customActions) == null ? void 0 : _b.length) || 0) + (((_c = props.customButtons) == null ? void 0 : _c.length) || (props.customButtonsFn ? 2 : 0));
17197
+ const spacingWidth = Math.max(buttonCount - 1, 0) * 8;
17198
+ totalWidth += spacingWidth;
17199
+ totalWidth += 32;
17200
+ const actionWidth = Math.max(totalWidth, 200);
17201
+ return [...base, { title: "عملیات", key: "actions", sortable: false, width: actionWidth }];
17202
+ });
17203
+ const hasAutocomplete = (header) => {
17204
+ return Boolean(header.autocompleteItems);
17521
17205
  };
17522
- const translateValue = (value2) => {
17523
- const translations = {
17524
- ACTIVE: "فعال",
17525
- INACTIVE: "غیرفعال",
17526
- PENDING: "در انتظار",
17527
- COMPLETED: "تکمیل شده"
17528
- // Add more translations as needed
17529
- };
17530
- return translations[value2] || value2;
17206
+ const resolveAutocompleteItems = (header, context) => {
17207
+ const enhancedHeader = header;
17208
+ const source = enhancedHeader.autocompleteItems;
17209
+ if (!source) return [];
17210
+ try {
17211
+ if (typeof source === "function") {
17212
+ const baseContext = context ?? formModel.value;
17213
+ return source(baseContext) ?? [];
17214
+ }
17215
+ if (isRef(source)) {
17216
+ return source.value ?? [];
17217
+ }
17218
+ const resolved = unref(source);
17219
+ return Array.isArray(resolved) ? resolved : [];
17220
+ } catch (error2) {
17221
+ console.error("Error resolving autocomplete items for header:", header.key, error2);
17222
+ return [];
17223
+ }
17531
17224
  };
17532
- const handleFilterApply = (filterData) => {
17533
- filterModel.value = filterData;
17534
- currentPage.value = 1;
17535
- debouncedFetchData();
17536
- filterDialog.value = false;
17225
+ const resolveHeaderDefaultValue = (header, context) => {
17226
+ const rawDefault = header.defaultValue;
17227
+ if (rawDefault === void 0) {
17228
+ return void 0;
17229
+ }
17230
+ try {
17231
+ if (typeof rawDefault === "function") {
17232
+ return rawDefault(context);
17233
+ }
17234
+ if (isRef(rawDefault)) {
17235
+ return unref(rawDefault);
17236
+ }
17237
+ return rawDefault;
17238
+ } catch (error2) {
17239
+ console.error("Error resolving default value for header:", header.key, error2);
17240
+ return void 0;
17241
+ }
17537
17242
  };
17538
- return (_ctx, _cache) => {
17539
- var _a;
17540
- return openBlock(), createElementBlock(Fragment, null, [
17541
- props.title ? (openBlock(), createElementBlock("div", _hoisted_1$9, [
17542
- createElementVNode("h3", _hoisted_2$5, toDisplayString(props.title), 1)
17543
- ])) : createCommentVNode("", true),
17544
- createElementVNode("div", _hoisted_3$4, [
17545
- ((_a = props.actions) == null ? void 0 : _a.includes("create")) ? (openBlock(), createBlock(VBtn, {
17546
- key: 0,
17547
- color: "green",
17548
- class: "me-2",
17549
- onClick: _cache[0] || (_cache[0] = ($event) => openDialog())
17550
- }, {
17551
- default: withCtx(() => [..._cache[19] || (_cache[19] = [
17552
- createTextVNode("ایجاد ✅", -1)
17553
- ])]),
17554
- _: 1
17555
- })) : createCommentVNode("", true),
17556
- hasFilterComponent.value ? (openBlock(), createBlock(VBtn, {
17557
- key: 1,
17558
- class: "me-2",
17559
- onClick: _cache[1] || (_cache[1] = ($event) => filterDialog.value = true)
17560
- }, {
17561
- default: withCtx(() => [..._cache[20] || (_cache[20] = [
17562
- createTextVNode("فیلتر 🔍", -1)
17563
- ])]),
17564
- _: 1
17565
- })) : createCommentVNode("", true),
17566
- props.showRefreshButton ? (openBlock(), createBlock(VBtn, {
17567
- key: 2,
17568
- color: "blue",
17569
- onClick: unref(debouncedFetchData),
17570
- loading: loading.value
17571
- }, {
17572
- default: withCtx(() => [..._cache[21] || (_cache[21] = [
17573
- createTextVNode("بروزرسانی 🔄", -1)
17574
- ])]),
17575
- _: 1
17576
- }, 8, ["onClick", "loading"])) : createCommentVNode("", true),
17577
- props.selectable && hasSelection.value ? (openBlock(), createElementBlock("div", _hoisted_4$2, [
17578
- createVNode(VChip, {
17579
- color: "primary",
17580
- class: "me-2"
17581
- }, {
17582
- default: withCtx(() => [
17583
- createTextVNode(toDisplayString(selectedCount.value) + " آیتم انتخاب شده ", 1)
17584
- ]),
17585
- _: 1
17586
- }),
17587
- createVNode(VBtn, {
17588
- color: "error",
17589
- size: "small",
17590
- class: "me-2",
17591
- onClick: clearSelection
17592
- }, {
17593
- default: withCtx(() => [..._cache[22] || (_cache[22] = [
17594
- createTextVNode(" پاک کردن انتخاب ", -1)
17595
- ])]),
17596
- _: 1
17597
- })
17598
- ])) : createCommentVNode("", true),
17599
- createVNode(Transition, {
17600
- name: "slide-left",
17601
- appear: ""
17602
- }, {
17603
- default: withCtx(() => [
17604
- props.bulkMode && hasValidSelection.value || props.enableGroupDelete && hasSelection.value ? (openBlock(), createElementBlock("div", _hoisted_5$2, [
17605
- props.enableGroupDelete ? (openBlock(), createBlock(VBtn, {
17606
- key: 0,
17607
- color: "red",
17608
- size: "small",
17609
- class: "me-2",
17610
- onClick: openGroupDeleteDialog
17611
- }, {
17612
- default: withCtx(() => [
17613
- _cache[23] || (_cache[23] = createElementVNode("span", { class: "me-1" }, "🗑️", -1)),
17614
- createTextVNode(" حذف گروهی (" + toDisplayString(selectedCount.value) + ") ", 1)
17615
- ]),
17616
- _: 1
17617
- })) : createCommentVNode("", true),
17618
- props.bulkMode ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(validSelectedItems.value, (item) => {
17619
- var _a2, _b, _c;
17620
- return openBlock(), createElementBlock(Fragment, {
17621
- key: getUniqueValue(item)
17622
- }, [
17623
- ((_a2 = props.actions) == null ? void 0 : _a2.includes("edit")) ? (openBlock(), createBlock(VBtn, {
17624
- key: 0,
17625
- color: "blue",
17626
- size: "small",
17627
- class: "me-2",
17628
- onClick: ($event) => openDialog(item)
17629
- }, {
17630
- default: withCtx(() => [..._cache[24] || (_cache[24] = [
17631
- createElementVNode("span", { class: "me-1" }, "✏️", -1),
17632
- createTextVNode(" ویرایش ", -1)
17633
- ])]),
17634
- _: 1
17635
- }, 8, ["onClick"])) : createCommentVNode("", true),
17636
- ((_b = props.actions) == null ? void 0 : _b.includes("delete")) ? (openBlock(), createBlock(VBtn, {
17637
- key: 1,
17638
- color: "red",
17639
- size: "small",
17640
- class: "me-2",
17641
- onClick: ($event) => openDeleteDialog(item)
17642
- }, {
17643
- default: withCtx(() => [..._cache[25] || (_cache[25] = [
17644
- createElementVNode("span", { class: "me-1" }, "🗑️", -1),
17645
- createTextVNode(" حذف ", -1)
17646
- ])]),
17647
- _: 1
17648
- }, 8, ["onClick"])) : createCommentVNode("", true),
17649
- ((_c = props.actions) == null ? void 0 : _c.includes("view")) ? (openBlock(), createBlock(VBtn, {
17650
- key: 2,
17651
- color: "purple",
17652
- size: "small",
17653
- class: "me-2",
17654
- onClick: ($event) => goToRoute("view", item)
17655
- }, {
17656
- default: withCtx(() => [..._cache[26] || (_cache[26] = [
17657
- createElementVNode("span", { class: "me-1" }, "👁️", -1),
17658
- createTextVNode(" نمایش ", -1)
17659
- ])]),
17660
- _: 1
17661
- }, 8, ["onClick"])) : createCommentVNode("", true),
17662
- (openBlock(true), createElementBlock(Fragment, null, renderList(getRoutesForItem(item), (routePath, routeKey) => {
17663
- return openBlock(), createBlock(VBtn, {
17664
- key: routeKey,
17665
- color: "indigo",
17666
- size: "small",
17667
- class: "me-2",
17668
- onClick: ($event) => goToRoute(routeKey, item)
17669
- }, {
17670
- default: withCtx(() => [
17671
- _cache[27] || (_cache[27] = createElementVNode("span", { class: "me-1" }, "➡️", -1)),
17672
- createTextVNode(" " + toDisplayString(String(routeKey)), 1)
17673
- ]),
17674
- _: 2
17675
- }, 1032, ["onClick"]);
17676
- }), 128)),
17677
- (openBlock(true), createElementBlock(Fragment, null, renderList(props.downloadLink, (value2, key2) => {
17678
- return openBlock(), createBlock(VBtn, {
17679
- size: "small",
17680
- class: "me-2",
17681
- key: key2,
17682
- onClick: ($event) => download(key2, item)
17683
- }, {
17684
- default: withCtx(() => [
17685
- _cache[28] || (_cache[28] = createElementVNode("span", { class: "me-1" }, "⬇️", -1)),
17686
- createTextVNode(" " + toDisplayString(key2), 1)
17687
- ]),
17688
- _: 2
17689
- }, 1032, ["onClick"]);
17690
- }), 128)),
17691
- (openBlock(true), createElementBlock(Fragment, null, renderList(props.customActions, (action, index2) => {
17692
- return openBlock(), createElementBlock(Fragment, {
17693
- key: action.title || index2
17694
- }, [
17695
- !action.condition || action.condition(item) ? (openBlock(), createBlock(VBtn, {
17696
- key: 0,
17697
- color: "orange",
17698
- size: "small",
17699
- class: "me-2",
17700
- onClick: ($event) => openCustomActionDialog(action, item)
17701
- }, {
17702
- default: withCtx(() => [
17703
- createTextVNode(toDisplayString(action.title), 1)
17704
- ]),
17705
- _: 2
17706
- }, 1032, ["onClick"])) : createCommentVNode("", true)
17707
- ], 64);
17708
- }), 128)),
17709
- props.customButtonsFn ? (openBlock(true), createElementBlock(Fragment, { key: 3 }, renderList(props.customButtonsFn(item), (button) => {
17710
- return openBlock(), createBlock(VBtn, {
17711
- key: button.label,
17712
- color: button.color || "primary",
17713
- size: "small",
17714
- class: "me-2",
17715
- disabled: button.disabled,
17716
- onClick: ($event) => button.onClick(item)
17717
- }, {
17718
- default: withCtx(() => [
17719
- button.icon ? (openBlock(), createElementBlock("span", _hoisted_6$1, toDisplayString(button.icon), 1)) : createCommentVNode("", true),
17720
- createTextVNode(" " + toDisplayString(button.label), 1)
17721
- ]),
17722
- _: 2
17723
- }, 1032, ["color", "disabled", "onClick"]);
17724
- }), 128)) : (openBlock(true), createElementBlock(Fragment, { key: 4 }, renderList(props.customButtons, (button) => {
17725
- return openBlock(), createBlock(VBtn, {
17726
- key: button.label,
17727
- color: button.color || "primary",
17728
- size: "small",
17729
- class: "me-2",
17730
- onClick: ($event) => button.onClick(item)
17731
- }, {
17732
- default: withCtx(() => [
17733
- button.icon ? (openBlock(), createElementBlock("span", _hoisted_7$1, toDisplayString(button.icon), 1)) : createCommentVNode("", true),
17734
- createTextVNode(" " + toDisplayString(button.label), 1)
17735
- ]),
17736
- _: 2
17737
- }, 1032, ["color", "onClick"]);
17738
- }), 128))
17739
- ], 64);
17740
- }), 128)) : createCommentVNode("", true)
17741
- ])) : createCommentVNode("", true)
17742
- ]),
17743
- _: 1
17744
- })
17745
- ]),
17746
- createElementVNode("div", mergeProps({ class: "data-table-container" }, _ctx.$attrs, {
17747
- role: "region",
17748
- "aria-busy": loading.value || isLoadingMore.value,
17749
- "aria-live": loading.value || isLoadingMore.value ? "polite" : "off"
17750
- }), [
17751
- loading.value && !isLoadingMore.value ? (openBlock(), createElementBlock("div", {
17752
- key: 0,
17753
- class: "skeleton-container",
17754
- style: normalizeStyle({ height: `${props.height}px` })
17755
- }, [
17756
- createVNode(VSkeletonLoader, {
17757
- type: "table",
17758
- loading: loading.value,
17759
- class: "mx-auto",
17760
- "max-width": "100%",
17761
- boilerplate: false
17762
- }, null, 8, ["loading"])
17763
- ], 4)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
17764
- props.groupBy && unref(groupedItems).length > 0 ? (openBlock(), createElementBlock("div", _hoisted_9$1, [
17765
- createElementVNode("div", _hoisted_10$1, [
17766
- createVNode(VBtn, {
17767
- size: "small",
17768
- color: "primary",
17769
- onClick: expandAllGroups,
17770
- class: "me-2"
17771
- }, {
17772
- default: withCtx(() => [..._cache[29] || (_cache[29] = [
17773
- createTextVNode(" گسترش همه ", -1)
17774
- ])]),
17775
- _: 1
17776
- }),
17777
- createVNode(VBtn, {
17778
- size: "small",
17779
- color: "secondary",
17780
- onClick: collapseAllGroups,
17781
- class: "me-2"
17782
- }, {
17783
- default: withCtx(() => [..._cache[30] || (_cache[30] = [
17784
- createTextVNode(" جمع کردن همه ", -1)
17785
- ])]),
17786
- _: 1
17787
- })
17788
- ]),
17789
- createElementVNode("div", {
17790
- class: "groups-scroll-container",
17791
- style: normalizeStyle({ height: `${props.height - 120}px` })
17792
- }, [
17793
- createElementVNode("div", _hoisted_11$1, [
17794
- (openBlock(true), createElementBlock(Fragment, null, renderList(unref(groupedItems), (group) => {
17795
- return openBlock(), createElementBlock("div", {
17796
- key: group.groupKey,
17797
- class: "group-section"
17798
- }, [
17799
- createElementVNode("div", {
17800
- class: normalizeClass(["group-header", { expanded: group.isExpanded }]),
17801
- role: "button",
17802
- tabindex: "0",
17803
- onClick: withModifiers(($event) => toggleGroup(group.groupKey), ["stop"]),
17804
- onMousedown: _cache[2] || (_cache[2] = withModifiers(() => {
17805
- }, ["stop"])),
17806
- onKeydown: [
17807
- withKeys(withModifiers(($event) => toggleGroup(group.groupKey), ["prevent"]), ["enter"]),
17808
- withKeys(withModifiers(($event) => toggleGroup(group.groupKey), ["prevent"]), ["space"])
17809
- ],
17810
- "aria-expanded": group.isExpanded ? "true" : "false",
17811
- "aria-controls": `group-panel-${group.groupKey}`,
17812
- id: `group-header-${group.groupKey}`
17813
- }, [
17814
- group.isExpanded ? (openBlock(), createBlock(unref(IconChevronDown), {
17815
- key: 0,
17816
- class: "me-2 chevron-icon"
17817
- })) : (openBlock(), createBlock(unref(IconChevronRight), {
17818
- key: 1,
17819
- class: "me-2 chevron-icon"
17820
- })),
17821
- createElementVNode("span", _hoisted_13$1, toDisplayString(group.groupLabel), 1),
17822
- createVNode(VChip, {
17823
- size: "small",
17824
- color: "darkprimary",
17825
- class: "ms-auto"
17826
- }, {
17827
- default: withCtx(() => [
17828
- createTextVNode(toDisplayString(group.count), 1)
17829
- ]),
17830
- _: 2
17831
- }, 1024)
17832
- ], 42, _hoisted_12$1),
17833
- createVNode(Transition, {
17834
- name: "group-expand",
17835
- appear: ""
17836
- }, {
17837
- default: withCtx(() => [
17838
- group.isExpanded ? (openBlock(), createElementBlock("div", {
17839
- key: 0,
17840
- class: "group-items",
17841
- id: `group-panel-${group.groupKey}`,
17842
- "aria-labelledby": `group-header-${group.groupKey}`,
17843
- role: "region"
17844
- }, [
17845
- createVNode(VDataTable, {
17846
- headers: groupedHeaders.value,
17847
- items: group.items,
17848
- "items-per-page": itemsPerPage.value,
17849
- "hide-default-footer": "",
17850
- class: "elevation-1 group-table",
17851
- "no-data-text": "رکوردی یافت نشد",
17852
- hover: "",
17853
- height: "auto",
17854
- density: "compact"
17855
- }, {
17856
- "header.selection": withCtx(({ column }) => [
17857
- props.selectable && props.multiSelect ? (openBlock(), createBlock(VCheckbox, {
17858
- key: 0,
17859
- "model-value": selectAll.value,
17860
- "onUpdate:modelValue": toggleSelectAll,
17861
- indeterminate: selectedCount.value > 0 && selectedCount.value < items.value.length,
17862
- "hide-details": "",
17863
- density: "compact"
17864
- }, null, 8, ["model-value", "indeterminate"])) : createCommentVNode("", true)
17865
- ]),
17866
- item: withCtx(({ item, columns, index: index2 }) => [
17867
- createElementVNode("tr", {
17868
- style: normalizeStyle({
17869
- background: isSelected(item) && props.bulkMode ? "rgb(var(--v-theme-primary200))" : index2 % 2 === 0 ? "rgb(var(--v-theme-surface))" : "rgb(var(--v-theme-lightprimary))",
17870
- cursor: props.bulkMode && props.selectable ? "pointer" : "default"
17871
- }),
17872
- tabindex: props.selectable ? 0 : -1,
17873
- onKeydown: withKeys(withModifiers(($event) => props.selectable && toggleSelection(item), ["prevent"]), ["enter"]),
17874
- onClick: ($event) => props.bulkMode && props.selectable && selectSingleItem(item)
17875
- }, [
17876
- (openBlock(true), createElementBlock(Fragment, null, renderList(columns, (column) => {
17877
- var _a2, _b, _c;
17878
- return openBlock(), createElementBlock("td", {
17879
- key: column.key || "unknown",
17880
- style: normalizeStyle({
17881
- ...getColumnStyle(column, item),
17882
- ...column.width ? { width: column.width + "px", minWidth: column.width + "px", maxWidth: column.width + "px" } : {}
17883
- })
17884
- }, [
17885
- column.key === "selection" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
17886
- props.bulkMode ? (openBlock(), createBlock(VRadio, {
17887
- key: 0,
17888
- "model-value": radioGroupValue.value,
17889
- value: getUniqueValue(item),
17890
- onClick: withModifiers(($event) => selectSingleItem(item), ["stop"]),
17891
- disabled: !props.selectable,
17892
- "hide-details": "",
17893
- density: "compact"
17894
- }, null, 8, ["model-value", "value", "onClick", "disabled"])) : (openBlock(), createBlock(VCheckbox, {
17895
- key: 1,
17896
- "model-value": isSelected(item),
17897
- "onUpdate:modelValue": ($event) => toggleSelection(item),
17898
- disabled: !props.selectable,
17899
- "hide-details": "",
17900
- density: "compact"
17901
- }, null, 8, ["model-value", "onUpdate:modelValue", "disabled"]))
17902
- ], 64)) : createCommentVNode("", true),
17903
- column.key === "actions" && hasAnyActions.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
17904
- ((_a2 = props.actions) == null ? void 0 : _a2.includes("edit")) ? (openBlock(), createBlock(VBtn, {
17905
- key: 0,
17906
- color: "blue",
17907
- size: "small",
17908
- class: "mr-2",
17909
- onClick: ($event) => openDialog(item)
17910
- }, {
17911
- default: withCtx(() => [..._cache[31] || (_cache[31] = [
17912
- createTextVNode(" ویرایش ✏️ ", -1)
17913
- ])]),
17914
- _: 1
17915
- }, 8, ["onClick"])) : createCommentVNode("", true),
17916
- ((_b = props.actions) == null ? void 0 : _b.includes("delete")) ? (openBlock(), createBlock(VBtn, {
17917
- key: 1,
17918
- color: "red",
17919
- size: "small",
17920
- class: "mr-2",
17921
- onClick: ($event) => openDeleteDialog(item)
17922
- }, {
17923
- default: withCtx(() => [..._cache[32] || (_cache[32] = [
17924
- createTextVNode("حذف ❌ ", -1)
17925
- ])]),
17926
- _: 1
17927
- }, 8, ["onClick"])) : createCommentVNode("", true),
17928
- ((_c = props.actions) == null ? void 0 : _c.includes("view")) ? (openBlock(), createBlock(VBtn, {
17929
- key: 2,
17930
- color: "purple",
17931
- size: "small",
17932
- class: "mr-2",
17933
- onClick: ($event) => goToRoute("view", item)
17934
- }, {
17935
- default: withCtx(() => [..._cache[33] || (_cache[33] = [
17936
- createTextVNode("🔍 نمایش ", -1)
17937
- ])]),
17938
- _: 1
17939
- }, 8, ["onClick"])) : createCommentVNode("", true),
17940
- (openBlock(true), createElementBlock(Fragment, null, renderList(getRoutesForItem(item), (routePath, routeKey) => {
17941
- return openBlock(), createBlock(VBtn, {
17942
- key: routeKey,
17943
- color: "indigo",
17944
- size: "small",
17945
- class: "mr-2",
17946
- onClick: ($event) => goToRoute(routeKey, item)
17947
- }, {
17948
- default: withCtx(() => [
17949
- createTextVNode(toDisplayString(routeKey.toUpperCase()), 1)
17950
- ]),
17951
- _: 2
17952
- }, 1032, ["onClick"]);
17953
- }), 128)),
17954
- (openBlock(true), createElementBlock(Fragment, null, renderList(props.downloadLink, (value2, key2) => {
17955
- return openBlock(), createBlock(VBtn, {
17956
- size: "small",
17957
- class: "mr-2",
17958
- key: key2,
17959
- onClick: ($event) => download(key2, item)
17960
- }, {
17961
- default: withCtx(() => [
17962
- createTextVNode(toDisplayString(key2) + " ⬇️ ", 1)
17963
- ]),
17964
- _: 2
17965
- }, 1032, ["onClick"]);
17966
- }), 128)),
17967
- (openBlock(true), createElementBlock(Fragment, null, renderList(props.customActions, (action, index22) => {
17968
- return openBlock(), createElementBlock(Fragment, {
17969
- key: action.title || index22
17970
- }, [
17971
- !action.condition || action.condition(item) ? (openBlock(), createBlock(VBtn, {
17972
- key: 0,
17973
- color: "orange",
17974
- size: "small",
17975
- class: "mr-2",
17976
- onClick: ($event) => openCustomActionDialog(action, item)
17977
- }, {
17978
- default: withCtx(() => [
17979
- createTextVNode(toDisplayString(action.title), 1)
17980
- ]),
17981
- _: 2
17982
- }, 1032, ["onClick"])) : createCommentVNode("", true)
17983
- ], 64);
17984
- }), 128)),
17985
- props.customButtonsFn ? (openBlock(true), createElementBlock(Fragment, { key: 3 }, renderList(props.customButtonsFn(item), (button) => {
17986
- return openBlock(), createBlock(VBtn, {
17987
- key: button.label,
17988
- color: button.color || "primary",
17989
- size: "small",
17990
- class: "mr-2",
17991
- disabled: button.disabled,
17992
- onClick: ($event) => button.onClick(item)
17993
- }, {
17994
- default: withCtx(() => [
17995
- createTextVNode(toDisplayString(button.label), 1)
17996
- ]),
17997
- _: 2
17998
- }, 1032, ["color", "disabled", "onClick"]);
17999
- }), 128)) : (openBlock(true), createElementBlock(Fragment, { key: 4 }, renderList(props.customButtons, (button) => {
18000
- return openBlock(), createBlock(VBtn, {
18001
- key: button.label,
18002
- color: button.color || "primary",
18003
- size: "small",
18004
- class: "mr-2",
18005
- onClick: ($event) => button.onClick(item)
18006
- }, {
18007
- default: withCtx(() => [
18008
- createTextVNode(toDisplayString(button.label), 1)
18009
- ]),
18010
- _: 2
18011
- }, 1032, ["color", "onClick"]);
18012
- }), 128))
18013
- ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [
18014
- createTextVNode(toDisplayString(getTranslatedValue(getNestedValue2(item, column.key || ""), column, item)), 1)
18015
- ], 64))
18016
- ], 4);
18017
- }), 128))
18018
- ], 44, _hoisted_15$1)
18019
- ]),
18020
- _: 1
18021
- }, 8, ["headers", "items", "items-per-page"])
18022
- ], 8, _hoisted_14$1)) : createCommentVNode("", true)
18023
- ]),
18024
- _: 2
18025
- }, 1024)
18026
- ]);
18027
- }), 128))
18028
- ])
18029
- ], 4)
18030
- ])) : (openBlock(), createBlock(VDataTable, {
18031
- key: 1,
18032
- headers: normalHeaders.value,
18033
- items: items.value,
18034
- "items-per-page": itemsPerPage.value,
18035
- "hide-default-footer": "",
18036
- class: "elevation-1",
18037
- "no-data-text": "رکوردی یافت نشد",
18038
- hover: "",
18039
- height: props.height,
18040
- density: "compact"
18041
- }, {
18042
- "header.selection": withCtx(({ column }) => [
18043
- props.selectable && props.multiSelect ? (openBlock(), createBlock(VCheckbox, {
18044
- key: 0,
18045
- "model-value": selectAll.value,
18046
- "onUpdate:modelValue": toggleSelectAll,
18047
- indeterminate: selectedCount.value > 0 && selectedCount.value < items.value.length,
18048
- "hide-details": "",
18049
- density: "compact"
18050
- }, null, 8, ["model-value", "indeterminate"])) : createCommentVNode("", true)
18051
- ]),
18052
- item: withCtx(({ item, columns, index: index2 }) => [
18053
- createElementVNode("tr", {
18054
- style: normalizeStyle({
18055
- color: isSelected(item) && props.bulkMode ? "rgb(var(--v-theme-white))" : "rgb(var(--v-theme-darkText))",
18056
- background: isSelected(item) && props.bulkMode ? "rgb(var(--v-theme-primary))" : index2 % 2 === 0 ? "rgb(var(--v-theme-surface))" : "rgb(var(--v-theme-lightprimary))",
18057
- cursor: props.bulkMode && props.selectable ? "pointer" : "default"
18058
- }),
18059
- tabindex: props.selectable ? 0 : -1,
18060
- onKeydown: withKeys(withModifiers(($event) => props.selectable && toggleSelection(item), ["prevent"]), ["enter"]),
18061
- onClick: ($event) => props.bulkMode && props.selectable && selectSingleItem(item)
18062
- }, [
18063
- (openBlock(true), createElementBlock(Fragment, null, renderList(columns, (column) => {
18064
- var _a2, _b, _c;
18065
- return openBlock(), createElementBlock("td", {
18066
- key: column.key || "unknown",
18067
- style: normalizeStyle({
18068
- ...getColumnStyle(column, item),
18069
- ...column.width ? { width: column.width + "px", minWidth: column.width + "px", maxWidth: column.width + "px" } : {}
18070
- })
18071
- }, [
18072
- column.key === "selection" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
18073
- props.bulkMode ? (openBlock(), createBlock(VRadio, {
18074
- key: 0,
18075
- "model-value": radioGroupValue.value,
18076
- value: getUniqueValue(item),
18077
- onClick: withModifiers(($event) => selectSingleItem(item), ["stop"]),
18078
- disabled: !props.selectable,
18079
- "hide-details": "",
18080
- density: "compact"
18081
- }, null, 8, ["model-value", "value", "onClick", "disabled"])) : (openBlock(), createBlock(VCheckbox, {
18082
- key: 1,
18083
- "model-value": isSelected(item),
18084
- "onUpdate:modelValue": ($event) => toggleSelection(item),
18085
- disabled: !props.selectable,
18086
- "hide-details": "",
18087
- density: "compact"
18088
- }, null, 8, ["model-value", "onUpdate:modelValue", "disabled"]))
18089
- ], 64)) : createCommentVNode("", true),
18090
- column.key === "actions" && hasAnyActions.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
18091
- ((_a2 = props.actions) == null ? void 0 : _a2.includes("edit")) ? (openBlock(), createBlock(VBtn, {
18092
- key: 0,
18093
- color: "blue",
18094
- size: "small",
18095
- class: "mr-2",
18096
- onClick: ($event) => openDialog(item)
18097
- }, {
18098
- default: withCtx(() => [..._cache[34] || (_cache[34] = [
18099
- createTextVNode(" ویرایش ✏️ ", -1)
18100
- ])]),
18101
- _: 1
18102
- }, 8, ["onClick"])) : createCommentVNode("", true),
18103
- ((_b = props.actions) == null ? void 0 : _b.includes("delete")) ? (openBlock(), createBlock(VBtn, {
18104
- key: 1,
18105
- color: "red",
18106
- size: "small",
18107
- class: "mr-2",
18108
- onClick: ($event) => openDeleteDialog(item)
18109
- }, {
18110
- default: withCtx(() => [..._cache[35] || (_cache[35] = [
18111
- createTextVNode("حذف ❌ ", -1)
18112
- ])]),
18113
- _: 1
18114
- }, 8, ["onClick"])) : createCommentVNode("", true),
18115
- ((_c = props.actions) == null ? void 0 : _c.includes("view")) ? (openBlock(), createBlock(VBtn, {
18116
- key: 2,
18117
- color: "purple",
18118
- size: "small",
18119
- class: "mr-2",
18120
- onClick: ($event) => goToRoute("view", item)
18121
- }, {
18122
- default: withCtx(() => [..._cache[36] || (_cache[36] = [
18123
- createTextVNode("🔍 نمایش ", -1)
18124
- ])]),
18125
- _: 1
18126
- }, 8, ["onClick"])) : createCommentVNode("", true),
18127
- (openBlock(true), createElementBlock(Fragment, null, renderList(getRoutesForItem(item), (routePath, routeKey) => {
18128
- return openBlock(), createBlock(VBtn, {
18129
- key: routeKey,
18130
- color: "indigo",
18131
- size: "small",
18132
- class: "mr-2",
18133
- onClick: ($event) => goToRoute(routeKey, item)
18134
- }, {
18135
- default: withCtx(() => [
18136
- createTextVNode(toDisplayString(routeKey.toUpperCase()), 1)
18137
- ]),
18138
- _: 2
18139
- }, 1032, ["onClick"]);
18140
- }), 128)),
18141
- (openBlock(true), createElementBlock(Fragment, null, renderList(props.downloadLink, (value2, key2) => {
18142
- return openBlock(), createBlock(VBtn, {
18143
- size: "small",
18144
- class: "mr-2",
18145
- key: key2,
18146
- onClick: ($event) => download(key2, item)
18147
- }, {
18148
- default: withCtx(() => [
18149
- createTextVNode(toDisplayString(key2) + " ⬇️ ", 1)
18150
- ]),
18151
- _: 2
18152
- }, 1032, ["onClick"]);
18153
- }), 128)),
18154
- (openBlock(true), createElementBlock(Fragment, null, renderList(props.customActions, (action, index22) => {
18155
- return openBlock(), createElementBlock(Fragment, {
18156
- key: action.title || index22
18157
- }, [
18158
- !action.condition || action.condition(item) ? (openBlock(), createBlock(VBtn, {
18159
- key: 0,
18160
- color: "orange",
18161
- size: "small",
18162
- class: "mr-2",
18163
- onClick: ($event) => openCustomActionDialog(action, item)
18164
- }, {
18165
- default: withCtx(() => [
18166
- createTextVNode(toDisplayString(action.title), 1)
18167
- ]),
18168
- _: 2
18169
- }, 1032, ["onClick"])) : createCommentVNode("", true)
18170
- ], 64);
18171
- }), 128)),
18172
- props.customButtonsFn ? (openBlock(true), createElementBlock(Fragment, { key: 3 }, renderList(props.customButtonsFn(item), (button) => {
18173
- return openBlock(), createBlock(VBtn, {
18174
- key: button.label,
18175
- color: button.color || "primary",
18176
- size: "small",
18177
- class: "mr-2",
18178
- disabled: button.disabled,
18179
- onClick: ($event) => button.onClick(item)
18180
- }, {
18181
- default: withCtx(() => [
18182
- createTextVNode(toDisplayString(button.label), 1)
18183
- ]),
18184
- _: 2
18185
- }, 1032, ["color", "disabled", "onClick"]);
18186
- }), 128)) : (openBlock(true), createElementBlock(Fragment, { key: 4 }, renderList(props.customButtons, (button) => {
18187
- return openBlock(), createBlock(VBtn, {
18188
- key: button.label,
18189
- color: button.color || "primary",
18190
- size: "small",
18191
- class: "mr-2",
18192
- onClick: ($event) => button.onClick(item)
18193
- }, {
18194
- default: withCtx(() => [
18195
- createTextVNode(toDisplayString(button.label), 1)
18196
- ]),
18197
- _: 2
18198
- }, 1032, ["color", "onClick"]);
18199
- }), 128))
18200
- ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [
18201
- createTextVNode(toDisplayString(getTranslatedValue(getNestedValue2(item, column.key || ""), column, item)), 1)
18202
- ], 64))
18203
- ], 4);
18204
- }), 128))
18205
- ], 44, _hoisted_16$1)
18206
- ]),
18207
- _: 1
18208
- }, 8, ["headers", "items", "items-per-page", "height"])),
18209
- isLoadingMore.value ? (openBlock(), createElementBlock("div", _hoisted_17, [
18210
- createVNode(VProgressCircular, {
18211
- indeterminate: "",
18212
- color: "primary"
18213
- })
18214
- ])) : createCommentVNode("", true)
18215
- ], 64)),
18216
- props.showPagination ? (openBlock(), createElementBlock("div", _hoisted_18, [
18217
- createElementVNode("div", _hoisted_19, [
18218
- createElementVNode("div", _hoisted_20, " نمایش " + toDisplayString((currentPage.value - 1) * itemsPerPage.value + 1) + " تا " + toDisplayString(Math.min(currentPage.value * itemsPerPage.value, totalSize.value)) + " از " + toDisplayString(totalSize.value) + " رکورد ", 1),
18219
- createVNode(VPagination, {
18220
- modelValue: currentPage.value,
18221
- "onUpdate:modelValue": [
18222
- _cache[3] || (_cache[3] = ($event) => currentPage.value = $event),
18223
- handlePageChange
18224
- ],
18225
- length: totalPages.value,
18226
- "total-visible": 5,
18227
- size: "small"
18228
- }, null, 8, ["modelValue", "length"])
18229
- ])
18230
- ])) : createCommentVNode("", true)
18231
- ], 16, _hoisted_8$1),
18232
- createVNode(VDialog, {
18233
- modelValue: dialog.value,
18234
- "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => dialog.value = $event),
18235
- "max-width": "1400"
18236
- }, {
18237
- default: withCtx(() => [
18238
- createVNode(VCard, null, {
18239
- default: withCtx(() => [
18240
- createVNode(VCardTitle, null, {
18241
- default: withCtx(() => [
18242
- createTextVNode(toDisplayString(isEditing.value ? "ویرایش" : "ایجاد"), 1)
18243
- ]),
18244
- _: 1
18245
- }),
18246
- createVNode(VCardText, null, {
18247
- default: withCtx(() => [
18248
- createVNode(VContainer, null, {
18249
- default: withCtx(() => [
18250
- props.formComponent ? (openBlock(), createBlock(resolveDynamicComponent(props.formComponent), {
18251
- key: 0,
18252
- modelValue: formModel.value,
18253
- "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => formModel.value = $event)
18254
- }, null, 8, ["modelValue"])) : (openBlock(), createBlock(VRow, { key: 1 }, {
18255
- default: withCtx(() => [
18256
- (openBlock(true), createElementBlock(Fragment, null, renderList(formHeaders.value, (header) => {
18257
- return openBlock(), createBlock(VCol, {
18258
- key: resolveHeaderKey(header),
18259
- cols: "12",
18260
- md: "4"
18261
- }, {
18262
- default: withCtx(() => [
18263
- !header.hidden ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
18264
- header.isDate ? (openBlock(), createBlock(ShamsiDatePicker, {
18265
- key: 0,
18266
- modelValue: formModel.value[resolveHeaderKey(header)],
18267
- "onUpdate:modelValue": ($event) => formModel.value[resolveHeaderKey(header)] = $event,
18268
- label: resolveHeaderTitle(header),
18269
- disabled: isHeaderDisabled(header)
18270
- }, null, 8, ["modelValue", "onUpdate:modelValue", "label", "disabled"])) : hasAutocomplete(header) ? (openBlock(), createBlock(VAutocomplete, {
18271
- key: 1,
18272
- modelValue: formModel.value[resolveHeaderKey(header)],
18273
- "onUpdate:modelValue": ($event) => formModel.value[resolveHeaderKey(header)] = $event,
18274
- label: resolveHeaderTitle(header),
18275
- items: resolveAutocompleteItems(header, formModel.value.value),
18276
- "item-title": resolveAutocompleteItemTitle(header),
18277
- "item-value": resolveAutocompleteItemValue(header),
18278
- "return-object": resolveAutocompleteReturnObject(header),
18279
- multiple: resolveAutocompleteMultiple(header),
18280
- chips: resolveAutocompleteMultiple(header),
18281
- "closable-chips": resolveAutocompleteMultiple(header),
18282
- disabled: isHeaderDisabled(header),
18283
- clearable: "",
18284
- variant: "outlined"
18285
- }, null, 8, ["modelValue", "onUpdate:modelValue", "label", "items", "item-title", "item-value", "return-object", "multiple", "chips", "closable-chips", "disabled"])) : isMoneyHeader(header) ? (openBlock(), createBlock(_sfc_main$h, {
18286
- key: 2,
18287
- modelValue: formModel.value[resolveHeaderKey(header)],
18288
- "onUpdate:modelValue": ($event) => formModel.value[resolveHeaderKey(header)] = $event,
18289
- label: resolveHeaderTitle(header),
18290
- disabled: isHeaderDisabled(header)
18291
- }, null, 8, ["modelValue", "onUpdate:modelValue", "label", "disabled"])) : (openBlock(), createBlock(VTextField, {
18292
- key: 3,
18293
- modelValue: formModel.value[resolveHeaderKey(header)],
18294
- "onUpdate:modelValue": ($event) => formModel.value[resolveHeaderKey(header)] = $event,
18295
- label: resolveHeaderTitle(header),
18296
- variant: "outlined",
18297
- disabled: isHeaderDisabled(header),
18298
- type: getFieldInputType(header)
18299
- }, null, 8, ["modelValue", "onUpdate:modelValue", "label", "disabled", "type"]))
18300
- ], 64)) : createCommentVNode("", true)
18301
- ]),
18302
- _: 2
18303
- }, 1024);
18304
- }), 128))
18305
- ]),
18306
- _: 1
18307
- }))
18308
- ]),
18309
- _: 1
18310
- })
18311
- ]),
18312
- _: 1
18313
- }),
18314
- createVNode(VCardActions, null, {
18315
- default: withCtx(() => [
18316
- createVNode(VBtn, {
18317
- variant: "tonal",
18318
- color: "error",
18319
- onClick: _cache[5] || (_cache[5] = ($event) => dialog.value = false)
18320
- }, {
18321
- default: withCtx(() => [..._cache[37] || (_cache[37] = [
18322
- createTextVNode("انصراف", -1)
18323
- ])]),
18324
- _: 1
18325
- }),
18326
- createVNode(VBtn, {
18327
- color: "primary",
18328
- var: "",
18329
- onClick: saveItem
18330
- }, {
18331
- default: withCtx(() => [
18332
- createTextVNode(toDisplayString(isEditing.value ? "ذخیره" : "ایجاد"), 1)
18333
- ]),
18334
- _: 1
18335
- })
18336
- ]),
18337
- _: 1
18338
- })
18339
- ]),
18340
- _: 1
18341
- })
18342
- ]),
18343
- _: 1
18344
- }, 8, ["modelValue"]),
18345
- createVNode(VDialog, {
18346
- modelValue: deleteDialog.value,
18347
- "onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => deleteDialog.value = $event),
18348
- "max-width": "400"
18349
- }, {
18350
- default: withCtx(() => [
18351
- createVNode(VCard, null, {
18352
- default: withCtx(() => [
18353
- createVNode(VCardTitle, null, {
18354
- default: withCtx(() => [..._cache[38] || (_cache[38] = [
18355
- createTextVNode("حذف آیتم", -1)
18356
- ])]),
18357
- _: 1
18358
- }),
18359
- createVNode(VCardText, null, {
18360
- default: withCtx(() => [..._cache[39] || (_cache[39] = [
18361
- createTextVNode(" آیا مایل به حذف این رکورد هستید ?", -1)
18362
- ])]),
18363
- _: 1
18364
- }),
18365
- createVNode(VCardActions, null, {
18366
- default: withCtx(() => [
18367
- createVNode(VBtn, {
18368
- color: "grey",
18369
- onClick: _cache[7] || (_cache[7] = ($event) => deleteDialog.value = false)
18370
- }, {
18371
- default: withCtx(() => [..._cache[40] || (_cache[40] = [
18372
- createTextVNode("انصراف", -1)
18373
- ])]),
18374
- _: 1
18375
- }),
18376
- createVNode(VBtn, {
18377
- color: "red",
18378
- onClick: _cache[8] || (_cache[8] = ($event) => {
18379
- var _a2;
18380
- return deleteItem(String(((_a2 = itemToDelete.value) == null ? void 0 : _a2.id) || ""));
18381
- })
18382
- }, {
18383
- default: withCtx(() => [..._cache[41] || (_cache[41] = [
18384
- createTextVNode("حذف", -1)
18385
- ])]),
18386
- _: 1
18387
- })
18388
- ]),
18389
- _: 1
18390
- })
18391
- ]),
18392
- _: 1
18393
- })
18394
- ]),
18395
- _: 1
18396
- }, 8, ["modelValue"]),
18397
- createVNode(VDialog, {
18398
- modelValue: groupDeleteDialog.value,
18399
- "onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => groupDeleteDialog.value = $event),
18400
- "max-width": "500"
18401
- }, {
18402
- default: withCtx(() => [
18403
- createVNode(VCard, null, {
18404
- default: withCtx(() => [
18405
- createVNode(VCardTitle, { class: "text-h6" }, {
18406
- default: withCtx(() => [
18407
- createVNode(VIcon, {
18408
- color: "red",
18409
- class: "me-2"
18410
- }, {
18411
- default: withCtx(() => [..._cache[42] || (_cache[42] = [
18412
- createTextVNode("🗑️", -1)
18413
- ])]),
18414
- _: 1
18415
- }),
18416
- _cache[43] || (_cache[43] = createTextVNode(" حذف گروهی ", -1))
18417
- ]),
18418
- _: 1
18419
- }),
18420
- createVNode(VCardText, null, {
18421
- default: withCtx(() => [
18422
- createElementVNode("p", null, [
18423
- _cache[44] || (_cache[44] = createTextVNode(" آیا مایل به حذف ", -1)),
18424
- createElementVNode("strong", null, toDisplayString(selectedCount.value), 1),
18425
- _cache[45] || (_cache[45] = createTextVNode(" آیتم انتخاب شده هستید؟ ", -1))
18426
- ]),
18427
- createVNode(VAlert, {
18428
- type: "warning",
18429
- variant: "tonal",
18430
- class: "mt-3"
18431
- }, {
18432
- default: withCtx(() => [..._cache[46] || (_cache[46] = [
18433
- createTextVNode(" این عمل قابل بازگشت نیست! ", -1)
18434
- ])]),
18435
- _: 1
18436
- })
18437
- ]),
18438
- _: 1
18439
- }),
18440
- createVNode(VCardActions, null, {
18441
- default: withCtx(() => [
18442
- createVNode(VSpacer),
18443
- createVNode(VBtn, {
18444
- color: "grey",
18445
- onClick: _cache[10] || (_cache[10] = ($event) => groupDeleteDialog.value = false)
18446
- }, {
18447
- default: withCtx(() => [..._cache[47] || (_cache[47] = [
18448
- createTextVNode("انصراف", -1)
18449
- ])]),
18450
- _: 1
18451
- }),
18452
- createVNode(VBtn, {
18453
- color: "red",
18454
- onClick: deleteGroupItems,
18455
- loading: loading.value
18456
- }, {
18457
- default: withCtx(() => [
18458
- createTextVNode(" حذف " + toDisplayString(selectedCount.value) + " آیتم ", 1)
18459
- ]),
18460
- _: 1
18461
- }, 8, ["loading"])
18462
- ]),
18463
- _: 1
18464
- })
18465
- ]),
18466
- _: 1
18467
- })
18468
- ]),
18469
- _: 1
18470
- }, 8, ["modelValue"]),
18471
- createVNode(VDialog, {
18472
- modelValue: customActionDialog.value,
18473
- "onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => customActionDialog.value = $event),
18474
- "max-width": "1300"
18475
- }, {
18476
- default: withCtx(() => [
18477
- createVNode(VCard, null, {
18478
- default: withCtx(() => [
18479
- createVNode(VCardTitle, null, {
18480
- default: withCtx(() => {
18481
- var _a2, _b;
18482
- return [
18483
- createTextVNode(toDisplayString(((_b = (_a2 = props.customActions) == null ? void 0 : _a2.find((a) => a.component === customActionComponent.value)) == null ? void 0 : _b.title) || ""), 1)
18484
- ];
18485
- }),
18486
- _: 1
18487
- }),
18488
- createVNode(VCardText, null, {
18489
- default: withCtx(() => [
18490
- customActionComponent.value ? (openBlock(), createBlock(resolveDynamicComponent(customActionComponent.value), {
18491
- key: 0,
18492
- item: customActionItem.value,
18493
- onClose: _cache[12] || (_cache[12] = ($event) => customActionDialog.value = false)
18494
- }, null, 40, ["item"])) : createCommentVNode("", true)
18495
- ]),
18496
- _: 1
18497
- })
18498
- ]),
18499
- _: 1
18500
- })
18501
- ]),
18502
- _: 1
18503
- }, 8, ["modelValue"]),
18504
- createVNode(VDialog, {
18505
- modelValue: filterDialog.value,
18506
- "onUpdate:modelValue": _cache[16] || (_cache[16] = ($event) => filterDialog.value = $event),
18507
- "max-width": "800"
18508
- }, {
18509
- default: withCtx(() => [
18510
- createVNode(VCard, null, {
18511
- default: withCtx(() => [
18512
- createVNode(VCardTitle, null, {
18513
- default: withCtx(() => [..._cache[48] || (_cache[48] = [
18514
- createTextVNode("فیلتر", -1)
18515
- ])]),
18516
- _: 1
18517
- }),
18518
- createVNode(VCardText, null, {
18519
- default: withCtx(() => [
18520
- props.filterComponent ? (openBlock(), createBlock(resolveDynamicComponent(props.filterComponent), {
18521
- key: 0,
18522
- modelValue: filterModel.value,
18523
- "onUpdate:modelValue": [
18524
- _cache[14] || (_cache[14] = ($event) => filterModel.value = $event),
18525
- _cache[15] || (_cache[15] = ($event) => filterModel.value = $event)
18526
- ],
18527
- onApply: handleFilterApply
18528
- }, null, 40, ["modelValue"])) : createCommentVNode("", true)
18529
- ]),
18530
- _: 1
18531
- })
18532
- ]),
18533
- _: 1
18534
- })
18535
- ]),
18536
- _: 1
18537
- }, 8, ["modelValue"]),
18538
- snackbar.value ? (openBlock(), createBlock(VSnackbar, {
18539
- key: 1,
18540
- modelValue: snackbar.value,
18541
- "onUpdate:modelValue": _cache[18] || (_cache[18] = ($event) => snackbar.value = $event),
18542
- timeout: 3e3,
18543
- location: "top"
18544
- }, {
18545
- actions: withCtx(() => [
18546
- createVNode(VBtn, {
18547
- color: "white",
18548
- variant: "text",
18549
- onClick: _cache[17] || (_cache[17] = ($event) => snackbar.value = false)
18550
- }, {
18551
- default: withCtx(() => [..._cache[49] || (_cache[49] = [
18552
- createTextVNode(" بستن ", -1)
18553
- ])]),
18554
- _: 1
18555
- })
18556
- ]),
18557
- default: withCtx(() => [
18558
- createTextVNode(toDisplayString(snackbarMessage.value) + " ", 1)
18559
- ]),
18560
- _: 1
18561
- }, 8, ["modelValue"])) : createCommentVNode("", true)
18562
- ], 64);
17243
+ const resolveAutocompleteItemTitle = (header) => {
17244
+ return header.autocompleteItemTitle ?? "title";
17245
+ };
17246
+ const resolveAutocompleteItemValue = (header) => {
17247
+ return header.autocompleteItemValue ?? "value";
17248
+ };
17249
+ const resolveAutocompleteReturnObject = (header) => {
17250
+ const value2 = header.autocompleteReturnObject;
17251
+ return value2 !== false;
17252
+ };
17253
+ const resolveAutocompleteMultiple = (header) => {
17254
+ return header.autocompleteMultiple === true;
17255
+ };
17256
+ const formHeaders = computed(() => props.headers);
17257
+ const isMoneyHeader = (header) => {
17258
+ if (!header || typeof header.type !== "string") {
17259
+ return false;
17260
+ }
17261
+ return header.type.toLowerCase() === "money";
17262
+ };
17263
+ const getFieldInputType = (header) => {
17264
+ return typeof (header == null ? void 0 : header.type) === "string" ? header.type : void 0;
17265
+ };
17266
+ const resolveHeaderKey = (header) => header.key;
17267
+ const resolveHeaderTitle = (header) => header.title;
17268
+ const isHeaderDisabled = (header) => header.editable === false;
17269
+ const getUniqueValue = (item) => {
17270
+ if (typeof props.uniqueKey === "function") {
17271
+ return props.uniqueKey(item);
17272
+ }
17273
+ if (typeof props.uniqueKey === "string") {
17274
+ return props.uniqueKey.split(".").reduce((obj, key2) => obj == null ? void 0 : obj[key2], item);
17275
+ }
17276
+ return item.id;
17277
+ };
17278
+ const toggleSelection = (item) => {
17279
+ if (!props.selectable) return;
17280
+ selection.toggleSelection(item);
17281
+ emit("update:selectedItems", selectedItems.value);
17282
+ emit("selection-change", selectedItems.value);
17283
+ };
17284
+ const toggleSelectAll = () => {
17285
+ if (!props.selectable || !props.multiSelect) return;
17286
+ selection.toggleSelectAll();
17287
+ emit("update:selectedItems", selectedItems.value);
17288
+ emit("selection-change", selectedItems.value);
17289
+ };
17290
+ const toggleGroup = (groupKey) => {
17291
+ setTimeout(() => {
17292
+ selection.toggleGroup(groupKey);
17293
+ }, 0);
17294
+ };
17295
+ const expandAllGroups = () => selection.expandAllGroups();
17296
+ const collapseAllGroups = () => selection.collapseAllGroups();
17297
+ const isSelected = (item) => selection.isSelected(item);
17298
+ const selectedCount = computed(() => selectedItems.value.length);
17299
+ const hasSelection = computed(() => selectedItems.value.length > 0);
17300
+ const validSelectedItems = computed(() => {
17301
+ if (!props.selectable || !props.bulkMode) return selectedItems.value;
17302
+ return selectedItems.value.filter((selectedItem) => {
17303
+ const uniqueValue = getUniqueValue(selectedItem);
17304
+ return items.value.some((item) => getUniqueValue(item) === uniqueValue);
17305
+ });
17306
+ });
17307
+ const hasValidSelection = computed(() => {
17308
+ if (!props.selectable || !props.bulkMode) return hasSelection.value;
17309
+ return validSelectedItems.value.length > 0;
17310
+ });
17311
+ const clearSelection = () => {
17312
+ selection.clearSelection();
17313
+ emit("update:selectedItems", selectedItems.value);
17314
+ emit("selection-change", selectedItems.value);
18563
17315
  };
18564
- }
18565
- });
18566
- const makeVTextareaProps = propsFactory({
18567
- autoGrow: Boolean,
18568
- autofocus: Boolean,
18569
- counter: [Boolean, Number, String],
18570
- counterValue: Function,
18571
- prefix: String,
18572
- placeholder: String,
18573
- persistentPlaceholder: Boolean,
18574
- persistentCounter: Boolean,
18575
- noResize: Boolean,
18576
- rows: {
18577
- type: [Number, String],
18578
- default: 5,
18579
- validator: (v) => !isNaN(parseFloat(v))
18580
- },
18581
- maxRows: {
18582
- type: [Number, String],
18583
- validator: (v) => !isNaN(parseFloat(v))
18584
- },
18585
- suffix: String,
18586
- modelModifiers: Object,
18587
- ...makeAutocompleteProps(),
18588
- ...makeVInputProps(),
18589
- ...makeVFieldProps()
18590
- }, "VTextarea");
18591
- const VTextarea = genericComponent()({
18592
- name: "VTextarea",
18593
- directives: {
18594
- vIntersect: Intersect
18595
- },
18596
- inheritAttrs: false,
18597
- props: makeVTextareaProps(),
18598
- emits: {
18599
- "click:control": (e) => true,
18600
- "mousedown:control": (e) => true,
18601
- "update:focused": (focused) => true,
18602
- "update:modelValue": (val2) => true,
18603
- "update:rows": (rows) => true
18604
- },
18605
- setup(props, _ref) {
18606
- let {
18607
- attrs,
18608
- emit,
18609
- slots
18610
- } = _ref;
18611
- const model = useProxiedModel(props, "modelValue");
18612
- const {
18613
- isFocused,
18614
- focus,
18615
- blur
18616
- } = useFocus(props);
18617
- const {
18618
- onIntersect
18619
- } = useAutofocus(props);
18620
- const counterValue = computed(() => {
18621
- return typeof props.counterValue === "function" ? props.counterValue(model.value) : (model.value || "").toString().length;
17316
+ const selectSingleItem = (item) => {
17317
+ selection.clearSelection();
17318
+ selection.selectedItems.value = [item];
17319
+ emit("update:selectedItems", selectedItems.value);
17320
+ emit("selection-change", selectedItems.value);
17321
+ };
17322
+ const radioGroupValue = computed(() => {
17323
+ return selectedItems.value.length > 0 ? getUniqueValue(selectedItems.value[0]) : null;
18622
17324
  });
18623
- const max = computed(() => {
18624
- if (attrs.maxlength) return attrs.maxlength;
18625
- if (!props.counter || typeof props.counter !== "number" && typeof props.counter !== "string") return void 0;
18626
- return props.counter;
17325
+ const cleanFilterModel = computed(() => {
17326
+ const model = { ...filterModel.value };
17327
+ Object.keys(model).forEach((key2) => {
17328
+ if (model[key2] === null || model[key2] === void 0 || model[key2] === "") {
17329
+ delete model[key2];
17330
+ }
17331
+ });
17332
+ return model;
18627
17333
  });
18628
- const vInputRef = ref();
18629
- const vFieldRef = ref();
18630
- const controlHeight = shallowRef("");
18631
- const textareaRef = ref();
18632
- const autocomplete = useAutocomplete(props);
18633
- const isActive = computed(() => props.persistentPlaceholder || isFocused.value || props.active);
18634
- function onFocus() {
18635
- var _a;
18636
- if (autocomplete.isSuppressing.value) {
18637
- autocomplete.update();
17334
+ const hasFilterComponent = computed(() => {
17335
+ return !!props.filterComponent;
17336
+ });
17337
+ const fetchData = async (queryParams) => {
17338
+ var _a, _b;
17339
+ loading.value = true;
17340
+ error.value = null;
17341
+ let params = {
17342
+ ...cleanFilterModel.value,
17343
+ ...props.queryParams
17344
+ };
17345
+ if (queryParams) {
17346
+ params = { ...params, ...queryParams };
17347
+ }
17348
+ try {
17349
+ const shouldPaginate = props.showPagination !== false;
17350
+ const requestParams = shouldPaginate ? {
17351
+ ...params,
17352
+ page: currentPage.value - 1,
17353
+ size: itemsPerPage.value
17354
+ } : params;
17355
+ const response = await api.fetch(requestParams);
17356
+ const serverRawData = shouldPaginate ? ((_a = response.data) == null ? void 0 : _a.content) ?? [] : response.data ?? [];
17357
+ const serverData = Array.isArray(serverRawData) ? serverRawData : [];
17358
+ originalServerData.value = serverData;
17359
+ items.value = serverData.map((item) => {
17360
+ const newItem = { ...item };
17361
+ props.headers.forEach((header) => {
17362
+ if (header.isDate && newItem[header.key]) {
17363
+ try {
17364
+ newItem[header.key] = DateConverter.toShamsi(newItem[header.key]);
17365
+ } catch (error2) {
17366
+ console.error(`Error converting date for field ${header.key}:`, error2);
17367
+ }
17368
+ }
17369
+ });
17370
+ return newItem;
17371
+ });
17372
+ if (shouldPaginate && ((_b = response.data) == null ? void 0 : _b.page)) {
17373
+ totalSize.value = response.data.page.totalElements;
17374
+ totalPages.value = response.data.page.totalPages;
17375
+ hasMore.value = currentPage.value < response.data.page.totalPages;
17376
+ } else {
17377
+ totalSize.value = serverData.length;
17378
+ totalPages.value = 1;
17379
+ hasMore.value = false;
17380
+ }
17381
+ if (props.defaultSelected && items.value.length > 0 && props.defaultSelected in items.value[0]) {
17382
+ const defaultSelectedItems = items.value.filter((item) => item[props.defaultSelected] === true);
17383
+ selectedItems.value = [...defaultSelectedItems];
17384
+ emit("update:selectedItems", selectedItems.value);
17385
+ emit("selection-change", selectedItems.value);
17386
+ }
17387
+ } catch (err) {
17388
+ if (err.response) {
17389
+ error.value = `خطای سرور: ${err.response.status} - ${err.response.data.message || "خطای ناشناخته"}`;
17390
+ } else if (err.request) {
17391
+ error.value = "خطای شبکه. لطفا دوباره تلاش کنید.";
17392
+ } else {
17393
+ error.value = "یک خطای غیرمنتظره رخ داد.";
17394
+ }
17395
+ console.error(err);
17396
+ } finally {
17397
+ loading.value = false;
17398
+ }
17399
+ };
17400
+ const debouncedFetchData = useDebounceFn(fetchData, 300);
17401
+ watch(
17402
+ [cleanFilterModel],
17403
+ () => {
17404
+ debouncedFetchData();
17405
+ },
17406
+ { deep: true }
17407
+ );
17408
+ watch(
17409
+ () => props.pageSize,
17410
+ (newPageSize) => {
17411
+ itemsPerPage.value = newPageSize;
17412
+ currentPage.value = 1;
17413
+ debouncedFetchData();
17414
+ }
17415
+ );
17416
+ watch(
17417
+ () => items.value,
17418
+ (newItems) => {
17419
+ if (props.selectable && props.bulkMode && selectedItems.value.length > 0) {
17420
+ const invalidSelections = selectedItems.value.filter((selectedItem) => {
17421
+ const uniqueValue = getUniqueValue(selectedItem);
17422
+ return !newItems.some((item) => getUniqueValue(item) === uniqueValue);
17423
+ });
17424
+ if (invalidSelections.length > 0) {
17425
+ const validSelections = selectedItems.value.filter((selectedItem) => {
17426
+ const uniqueValue = getUniqueValue(selectedItem);
17427
+ return newItems.some((item) => getUniqueValue(item) === uniqueValue);
17428
+ });
17429
+ selectedItems.value = validSelections;
17430
+ emit("update:selectedItems", selectedItems.value);
17431
+ emit("selection-change", selectedItems.value);
17432
+ }
17433
+ }
17434
+ },
17435
+ { deep: true }
17436
+ );
17437
+ onBeforeUnmount(() => {
17438
+ });
17439
+ const componentAxiosInstance = props.axiosInstance || getAxiosInstance();
17440
+ const api = apiService(componentAxiosInstance, props.apiResource);
17441
+ const customActionDialog = ref(false);
17442
+ const customActionComponent = shallowRef(null);
17443
+ const customActionItem = ref(null);
17444
+ const textPreviewDialog = ref(false);
17445
+ const previewText = ref("");
17446
+ const previewTitle = ref("");
17447
+ const previewItem = ref(null);
17448
+ __expose({
17449
+ fetchData,
17450
+ items,
17451
+ selectedItems,
17452
+ getSelectedItems: () => selectedItems.value,
17453
+ clearSelection: () => {
17454
+ selectedItems.value = [];
17455
+ selectAll.value = false;
17456
+ },
17457
+ // Grouping methods (handled by useTableSelection composable)
17458
+ groupedItems,
17459
+ toggleGroup,
17460
+ expandAllGroups,
17461
+ collapseAllGroups,
17462
+ formModel
17463
+ });
17464
+ const openDialog = (item) => {
17465
+ editedItem.value = item ? { ...item } : {};
17466
+ isEditing.value = !!item;
17467
+ dialog.value = true;
17468
+ if (!isEditing.value) {
17469
+ const defaultContext = { ...editedItem.value };
17470
+ for (const header of props.headers) {
17471
+ if (header.defaultValue === void 0) {
17472
+ continue;
17473
+ }
17474
+ const resolvedDefault = resolveHeaderDefaultValue(header, defaultContext);
17475
+ if (resolvedDefault !== void 0) {
17476
+ editedItem.value[header.key] = resolvedDefault;
17477
+ defaultContext[header.key] = resolvedDefault;
17478
+ }
17479
+ }
17480
+ }
17481
+ formModel.value = { ...editedItem.value };
17482
+ props.headers.forEach((header) => {
17483
+ if (!hasAutocomplete(header)) return;
17484
+ const enhancedHeader = header;
17485
+ const currentValue = formModel.value[header.key];
17486
+ const valueKey = resolveAutocompleteItemValue(header);
17487
+ if (enhancedHeader.autocompleteReturnObject === false) {
17488
+ if (Array.isArray(currentValue)) {
17489
+ formModel.value[header.key] = currentValue.map(
17490
+ (item2) => item2 && typeof item2 === "object" ? item2[valueKey] ?? null : item2
17491
+ );
17492
+ } else if (currentValue && typeof currentValue === "object") {
17493
+ formModel.value[header.key] = currentValue[valueKey] ?? null;
17494
+ }
17495
+ }
17496
+ });
17497
+ if (isEditing.value) {
17498
+ try {
17499
+ props.headers.forEach((header) => {
17500
+ if (header.isDate) {
17501
+ const v = formModel.value[header.key];
17502
+ if (typeof v === "string" && v.includes("/")) {
17503
+ formModel.value[header.key] = DateConverter.toGregorian(v);
17504
+ } else if (typeof v === "string" && v.includes("T")) {
17505
+ formModel.value[header.key] = v.split("T")[0];
17506
+ }
17507
+ }
17508
+ });
17509
+ } catch (e) {
17510
+ console.error("Error normalizing date fields for edit form:", e);
17511
+ }
18638
17512
  }
18639
- if (textareaRef.value !== document.activeElement) {
18640
- (_a = textareaRef.value) == null ? void 0 : _a.focus();
17513
+ };
17514
+ const openDeleteDialog = (item) => {
17515
+ itemToDelete.value = item;
17516
+ deleteDialog.value = true;
17517
+ };
17518
+ const groupDeleteDialog = ref(false);
17519
+ const openGroupDeleteDialog = () => {
17520
+ groupDeleteDialog.value = true;
17521
+ };
17522
+ const deleteGroupItems = async () => {
17523
+ try {
17524
+ const selectedIds = validSelectedItems.value.map((item) => getUniqueValue(item));
17525
+ const idsParam = selectedIds.join(",");
17526
+ await api.delete(`?ids=${idsParam}`);
17527
+ groupDeleteDialog.value = false;
17528
+ clearSelection();
17529
+ await fetchData();
17530
+ snackbarMessage.value = `✅ ${selectedIds.length} آیتم با موفقیت حذف شد`;
17531
+ snackbar.value = true;
17532
+ } catch (err) {
17533
+ console.error("خطا در حذف گروهی اطلاعات", err);
17534
+ snackbarMessage.value = "❌ خطا در حذف گروهی اطلاعات!";
17535
+ snackbar.value = true;
18641
17536
  }
18642
- if (!isFocused.value) focus();
18643
- }
18644
- function onControlClick(e) {
18645
- onFocus();
18646
- emit("click:control", e);
18647
- }
18648
- function onControlMousedown(e) {
18649
- emit("mousedown:control", e);
18650
- }
18651
- function onClear(e) {
18652
- e.stopPropagation();
18653
- onFocus();
18654
- nextTick(() => {
18655
- model.value = "";
18656
- callEvent(props["onClick:clear"], e);
17537
+ };
17538
+ const saveItem = async () => {
17539
+ if (!formModel.value) return;
17540
+ try {
17541
+ const dataToSave = { ...formModel.value };
17542
+ props.headers.forEach((header) => {
17543
+ if (header.isDate && dataToSave[header.key]) {
17544
+ try {
17545
+ const raw = dataToSave[header.key];
17546
+ if (typeof raw === "string") {
17547
+ const toIsoWithOffset = (ymd) => {
17548
+ const [y, m, d] = ymd.split("-").map(Number);
17549
+ const local = new Date(y, (m || 1) - 1, d || 1, 0, 0, 0, 0);
17550
+ const offsetMin = -local.getTimezoneOffset();
17551
+ const sign = offsetMin >= 0 ? "+" : "-";
17552
+ const abs = Math.abs(offsetMin);
17553
+ const hh = String(Math.floor(abs / 60)).padStart(2, "0");
17554
+ const mm = String(abs % 60).padStart(2, "0");
17555
+ const mm2 = String(m).padStart(2, "0");
17556
+ const dd2 = String(d).padStart(2, "0");
17557
+ return `${y}-${mm2}-${dd2}T00:00:00${sign}${hh}:${mm}`;
17558
+ };
17559
+ if (raw.includes("/")) {
17560
+ const greg = DateConverter.toGregorian(raw);
17561
+ dataToSave[header.key] = props.dateWithTimezone ? toIsoWithOffset(greg) : greg;
17562
+ } else if (raw.includes("T")) {
17563
+ dataToSave[header.key] = props.dateWithTimezone ? raw : raw.split("T")[0];
17564
+ } else {
17565
+ dataToSave[header.key] = props.dateWithTimezone ? toIsoWithOffset(raw) : raw;
17566
+ }
17567
+ }
17568
+ } catch (error2) {
17569
+ console.error(`Error converting date for field ${header.key}:`, error2);
17570
+ }
17571
+ }
17572
+ });
17573
+ if (isEditing.value && dataToSave.id) {
17574
+ await api.update(dataToSave);
17575
+ snackbarMessage.value = "✅ آیتم با موفقیت بروزرسانی شد!";
17576
+ } else {
17577
+ const response = await api.create(dataToSave);
17578
+ snackbarMessage.value = "✅ آیتم با موفقیت ایجاد شد!";
17579
+ if (response.data) items.value.push(response.data);
17580
+ }
17581
+ snackbar.value = true;
17582
+ dialog.value = false;
17583
+ await fetchData();
17584
+ } catch (err) {
17585
+ console.error("خطا در ذخیره اطلاعات", err);
17586
+ snackbarMessage.value = "❌ خطا در ذخیره اطلاعات!";
17587
+ snackbar.value = true;
17588
+ }
17589
+ };
17590
+ const deleteItem = async (id) => {
17591
+ try {
17592
+ await api.delete(id);
17593
+ deleteDialog.value = false;
17594
+ items.value = items.value.filter((item) => item.id !== id);
17595
+ await fetchData();
17596
+ } catch (err) {
17597
+ console.error("خطا در حذف اطلاعات", err);
17598
+ snackbarMessage.value = "❌ خطا در حذف اطلاعات!";
17599
+ snackbar.value = true;
17600
+ }
17601
+ };
17602
+ const goToRoute = (key2, item) => {
17603
+ const routes = getRoutesForItem(item);
17604
+ if (!routes || !routes[key2] || !item) return;
17605
+ let routePath = routes[key2];
17606
+ const missingParams = [];
17607
+ routePath = routePath.replace(/\{(\w+)}/g, (_, field) => {
17608
+ if (item[field] !== void 0) {
17609
+ return item[field];
17610
+ } else {
17611
+ missingParams.push(field);
17612
+ return `{${field}}`;
17613
+ }
18657
17614
  });
18658
- }
18659
- function onInput(e) {
18660
- var _a;
18661
- const el = e.target;
18662
- model.value = el.value;
18663
- if ((_a = props.modelModifiers) == null ? void 0 : _a.trim) {
18664
- const caretPosition = [el.selectionStart, el.selectionEnd];
18665
- nextTick(() => {
18666
- el.selectionStart = caretPosition[0];
18667
- el.selectionEnd = caretPosition[1];
17615
+ if (missingParams.length > 0) {
17616
+ snackbarMessage.value = ` خطا : ${missingParams.join(" , ")} در خروجی نیست `;
17617
+ snackbar.value = true;
17618
+ return;
17619
+ }
17620
+ router.push(routePath);
17621
+ };
17622
+ const download = async (key2, item) => {
17623
+ if (!props.downloadLink || !item) return;
17624
+ const fileKey = props.downloadLink[key2];
17625
+ const url = item[fileKey];
17626
+ if (!url || typeof url !== "string") {
17627
+ snackbarMessage.value = `❌ لینک فایل یافت نشد.`;
17628
+ snackbar.value = true;
17629
+ return;
17630
+ }
17631
+ const fileUrlString = url;
17632
+ try {
17633
+ const response = await fetch(fileUrlString, {
17634
+ method: "GET",
17635
+ headers: {
17636
+ Accept: "application/octet-stream,application/pdf,image/*,*/*"
17637
+ },
17638
+ credentials: "include"
17639
+ // Include cookies for authentication
17640
+ });
17641
+ if (!response.ok) {
17642
+ throw new Error(`HTTP error! status: ${response.status}`);
17643
+ }
17644
+ const contentType = response.headers.get("content-type");
17645
+ const contentLength = response.headers.get("content-length");
17646
+ console.log("Response headers:", {
17647
+ contentType,
17648
+ contentLength,
17649
+ url: fileUrlString
18668
17650
  });
17651
+ if (contentType && contentType.includes("xml")) {
17652
+ const errorText = await response.text();
17653
+ console.error("Server returned XML error:", errorText);
17654
+ snackbarMessage.value = `❌ خطای سرور: فایل در دسترس نیست`;
17655
+ snackbar.value = true;
17656
+ return;
17657
+ }
17658
+ if (contentLength && parseInt(contentLength) < 1e3) {
17659
+ const responseText = await response.text();
17660
+ console.log("Small response:", responseText);
17661
+ if (responseText.includes("error") || responseText.includes("Error")) {
17662
+ snackbarMessage.value = `❌ خطای سرور: فایل در دسترس نیست`;
17663
+ snackbar.value = true;
17664
+ return;
17665
+ }
17666
+ }
17667
+ const blob = await response.blob();
17668
+ const url2 = window.URL.createObjectURL(blob);
17669
+ const link = document.createElement("a");
17670
+ link.href = url2;
17671
+ const filename = fileUrlString.split("/").pop() || "download";
17672
+ link.download = filename;
17673
+ document.body.appendChild(link);
17674
+ link.click();
17675
+ document.body.removeChild(link);
17676
+ window.URL.revokeObjectURL(url2);
17677
+ snackbarMessage.value = `✅ دانلود شروع شد`;
17678
+ snackbar.value = true;
17679
+ } catch (error2) {
17680
+ console.error("Download error:", error2);
17681
+ try {
17682
+ const axiosResponse = await componentAxiosInstance.get(fileUrlString, {
17683
+ responseType: "blob",
17684
+ headers: {
17685
+ Accept: "application/octet-stream,application/pdf,image/*,*/*"
17686
+ }
17687
+ });
17688
+ const contentType = axiosResponse.headers["content-type"];
17689
+ const contentLength = axiosResponse.headers["content-length"];
17690
+ console.log("Axios response headers:", {
17691
+ contentType,
17692
+ contentLength,
17693
+ url: fileUrlString
17694
+ });
17695
+ if (contentType && contentType.includes("xml")) {
17696
+ const textResponse = await componentAxiosInstance.get(fileUrlString, {
17697
+ responseType: "text"
17698
+ });
17699
+ console.error("Server returned XML error:", textResponse.data);
17700
+ snackbarMessage.value = `❌ خطای سرور: فایل در دسترس نیست`;
17701
+ snackbar.value = true;
17702
+ return;
17703
+ }
17704
+ const blob = new Blob([axiosResponse.data]);
17705
+ const url2 = window.URL.createObjectURL(blob);
17706
+ const link = document.createElement("a");
17707
+ link.href = url2;
17708
+ const filename = fileUrlString.split("/").pop() || "download";
17709
+ link.download = filename;
17710
+ document.body.appendChild(link);
17711
+ link.click();
17712
+ document.body.removeChild(link);
17713
+ window.URL.revokeObjectURL(url2);
17714
+ snackbarMessage.value = `✅ دانلود شروع شد`;
17715
+ snackbar.value = true;
17716
+ } catch (axiosError) {
17717
+ console.error("Axios download error:", axiosError);
17718
+ if (axiosError.response) {
17719
+ try {
17720
+ const errorText = await componentAxiosInstance.get(fileUrlString, {
17721
+ responseType: "text"
17722
+ });
17723
+ console.error("Server error response:", errorText.data);
17724
+ } catch (textError) {
17725
+ console.error("Could not get error text:", textError);
17726
+ }
17727
+ }
17728
+ snackbarMessage.value = `❌ خطا در دانلود فایل`;
17729
+ snackbar.value = true;
17730
+ }
17731
+ }
17732
+ };
17733
+ const handlePageChange = (newPage) => {
17734
+ currentPage.value = newPage;
17735
+ debouncedFetchData();
17736
+ };
17737
+ onMounted(() => {
17738
+ if (props.autoFetch) {
17739
+ fetchData();
18669
17740
  }
18670
- }
18671
- const sizerRef = ref();
18672
- const rows = ref(Number(props.rows));
18673
- const isPlainOrUnderlined = computed(() => ["plain", "underlined"].includes(props.variant));
18674
- watchEffect(() => {
18675
- if (!props.autoGrow) rows.value = Number(props.rows);
18676
17741
  });
18677
- function calculateInputHeight() {
18678
- if (!props.autoGrow) return;
18679
- nextTick(() => {
18680
- if (!sizerRef.value || !vFieldRef.value) return;
18681
- const style = getComputedStyle(sizerRef.value);
18682
- const fieldStyle = getComputedStyle(vFieldRef.value.$el);
18683
- const padding = parseFloat(style.getPropertyValue("--v-field-padding-top")) + parseFloat(style.getPropertyValue("--v-input-padding-top")) + parseFloat(style.getPropertyValue("--v-field-padding-bottom"));
18684
- const height2 = sizerRef.value.scrollHeight;
18685
- const lineHeight = parseFloat(style.lineHeight);
18686
- const minHeight = Math.max(parseFloat(props.rows) * lineHeight + padding, parseFloat(fieldStyle.getPropertyValue("--v-input-control-height")));
18687
- const maxHeight = parseFloat(props.maxRows) * lineHeight + padding || Infinity;
18688
- const newHeight = clamp(height2 ?? 0, minHeight, maxHeight);
18689
- rows.value = Math.floor((newHeight - padding) / lineHeight);
18690
- controlHeight.value = convertToUnit(newHeight);
17742
+ const openCustomActionDialog = (action, item) => {
17743
+ customActionComponent.value = action.component;
17744
+ const originalItem = originalServerData.value.find((originalItem2) => {
17745
+ const itemId = typeof props.uniqueKey === "function" ? props.uniqueKey(item) : item[props.uniqueKey];
17746
+ const originalId = typeof props.uniqueKey === "function" ? props.uniqueKey(originalItem2) : originalItem2[props.uniqueKey];
17747
+ return itemId === originalId;
18691
17748
  });
18692
- }
18693
- onMounted(calculateInputHeight);
18694
- watch(model, calculateInputHeight);
18695
- watch(() => props.rows, calculateInputHeight);
18696
- watch(() => props.maxRows, calculateInputHeight);
18697
- watch(() => props.density, calculateInputHeight);
18698
- watch(rows, (val2) => {
18699
- emit("update:rows", val2);
18700
- });
18701
- let observer;
18702
- watch(sizerRef, (val2) => {
18703
- if (val2) {
18704
- observer = new ResizeObserver(calculateInputHeight);
18705
- observer.observe(sizerRef.value);
18706
- } else {
18707
- observer == null ? void 0 : observer.disconnect();
17749
+ customActionItem.value = originalItem ? { ...originalItem } : { ...item };
17750
+ customActionDialog.value = true;
17751
+ };
17752
+ const getColumnStyle = (column, item) => {
17753
+ const header = props.headers.find((h2) => h2.key === column.key);
17754
+ if (!header) return {};
17755
+ const baseStyle = header.style || {};
17756
+ if (header.conditionalStyle) {
17757
+ const conditionalStyle = header.conditionalStyle(item[column.key], item);
17758
+ return { ...baseStyle, ...conditionalStyle };
18708
17759
  }
18709
- });
18710
- onBeforeUnmount(() => {
18711
- observer == null ? void 0 : observer.disconnect();
18712
- });
18713
- useRender(() => {
18714
- const hasCounter = !!(slots.counter || props.counter || props.counterValue);
18715
- const hasDetails = !!(hasCounter || slots.details);
18716
- const [rootAttrs, inputAttrs] = filterInputAttrs(attrs);
18717
- const {
18718
- modelValue: _,
18719
- ...inputProps
18720
- } = VInput.filterProps(props);
18721
- const fieldProps = {
18722
- ...VField.filterProps(props),
18723
- "onClick:clear": onClear
17760
+ return baseStyle;
17761
+ };
17762
+ const getNestedValue2 = (obj, path) => {
17763
+ return path.split(".").reduce((current, key2) => {
17764
+ return current && current[key2] !== void 0 ? current[key2] : null;
17765
+ }, obj);
17766
+ };
17767
+ const getTranslatedValue = (value2, column, item) => {
17768
+ const header = props.headers.find((h2) => h2.key === column.key);
17769
+ if (!header) return value2;
17770
+ if (header.customRenderer) {
17771
+ return header.customRenderer(item);
17772
+ }
17773
+ if (header.formatter) {
17774
+ return header.formatter(value2, item);
17775
+ }
17776
+ if (String(header.type).toLowerCase() === "money") {
17777
+ try {
17778
+ return formatNumberWithCommas(value2 ?? 0, 0);
17779
+ } catch (e) {
17780
+ return value2;
17781
+ }
17782
+ }
17783
+ if (header.translate) {
17784
+ if (header.options) {
17785
+ const option = header.options.find((opt) => opt.value === value2);
17786
+ return (option == null ? void 0 : option.title) || value2;
17787
+ }
17788
+ return translateValue(value2);
17789
+ }
17790
+ return value2;
17791
+ };
17792
+ const translateValue = (value2) => {
17793
+ const translations = {
17794
+ ACTIVE: "فعال",
17795
+ INACTIVE: "غیرفعال",
17796
+ PENDING: "در انتظار",
17797
+ COMPLETED: "تکمیل شده"
17798
+ // Add more translations as needed
18724
17799
  };
18725
- return createVNode(VInput, mergeProps({
18726
- "ref": vInputRef,
18727
- "modelValue": model.value,
18728
- "onUpdate:modelValue": ($event) => model.value = $event,
18729
- "class": ["v-textarea v-text-field", {
18730
- "v-textarea--prefixed": props.prefix,
18731
- "v-textarea--suffixed": props.suffix,
18732
- "v-text-field--prefixed": props.prefix,
18733
- "v-text-field--suffixed": props.suffix,
18734
- "v-textarea--auto-grow": props.autoGrow,
18735
- "v-textarea--no-resize": props.noResize || props.autoGrow,
18736
- "v-input--plain-underlined": isPlainOrUnderlined.value
18737
- }, props.class],
18738
- "style": props.style
18739
- }, rootAttrs, inputProps, {
18740
- "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
18741
- "focused": isFocused.value
18742
- }), {
18743
- ...slots,
18744
- default: (_ref2) => {
18745
- let {
18746
- id,
18747
- isDisabled,
18748
- isDirty,
18749
- isReadonly,
18750
- isValid,
18751
- hasDetails: hasDetails2
18752
- } = _ref2;
18753
- return createVNode(VField, mergeProps({
18754
- "ref": vFieldRef,
18755
- "style": {
18756
- "--v-textarea-control-height": controlHeight.value
18757
- },
18758
- "onClick": onControlClick,
18759
- "onMousedown": onControlMousedown,
18760
- "onClick:prependInner": props["onClick:prependInner"],
18761
- "onClick:appendInner": props["onClick:appendInner"]
18762
- }, fieldProps, {
18763
- "id": id.value,
18764
- "active": isActive.value || isDirty.value,
18765
- "centerAffix": rows.value === 1 && !isPlainOrUnderlined.value,
18766
- "dirty": isDirty.value || props.dirty,
18767
- "disabled": isDisabled.value,
18768
- "focused": isFocused.value,
18769
- "details": hasDetails2.value,
18770
- "error": isValid.value === false
18771
- }), {
18772
- ...slots,
18773
- default: (_ref3) => {
18774
- let {
18775
- props: {
18776
- class: fieldClass,
18777
- ...slotProps
18778
- }
18779
- } = _ref3;
18780
- return createElementVNode(Fragment, null, [props.prefix && createElementVNode("span", {
18781
- "class": "v-text-field__prefix"
18782
- }, [props.prefix]), withDirectives(createElementVNode("textarea", mergeProps({
18783
- "ref": textareaRef,
18784
- "class": fieldClass,
18785
- "value": model.value,
18786
- "onInput": onInput,
18787
- "autofocus": props.autofocus,
18788
- "readonly": isReadonly.value,
18789
- "disabled": isDisabled.value,
18790
- "placeholder": props.placeholder,
18791
- "rows": props.rows,
18792
- "name": autocomplete.fieldName.value,
18793
- "autocomplete": autocomplete.fieldAutocomplete.value,
18794
- "onFocus": onFocus,
18795
- "onBlur": blur
18796
- }, slotProps, inputAttrs), null), [[Intersect, {
18797
- handler: onIntersect
18798
- }, null, {
18799
- once: true
18800
- }]]), props.autoGrow && withDirectives(createElementVNode("textarea", {
18801
- "class": normalizeClass([fieldClass, "v-textarea__sizer"]),
18802
- "id": `${slotProps.id}-sizer`,
18803
- "onUpdate:modelValue": ($event) => model.value = $event,
18804
- "ref": sizerRef,
18805
- "readonly": true,
18806
- "aria-hidden": "true"
18807
- }, null), [[vModelText, model.value]]), props.suffix && createElementVNode("span", {
18808
- "class": "v-text-field__suffix"
18809
- }, [props.suffix])]);
18810
- }
18811
- });
18812
- },
18813
- details: hasDetails ? (slotProps) => {
18814
- var _a;
18815
- return createElementVNode(Fragment, null, [(_a = slots.details) == null ? void 0 : _a.call(slots, slotProps), hasCounter && createElementVNode(Fragment, null, [createElementVNode("span", null, null), createVNode(VCounter, {
18816
- "active": props.persistentCounter || isFocused.value,
18817
- "value": counterValue.value,
18818
- "max": max.value,
18819
- "disabled": props.disabled
18820
- }, slots.counter)])]);
18821
- } : void 0
18822
- });
18823
- });
18824
- return forwardRefs({}, vInputRef, vFieldRef, textareaRef);
17800
+ return translations[value2] || value2;
17801
+ };
17802
+ const truncateText = (text2, maxLength = props.maxTextLength) => {
17803
+ if (text2 === null || text2 === void 0) return "";
17804
+ const textStr = String(text2);
17805
+ if (textStr.length <= maxLength) return textStr;
17806
+ return textStr.substring(0, maxLength) + "...";
17807
+ };
17808
+ const shouldTruncate = (text2) => {
17809
+ if (text2 === null || text2 === void 0) return false;
17810
+ return String(text2).length > props.maxTextLength;
17811
+ };
17812
+ const openTextPreview = (text2, columnTitle, item) => {
17813
+ previewText.value = text2 === null || text2 === void 0 ? "" : String(text2);
17814
+ previewTitle.value = columnTitle;
17815
+ previewItem.value = item;
17816
+ textPreviewDialog.value = true;
17817
+ };
17818
+ const copyToClipboard = async (text2) => {
17819
+ try {
17820
+ await navigator.clipboard.writeText(text2);
17821
+ snackbarMessage.value = "✅ متن با موفقیت کپی شد!";
17822
+ snackbar.value = true;
17823
+ } catch (err) {
17824
+ console.error("Failed to copy text:", err);
17825
+ try {
17826
+ const textArea = document.createElement("textarea");
17827
+ textArea.value = text2;
17828
+ textArea.style.position = "fixed";
17829
+ textArea.style.opacity = "0";
17830
+ document.body.appendChild(textArea);
17831
+ textArea.select();
17832
+ document.execCommand("copy");
17833
+ document.body.removeChild(textArea);
17834
+ snackbarMessage.value = "✅ متن با موفقیت کپی شد!";
17835
+ snackbar.value = true;
17836
+ } catch (fallbackErr) {
17837
+ snackbarMessage.value = "❌ خطا در کپی کردن متن!";
17838
+ snackbar.value = true;
17839
+ }
17840
+ }
17841
+ };
17842
+ const copyCompleteRecord = async () => {
17843
+ if (!previewItem.value) return;
17844
+ try {
17845
+ const recordText = JSON.stringify(previewItem.value, null, 2);
17846
+ await copyToClipboard(recordText);
17847
+ } catch (err) {
17848
+ console.error("Failed to copy record:", err);
17849
+ snackbarMessage.value = "❌ خطا در کپی کردن رکورد!";
17850
+ snackbar.value = true;
17851
+ }
17852
+ };
17853
+ const handleFilterApply = (filterData) => {
17854
+ filterModel.value = filterData;
17855
+ currentPage.value = 1;
17856
+ debouncedFetchData();
17857
+ filterDialog.value = false;
17858
+ };
17859
+ return (_ctx, _cache) => {
17860
+ var _a;
17861
+ return openBlock(), createElementBlock(Fragment, null, [
17862
+ props.title ? (openBlock(), createElementBlock("div", _hoisted_1$9, [
17863
+ createElementVNode("h3", _hoisted_2$5, toDisplayString(props.title), 1)
17864
+ ])) : createCommentVNode("", true),
17865
+ createElementVNode("div", _hoisted_3$4, [
17866
+ ((_a = props.actions) == null ? void 0 : _a.includes("create")) ? (openBlock(), createBlock(VBtn, {
17867
+ key: 0,
17868
+ color: "green",
17869
+ class: "me-2",
17870
+ onClick: _cache[0] || (_cache[0] = ($event) => openDialog())
17871
+ }, {
17872
+ default: withCtx(() => [..._cache[23] || (_cache[23] = [
17873
+ createTextVNode("ایجاد ✅", -1)
17874
+ ])]),
17875
+ _: 1
17876
+ })) : createCommentVNode("", true),
17877
+ hasFilterComponent.value ? (openBlock(), createBlock(VBtn, {
17878
+ key: 1,
17879
+ class: "me-2",
17880
+ onClick: _cache[1] || (_cache[1] = ($event) => filterDialog.value = true)
17881
+ }, {
17882
+ default: withCtx(() => [..._cache[24] || (_cache[24] = [
17883
+ createTextVNode("فیلتر 🔍", -1)
17884
+ ])]),
17885
+ _: 1
17886
+ })) : createCommentVNode("", true),
17887
+ props.showRefreshButton ? (openBlock(), createBlock(VBtn, {
17888
+ key: 2,
17889
+ color: "blue",
17890
+ onClick: unref(debouncedFetchData),
17891
+ loading: loading.value
17892
+ }, {
17893
+ default: withCtx(() => [..._cache[25] || (_cache[25] = [
17894
+ createTextVNode("بروزرسانی 🔄", -1)
17895
+ ])]),
17896
+ _: 1
17897
+ }, 8, ["onClick", "loading"])) : createCommentVNode("", true),
17898
+ props.selectable && hasSelection.value ? (openBlock(), createElementBlock("div", _hoisted_4$2, [
17899
+ createVNode(VChip, {
17900
+ color: "primary",
17901
+ class: "me-2"
17902
+ }, {
17903
+ default: withCtx(() => [
17904
+ createTextVNode(toDisplayString(selectedCount.value) + " آیتم انتخاب شده ", 1)
17905
+ ]),
17906
+ _: 1
17907
+ }),
17908
+ createVNode(VBtn, {
17909
+ color: "error",
17910
+ size: "small",
17911
+ class: "me-2",
17912
+ onClick: clearSelection
17913
+ }, {
17914
+ default: withCtx(() => [..._cache[26] || (_cache[26] = [
17915
+ createTextVNode(" پاک کردن انتخاب ", -1)
17916
+ ])]),
17917
+ _: 1
17918
+ })
17919
+ ])) : createCommentVNode("", true),
17920
+ createVNode(Transition, {
17921
+ name: "slide-left",
17922
+ appear: ""
17923
+ }, {
17924
+ default: withCtx(() => [
17925
+ props.bulkMode && hasValidSelection.value || props.enableGroupDelete && hasSelection.value ? (openBlock(), createElementBlock("div", _hoisted_5$2, [
17926
+ props.enableGroupDelete ? (openBlock(), createBlock(VBtn, {
17927
+ key: 0,
17928
+ color: "red",
17929
+ size: "small",
17930
+ class: "me-2",
17931
+ onClick: openGroupDeleteDialog
17932
+ }, {
17933
+ default: withCtx(() => [
17934
+ _cache[27] || (_cache[27] = createElementVNode("span", { class: "me-1" }, "🗑️", -1)),
17935
+ createTextVNode(" حذف گروهی (" + toDisplayString(selectedCount.value) + ") ", 1)
17936
+ ]),
17937
+ _: 1
17938
+ })) : createCommentVNode("", true),
17939
+ props.bulkMode ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(validSelectedItems.value, (item) => {
17940
+ var _a2, _b, _c;
17941
+ return openBlock(), createElementBlock(Fragment, {
17942
+ key: getUniqueValue(item)
17943
+ }, [
17944
+ ((_a2 = props.actions) == null ? void 0 : _a2.includes("edit")) ? (openBlock(), createBlock(VBtn, {
17945
+ key: 0,
17946
+ color: "blue",
17947
+ size: "small",
17948
+ class: "me-2",
17949
+ onClick: ($event) => openDialog(item)
17950
+ }, {
17951
+ default: withCtx(() => [..._cache[28] || (_cache[28] = [
17952
+ createElementVNode("span", { class: "me-1" }, "✏️", -1),
17953
+ createTextVNode(" ویرایش ", -1)
17954
+ ])]),
17955
+ _: 1
17956
+ }, 8, ["onClick"])) : createCommentVNode("", true),
17957
+ ((_b = props.actions) == null ? void 0 : _b.includes("delete")) ? (openBlock(), createBlock(VBtn, {
17958
+ key: 1,
17959
+ color: "red",
17960
+ size: "small",
17961
+ class: "me-2",
17962
+ onClick: ($event) => openDeleteDialog(item)
17963
+ }, {
17964
+ default: withCtx(() => [..._cache[29] || (_cache[29] = [
17965
+ createElementVNode("span", { class: "me-1" }, "🗑️", -1),
17966
+ createTextVNode(" حذف ", -1)
17967
+ ])]),
17968
+ _: 1
17969
+ }, 8, ["onClick"])) : createCommentVNode("", true),
17970
+ ((_c = props.actions) == null ? void 0 : _c.includes("view")) ? (openBlock(), createBlock(VBtn, {
17971
+ key: 2,
17972
+ color: "purple",
17973
+ size: "small",
17974
+ class: "me-2",
17975
+ onClick: ($event) => goToRoute("view", item)
17976
+ }, {
17977
+ default: withCtx(() => [..._cache[30] || (_cache[30] = [
17978
+ createElementVNode("span", { class: "me-1" }, "👁️", -1),
17979
+ createTextVNode(" نمایش ", -1)
17980
+ ])]),
17981
+ _: 1
17982
+ }, 8, ["onClick"])) : createCommentVNode("", true),
17983
+ (openBlock(true), createElementBlock(Fragment, null, renderList(getRoutesForItem(item), (routePath, routeKey) => {
17984
+ return openBlock(), createBlock(VBtn, {
17985
+ key: routeKey,
17986
+ color: "indigo",
17987
+ size: "small",
17988
+ class: "me-2",
17989
+ onClick: ($event) => goToRoute(routeKey, item)
17990
+ }, {
17991
+ default: withCtx(() => [
17992
+ _cache[31] || (_cache[31] = createElementVNode("span", { class: "me-1" }, "➡️", -1)),
17993
+ createTextVNode(" " + toDisplayString(String(routeKey)), 1)
17994
+ ]),
17995
+ _: 2
17996
+ }, 1032, ["onClick"]);
17997
+ }), 128)),
17998
+ (openBlock(true), createElementBlock(Fragment, null, renderList(props.downloadLink, (value2, key2) => {
17999
+ return openBlock(), createBlock(VBtn, {
18000
+ size: "small",
18001
+ class: "me-2",
18002
+ key: key2,
18003
+ onClick: ($event) => download(key2, item)
18004
+ }, {
18005
+ default: withCtx(() => [
18006
+ _cache[32] || (_cache[32] = createElementVNode("span", { class: "me-1" }, "⬇️", -1)),
18007
+ createTextVNode(" " + toDisplayString(key2), 1)
18008
+ ]),
18009
+ _: 2
18010
+ }, 1032, ["onClick"]);
18011
+ }), 128)),
18012
+ (openBlock(true), createElementBlock(Fragment, null, renderList(props.customActions, (action, index2) => {
18013
+ return openBlock(), createElementBlock(Fragment, {
18014
+ key: action.title || index2
18015
+ }, [
18016
+ !action.condition || action.condition(item) ? (openBlock(), createBlock(VBtn, {
18017
+ key: 0,
18018
+ color: "orange",
18019
+ size: "small",
18020
+ class: "me-2",
18021
+ onClick: ($event) => openCustomActionDialog(action, item)
18022
+ }, {
18023
+ default: withCtx(() => [
18024
+ createTextVNode(toDisplayString(action.title), 1)
18025
+ ]),
18026
+ _: 2
18027
+ }, 1032, ["onClick"])) : createCommentVNode("", true)
18028
+ ], 64);
18029
+ }), 128)),
18030
+ props.customButtonsFn ? (openBlock(true), createElementBlock(Fragment, { key: 3 }, renderList(props.customButtonsFn(item), (button) => {
18031
+ return openBlock(), createBlock(VBtn, {
18032
+ key: button.label,
18033
+ color: button.color || "primary",
18034
+ size: "small",
18035
+ class: "me-2",
18036
+ disabled: button.disabled,
18037
+ onClick: ($event) => button.onClick(item)
18038
+ }, {
18039
+ default: withCtx(() => [
18040
+ button.icon ? (openBlock(), createElementBlock("span", _hoisted_6$1, toDisplayString(button.icon), 1)) : createCommentVNode("", true),
18041
+ createTextVNode(" " + toDisplayString(button.label), 1)
18042
+ ]),
18043
+ _: 2
18044
+ }, 1032, ["color", "disabled", "onClick"]);
18045
+ }), 128)) : (openBlock(true), createElementBlock(Fragment, { key: 4 }, renderList(props.customButtons, (button) => {
18046
+ return openBlock(), createBlock(VBtn, {
18047
+ key: button.label,
18048
+ color: button.color || "primary",
18049
+ size: "small",
18050
+ class: "me-2",
18051
+ onClick: ($event) => button.onClick(item)
18052
+ }, {
18053
+ default: withCtx(() => [
18054
+ button.icon ? (openBlock(), createElementBlock("span", _hoisted_7$1, toDisplayString(button.icon), 1)) : createCommentVNode("", true),
18055
+ createTextVNode(" " + toDisplayString(button.label), 1)
18056
+ ]),
18057
+ _: 2
18058
+ }, 1032, ["color", "onClick"]);
18059
+ }), 128))
18060
+ ], 64);
18061
+ }), 128)) : createCommentVNode("", true)
18062
+ ])) : createCommentVNode("", true)
18063
+ ]),
18064
+ _: 1
18065
+ })
18066
+ ]),
18067
+ createElementVNode("div", mergeProps({ class: "data-table-container" }, _ctx.$attrs, {
18068
+ role: "region",
18069
+ "aria-busy": loading.value || isLoadingMore.value,
18070
+ "aria-live": loading.value || isLoadingMore.value ? "polite" : "off"
18071
+ }), [
18072
+ loading.value && !isLoadingMore.value ? (openBlock(), createElementBlock("div", {
18073
+ key: 0,
18074
+ class: "skeleton-container",
18075
+ style: normalizeStyle({ height: `${props.height}px` })
18076
+ }, [
18077
+ createVNode(VSkeletonLoader, {
18078
+ type: "table",
18079
+ loading: loading.value,
18080
+ class: "mx-auto",
18081
+ "max-width": "100%",
18082
+ boilerplate: false
18083
+ }, null, 8, ["loading"])
18084
+ ], 4)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
18085
+ props.groupBy && unref(groupedItems).length > 0 ? (openBlock(), createElementBlock("div", _hoisted_9$1, [
18086
+ createElementVNode("div", _hoisted_10$1, [
18087
+ createVNode(VBtn, {
18088
+ size: "small",
18089
+ color: "primary",
18090
+ onClick: expandAllGroups,
18091
+ class: "me-2"
18092
+ }, {
18093
+ default: withCtx(() => [..._cache[33] || (_cache[33] = [
18094
+ createTextVNode(" گسترش همه ", -1)
18095
+ ])]),
18096
+ _: 1
18097
+ }),
18098
+ createVNode(VBtn, {
18099
+ size: "small",
18100
+ color: "secondary",
18101
+ onClick: collapseAllGroups,
18102
+ class: "me-2"
18103
+ }, {
18104
+ default: withCtx(() => [..._cache[34] || (_cache[34] = [
18105
+ createTextVNode(" جمع کردن همه ", -1)
18106
+ ])]),
18107
+ _: 1
18108
+ })
18109
+ ]),
18110
+ createElementVNode("div", {
18111
+ class: "groups-scroll-container",
18112
+ style: normalizeStyle({ height: `${props.height - 120}px` })
18113
+ }, [
18114
+ createElementVNode("div", _hoisted_11$1, [
18115
+ (openBlock(true), createElementBlock(Fragment, null, renderList(unref(groupedItems), (group) => {
18116
+ return openBlock(), createElementBlock("div", {
18117
+ key: group.groupKey,
18118
+ class: "group-section"
18119
+ }, [
18120
+ createElementVNode("div", {
18121
+ class: normalizeClass(["group-header", { expanded: group.isExpanded }]),
18122
+ role: "button",
18123
+ tabindex: "0",
18124
+ onClick: withModifiers(($event) => toggleGroup(group.groupKey), ["stop"]),
18125
+ onMousedown: _cache[2] || (_cache[2] = withModifiers(() => {
18126
+ }, ["stop"])),
18127
+ onKeydown: [
18128
+ withKeys(withModifiers(($event) => toggleGroup(group.groupKey), ["prevent"]), ["enter"]),
18129
+ withKeys(withModifiers(($event) => toggleGroup(group.groupKey), ["prevent"]), ["space"])
18130
+ ],
18131
+ "aria-expanded": group.isExpanded ? "true" : "false",
18132
+ "aria-controls": `group-panel-${group.groupKey}`,
18133
+ id: `group-header-${group.groupKey}`
18134
+ }, [
18135
+ group.isExpanded ? (openBlock(), createBlock(unref(IconChevronDown), {
18136
+ key: 0,
18137
+ class: "me-2 chevron-icon"
18138
+ })) : (openBlock(), createBlock(unref(IconChevronRight), {
18139
+ key: 1,
18140
+ class: "me-2 chevron-icon"
18141
+ })),
18142
+ createElementVNode("span", _hoisted_13$1, toDisplayString(group.groupLabel), 1),
18143
+ createVNode(VChip, {
18144
+ size: "small",
18145
+ color: "darkprimary",
18146
+ class: "ms-auto"
18147
+ }, {
18148
+ default: withCtx(() => [
18149
+ createTextVNode(toDisplayString(group.count), 1)
18150
+ ]),
18151
+ _: 2
18152
+ }, 1024)
18153
+ ], 42, _hoisted_12$1),
18154
+ createVNode(Transition, {
18155
+ name: "group-expand",
18156
+ appear: ""
18157
+ }, {
18158
+ default: withCtx(() => [
18159
+ group.isExpanded ? (openBlock(), createElementBlock("div", {
18160
+ key: 0,
18161
+ class: "group-items",
18162
+ id: `group-panel-${group.groupKey}`,
18163
+ "aria-labelledby": `group-header-${group.groupKey}`,
18164
+ role: "region"
18165
+ }, [
18166
+ createVNode(VDataTable, {
18167
+ headers: groupedHeaders.value,
18168
+ items: group.items,
18169
+ "items-per-page": itemsPerPage.value,
18170
+ "hide-default-footer": "",
18171
+ class: "elevation-1 group-table",
18172
+ "no-data-text": "رکوردی یافت نشد",
18173
+ hover: "",
18174
+ height: "auto",
18175
+ density: "compact"
18176
+ }, {
18177
+ "header.selection": withCtx(({ column }) => [
18178
+ props.selectable && props.multiSelect ? (openBlock(), createBlock(VCheckbox, {
18179
+ key: 0,
18180
+ "model-value": selectAll.value,
18181
+ "onUpdate:modelValue": toggleSelectAll,
18182
+ indeterminate: selectedCount.value > 0 && selectedCount.value < items.value.length,
18183
+ "hide-details": "",
18184
+ density: "compact"
18185
+ }, null, 8, ["model-value", "indeterminate"])) : createCommentVNode("", true)
18186
+ ]),
18187
+ item: withCtx(({ item, columns, index: index2 }) => [
18188
+ createElementVNode("tr", {
18189
+ style: normalizeStyle({
18190
+ background: isSelected(item) && props.bulkMode ? "rgb(var(--v-theme-primary200))" : index2 % 2 === 0 ? "rgb(var(--v-theme-surface))" : "rgb(var(--v-theme-lightprimary))",
18191
+ cursor: props.bulkMode && props.selectable ? "pointer" : "default"
18192
+ }),
18193
+ tabindex: props.selectable ? 0 : -1,
18194
+ onKeydown: withKeys(withModifiers(($event) => props.selectable && toggleSelection(item), ["prevent"]), ["enter"]),
18195
+ onClick: ($event) => props.bulkMode && props.selectable && selectSingleItem(item)
18196
+ }, [
18197
+ (openBlock(true), createElementBlock(Fragment, null, renderList(columns, (column) => {
18198
+ var _a2, _b, _c;
18199
+ return openBlock(), createElementBlock("td", {
18200
+ key: column.key || "unknown",
18201
+ style: normalizeStyle({
18202
+ ...getColumnStyle(column, item),
18203
+ ...column.width ? { width: column.width + "px", minWidth: column.width + "px", maxWidth: column.width + "px" } : {}
18204
+ })
18205
+ }, [
18206
+ column.key === "selection" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
18207
+ props.bulkMode ? (openBlock(), createBlock(VRadio, {
18208
+ key: 0,
18209
+ "model-value": radioGroupValue.value,
18210
+ value: getUniqueValue(item),
18211
+ onClick: withModifiers(($event) => selectSingleItem(item), ["stop"]),
18212
+ disabled: !props.selectable,
18213
+ "hide-details": "",
18214
+ density: "compact"
18215
+ }, null, 8, ["model-value", "value", "onClick", "disabled"])) : (openBlock(), createBlock(VCheckbox, {
18216
+ key: 1,
18217
+ "model-value": isSelected(item),
18218
+ "onUpdate:modelValue": ($event) => toggleSelection(item),
18219
+ disabled: !props.selectable,
18220
+ "hide-details": "",
18221
+ density: "compact"
18222
+ }, null, 8, ["model-value", "onUpdate:modelValue", "disabled"]))
18223
+ ], 64)) : createCommentVNode("", true),
18224
+ column.key === "actions" && hasAnyActions.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
18225
+ ((_a2 = props.actions) == null ? void 0 : _a2.includes("edit")) ? (openBlock(), createBlock(VBtn, {
18226
+ key: 0,
18227
+ color: "blue",
18228
+ size: "small",
18229
+ class: "mr-2",
18230
+ onClick: ($event) => openDialog(item)
18231
+ }, {
18232
+ default: withCtx(() => [..._cache[35] || (_cache[35] = [
18233
+ createTextVNode(" ویرایش ✏️ ", -1)
18234
+ ])]),
18235
+ _: 1
18236
+ }, 8, ["onClick"])) : createCommentVNode("", true),
18237
+ ((_b = props.actions) == null ? void 0 : _b.includes("delete")) ? (openBlock(), createBlock(VBtn, {
18238
+ key: 1,
18239
+ color: "red",
18240
+ size: "small",
18241
+ class: "mr-2",
18242
+ onClick: ($event) => openDeleteDialog(item)
18243
+ }, {
18244
+ default: withCtx(() => [..._cache[36] || (_cache[36] = [
18245
+ createTextVNode("حذف ❌ ", -1)
18246
+ ])]),
18247
+ _: 1
18248
+ }, 8, ["onClick"])) : createCommentVNode("", true),
18249
+ ((_c = props.actions) == null ? void 0 : _c.includes("view")) ? (openBlock(), createBlock(VBtn, {
18250
+ key: 2,
18251
+ color: "purple",
18252
+ size: "small",
18253
+ class: "mr-2",
18254
+ onClick: ($event) => goToRoute("view", item)
18255
+ }, {
18256
+ default: withCtx(() => [..._cache[37] || (_cache[37] = [
18257
+ createTextVNode("🔍 نمایش ", -1)
18258
+ ])]),
18259
+ _: 1
18260
+ }, 8, ["onClick"])) : createCommentVNode("", true),
18261
+ (openBlock(true), createElementBlock(Fragment, null, renderList(getRoutesForItem(item), (routePath, routeKey) => {
18262
+ return openBlock(), createBlock(VBtn, {
18263
+ key: routeKey,
18264
+ color: "indigo",
18265
+ size: "small",
18266
+ class: "mr-2",
18267
+ onClick: ($event) => goToRoute(routeKey, item)
18268
+ }, {
18269
+ default: withCtx(() => [
18270
+ createTextVNode(toDisplayString(routeKey.toUpperCase()), 1)
18271
+ ]),
18272
+ _: 2
18273
+ }, 1032, ["onClick"]);
18274
+ }), 128)),
18275
+ (openBlock(true), createElementBlock(Fragment, null, renderList(props.downloadLink, (value2, key2) => {
18276
+ return openBlock(), createBlock(VBtn, {
18277
+ size: "small",
18278
+ class: "mr-2",
18279
+ key: key2,
18280
+ onClick: ($event) => download(key2, item)
18281
+ }, {
18282
+ default: withCtx(() => [
18283
+ createTextVNode(toDisplayString(key2) + " ⬇️ ", 1)
18284
+ ]),
18285
+ _: 2
18286
+ }, 1032, ["onClick"]);
18287
+ }), 128)),
18288
+ (openBlock(true), createElementBlock(Fragment, null, renderList(props.customActions, (action, index22) => {
18289
+ return openBlock(), createElementBlock(Fragment, {
18290
+ key: action.title || index22
18291
+ }, [
18292
+ !action.condition || action.condition(item) ? (openBlock(), createBlock(VBtn, {
18293
+ key: 0,
18294
+ color: "orange",
18295
+ size: "small",
18296
+ class: "mr-2",
18297
+ onClick: ($event) => openCustomActionDialog(action, item)
18298
+ }, {
18299
+ default: withCtx(() => [
18300
+ createTextVNode(toDisplayString(action.title), 1)
18301
+ ]),
18302
+ _: 2
18303
+ }, 1032, ["onClick"])) : createCommentVNode("", true)
18304
+ ], 64);
18305
+ }), 128)),
18306
+ props.customButtonsFn ? (openBlock(true), createElementBlock(Fragment, { key: 3 }, renderList(props.customButtonsFn(item), (button) => {
18307
+ return openBlock(), createBlock(VBtn, {
18308
+ key: button.label,
18309
+ color: button.color || "primary",
18310
+ size: "small",
18311
+ class: "mr-2",
18312
+ disabled: button.disabled,
18313
+ onClick: ($event) => button.onClick(item)
18314
+ }, {
18315
+ default: withCtx(() => [
18316
+ createTextVNode(toDisplayString(button.label), 1)
18317
+ ]),
18318
+ _: 2
18319
+ }, 1032, ["color", "disabled", "onClick"]);
18320
+ }), 128)) : (openBlock(true), createElementBlock(Fragment, { key: 4 }, renderList(props.customButtons, (button) => {
18321
+ return openBlock(), createBlock(VBtn, {
18322
+ key: button.label,
18323
+ color: button.color || "primary",
18324
+ size: "small",
18325
+ class: "mr-2",
18326
+ onClick: ($event) => button.onClick(item)
18327
+ }, {
18328
+ default: withCtx(() => [
18329
+ createTextVNode(toDisplayString(button.label), 1)
18330
+ ]),
18331
+ _: 2
18332
+ }, 1032, ["color", "onClick"]);
18333
+ }), 128))
18334
+ ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [
18335
+ shouldTruncate(getTranslatedValue(getNestedValue2(item, column.key || ""), column, item)) ? (openBlock(), createElementBlock("span", {
18336
+ key: 0,
18337
+ class: "truncated-text",
18338
+ style: { cursor: "pointer", color: "rgb(var(--v-theme-primary))", textDecoration: "underline" },
18339
+ onClick: withModifiers(($event) => openTextPreview(getTranslatedValue(getNestedValue2(item, column.key || ""), column, item), column.title || column.key || "", item), ["stop"])
18340
+ }, toDisplayString(truncateText(getTranslatedValue(getNestedValue2(item, column.key || ""), column, item))), 9, _hoisted_16$1)) : (openBlock(), createElementBlock("span", _hoisted_17, toDisplayString(getTranslatedValue(getNestedValue2(item, column.key || ""), column, item)), 1))
18341
+ ], 64))
18342
+ ], 4);
18343
+ }), 128))
18344
+ ], 44, _hoisted_15$1)
18345
+ ]),
18346
+ _: 1
18347
+ }, 8, ["headers", "items", "items-per-page"])
18348
+ ], 8, _hoisted_14$1)) : createCommentVNode("", true)
18349
+ ]),
18350
+ _: 2
18351
+ }, 1024)
18352
+ ]);
18353
+ }), 128))
18354
+ ])
18355
+ ], 4)
18356
+ ])) : (openBlock(), createBlock(VDataTable, {
18357
+ key: 1,
18358
+ headers: normalHeaders.value,
18359
+ items: items.value,
18360
+ "items-per-page": itemsPerPage.value,
18361
+ "hide-default-footer": "",
18362
+ class: "elevation-1",
18363
+ "no-data-text": "رکوردی یافت نشد",
18364
+ hover: "",
18365
+ height: props.height,
18366
+ density: "compact"
18367
+ }, {
18368
+ "header.selection": withCtx(({ column }) => [
18369
+ props.selectable && props.multiSelect ? (openBlock(), createBlock(VCheckbox, {
18370
+ key: 0,
18371
+ "model-value": selectAll.value,
18372
+ "onUpdate:modelValue": toggleSelectAll,
18373
+ indeterminate: selectedCount.value > 0 && selectedCount.value < items.value.length,
18374
+ "hide-details": "",
18375
+ density: "compact"
18376
+ }, null, 8, ["model-value", "indeterminate"])) : createCommentVNode("", true)
18377
+ ]),
18378
+ item: withCtx(({ item, columns, index: index2 }) => [
18379
+ createElementVNode("tr", {
18380
+ style: normalizeStyle({
18381
+ color: isSelected(item) && props.bulkMode ? "rgb(var(--v-theme-white))" : "rgb(var(--v-theme-darkText))",
18382
+ background: isSelected(item) && props.bulkMode ? "rgb(var(--v-theme-primary))" : index2 % 2 === 0 ? "rgb(var(--v-theme-surface))" : "rgb(var(--v-theme-lightprimary))",
18383
+ cursor: props.bulkMode && props.selectable ? "pointer" : "default"
18384
+ }),
18385
+ tabindex: props.selectable ? 0 : -1,
18386
+ onKeydown: withKeys(withModifiers(($event) => props.selectable && toggleSelection(item), ["prevent"]), ["enter"]),
18387
+ onClick: ($event) => props.bulkMode && props.selectable && selectSingleItem(item)
18388
+ }, [
18389
+ (openBlock(true), createElementBlock(Fragment, null, renderList(columns, (column) => {
18390
+ var _a2, _b, _c;
18391
+ return openBlock(), createElementBlock("td", {
18392
+ key: column.key || "unknown",
18393
+ style: normalizeStyle({
18394
+ ...getColumnStyle(column, item),
18395
+ ...column.width ? { width: column.width + "px", minWidth: column.width + "px", maxWidth: column.width + "px" } : {}
18396
+ })
18397
+ }, [
18398
+ column.key === "selection" ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
18399
+ props.bulkMode ? (openBlock(), createBlock(VRadio, {
18400
+ key: 0,
18401
+ "model-value": radioGroupValue.value,
18402
+ value: getUniqueValue(item),
18403
+ onClick: withModifiers(($event) => selectSingleItem(item), ["stop"]),
18404
+ disabled: !props.selectable,
18405
+ "hide-details": "",
18406
+ density: "compact"
18407
+ }, null, 8, ["model-value", "value", "onClick", "disabled"])) : (openBlock(), createBlock(VCheckbox, {
18408
+ key: 1,
18409
+ "model-value": isSelected(item),
18410
+ "onUpdate:modelValue": ($event) => toggleSelection(item),
18411
+ disabled: !props.selectable,
18412
+ "hide-details": "",
18413
+ density: "compact"
18414
+ }, null, 8, ["model-value", "onUpdate:modelValue", "disabled"]))
18415
+ ], 64)) : createCommentVNode("", true),
18416
+ column.key === "actions" && hasAnyActions.value ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [
18417
+ ((_a2 = props.actions) == null ? void 0 : _a2.includes("edit")) ? (openBlock(), createBlock(VBtn, {
18418
+ key: 0,
18419
+ color: "blue",
18420
+ size: "small",
18421
+ class: "mr-2",
18422
+ onClick: ($event) => openDialog(item)
18423
+ }, {
18424
+ default: withCtx(() => [..._cache[38] || (_cache[38] = [
18425
+ createTextVNode(" ویرایش ✏️ ", -1)
18426
+ ])]),
18427
+ _: 1
18428
+ }, 8, ["onClick"])) : createCommentVNode("", true),
18429
+ ((_b = props.actions) == null ? void 0 : _b.includes("delete")) ? (openBlock(), createBlock(VBtn, {
18430
+ key: 1,
18431
+ color: "red",
18432
+ size: "small",
18433
+ class: "mr-2",
18434
+ onClick: ($event) => openDeleteDialog(item)
18435
+ }, {
18436
+ default: withCtx(() => [..._cache[39] || (_cache[39] = [
18437
+ createTextVNode("حذف ❌ ", -1)
18438
+ ])]),
18439
+ _: 1
18440
+ }, 8, ["onClick"])) : createCommentVNode("", true),
18441
+ ((_c = props.actions) == null ? void 0 : _c.includes("view")) ? (openBlock(), createBlock(VBtn, {
18442
+ key: 2,
18443
+ color: "purple",
18444
+ size: "small",
18445
+ class: "mr-2",
18446
+ onClick: ($event) => goToRoute("view", item)
18447
+ }, {
18448
+ default: withCtx(() => [..._cache[40] || (_cache[40] = [
18449
+ createTextVNode("🔍 نمایش ", -1)
18450
+ ])]),
18451
+ _: 1
18452
+ }, 8, ["onClick"])) : createCommentVNode("", true),
18453
+ (openBlock(true), createElementBlock(Fragment, null, renderList(getRoutesForItem(item), (routePath, routeKey) => {
18454
+ return openBlock(), createBlock(VBtn, {
18455
+ key: routeKey,
18456
+ color: "indigo",
18457
+ size: "small",
18458
+ class: "mr-2",
18459
+ onClick: ($event) => goToRoute(routeKey, item)
18460
+ }, {
18461
+ default: withCtx(() => [
18462
+ createTextVNode(toDisplayString(routeKey.toUpperCase()), 1)
18463
+ ]),
18464
+ _: 2
18465
+ }, 1032, ["onClick"]);
18466
+ }), 128)),
18467
+ (openBlock(true), createElementBlock(Fragment, null, renderList(props.downloadLink, (value2, key2) => {
18468
+ return openBlock(), createBlock(VBtn, {
18469
+ size: "small",
18470
+ class: "mr-2",
18471
+ key: key2,
18472
+ onClick: ($event) => download(key2, item)
18473
+ }, {
18474
+ default: withCtx(() => [
18475
+ createTextVNode(toDisplayString(key2) + " ⬇️ ", 1)
18476
+ ]),
18477
+ _: 2
18478
+ }, 1032, ["onClick"]);
18479
+ }), 128)),
18480
+ (openBlock(true), createElementBlock(Fragment, null, renderList(props.customActions, (action, index22) => {
18481
+ return openBlock(), createElementBlock(Fragment, {
18482
+ key: action.title || index22
18483
+ }, [
18484
+ !action.condition || action.condition(item) ? (openBlock(), createBlock(VBtn, {
18485
+ key: 0,
18486
+ color: "orange",
18487
+ size: "small",
18488
+ class: "mr-2",
18489
+ onClick: ($event) => openCustomActionDialog(action, item)
18490
+ }, {
18491
+ default: withCtx(() => [
18492
+ createTextVNode(toDisplayString(action.title), 1)
18493
+ ]),
18494
+ _: 2
18495
+ }, 1032, ["onClick"])) : createCommentVNode("", true)
18496
+ ], 64);
18497
+ }), 128)),
18498
+ props.customButtonsFn ? (openBlock(true), createElementBlock(Fragment, { key: 3 }, renderList(props.customButtonsFn(item), (button) => {
18499
+ return openBlock(), createBlock(VBtn, {
18500
+ key: button.label,
18501
+ color: button.color || "primary",
18502
+ size: "small",
18503
+ class: "mr-2",
18504
+ disabled: button.disabled,
18505
+ onClick: ($event) => button.onClick(item)
18506
+ }, {
18507
+ default: withCtx(() => [
18508
+ createTextVNode(toDisplayString(button.label), 1)
18509
+ ]),
18510
+ _: 2
18511
+ }, 1032, ["color", "disabled", "onClick"]);
18512
+ }), 128)) : (openBlock(true), createElementBlock(Fragment, { key: 4 }, renderList(props.customButtons, (button) => {
18513
+ return openBlock(), createBlock(VBtn, {
18514
+ key: button.label,
18515
+ color: button.color || "primary",
18516
+ size: "small",
18517
+ class: "mr-2",
18518
+ onClick: ($event) => button.onClick(item)
18519
+ }, {
18520
+ default: withCtx(() => [
18521
+ createTextVNode(toDisplayString(button.label), 1)
18522
+ ]),
18523
+ _: 2
18524
+ }, 1032, ["color", "onClick"]);
18525
+ }), 128))
18526
+ ], 64)) : (openBlock(), createElementBlock(Fragment, { key: 2 }, [
18527
+ shouldTruncate(getTranslatedValue(getNestedValue2(item, column.key || ""), column, item)) ? (openBlock(), createElementBlock("span", {
18528
+ key: 0,
18529
+ class: "truncated-text",
18530
+ style: { cursor: "pointer", color: "rgb(var(--v-theme-primary))", textDecoration: "underline" },
18531
+ onClick: withModifiers(($event) => openTextPreview(getTranslatedValue(getNestedValue2(item, column.key || ""), column, item), column.title || column.key || "", item), ["stop"])
18532
+ }, toDisplayString(truncateText(getTranslatedValue(getNestedValue2(item, column.key || ""), column, item))), 9, _hoisted_19)) : (openBlock(), createElementBlock("span", _hoisted_20, toDisplayString(getTranslatedValue(getNestedValue2(item, column.key || ""), column, item)), 1))
18533
+ ], 64))
18534
+ ], 4);
18535
+ }), 128))
18536
+ ], 44, _hoisted_18)
18537
+ ]),
18538
+ _: 1
18539
+ }, 8, ["headers", "items", "items-per-page", "height"])),
18540
+ isLoadingMore.value ? (openBlock(), createElementBlock("div", _hoisted_21, [
18541
+ createVNode(VProgressCircular, {
18542
+ indeterminate: "",
18543
+ color: "primary"
18544
+ })
18545
+ ])) : createCommentVNode("", true)
18546
+ ], 64)),
18547
+ props.showPagination ? (openBlock(), createElementBlock("div", _hoisted_22, [
18548
+ createElementVNode("div", _hoisted_23, [
18549
+ createElementVNode("div", _hoisted_24, " نمایش " + toDisplayString((currentPage.value - 1) * itemsPerPage.value + 1) + " تا " + toDisplayString(Math.min(currentPage.value * itemsPerPage.value, totalSize.value)) + " از " + toDisplayString(totalSize.value) + " رکورد ", 1),
18550
+ createVNode(VPagination, {
18551
+ modelValue: currentPage.value,
18552
+ "onUpdate:modelValue": [
18553
+ _cache[3] || (_cache[3] = ($event) => currentPage.value = $event),
18554
+ handlePageChange
18555
+ ],
18556
+ length: totalPages.value,
18557
+ "total-visible": 5,
18558
+ size: "small"
18559
+ }, null, 8, ["modelValue", "length"])
18560
+ ])
18561
+ ])) : createCommentVNode("", true)
18562
+ ], 16, _hoisted_8$1),
18563
+ createVNode(VDialog, {
18564
+ modelValue: dialog.value,
18565
+ "onUpdate:modelValue": _cache[6] || (_cache[6] = ($event) => dialog.value = $event),
18566
+ "max-width": "1400"
18567
+ }, {
18568
+ default: withCtx(() => [
18569
+ createVNode(VCard, null, {
18570
+ default: withCtx(() => [
18571
+ createVNode(VCardTitle, null, {
18572
+ default: withCtx(() => [
18573
+ createTextVNode(toDisplayString(isEditing.value ? "ویرایش" : "ایجاد"), 1)
18574
+ ]),
18575
+ _: 1
18576
+ }),
18577
+ createVNode(VCardText, null, {
18578
+ default: withCtx(() => [
18579
+ createVNode(VContainer, null, {
18580
+ default: withCtx(() => [
18581
+ props.formComponent ? (openBlock(), createBlock(resolveDynamicComponent(props.formComponent), {
18582
+ key: 0,
18583
+ modelValue: formModel.value,
18584
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => formModel.value = $event)
18585
+ }, null, 8, ["modelValue"])) : (openBlock(), createBlock(VRow, { key: 1 }, {
18586
+ default: withCtx(() => [
18587
+ (openBlock(true), createElementBlock(Fragment, null, renderList(formHeaders.value, (header) => {
18588
+ return openBlock(), createBlock(VCol, {
18589
+ key: resolveHeaderKey(header),
18590
+ cols: "12",
18591
+ md: "4"
18592
+ }, {
18593
+ default: withCtx(() => [
18594
+ !header.hidden ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
18595
+ header.isDate ? (openBlock(), createBlock(ShamsiDatePicker, {
18596
+ key: 0,
18597
+ modelValue: formModel.value[resolveHeaderKey(header)],
18598
+ "onUpdate:modelValue": ($event) => formModel.value[resolveHeaderKey(header)] = $event,
18599
+ label: resolveHeaderTitle(header),
18600
+ disabled: isHeaderDisabled(header)
18601
+ }, null, 8, ["modelValue", "onUpdate:modelValue", "label", "disabled"])) : hasAutocomplete(header) ? (openBlock(), createBlock(VAutocomplete, {
18602
+ key: 1,
18603
+ modelValue: formModel.value[resolveHeaderKey(header)],
18604
+ "onUpdate:modelValue": ($event) => formModel.value[resolveHeaderKey(header)] = $event,
18605
+ label: resolveHeaderTitle(header),
18606
+ items: resolveAutocompleteItems(header, formModel.value.value),
18607
+ "item-title": resolveAutocompleteItemTitle(header),
18608
+ "item-value": resolveAutocompleteItemValue(header),
18609
+ "return-object": resolveAutocompleteReturnObject(header),
18610
+ multiple: resolveAutocompleteMultiple(header),
18611
+ chips: resolveAutocompleteMultiple(header),
18612
+ "closable-chips": resolveAutocompleteMultiple(header),
18613
+ disabled: isHeaderDisabled(header),
18614
+ clearable: "",
18615
+ variant: "outlined"
18616
+ }, null, 8, ["modelValue", "onUpdate:modelValue", "label", "items", "item-title", "item-value", "return-object", "multiple", "chips", "closable-chips", "disabled"])) : isMoneyHeader(header) ? (openBlock(), createBlock(_sfc_main$h, {
18617
+ key: 2,
18618
+ modelValue: formModel.value[resolveHeaderKey(header)],
18619
+ "onUpdate:modelValue": ($event) => formModel.value[resolveHeaderKey(header)] = $event,
18620
+ label: resolveHeaderTitle(header),
18621
+ disabled: isHeaderDisabled(header)
18622
+ }, null, 8, ["modelValue", "onUpdate:modelValue", "label", "disabled"])) : (openBlock(), createBlock(VTextField, {
18623
+ key: 3,
18624
+ modelValue: formModel.value[resolveHeaderKey(header)],
18625
+ "onUpdate:modelValue": ($event) => formModel.value[resolveHeaderKey(header)] = $event,
18626
+ label: resolveHeaderTitle(header),
18627
+ variant: "outlined",
18628
+ disabled: isHeaderDisabled(header),
18629
+ type: getFieldInputType(header)
18630
+ }, null, 8, ["modelValue", "onUpdate:modelValue", "label", "disabled", "type"]))
18631
+ ], 64)) : createCommentVNode("", true)
18632
+ ]),
18633
+ _: 2
18634
+ }, 1024);
18635
+ }), 128))
18636
+ ]),
18637
+ _: 1
18638
+ }))
18639
+ ]),
18640
+ _: 1
18641
+ })
18642
+ ]),
18643
+ _: 1
18644
+ }),
18645
+ createVNode(VCardActions, null, {
18646
+ default: withCtx(() => [
18647
+ createVNode(VBtn, {
18648
+ variant: "tonal",
18649
+ color: "error",
18650
+ onClick: _cache[5] || (_cache[5] = ($event) => dialog.value = false)
18651
+ }, {
18652
+ default: withCtx(() => [..._cache[41] || (_cache[41] = [
18653
+ createTextVNode("انصراف", -1)
18654
+ ])]),
18655
+ _: 1
18656
+ }),
18657
+ createVNode(VBtn, {
18658
+ color: "primary",
18659
+ var: "",
18660
+ onClick: saveItem
18661
+ }, {
18662
+ default: withCtx(() => [
18663
+ createTextVNode(toDisplayString(isEditing.value ? "ذخیره" : "ایجاد"), 1)
18664
+ ]),
18665
+ _: 1
18666
+ })
18667
+ ]),
18668
+ _: 1
18669
+ })
18670
+ ]),
18671
+ _: 1
18672
+ })
18673
+ ]),
18674
+ _: 1
18675
+ }, 8, ["modelValue"]),
18676
+ createVNode(VDialog, {
18677
+ modelValue: deleteDialog.value,
18678
+ "onUpdate:modelValue": _cache[9] || (_cache[9] = ($event) => deleteDialog.value = $event),
18679
+ "max-width": "400"
18680
+ }, {
18681
+ default: withCtx(() => [
18682
+ createVNode(VCard, null, {
18683
+ default: withCtx(() => [
18684
+ createVNode(VCardTitle, null, {
18685
+ default: withCtx(() => [..._cache[42] || (_cache[42] = [
18686
+ createTextVNode("حذف آیتم", -1)
18687
+ ])]),
18688
+ _: 1
18689
+ }),
18690
+ createVNode(VCardText, null, {
18691
+ default: withCtx(() => [..._cache[43] || (_cache[43] = [
18692
+ createTextVNode(" آیا مایل به حذف این رکورد هستید ?", -1)
18693
+ ])]),
18694
+ _: 1
18695
+ }),
18696
+ createVNode(VCardActions, null, {
18697
+ default: withCtx(() => [
18698
+ createVNode(VBtn, {
18699
+ color: "grey",
18700
+ onClick: _cache[7] || (_cache[7] = ($event) => deleteDialog.value = false)
18701
+ }, {
18702
+ default: withCtx(() => [..._cache[44] || (_cache[44] = [
18703
+ createTextVNode("انصراف", -1)
18704
+ ])]),
18705
+ _: 1
18706
+ }),
18707
+ createVNode(VBtn, {
18708
+ color: "red",
18709
+ onClick: _cache[8] || (_cache[8] = ($event) => {
18710
+ var _a2;
18711
+ return deleteItem(String(((_a2 = itemToDelete.value) == null ? void 0 : _a2.id) || ""));
18712
+ })
18713
+ }, {
18714
+ default: withCtx(() => [..._cache[45] || (_cache[45] = [
18715
+ createTextVNode("حذف", -1)
18716
+ ])]),
18717
+ _: 1
18718
+ })
18719
+ ]),
18720
+ _: 1
18721
+ })
18722
+ ]),
18723
+ _: 1
18724
+ })
18725
+ ]),
18726
+ _: 1
18727
+ }, 8, ["modelValue"]),
18728
+ createVNode(VDialog, {
18729
+ modelValue: groupDeleteDialog.value,
18730
+ "onUpdate:modelValue": _cache[11] || (_cache[11] = ($event) => groupDeleteDialog.value = $event),
18731
+ "max-width": "500"
18732
+ }, {
18733
+ default: withCtx(() => [
18734
+ createVNode(VCard, null, {
18735
+ default: withCtx(() => [
18736
+ createVNode(VCardTitle, { class: "text-h6" }, {
18737
+ default: withCtx(() => [
18738
+ createVNode(VIcon, {
18739
+ color: "red",
18740
+ class: "me-2"
18741
+ }, {
18742
+ default: withCtx(() => [..._cache[46] || (_cache[46] = [
18743
+ createTextVNode("🗑️", -1)
18744
+ ])]),
18745
+ _: 1
18746
+ }),
18747
+ _cache[47] || (_cache[47] = createTextVNode(" حذف گروهی ", -1))
18748
+ ]),
18749
+ _: 1
18750
+ }),
18751
+ createVNode(VCardText, null, {
18752
+ default: withCtx(() => [
18753
+ createElementVNode("p", null, [
18754
+ _cache[48] || (_cache[48] = createTextVNode(" آیا مایل به حذف ", -1)),
18755
+ createElementVNode("strong", null, toDisplayString(selectedCount.value), 1),
18756
+ _cache[49] || (_cache[49] = createTextVNode(" آیتم انتخاب شده هستید؟ ", -1))
18757
+ ]),
18758
+ createVNode(VAlert, {
18759
+ type: "warning",
18760
+ variant: "tonal",
18761
+ class: "mt-3"
18762
+ }, {
18763
+ default: withCtx(() => [..._cache[50] || (_cache[50] = [
18764
+ createTextVNode(" این عمل قابل بازگشت نیست! ", -1)
18765
+ ])]),
18766
+ _: 1
18767
+ })
18768
+ ]),
18769
+ _: 1
18770
+ }),
18771
+ createVNode(VCardActions, null, {
18772
+ default: withCtx(() => [
18773
+ createVNode(VSpacer),
18774
+ createVNode(VBtn, {
18775
+ color: "grey",
18776
+ onClick: _cache[10] || (_cache[10] = ($event) => groupDeleteDialog.value = false)
18777
+ }, {
18778
+ default: withCtx(() => [..._cache[51] || (_cache[51] = [
18779
+ createTextVNode("انصراف", -1)
18780
+ ])]),
18781
+ _: 1
18782
+ }),
18783
+ createVNode(VBtn, {
18784
+ color: "red",
18785
+ onClick: deleteGroupItems,
18786
+ loading: loading.value
18787
+ }, {
18788
+ default: withCtx(() => [
18789
+ createTextVNode(" حذف " + toDisplayString(selectedCount.value) + " آیتم ", 1)
18790
+ ]),
18791
+ _: 1
18792
+ }, 8, ["loading"])
18793
+ ]),
18794
+ _: 1
18795
+ })
18796
+ ]),
18797
+ _: 1
18798
+ })
18799
+ ]),
18800
+ _: 1
18801
+ }, 8, ["modelValue"]),
18802
+ createVNode(VDialog, {
18803
+ modelValue: customActionDialog.value,
18804
+ "onUpdate:modelValue": _cache[13] || (_cache[13] = ($event) => customActionDialog.value = $event),
18805
+ "max-width": "1300"
18806
+ }, {
18807
+ default: withCtx(() => [
18808
+ createVNode(VCard, null, {
18809
+ default: withCtx(() => [
18810
+ createVNode(VCardTitle, null, {
18811
+ default: withCtx(() => {
18812
+ var _a2, _b;
18813
+ return [
18814
+ createTextVNode(toDisplayString(((_b = (_a2 = props.customActions) == null ? void 0 : _a2.find((a) => a.component === customActionComponent.value)) == null ? void 0 : _b.title) || ""), 1)
18815
+ ];
18816
+ }),
18817
+ _: 1
18818
+ }),
18819
+ createVNode(VCardText, null, {
18820
+ default: withCtx(() => [
18821
+ customActionComponent.value ? (openBlock(), createBlock(resolveDynamicComponent(customActionComponent.value), {
18822
+ key: 0,
18823
+ item: customActionItem.value,
18824
+ onClose: _cache[12] || (_cache[12] = ($event) => customActionDialog.value = false)
18825
+ }, null, 40, ["item"])) : createCommentVNode("", true)
18826
+ ]),
18827
+ _: 1
18828
+ })
18829
+ ]),
18830
+ _: 1
18831
+ })
18832
+ ]),
18833
+ _: 1
18834
+ }, 8, ["modelValue"]),
18835
+ createVNode(VDialog, {
18836
+ modelValue: filterDialog.value,
18837
+ "onUpdate:modelValue": _cache[16] || (_cache[16] = ($event) => filterDialog.value = $event),
18838
+ "max-width": "800"
18839
+ }, {
18840
+ default: withCtx(() => [
18841
+ createVNode(VCard, null, {
18842
+ default: withCtx(() => [
18843
+ createVNode(VCardTitle, null, {
18844
+ default: withCtx(() => [..._cache[52] || (_cache[52] = [
18845
+ createTextVNode("فیلتر", -1)
18846
+ ])]),
18847
+ _: 1
18848
+ }),
18849
+ createVNode(VCardText, null, {
18850
+ default: withCtx(() => [
18851
+ props.filterComponent ? (openBlock(), createBlock(resolveDynamicComponent(props.filterComponent), {
18852
+ key: 0,
18853
+ modelValue: filterModel.value,
18854
+ "onUpdate:modelValue": [
18855
+ _cache[14] || (_cache[14] = ($event) => filterModel.value = $event),
18856
+ _cache[15] || (_cache[15] = ($event) => filterModel.value = $event)
18857
+ ],
18858
+ onApply: handleFilterApply
18859
+ }, null, 40, ["modelValue"])) : createCommentVNode("", true)
18860
+ ]),
18861
+ _: 1
18862
+ })
18863
+ ]),
18864
+ _: 1
18865
+ })
18866
+ ]),
18867
+ _: 1
18868
+ }, 8, ["modelValue"]),
18869
+ createVNode(VDialog, {
18870
+ modelValue: textPreviewDialog.value,
18871
+ "onUpdate:modelValue": _cache[20] || (_cache[20] = ($event) => textPreviewDialog.value = $event),
18872
+ "max-width": "800"
18873
+ }, {
18874
+ default: withCtx(() => [
18875
+ createVNode(VCard, null, {
18876
+ default: withCtx(() => [
18877
+ createVNode(VCardTitle, { class: "d-flex justify-space-between align-center" }, {
18878
+ default: withCtx(() => [
18879
+ createElementVNode("span", null, toDisplayString(previewTitle.value), 1),
18880
+ createVNode(VBtn, {
18881
+ icon: "",
18882
+ variant: "text",
18883
+ onClick: _cache[17] || (_cache[17] = ($event) => textPreviewDialog.value = false)
18884
+ }, {
18885
+ default: withCtx(() => [
18886
+ createVNode(VIcon, null, {
18887
+ default: withCtx(() => [..._cache[53] || (_cache[53] = [
18888
+ createTextVNode("mdi-close", -1)
18889
+ ])]),
18890
+ _: 1
18891
+ })
18892
+ ]),
18893
+ _: 1
18894
+ })
18895
+ ]),
18896
+ _: 1
18897
+ }),
18898
+ createVNode(VCardText, null, {
18899
+ default: withCtx(() => [
18900
+ createVNode(VTextarea, {
18901
+ "model-value": previewText.value,
18902
+ readonly: "",
18903
+ "auto-grow": "",
18904
+ variant: "outlined",
18905
+ rows: "10",
18906
+ class: "mb-4"
18907
+ }, null, 8, ["model-value"])
18908
+ ]),
18909
+ _: 1
18910
+ }),
18911
+ createVNode(VCardActions, null, {
18912
+ default: withCtx(() => [
18913
+ createVNode(VSpacer),
18914
+ createVNode(VBtn, {
18915
+ color: "primary",
18916
+ onClick: _cache[18] || (_cache[18] = ($event) => copyToClipboard(previewText.value))
18917
+ }, {
18918
+ default: withCtx(() => [
18919
+ createVNode(VIcon, { start: "" }, {
18920
+ default: withCtx(() => [..._cache[54] || (_cache[54] = [
18921
+ createTextVNode("mdi-content-copy", -1)
18922
+ ])]),
18923
+ _: 1
18924
+ }),
18925
+ _cache[55] || (_cache[55] = createTextVNode(" کپی متن ", -1))
18926
+ ]),
18927
+ _: 1
18928
+ }),
18929
+ createVNode(VBtn, {
18930
+ color: "success",
18931
+ onClick: copyCompleteRecord
18932
+ }, {
18933
+ default: withCtx(() => [
18934
+ createVNode(VIcon, { start: "" }, {
18935
+ default: withCtx(() => [..._cache[56] || (_cache[56] = [
18936
+ createTextVNode("mdi-content-copy", -1)
18937
+ ])]),
18938
+ _: 1
18939
+ }),
18940
+ _cache[57] || (_cache[57] = createTextVNode(" کپی رکورد کامل ", -1))
18941
+ ]),
18942
+ _: 1
18943
+ }),
18944
+ createVNode(VBtn, {
18945
+ color: "grey",
18946
+ onClick: _cache[19] || (_cache[19] = ($event) => textPreviewDialog.value = false)
18947
+ }, {
18948
+ default: withCtx(() => [..._cache[58] || (_cache[58] = [
18949
+ createTextVNode("بستن", -1)
18950
+ ])]),
18951
+ _: 1
18952
+ })
18953
+ ]),
18954
+ _: 1
18955
+ })
18956
+ ]),
18957
+ _: 1
18958
+ })
18959
+ ]),
18960
+ _: 1
18961
+ }, 8, ["modelValue"]),
18962
+ snackbar.value ? (openBlock(), createBlock(VSnackbar, {
18963
+ key: 1,
18964
+ modelValue: snackbar.value,
18965
+ "onUpdate:modelValue": _cache[22] || (_cache[22] = ($event) => snackbar.value = $event),
18966
+ timeout: 3e3,
18967
+ location: "top"
18968
+ }, {
18969
+ actions: withCtx(() => [
18970
+ createVNode(VBtn, {
18971
+ color: "white",
18972
+ variant: "text",
18973
+ onClick: _cache[21] || (_cache[21] = ($event) => snackbar.value = false)
18974
+ }, {
18975
+ default: withCtx(() => [..._cache[59] || (_cache[59] = [
18976
+ createTextVNode(" بستن ", -1)
18977
+ ])]),
18978
+ _: 1
18979
+ })
18980
+ ]),
18981
+ default: withCtx(() => [
18982
+ createTextVNode(toDisplayString(snackbarMessage.value) + " ", 1)
18983
+ ]),
18984
+ _: 1
18985
+ }, 8, ["modelValue"])) : createCommentVNode("", true)
18986
+ ], 64);
18987
+ };
18825
18988
  }
18826
18989
  });
18827
18990
  const _hoisted_1$8 = { class: "description-input" };