@universe-platform/ui 0.1.0-beta.22 → 0.1.0-beta.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/globals.css +3 -0
- package/dist/index.d.mts +12 -4
- package/dist/index.d.ts +12 -4
- package/dist/index.js +195 -67
- package/dist/index.mjs +206 -75
- package/dist/phone.d.mts +8 -4
- package/dist/phone.d.ts +8 -4
- package/dist/phone.js +7 -1
- package/dist/phone.mjs +7 -1
- package/package.json +1 -1
package/dist/globals.css
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -53,10 +53,14 @@ declare function isValidPhoneNumber(phone: string): boolean;
|
|
|
53
53
|
*/
|
|
54
54
|
declare function generateWhatsAppLink(phone: string, defaultCountryCode?: string): string | null;
|
|
55
55
|
/**
|
|
56
|
-
* Normalizes a phone number for WhatsApp sending (
|
|
57
|
-
* -
|
|
58
|
-
* -
|
|
59
|
-
* -
|
|
56
|
+
* Normalizes a phone number for WhatsApp sending (Meta international format without leading '+').
|
|
57
|
+
* - Returns empty string if input is falsy.
|
|
58
|
+
* - Trims input and removes leading '+' if it exists.
|
|
59
|
+
* - Strips all non-digit characters.
|
|
60
|
+
* - If starting with '972', returns it as is.
|
|
61
|
+
* - If starting with '0' (Israeli mobile/landline), strips '0' and prepends '972'.
|
|
62
|
+
* - If exactly 9 digits long (omitted leading zero), prepends '972'.
|
|
63
|
+
* - Returns the processed digits string.
|
|
60
64
|
*/
|
|
61
65
|
declare function normalizePhoneForWhatsApp(phone: string): string;
|
|
62
66
|
|
|
@@ -547,6 +551,8 @@ declare function useWhatsAppState(props: WhatsAppComponentProps): {
|
|
|
547
551
|
isTestDisabled: boolean;
|
|
548
552
|
sendButtonTitle: string;
|
|
549
553
|
testButtonTitle: string;
|
|
554
|
+
requiresMediaHeader: boolean;
|
|
555
|
+
isMediaMissing: boolean;
|
|
550
556
|
templates: MetaWhatsAppTemplate[];
|
|
551
557
|
selectedTemplateId: string | null;
|
|
552
558
|
setSelectedTemplateId: react.Dispatch<react.SetStateAction<string | null>>;
|
|
@@ -556,6 +562,8 @@ declare function useWhatsAppState(props: WhatsAppComponentProps): {
|
|
|
556
562
|
headerMediaUrl: string;
|
|
557
563
|
handleHeaderMediaUrlChange: (newUrl: string) => void;
|
|
558
564
|
handleResetHeaderMediaUrl: () => void;
|
|
565
|
+
isUploadingMedia: boolean;
|
|
566
|
+
handleFileUpload: (file: File, templateName?: string) => Promise<void>;
|
|
559
567
|
templateVariables: string[];
|
|
560
568
|
variableMapping: TemplateVariableMapping;
|
|
561
569
|
textableColumnOptions: TextableColumnOption[];
|
package/dist/index.d.ts
CHANGED
|
@@ -53,10 +53,14 @@ declare function isValidPhoneNumber(phone: string): boolean;
|
|
|
53
53
|
*/
|
|
54
54
|
declare function generateWhatsAppLink(phone: string, defaultCountryCode?: string): string | null;
|
|
55
55
|
/**
|
|
56
|
-
* Normalizes a phone number for WhatsApp sending (
|
|
57
|
-
* -
|
|
58
|
-
* -
|
|
59
|
-
* -
|
|
56
|
+
* Normalizes a phone number for WhatsApp sending (Meta international format without leading '+').
|
|
57
|
+
* - Returns empty string if input is falsy.
|
|
58
|
+
* - Trims input and removes leading '+' if it exists.
|
|
59
|
+
* - Strips all non-digit characters.
|
|
60
|
+
* - If starting with '972', returns it as is.
|
|
61
|
+
* - If starting with '0' (Israeli mobile/landline), strips '0' and prepends '972'.
|
|
62
|
+
* - If exactly 9 digits long (omitted leading zero), prepends '972'.
|
|
63
|
+
* - Returns the processed digits string.
|
|
60
64
|
*/
|
|
61
65
|
declare function normalizePhoneForWhatsApp(phone: string): string;
|
|
62
66
|
|
|
@@ -547,6 +551,8 @@ declare function useWhatsAppState(props: WhatsAppComponentProps): {
|
|
|
547
551
|
isTestDisabled: boolean;
|
|
548
552
|
sendButtonTitle: string;
|
|
549
553
|
testButtonTitle: string;
|
|
554
|
+
requiresMediaHeader: boolean;
|
|
555
|
+
isMediaMissing: boolean;
|
|
550
556
|
templates: MetaWhatsAppTemplate[];
|
|
551
557
|
selectedTemplateId: string | null;
|
|
552
558
|
setSelectedTemplateId: react.Dispatch<react.SetStateAction<string | null>>;
|
|
@@ -556,6 +562,8 @@ declare function useWhatsAppState(props: WhatsAppComponentProps): {
|
|
|
556
562
|
headerMediaUrl: string;
|
|
557
563
|
handleHeaderMediaUrlChange: (newUrl: string) => void;
|
|
558
564
|
handleResetHeaderMediaUrl: () => void;
|
|
565
|
+
isUploadingMedia: boolean;
|
|
566
|
+
handleFileUpload: (file: File, templateName?: string) => Promise<void>;
|
|
559
567
|
templateVariables: string[];
|
|
560
568
|
variableMapping: TemplateVariableMapping;
|
|
561
569
|
textableColumnOptions: TextableColumnOption[];
|
package/dist/index.js
CHANGED
|
@@ -202,9 +202,15 @@ function normalizePhoneForWhatsApp(phone) {
|
|
|
202
202
|
cleaned = cleaned.substring(1);
|
|
203
203
|
}
|
|
204
204
|
const digitsOnly = cleaned.replace(/\D/g, "");
|
|
205
|
-
if (digitsOnly.startsWith("
|
|
205
|
+
if (digitsOnly.startsWith("972")) {
|
|
206
|
+
return digitsOnly;
|
|
207
|
+
}
|
|
208
|
+
if (digitsOnly.startsWith("0")) {
|
|
206
209
|
return `972${digitsOnly.substring(1)}`;
|
|
207
210
|
}
|
|
211
|
+
if (digitsOnly.length === 9) {
|
|
212
|
+
return `972${digitsOnly}`;
|
|
213
|
+
}
|
|
208
214
|
return digitsOnly;
|
|
209
215
|
}
|
|
210
216
|
|
|
@@ -9727,9 +9733,12 @@ function buildTemplateComponents(params) {
|
|
|
9727
9733
|
const format = (headerComp.format || "TEXT").toUpperCase();
|
|
9728
9734
|
if (format === "IMAGE" || format === "DOCUMENT" || format === "VIDEO") {
|
|
9729
9735
|
const validMediaUrl = resolveHeaderMediaUrl(headerComp, mediaUrl, selectedTemplate.name);
|
|
9736
|
+
console.log(
|
|
9737
|
+
`[MEDIA_DEBUG] template: ${selectedTemplate.name}, format: ${format}, resolvedUrl: ${validMediaUrl}`
|
|
9738
|
+
);
|
|
9730
9739
|
if (validMediaUrl) {
|
|
9731
9740
|
if (format === "DOCUMENT") {
|
|
9732
|
-
const docFilename = resolveDocumentFilename(headerComp, validMediaUrl);
|
|
9741
|
+
const docFilename = resolveDocumentFilename(headerComp, validMediaUrl) || "document.pdf";
|
|
9733
9742
|
components.push({
|
|
9734
9743
|
type: "header",
|
|
9735
9744
|
parameters: [
|
|
@@ -9898,11 +9907,6 @@ function findColumnDef(colOption, tableColumns) {
|
|
|
9898
9907
|
}
|
|
9899
9908
|
return null;
|
|
9900
9909
|
}
|
|
9901
|
-
var DEFAULT_FALLBACK_MEDIA_URLS = {
|
|
9902
|
-
image: "https://images.unsplash.com/photo-1579202673506-ca3ce28943ef?q=80&w=800&fm=jpg&fit=crop",
|
|
9903
|
-
document: "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
|
|
9904
|
-
video: "https://www.w3schools.com/html/mov_bbb.mp4"
|
|
9905
|
-
};
|
|
9906
9910
|
function resolveDocumentFilename(headerComp, mediaUrl) {
|
|
9907
9911
|
var _a, _b, _c;
|
|
9908
9912
|
if ((_a = headerComp == null ? void 0 : headerComp.document) == null ? void 0 : _a.filename) {
|
|
@@ -9916,8 +9920,11 @@ function resolveDocumentFilename(headerComp, mediaUrl) {
|
|
|
9916
9920
|
const urlObj = new URL(mediaUrl);
|
|
9917
9921
|
const pathname = urlObj.pathname;
|
|
9918
9922
|
const lastSegment = pathname.substring(pathname.lastIndexOf("/") + 1);
|
|
9919
|
-
if (lastSegment
|
|
9920
|
-
|
|
9923
|
+
if (lastSegment) {
|
|
9924
|
+
const decoded = decodeURIComponent(lastSegment).trim();
|
|
9925
|
+
if (decoded) {
|
|
9926
|
+
return decoded.includes(".") ? decoded : `${decoded}.pdf`;
|
|
9927
|
+
}
|
|
9921
9928
|
}
|
|
9922
9929
|
} catch (e) {
|
|
9923
9930
|
}
|
|
@@ -9925,61 +9932,73 @@ function resolveDocumentFilename(headerComp, mediaUrl) {
|
|
|
9925
9932
|
return "document.pdf";
|
|
9926
9933
|
}
|
|
9927
9934
|
function resolveHeaderMediaUrl(headerComp, customMediaUrl, templateName) {
|
|
9928
|
-
|
|
9929
|
-
const isImageFormat =
|
|
9935
|
+
const format = ((headerComp == null ? void 0 : headerComp.format) || "").toUpperCase();
|
|
9936
|
+
const isImageFormat = format === "IMAGE";
|
|
9930
9937
|
const sanitizeCandidate = (rawUrl) => {
|
|
9938
|
+
if (!rawUrl || typeof rawUrl !== "string") {
|
|
9939
|
+
return null;
|
|
9940
|
+
}
|
|
9931
9941
|
let trimmed = rawUrl.trim();
|
|
9942
|
+
if (trimmed.startsWith("4:")) {
|
|
9943
|
+
return null;
|
|
9944
|
+
}
|
|
9932
9945
|
if (!trimmed.startsWith("http://") && !trimmed.startsWith("https://")) {
|
|
9933
9946
|
return null;
|
|
9934
9947
|
}
|
|
9948
|
+
const lower = trimmed.toLowerCase();
|
|
9949
|
+
if (lower.includes("scontent.whatsapp.net") || lower.includes("lookaside.fbsbx.com")) {
|
|
9950
|
+
return null;
|
|
9951
|
+
}
|
|
9935
9952
|
if (isImageFormat) {
|
|
9936
|
-
if (
|
|
9937
|
-
trimmed = trimmed.replace(
|
|
9953
|
+
if (lower.includes("unsplash.com") && lower.includes("auto=format")) {
|
|
9954
|
+
trimmed = trimmed.replace(/auto=format/gi, "fm=jpg");
|
|
9938
9955
|
}
|
|
9939
|
-
if (
|
|
9956
|
+
if (lower.includes(".webp")) {
|
|
9940
9957
|
return null;
|
|
9941
9958
|
}
|
|
9942
9959
|
}
|
|
9943
9960
|
return trimmed;
|
|
9944
9961
|
};
|
|
9945
|
-
|
|
9946
|
-
|
|
9947
|
-
if (
|
|
9948
|
-
|
|
9949
|
-
|
|
9950
|
-
|
|
9951
|
-
|
|
9952
|
-
|
|
9953
|
-
|
|
9954
|
-
|
|
9955
|
-
|
|
9956
|
-
|
|
9957
|
-
|
|
9958
|
-
|
|
9959
|
-
for (const candidate of candidates) {
|
|
9960
|
-
if (typeof candidate === "string") {
|
|
9961
|
-
const sanitized = sanitizeCandidate(candidate);
|
|
9962
|
-
if (sanitized) return sanitized;
|
|
9962
|
+
const computeUrl = () => {
|
|
9963
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
9964
|
+
if (customMediaUrl && typeof customMediaUrl === "string") {
|
|
9965
|
+
const sanitized = sanitizeCandidate(customMediaUrl);
|
|
9966
|
+
if (sanitized) return sanitized;
|
|
9967
|
+
}
|
|
9968
|
+
if (templateName && typeof window !== "undefined") {
|
|
9969
|
+
try {
|
|
9970
|
+
const persisted = localStorage.getItem(`whatsapp_template_media_${templateName}`) || localStorage.getItem(`whatsapp_template_media_${templateName.toLowerCase()}`);
|
|
9971
|
+
if (persisted && typeof persisted === "string") {
|
|
9972
|
+
const sanitized = sanitizeCandidate(persisted);
|
|
9973
|
+
if (sanitized) return sanitized;
|
|
9974
|
+
}
|
|
9975
|
+
} catch (e) {
|
|
9963
9976
|
}
|
|
9964
9977
|
}
|
|
9965
|
-
|
|
9966
|
-
|
|
9967
|
-
|
|
9968
|
-
|
|
9969
|
-
|
|
9970
|
-
|
|
9971
|
-
|
|
9978
|
+
if (headerComp) {
|
|
9979
|
+
const candidates = [
|
|
9980
|
+
headerComp.url,
|
|
9981
|
+
headerComp.link,
|
|
9982
|
+
(_a = headerComp.image) == null ? void 0 : _a.link,
|
|
9983
|
+
(_b = headerComp.document) == null ? void 0 : _b.link,
|
|
9984
|
+
(_c = headerComp.video) == null ? void 0 : _c.link,
|
|
9985
|
+
(_e = (_d = headerComp.example) == null ? void 0 : _d.header_url) == null ? void 0 : _e[0],
|
|
9986
|
+
(_g = (_f = headerComp.example) == null ? void 0 : _f.header_handle) == null ? void 0 : _g[0]
|
|
9987
|
+
];
|
|
9988
|
+
for (const candidate of candidates) {
|
|
9989
|
+
if (typeof candidate === "string") {
|
|
9990
|
+
const sanitized = sanitizeCandidate(candidate);
|
|
9991
|
+
if (sanitized) return sanitized;
|
|
9992
|
+
}
|
|
9972
9993
|
}
|
|
9973
|
-
} catch (e) {
|
|
9974
9994
|
}
|
|
9975
|
-
|
|
9976
|
-
|
|
9977
|
-
|
|
9978
|
-
|
|
9979
|
-
|
|
9980
|
-
|
|
9981
|
-
|
|
9982
|
-
return DEFAULT_FALLBACK_MEDIA_URLS.image;
|
|
9995
|
+
return null;
|
|
9996
|
+
};
|
|
9997
|
+
const validMediaUrl = computeUrl();
|
|
9998
|
+
console.log(
|
|
9999
|
+
`[MEDIA_DEBUG] template: ${templateName || "unknown"}, format: ${format}, resolvedUrl: ${validMediaUrl}`
|
|
10000
|
+
);
|
|
10001
|
+
return validMediaUrl;
|
|
9983
10002
|
}
|
|
9984
10003
|
function buildWhatsAppPayload(to, templateName, languageCode, components) {
|
|
9985
10004
|
const payload = {
|
|
@@ -11133,6 +11152,48 @@ function useWhatsAppState(props) {
|
|
|
11133
11152
|
);
|
|
11134
11153
|
setHeaderMediaUrl(defaultUrl || "");
|
|
11135
11154
|
}, [templateHeaderComp, selectedTemplate == null ? void 0 : selectedTemplate.name]);
|
|
11155
|
+
const [isUploadingMedia, setIsUploadingMedia] = (0, import_react17.useState)(false);
|
|
11156
|
+
const handleFileUpload = (0, import_react17.useCallback)(
|
|
11157
|
+
async (file, templateName) => {
|
|
11158
|
+
const tplName = templateName || (selectedTemplate == null ? void 0 : selectedTemplate.name) || "";
|
|
11159
|
+
if (!file) return;
|
|
11160
|
+
setIsUploadingMedia(true);
|
|
11161
|
+
try {
|
|
11162
|
+
const formData = new FormData();
|
|
11163
|
+
formData.append("file", file);
|
|
11164
|
+
const res = await fetch("/api/whatsapp/upload-media", {
|
|
11165
|
+
method: "POST",
|
|
11166
|
+
body: formData
|
|
11167
|
+
});
|
|
11168
|
+
const data = await res.json().catch(() => ({}));
|
|
11169
|
+
if (!res.ok || !(data == null ? void 0 : data.url)) {
|
|
11170
|
+
throw new Error((data == null ? void 0 : data.error) || `\u05D4\u05E2\u05DC\u05D0\u05EA \u05D4\u05E7\u05D5\u05D1\u05E5 \u05E0\u05DB\u05E9\u05DC\u05D4 (${res.status})`);
|
|
11171
|
+
}
|
|
11172
|
+
const publicUrl = data.url;
|
|
11173
|
+
setHeaderMediaUrl(publicUrl);
|
|
11174
|
+
if (tplName && typeof window !== "undefined") {
|
|
11175
|
+
try {
|
|
11176
|
+
localStorage.setItem(`whatsapp_template_media_${tplName}`, publicUrl);
|
|
11177
|
+
localStorage.setItem(`whatsapp_template_media_${tplName.toLowerCase()}`, publicUrl);
|
|
11178
|
+
} catch (e) {
|
|
11179
|
+
}
|
|
11180
|
+
}
|
|
11181
|
+
setFeedback({
|
|
11182
|
+
type: "success",
|
|
11183
|
+
message: "\u05E7\u05D5\u05D1\u05E5 \u05D4\u05DE\u05D3\u05D9\u05D4 \u05D4\u05D5\u05E2\u05DC\u05D4 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4 \u05D5\u05E9\u05D5\u05D9\u05DA \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA"
|
|
11184
|
+
});
|
|
11185
|
+
} catch (err) {
|
|
11186
|
+
console.error("[useWhatsAppState] handleFileUpload error:", err);
|
|
11187
|
+
setFeedback({
|
|
11188
|
+
type: "error",
|
|
11189
|
+
message: (err == null ? void 0 : err.message) || "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E2\u05EA \u05D4\u05E2\u05DC\u05D0\u05EA \u05E7\u05D5\u05D1\u05E5 \u05D4\u05DE\u05D3\u05D9\u05D4"
|
|
11190
|
+
});
|
|
11191
|
+
} finally {
|
|
11192
|
+
setIsUploadingMedia(false);
|
|
11193
|
+
}
|
|
11194
|
+
},
|
|
11195
|
+
[selectedTemplate == null ? void 0 : selectedTemplate.name]
|
|
11196
|
+
);
|
|
11136
11197
|
const templateVariables = (0, import_react17.useMemo)(() => {
|
|
11137
11198
|
return extractTemplateVariables(selectedTemplate);
|
|
11138
11199
|
}, [selectedTemplate]);
|
|
@@ -11250,13 +11311,20 @@ function useWhatsAppState(props) {
|
|
|
11250
11311
|
const isTemplateValid = Boolean(
|
|
11251
11312
|
selectedTemplate && getStatusConfig(selectedTemplate.status).isSelectable
|
|
11252
11313
|
);
|
|
11253
|
-
const
|
|
11254
|
-
const
|
|
11255
|
-
const
|
|
11256
|
-
const
|
|
11314
|
+
const headerFormat = ((templateHeaderComp == null ? void 0 : templateHeaderComp.format) || "").toUpperCase();
|
|
11315
|
+
const requiresMediaHeader = headerFormat === "IMAGE" || headerFormat === "DOCUMENT" || headerFormat === "VIDEO";
|
|
11316
|
+
const isMediaMissing = requiresMediaHeader && (!headerMediaUrl || !headerMediaUrl.trim() || !headerMediaUrl.startsWith("http"));
|
|
11317
|
+
const isSendDisabled = isSendingBroadcast || isScanningPhoneColumns || !hasPhoneColumn || !isTemplateValid || selectedRowIds.length === 0 || finalRecipientCount === 0 || isSubtableFilterIncomplete || isPostSendActionIncomplete || isStaticVariableMissing || isMediaMissing;
|
|
11318
|
+
const isTestDisabled = isSendingTest || isScanningPhoneColumns || !hasPhoneColumn || !isTemplateValid || isSubtableFilterIncomplete || isPostSendActionIncomplete || isStaticVariableMissing || isMediaMissing;
|
|
11319
|
+
const sendButtonTitle = isSendingBroadcast ? "\u05E9\u05D5\u05DC\u05D7 \u05D4\u05D5\u05D3\u05E2\u05D5\u05EA \u05D1\u05EA\u05E4\u05D5\u05E6\u05D4..." : isScanningPhoneColumns ? "\u05D8\u05D5\u05E2\u05DF \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF..." : !hasPhoneColumn ? "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D4 \u05E2\u05DE\u05D5\u05D3\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05D8\u05D1\u05DC\u05D4" : !isTemplateValid ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05EA\u05D1\u05E0\u05D9\u05EA \u05DE\u05D0\u05D5\u05E9\u05E8\u05EA \u05EA\u05D7\u05D9\u05DC\u05D4" : isMediaMissing ? "\u05D9\u05E9 \u05DC\u05D4\u05E2\u05DC\u05D5\u05EA \u05E7\u05D5\u05D1\u05E5 \u05E2\u05D1\u05D5\u05E8 \u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5 \u05DB\u05D3\u05D9 \u05DC\u05E9\u05DC\u05D5\u05D7" : isSubtableFilterIncomplete ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05E2\u05E8\u05DA \u05DC\u05E1\u05D9\u05E0\u05D5\u05DF \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA" : isPostSendActionIncomplete ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05E2\u05E8\u05DA \u05D9\u05E2\u05D3 \u05DC\u05E2\u05D3\u05DB\u05D5\u05DF \u05DC\u05D0\u05D7\u05E8 \u05E9\u05DC\u05D9\u05D7\u05D4" : isStaticVariableMissing ? "\u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05E2\u05E8\u05DA \u05E2\u05D1\u05D5\u05E8 \u05DB\u05DC \u05DE\u05E9\u05EA\u05E0\u05D4 \u05D1\u05D8\u05E7\u05E1\u05D8 \u05E7\u05D1\u05D5\u05E2" : selectedRowIds.length === 0 ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05DC\u05E4\u05D7\u05D5\u05EA \u05E9\u05D5\u05E8\u05D4 \u05D0\u05D7\u05EA \u05DE\u05D4\u05D8\u05D1\u05DC\u05D4" : finalRecipientCount === 0 ? "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05E0\u05DE\u05E2\u05E0\u05D9\u05DD \u05E2\u05DD \u05D8\u05DC\u05E4\u05D5\u05DF \u05EA\u05E7\u05D9\u05DF \u05D4\u05EA\u05D5\u05D0\u05DE\u05D9\u05DD \u05DC\u05E1\u05D9\u05E0\u05D5\u05DF" : `\u05E9\u05DC\u05D7 \u05DC-${finalRecipientCount} \u05E0\u05DE\u05E2\u05E0\u05D9\u05DD (\u05DE\u05EA\u05D5\u05DA ${validMainRowsCount} \u05E9\u05D5\u05E8\u05D5\u05EA \u05E8\u05D0\u05E9\u05D9\u05D5\u05EA)`;
|
|
11320
|
+
const testButtonTitle = isScanningPhoneColumns ? "\u05D8\u05D5\u05E2\u05DF \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF..." : !hasPhoneColumn ? "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D4 \u05E2\u05DE\u05D5\u05D3\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05D8\u05D1\u05DC\u05D4" : !isTemplateValid ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05EA\u05D1\u05E0\u05D9\u05EA \u05DE\u05D0\u05D5\u05E9\u05E8\u05EA \u05EA\u05D7\u05D9\u05DC\u05D4" : isMediaMissing ? "\u05D9\u05E9 \u05DC\u05D4\u05E2\u05DC\u05D5\u05EA \u05E7\u05D5\u05D1\u05E5 \u05E2\u05D1\u05D5\u05E8 \u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5 \u05DB\u05D3\u05D9 \u05DC\u05E9\u05DC\u05D5\u05D7" : isSubtableFilterIncomplete ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05E2\u05E8\u05DA \u05DC\u05E1\u05D9\u05E0\u05D5\u05DF \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA" : isPostSendActionIncomplete ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05E2\u05E8\u05DA \u05D9\u05E2\u05D3 \u05DC\u05E2\u05D3\u05DB\u05D5\u05DF \u05DC\u05D0\u05D7\u05E8 \u05E9\u05DC\u05D9\u05D7\u05D4" : isStaticVariableMissing ? "\u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05E2\u05E8\u05DA \u05E2\u05D1\u05D5\u05E8 \u05DB\u05DC \u05DE\u05E9\u05EA\u05E0\u05D4 \u05D1\u05D8\u05E7\u05E1\u05D8 \u05E7\u05D1\u05D5\u05E2" : "\u05E9\u05DC\u05D9\u05D7\u05EA \u05D4\u05D5\u05D3\u05E2\u05EA \u05D1\u05D3\u05D9\u05E7\u05D4 \u05DC\u05DE\u05E1\u05E4\u05E8 \u05D1\u05D3\u05D9\u05E7\u05D4";
|
|
11257
11321
|
const handleSendTest = async () => {
|
|
11258
11322
|
var _a2;
|
|
11259
11323
|
if (isSendingTest) return;
|
|
11324
|
+
if (isMediaMissing) {
|
|
11325
|
+
setTestFeedback("\u05D9\u05E9 \u05DC\u05D4\u05E2\u05DC\u05D5\u05EA \u05E7\u05D5\u05D1\u05E5 \u05E2\u05D1\u05D5\u05E8 \u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5 \u05DB\u05D3\u05D9 \u05DC\u05E9\u05DC\u05D5\u05D7");
|
|
11326
|
+
return;
|
|
11327
|
+
}
|
|
11260
11328
|
if (isSubtableFilterIncomplete) {
|
|
11261
11329
|
setTestFeedback("\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05E2\u05E8\u05DA \u05DC\u05E1\u05D9\u05E0\u05D5\u05DF \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA");
|
|
11262
11330
|
return;
|
|
@@ -11598,6 +11666,8 @@ function useWhatsAppState(props) {
|
|
|
11598
11666
|
isTestDisabled,
|
|
11599
11667
|
sendButtonTitle,
|
|
11600
11668
|
testButtonTitle,
|
|
11669
|
+
requiresMediaHeader,
|
|
11670
|
+
isMediaMissing,
|
|
11601
11671
|
// Templates & Meta API
|
|
11602
11672
|
templates,
|
|
11603
11673
|
selectedTemplateId,
|
|
@@ -11608,6 +11678,8 @@ function useWhatsAppState(props) {
|
|
|
11608
11678
|
headerMediaUrl,
|
|
11609
11679
|
handleHeaderMediaUrlChange,
|
|
11610
11680
|
handleResetHeaderMediaUrl,
|
|
11681
|
+
isUploadingMedia,
|
|
11682
|
+
handleFileUpload,
|
|
11611
11683
|
templateVariables,
|
|
11612
11684
|
variableMapping,
|
|
11613
11685
|
textableColumnOptions,
|
|
@@ -11644,6 +11716,7 @@ function useWhatsAppState(props) {
|
|
|
11644
11716
|
}
|
|
11645
11717
|
|
|
11646
11718
|
// src/components/WhatsAppComponent/ui/TemplateSelectionBlock.tsx
|
|
11719
|
+
var import_react18 = require("react");
|
|
11647
11720
|
var import_lucide_react11 = require("lucide-react");
|
|
11648
11721
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
11649
11722
|
function TemplateSelectionBlock({
|
|
@@ -11667,8 +11740,11 @@ function TemplateSelectionBlock({
|
|
|
11667
11740
|
handleDeleteTemplate,
|
|
11668
11741
|
isDeleting,
|
|
11669
11742
|
setIsModalOpen,
|
|
11670
|
-
setFeedback
|
|
11743
|
+
setFeedback,
|
|
11744
|
+
isUploadingMedia = false,
|
|
11745
|
+
handleFileUpload
|
|
11671
11746
|
}) {
|
|
11747
|
+
const fileInputRef = (0, import_react18.useRef)(null);
|
|
11672
11748
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "col-span-12 lg:col-span-5 min-h-[26rem] h-full flex flex-col bg-slate-50/70 border border-slate-200 rounded-2xl p-3.5 relative", children: [
|
|
11673
11749
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "space-y-1.5 shrink-0", children: [
|
|
11674
11750
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center justify-between pb-1.5 border-b border-slate-200/70 shrink-0 gap-2", children: [
|
|
@@ -11848,10 +11924,15 @@ function TemplateSelectionBlock({
|
|
|
11848
11924
|
})(),
|
|
11849
11925
|
templateHeaderComp && (() => {
|
|
11850
11926
|
const headerFormat = (templateHeaderComp.format || "").toUpperCase();
|
|
11927
|
+
if (headerFormat !== "IMAGE" && headerFormat !== "DOCUMENT" && headerFormat !== "VIDEO") {
|
|
11928
|
+
return null;
|
|
11929
|
+
}
|
|
11851
11930
|
const docFilename = resolveDocumentFilename(templateHeaderComp, headerMediaUrl);
|
|
11931
|
+
const hasValidMedia = Boolean(headerMediaUrl && headerMediaUrl.trim() && headerMediaUrl.startsWith("http"));
|
|
11932
|
+
const uploadButtonLabel = headerFormat === "DOCUMENT" ? "\u05D4\u05E2\u05DC\u05D4 \u05DE\u05E1\u05DE\u05DA" : headerFormat === "IMAGE" ? "\u05D4\u05E2\u05DC\u05D4 \u05EA\u05DE\u05D5\u05E0\u05D4" : "\u05D4\u05E2\u05DC\u05D4 \u05E7\u05D5\u05D1\u05E5";
|
|
11852
11933
|
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "p-2.5 bg-slate-50 border border-slate-200/90 rounded-xl flex items-center justify-between gap-3 shrink-0 shadow-2xs", children: [
|
|
11853
11934
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "flex items-center gap-2.5 overflow-hidden", children: headerFormat === "IMAGE" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
11854
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "w-8 h-8 rounded-lg overflow-hidden border border-slate-200 shrink-0 bg-slate-100 flex items-center justify-center", children:
|
|
11935
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: "w-8 h-8 rounded-lg overflow-hidden border border-slate-200 shrink-0 bg-slate-100 flex items-center justify-center", children: hasValidMedia ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
11855
11936
|
"img",
|
|
11856
11937
|
{
|
|
11857
11938
|
src: headerMediaUrl,
|
|
@@ -11861,26 +11942,33 @@ function TemplateSelectionBlock({
|
|
|
11861
11942
|
e.currentTarget.style.display = "none";
|
|
11862
11943
|
}
|
|
11863
11944
|
}
|
|
11864
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react11.Image, { className: "w-4 h-4 text-
|
|
11945
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react11.Image, { className: "w-4 h-4 text-amber-600" }) }),
|
|
11865
11946
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "overflow-hidden", children: [
|
|
11866
11947
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-xs font-bold text-slate-800 block truncate", children: "\u05EA\u05DE\u05D5\u05E0\u05EA \u05DB\u05D5\u05EA\u05E8\u05EA" }),
|
|
11867
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-[10px] text-slate-400 block truncate", children: "\u05E7\u05D5\u05D1\u05E5 \u05DE\
|
|
11948
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-[10px] text-slate-400 block truncate", children: hasValidMedia ? "\u05E7\u05D5\u05D1\u05E5 \u05EA\u05DE\u05D5\u05E0\u05D4 \u05DE\u05E7\u05D5\u05E9\u05E8 \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA" : "\u05D8\u05E8\u05DD \u05D4\u05D5\u05E2\u05DC\u05D4 \u05E7\u05D5\u05D1\u05E5 \u05EA\u05DE\u05D5\u05E0\u05D4" })
|
|
11868
11949
|
] })
|
|
11869
11950
|
] }) : headerFormat === "DOCUMENT" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
11870
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className:
|
|
11951
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: `w-8 h-8 rounded-lg flex items-center justify-center shrink-0 border ${hasValidMedia ? "bg-rose-50 text-rose-600 border-rose-100" : "bg-slate-100 text-slate-400 border-slate-200"}`, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react11.FileText, { className: "w-4 h-4" }) }),
|
|
11871
11952
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "overflow-hidden", children: [
|
|
11872
11953
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-xs font-bold text-slate-800 block truncate", children: "\u05DE\u05E1\u05DE\u05DA \u05DB\u05D5\u05EA\u05E8\u05EA (PDF)" }),
|
|
11873
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-[10px] text-slate-500 font-mono block truncate", title: docFilename, children: docFilename })
|
|
11954
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-[10px] text-slate-500 font-mono block truncate", title: hasValidMedia ? docFilename : void 0, children: hasValidMedia ? docFilename : "\u05D8\u05E8\u05DD \u05D4\u05D5\u05E2\u05DC\u05D4 \u05E7\u05D5\u05D1\u05E5 \u05DE\u05E1\u05DE\u05DA" })
|
|
11874
11955
|
] })
|
|
11875
11956
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
11876
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className:
|
|
11957
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("div", { className: `w-8 h-8 rounded-lg flex items-center justify-center shrink-0 border ${hasValidMedia ? "bg-indigo-50 text-indigo-600 border-indigo-100" : "bg-slate-100 text-slate-400 border-slate-200"}`, children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react11.Video, { className: "w-4 h-4" }) }),
|
|
11877
11958
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "overflow-hidden", children: [
|
|
11878
11959
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-xs font-bold text-slate-800 block truncate", children: "\u05E1\u05E8\u05D8\u05D5\u05DF \u05DB\u05D5\u05EA\u05E8\u05EA" }),
|
|
11879
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-[10px] text-slate-400 block truncate", children: "\u05E7\u05D5\u05D1\u05E5 \u05D5\u05D9\u05D3\u05D0\u05D5 \u05DE\
|
|
11960
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { className: "text-[10px] text-slate-400 block truncate", children: hasValidMedia ? "\u05E7\u05D5\u05D1\u05E5 \u05D5\u05D9\u05D3\u05D0\u05D5 \u05DE\u05E7\u05D5\u05E9\u05E8 \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA" : "\u05D8\u05E8\u05DD \u05D4\u05D5\u05E2\u05DC\u05D4 \u05E7\u05D5\u05D1\u05E5 \u05D5\u05D9\u05D3\u05D0\u05D5" })
|
|
11880
11961
|
] })
|
|
11881
11962
|
] }) }),
|
|
11882
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-
|
|
11883
|
-
|
|
11963
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
11964
|
+
hasValidMedia ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "inline-flex items-center gap-1 text-[10px] font-medium text-emerald-800 px-2 py-0.5 bg-emerald-50 border border-emerald-200 rounded-lg", children: [
|
|
11965
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react11.CheckCircle2, { className: "w-3 h-3 text-emerald-600" }),
|
|
11966
|
+
"\u05E7\u05D5\u05D1\u05E5 \u05DE\u05E6\u05D5\u05E8\u05E3 \u05EA\u05E7\u05D9\u05DF"
|
|
11967
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("span", { className: "inline-flex items-center gap-1 text-[10px] font-semibold text-amber-800 px-2 py-0.5 bg-amber-50 border border-amber-200 rounded-lg", children: [
|
|
11968
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react11.AlertCircle, { className: "w-3 h-3 text-amber-600 shrink-0" }),
|
|
11969
|
+
"\u05E0\u05D3\u05E8\u05E9 \u05E6\u05D9\u05E8\u05D5\u05E3 \u05E7\u05D5\u05D1\u05E5 \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5"
|
|
11970
|
+
] }),
|
|
11971
|
+
hasValidMedia && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
11884
11972
|
"a",
|
|
11885
11973
|
{
|
|
11886
11974
|
href: headerMediaUrl,
|
|
@@ -11891,7 +11979,44 @@ function TemplateSelectionBlock({
|
|
|
11891
11979
|
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react11.ExternalLink, { className: "w-3.5 h-3.5" })
|
|
11892
11980
|
}
|
|
11893
11981
|
),
|
|
11894
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
11982
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
11983
|
+
"input",
|
|
11984
|
+
{
|
|
11985
|
+
ref: fileInputRef,
|
|
11986
|
+
type: "file",
|
|
11987
|
+
className: "hidden",
|
|
11988
|
+
accept: headerFormat === "DOCUMENT" ? ".pdf,application/pdf" : headerFormat === "VIDEO" ? "video/mp4,video/*" : "image/png,image/jpeg,image/jpg",
|
|
11989
|
+
onChange: (e) => {
|
|
11990
|
+
var _a;
|
|
11991
|
+
const file = (_a = e.target.files) == null ? void 0 : _a[0];
|
|
11992
|
+
if (file && handleFileUpload && (selectedTemplate == null ? void 0 : selectedTemplate.name)) {
|
|
11993
|
+
handleFileUpload(file, selectedTemplate.name);
|
|
11994
|
+
}
|
|
11995
|
+
e.target.value = "";
|
|
11996
|
+
},
|
|
11997
|
+
disabled: isUploadingMedia
|
|
11998
|
+
}
|
|
11999
|
+
),
|
|
12000
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
12001
|
+
"button",
|
|
12002
|
+
{
|
|
12003
|
+
type: "button",
|
|
12004
|
+
disabled: isUploadingMedia,
|
|
12005
|
+
onClick: () => {
|
|
12006
|
+
var _a;
|
|
12007
|
+
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
12008
|
+
},
|
|
12009
|
+
className: `inline-flex items-center gap-1.5 px-2.5 py-1 text-[11px] font-medium rounded-lg transition-colors border shadow-2xs ${isUploadingMedia ? "bg-slate-100 text-slate-400 border-slate-200 cursor-not-allowed" : hasValidMedia ? "bg-white text-slate-700 hover:bg-slate-50 border-slate-200 hover:border-slate-300" : "bg-emerald-600 text-white hover:bg-emerald-700 border-emerald-600"}`,
|
|
12010
|
+
title: hasValidMedia ? "\u05D4\u05D7\u05DC\u05E3 \u05E7\u05D5\u05D1\u05E5 \u05DE\u05D3\u05D9\u05D4 \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5" : `${uploadButtonLabel} \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5`,
|
|
12011
|
+
children: isUploadingMedia ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
12012
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react11.Loader2, { className: "w-3.5 h-3.5 animate-spin" }),
|
|
12013
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: "\u05DE\u05E2\u05DC\u05D4..." })
|
|
12014
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
12015
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react11.Upload, { className: "w-3.5 h-3.5" }),
|
|
12016
|
+
/* @__PURE__ */ (0, import_jsx_runtime15.jsx)("span", { children: hasValidMedia ? "\u05D4\u05D7\u05DC\u05E3 \u05E7\u05D5\u05D1\u05E5" : uploadButtonLabel })
|
|
12017
|
+
] })
|
|
12018
|
+
}
|
|
12019
|
+
)
|
|
11895
12020
|
] })
|
|
11896
12021
|
] });
|
|
11897
12022
|
})(),
|
|
@@ -12647,7 +12772,9 @@ function WhatsAppComponent(props) {
|
|
|
12647
12772
|
handleDeleteTemplate: state.handleDeleteTemplate,
|
|
12648
12773
|
isDeleting: state.isDeleting,
|
|
12649
12774
|
setIsModalOpen: state.setIsModalOpen,
|
|
12650
|
-
setFeedback: state.setFeedback
|
|
12775
|
+
setFeedback: state.setFeedback,
|
|
12776
|
+
isUploadingMedia: state.isUploadingMedia,
|
|
12777
|
+
handleFileUpload: state.handleFileUpload
|
|
12651
12778
|
}
|
|
12652
12779
|
),
|
|
12653
12780
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
@@ -12833,7 +12960,7 @@ function WhatsAppComponent(props) {
|
|
|
12833
12960
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "w-7 h-7 rounded-md bg-indigo-50 text-indigo-600 border border-indigo-100 flex items-center justify-center shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react14.Video, { className: "w-3.5 h-3.5" }) }),
|
|
12834
12961
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "font-semibold text-slate-800 truncate", children: "\u05E1\u05E8\u05D8\u05D5\u05DF \u05DB\u05D5\u05EA\u05E8\u05EA" })
|
|
12835
12962
|
] }) }),
|
|
12836
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-[10px] text-emerald-700 bg-emerald-50 border border-emerald-200 px-1.5 py-0.5 rounded font-medium shrink-0", children: "\u05DE\u05E6\u05D5\u05E8\u05E3 \
|
|
12963
|
+
state.headerMediaUrl && state.headerMediaUrl.startsWith("http") ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-[10px] text-emerald-700 bg-emerald-50 border border-emerald-200 px-1.5 py-0.5 rounded font-medium shrink-0", children: "\u05E7\u05D5\u05D1\u05E5 \u05DE\u05E6\u05D5\u05E8\u05E3 \u05EA\u05E7\u05D9\u05DF" }) : /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-[10px] text-amber-700 bg-amber-50 border border-amber-200 px-1.5 py-0.5 rounded font-medium shrink-0", children: "\u05E0\u05D3\u05E8\u05E9 \u05E6\u05D9\u05E8\u05D5\u05E3 \u05E7\u05D5\u05D1\u05E5 \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5" })
|
|
12837
12964
|
] });
|
|
12838
12965
|
})(),
|
|
12839
12966
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-1.5", children: [
|
|
@@ -12892,9 +13019,10 @@ function WhatsAppComponent(props) {
|
|
|
12892
13019
|
"button",
|
|
12893
13020
|
{
|
|
12894
13021
|
type: "button",
|
|
12895
|
-
disabled: !state.testPhoneNumber.trim() || state.isSendingTest,
|
|
13022
|
+
disabled: !state.testPhoneNumber.trim() || state.isSendingTest || state.isTestDisabled,
|
|
12896
13023
|
onClick: state.handleSendTest,
|
|
12897
|
-
|
|
13024
|
+
title: state.testButtonTitle,
|
|
13025
|
+
className: `px-4 py-2 text-xs font-bold rounded-xl transition-all flex items-center gap-1.5 ${!state.testPhoneNumber.trim() || state.isSendingTest || state.isTestDisabled ? "bg-emerald-600/40 text-white/70 cursor-not-allowed" : "bg-emerald-600 hover:bg-emerald-700 active:scale-[0.98] text-white shadow-xs cursor-pointer"}`,
|
|
12898
13026
|
children: state.isSendingTest ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
12899
13027
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react14.Loader2, { className: "w-3.5 h-3.5 animate-spin" }),
|
|
12900
13028
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { children: "\u05E9\u05D5\u05DC\u05D7..." })
|
package/dist/index.mjs
CHANGED
|
@@ -97,9 +97,15 @@ function normalizePhoneForWhatsApp(phone) {
|
|
|
97
97
|
cleaned = cleaned.substring(1);
|
|
98
98
|
}
|
|
99
99
|
const digitsOnly = cleaned.replace(/\D/g, "");
|
|
100
|
-
if (digitsOnly.startsWith("
|
|
100
|
+
if (digitsOnly.startsWith("972")) {
|
|
101
|
+
return digitsOnly;
|
|
102
|
+
}
|
|
103
|
+
if (digitsOnly.startsWith("0")) {
|
|
101
104
|
return `972${digitsOnly.substring(1)}`;
|
|
102
105
|
}
|
|
106
|
+
if (digitsOnly.length === 9) {
|
|
107
|
+
return `972${digitsOnly}`;
|
|
108
|
+
}
|
|
103
109
|
return digitsOnly;
|
|
104
110
|
}
|
|
105
111
|
|
|
@@ -7713,7 +7719,7 @@ function TableBlock(props) {
|
|
|
7713
7719
|
}
|
|
7714
7720
|
|
|
7715
7721
|
// src/components/WhatsAppComponent/WhatsAppComponent.tsx
|
|
7716
|
-
import { CheckCircle2 as
|
|
7722
|
+
import { CheckCircle2 as CheckCircle24, AlertCircle as AlertCircle5, X as X12, Loader2 as Loader27, Phone as Phone4, Send as Send2, Image as ImageIcon3, FileText as FileText4, Video as Video3 } from "lucide-react";
|
|
7717
7723
|
|
|
7718
7724
|
// src/components/WhatsAppComponent/CreateTemplateModal.tsx
|
|
7719
7725
|
import { useState as useState14, useEffect as useEffect12, useRef as useRef11, useMemo as useMemo7 } from "react";
|
|
@@ -9645,9 +9651,12 @@ function buildTemplateComponents(params) {
|
|
|
9645
9651
|
const format = (headerComp.format || "TEXT").toUpperCase();
|
|
9646
9652
|
if (format === "IMAGE" || format === "DOCUMENT" || format === "VIDEO") {
|
|
9647
9653
|
const validMediaUrl = resolveHeaderMediaUrl(headerComp, mediaUrl, selectedTemplate.name);
|
|
9654
|
+
console.log(
|
|
9655
|
+
`[MEDIA_DEBUG] template: ${selectedTemplate.name}, format: ${format}, resolvedUrl: ${validMediaUrl}`
|
|
9656
|
+
);
|
|
9648
9657
|
if (validMediaUrl) {
|
|
9649
9658
|
if (format === "DOCUMENT") {
|
|
9650
|
-
const docFilename = resolveDocumentFilename(headerComp, validMediaUrl);
|
|
9659
|
+
const docFilename = resolveDocumentFilename(headerComp, validMediaUrl) || "document.pdf";
|
|
9651
9660
|
components.push({
|
|
9652
9661
|
type: "header",
|
|
9653
9662
|
parameters: [
|
|
@@ -9816,11 +9825,6 @@ function findColumnDef(colOption, tableColumns) {
|
|
|
9816
9825
|
}
|
|
9817
9826
|
return null;
|
|
9818
9827
|
}
|
|
9819
|
-
var DEFAULT_FALLBACK_MEDIA_URLS = {
|
|
9820
|
-
image: "https://images.unsplash.com/photo-1579202673506-ca3ce28943ef?q=80&w=800&fm=jpg&fit=crop",
|
|
9821
|
-
document: "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf",
|
|
9822
|
-
video: "https://www.w3schools.com/html/mov_bbb.mp4"
|
|
9823
|
-
};
|
|
9824
9828
|
function resolveDocumentFilename(headerComp, mediaUrl) {
|
|
9825
9829
|
var _a, _b, _c;
|
|
9826
9830
|
if ((_a = headerComp == null ? void 0 : headerComp.document) == null ? void 0 : _a.filename) {
|
|
@@ -9834,8 +9838,11 @@ function resolveDocumentFilename(headerComp, mediaUrl) {
|
|
|
9834
9838
|
const urlObj = new URL(mediaUrl);
|
|
9835
9839
|
const pathname = urlObj.pathname;
|
|
9836
9840
|
const lastSegment = pathname.substring(pathname.lastIndexOf("/") + 1);
|
|
9837
|
-
if (lastSegment
|
|
9838
|
-
|
|
9841
|
+
if (lastSegment) {
|
|
9842
|
+
const decoded = decodeURIComponent(lastSegment).trim();
|
|
9843
|
+
if (decoded) {
|
|
9844
|
+
return decoded.includes(".") ? decoded : `${decoded}.pdf`;
|
|
9845
|
+
}
|
|
9839
9846
|
}
|
|
9840
9847
|
} catch (e) {
|
|
9841
9848
|
}
|
|
@@ -9843,61 +9850,73 @@ function resolveDocumentFilename(headerComp, mediaUrl) {
|
|
|
9843
9850
|
return "document.pdf";
|
|
9844
9851
|
}
|
|
9845
9852
|
function resolveHeaderMediaUrl(headerComp, customMediaUrl, templateName) {
|
|
9846
|
-
|
|
9847
|
-
const isImageFormat =
|
|
9853
|
+
const format = ((headerComp == null ? void 0 : headerComp.format) || "").toUpperCase();
|
|
9854
|
+
const isImageFormat = format === "IMAGE";
|
|
9848
9855
|
const sanitizeCandidate = (rawUrl) => {
|
|
9856
|
+
if (!rawUrl || typeof rawUrl !== "string") {
|
|
9857
|
+
return null;
|
|
9858
|
+
}
|
|
9849
9859
|
let trimmed = rawUrl.trim();
|
|
9860
|
+
if (trimmed.startsWith("4:")) {
|
|
9861
|
+
return null;
|
|
9862
|
+
}
|
|
9850
9863
|
if (!trimmed.startsWith("http://") && !trimmed.startsWith("https://")) {
|
|
9851
9864
|
return null;
|
|
9852
9865
|
}
|
|
9866
|
+
const lower = trimmed.toLowerCase();
|
|
9867
|
+
if (lower.includes("scontent.whatsapp.net") || lower.includes("lookaside.fbsbx.com")) {
|
|
9868
|
+
return null;
|
|
9869
|
+
}
|
|
9853
9870
|
if (isImageFormat) {
|
|
9854
|
-
if (
|
|
9855
|
-
trimmed = trimmed.replace(
|
|
9871
|
+
if (lower.includes("unsplash.com") && lower.includes("auto=format")) {
|
|
9872
|
+
trimmed = trimmed.replace(/auto=format/gi, "fm=jpg");
|
|
9856
9873
|
}
|
|
9857
|
-
if (
|
|
9874
|
+
if (lower.includes(".webp")) {
|
|
9858
9875
|
return null;
|
|
9859
9876
|
}
|
|
9860
9877
|
}
|
|
9861
9878
|
return trimmed;
|
|
9862
9879
|
};
|
|
9863
|
-
|
|
9864
|
-
|
|
9865
|
-
if (
|
|
9866
|
-
|
|
9867
|
-
|
|
9868
|
-
|
|
9869
|
-
|
|
9870
|
-
|
|
9871
|
-
|
|
9872
|
-
|
|
9873
|
-
|
|
9874
|
-
|
|
9875
|
-
|
|
9876
|
-
|
|
9877
|
-
for (const candidate of candidates) {
|
|
9878
|
-
if (typeof candidate === "string") {
|
|
9879
|
-
const sanitized = sanitizeCandidate(candidate);
|
|
9880
|
-
if (sanitized) return sanitized;
|
|
9880
|
+
const computeUrl = () => {
|
|
9881
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
9882
|
+
if (customMediaUrl && typeof customMediaUrl === "string") {
|
|
9883
|
+
const sanitized = sanitizeCandidate(customMediaUrl);
|
|
9884
|
+
if (sanitized) return sanitized;
|
|
9885
|
+
}
|
|
9886
|
+
if (templateName && typeof window !== "undefined") {
|
|
9887
|
+
try {
|
|
9888
|
+
const persisted = localStorage.getItem(`whatsapp_template_media_${templateName}`) || localStorage.getItem(`whatsapp_template_media_${templateName.toLowerCase()}`);
|
|
9889
|
+
if (persisted && typeof persisted === "string") {
|
|
9890
|
+
const sanitized = sanitizeCandidate(persisted);
|
|
9891
|
+
if (sanitized) return sanitized;
|
|
9892
|
+
}
|
|
9893
|
+
} catch (e) {
|
|
9881
9894
|
}
|
|
9882
9895
|
}
|
|
9883
|
-
|
|
9884
|
-
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
|
|
9896
|
+
if (headerComp) {
|
|
9897
|
+
const candidates = [
|
|
9898
|
+
headerComp.url,
|
|
9899
|
+
headerComp.link,
|
|
9900
|
+
(_a = headerComp.image) == null ? void 0 : _a.link,
|
|
9901
|
+
(_b = headerComp.document) == null ? void 0 : _b.link,
|
|
9902
|
+
(_c = headerComp.video) == null ? void 0 : _c.link,
|
|
9903
|
+
(_e = (_d = headerComp.example) == null ? void 0 : _d.header_url) == null ? void 0 : _e[0],
|
|
9904
|
+
(_g = (_f = headerComp.example) == null ? void 0 : _f.header_handle) == null ? void 0 : _g[0]
|
|
9905
|
+
];
|
|
9906
|
+
for (const candidate of candidates) {
|
|
9907
|
+
if (typeof candidate === "string") {
|
|
9908
|
+
const sanitized = sanitizeCandidate(candidate);
|
|
9909
|
+
if (sanitized) return sanitized;
|
|
9910
|
+
}
|
|
9890
9911
|
}
|
|
9891
|
-
} catch (e) {
|
|
9892
9912
|
}
|
|
9893
|
-
|
|
9894
|
-
|
|
9895
|
-
|
|
9896
|
-
|
|
9897
|
-
|
|
9898
|
-
|
|
9899
|
-
|
|
9900
|
-
return DEFAULT_FALLBACK_MEDIA_URLS.image;
|
|
9913
|
+
return null;
|
|
9914
|
+
};
|
|
9915
|
+
const validMediaUrl = computeUrl();
|
|
9916
|
+
console.log(
|
|
9917
|
+
`[MEDIA_DEBUG] template: ${templateName || "unknown"}, format: ${format}, resolvedUrl: ${validMediaUrl}`
|
|
9918
|
+
);
|
|
9919
|
+
return validMediaUrl;
|
|
9901
9920
|
}
|
|
9902
9921
|
function buildWhatsAppPayload(to, templateName, languageCode, components) {
|
|
9903
9922
|
const payload = {
|
|
@@ -11051,6 +11070,48 @@ function useWhatsAppState(props) {
|
|
|
11051
11070
|
);
|
|
11052
11071
|
setHeaderMediaUrl(defaultUrl || "");
|
|
11053
11072
|
}, [templateHeaderComp, selectedTemplate == null ? void 0 : selectedTemplate.name]);
|
|
11073
|
+
const [isUploadingMedia, setIsUploadingMedia] = useState15(false);
|
|
11074
|
+
const handleFileUpload = useCallback12(
|
|
11075
|
+
async (file, templateName) => {
|
|
11076
|
+
const tplName = templateName || (selectedTemplate == null ? void 0 : selectedTemplate.name) || "";
|
|
11077
|
+
if (!file) return;
|
|
11078
|
+
setIsUploadingMedia(true);
|
|
11079
|
+
try {
|
|
11080
|
+
const formData = new FormData();
|
|
11081
|
+
formData.append("file", file);
|
|
11082
|
+
const res = await fetch("/api/whatsapp/upload-media", {
|
|
11083
|
+
method: "POST",
|
|
11084
|
+
body: formData
|
|
11085
|
+
});
|
|
11086
|
+
const data = await res.json().catch(() => ({}));
|
|
11087
|
+
if (!res.ok || !(data == null ? void 0 : data.url)) {
|
|
11088
|
+
throw new Error((data == null ? void 0 : data.error) || `\u05D4\u05E2\u05DC\u05D0\u05EA \u05D4\u05E7\u05D5\u05D1\u05E5 \u05E0\u05DB\u05E9\u05DC\u05D4 (${res.status})`);
|
|
11089
|
+
}
|
|
11090
|
+
const publicUrl = data.url;
|
|
11091
|
+
setHeaderMediaUrl(publicUrl);
|
|
11092
|
+
if (tplName && typeof window !== "undefined") {
|
|
11093
|
+
try {
|
|
11094
|
+
localStorage.setItem(`whatsapp_template_media_${tplName}`, publicUrl);
|
|
11095
|
+
localStorage.setItem(`whatsapp_template_media_${tplName.toLowerCase()}`, publicUrl);
|
|
11096
|
+
} catch (e) {
|
|
11097
|
+
}
|
|
11098
|
+
}
|
|
11099
|
+
setFeedback({
|
|
11100
|
+
type: "success",
|
|
11101
|
+
message: "\u05E7\u05D5\u05D1\u05E5 \u05D4\u05DE\u05D3\u05D9\u05D4 \u05D4\u05D5\u05E2\u05DC\u05D4 \u05D1\u05D4\u05E6\u05DC\u05D7\u05D4 \u05D5\u05E9\u05D5\u05D9\u05DA \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA"
|
|
11102
|
+
});
|
|
11103
|
+
} catch (err) {
|
|
11104
|
+
console.error("[useWhatsAppState] handleFileUpload error:", err);
|
|
11105
|
+
setFeedback({
|
|
11106
|
+
type: "error",
|
|
11107
|
+
message: (err == null ? void 0 : err.message) || "\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05E2\u05EA \u05D4\u05E2\u05DC\u05D0\u05EA \u05E7\u05D5\u05D1\u05E5 \u05D4\u05DE\u05D3\u05D9\u05D4"
|
|
11108
|
+
});
|
|
11109
|
+
} finally {
|
|
11110
|
+
setIsUploadingMedia(false);
|
|
11111
|
+
}
|
|
11112
|
+
},
|
|
11113
|
+
[selectedTemplate == null ? void 0 : selectedTemplate.name]
|
|
11114
|
+
);
|
|
11054
11115
|
const templateVariables = useMemo8(() => {
|
|
11055
11116
|
return extractTemplateVariables(selectedTemplate);
|
|
11056
11117
|
}, [selectedTemplate]);
|
|
@@ -11168,13 +11229,20 @@ function useWhatsAppState(props) {
|
|
|
11168
11229
|
const isTemplateValid = Boolean(
|
|
11169
11230
|
selectedTemplate && getStatusConfig(selectedTemplate.status).isSelectable
|
|
11170
11231
|
);
|
|
11171
|
-
const
|
|
11172
|
-
const
|
|
11173
|
-
const
|
|
11174
|
-
const
|
|
11232
|
+
const headerFormat = ((templateHeaderComp == null ? void 0 : templateHeaderComp.format) || "").toUpperCase();
|
|
11233
|
+
const requiresMediaHeader = headerFormat === "IMAGE" || headerFormat === "DOCUMENT" || headerFormat === "VIDEO";
|
|
11234
|
+
const isMediaMissing = requiresMediaHeader && (!headerMediaUrl || !headerMediaUrl.trim() || !headerMediaUrl.startsWith("http"));
|
|
11235
|
+
const isSendDisabled = isSendingBroadcast || isScanningPhoneColumns || !hasPhoneColumn || !isTemplateValid || selectedRowIds.length === 0 || finalRecipientCount === 0 || isSubtableFilterIncomplete || isPostSendActionIncomplete || isStaticVariableMissing || isMediaMissing;
|
|
11236
|
+
const isTestDisabled = isSendingTest || isScanningPhoneColumns || !hasPhoneColumn || !isTemplateValid || isSubtableFilterIncomplete || isPostSendActionIncomplete || isStaticVariableMissing || isMediaMissing;
|
|
11237
|
+
const sendButtonTitle = isSendingBroadcast ? "\u05E9\u05D5\u05DC\u05D7 \u05D4\u05D5\u05D3\u05E2\u05D5\u05EA \u05D1\u05EA\u05E4\u05D5\u05E6\u05D4..." : isScanningPhoneColumns ? "\u05D8\u05D5\u05E2\u05DF \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF..." : !hasPhoneColumn ? "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D4 \u05E2\u05DE\u05D5\u05D3\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05D8\u05D1\u05DC\u05D4" : !isTemplateValid ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05EA\u05D1\u05E0\u05D9\u05EA \u05DE\u05D0\u05D5\u05E9\u05E8\u05EA \u05EA\u05D7\u05D9\u05DC\u05D4" : isMediaMissing ? "\u05D9\u05E9 \u05DC\u05D4\u05E2\u05DC\u05D5\u05EA \u05E7\u05D5\u05D1\u05E5 \u05E2\u05D1\u05D5\u05E8 \u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5 \u05DB\u05D3\u05D9 \u05DC\u05E9\u05DC\u05D5\u05D7" : isSubtableFilterIncomplete ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05E2\u05E8\u05DA \u05DC\u05E1\u05D9\u05E0\u05D5\u05DF \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA" : isPostSendActionIncomplete ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05E2\u05E8\u05DA \u05D9\u05E2\u05D3 \u05DC\u05E2\u05D3\u05DB\u05D5\u05DF \u05DC\u05D0\u05D7\u05E8 \u05E9\u05DC\u05D9\u05D7\u05D4" : isStaticVariableMissing ? "\u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05E2\u05E8\u05DA \u05E2\u05D1\u05D5\u05E8 \u05DB\u05DC \u05DE\u05E9\u05EA\u05E0\u05D4 \u05D1\u05D8\u05E7\u05E1\u05D8 \u05E7\u05D1\u05D5\u05E2" : selectedRowIds.length === 0 ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05DC\u05E4\u05D7\u05D5\u05EA \u05E9\u05D5\u05E8\u05D4 \u05D0\u05D7\u05EA \u05DE\u05D4\u05D8\u05D1\u05DC\u05D4" : finalRecipientCount === 0 ? "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D5 \u05E0\u05DE\u05E2\u05E0\u05D9\u05DD \u05E2\u05DD \u05D8\u05DC\u05E4\u05D5\u05DF \u05EA\u05E7\u05D9\u05DF \u05D4\u05EA\u05D5\u05D0\u05DE\u05D9\u05DD \u05DC\u05E1\u05D9\u05E0\u05D5\u05DF" : `\u05E9\u05DC\u05D7 \u05DC-${finalRecipientCount} \u05E0\u05DE\u05E2\u05E0\u05D9\u05DD (\u05DE\u05EA\u05D5\u05DA ${validMainRowsCount} \u05E9\u05D5\u05E8\u05D5\u05EA \u05E8\u05D0\u05E9\u05D9\u05D5\u05EA)`;
|
|
11238
|
+
const testButtonTitle = isScanningPhoneColumns ? "\u05D8\u05D5\u05E2\u05DF \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF..." : !hasPhoneColumn ? "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D4 \u05E2\u05DE\u05D5\u05D3\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05D8\u05D1\u05DC\u05D4" : !isTemplateValid ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05EA\u05D1\u05E0\u05D9\u05EA \u05DE\u05D0\u05D5\u05E9\u05E8\u05EA \u05EA\u05D7\u05D9\u05DC\u05D4" : isMediaMissing ? "\u05D9\u05E9 \u05DC\u05D4\u05E2\u05DC\u05D5\u05EA \u05E7\u05D5\u05D1\u05E5 \u05E2\u05D1\u05D5\u05E8 \u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5 \u05DB\u05D3\u05D9 \u05DC\u05E9\u05DC\u05D5\u05D7" : isSubtableFilterIncomplete ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05E2\u05E8\u05DA \u05DC\u05E1\u05D9\u05E0\u05D5\u05DF \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA" : isPostSendActionIncomplete ? "\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05E2\u05E8\u05DA \u05D9\u05E2\u05D3 \u05DC\u05E2\u05D3\u05DB\u05D5\u05DF \u05DC\u05D0\u05D7\u05E8 \u05E9\u05DC\u05D9\u05D7\u05D4" : isStaticVariableMissing ? "\u05D9\u05E9 \u05DC\u05D4\u05D6\u05D9\u05DF \u05E2\u05E8\u05DA \u05E2\u05D1\u05D5\u05E8 \u05DB\u05DC \u05DE\u05E9\u05EA\u05E0\u05D4 \u05D1\u05D8\u05E7\u05E1\u05D8 \u05E7\u05D1\u05D5\u05E2" : "\u05E9\u05DC\u05D9\u05D7\u05EA \u05D4\u05D5\u05D3\u05E2\u05EA \u05D1\u05D3\u05D9\u05E7\u05D4 \u05DC\u05DE\u05E1\u05E4\u05E8 \u05D1\u05D3\u05D9\u05E7\u05D4";
|
|
11175
11239
|
const handleSendTest = async () => {
|
|
11176
11240
|
var _a2;
|
|
11177
11241
|
if (isSendingTest) return;
|
|
11242
|
+
if (isMediaMissing) {
|
|
11243
|
+
setTestFeedback("\u05D9\u05E9 \u05DC\u05D4\u05E2\u05DC\u05D5\u05EA \u05E7\u05D5\u05D1\u05E5 \u05E2\u05D1\u05D5\u05E8 \u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5 \u05DB\u05D3\u05D9 \u05DC\u05E9\u05DC\u05D5\u05D7");
|
|
11244
|
+
return;
|
|
11245
|
+
}
|
|
11178
11246
|
if (isSubtableFilterIncomplete) {
|
|
11179
11247
|
setTestFeedback("\u05D9\u05E9 \u05DC\u05D1\u05D7\u05D5\u05E8 \u05E2\u05E8\u05DA \u05DC\u05E1\u05D9\u05E0\u05D5\u05DF \u05D1\u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05D4\u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA");
|
|
11180
11248
|
return;
|
|
@@ -11516,6 +11584,8 @@ function useWhatsAppState(props) {
|
|
|
11516
11584
|
isTestDisabled,
|
|
11517
11585
|
sendButtonTitle,
|
|
11518
11586
|
testButtonTitle,
|
|
11587
|
+
requiresMediaHeader,
|
|
11588
|
+
isMediaMissing,
|
|
11519
11589
|
// Templates & Meta API
|
|
11520
11590
|
templates,
|
|
11521
11591
|
selectedTemplateId,
|
|
@@ -11526,6 +11596,8 @@ function useWhatsAppState(props) {
|
|
|
11526
11596
|
headerMediaUrl,
|
|
11527
11597
|
handleHeaderMediaUrlChange,
|
|
11528
11598
|
handleResetHeaderMediaUrl,
|
|
11599
|
+
isUploadingMedia,
|
|
11600
|
+
handleFileUpload,
|
|
11529
11601
|
templateVariables,
|
|
11530
11602
|
variableMapping,
|
|
11531
11603
|
textableColumnOptions,
|
|
@@ -11562,6 +11634,7 @@ function useWhatsAppState(props) {
|
|
|
11562
11634
|
}
|
|
11563
11635
|
|
|
11564
11636
|
// src/components/WhatsAppComponent/ui/TemplateSelectionBlock.tsx
|
|
11637
|
+
import { useRef as useRef13 } from "react";
|
|
11565
11638
|
import {
|
|
11566
11639
|
FileText as FileText3,
|
|
11567
11640
|
Trash2 as Trash23,
|
|
@@ -11573,7 +11646,10 @@ import {
|
|
|
11573
11646
|
Video as Video2,
|
|
11574
11647
|
Phone as Phone2,
|
|
11575
11648
|
Copy as Copy4,
|
|
11576
|
-
MessageSquare as MessageSquare2
|
|
11649
|
+
MessageSquare as MessageSquare2,
|
|
11650
|
+
Upload as Upload3,
|
|
11651
|
+
CheckCircle2 as CheckCircle23,
|
|
11652
|
+
AlertCircle as AlertCircle3
|
|
11577
11653
|
} from "lucide-react";
|
|
11578
11654
|
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
11579
11655
|
function TemplateSelectionBlock({
|
|
@@ -11597,8 +11673,11 @@ function TemplateSelectionBlock({
|
|
|
11597
11673
|
handleDeleteTemplate,
|
|
11598
11674
|
isDeleting,
|
|
11599
11675
|
setIsModalOpen,
|
|
11600
|
-
setFeedback
|
|
11676
|
+
setFeedback,
|
|
11677
|
+
isUploadingMedia = false,
|
|
11678
|
+
handleFileUpload
|
|
11601
11679
|
}) {
|
|
11680
|
+
const fileInputRef = useRef13(null);
|
|
11602
11681
|
return /* @__PURE__ */ jsxs14("div", { className: "col-span-12 lg:col-span-5 min-h-[26rem] h-full flex flex-col bg-slate-50/70 border border-slate-200 rounded-2xl p-3.5 relative", children: [
|
|
11603
11682
|
/* @__PURE__ */ jsxs14("div", { className: "space-y-1.5 shrink-0", children: [
|
|
11604
11683
|
/* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between pb-1.5 border-b border-slate-200/70 shrink-0 gap-2", children: [
|
|
@@ -11778,10 +11857,15 @@ function TemplateSelectionBlock({
|
|
|
11778
11857
|
})(),
|
|
11779
11858
|
templateHeaderComp && (() => {
|
|
11780
11859
|
const headerFormat = (templateHeaderComp.format || "").toUpperCase();
|
|
11860
|
+
if (headerFormat !== "IMAGE" && headerFormat !== "DOCUMENT" && headerFormat !== "VIDEO") {
|
|
11861
|
+
return null;
|
|
11862
|
+
}
|
|
11781
11863
|
const docFilename = resolveDocumentFilename(templateHeaderComp, headerMediaUrl);
|
|
11864
|
+
const hasValidMedia = Boolean(headerMediaUrl && headerMediaUrl.trim() && headerMediaUrl.startsWith("http"));
|
|
11865
|
+
const uploadButtonLabel = headerFormat === "DOCUMENT" ? "\u05D4\u05E2\u05DC\u05D4 \u05DE\u05E1\u05DE\u05DA" : headerFormat === "IMAGE" ? "\u05D4\u05E2\u05DC\u05D4 \u05EA\u05DE\u05D5\u05E0\u05D4" : "\u05D4\u05E2\u05DC\u05D4 \u05E7\u05D5\u05D1\u05E5";
|
|
11782
11866
|
return /* @__PURE__ */ jsxs14("div", { className: "p-2.5 bg-slate-50 border border-slate-200/90 rounded-xl flex items-center justify-between gap-3 shrink-0 shadow-2xs", children: [
|
|
11783
11867
|
/* @__PURE__ */ jsx15("div", { className: "flex items-center gap-2.5 overflow-hidden", children: headerFormat === "IMAGE" ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
11784
|
-
/* @__PURE__ */ jsx15("div", { className: "w-8 h-8 rounded-lg overflow-hidden border border-slate-200 shrink-0 bg-slate-100 flex items-center justify-center", children:
|
|
11868
|
+
/* @__PURE__ */ jsx15("div", { className: "w-8 h-8 rounded-lg overflow-hidden border border-slate-200 shrink-0 bg-slate-100 flex items-center justify-center", children: hasValidMedia ? /* @__PURE__ */ jsx15(
|
|
11785
11869
|
"img",
|
|
11786
11870
|
{
|
|
11787
11871
|
src: headerMediaUrl,
|
|
@@ -11791,26 +11875,33 @@ function TemplateSelectionBlock({
|
|
|
11791
11875
|
e.currentTarget.style.display = "none";
|
|
11792
11876
|
}
|
|
11793
11877
|
}
|
|
11794
|
-
) : /* @__PURE__ */ jsx15(ImageIcon2, { className: "w-4 h-4 text-
|
|
11878
|
+
) : /* @__PURE__ */ jsx15(ImageIcon2, { className: "w-4 h-4 text-amber-600" }) }),
|
|
11795
11879
|
/* @__PURE__ */ jsxs14("div", { className: "overflow-hidden", children: [
|
|
11796
11880
|
/* @__PURE__ */ jsx15("span", { className: "text-xs font-bold text-slate-800 block truncate", children: "\u05EA\u05DE\u05D5\u05E0\u05EA \u05DB\u05D5\u05EA\u05E8\u05EA" }),
|
|
11797
|
-
/* @__PURE__ */ jsx15("span", { className: "text-[10px] text-slate-400 block truncate", children: "\u05E7\u05D5\u05D1\u05E5 \u05DE\
|
|
11881
|
+
/* @__PURE__ */ jsx15("span", { className: "text-[10px] text-slate-400 block truncate", children: hasValidMedia ? "\u05E7\u05D5\u05D1\u05E5 \u05EA\u05DE\u05D5\u05E0\u05D4 \u05DE\u05E7\u05D5\u05E9\u05E8 \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA" : "\u05D8\u05E8\u05DD \u05D4\u05D5\u05E2\u05DC\u05D4 \u05E7\u05D5\u05D1\u05E5 \u05EA\u05DE\u05D5\u05E0\u05D4" })
|
|
11798
11882
|
] })
|
|
11799
11883
|
] }) : headerFormat === "DOCUMENT" ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
11800
|
-
/* @__PURE__ */ jsx15("div", { className:
|
|
11884
|
+
/* @__PURE__ */ jsx15("div", { className: `w-8 h-8 rounded-lg flex items-center justify-center shrink-0 border ${hasValidMedia ? "bg-rose-50 text-rose-600 border-rose-100" : "bg-slate-100 text-slate-400 border-slate-200"}`, children: /* @__PURE__ */ jsx15(FileText3, { className: "w-4 h-4" }) }),
|
|
11801
11885
|
/* @__PURE__ */ jsxs14("div", { className: "overflow-hidden", children: [
|
|
11802
11886
|
/* @__PURE__ */ jsx15("span", { className: "text-xs font-bold text-slate-800 block truncate", children: "\u05DE\u05E1\u05DE\u05DA \u05DB\u05D5\u05EA\u05E8\u05EA (PDF)" }),
|
|
11803
|
-
/* @__PURE__ */ jsx15("span", { className: "text-[10px] text-slate-500 font-mono block truncate", title: docFilename, children: docFilename })
|
|
11887
|
+
/* @__PURE__ */ jsx15("span", { className: "text-[10px] text-slate-500 font-mono block truncate", title: hasValidMedia ? docFilename : void 0, children: hasValidMedia ? docFilename : "\u05D8\u05E8\u05DD \u05D4\u05D5\u05E2\u05DC\u05D4 \u05E7\u05D5\u05D1\u05E5 \u05DE\u05E1\u05DE\u05DA" })
|
|
11804
11888
|
] })
|
|
11805
11889
|
] }) : /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
11806
|
-
/* @__PURE__ */ jsx15("div", { className:
|
|
11890
|
+
/* @__PURE__ */ jsx15("div", { className: `w-8 h-8 rounded-lg flex items-center justify-center shrink-0 border ${hasValidMedia ? "bg-indigo-50 text-indigo-600 border-indigo-100" : "bg-slate-100 text-slate-400 border-slate-200"}`, children: /* @__PURE__ */ jsx15(Video2, { className: "w-4 h-4" }) }),
|
|
11807
11891
|
/* @__PURE__ */ jsxs14("div", { className: "overflow-hidden", children: [
|
|
11808
11892
|
/* @__PURE__ */ jsx15("span", { className: "text-xs font-bold text-slate-800 block truncate", children: "\u05E1\u05E8\u05D8\u05D5\u05DF \u05DB\u05D5\u05EA\u05E8\u05EA" }),
|
|
11809
|
-
/* @__PURE__ */ jsx15("span", { className: "text-[10px] text-slate-400 block truncate", children: "\u05E7\u05D5\u05D1\u05E5 \u05D5\u05D9\u05D3\u05D0\u05D5 \u05DE\
|
|
11893
|
+
/* @__PURE__ */ jsx15("span", { className: "text-[10px] text-slate-400 block truncate", children: hasValidMedia ? "\u05E7\u05D5\u05D1\u05E5 \u05D5\u05D9\u05D3\u05D0\u05D5 \u05DE\u05E7\u05D5\u05E9\u05E8 \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA" : "\u05D8\u05E8\u05DD \u05D4\u05D5\u05E2\u05DC\u05D4 \u05E7\u05D5\u05D1\u05E5 \u05D5\u05D9\u05D3\u05D0\u05D5" })
|
|
11810
11894
|
] })
|
|
11811
11895
|
] }) }),
|
|
11812
|
-
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-
|
|
11813
|
-
|
|
11896
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2 shrink-0", children: [
|
|
11897
|
+
hasValidMedia ? /* @__PURE__ */ jsxs14("span", { className: "inline-flex items-center gap-1 text-[10px] font-medium text-emerald-800 px-2 py-0.5 bg-emerald-50 border border-emerald-200 rounded-lg", children: [
|
|
11898
|
+
/* @__PURE__ */ jsx15(CheckCircle23, { className: "w-3 h-3 text-emerald-600" }),
|
|
11899
|
+
"\u05E7\u05D5\u05D1\u05E5 \u05DE\u05E6\u05D5\u05E8\u05E3 \u05EA\u05E7\u05D9\u05DF"
|
|
11900
|
+
] }) : /* @__PURE__ */ jsxs14("span", { className: "inline-flex items-center gap-1 text-[10px] font-semibold text-amber-800 px-2 py-0.5 bg-amber-50 border border-amber-200 rounded-lg", children: [
|
|
11901
|
+
/* @__PURE__ */ jsx15(AlertCircle3, { className: "w-3 h-3 text-amber-600 shrink-0" }),
|
|
11902
|
+
"\u05E0\u05D3\u05E8\u05E9 \u05E6\u05D9\u05E8\u05D5\u05E3 \u05E7\u05D5\u05D1\u05E5 \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5"
|
|
11903
|
+
] }),
|
|
11904
|
+
hasValidMedia && /* @__PURE__ */ jsx15(
|
|
11814
11905
|
"a",
|
|
11815
11906
|
{
|
|
11816
11907
|
href: headerMediaUrl,
|
|
@@ -11821,7 +11912,44 @@ function TemplateSelectionBlock({
|
|
|
11821
11912
|
children: /* @__PURE__ */ jsx15(ExternalLink4, { className: "w-3.5 h-3.5" })
|
|
11822
11913
|
}
|
|
11823
11914
|
),
|
|
11824
|
-
/* @__PURE__ */ jsx15(
|
|
11915
|
+
/* @__PURE__ */ jsx15(
|
|
11916
|
+
"input",
|
|
11917
|
+
{
|
|
11918
|
+
ref: fileInputRef,
|
|
11919
|
+
type: "file",
|
|
11920
|
+
className: "hidden",
|
|
11921
|
+
accept: headerFormat === "DOCUMENT" ? ".pdf,application/pdf" : headerFormat === "VIDEO" ? "video/mp4,video/*" : "image/png,image/jpeg,image/jpg",
|
|
11922
|
+
onChange: (e) => {
|
|
11923
|
+
var _a;
|
|
11924
|
+
const file = (_a = e.target.files) == null ? void 0 : _a[0];
|
|
11925
|
+
if (file && handleFileUpload && (selectedTemplate == null ? void 0 : selectedTemplate.name)) {
|
|
11926
|
+
handleFileUpload(file, selectedTemplate.name);
|
|
11927
|
+
}
|
|
11928
|
+
e.target.value = "";
|
|
11929
|
+
},
|
|
11930
|
+
disabled: isUploadingMedia
|
|
11931
|
+
}
|
|
11932
|
+
),
|
|
11933
|
+
/* @__PURE__ */ jsx15(
|
|
11934
|
+
"button",
|
|
11935
|
+
{
|
|
11936
|
+
type: "button",
|
|
11937
|
+
disabled: isUploadingMedia,
|
|
11938
|
+
onClick: () => {
|
|
11939
|
+
var _a;
|
|
11940
|
+
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
11941
|
+
},
|
|
11942
|
+
className: `inline-flex items-center gap-1.5 px-2.5 py-1 text-[11px] font-medium rounded-lg transition-colors border shadow-2xs ${isUploadingMedia ? "bg-slate-100 text-slate-400 border-slate-200 cursor-not-allowed" : hasValidMedia ? "bg-white text-slate-700 hover:bg-slate-50 border-slate-200 hover:border-slate-300" : "bg-emerald-600 text-white hover:bg-emerald-700 border-emerald-600"}`,
|
|
11943
|
+
title: hasValidMedia ? "\u05D4\u05D7\u05DC\u05E3 \u05E7\u05D5\u05D1\u05E5 \u05DE\u05D3\u05D9\u05D4 \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5" : `${uploadButtonLabel} \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5`,
|
|
11944
|
+
children: isUploadingMedia ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
11945
|
+
/* @__PURE__ */ jsx15(Loader25, { className: "w-3.5 h-3.5 animate-spin" }),
|
|
11946
|
+
/* @__PURE__ */ jsx15("span", { children: "\u05DE\u05E2\u05DC\u05D4..." })
|
|
11947
|
+
] }) : /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
11948
|
+
/* @__PURE__ */ jsx15(Upload3, { className: "w-3.5 h-3.5" }),
|
|
11949
|
+
/* @__PURE__ */ jsx15("span", { children: hasValidMedia ? "\u05D4\u05D7\u05DC\u05E3 \u05E7\u05D5\u05D1\u05E5" : uploadButtonLabel })
|
|
11950
|
+
] })
|
|
11951
|
+
}
|
|
11952
|
+
)
|
|
11825
11953
|
] })
|
|
11826
11954
|
] });
|
|
11827
11955
|
})(),
|
|
@@ -12031,7 +12159,7 @@ import {
|
|
|
12031
12159
|
Users,
|
|
12032
12160
|
ChevronDown as ChevronDown5,
|
|
12033
12161
|
Loader2 as Loader26,
|
|
12034
|
-
AlertCircle as
|
|
12162
|
+
AlertCircle as AlertCircle4,
|
|
12035
12163
|
Send,
|
|
12036
12164
|
X as X11,
|
|
12037
12165
|
CheckSquare as CheckSquare2
|
|
@@ -12090,7 +12218,7 @@ function SettingsAndActionsBlock({
|
|
|
12090
12218
|
/* @__PURE__ */ jsx17(Loader26, { className: "w-4 h-4 animate-spin text-emerald-600 shrink-0" }),
|
|
12091
12219
|
/* @__PURE__ */ jsx17("span", { className: "font-medium text-[11px] text-slate-600", children: "\u05E1\u05D5\u05E8\u05E7 \u05E2\u05DE\u05D5\u05D3\u05D5\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05D8\u05D1\u05DC\u05D4 \u05D5\u05D1\u05D8\u05D1\u05DC\u05D0\u05D5\u05EA \u05DE\u05E7\u05D5\u05E9\u05E8\u05D5\u05EA..." })
|
|
12092
12220
|
] }) : targetPhoneOptions.length === 0 ? /* @__PURE__ */ jsxs16("div", { className: "p-2.5 bg-amber-50 border border-amber-200 rounded-xl text-amber-900 text-xs flex items-center gap-2 shadow-2xs", children: [
|
|
12093
|
-
/* @__PURE__ */ jsx17(
|
|
12221
|
+
/* @__PURE__ */ jsx17(AlertCircle4, { className: "w-4 h-4 text-amber-600 shrink-0" }),
|
|
12094
12222
|
/* @__PURE__ */ jsx17("span", { className: "font-semibold text-[11px]", children: "\u05DC\u05D0 \u05E0\u05DE\u05E6\u05D0\u05D4 \u05E2\u05DE\u05D5\u05D3\u05EA \u05D8\u05DC\u05E4\u05D5\u05DF \u05D1\u05D8\u05D1\u05DC\u05D4" })
|
|
12095
12223
|
] }) : targetPhoneOptions.length === 1 && targetPhoneOptions[0].type === "DIRECT" ? /* @__PURE__ */ jsxs16("div", { className: "space-y-1", children: [
|
|
12096
12224
|
/* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between", children: [
|
|
@@ -12534,7 +12662,7 @@ function WhatsAppComponent(props) {
|
|
|
12534
12662
|
className: `px-6 py-3 border-b text-xs flex items-center justify-between gap-3 ${state.feedback.type === "success" ? "bg-emerald-50 border-emerald-200 text-emerald-800" : "bg-rose-50 border-rose-200 text-rose-800"}`,
|
|
12535
12663
|
children: [
|
|
12536
12664
|
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
|
|
12537
|
-
state.feedback.type === "success" ? /* @__PURE__ */ jsx18(
|
|
12665
|
+
state.feedback.type === "success" ? /* @__PURE__ */ jsx18(CheckCircle24, { className: "w-4 h-4 text-emerald-600 shrink-0" }) : /* @__PURE__ */ jsx18(AlertCircle5, { className: "w-4 h-4 text-rose-600 shrink-0" }),
|
|
12538
12666
|
/* @__PURE__ */ jsx18("span", { children: state.feedback.message })
|
|
12539
12667
|
] }),
|
|
12540
12668
|
/* @__PURE__ */ jsx18(
|
|
@@ -12551,7 +12679,7 @@ function WhatsAppComponent(props) {
|
|
|
12551
12679
|
),
|
|
12552
12680
|
state.fetchError && !state.isLoadingTemplates && /* @__PURE__ */ jsxs17("div", { className: "px-6 py-3 bg-amber-50 border-b border-amber-200 text-xs text-amber-900 flex items-center justify-between", children: [
|
|
12553
12681
|
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
|
|
12554
|
-
/* @__PURE__ */ jsx18(
|
|
12682
|
+
/* @__PURE__ */ jsx18(AlertCircle5, { className: "w-4 h-4 text-amber-600 shrink-0" }),
|
|
12555
12683
|
/* @__PURE__ */ jsxs17("span", { children: [
|
|
12556
12684
|
"\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D8\u05E2\u05D9\u05E0\u05EA \u05EA\u05D1\u05E0\u05D9\u05D5\u05EA \u05DE-Meta: ",
|
|
12557
12685
|
state.fetchError
|
|
@@ -12592,7 +12720,9 @@ function WhatsAppComponent(props) {
|
|
|
12592
12720
|
handleDeleteTemplate: state.handleDeleteTemplate,
|
|
12593
12721
|
isDeleting: state.isDeleting,
|
|
12594
12722
|
setIsModalOpen: state.setIsModalOpen,
|
|
12595
|
-
setFeedback: state.setFeedback
|
|
12723
|
+
setFeedback: state.setFeedback,
|
|
12724
|
+
isUploadingMedia: state.isUploadingMedia,
|
|
12725
|
+
handleFileUpload: state.handleFileUpload
|
|
12596
12726
|
}
|
|
12597
12727
|
),
|
|
12598
12728
|
/* @__PURE__ */ jsx18(
|
|
@@ -12662,7 +12792,7 @@ function WhatsAppComponent(props) {
|
|
|
12662
12792
|
/* @__PURE__ */ jsx18(Loader27, { className: "w-6 h-6 animate-spin text-emerald-600" }),
|
|
12663
12793
|
/* @__PURE__ */ jsx18("span", { children: "\u05D8\u05D5\u05E2\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DE\u05D4\u05D8\u05D1\u05DC\u05D4..." })
|
|
12664
12794
|
] }) : state.tableError ? /* @__PURE__ */ jsxs17("div", { className: "flex-1 flex items-center justify-center p-6 text-center text-xs text-rose-600 bg-rose-50 gap-2", children: [
|
|
12665
|
-
/* @__PURE__ */ jsx18(
|
|
12795
|
+
/* @__PURE__ */ jsx18(AlertCircle5, { className: "w-4 h-4 text-rose-500 shrink-0" }),
|
|
12666
12796
|
/* @__PURE__ */ jsx18("span", { children: state.tableError })
|
|
12667
12797
|
] }) : !(settings == null ? void 0 : settings.tableMetaId) ? /* @__PURE__ */ jsx18("div", { className: "flex-1 flex items-center justify-center p-10 text-center text-xs text-slate-400", children: "\u05DC\u05D0 \u05E0\u05D1\u05D7\u05E8\u05D4 \u05D8\u05D1\u05DC\u05EA \u05DE\u05E7\u05D5\u05E8 \u05E2\u05D1\u05D5\u05E8 \u05E8\u05DB\u05D9\u05D1 WhatsApp \u05D6\u05D4" }) : /* @__PURE__ */ jsx18(
|
|
12668
12798
|
TableBlockClient,
|
|
@@ -12778,7 +12908,7 @@ function WhatsAppComponent(props) {
|
|
|
12778
12908
|
/* @__PURE__ */ jsx18("div", { className: "w-7 h-7 rounded-md bg-indigo-50 text-indigo-600 border border-indigo-100 flex items-center justify-center shrink-0", children: /* @__PURE__ */ jsx18(Video3, { className: "w-3.5 h-3.5" }) }),
|
|
12779
12909
|
/* @__PURE__ */ jsx18("span", { className: "font-semibold text-slate-800 truncate", children: "\u05E1\u05E8\u05D8\u05D5\u05DF \u05DB\u05D5\u05EA\u05E8\u05EA" })
|
|
12780
12910
|
] }) }),
|
|
12781
|
-
/* @__PURE__ */ jsx18("span", { className: "text-[10px] text-emerald-700 bg-emerald-50 border border-emerald-200 px-1.5 py-0.5 rounded font-medium shrink-0", children: "\u05DE\u05E6\u05D5\u05E8\u05E3 \
|
|
12911
|
+
state.headerMediaUrl && state.headerMediaUrl.startsWith("http") ? /* @__PURE__ */ jsx18("span", { className: "text-[10px] text-emerald-700 bg-emerald-50 border border-emerald-200 px-1.5 py-0.5 rounded font-medium shrink-0", children: "\u05E7\u05D5\u05D1\u05E5 \u05DE\u05E6\u05D5\u05E8\u05E3 \u05EA\u05E7\u05D9\u05DF" }) : /* @__PURE__ */ jsx18("span", { className: "text-[10px] text-amber-700 bg-amber-50 border border-amber-200 px-1.5 py-0.5 rounded font-medium shrink-0", children: "\u05E0\u05D3\u05E8\u05E9 \u05E6\u05D9\u05E8\u05D5\u05E3 \u05E7\u05D5\u05D1\u05E5 \u05DC\u05EA\u05D1\u05E0\u05D9\u05EA \u05D6\u05D5" })
|
|
12782
12912
|
] });
|
|
12783
12913
|
})(),
|
|
12784
12914
|
/* @__PURE__ */ jsxs17("div", { className: "space-y-1.5", children: [
|
|
@@ -12814,7 +12944,7 @@ function WhatsAppComponent(props) {
|
|
|
12814
12944
|
/* @__PURE__ */ jsx18("p", { className: "text-[11px] text-slate-500 leading-normal", children: "\u05D4\u05D5\u05D3\u05E2\u05EA \u05D4\u05D1\u05D3\u05D9\u05E7\u05D4 \u05EA\u05D9\u05E9\u05DC\u05D7 \u05D9\u05E9\u05D9\u05E8\u05D5\u05EA \u05DC\u05DE\u05E1\u05E4\u05E8 \u05D6\u05D4 \u05DC\u05E6\u05D5\u05E8\u05DA \u05D5\u05D9\u05D3\u05D5\u05D0 \u05EA\u05E7\u05D9\u05E0\u05D5\u05EA \u05EA\u05D5\u05DB\u05DF \u05D4\u05D4\u05D5\u05D3\u05E2\u05D4 \u05D5\u05D4\u05E2\u05D9\u05E6\u05D5\u05D1." })
|
|
12815
12945
|
] }),
|
|
12816
12946
|
state.testFeedback && /* @__PURE__ */ jsxs17("div", { className: "p-2.5 bg-rose-50 border border-rose-200 rounded-xl text-xs text-rose-700 flex items-center gap-2", children: [
|
|
12817
|
-
/* @__PURE__ */ jsx18(
|
|
12947
|
+
/* @__PURE__ */ jsx18(AlertCircle5, { className: "w-4 h-4 text-rose-500 shrink-0" }),
|
|
12818
12948
|
/* @__PURE__ */ jsx18("span", { children: state.testFeedback })
|
|
12819
12949
|
] })
|
|
12820
12950
|
] }),
|
|
@@ -12837,9 +12967,10 @@ function WhatsAppComponent(props) {
|
|
|
12837
12967
|
"button",
|
|
12838
12968
|
{
|
|
12839
12969
|
type: "button",
|
|
12840
|
-
disabled: !state.testPhoneNumber.trim() || state.isSendingTest,
|
|
12970
|
+
disabled: !state.testPhoneNumber.trim() || state.isSendingTest || state.isTestDisabled,
|
|
12841
12971
|
onClick: state.handleSendTest,
|
|
12842
|
-
|
|
12972
|
+
title: state.testButtonTitle,
|
|
12973
|
+
className: `px-4 py-2 text-xs font-bold rounded-xl transition-all flex items-center gap-1.5 ${!state.testPhoneNumber.trim() || state.isSendingTest || state.isTestDisabled ? "bg-emerald-600/40 text-white/70 cursor-not-allowed" : "bg-emerald-600 hover:bg-emerald-700 active:scale-[0.98] text-white shadow-xs cursor-pointer"}`,
|
|
12843
12974
|
children: state.isSendingTest ? /* @__PURE__ */ jsxs17(Fragment7, { children: [
|
|
12844
12975
|
/* @__PURE__ */ jsx18(Loader27, { className: "w-3.5 h-3.5 animate-spin" }),
|
|
12845
12976
|
/* @__PURE__ */ jsx18("span", { children: "\u05E9\u05D5\u05DC\u05D7..." })
|
package/dist/phone.d.mts
CHANGED
|
@@ -35,10 +35,14 @@ declare function isValidPhoneNumber(phone: string): boolean;
|
|
|
35
35
|
*/
|
|
36
36
|
declare function generateWhatsAppLink(phone: string, defaultCountryCode?: string): string | null;
|
|
37
37
|
/**
|
|
38
|
-
* Normalizes a phone number for WhatsApp sending (
|
|
39
|
-
* -
|
|
40
|
-
* -
|
|
41
|
-
* -
|
|
38
|
+
* Normalizes a phone number for WhatsApp sending (Meta international format without leading '+').
|
|
39
|
+
* - Returns empty string if input is falsy.
|
|
40
|
+
* - Trims input and removes leading '+' if it exists.
|
|
41
|
+
* - Strips all non-digit characters.
|
|
42
|
+
* - If starting with '972', returns it as is.
|
|
43
|
+
* - If starting with '0' (Israeli mobile/landline), strips '0' and prepends '972'.
|
|
44
|
+
* - If exactly 9 digits long (omitted leading zero), prepends '972'.
|
|
45
|
+
* - Returns the processed digits string.
|
|
42
46
|
*/
|
|
43
47
|
declare function normalizePhoneForWhatsApp(phone: string): string;
|
|
44
48
|
|
package/dist/phone.d.ts
CHANGED
|
@@ -35,10 +35,14 @@ declare function isValidPhoneNumber(phone: string): boolean;
|
|
|
35
35
|
*/
|
|
36
36
|
declare function generateWhatsAppLink(phone: string, defaultCountryCode?: string): string | null;
|
|
37
37
|
/**
|
|
38
|
-
* Normalizes a phone number for WhatsApp sending (
|
|
39
|
-
* -
|
|
40
|
-
* -
|
|
41
|
-
* -
|
|
38
|
+
* Normalizes a phone number for WhatsApp sending (Meta international format without leading '+').
|
|
39
|
+
* - Returns empty string if input is falsy.
|
|
40
|
+
* - Trims input and removes leading '+' if it exists.
|
|
41
|
+
* - Strips all non-digit characters.
|
|
42
|
+
* - If starting with '972', returns it as is.
|
|
43
|
+
* - If starting with '0' (Israeli mobile/landline), strips '0' and prepends '972'.
|
|
44
|
+
* - If exactly 9 digits long (omitted leading zero), prepends '972'.
|
|
45
|
+
* - Returns the processed digits string.
|
|
42
46
|
*/
|
|
43
47
|
declare function normalizePhoneForWhatsApp(phone: string): string;
|
|
44
48
|
|
package/dist/phone.js
CHANGED
|
@@ -88,9 +88,15 @@ function normalizePhoneForWhatsApp(phone) {
|
|
|
88
88
|
cleaned = cleaned.substring(1);
|
|
89
89
|
}
|
|
90
90
|
const digitsOnly = cleaned.replace(/\D/g, "");
|
|
91
|
-
if (digitsOnly.startsWith("
|
|
91
|
+
if (digitsOnly.startsWith("972")) {
|
|
92
|
+
return digitsOnly;
|
|
93
|
+
}
|
|
94
|
+
if (digitsOnly.startsWith("0")) {
|
|
92
95
|
return `972${digitsOnly.substring(1)}`;
|
|
93
96
|
}
|
|
97
|
+
if (digitsOnly.length === 9) {
|
|
98
|
+
return `972${digitsOnly}`;
|
|
99
|
+
}
|
|
94
100
|
return digitsOnly;
|
|
95
101
|
}
|
|
96
102
|
// Annotate the CommonJS export names for ESM import in node:
|
package/dist/phone.mjs
CHANGED
|
@@ -57,9 +57,15 @@ function normalizePhoneForWhatsApp(phone) {
|
|
|
57
57
|
cleaned = cleaned.substring(1);
|
|
58
58
|
}
|
|
59
59
|
const digitsOnly = cleaned.replace(/\D/g, "");
|
|
60
|
-
if (digitsOnly.startsWith("
|
|
60
|
+
if (digitsOnly.startsWith("972")) {
|
|
61
|
+
return digitsOnly;
|
|
62
|
+
}
|
|
63
|
+
if (digitsOnly.startsWith("0")) {
|
|
61
64
|
return `972${digitsOnly.substring(1)}`;
|
|
62
65
|
}
|
|
66
|
+
if (digitsOnly.length === 9) {
|
|
67
|
+
return `972${digitsOnly}`;
|
|
68
|
+
}
|
|
63
69
|
return digitsOnly;
|
|
64
70
|
}
|
|
65
71
|
export {
|