@sesionario/blocks 1.39.0 → 1.40.0
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/README.md +21 -0
- package/dist/index.cjs +813 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +32 -2
- package/dist/index.d.ts +32 -2
- package/dist/index.js +812 -58
- package/dist/index.js.map +1 -1
- package/dist/livo.cjs +8 -0
- package/dist/livo.cjs.map +1 -1
- package/dist/livo.js +8 -0
- package/dist/livo.js.map +1 -1
- package/dist/office.cjs +310 -0
- package/dist/office.cjs.map +1 -0
- package/dist/office.d.cts +53 -0
- package/dist/office.d.ts +53 -0
- package/dist/office.js +282 -0
- package/dist/office.js.map +1 -0
- package/dist/theme-chrome.cjs +127 -0
- package/dist/theme-chrome.cjs.map +1 -0
- package/dist/theme-chrome.d.cts +8 -0
- package/dist/theme-chrome.d.ts +8 -0
- package/dist/theme-chrome.js +125 -0
- package/dist/theme-chrome.js.map +1 -0
- package/dist/theme.cjs +138 -0
- package/dist/theme.cjs.map +1 -1
- package/dist/theme.d.cts +47 -1
- package/dist/theme.d.ts +47 -1
- package/dist/theme.js +133 -1
- package/dist/theme.js.map +1 -1
- package/package.json +22 -2
package/dist/index.js
CHANGED
|
@@ -23,6 +23,7 @@ import flags from 'react-phone-number-input/flags';
|
|
|
23
23
|
import * as ScrollAreaPrimitive from '@radix-ui/react-scroll-area';
|
|
24
24
|
import { MessageScroller as MessageScroller$1 } from '@shadcn/react/message-scroller';
|
|
25
25
|
export { useMessageScroller, useMessageScrollerScrollable, useMessageScrollerVisibility } from '@shadcn/react/message-scroller';
|
|
26
|
+
import { Slot as Slot$1 } from 'radix-ui';
|
|
26
27
|
|
|
27
28
|
var LanguageContext = createContext(null);
|
|
28
29
|
function useLanguageContext() {
|
|
@@ -602,7 +603,7 @@ function useEditableSection({
|
|
|
602
603
|
},
|
|
603
604
|
resolvedLabels,
|
|
604
605
|
contentStyle: stableHeight && minHeightPx != null ? { minHeight: minHeightPx } : void 0,
|
|
605
|
-
actionsClassName: "flex min-h-9
|
|
606
|
+
actionsClassName: "flex min-h-9 w-full flex-wrap items-center gap-2 *:flex-1 sm:w-auto sm:min-w-[11rem] sm:justify-end sm:*:flex-none"
|
|
606
607
|
};
|
|
607
608
|
}
|
|
608
609
|
function EditableSection({
|
|
@@ -4700,6 +4701,7 @@ function useSearchHotkey(options = {}) {
|
|
|
4700
4701
|
}
|
|
4701
4702
|
|
|
4702
4703
|
// src/lib/scroll-restoration/store.ts
|
|
4704
|
+
var programmaticDepth = 0;
|
|
4703
4705
|
var MAX_MARKS = 30;
|
|
4704
4706
|
var MAX_SNAPSHOT_ROUTES = 3;
|
|
4705
4707
|
var PENDING_TRAVERSAL_TTL_MS = 1e3;
|
|
@@ -4791,6 +4793,9 @@ function consumePendingTraversal(routeKey) {
|
|
|
4791
4793
|
clearPendingTraversalTimer();
|
|
4792
4794
|
return true;
|
|
4793
4795
|
}
|
|
4796
|
+
function isProgrammaticScroll() {
|
|
4797
|
+
return programmaticDepth > 0;
|
|
4798
|
+
}
|
|
4794
4799
|
function getScrollTop(container) {
|
|
4795
4800
|
if (!container) {
|
|
4796
4801
|
return window.scrollY || document.documentElement.scrollTop || 0;
|
|
@@ -4798,11 +4803,37 @@ function getScrollTop(container) {
|
|
|
4798
4803
|
return container.scrollTop;
|
|
4799
4804
|
}
|
|
4800
4805
|
function setScrollTop(container, top) {
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4806
|
+
programmaticDepth += 1;
|
|
4807
|
+
try {
|
|
4808
|
+
if (!container) {
|
|
4809
|
+
window.scrollTo({ top, left: 0, behavior: "instant" });
|
|
4810
|
+
return;
|
|
4811
|
+
}
|
|
4812
|
+
container.scrollTop = top;
|
|
4813
|
+
} finally {
|
|
4814
|
+
queueMicrotask(() => {
|
|
4815
|
+
programmaticDepth = Math.max(0, programmaticDepth - 1);
|
|
4816
|
+
});
|
|
4804
4817
|
}
|
|
4805
|
-
|
|
4818
|
+
}
|
|
4819
|
+
function isOverflowScrollport(element) {
|
|
4820
|
+
const overflow = getComputedStyle(element).overflowY;
|
|
4821
|
+
return overflow === "auto" || overflow === "scroll" || overflow === "overlay";
|
|
4822
|
+
}
|
|
4823
|
+
function resolveScrollPort(container) {
|
|
4824
|
+
if (!container) return "window";
|
|
4825
|
+
const windowTop = getScrollTop(null);
|
|
4826
|
+
const nestedTop = container.scrollTop;
|
|
4827
|
+
if (nestedTop > windowTop) return "container";
|
|
4828
|
+
if (windowTop > nestedTop) return "window";
|
|
4829
|
+
return isOverflowScrollport(container) ? "container" : "window";
|
|
4830
|
+
}
|
|
4831
|
+
function resetScrollports(container) {
|
|
4832
|
+
setScrollTop(null, 0);
|
|
4833
|
+
if (container) setScrollTop(container, 0);
|
|
4834
|
+
}
|
|
4835
|
+
function portNode(container, port) {
|
|
4836
|
+
return port === "container" ? container : null;
|
|
4806
4837
|
}
|
|
4807
4838
|
function scrollportTop(container) {
|
|
4808
4839
|
return container ? container.getBoundingClientRect().top : 0;
|
|
@@ -4844,11 +4875,14 @@ function resolveAnchor(container, attribute) {
|
|
|
4844
4875
|
return { id: bestId, top: bestTop };
|
|
4845
4876
|
}
|
|
4846
4877
|
function captureMark(container, attribute) {
|
|
4847
|
-
const
|
|
4878
|
+
const port = resolveScrollPort(container);
|
|
4879
|
+
const node = portNode(container, port);
|
|
4880
|
+
const anchor = resolveAnchor(node, attribute);
|
|
4848
4881
|
return {
|
|
4849
|
-
top: getScrollTop(
|
|
4882
|
+
top: getScrollTop(node),
|
|
4850
4883
|
anchorId: anchor?.id ?? null,
|
|
4851
|
-
anchorTop: anchor?.top ?? 0
|
|
4884
|
+
anchorTop: anchor?.top ?? 0,
|
|
4885
|
+
port
|
|
4852
4886
|
};
|
|
4853
4887
|
}
|
|
4854
4888
|
function applyMark(container, mark, attribute) {
|
|
@@ -4868,6 +4902,22 @@ function applyMark(container, mark, attribute) {
|
|
|
4868
4902
|
setScrollTop(container, mark.top);
|
|
4869
4903
|
return false;
|
|
4870
4904
|
}
|
|
4905
|
+
function restoreScrollports(container, mark, attribute) {
|
|
4906
|
+
const port = mark.port ?? "window";
|
|
4907
|
+
switch (port) {
|
|
4908
|
+
case "container":
|
|
4909
|
+
setScrollTop(null, 0);
|
|
4910
|
+
if (!container) return false;
|
|
4911
|
+
return applyMark(container, mark, attribute);
|
|
4912
|
+
case "window":
|
|
4913
|
+
if (container) setScrollTop(container, 0);
|
|
4914
|
+
return applyMark(null, mark, attribute);
|
|
4915
|
+
default: {
|
|
4916
|
+
const exhaustive = port;
|
|
4917
|
+
return exhaustive;
|
|
4918
|
+
}
|
|
4919
|
+
}
|
|
4920
|
+
}
|
|
4871
4921
|
function getScrollHeight(container) {
|
|
4872
4922
|
if (!container) {
|
|
4873
4923
|
return Math.max(
|
|
@@ -4883,8 +4933,37 @@ var ScrollRestorationContext = createContext(null);
|
|
|
4883
4933
|
function useScrollRestorationContext() {
|
|
4884
4934
|
return useContext(ScrollRestorationContext);
|
|
4885
4935
|
}
|
|
4886
|
-
function readContainer(containerRef) {
|
|
4887
|
-
return containerRef?.current ?? null;
|
|
4936
|
+
function readContainer(containerRef, registered) {
|
|
4937
|
+
return registered ?? containerRef?.current ?? null;
|
|
4938
|
+
}
|
|
4939
|
+
var USER_INTENT_EVENTS = [
|
|
4940
|
+
"wheel",
|
|
4941
|
+
"touchstart",
|
|
4942
|
+
"keydown",
|
|
4943
|
+
"pointerdown"
|
|
4944
|
+
];
|
|
4945
|
+
function listenForUserIntent(onIntent) {
|
|
4946
|
+
for (const type of USER_INTENT_EVENTS) {
|
|
4947
|
+
window.addEventListener(type, onIntent, { passive: true, once: true });
|
|
4948
|
+
}
|
|
4949
|
+
return () => {
|
|
4950
|
+
for (const type of USER_INTENT_EVENTS) {
|
|
4951
|
+
window.removeEventListener(type, onIntent);
|
|
4952
|
+
}
|
|
4953
|
+
};
|
|
4954
|
+
}
|
|
4955
|
+
function useRegisterScrollContainer(containerRef) {
|
|
4956
|
+
const ctx = useScrollRestorationContext();
|
|
4957
|
+
const setContainerRef = useRef(ctx?.setScrollContainer);
|
|
4958
|
+
setContainerRef.current = ctx?.setScrollContainer;
|
|
4959
|
+
useLayoutEffect(() => {
|
|
4960
|
+
const setContainer = setContainerRef.current;
|
|
4961
|
+
if (!setContainer) return;
|
|
4962
|
+
setContainer(containerRef.current);
|
|
4963
|
+
return () => {
|
|
4964
|
+
setContainer(null);
|
|
4965
|
+
};
|
|
4966
|
+
}, [containerRef]);
|
|
4888
4967
|
}
|
|
4889
4968
|
function ScrollRestorationProvider({
|
|
4890
4969
|
routeKey,
|
|
@@ -4901,13 +4980,23 @@ function ScrollRestorationProvider({
|
|
|
4901
4980
|
};
|
|
4902
4981
|
}
|
|
4903
4982
|
const isTraversal = traversalForRouteRef.current.isTraversal;
|
|
4983
|
+
const registeredContainerRef = useRef(null);
|
|
4984
|
+
const [scrollContainerNode, setScrollContainerNode] = useState(null);
|
|
4985
|
+
const setScrollContainer = useCallback((node) => {
|
|
4986
|
+
registeredContainerRef.current = node;
|
|
4987
|
+
setScrollContainerNode((current) => current === node ? current : node);
|
|
4988
|
+
}, []);
|
|
4989
|
+
const readActiveContainer = useCallback(() => {
|
|
4990
|
+
return readContainer(containerRef, registeredContainerRef.current);
|
|
4991
|
+
}, [containerRef]);
|
|
4904
4992
|
const value = useMemo(
|
|
4905
4993
|
() => ({
|
|
4906
4994
|
routeKey,
|
|
4907
4995
|
isTraversal,
|
|
4908
|
-
anchorAttribute
|
|
4996
|
+
anchorAttribute,
|
|
4997
|
+
setScrollContainer
|
|
4909
4998
|
}),
|
|
4910
|
-
[routeKey, isTraversal, anchorAttribute]
|
|
4999
|
+
[routeKey, isTraversal, anchorAttribute, setScrollContainer]
|
|
4911
5000
|
);
|
|
4912
5001
|
useEffect(() => {
|
|
4913
5002
|
if (typeof window === "undefined" || !("scrollRestoration" in history)) {
|
|
@@ -4922,34 +5011,50 @@ function ScrollRestorationProvider({
|
|
|
4922
5011
|
const prevRouteKeyRef = useRef(routeKey);
|
|
4923
5012
|
const anchorAttributeRef = useRef(anchorAttribute);
|
|
4924
5013
|
anchorAttributeRef.current = anchorAttribute;
|
|
5014
|
+
useLayoutEffect(() => {
|
|
5015
|
+
const nodes = [document.documentElement];
|
|
5016
|
+
const container = readActiveContainer();
|
|
5017
|
+
if (container) nodes.push(container);
|
|
5018
|
+
const previous = nodes.map((node) => node.style.overflowAnchor);
|
|
5019
|
+
for (const node of nodes) node.style.overflowAnchor = "none";
|
|
5020
|
+
return () => {
|
|
5021
|
+
nodes.forEach((node, index) => {
|
|
5022
|
+
node.style.overflowAnchor = previous[index] ?? "";
|
|
5023
|
+
});
|
|
5024
|
+
};
|
|
5025
|
+
}, [readActiveContainer, scrollContainerNode]);
|
|
4925
5026
|
useEffect(() => {
|
|
4926
|
-
const container =
|
|
4927
|
-
const target = container ?? window;
|
|
5027
|
+
const container = readActiveContainer();
|
|
4928
5028
|
let rafId = 0;
|
|
4929
5029
|
const onScroll = () => {
|
|
5030
|
+
if (isProgrammaticScroll()) return;
|
|
4930
5031
|
if (rafId) return;
|
|
4931
5032
|
rafId = requestAnimationFrame(() => {
|
|
4932
5033
|
rafId = 0;
|
|
4933
5034
|
setScrollMark(
|
|
4934
5035
|
routeKey,
|
|
4935
|
-
captureMark(
|
|
5036
|
+
captureMark(readActiveContainer(), anchorAttribute)
|
|
4936
5037
|
);
|
|
4937
5038
|
});
|
|
4938
5039
|
};
|
|
4939
|
-
|
|
5040
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
5041
|
+
container?.addEventListener("scroll", onScroll, { passive: true });
|
|
4940
5042
|
return () => {
|
|
4941
|
-
|
|
5043
|
+
window.removeEventListener("scroll", onScroll);
|
|
5044
|
+
container?.removeEventListener("scroll", onScroll);
|
|
4942
5045
|
if (rafId) cancelAnimationFrame(rafId);
|
|
4943
5046
|
};
|
|
4944
|
-
}, [routeKey,
|
|
5047
|
+
}, [routeKey, anchorAttribute, readActiveContainer, scrollContainerNode]);
|
|
4945
5048
|
useLayoutEffect(() => {
|
|
4946
|
-
const container =
|
|
5049
|
+
const container = readActiveContainer();
|
|
4947
5050
|
const prevKey = prevRouteKeyRef.current;
|
|
4948
5051
|
if (prevKey !== routeKey) {
|
|
4949
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
)
|
|
5052
|
+
const fresh = captureMark(container, anchorAttributeRef.current);
|
|
5053
|
+
const existing = getScrollMark(prevKey);
|
|
5054
|
+
const paneUnmounted = existing?.port === "container" && fresh.port === "window" && fresh.top === 0 && container === null;
|
|
5055
|
+
if (!paneUnmounted) {
|
|
5056
|
+
setScrollMark(prevKey, fresh);
|
|
5057
|
+
}
|
|
4953
5058
|
prevRouteKeyRef.current = routeKey;
|
|
4954
5059
|
}
|
|
4955
5060
|
const hasHash = typeof window !== "undefined" && window.location.hash.length > 1;
|
|
@@ -4957,51 +5062,58 @@ function ScrollRestorationProvider({
|
|
|
4957
5062
|
consumePendingTraversal(routeKey);
|
|
4958
5063
|
const mark = getScrollMark(routeKey);
|
|
4959
5064
|
if (!mark) return void 0;
|
|
4960
|
-
|
|
4961
|
-
return startStabilizationLoop(
|
|
5065
|
+
restoreScrollports(container, mark, anchorAttribute);
|
|
5066
|
+
return startStabilizationLoop(
|
|
5067
|
+
() => readActiveContainer(),
|
|
5068
|
+
mark,
|
|
5069
|
+
anchorAttribute
|
|
5070
|
+
);
|
|
4962
5071
|
}
|
|
4963
5072
|
clearRoute(routeKey);
|
|
4964
|
-
if (
|
|
4965
|
-
|
|
4966
|
-
|
|
4967
|
-
return void 0;
|
|
4968
|
-
}, [routeKey, isTraversal, containerRef, anchorAttribute]);
|
|
5073
|
+
if (hasHash) return void 0;
|
|
5074
|
+
return startFreshReset(readActiveContainer);
|
|
5075
|
+
}, [routeKey, isTraversal, anchorAttribute, readActiveContainer]);
|
|
4969
5076
|
return /* @__PURE__ */ jsx(ScrollRestorationContext.Provider, { value, children });
|
|
4970
5077
|
}
|
|
4971
|
-
function
|
|
5078
|
+
function startFreshReset(readContainer2) {
|
|
5079
|
+
let cancelled = false;
|
|
5080
|
+
const apply = () => {
|
|
5081
|
+
if (cancelled) return;
|
|
5082
|
+
resetScrollports(readContainer2());
|
|
5083
|
+
};
|
|
5084
|
+
apply();
|
|
5085
|
+
let rafId = requestAnimationFrame(() => {
|
|
5086
|
+
rafId = 0;
|
|
5087
|
+
apply();
|
|
5088
|
+
});
|
|
5089
|
+
const stopIntent = listenForUserIntent(() => {
|
|
5090
|
+
cancelled = true;
|
|
5091
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
5092
|
+
rafId = 0;
|
|
5093
|
+
});
|
|
5094
|
+
return () => {
|
|
5095
|
+
cancelled = true;
|
|
5096
|
+
if (rafId) cancelAnimationFrame(rafId);
|
|
5097
|
+
stopIntent();
|
|
5098
|
+
};
|
|
5099
|
+
}
|
|
5100
|
+
function startStabilizationLoop(readContainer2, mark, attribute) {
|
|
5101
|
+
const portNode2 = () => (mark.port ?? "window") === "container" ? readContainer2() : null;
|
|
4972
5102
|
const startedAt = performance.now();
|
|
4973
|
-
let lastHeight = getScrollHeight(
|
|
5103
|
+
let lastHeight = getScrollHeight(portNode2());
|
|
4974
5104
|
let rafId = 0;
|
|
4975
5105
|
let aborted = false;
|
|
4976
5106
|
const abort = () => {
|
|
4977
5107
|
aborted = true;
|
|
4978
5108
|
};
|
|
4979
|
-
const
|
|
4980
|
-
abort();
|
|
4981
|
-
};
|
|
4982
|
-
window.addEventListener("wheel", onUserIntent, {
|
|
4983
|
-
passive: true,
|
|
4984
|
-
once: true
|
|
4985
|
-
});
|
|
4986
|
-
window.addEventListener("touchstart", onUserIntent, {
|
|
4987
|
-
passive: true,
|
|
4988
|
-
once: true
|
|
4989
|
-
});
|
|
4990
|
-
window.addEventListener("keydown", onUserIntent, {
|
|
4991
|
-
passive: true,
|
|
4992
|
-
once: true
|
|
4993
|
-
});
|
|
4994
|
-
window.addEventListener("pointerdown", onUserIntent, {
|
|
4995
|
-
passive: true,
|
|
4996
|
-
once: true
|
|
4997
|
-
});
|
|
5109
|
+
const stopIntent = listenForUserIntent(abort);
|
|
4998
5110
|
const tick = () => {
|
|
4999
5111
|
if (aborted) return;
|
|
5000
5112
|
if (performance.now() - startedAt > STABILIZE_MS) return;
|
|
5001
|
-
const height = getScrollHeight(
|
|
5113
|
+
const height = getScrollHeight(portNode2());
|
|
5002
5114
|
if (height !== lastHeight) {
|
|
5003
5115
|
lastHeight = height;
|
|
5004
|
-
|
|
5116
|
+
restoreScrollports(readContainer2(), mark, attribute);
|
|
5005
5117
|
}
|
|
5006
5118
|
rafId = requestAnimationFrame(tick);
|
|
5007
5119
|
};
|
|
@@ -5009,10 +5121,7 @@ function startStabilizationLoop(container, mark, attribute) {
|
|
|
5009
5121
|
return () => {
|
|
5010
5122
|
abort();
|
|
5011
5123
|
if (rafId) cancelAnimationFrame(rafId);
|
|
5012
|
-
|
|
5013
|
-
window.removeEventListener("touchstart", onUserIntent);
|
|
5014
|
-
window.removeEventListener("keydown", onUserIntent);
|
|
5015
|
-
window.removeEventListener("pointerdown", onUserIntent);
|
|
5124
|
+
stopIntent();
|
|
5016
5125
|
};
|
|
5017
5126
|
}
|
|
5018
5127
|
|
|
@@ -8082,7 +8191,652 @@ function useRealtimeChannel({
|
|
|
8082
8191
|
};
|
|
8083
8192
|
}, [enabled, reconnectDelayMs]);
|
|
8084
8193
|
}
|
|
8194
|
+
var badgeVariants = cva(
|
|
8195
|
+
"inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3",
|
|
8196
|
+
{
|
|
8197
|
+
variants: {
|
|
8198
|
+
variant: {
|
|
8199
|
+
default: "bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
8200
|
+
secondary: "bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
8201
|
+
destructive: "bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90",
|
|
8202
|
+
outline: "border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
8203
|
+
ghost: "[a&]:hover:bg-accent [a&]:hover:text-accent-foreground",
|
|
8204
|
+
link: "text-primary underline-offset-4 [a&]:hover:underline"
|
|
8205
|
+
}
|
|
8206
|
+
},
|
|
8207
|
+
defaultVariants: {
|
|
8208
|
+
variant: "default"
|
|
8209
|
+
}
|
|
8210
|
+
}
|
|
8211
|
+
);
|
|
8212
|
+
function Badge({
|
|
8213
|
+
className,
|
|
8214
|
+
variant = "default",
|
|
8215
|
+
asChild = false,
|
|
8216
|
+
...props
|
|
8217
|
+
}) {
|
|
8218
|
+
const Comp = asChild ? Slot$1.Root : "span";
|
|
8219
|
+
return /* @__PURE__ */ jsx(
|
|
8220
|
+
Comp,
|
|
8221
|
+
{
|
|
8222
|
+
"data-slot": "badge",
|
|
8223
|
+
"data-variant": variant,
|
|
8224
|
+
className: cn(badgeVariants({ variant }), className),
|
|
8225
|
+
...props
|
|
8226
|
+
}
|
|
8227
|
+
);
|
|
8228
|
+
}
|
|
8229
|
+
var INVITE_EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/i;
|
|
8230
|
+
var INVITE_STATUS_CLASS = {
|
|
8231
|
+
pending: "border-amber-500/40 bg-amber-500/15 font-medium text-amber-800 dark:text-amber-300",
|
|
8232
|
+
claimed: "border-emerald-500/40 bg-emerald-500/15 font-medium text-emerald-800 dark:text-emerald-300",
|
|
8233
|
+
failed: "border-destructive/40 bg-destructive/15 font-medium text-destructive",
|
|
8234
|
+
cancelled: "text-muted-foreground"
|
|
8235
|
+
};
|
|
8236
|
+
var INVITE_STATUS_LABELS = {
|
|
8237
|
+
es: {
|
|
8238
|
+
pending: "Pendiente",
|
|
8239
|
+
claimed: "Registrado",
|
|
8240
|
+
failed: "Con error",
|
|
8241
|
+
cancelled: "Cancelada"
|
|
8242
|
+
},
|
|
8243
|
+
en: {
|
|
8244
|
+
pending: "Pending",
|
|
8245
|
+
claimed: "Registered",
|
|
8246
|
+
failed: "Error",
|
|
8247
|
+
cancelled: "Cancelled"
|
|
8248
|
+
}
|
|
8249
|
+
};
|
|
8250
|
+
function inviteStatusLabel(status, language) {
|
|
8251
|
+
const labels = language.startsWith("en") ? INVITE_STATUS_LABELS.en : INVITE_STATUS_LABELS.es;
|
|
8252
|
+
switch (status) {
|
|
8253
|
+
case "pending":
|
|
8254
|
+
case "claimed":
|
|
8255
|
+
case "failed":
|
|
8256
|
+
case "cancelled":
|
|
8257
|
+
return labels[status];
|
|
8258
|
+
default:
|
|
8259
|
+
return status;
|
|
8260
|
+
}
|
|
8261
|
+
}
|
|
8262
|
+
function resendWaitMessage(waitSeconds) {
|
|
8263
|
+
const total = Math.max(0, Math.ceil(waitSeconds));
|
|
8264
|
+
if (total < 60) {
|
|
8265
|
+
const secondLabel2 = total === 1 ? "segundo" : "segundos";
|
|
8266
|
+
return `Espera ${total} ${secondLabel2} antes de reenviar`;
|
|
8267
|
+
}
|
|
8268
|
+
const minutes = Math.floor(total / 60);
|
|
8269
|
+
const seconds = total % 60;
|
|
8270
|
+
const minuteLabel = minutes === 1 ? "minuto" : "minutos";
|
|
8271
|
+
if (seconds === 0)
|
|
8272
|
+
return `Espera ${minutes} ${minuteLabel} antes de reenviar`;
|
|
8273
|
+
const secondLabel = seconds === 1 ? "segundo" : "segundos";
|
|
8274
|
+
return `Espera ${minutes} ${minuteLabel} y ${seconds} ${secondLabel} antes de reenviar`;
|
|
8275
|
+
}
|
|
8276
|
+
function isInviteEmail(value) {
|
|
8277
|
+
const email = value.trim().toLowerCase();
|
|
8278
|
+
return email.length > 0 && email.length <= 320 && INVITE_EMAIL_RE.test(email);
|
|
8279
|
+
}
|
|
8280
|
+
function mergeInviteEmails(current, raw) {
|
|
8281
|
+
const pills = [...current];
|
|
8282
|
+
const seen = new Set(pills);
|
|
8283
|
+
const invalid = [];
|
|
8284
|
+
for (const part of raw.split(/[\n,;]+/)) {
|
|
8285
|
+
const token = part.trim();
|
|
8286
|
+
if (!token) continue;
|
|
8287
|
+
const email = token.toLowerCase();
|
|
8288
|
+
if (!isInviteEmail(email)) {
|
|
8289
|
+
invalid.push(token);
|
|
8290
|
+
continue;
|
|
8291
|
+
}
|
|
8292
|
+
if (seen.has(email)) continue;
|
|
8293
|
+
seen.add(email);
|
|
8294
|
+
pills.push(email);
|
|
8295
|
+
}
|
|
8296
|
+
return { pills, invalid };
|
|
8297
|
+
}
|
|
8298
|
+
async function readJson(res) {
|
|
8299
|
+
return await res.json();
|
|
8300
|
+
}
|
|
8301
|
+
function MembershipInvitePanel({
|
|
8302
|
+
basePath,
|
|
8303
|
+
query,
|
|
8304
|
+
onQueryChange,
|
|
8305
|
+
onNotify,
|
|
8306
|
+
onConfigure
|
|
8307
|
+
}) {
|
|
8308
|
+
const language = useLanguageContext()?.language ?? "es";
|
|
8309
|
+
const [configured, setConfigured] = useState(null);
|
|
8310
|
+
const [types, setTypes] = useState([]);
|
|
8311
|
+
const [tab, setTab] = useState("emails");
|
|
8312
|
+
const [emailPills, setEmailPills] = useState([]);
|
|
8313
|
+
const [emailDraft, setEmailDraft] = useState("");
|
|
8314
|
+
const [csvText, setCsvText] = useState("");
|
|
8315
|
+
const [typeId, setTypeId] = useState("");
|
|
8316
|
+
const [paidUp, setPaidUp] = useState(null);
|
|
8317
|
+
const [unpaidPolicy, setUnpaidPolicy] = useState("lapsed_with_charge");
|
|
8318
|
+
const [graceDays, setGraceDays] = useState("30");
|
|
8319
|
+
const [sendInvites, setSendInvites] = useState(true);
|
|
8320
|
+
const [preview, setPreview] = useState(null);
|
|
8321
|
+
const [busy, setBusy] = useState(false);
|
|
8322
|
+
const [items, setItems] = useState([]);
|
|
8323
|
+
const [nextCursor, setNextCursor] = useState(null);
|
|
8324
|
+
const [listLoading, setListLoading] = useState(true);
|
|
8325
|
+
const [draftQ, setDraftQ] = useState(query.q);
|
|
8326
|
+
const [cancelId, setCancelId] = useState(null);
|
|
8327
|
+
const [refresh, setRefresh] = useState(0);
|
|
8328
|
+
useEffect(() => {
|
|
8329
|
+
let cancelled = false;
|
|
8330
|
+
void (async () => {
|
|
8331
|
+
const res = await fetch(`${basePath}/membership-invites/options`, {
|
|
8332
|
+
credentials: "include"
|
|
8333
|
+
});
|
|
8334
|
+
const body = await readJson(res);
|
|
8335
|
+
if (cancelled) return;
|
|
8336
|
+
const result = body.result;
|
|
8337
|
+
setConfigured(Boolean(result?.configured));
|
|
8338
|
+
const nextTypes = result?.types ?? [];
|
|
8339
|
+
setTypes(nextTypes);
|
|
8340
|
+
setTypeId((current) => current || nextTypes[0]?.id || "");
|
|
8341
|
+
})();
|
|
8342
|
+
return () => {
|
|
8343
|
+
cancelled = true;
|
|
8344
|
+
};
|
|
8345
|
+
}, [basePath]);
|
|
8346
|
+
useEffect(() => {
|
|
8347
|
+
const handle = setTimeout(() => {
|
|
8348
|
+
if (draftQ !== query.q)
|
|
8349
|
+
onQueryChange({ q: draftQ, status: query.status });
|
|
8350
|
+
}, 300);
|
|
8351
|
+
return () => clearTimeout(handle);
|
|
8352
|
+
}, [draftQ, onQueryChange, query.q, query.status]);
|
|
8353
|
+
useEffect(() => {
|
|
8354
|
+
let cancelled = false;
|
|
8355
|
+
setListLoading(true);
|
|
8356
|
+
const params = new URLSearchParams();
|
|
8357
|
+
if (query.q) params.set("q", query.q);
|
|
8358
|
+
if (query.status) params.set("status", query.status);
|
|
8359
|
+
params.set("limit", "20");
|
|
8360
|
+
void (async () => {
|
|
8361
|
+
const res = await fetch(
|
|
8362
|
+
`${basePath}/membership-invites?${params.toString()}`,
|
|
8363
|
+
{ credentials: "include" }
|
|
8364
|
+
);
|
|
8365
|
+
const body = await readJson(res);
|
|
8366
|
+
if (cancelled) return;
|
|
8367
|
+
const result = body.result;
|
|
8368
|
+
setItems(result?.items ?? []);
|
|
8369
|
+
setNextCursor(result?.nextCursor ?? null);
|
|
8370
|
+
setListLoading(false);
|
|
8371
|
+
})();
|
|
8372
|
+
return () => {
|
|
8373
|
+
cancelled = true;
|
|
8374
|
+
};
|
|
8375
|
+
}, [basePath, query.q, query.status, refresh]);
|
|
8376
|
+
if (configured === null)
|
|
8377
|
+
return /* @__PURE__ */ jsx(LoadingState, { label: "Cargando invitaciones\u2026" });
|
|
8378
|
+
if (!configured) {
|
|
8379
|
+
return /* @__PURE__ */ jsx(
|
|
8380
|
+
EmptyState,
|
|
8381
|
+
{
|
|
8382
|
+
title: "Configura la membres\xEDa primero",
|
|
8383
|
+
description: "El colegio necesita un modo de suscripci\xF3n y al menos un tipo activo.",
|
|
8384
|
+
action: onConfigure ? /* @__PURE__ */ jsx(Button, { type: "button", onClick: onConfigure, children: "Ir a configuraci\xF3n" }) : void 0
|
|
8385
|
+
}
|
|
8386
|
+
);
|
|
8387
|
+
}
|
|
8388
|
+
function applyEmailDraft() {
|
|
8389
|
+
const next = mergeInviteEmails(emailPills, emailDraft);
|
|
8390
|
+
setEmailPills(next.pills);
|
|
8391
|
+
setEmailDraft(next.invalid.join("\n"));
|
|
8392
|
+
if (next.invalid.length > 0) onNotify?.("Correo no v\xE1lido", "error");
|
|
8393
|
+
return next;
|
|
8394
|
+
}
|
|
8395
|
+
function emailSourceText() {
|
|
8396
|
+
if (tab !== "emails") return "";
|
|
8397
|
+
const next = applyEmailDraft();
|
|
8398
|
+
return next.invalid.length > 0 ? null : next.pills.join("\n");
|
|
8399
|
+
}
|
|
8400
|
+
const payload = (emailText) => ({
|
|
8401
|
+
source: tab === "emails" ? { kind: "emails", text: emailText } : { kind: "csv", text: csvText },
|
|
8402
|
+
defaults: { defaultTypeId: typeId, defaultPaidUp: paidUp === true },
|
|
8403
|
+
options: {
|
|
8404
|
+
unpaidPolicy,
|
|
8405
|
+
unpaidGraceDays: unpaidPolicy === "active_with_charge" ? Number(graceDays) || 30 : void 0,
|
|
8406
|
+
sendInvites
|
|
8407
|
+
}
|
|
8408
|
+
});
|
|
8409
|
+
async function runPreview() {
|
|
8410
|
+
if (paidUp === null) {
|
|
8411
|
+
onNotify?.("Elige si est\xE1n al corriente", "error");
|
|
8412
|
+
return;
|
|
8413
|
+
}
|
|
8414
|
+
const emailText = emailSourceText();
|
|
8415
|
+
if (emailText === null) return;
|
|
8416
|
+
setBusy(true);
|
|
8417
|
+
try {
|
|
8418
|
+
const res = await fetch(`${basePath}/membership-invites/preview`, {
|
|
8419
|
+
method: "POST",
|
|
8420
|
+
credentials: "include",
|
|
8421
|
+
headers: { "content-type": "application/json" },
|
|
8422
|
+
body: JSON.stringify(payload(emailText))
|
|
8423
|
+
});
|
|
8424
|
+
const body = await readJson(res);
|
|
8425
|
+
if (!res.ok || !body.success) {
|
|
8426
|
+
onNotify?.(body.error ?? "No se pudo revisar", "error");
|
|
8427
|
+
return;
|
|
8428
|
+
}
|
|
8429
|
+
const result = body.result;
|
|
8430
|
+
setPreview(result.rows ?? []);
|
|
8431
|
+
} finally {
|
|
8432
|
+
setBusy(false);
|
|
8433
|
+
}
|
|
8434
|
+
}
|
|
8435
|
+
async function runCommit() {
|
|
8436
|
+
const emailText = emailSourceText();
|
|
8437
|
+
if (emailText === null) return;
|
|
8438
|
+
setBusy(true);
|
|
8439
|
+
try {
|
|
8440
|
+
const res = await fetch(`${basePath}/membership-invites`, {
|
|
8441
|
+
method: "POST",
|
|
8442
|
+
credentials: "include",
|
|
8443
|
+
headers: { "content-type": "application/json" },
|
|
8444
|
+
body: JSON.stringify(payload(emailText))
|
|
8445
|
+
});
|
|
8446
|
+
const body = await readJson(res);
|
|
8447
|
+
if (!res.ok || !body.success) {
|
|
8448
|
+
onNotify?.(body.error ?? "No se pudo guardar", "error");
|
|
8449
|
+
return;
|
|
8450
|
+
}
|
|
8451
|
+
onNotify?.("Invitaciones guardadas", "success");
|
|
8452
|
+
setPreview(null);
|
|
8453
|
+
setEmailPills([]);
|
|
8454
|
+
setEmailDraft("");
|
|
8455
|
+
setCsvText("");
|
|
8456
|
+
setRefresh((value) => value + 1);
|
|
8457
|
+
} finally {
|
|
8458
|
+
setBusy(false);
|
|
8459
|
+
}
|
|
8460
|
+
}
|
|
8461
|
+
async function downloadTemplate() {
|
|
8462
|
+
const res = await fetch(`${basePath}/membership-invites/template`, {
|
|
8463
|
+
credentials: "include"
|
|
8464
|
+
});
|
|
8465
|
+
const blob = await res.blob();
|
|
8466
|
+
const url = URL.createObjectURL(blob);
|
|
8467
|
+
const anchor = document.createElement("a");
|
|
8468
|
+
anchor.href = url;
|
|
8469
|
+
anchor.download = "membership-invites.csv";
|
|
8470
|
+
anchor.click();
|
|
8471
|
+
URL.revokeObjectURL(url);
|
|
8472
|
+
}
|
|
8473
|
+
async function loadMore() {
|
|
8474
|
+
if (!nextCursor) return;
|
|
8475
|
+
const params = new URLSearchParams();
|
|
8476
|
+
if (query.q) params.set("q", query.q);
|
|
8477
|
+
if (query.status) params.set("status", query.status);
|
|
8478
|
+
params.set("limit", "20");
|
|
8479
|
+
params.set("cursor", nextCursor);
|
|
8480
|
+
const res = await fetch(
|
|
8481
|
+
`${basePath}/membership-invites?${params.toString()}`,
|
|
8482
|
+
{ credentials: "include" }
|
|
8483
|
+
);
|
|
8484
|
+
const body = await readJson(res);
|
|
8485
|
+
const result = body.result;
|
|
8486
|
+
setItems((current) => [...current, ...result?.items ?? []]);
|
|
8487
|
+
setNextCursor(result?.nextCursor ?? null);
|
|
8488
|
+
}
|
|
8489
|
+
async function sendOne(id) {
|
|
8490
|
+
const res = await fetch(`${basePath}/membership-invites/${id}/send`, {
|
|
8491
|
+
method: "POST",
|
|
8492
|
+
credentials: "include"
|
|
8493
|
+
});
|
|
8494
|
+
const body = await readJson(res);
|
|
8495
|
+
if (!res.ok) {
|
|
8496
|
+
onNotify?.(
|
|
8497
|
+
body.error === "throttled" ? typeof body.waitSeconds === "number" ? resendWaitMessage(body.waitSeconds) : "Espera unos minutos antes de reenviar" : body.error ?? "No se pudo enviar",
|
|
8498
|
+
"error"
|
|
8499
|
+
);
|
|
8500
|
+
return;
|
|
8501
|
+
}
|
|
8502
|
+
onNotify?.("Invitaci\xF3n enviada", "success");
|
|
8503
|
+
}
|
|
8504
|
+
async function confirmCancel() {
|
|
8505
|
+
if (!cancelId) return;
|
|
8506
|
+
const id = cancelId;
|
|
8507
|
+
setCancelId(null);
|
|
8508
|
+
const res = await fetch(`${basePath}/membership-invites/${id}/cancel`, {
|
|
8509
|
+
method: "POST",
|
|
8510
|
+
credentials: "include"
|
|
8511
|
+
});
|
|
8512
|
+
if (!res.ok) {
|
|
8513
|
+
onNotify?.("No se pudo cancelar", "error");
|
|
8514
|
+
return;
|
|
8515
|
+
}
|
|
8516
|
+
setItems(
|
|
8517
|
+
(current) => current.map(
|
|
8518
|
+
(row) => row.id === id ? { ...row, status: "cancelled" } : row
|
|
8519
|
+
)
|
|
8520
|
+
);
|
|
8521
|
+
onNotify?.("Invitaci\xF3n cancelada", "success");
|
|
8522
|
+
}
|
|
8523
|
+
const invalidPreview = preview?.some((row) => row.outcome === "invalid");
|
|
8524
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-8", children: [
|
|
8525
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
8526
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", role: "tablist", children: [
|
|
8527
|
+
/* @__PURE__ */ jsx(
|
|
8528
|
+
Button,
|
|
8529
|
+
{
|
|
8530
|
+
type: "button",
|
|
8531
|
+
variant: tab === "emails" ? "default" : "outline",
|
|
8532
|
+
onClick: () => setTab("emails"),
|
|
8533
|
+
children: "Correos"
|
|
8534
|
+
}
|
|
8535
|
+
),
|
|
8536
|
+
/* @__PURE__ */ jsx(
|
|
8537
|
+
Button,
|
|
8538
|
+
{
|
|
8539
|
+
type: "button",
|
|
8540
|
+
variant: tab === "csv" ? "default" : "outline",
|
|
8541
|
+
onClick: () => setTab("csv"),
|
|
8542
|
+
children: "CSV"
|
|
8543
|
+
}
|
|
8544
|
+
)
|
|
8545
|
+
] }),
|
|
8546
|
+
tab === "emails" ? /* @__PURE__ */ jsxs("div", { className: "border-input bg-background focus-within:border-ring focus-within:ring-ring/50 flex min-h-28 w-full flex-wrap items-center gap-1.5 rounded-md border px-2 py-2 focus-within:ring-[3px]", children: [
|
|
8547
|
+
emailPills.map((email) => /* @__PURE__ */ jsxs(Badge, { variant: "secondary", children: [
|
|
8548
|
+
email,
|
|
8549
|
+
/* @__PURE__ */ jsx(
|
|
8550
|
+
Button,
|
|
8551
|
+
{
|
|
8552
|
+
type: "button",
|
|
8553
|
+
variant: "ghost",
|
|
8554
|
+
size: "icon-sm",
|
|
8555
|
+
className: "size-4",
|
|
8556
|
+
"aria-label": `Quitar ${email}`,
|
|
8557
|
+
onClick: () => setEmailPills(
|
|
8558
|
+
(current) => current.filter((item) => item !== email)
|
|
8559
|
+
),
|
|
8560
|
+
children: /* @__PURE__ */ jsx(X, {})
|
|
8561
|
+
}
|
|
8562
|
+
)
|
|
8563
|
+
] }, email)),
|
|
8564
|
+
/* @__PURE__ */ jsx(
|
|
8565
|
+
Input,
|
|
8566
|
+
{
|
|
8567
|
+
"aria-label": "Correos",
|
|
8568
|
+
className: "h-8 min-w-40 flex-1 border-0 bg-transparent px-1 shadow-none focus-visible:border-transparent focus-visible:ring-0 dark:bg-transparent",
|
|
8569
|
+
placeholder: emailPills.length === 0 ? "Escribe un correo y pulsa Enter" : "",
|
|
8570
|
+
value: emailDraft,
|
|
8571
|
+
onChange: (event) => setEmailDraft(event.target.value),
|
|
8572
|
+
onKeyDown: (event) => {
|
|
8573
|
+
if (event.key === "Enter" || event.key === ",") {
|
|
8574
|
+
event.preventDefault();
|
|
8575
|
+
applyEmailDraft();
|
|
8576
|
+
return;
|
|
8577
|
+
}
|
|
8578
|
+
if (event.key === "Backspace" && emailDraft.length === 0 && emailPills.length > 0) {
|
|
8579
|
+
event.preventDefault();
|
|
8580
|
+
setEmailPills((current) => current.slice(0, -1));
|
|
8581
|
+
}
|
|
8582
|
+
},
|
|
8583
|
+
onPaste: (event) => {
|
|
8584
|
+
const text = event.clipboardData.getData("text");
|
|
8585
|
+
if (!/[\n,;]/.test(text) && !isInviteEmail(text)) return;
|
|
8586
|
+
event.preventDefault();
|
|
8587
|
+
const next = mergeInviteEmails(
|
|
8588
|
+
emailPills,
|
|
8589
|
+
`${emailDraft}${text}`
|
|
8590
|
+
);
|
|
8591
|
+
setEmailPills(next.pills);
|
|
8592
|
+
setEmailDraft(next.invalid.join("\n"));
|
|
8593
|
+
if (next.invalid.length > 0)
|
|
8594
|
+
onNotify?.("Correo no v\xE1lido", "error");
|
|
8595
|
+
}
|
|
8596
|
+
}
|
|
8597
|
+
)
|
|
8598
|
+
] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
8599
|
+
/* @__PURE__ */ jsx(
|
|
8600
|
+
Button,
|
|
8601
|
+
{
|
|
8602
|
+
type: "button",
|
|
8603
|
+
variant: "outline",
|
|
8604
|
+
onClick: () => void downloadTemplate(),
|
|
8605
|
+
children: "Descargar plantilla"
|
|
8606
|
+
}
|
|
8607
|
+
),
|
|
8608
|
+
/* @__PURE__ */ jsx(
|
|
8609
|
+
Input,
|
|
8610
|
+
{
|
|
8611
|
+
"aria-label": "Archivo CSV",
|
|
8612
|
+
type: "file",
|
|
8613
|
+
accept: ".csv,text/csv",
|
|
8614
|
+
onChange: (event) => {
|
|
8615
|
+
const file = event.target.files?.[0];
|
|
8616
|
+
if (!file) return;
|
|
8617
|
+
void file.text().then(setCsvText);
|
|
8618
|
+
}
|
|
8619
|
+
}
|
|
8620
|
+
)
|
|
8621
|
+
] }),
|
|
8622
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1 text-sm", children: [
|
|
8623
|
+
/* @__PURE__ */ jsx("span", { children: "Tipo de membres\xEDa" }),
|
|
8624
|
+
/* @__PURE__ */ jsx(
|
|
8625
|
+
"select",
|
|
8626
|
+
{
|
|
8627
|
+
"aria-label": "Tipo de membres\xEDa",
|
|
8628
|
+
className: "border-input bg-background h-9 w-full rounded-md border px-2",
|
|
8629
|
+
value: typeId,
|
|
8630
|
+
onChange: (event) => setTypeId(event.target.value),
|
|
8631
|
+
children: types.map((type) => /* @__PURE__ */ jsx("option", { value: type.id, children: type.name }, type.id))
|
|
8632
|
+
}
|
|
8633
|
+
)
|
|
8634
|
+
] }),
|
|
8635
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1 text-sm", children: [
|
|
8636
|
+
/* @__PURE__ */ jsx("span", { children: "\xBFAl corriente?" }),
|
|
8637
|
+
/* @__PURE__ */ jsxs(
|
|
8638
|
+
"select",
|
|
8639
|
+
{
|
|
8640
|
+
"aria-label": "Al corriente",
|
|
8641
|
+
className: "border-input bg-background h-9 w-full rounded-md border px-2",
|
|
8642
|
+
value: paidUp === null ? "" : paidUp ? "yes" : "no",
|
|
8643
|
+
onChange: (event) => {
|
|
8644
|
+
if (event.target.value === "yes") setPaidUp(true);
|
|
8645
|
+
else if (event.target.value === "no") setPaidUp(false);
|
|
8646
|
+
else setPaidUp(null);
|
|
8647
|
+
},
|
|
8648
|
+
children: [
|
|
8649
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Elige una opci\xF3n" }),
|
|
8650
|
+
/* @__PURE__ */ jsx("option", { value: "yes", children: "S\xED, al corriente" }),
|
|
8651
|
+
/* @__PURE__ */ jsx("option", { value: "no", children: "No" })
|
|
8652
|
+
]
|
|
8653
|
+
}
|
|
8654
|
+
)
|
|
8655
|
+
] }),
|
|
8656
|
+
/* @__PURE__ */ jsxs("label", { className: "block space-y-1 text-sm", children: [
|
|
8657
|
+
/* @__PURE__ */ jsx("span", { children: "Si no est\xE1n al corriente" }),
|
|
8658
|
+
/* @__PURE__ */ jsxs(
|
|
8659
|
+
"select",
|
|
8660
|
+
{
|
|
8661
|
+
"aria-label": "Pol\xEDtica de adeudo",
|
|
8662
|
+
className: "border-input bg-background h-9 w-full rounded-md border px-2",
|
|
8663
|
+
value: unpaidPolicy,
|
|
8664
|
+
onChange: (event) => setUnpaidPolicy(event.target.value),
|
|
8665
|
+
children: [
|
|
8666
|
+
/* @__PURE__ */ jsx("option", { value: "lapsed_with_charge", children: "Socio reconocido, sin acceso hasta que pague" }),
|
|
8667
|
+
/* @__PURE__ */ jsx("option", { value: "active_with_charge", children: "Con acceso por unos d\xEDas y un cargo abierto" }),
|
|
8668
|
+
/* @__PURE__ */ jsx("option", { value: "active_no_charge", children: "Activo sin cargo (no se registra el adeudo)" })
|
|
8669
|
+
]
|
|
8670
|
+
}
|
|
8671
|
+
)
|
|
8672
|
+
] }),
|
|
8673
|
+
unpaidPolicy === "active_with_charge" ? /* @__PURE__ */ jsxs("label", { className: "block space-y-1 text-sm", children: [
|
|
8674
|
+
/* @__PURE__ */ jsx("span", { children: "D\xEDas de acceso antes de vencer" }),
|
|
8675
|
+
/* @__PURE__ */ jsx(
|
|
8676
|
+
Input,
|
|
8677
|
+
{
|
|
8678
|
+
"aria-label": "D\xEDas de gracia",
|
|
8679
|
+
inputMode: "numeric",
|
|
8680
|
+
value: graceDays,
|
|
8681
|
+
onChange: (event) => setGraceDays(event.target.value)
|
|
8682
|
+
}
|
|
8683
|
+
)
|
|
8684
|
+
] }) : null,
|
|
8685
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-2 text-sm", children: [
|
|
8686
|
+
/* @__PURE__ */ jsx(
|
|
8687
|
+
"input",
|
|
8688
|
+
{
|
|
8689
|
+
type: "checkbox",
|
|
8690
|
+
checked: sendInvites,
|
|
8691
|
+
onChange: (event) => setSendInvites(event.target.checked)
|
|
8692
|
+
}
|
|
8693
|
+
),
|
|
8694
|
+
"Enviar invitaciones al guardar"
|
|
8695
|
+
] }),
|
|
8696
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
8697
|
+
/* @__PURE__ */ jsx(
|
|
8698
|
+
Button,
|
|
8699
|
+
{
|
|
8700
|
+
type: "button",
|
|
8701
|
+
variant: "outline",
|
|
8702
|
+
disabled: busy,
|
|
8703
|
+
onClick: () => void runPreview(),
|
|
8704
|
+
children: "Revisar"
|
|
8705
|
+
}
|
|
8706
|
+
),
|
|
8707
|
+
/* @__PURE__ */ jsx(
|
|
8708
|
+
Button,
|
|
8709
|
+
{
|
|
8710
|
+
type: "button",
|
|
8711
|
+
disabled: busy || !preview || invalidPreview,
|
|
8712
|
+
onClick: () => void runCommit(),
|
|
8713
|
+
children: "Guardar"
|
|
8714
|
+
}
|
|
8715
|
+
)
|
|
8716
|
+
] }),
|
|
8717
|
+
preview ? /* @__PURE__ */ jsxs("table", { className: "w-full text-sm", children: [
|
|
8718
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
|
|
8719
|
+
/* @__PURE__ */ jsx("th", { className: "text-left", children: "Correo" }),
|
|
8720
|
+
/* @__PURE__ */ jsx("th", { className: "text-left", children: "Resultado" })
|
|
8721
|
+
] }) }),
|
|
8722
|
+
/* @__PURE__ */ jsx("tbody", { children: preview.map((row) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
8723
|
+
/* @__PURE__ */ jsx("td", { children: row.email }),
|
|
8724
|
+
/* @__PURE__ */ jsxs("td", { children: [
|
|
8725
|
+
row.outcome,
|
|
8726
|
+
row.errors.length > 0 ? ` (${row.errors.join(", ")})` : ""
|
|
8727
|
+
] })
|
|
8728
|
+
] }, `${row.line}-${row.email}`)) })
|
|
8729
|
+
] }) : null
|
|
8730
|
+
] }),
|
|
8731
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
8732
|
+
/* @__PURE__ */ jsx("h2", { className: "text-lg font-medium", children: "Invitaciones" }),
|
|
8733
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
8734
|
+
/* @__PURE__ */ jsx(
|
|
8735
|
+
Input,
|
|
8736
|
+
{
|
|
8737
|
+
"aria-label": "Buscar invitaciones",
|
|
8738
|
+
className: "min-w-0 flex-1",
|
|
8739
|
+
value: draftQ,
|
|
8740
|
+
onChange: (event) => setDraftQ(event.target.value),
|
|
8741
|
+
placeholder: "Correo o nombre"
|
|
8742
|
+
}
|
|
8743
|
+
),
|
|
8744
|
+
/* @__PURE__ */ jsxs(
|
|
8745
|
+
"select",
|
|
8746
|
+
{
|
|
8747
|
+
"aria-label": "Estado",
|
|
8748
|
+
className: "border-input bg-background h-9 shrink-0 rounded-md border px-2",
|
|
8749
|
+
value: query.status,
|
|
8750
|
+
onChange: (event) => onQueryChange({ q: query.q, status: event.target.value }),
|
|
8751
|
+
children: [
|
|
8752
|
+
/* @__PURE__ */ jsx("option", { value: "", children: "Todos" }),
|
|
8753
|
+
/* @__PURE__ */ jsx("option", { value: "pending", children: "Pendientes" }),
|
|
8754
|
+
/* @__PURE__ */ jsx("option", { value: "claimed", children: "Registrados" }),
|
|
8755
|
+
/* @__PURE__ */ jsx("option", { value: "failed", children: "Con error" }),
|
|
8756
|
+
/* @__PURE__ */ jsx("option", { value: "cancelled", children: "Canceladas" })
|
|
8757
|
+
]
|
|
8758
|
+
}
|
|
8759
|
+
)
|
|
8760
|
+
] }),
|
|
8761
|
+
listLoading ? /* @__PURE__ */ jsx(LoadingState, { label: "Cargando lista\u2026" }) : null,
|
|
8762
|
+
!listLoading && items.length === 0 ? /* @__PURE__ */ jsx(
|
|
8763
|
+
EmptyState,
|
|
8764
|
+
{
|
|
8765
|
+
title: "No hay invitaciones",
|
|
8766
|
+
description: "Agrega correos o un CSV."
|
|
8767
|
+
}
|
|
8768
|
+
) : null,
|
|
8769
|
+
/* @__PURE__ */ jsx("ul", { className: "divide-y", children: items.map((row) => /* @__PURE__ */ jsxs(
|
|
8770
|
+
"li",
|
|
8771
|
+
{
|
|
8772
|
+
className: "flex flex-col gap-2 py-3 sm:flex-row sm:items-center sm:justify-between",
|
|
8773
|
+
children: [
|
|
8774
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
8775
|
+
/* @__PURE__ */ jsx("p", { className: "break-all", children: row.email }),
|
|
8776
|
+
/* @__PURE__ */ jsxs("p", { className: "text-muted-foreground mt-1 flex flex-wrap items-center gap-x-1.5 gap-y-1 text-xs", children: [
|
|
8777
|
+
row.fullName ? /* @__PURE__ */ jsx("span", { children: row.fullName }) : null,
|
|
8778
|
+
/* @__PURE__ */ jsx(
|
|
8779
|
+
Badge,
|
|
8780
|
+
{
|
|
8781
|
+
variant: "outline",
|
|
8782
|
+
className: INVITE_STATUS_CLASS[row.status],
|
|
8783
|
+
children: inviteStatusLabel(row.status, language)
|
|
8784
|
+
}
|
|
8785
|
+
),
|
|
8786
|
+
row.failureReason ? /* @__PURE__ */ jsx("span", { children: row.failureReason }) : null
|
|
8787
|
+
] })
|
|
8788
|
+
] }),
|
|
8789
|
+
row.status === "pending" ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
8790
|
+
/* @__PURE__ */ jsx(
|
|
8791
|
+
Button,
|
|
8792
|
+
{
|
|
8793
|
+
type: "button",
|
|
8794
|
+
variant: "outline",
|
|
8795
|
+
onClick: () => void sendOne(row.id),
|
|
8796
|
+
children: "Enviar invitaci\xF3n"
|
|
8797
|
+
}
|
|
8798
|
+
),
|
|
8799
|
+
/* @__PURE__ */ jsx(
|
|
8800
|
+
Button,
|
|
8801
|
+
{
|
|
8802
|
+
type: "button",
|
|
8803
|
+
variant: "ghost",
|
|
8804
|
+
onClick: () => setCancelId(row.id),
|
|
8805
|
+
children: "Cancelar"
|
|
8806
|
+
}
|
|
8807
|
+
)
|
|
8808
|
+
] }) : null
|
|
8809
|
+
]
|
|
8810
|
+
},
|
|
8811
|
+
row.id
|
|
8812
|
+
)) }),
|
|
8813
|
+
nextCursor ? /* @__PURE__ */ jsx(
|
|
8814
|
+
Button,
|
|
8815
|
+
{
|
|
8816
|
+
type: "button",
|
|
8817
|
+
variant: "outline",
|
|
8818
|
+
onClick: () => void loadMore(),
|
|
8819
|
+
children: "Cargar m\xE1s"
|
|
8820
|
+
}
|
|
8821
|
+
) : null
|
|
8822
|
+
] }),
|
|
8823
|
+
/* @__PURE__ */ jsx(
|
|
8824
|
+
ConfirmDestructiveDialog,
|
|
8825
|
+
{
|
|
8826
|
+
open: cancelId !== null,
|
|
8827
|
+
onOpenChange: (open) => {
|
|
8828
|
+
if (!open) setCancelId(null);
|
|
8829
|
+
},
|
|
8830
|
+
title: "Cancelar invitaci\xF3n",
|
|
8831
|
+
description: "Esta persona ya no quedar\xE1 registrada como socia al crear su cuenta.",
|
|
8832
|
+
confirmLabel: "Cancelar invitaci\xF3n",
|
|
8833
|
+
cancelLabel: "Volver",
|
|
8834
|
+
onConfirm: () => void confirmCancel()
|
|
8835
|
+
}
|
|
8836
|
+
)
|
|
8837
|
+
] });
|
|
8838
|
+
}
|
|
8085
8839
|
|
|
8086
|
-
export { AvatarEditor, AvatarEditorDialog, BrandX, Bubble, BubbleContent, BubbleGroup, BubbleReactions, ChatMessageList, ConfirmDestructiveDialog, DEFAULT_EDITABLE_SECTION_LABELS, DataList, DataListItem, DropdownMenuItem, DropdownMenuSeparator, EditableSection, EmojiInput, EmojiPicker, EmojiPickerPopover, EmojiTextarea, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, ErrorState, ExpandableText, FieldMessage, ImageLightbox, LanguageContext, LanguageSwitcher, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, MediaCarousel, MediaViewerDialog, Message, MessageAvatar, MessageComposer, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, OrgSwitcher, PLATFORM_ACCOUNT_ORG_COLLAPSE_AT, PaymentIcon, PhoneInput, PlatformAccountMenu, PlatformNavbar, SafeImage, ScrollRestorationProvider, SearchCommand, SearchablePicker, SupportMessengerProvider, ThemeSwitcher, VerifiedProfessionalBadge, ZOOM_PAN_MAX_SCALE, ZOOM_PAN_MIN_SCALE, ZOOM_PAN_SWIPE_COMMIT_PX, ZOOM_PAN_SWIPE_SNAP_MS, avatarFallbackStyle, bubbleVariants, cn, createSupportChatClient, defaultLanguages, formatPaymentCardBrand, fuzzyMatch, getAvatarColors, getInitials, insertAtCaret, markerVariants, mergePlatformAccountOrgs, normalizeEmojiQuery, normalizePaymentCardBrand, paymentIconBrandFromStripe, paymentTypeFromStripeBrand, prefersReducedMotion, useDebouncedValue, useDebouncedValueStrict, useEditableSection, useLanguageContext, useMediaQuery2 as useMediaQuery, useRealtimeChannel, useRestorableState, useScrollFadeXEdges, useScrollRestorationContext, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional, useZoomPanGestures, zoomToward };
|
|
8840
|
+
export { AvatarEditor, AvatarEditorDialog, BrandX, Bubble, BubbleContent, BubbleGroup, BubbleReactions, ChatMessageList, ConfirmDestructiveDialog, DEFAULT_EDITABLE_SECTION_LABELS, DataList, DataListItem, DropdownMenuItem, DropdownMenuSeparator, EditableSection, EmojiInput, EmojiPicker, EmojiPickerPopover, EmojiTextarea, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, ErrorState, ExpandableText, FieldMessage, ImageLightbox, LanguageContext, LanguageSwitcher, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, MediaCarousel, MediaViewerDialog, MembershipInvitePanel, Message, MessageAvatar, MessageComposer, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, OrgSwitcher, PLATFORM_ACCOUNT_ORG_COLLAPSE_AT, PaymentIcon, PhoneInput, PlatformAccountMenu, PlatformNavbar, SafeImage, ScrollRestorationProvider, SearchCommand, SearchablePicker, SupportMessengerProvider, ThemeSwitcher, VerifiedProfessionalBadge, ZOOM_PAN_MAX_SCALE, ZOOM_PAN_MIN_SCALE, ZOOM_PAN_SWIPE_COMMIT_PX, ZOOM_PAN_SWIPE_SNAP_MS, avatarFallbackStyle, bubbleVariants, cn, createSupportChatClient, defaultLanguages, formatPaymentCardBrand, fuzzyMatch, getAvatarColors, getInitials, insertAtCaret, markerVariants, mergePlatformAccountOrgs, normalizeEmojiQuery, normalizePaymentCardBrand, paymentIconBrandFromStripe, paymentTypeFromStripeBrand, prefersReducedMotion, useDebouncedValue, useDebouncedValueStrict, useEditableSection, useLanguageContext, useMediaQuery2 as useMediaQuery, useRealtimeChannel, useRegisterScrollContainer, useRestorableState, useScrollFadeXEdges, useScrollRestorationContext, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional, useZoomPanGestures, zoomToward };
|
|
8087
8841
|
//# sourceMappingURL=index.js.map
|
|
8088
8842
|
//# sourceMappingURL=index.js.map
|