@universe-platform/ui 0.1.0-beta.21 → 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 +205 -67
- package/dist/index.mjs +216 -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 = {
|
|
@@ -10000,6 +10019,10 @@ function buildWhatsAppPayload(to, templateName, languageCode, components) {
|
|
|
10000
10019
|
}
|
|
10001
10020
|
async function sendWhatsAppMessage(payload, executeAction, orgId) {
|
|
10002
10021
|
try {
|
|
10022
|
+
console.log(
|
|
10023
|
+
"[whatsappApi] Dispatching WhatsApp message action with payload:",
|
|
10024
|
+
JSON.stringify(payload, null, 2)
|
|
10025
|
+
);
|
|
10003
10026
|
const actionPayload = {
|
|
10004
10027
|
payload
|
|
10005
10028
|
};
|
|
@@ -10009,12 +10032,18 @@ async function sendWhatsAppMessage(payload, executeAction, orgId) {
|
|
|
10009
10032
|
}
|
|
10010
10033
|
const result = await executeAction("SEND_WHATSAPP_MESSAGE", actionPayload);
|
|
10011
10034
|
if (result && result.success === false) {
|
|
10035
|
+
console.error(
|
|
10036
|
+
"[whatsappApi] SEND_WHATSAPP_MESSAGE dispatch failed:",
|
|
10037
|
+
result.error,
|
|
10038
|
+
result.details || result
|
|
10039
|
+
);
|
|
10012
10040
|
return {
|
|
10013
10041
|
success: false,
|
|
10014
10042
|
error: result.error || "\u05E9\u05DC\u05D9\u05D7\u05EA \u05D4\u05D5\u05D3\u05E2\u05EA WhatsApp \u05E0\u05DB\u05E9\u05DC\u05D4",
|
|
10015
10043
|
data: result
|
|
10016
10044
|
};
|
|
10017
10045
|
}
|
|
10046
|
+
console.log("[whatsappApi] SEND_WHATSAPP_MESSAGE dispatch succeeded:", result);
|
|
10018
10047
|
return {
|
|
10019
10048
|
success: true,
|
|
10020
10049
|
data: result
|
|
@@ -11123,6 +11152,48 @@ function useWhatsAppState(props) {
|
|
|
11123
11152
|
);
|
|
11124
11153
|
setHeaderMediaUrl(defaultUrl || "");
|
|
11125
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
|
+
);
|
|
11126
11197
|
const templateVariables = (0, import_react17.useMemo)(() => {
|
|
11127
11198
|
return extractTemplateVariables(selectedTemplate);
|
|
11128
11199
|
}, [selectedTemplate]);
|
|
@@ -11240,13 +11311,20 @@ function useWhatsAppState(props) {
|
|
|
11240
11311
|
const isTemplateValid = Boolean(
|
|
11241
11312
|
selectedTemplate && getStatusConfig(selectedTemplate.status).isSelectable
|
|
11242
11313
|
);
|
|
11243
|
-
const
|
|
11244
|
-
const
|
|
11245
|
-
const
|
|
11246
|
-
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";
|
|
11247
11321
|
const handleSendTest = async () => {
|
|
11248
11322
|
var _a2;
|
|
11249
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
|
+
}
|
|
11250
11328
|
if (isSubtableFilterIncomplete) {
|
|
11251
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");
|
|
11252
11330
|
return;
|
|
@@ -11588,6 +11666,8 @@ function useWhatsAppState(props) {
|
|
|
11588
11666
|
isTestDisabled,
|
|
11589
11667
|
sendButtonTitle,
|
|
11590
11668
|
testButtonTitle,
|
|
11669
|
+
requiresMediaHeader,
|
|
11670
|
+
isMediaMissing,
|
|
11591
11671
|
// Templates & Meta API
|
|
11592
11672
|
templates,
|
|
11593
11673
|
selectedTemplateId,
|
|
@@ -11598,6 +11678,8 @@ function useWhatsAppState(props) {
|
|
|
11598
11678
|
headerMediaUrl,
|
|
11599
11679
|
handleHeaderMediaUrlChange,
|
|
11600
11680
|
handleResetHeaderMediaUrl,
|
|
11681
|
+
isUploadingMedia,
|
|
11682
|
+
handleFileUpload,
|
|
11601
11683
|
templateVariables,
|
|
11602
11684
|
variableMapping,
|
|
11603
11685
|
textableColumnOptions,
|
|
@@ -11634,6 +11716,7 @@ function useWhatsAppState(props) {
|
|
|
11634
11716
|
}
|
|
11635
11717
|
|
|
11636
11718
|
// src/components/WhatsAppComponent/ui/TemplateSelectionBlock.tsx
|
|
11719
|
+
var import_react18 = require("react");
|
|
11637
11720
|
var import_lucide_react11 = require("lucide-react");
|
|
11638
11721
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
11639
11722
|
function TemplateSelectionBlock({
|
|
@@ -11657,8 +11740,11 @@ function TemplateSelectionBlock({
|
|
|
11657
11740
|
handleDeleteTemplate,
|
|
11658
11741
|
isDeleting,
|
|
11659
11742
|
setIsModalOpen,
|
|
11660
|
-
setFeedback
|
|
11743
|
+
setFeedback,
|
|
11744
|
+
isUploadingMedia = false,
|
|
11745
|
+
handleFileUpload
|
|
11661
11746
|
}) {
|
|
11747
|
+
const fileInputRef = (0, import_react18.useRef)(null);
|
|
11662
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: [
|
|
11663
11749
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "space-y-1.5 shrink-0", children: [
|
|
11664
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: [
|
|
@@ -11838,10 +11924,15 @@ function TemplateSelectionBlock({
|
|
|
11838
11924
|
})(),
|
|
11839
11925
|
templateHeaderComp && (() => {
|
|
11840
11926
|
const headerFormat = (templateHeaderComp.format || "").toUpperCase();
|
|
11927
|
+
if (headerFormat !== "IMAGE" && headerFormat !== "DOCUMENT" && headerFormat !== "VIDEO") {
|
|
11928
|
+
return null;
|
|
11929
|
+
}
|
|
11841
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";
|
|
11842
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: [
|
|
11843
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: [
|
|
11844
|
-
/* @__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)(
|
|
11845
11936
|
"img",
|
|
11846
11937
|
{
|
|
11847
11938
|
src: headerMediaUrl,
|
|
@@ -11851,26 +11942,33 @@ function TemplateSelectionBlock({
|
|
|
11851
11942
|
e.currentTarget.style.display = "none";
|
|
11852
11943
|
}
|
|
11853
11944
|
}
|
|
11854
|
-
) : /* @__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" }) }),
|
|
11855
11946
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "overflow-hidden", children: [
|
|
11856
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" }),
|
|
11857
|
-
/* @__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" })
|
|
11858
11949
|
] })
|
|
11859
11950
|
] }) : headerFormat === "DOCUMENT" ? /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
11860
|
-
/* @__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" }) }),
|
|
11861
11952
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "overflow-hidden", children: [
|
|
11862
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)" }),
|
|
11863
|
-
/* @__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" })
|
|
11864
11955
|
] })
|
|
11865
11956
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(import_jsx_runtime15.Fragment, { children: [
|
|
11866
|
-
/* @__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" }) }),
|
|
11867
11958
|
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "overflow-hidden", children: [
|
|
11868
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" }),
|
|
11869
|
-
/* @__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" })
|
|
11870
11961
|
] })
|
|
11871
11962
|
] }) }),
|
|
11872
|
-
/* @__PURE__ */ (0, import_jsx_runtime15.jsxs)("div", { className: "flex items-center gap-
|
|
11873
|
-
|
|
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)(
|
|
11874
11972
|
"a",
|
|
11875
11973
|
{
|
|
11876
11974
|
href: headerMediaUrl,
|
|
@@ -11881,7 +11979,44 @@ function TemplateSelectionBlock({
|
|
|
11881
11979
|
children: /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_lucide_react11.ExternalLink, { className: "w-3.5 h-3.5" })
|
|
11882
11980
|
}
|
|
11883
11981
|
),
|
|
11884
|
-
/* @__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
|
+
)
|
|
11885
12020
|
] })
|
|
11886
12021
|
] });
|
|
11887
12022
|
})(),
|
|
@@ -12637,7 +12772,9 @@ function WhatsAppComponent(props) {
|
|
|
12637
12772
|
handleDeleteTemplate: state.handleDeleteTemplate,
|
|
12638
12773
|
isDeleting: state.isDeleting,
|
|
12639
12774
|
setIsModalOpen: state.setIsModalOpen,
|
|
12640
|
-
setFeedback: state.setFeedback
|
|
12775
|
+
setFeedback: state.setFeedback,
|
|
12776
|
+
isUploadingMedia: state.isUploadingMedia,
|
|
12777
|
+
handleFileUpload: state.handleFileUpload
|
|
12641
12778
|
}
|
|
12642
12779
|
),
|
|
12643
12780
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
@@ -12823,7 +12960,7 @@ function WhatsAppComponent(props) {
|
|
|
12823
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" }) }),
|
|
12824
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" })
|
|
12825
12962
|
] }) }),
|
|
12826
|
-
/* @__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" })
|
|
12827
12964
|
] });
|
|
12828
12965
|
})(),
|
|
12829
12966
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "space-y-1.5", children: [
|
|
@@ -12882,9 +13019,10 @@ function WhatsAppComponent(props) {
|
|
|
12882
13019
|
"button",
|
|
12883
13020
|
{
|
|
12884
13021
|
type: "button",
|
|
12885
|
-
disabled: !state.testPhoneNumber.trim() || state.isSendingTest,
|
|
13022
|
+
disabled: !state.testPhoneNumber.trim() || state.isSendingTest || state.isTestDisabled,
|
|
12886
13023
|
onClick: state.handleSendTest,
|
|
12887
|
-
|
|
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"}`,
|
|
12888
13026
|
children: state.isSendingTest ? /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
12889
13027
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(import_lucide_react14.Loader2, { className: "w-3.5 h-3.5 animate-spin" }),
|
|
12890
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 = {
|
|
@@ -9918,6 +9937,10 @@ function buildWhatsAppPayload(to, templateName, languageCode, components) {
|
|
|
9918
9937
|
}
|
|
9919
9938
|
async function sendWhatsAppMessage(payload, executeAction, orgId) {
|
|
9920
9939
|
try {
|
|
9940
|
+
console.log(
|
|
9941
|
+
"[whatsappApi] Dispatching WhatsApp message action with payload:",
|
|
9942
|
+
JSON.stringify(payload, null, 2)
|
|
9943
|
+
);
|
|
9921
9944
|
const actionPayload = {
|
|
9922
9945
|
payload
|
|
9923
9946
|
};
|
|
@@ -9927,12 +9950,18 @@ async function sendWhatsAppMessage(payload, executeAction, orgId) {
|
|
|
9927
9950
|
}
|
|
9928
9951
|
const result = await executeAction("SEND_WHATSAPP_MESSAGE", actionPayload);
|
|
9929
9952
|
if (result && result.success === false) {
|
|
9953
|
+
console.error(
|
|
9954
|
+
"[whatsappApi] SEND_WHATSAPP_MESSAGE dispatch failed:",
|
|
9955
|
+
result.error,
|
|
9956
|
+
result.details || result
|
|
9957
|
+
);
|
|
9930
9958
|
return {
|
|
9931
9959
|
success: false,
|
|
9932
9960
|
error: result.error || "\u05E9\u05DC\u05D9\u05D7\u05EA \u05D4\u05D5\u05D3\u05E2\u05EA WhatsApp \u05E0\u05DB\u05E9\u05DC\u05D4",
|
|
9933
9961
|
data: result
|
|
9934
9962
|
};
|
|
9935
9963
|
}
|
|
9964
|
+
console.log("[whatsappApi] SEND_WHATSAPP_MESSAGE dispatch succeeded:", result);
|
|
9936
9965
|
return {
|
|
9937
9966
|
success: true,
|
|
9938
9967
|
data: result
|
|
@@ -11041,6 +11070,48 @@ function useWhatsAppState(props) {
|
|
|
11041
11070
|
);
|
|
11042
11071
|
setHeaderMediaUrl(defaultUrl || "");
|
|
11043
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
|
+
);
|
|
11044
11115
|
const templateVariables = useMemo8(() => {
|
|
11045
11116
|
return extractTemplateVariables(selectedTemplate);
|
|
11046
11117
|
}, [selectedTemplate]);
|
|
@@ -11158,13 +11229,20 @@ function useWhatsAppState(props) {
|
|
|
11158
11229
|
const isTemplateValid = Boolean(
|
|
11159
11230
|
selectedTemplate && getStatusConfig(selectedTemplate.status).isSelectable
|
|
11160
11231
|
);
|
|
11161
|
-
const
|
|
11162
|
-
const
|
|
11163
|
-
const
|
|
11164
|
-
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";
|
|
11165
11239
|
const handleSendTest = async () => {
|
|
11166
11240
|
var _a2;
|
|
11167
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
|
+
}
|
|
11168
11246
|
if (isSubtableFilterIncomplete) {
|
|
11169
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");
|
|
11170
11248
|
return;
|
|
@@ -11506,6 +11584,8 @@ function useWhatsAppState(props) {
|
|
|
11506
11584
|
isTestDisabled,
|
|
11507
11585
|
sendButtonTitle,
|
|
11508
11586
|
testButtonTitle,
|
|
11587
|
+
requiresMediaHeader,
|
|
11588
|
+
isMediaMissing,
|
|
11509
11589
|
// Templates & Meta API
|
|
11510
11590
|
templates,
|
|
11511
11591
|
selectedTemplateId,
|
|
@@ -11516,6 +11596,8 @@ function useWhatsAppState(props) {
|
|
|
11516
11596
|
headerMediaUrl,
|
|
11517
11597
|
handleHeaderMediaUrlChange,
|
|
11518
11598
|
handleResetHeaderMediaUrl,
|
|
11599
|
+
isUploadingMedia,
|
|
11600
|
+
handleFileUpload,
|
|
11519
11601
|
templateVariables,
|
|
11520
11602
|
variableMapping,
|
|
11521
11603
|
textableColumnOptions,
|
|
@@ -11552,6 +11634,7 @@ function useWhatsAppState(props) {
|
|
|
11552
11634
|
}
|
|
11553
11635
|
|
|
11554
11636
|
// src/components/WhatsAppComponent/ui/TemplateSelectionBlock.tsx
|
|
11637
|
+
import { useRef as useRef13 } from "react";
|
|
11555
11638
|
import {
|
|
11556
11639
|
FileText as FileText3,
|
|
11557
11640
|
Trash2 as Trash23,
|
|
@@ -11563,7 +11646,10 @@ import {
|
|
|
11563
11646
|
Video as Video2,
|
|
11564
11647
|
Phone as Phone2,
|
|
11565
11648
|
Copy as Copy4,
|
|
11566
|
-
MessageSquare as MessageSquare2
|
|
11649
|
+
MessageSquare as MessageSquare2,
|
|
11650
|
+
Upload as Upload3,
|
|
11651
|
+
CheckCircle2 as CheckCircle23,
|
|
11652
|
+
AlertCircle as AlertCircle3
|
|
11567
11653
|
} from "lucide-react";
|
|
11568
11654
|
import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
11569
11655
|
function TemplateSelectionBlock({
|
|
@@ -11587,8 +11673,11 @@ function TemplateSelectionBlock({
|
|
|
11587
11673
|
handleDeleteTemplate,
|
|
11588
11674
|
isDeleting,
|
|
11589
11675
|
setIsModalOpen,
|
|
11590
|
-
setFeedback
|
|
11676
|
+
setFeedback,
|
|
11677
|
+
isUploadingMedia = false,
|
|
11678
|
+
handleFileUpload
|
|
11591
11679
|
}) {
|
|
11680
|
+
const fileInputRef = useRef13(null);
|
|
11592
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: [
|
|
11593
11682
|
/* @__PURE__ */ jsxs14("div", { className: "space-y-1.5 shrink-0", children: [
|
|
11594
11683
|
/* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between pb-1.5 border-b border-slate-200/70 shrink-0 gap-2", children: [
|
|
@@ -11768,10 +11857,15 @@ function TemplateSelectionBlock({
|
|
|
11768
11857
|
})(),
|
|
11769
11858
|
templateHeaderComp && (() => {
|
|
11770
11859
|
const headerFormat = (templateHeaderComp.format || "").toUpperCase();
|
|
11860
|
+
if (headerFormat !== "IMAGE" && headerFormat !== "DOCUMENT" && headerFormat !== "VIDEO") {
|
|
11861
|
+
return null;
|
|
11862
|
+
}
|
|
11771
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";
|
|
11772
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: [
|
|
11773
11867
|
/* @__PURE__ */ jsx15("div", { className: "flex items-center gap-2.5 overflow-hidden", children: headerFormat === "IMAGE" ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
11774
|
-
/* @__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(
|
|
11775
11869
|
"img",
|
|
11776
11870
|
{
|
|
11777
11871
|
src: headerMediaUrl,
|
|
@@ -11781,26 +11875,33 @@ function TemplateSelectionBlock({
|
|
|
11781
11875
|
e.currentTarget.style.display = "none";
|
|
11782
11876
|
}
|
|
11783
11877
|
}
|
|
11784
|
-
) : /* @__PURE__ */ jsx15(ImageIcon2, { className: "w-4 h-4 text-
|
|
11878
|
+
) : /* @__PURE__ */ jsx15(ImageIcon2, { className: "w-4 h-4 text-amber-600" }) }),
|
|
11785
11879
|
/* @__PURE__ */ jsxs14("div", { className: "overflow-hidden", children: [
|
|
11786
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" }),
|
|
11787
|
-
/* @__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" })
|
|
11788
11882
|
] })
|
|
11789
11883
|
] }) : headerFormat === "DOCUMENT" ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
11790
|
-
/* @__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" }) }),
|
|
11791
11885
|
/* @__PURE__ */ jsxs14("div", { className: "overflow-hidden", children: [
|
|
11792
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)" }),
|
|
11793
|
-
/* @__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" })
|
|
11794
11888
|
] })
|
|
11795
11889
|
] }) : /* @__PURE__ */ jsxs14(Fragment4, { children: [
|
|
11796
|
-
/* @__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" }) }),
|
|
11797
11891
|
/* @__PURE__ */ jsxs14("div", { className: "overflow-hidden", children: [
|
|
11798
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" }),
|
|
11799
|
-
/* @__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" })
|
|
11800
11894
|
] })
|
|
11801
11895
|
] }) }),
|
|
11802
|
-
/* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-
|
|
11803
|
-
|
|
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(
|
|
11804
11905
|
"a",
|
|
11805
11906
|
{
|
|
11806
11907
|
href: headerMediaUrl,
|
|
@@ -11811,7 +11912,44 @@ function TemplateSelectionBlock({
|
|
|
11811
11912
|
children: /* @__PURE__ */ jsx15(ExternalLink4, { className: "w-3.5 h-3.5" })
|
|
11812
11913
|
}
|
|
11813
11914
|
),
|
|
11814
|
-
/* @__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
|
+
)
|
|
11815
11953
|
] })
|
|
11816
11954
|
] });
|
|
11817
11955
|
})(),
|
|
@@ -12021,7 +12159,7 @@ import {
|
|
|
12021
12159
|
Users,
|
|
12022
12160
|
ChevronDown as ChevronDown5,
|
|
12023
12161
|
Loader2 as Loader26,
|
|
12024
|
-
AlertCircle as
|
|
12162
|
+
AlertCircle as AlertCircle4,
|
|
12025
12163
|
Send,
|
|
12026
12164
|
X as X11,
|
|
12027
12165
|
CheckSquare as CheckSquare2
|
|
@@ -12080,7 +12218,7 @@ function SettingsAndActionsBlock({
|
|
|
12080
12218
|
/* @__PURE__ */ jsx17(Loader26, { className: "w-4 h-4 animate-spin text-emerald-600 shrink-0" }),
|
|
12081
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..." })
|
|
12082
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: [
|
|
12083
|
-
/* @__PURE__ */ jsx17(
|
|
12221
|
+
/* @__PURE__ */ jsx17(AlertCircle4, { className: "w-4 h-4 text-amber-600 shrink-0" }),
|
|
12084
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" })
|
|
12085
12223
|
] }) : targetPhoneOptions.length === 1 && targetPhoneOptions[0].type === "DIRECT" ? /* @__PURE__ */ jsxs16("div", { className: "space-y-1", children: [
|
|
12086
12224
|
/* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between", children: [
|
|
@@ -12524,7 +12662,7 @@ function WhatsAppComponent(props) {
|
|
|
12524
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"}`,
|
|
12525
12663
|
children: [
|
|
12526
12664
|
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
|
|
12527
|
-
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" }),
|
|
12528
12666
|
/* @__PURE__ */ jsx18("span", { children: state.feedback.message })
|
|
12529
12667
|
] }),
|
|
12530
12668
|
/* @__PURE__ */ jsx18(
|
|
@@ -12541,7 +12679,7 @@ function WhatsAppComponent(props) {
|
|
|
12541
12679
|
),
|
|
12542
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: [
|
|
12543
12681
|
/* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2", children: [
|
|
12544
|
-
/* @__PURE__ */ jsx18(
|
|
12682
|
+
/* @__PURE__ */ jsx18(AlertCircle5, { className: "w-4 h-4 text-amber-600 shrink-0" }),
|
|
12545
12683
|
/* @__PURE__ */ jsxs17("span", { children: [
|
|
12546
12684
|
"\u05E9\u05D2\u05D9\u05D0\u05D4 \u05D1\u05D8\u05E2\u05D9\u05E0\u05EA \u05EA\u05D1\u05E0\u05D9\u05D5\u05EA \u05DE-Meta: ",
|
|
12547
12685
|
state.fetchError
|
|
@@ -12582,7 +12720,9 @@ function WhatsAppComponent(props) {
|
|
|
12582
12720
|
handleDeleteTemplate: state.handleDeleteTemplate,
|
|
12583
12721
|
isDeleting: state.isDeleting,
|
|
12584
12722
|
setIsModalOpen: state.setIsModalOpen,
|
|
12585
|
-
setFeedback: state.setFeedback
|
|
12723
|
+
setFeedback: state.setFeedback,
|
|
12724
|
+
isUploadingMedia: state.isUploadingMedia,
|
|
12725
|
+
handleFileUpload: state.handleFileUpload
|
|
12586
12726
|
}
|
|
12587
12727
|
),
|
|
12588
12728
|
/* @__PURE__ */ jsx18(
|
|
@@ -12652,7 +12792,7 @@ function WhatsAppComponent(props) {
|
|
|
12652
12792
|
/* @__PURE__ */ jsx18(Loader27, { className: "w-6 h-6 animate-spin text-emerald-600" }),
|
|
12653
12793
|
/* @__PURE__ */ jsx18("span", { children: "\u05D8\u05D5\u05E2\u05DF \u05E8\u05E9\u05D5\u05DE\u05D5\u05EA \u05DE\u05D4\u05D8\u05D1\u05DC\u05D4..." })
|
|
12654
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: [
|
|
12655
|
-
/* @__PURE__ */ jsx18(
|
|
12795
|
+
/* @__PURE__ */ jsx18(AlertCircle5, { className: "w-4 h-4 text-rose-500 shrink-0" }),
|
|
12656
12796
|
/* @__PURE__ */ jsx18("span", { children: state.tableError })
|
|
12657
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(
|
|
12658
12798
|
TableBlockClient,
|
|
@@ -12768,7 +12908,7 @@ function WhatsAppComponent(props) {
|
|
|
12768
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" }) }),
|
|
12769
12909
|
/* @__PURE__ */ jsx18("span", { className: "font-semibold text-slate-800 truncate", children: "\u05E1\u05E8\u05D8\u05D5\u05DF \u05DB\u05D5\u05EA\u05E8\u05EA" })
|
|
12770
12910
|
] }) }),
|
|
12771
|
-
/* @__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" })
|
|
12772
12912
|
] });
|
|
12773
12913
|
})(),
|
|
12774
12914
|
/* @__PURE__ */ jsxs17("div", { className: "space-y-1.5", children: [
|
|
@@ -12804,7 +12944,7 @@ function WhatsAppComponent(props) {
|
|
|
12804
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." })
|
|
12805
12945
|
] }),
|
|
12806
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: [
|
|
12807
|
-
/* @__PURE__ */ jsx18(
|
|
12947
|
+
/* @__PURE__ */ jsx18(AlertCircle5, { className: "w-4 h-4 text-rose-500 shrink-0" }),
|
|
12808
12948
|
/* @__PURE__ */ jsx18("span", { children: state.testFeedback })
|
|
12809
12949
|
] })
|
|
12810
12950
|
] }),
|
|
@@ -12827,9 +12967,10 @@ function WhatsAppComponent(props) {
|
|
|
12827
12967
|
"button",
|
|
12828
12968
|
{
|
|
12829
12969
|
type: "button",
|
|
12830
|
-
disabled: !state.testPhoneNumber.trim() || state.isSendingTest,
|
|
12970
|
+
disabled: !state.testPhoneNumber.trim() || state.isSendingTest || state.isTestDisabled,
|
|
12831
12971
|
onClick: state.handleSendTest,
|
|
12832
|
-
|
|
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"}`,
|
|
12833
12974
|
children: state.isSendingTest ? /* @__PURE__ */ jsxs17(Fragment7, { children: [
|
|
12834
12975
|
/* @__PURE__ */ jsx18(Loader27, { className: "w-3.5 h-3.5 animate-spin" }),
|
|
12835
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 {
|