@myrjfa/ui 0.3.1 → 0.3.2
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/chat/MessageBubble.d.ts.map +1 -1
- package/dist/chat/MessageBubble.js +1 -1
- package/dist/chat/MessageInput.d.ts.map +1 -1
- package/dist/chat/MessageInput.js +16 -1
- package/dist/chat/dialogs/HostWorkspaceDialog.d.ts.map +1 -1
- package/dist/chat/dialogs/HostWorkspaceDialog.js +9 -1
- package/dist/misc/button.d.ts +1 -1
- package/package.json +2 -2
- package/dist/components/ui/misc/pwa-install-button.d.ts +0 -2
- package/dist/components/ui/misc/pwa-install-button.d.ts.map +0 -1
- package/dist/components/ui/misc/pwa-install-button.js +0 -17
- package/dist/layout/AppProviders.d.ts +0 -5
- package/dist/layout/AppProviders.d.ts.map +0 -1
- package/dist/layout/AppProviders.js +0 -11
- package/dist/layout/PublicShell.d.ts +0 -5
- package/dist/layout/PublicShell.d.ts.map +0 -1
- package/dist/layout/PublicShell.js +0 -5
- package/dist/misc/IosPwaNavBar.d.ts +0 -8
- package/dist/misc/IosPwaNavBar.d.ts.map +0 -1
- package/dist/misc/IosPwaNavBar.js +0 -25
- package/dist/misc/location/leafletMap.d.ts +0 -8
- package/dist/misc/location/leafletMap.d.ts.map +0 -1
- package/dist/misc/location/leafletMap.js +0 -62
- package/dist/misc/location/locationPicker.d.ts +0 -5
- package/dist/misc/location/locationPicker.d.ts.map +0 -1
- package/dist/misc/location/locationPicker.js +0 -95
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageBubble.d.ts","sourceRoot":"","sources":["../../src/chat/MessageBubble.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGH,KAAK,cAAc,EAEnB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,IAAI,EACZ,MAAM,oCAAoC,CAAC;AAqE5C,UAAU,kBAAkB;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,cAAc,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACvE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAC7H,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACzC;AAWD,wBAAgB,aAAa,CAAC,EAC1B,OAAO,EACP,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,MAAM,EACN,QAAQ,EACR,OAAO,EACP,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,YAAY,EACZ,UAAU,EACV,QAAQ,GACX,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"MessageBubble.d.ts","sourceRoot":"","sources":["../../src/chat/MessageBubble.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGH,KAAK,cAAc,EAEnB,KAAK,OAAO,EACZ,KAAK,WAAW,EAChB,KAAK,IAAI,EACZ,MAAM,oCAAoC,CAAC;AAqE5C,UAAU,kBAAkB;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,cAAc,CAAC;IAClC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrC,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3D,gBAAgB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,eAAe,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IACvE,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;IAC7H,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACzC;AAWD,wBAAgB,aAAa,CAAC,EAC1B,OAAO,EACP,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,UAAU,EACV,gBAAgB,EAChB,MAAM,EACN,QAAQ,EACR,OAAO,EACP,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,MAAM,EACN,UAAU,EACV,MAAM,EACN,KAAK,EACL,YAAY,EACZ,UAAU,EACV,QAAQ,GACX,EAAE,kBAAkB,2CA6zBpB"}
|
|
@@ -348,7 +348,7 @@ export function MessageBubble({ message, participants, currentUserId, currentAct
|
|
|
348
348
|
${message.isDeleted ? "opacity-60 italic" : ""}`, onContextMenu: (event) => {
|
|
349
349
|
event.preventDefault();
|
|
350
350
|
setShowActionMenu(true);
|
|
351
|
-
}, children: [message.content.media && message.content.media.length > 0 && (_jsx("div", { className: "mb-2 space-y-1", children: message.content.media.map((m, i) => (_jsx("div", { children: m.mimeType.startsWith("image/") ? (_jsx("img", { src: m.url, alt: m.name, className: "rounded-lg max-w-full max-h-64 object-cover" })) : m.mimeType.startsWith("audio/") ? (_jsx(AudioMessagePlayer, { src: m.url, messageId: `${message._id}:${i}` })) : m.mimeType.startsWith("video/") ? (_jsx("video", { src: m.url, poster: m.thumbnailUrl, controls: true, preload: "metadata", className: "max-h-72 w-full rounded-lg bg-black" })) : (_jsxs("a", { href: m.url, target: "_blank", rel: "noopener noreferrer", className: "flex items-center gap-3 rounded-lg border border-black/10 bg-white/80 p-3 text-sm text-slate-800 shadow-sm dark:bg-slate-900/70 dark:text-white", children: [_jsx(FileText, { className: "h-8 w-8 shrink-0 text-purple-500" }),
|
|
351
|
+
}, children: [message.content.media && message.content.media.length > 0 && (_jsx("div", { className: "mb-2 space-y-1", children: message.content.media.map((m, i) => (_jsx("div", { children: m.mimeType.startsWith("image/") ? (_jsx("img", { src: m.url, alt: m.name, className: "rounded-lg max-w-full max-h-64 object-cover" })) : m.mimeType.startsWith("audio/") ? (_jsx(AudioMessagePlayer, { src: m.url, messageId: `${message._id}:${i}` })) : m.mimeType.startsWith("video/") ? (_jsx("video", { src: m.url, poster: m.thumbnailUrl, controls: true, preload: "metadata", className: "max-h-72 w-full rounded-lg bg-black" })) : (_jsxs("a", { href: m.url, target: "_blank", rel: "noopener noreferrer", className: "flex items-center gap-3 rounded-lg border border-black/10 bg-white/80 p-3 text-sm text-slate-800 shadow-sm dark:bg-slate-900/70 dark:text-white", children: [_jsx(FileText, { className: "h-8 w-8 shrink-0 text-purple-500" }), _jsx("span", { className: "min-w-0 truncate", children: m.name || "Attachment" })] })) }, i))) })), _jsx("p", { className: "text-[15px] leading-relaxed whitespace-pre-wrap break-words", children: renderTextWithLinks((_f = message.content.text) !== null && _f !== void 0 ? _f : "") }), ((_g = message.content.linkPreview) === null || _g === void 0 ? void 0 : _g.url) && (() => {
|
|
352
352
|
const preview = message.content.linkPreview;
|
|
353
353
|
const mapCoordinates = coordinatesFromMapUrl(preview.url);
|
|
354
354
|
return (_jsxs("a", { href: preview.url, target: "_blank", rel: "noopener noreferrer", className: "mt-3 block overflow-hidden rounded-xl border border-black/10 bg-white/90 text-slate-900 shadow-sm transition-opacity hover:opacity-90 dark:border-white/10 dark:bg-slate-900/80 dark:text-white", children: [mapCoordinates ? (_jsx("div", { className: "h-28 w-full overflow-hidden bg-slate-100", children: _jsx(MapPreview, { latitude: mapCoordinates.latitude, longitude: mapCoordinates.longitude }) })) : preview.image ? (_jsx("img", { src: preview.image, alt: "", className: "h-32 w-full object-cover", onError: (event) => { event.currentTarget.style.display = "none"; } })) : null, _jsxs("div", { className: "p-3", children: [_jsx("p", { className: "text-[10px] font-semibold uppercase tracking-wider text-slate-500", children: preview.siteName || new URL(preview.url).hostname }), _jsx("p", { className: "mt-1 line-clamp-2 text-sm font-semibold", children: preview.title || preview.url }), preview.description && _jsx("p", { className: "mt-1 line-clamp-2 text-xs text-slate-600 dark:text-slate-300", children: preview.description })] })] }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageInput.d.ts","sourceRoot":"","sources":["../../src/chat/MessageInput.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAE7D,UAAU,iBAAiB;IACvB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpL,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,OAAO,KAAK,IAAI,CAAC;IACrF,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC5D,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;
|
|
1
|
+
{"version":3,"file":"MessageInput.d.ts","sourceRoot":"","sources":["../../src/chat/MessageInput.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAE,MAAM,oCAAoC,CAAC;AAE7D,UAAU,iBAAiB;IACvB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,IAAI,EAAE,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAC,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,cAAc,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACpL,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,GAAG,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7B,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnD,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,OAAO,KAAK,IAAI,CAAC;IACrF,YAAY,CAAC,EAAE,GAAG,EAAE,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,YAAY,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC5D,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,yBAAyB,CAAC,EAAE,OAAO,CAAC;IACpC,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAC1C;AAeD,wBAAgB,YAAY,CAAC,EACzB,MAAM,EACN,aAAa,EACb,YAAY,EACZ,QAAQ,EACR,OAAO,EACP,WAAW,EACX,MAAM,EACN,YAAY,EACZ,aAAa,EACb,cAAc,EACd,YAAY,EACZ,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,YAAiB,EAAE,QAAQ;AAC3B,WAAoB,EACpB,oBAA4B,EAC5B,iBAAyB,EACzB,yBAAiC,EACjC,kBAA0B,EAC1B,WAAgB,EAChB,YAAY,EACZ,aAAa,GAChB,EAAE,iBAAiB,2CA8kBnB"}
|
|
@@ -13,6 +13,21 @@ import { MediaComposerDialog } from "./dialogs/MediaComposerDialog";
|
|
|
13
13
|
import { showAlert } from "../misc/alertdialogclaude";
|
|
14
14
|
import { isCompressibleImage, compressImage } from "@myrjfa/state/dist/lib/utils/fileCompression";
|
|
15
15
|
import EmojiPicker from 'emoji-picker-react';
|
|
16
|
+
function LocalFilePreview({ file }) {
|
|
17
|
+
const [url, setUrl] = useState("");
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
const objectUrl = URL.createObjectURL(file);
|
|
20
|
+
setUrl(objectUrl);
|
|
21
|
+
return () => URL.revokeObjectURL(objectUrl);
|
|
22
|
+
}, [file]);
|
|
23
|
+
if (!url)
|
|
24
|
+
return null;
|
|
25
|
+
if (file.type.startsWith("image/"))
|
|
26
|
+
return _jsx("img", { src: url, alt: "", className: "h-9 w-9 rounded object-cover" });
|
|
27
|
+
if (file.type.startsWith("audio/"))
|
|
28
|
+
return _jsx("audio", { src: url, controls: true, className: "h-8 max-w-44" });
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
16
31
|
export function MessageInput({ onSend, onTypingStart, onTypingStop, disabled, replyTo, editMessage, onEdit, onCancelEdit, onCancelReply, onAddMilestone, onAddExpense, onAddEvent, onPayAndSplit, onPaymentDetails, onCreatePoll, participants = [], // Added
|
|
17
32
|
activePanel = "chat", allowAdvancedActions = false, enableAttachments = false, allowCollaborationActions = false, allowAnnouncements = false, initialText = "", externalText, onDraftChange, }) {
|
|
18
33
|
var _a, _b, _c;
|
|
@@ -306,7 +321,7 @@ activePanel = "chat", allowAdvancedActions = false, enableAttachments = false, a
|
|
|
306
321
|
.map(p => (_jsx("button", { onClick: () => insertMention(p), className: "w-full text-left px-3 py-2 text-sm hover:bg-indigo-50 dark:hover:bg-indigo-900/40 flex items-center gap-2", children: _jsxs("span", { className: "truncate", children: ["@", p.username || participantLabel(p)] }) }, p.actorId))), participants.filter((p) => {
|
|
307
322
|
const searchable = `${p.username || ""} ${p.displayName || ""}`.toLowerCase();
|
|
308
323
|
return !mentionSearch || searchable.includes(mentionSearch.toLowerCase());
|
|
309
|
-
}).length === 0 && (_jsx("div", { className: "px-3 py-2 text-xs text-gray-500 italic", children: "No members found" }))] })), allowAdvancedActions && enableAttachments && selectedFiles.length > 0 && !editMessage && (_jsx("div", { className: "max-w-4xl mx-auto mb-2 flex flex-wrap gap-2", children: selectedFiles.map((file, i) => (_jsxs("div", { className: "flex items-center gap-1 bg-gray-100 dark:bg-gray-800 rounded-lg px-2 py-1 text-xs text-gray-600 dark:text-gray-300", children: [
|
|
324
|
+
}).length === 0 && (_jsx("div", { className: "px-3 py-2 text-xs text-gray-500 italic", children: "No members found" }))] })), allowAdvancedActions && enableAttachments && selectedFiles.length > 0 && !editMessage && (_jsx("div", { className: "max-w-4xl mx-auto mb-2 flex flex-wrap gap-2", children: selectedFiles.map((file, i) => (_jsxs("div", { className: "flex items-center gap-1 bg-gray-100 dark:bg-gray-800 rounded-lg px-2 py-1 text-xs text-gray-600 dark:text-gray-300", children: [_jsx(LocalFilePreview, { file: file }), _jsx("span", { className: "truncate max-w-[150px]", children: file.name }), selectedFiles.length > 1 && _jsxs(_Fragment, { children: [_jsx("button", { type: "button", disabled: i === 0, onClick: () => moveFile(i, -1), "aria-label": "Move attachment left", children: _jsx(ChevronLeft, { className: "h-3.5 w-3.5" }) }), _jsx("button", { type: "button", disabled: i === selectedFiles.length - 1, onClick: () => moveFile(i, 1), "aria-label": "Move attachment right", children: _jsx(ChevronRight, { className: "h-3.5 w-3.5" }) })] }), _jsx("button", { onClick: () => removeFile(i), className: "ml-2 text-red-500 hover:text-red-700 font-bold", children: "\u00D7" })] }, `${file.name}-${i}`))) })), announcementMode && !editMessage && (_jsxs("div", { className: "mx-auto mb-2 flex max-w-4xl items-center justify-between rounded-xl border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900", children: [_jsxs("span", { className: "flex items-center gap-2 font-medium", children: [_jsx(Megaphone, { className: "h-4 w-4" }), "Sending as a group announcement"] }), _jsx("button", { type: "button", onClick: () => setAnnouncementMode(false), "aria-label": "Cancel announcement", children: _jsx(X, { className: "h-4 w-4" }) })] })), replyTo && (_jsxs("div", { className: "max-w-4xl mx-auto mb-2 flex items-center gap-2 bg-gray-100 dark:bg-gray-800 px-3 py-2 rounded-lg border-l-2 border-teal-500", children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("div", { className: "text-xs font-semibold text-teal-600 dark:text-teal-400", children: editMessage ? "Editing" : `Replying to ${participantLabel(participants.find((participant) => participant.actorId === replyTo.senderId) || {})}` }), _jsx("div", { className: "text-xs text-gray-600 dark:text-gray-400 truncate", children: (_c = replyTo.content.text) === null || _c === void 0 ? void 0 : _c.substring(0, 60) })] }), _jsx("button", { onClick: onCancelReply, className: "text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 flex-shrink-0", children: _jsx(X, { className: "w-4 h-4" }) })] })), _jsxs("div", { className: `${showMessageInput ? "flex" : "hidden md:flex"} items-end gap-2 max-w-4xl mx-auto`, children: [allowAdvancedActions && enableAttachments && (_jsx("input", { type: "file", ref: fileInputRef, onChange: handleFileChange, accept: fileAcceptType, multiple: true, className: "hidden" })), allowAdvancedActions && !editMessage && _jsxs(Popover, { open: isAttachmentMenuOpen, onOpenChange: setIsAttachmentMenuOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon", className: "text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 rounded-full h-10 w-10 shrink-0", children: _jsx(PlusCircleIcon, { className: "w-5 h-5" }) }) }), _jsxs(PopoverContent, { side: "top", align: "start", className: "w-48 p-2 flex flex-col gap-1", children: [enableAttachments && _jsxs(_Fragment, { children: [_jsxs(Button, { variant: "ghost", className: "justify-start gap-2 w-full", onClick: () => chooseFiles(".pdf,.doc,.docx,.txt,.xlsx,.pptx"), children: [_jsx(FileText, { className: "w-4 h-4 text-purple-500" }), "Document"] }), _jsxs(Button, { variant: "ghost", className: "justify-start gap-2 w-full", onClick: () => chooseFiles("image/*"), children: [_jsx(ImageIcon, { className: "w-4 h-4 text-blue-500" }), "Photos"] }), _jsxs(Button, { variant: "ghost", className: "justify-start gap-2 w-full", onClick: () => chooseFiles("video/*"), children: [_jsx(VideoIcon, { className: "w-4 h-4 text-rose-500" }), "Videos"] }), _jsxs(Button, { variant: "ghost", className: "justify-start gap-2 w-full", onClick: () => { setIsAttachmentMenuOpen(false); setIsLocationDialogOpen(true); }, children: [_jsx(MapPin, { className: "w-4 h-4 text-green-500" }), "Location"] })] }), allowCollaborationActions && _jsxs(Button, { variant: "ghost", className: "justify-start gap-2 w-full", onClick: () => { setIsAttachmentMenuOpen(false); setIsPollOpen(true); }, children: [_jsx(ChartBar, { className: "w-4 h-4 text-orange-500" }), "Poll"] }), allowCollaborationActions && _jsx("div", { className: "border-t border-gray-200 dark:border-gray-700 my-1" }), allowCollaborationActions && _jsxs(Button, { variant: "ghost", className: "justify-start gap-2 w-full text-teal-600 dark:text-teal-400", onClick: () => {
|
|
310
325
|
setIsAttachmentMenuOpen(false);
|
|
311
326
|
onAddMilestone === null || onAddMilestone === void 0 ? void 0 : onAddMilestone();
|
|
312
327
|
}, children: [_jsx(ListTodo, { className: "w-4 h-4" }), "Add Milestone"] }), allowCollaborationActions && _jsxs(Button, { variant: "ghost", className: "justify-start gap-2 w-full text-teal-600 dark:text-teal-400", onClick: () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HostWorkspaceDialog.d.ts","sourceRoot":"","sources":["../../../src/chat/dialogs/HostWorkspaceDialog.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAGR,gBAAgB,EAGnB,MAAM,oCAAoC,CAAC;AAkB5C,wBAAgB,mBAAmB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,cAAc,EACd,UAAU,EACV,cAAc,GACjB,EAAE;IACC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,cAAc,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACvD,
|
|
1
|
+
{"version":3,"file":"HostWorkspaceDialog.d.ts","sourceRoot":"","sources":["../../../src/chat/dialogs/HostWorkspaceDialog.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAGR,gBAAgB,EAGnB,MAAM,oCAAoC,CAAC;AAkB5C,wBAAgB,mBAAmB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,cAAc,EACd,UAAU,EACV,cAAc,GACjB,EAAE;IACC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACtC,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,cAAc,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACvD,2CA+HA"}
|
|
@@ -32,6 +32,7 @@ export function HostWorkspaceDialog({ open, onOpenChange, conversationId, onUseR
|
|
|
32
32
|
const [aiInstruction, setAiInstruction] = useState("");
|
|
33
33
|
const [aiResult, setAiResult] = useState("");
|
|
34
34
|
const [aiLoading, setAiLoading] = useState(false);
|
|
35
|
+
const [aiProposal, setAiProposal] = useState(null);
|
|
35
36
|
const reload = async () => {
|
|
36
37
|
const [business, conversationState, quickReplies, ownedListings] = await Promise.all([
|
|
37
38
|
chatApi.getChatBusinessProfile(),
|
|
@@ -83,7 +84,14 @@ export function HostWorkspaceDialog({ open, onOpenChange, conversationId, onUseR
|
|
|
83
84
|
["ai", "AI copilot"],
|
|
84
85
|
["profile", "Business"],
|
|
85
86
|
];
|
|
86
|
-
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "w-[calc(100vw-1.5rem)] sm:max-w-[560px]", children: [_jsx(DialogHeader, { children: _jsxs(DialogTitle, { className: "flex items-center gap-2", children: [_jsx(BriefcaseBusiness, { className: "h-5 w-5 text-teal-600" }), "Host workspace"] }) }), _jsx("div", { className: "flex gap-1 overflow-x-auto rounded-lg bg-slate-100 p-1", children: tabs.map(([value, label]) => _jsx("button", { type: "button", onClick: () => setTab(value), className: `whitespace-nowrap rounded-md px-3 py-2 text-sm ${tab === value ? "bg-white font-medium shadow-sm" : "text-slate-600"}`, children: label }, value)) }), _jsxs("div", { className: "max-h-[62vh] space-y-3 overflow-y-auto pr-1", children: [tab === "conversation" && _jsxs(_Fragment, { children: [_jsx("label", { className: "block text-sm font-medium", children: "Lead stage" }), _jsxs("select", { className: "h-10 w-full rounded-md border bg-background px-3 text-sm", value: (state === null || state === void 0 ? void 0 : state.leadStage) || "new", onChange: (e) => void updateState({ leadStage: e.target.value }), children: [_jsx("option", { value: "new", children: "New lead" }), _jsx("option", { value: "qualified", children: "Qualified" }), _jsx("option", { value: "quote_sent", children: "Quote sent" }), _jsx("option", { value: "booking_pending", children: "Booking pending" }), _jsx("option", { value: "confirmed", children: "Confirmed" }), _jsx("option", { value: "completed", children: "Completed" }), _jsx("option", { value: "follow_up", children: "Follow-up" }), _jsx("option", { value: "closed", children: "Closed" })] }), _jsx(Input, { value: ((state === null || state === void 0 ? void 0 : state.labels) || []).join(", "), onChange: (e) => setState((current) => ({ ...(current || { conversationId, leadStage: "new", privateNotes: [] }), labels: e.target.value.split(",").map((item) => item.trim()).filter(Boolean) })), onBlur: () => void updateState({ labels: (state === null || state === void 0 ? void 0 : state.labels) || [] }), placeholder: "Labels, separated by commas" }), _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsx(Input, { type: "datetime-local", value: ((_a = state === null || state === void 0 ? void 0 : state.followUpAt) === null || _a === void 0 ? void 0 : _a.slice(0, 16)) || "", onChange: (e) => setState((current) => ({ ...(current || { conversationId, leadStage: "new", labels: [], privateNotes: [] }), followUpAt: e.target.value })) }), _jsxs(Button, { variant: "outline", onClick: () => void updateState({ followUpAt: (state === null || state === void 0 ? void 0 : state.followUpAt) || null }), children: [_jsx(CalendarClock, { className: "mr-2 h-4 w-4" }), "Schedule"] })] }), _jsx(Textarea, { value: note, onChange: (e) => setNote(e.target.value), placeholder: "Private host note (never visible to the traveller)" }), _jsx(Button, { className: "w-full", disabled: !note.trim() || saving, onClick: () => void updateState({ privateNote: note }), children: "Add private note" }), !!((_b = state === null || state === void 0 ? void 0 : state.privateNotes) === null || _b === void 0 ? void 0 : _b.length) && _jsx("div", { className: "space-y-2 rounded-xl bg-amber-50 p-3", children: state.privateNotes.slice().reverse().map((item, index) => _jsx("p", { className: "text-sm text-amber-950", children: item.text }, `${item.createdAt}-${index}`)) })] }), tab === "replies" && _jsxs(_Fragment, { children: [_jsxs("div", { className: "grid grid-cols-[120px_1fr] gap-2", children: [_jsx(Input, { value: shortcut, onChange: (e) => setShortcut(e.target.value), placeholder: "/shortcut" }), _jsx(Input, { value: replyText, onChange: (e) => setReplyText(e.target.value), placeholder: "Reply text" })] }), _jsxs(Button, { className: "w-full", onClick: () => void addReply(), disabled: !shortcut.trim() || !replyText.trim(), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "Save quick reply"] }), replies.map((reply) => _jsxs("div", { className: "flex items-center gap-2 rounded-xl border p-3", children: [_jsxs("button", { className: "min-w-0 flex-1 text-left", onClick: () => { onUseReply(reply.text); onOpenChange(false); }, children: [_jsxs("span", { className: "block text-xs font-semibold text-teal-700", children: ["/", reply.shortcut] }), _jsx("span", { className: "line-clamp-2 text-sm", children: reply.text })] }), _jsx(Button, { size: "icon", variant: "ghost", className: "text-red-600", onClick: () => void chatApi.deleteChatQuickReply(reply._id).then(() => setReplies((items) => items.filter((item) => item._id !== reply._id))), children: _jsx(Trash2, { className: "h-4 w-4" }) })] }, reply._id))] }), tab === "listings" && _jsx(_Fragment, { children: listings.length ? listings.map((listing) => _jsxs("div", { className: "flex items-center gap-3 rounded-xl border p-3", children: [listing.image && _jsx("img", { src: listing.image, alt: "", className: "h-12 w-12 rounded-lg object-cover" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "truncate text-sm font-semibold", children: listing.title }), _jsx("p", { className: "text-xs capitalize text-slate-500", children: listing.category })] }), _jsxs(Button, { size: "sm", disabled: !listing.publicPath, onClick: () => { onShareListing(listing); onOpenChange(false); }, children: [_jsx(Send, { className: "mr-1 h-3.5 w-3.5" }), "Share"] })] }, `${listing.category}:${listing.listingId}`)) : _jsx("p", { className: "py-6 text-center text-sm text-slate-500", children: "No published owned listings found." }) }), tab === "ai" && _jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm text-slate-500", children: "Suggestions are private drafts. Nothing is sent or changed automatically." }), _jsx(Textarea, { value: aiInstruction, onChange: (e) => setAiInstruction(e.target.value), placeholder: "Optional instruction, e.g. keep it concise and recommend a family stay" }),
|
|
87
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "w-[calc(100vw-1.5rem)] sm:max-w-[560px]", children: [_jsx(DialogHeader, { children: _jsxs(DialogTitle, { className: "flex items-center gap-2", children: [_jsx(BriefcaseBusiness, { className: "h-5 w-5 text-teal-600" }), "Host workspace"] }) }), _jsx("div", { className: "flex gap-1 overflow-x-auto rounded-lg bg-slate-100 p-1", children: tabs.map(([value, label]) => _jsx("button", { type: "button", onClick: () => setTab(value), className: `whitespace-nowrap rounded-md px-3 py-2 text-sm ${tab === value ? "bg-white font-medium shadow-sm" : "text-slate-600"}`, children: label }, value)) }), _jsxs("div", { className: "max-h-[62vh] space-y-3 overflow-y-auto pr-1", children: [tab === "conversation" && _jsxs(_Fragment, { children: [_jsx("label", { className: "block text-sm font-medium", children: "Lead stage" }), _jsxs("select", { className: "h-10 w-full rounded-md border bg-background px-3 text-sm", value: (state === null || state === void 0 ? void 0 : state.leadStage) || "new", onChange: (e) => void updateState({ leadStage: e.target.value }), children: [_jsx("option", { value: "new", children: "New lead" }), _jsx("option", { value: "qualified", children: "Qualified" }), _jsx("option", { value: "quote_sent", children: "Quote sent" }), _jsx("option", { value: "booking_pending", children: "Booking pending" }), _jsx("option", { value: "confirmed", children: "Confirmed" }), _jsx("option", { value: "completed", children: "Completed" }), _jsx("option", { value: "follow_up", children: "Follow-up" }), _jsx("option", { value: "closed", children: "Closed" })] }), _jsx(Input, { value: ((state === null || state === void 0 ? void 0 : state.labels) || []).join(", "), onChange: (e) => setState((current) => ({ ...(current || { conversationId, leadStage: "new", privateNotes: [] }), labels: e.target.value.split(",").map((item) => item.trim()).filter(Boolean) })), onBlur: () => void updateState({ labels: (state === null || state === void 0 ? void 0 : state.labels) || [] }), placeholder: "Labels, separated by commas" }), _jsxs("div", { className: "grid grid-cols-2 gap-2", children: [_jsx(Input, { type: "datetime-local", value: ((_a = state === null || state === void 0 ? void 0 : state.followUpAt) === null || _a === void 0 ? void 0 : _a.slice(0, 16)) || "", onChange: (e) => setState((current) => ({ ...(current || { conversationId, leadStage: "new", labels: [], privateNotes: [] }), followUpAt: e.target.value })) }), _jsxs(Button, { variant: "outline", onClick: () => void updateState({ followUpAt: (state === null || state === void 0 ? void 0 : state.followUpAt) || null }), children: [_jsx(CalendarClock, { className: "mr-2 h-4 w-4" }), "Schedule"] })] }), _jsx(Textarea, { value: note, onChange: (e) => setNote(e.target.value), placeholder: "Private host note (never visible to the traveller)" }), _jsx(Button, { className: "w-full", disabled: !note.trim() || saving, onClick: () => void updateState({ privateNote: note }), children: "Add private note" }), !!((_b = state === null || state === void 0 ? void 0 : state.privateNotes) === null || _b === void 0 ? void 0 : _b.length) && _jsx("div", { className: "space-y-2 rounded-xl bg-amber-50 p-3", children: state.privateNotes.slice().reverse().map((item, index) => _jsx("p", { className: "text-sm text-amber-950", children: item.text }, `${item.createdAt}-${index}`)) })] }), tab === "replies" && _jsxs(_Fragment, { children: [_jsxs("div", { className: "grid grid-cols-[120px_1fr] gap-2", children: [_jsx(Input, { value: shortcut, onChange: (e) => setShortcut(e.target.value), placeholder: "/shortcut" }), _jsx(Input, { value: replyText, onChange: (e) => setReplyText(e.target.value), placeholder: "Reply text" })] }), _jsxs(Button, { className: "w-full", onClick: () => void addReply(), disabled: !shortcut.trim() || !replyText.trim(), children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "Save quick reply"] }), replies.map((reply) => _jsxs("div", { className: "flex items-center gap-2 rounded-xl border p-3", children: [_jsxs("button", { className: "min-w-0 flex-1 text-left", onClick: () => { onUseReply(reply.text); onOpenChange(false); }, children: [_jsxs("span", { className: "block text-xs font-semibold text-teal-700", children: ["/", reply.shortcut] }), _jsx("span", { className: "line-clamp-2 text-sm", children: reply.text })] }), _jsx(Button, { size: "icon", variant: "ghost", className: "text-red-600", onClick: () => void chatApi.deleteChatQuickReply(reply._id).then(() => setReplies((items) => items.filter((item) => item._id !== reply._id))), children: _jsx(Trash2, { className: "h-4 w-4" }) })] }, reply._id))] }), tab === "listings" && _jsx(_Fragment, { children: listings.length ? listings.map((listing) => _jsxs("div", { className: "flex items-center gap-3 rounded-xl border p-3", children: [listing.image && _jsx("img", { src: listing.image, alt: "", className: "h-12 w-12 rounded-lg object-cover" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsx("p", { className: "truncate text-sm font-semibold", children: listing.title }), _jsx("p", { className: "text-xs capitalize text-slate-500", children: listing.category })] }), _jsxs(Button, { size: "sm", disabled: !listing.publicPath, onClick: () => { onShareListing(listing); onOpenChange(false); }, children: [_jsx(Send, { className: "mr-1 h-3.5 w-3.5" }), "Share"] })] }, `${listing.category}:${listing.listingId}`)) : _jsx("p", { className: "py-6 text-center text-sm text-slate-500", children: "No published owned listings found." }) }), tab === "ai" && _jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm text-slate-500", children: "Suggestions are private drafts. Nothing is sent or changed automatically." }), _jsx(Textarea, { value: aiInstruction, onChange: (e) => setAiInstruction(e.target.value), placeholder: "Optional instruction, e.g. keep it concise and recommend a family stay" }), _jsxs(Button, { className: "w-full", variant: "secondary", disabled: aiLoading || !aiInstruction.trim(), onClick: () => {
|
|
88
|
+
setAiLoading(true);
|
|
89
|
+
void chatApi.requestChatAICommand(conversationId, aiInstruction).then((result) => {
|
|
90
|
+
setAiProposal(result.proposal ? { _id: result.proposal._id, preview: result.proposal.preview } : null);
|
|
91
|
+
if (result.draft)
|
|
92
|
+
setAiResult(result.draft.content || result.draft.summary || "");
|
|
93
|
+
}).catch((error) => showAlert(error instanceof Error ? error.message : "Command could not be prepared.", "AI command")).finally(() => setAiLoading(false));
|
|
94
|
+
}, children: [_jsx(Sparkles, { className: "mr-2 h-4 w-4" }), "Prepare command"] }), aiProposal && _jsxs("div", { className: "rounded-xl border border-amber-200 bg-amber-50 p-3", children: [_jsx("p", { className: "text-xs font-semibold uppercase text-amber-700", children: "Confirmation required" }), _jsx("p", { className: "mt-1 text-sm text-amber-950", children: aiProposal.preview }), _jsxs("div", { className: "mt-3 flex gap-2", children: [_jsx(Button, { className: "flex-1", onClick: () => void chatApi.decideChatAIProposal(aiProposal._id, true).then(() => { setAiProposal(null); void reload(); }), children: "Confirm" }), _jsx(Button, { className: "flex-1", variant: "outline", onClick: () => void chatApi.decideChatAIProposal(aiProposal._id, false).then(() => setAiProposal(null)), children: "Reject" })] })] }), _jsx("div", { className: "grid grid-cols-2 gap-2", children: [["suggest_reply", "Suggest reply"], ["summarize", "Summarize"], ["classify", "Lead insights"], ["recommend_listings", "Recommend listings"]].map(([task, label]) => _jsxs(Button, { variant: "outline", disabled: aiLoading, onClick: () => {
|
|
87
95
|
setAiLoading(true);
|
|
88
96
|
void chatApi.requestChatCopilotAssistance(conversationId, { task, instruction: aiInstruction }).then((result) => setAiResult(result.content || result.summary || "")).catch((error) => showAlert(error instanceof Error ? error.message : "AI assistance failed.", "AI copilot")).finally(() => setAiLoading(false));
|
|
89
97
|
}, children: [_jsx(Sparkles, { className: "mr-1.5 h-4 w-4" }), label] }, task)) }), aiResult && _jsxs("div", { className: "space-y-3 rounded-xl border border-violet-100 bg-violet-50 p-3", children: [_jsx("p", { className: "whitespace-pre-wrap text-sm text-violet-950", children: aiResult }), _jsx(Button, { className: "w-full", onClick: () => { onUseReply(aiResult); onOpenChange(false); }, children: "Use as draft" })] })] }), tab === "profile" && _jsxs(_Fragment, { children: [_jsx(Input, { value: profile.displayName, onChange: (e) => setProfile({ ...profile, displayName: e.target.value }), placeholder: "Business display name" }), _jsx(Input, { value: profile.languages.join(", "), onChange: (e) => setProfile({ ...profile, languages: e.target.value.split(",").map((item) => item.trim()).filter(Boolean) }), placeholder: "Languages" }), _jsx(Input, { value: profile.responseExpectation, onChange: (e) => setProfile({ ...profile, responseExpectation: e.target.value }), placeholder: "Usually replies within..." }), _jsxs("div", { className: "rounded-xl border p-3", children: [_jsxs("label", { className: "flex items-center justify-between text-sm font-medium", children: ["Greeting message", _jsx(Switch, { checked: profile.greeting.enabled, onCheckedChange: (enabled) => setProfile({ ...profile, greeting: { ...profile.greeting, enabled } }) })] }), _jsx(Textarea, { className: "mt-2", value: profile.greeting.text, onChange: (e) => setProfile({ ...profile, greeting: { ...profile.greeting, text: e.target.value } }), placeholder: "Welcome message" })] }), _jsxs("div", { className: "rounded-xl border p-3", children: [_jsxs("label", { className: "flex items-center justify-between text-sm font-medium", children: ["Away message", _jsx(Switch, { checked: profile.away.enabled, onCheckedChange: (enabled) => setProfile({ ...profile, away: { ...profile.away, enabled } }) })] }), _jsx(Textarea, { className: "mt-2", value: profile.away.text, onChange: (e) => setProfile({ ...profile, away: { ...profile.away, text: e.target.value } }), placeholder: "Outside-hours response" })] }), _jsxs(Button, { className: "w-full", disabled: saving, onClick: () => void saveProfile(), children: [_jsx(MessageSquareText, { className: "mr-2 h-4 w-4" }), "Save business chat settings"] })] })] })] }) }));
|
package/dist/misc/button.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type VariantProps } from "class-variance-authority";
|
|
2
2
|
declare const buttonVariants: (props?: ({
|
|
3
|
-
variant?: "
|
|
3
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | null | undefined;
|
|
4
4
|
size?: "default" | "sm" | "lg" | "icon" | null | undefined;
|
|
5
5
|
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
6
6
|
type ButtonProps = React.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myrjfa/ui",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
"./dist/*": "./dist/*.js"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"dist"
|
|
14
14
|
],
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@myrjfa/state": "
|
|
16
|
+
"@myrjfa/state": "file:../frontend-state",
|
|
17
17
|
"@hookform/resolvers": "^4.1.3",
|
|
18
18
|
"@iconify/react": "^5.2.0",
|
|
19
19
|
"@radix-ui/react-accordion": "^1.2.3",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pwa-install-button.d.ts","sourceRoot":"","sources":["../../../../src/components/ui/misc/pwa-install-button.tsx"],"names":[],"mappings":"AAGA,wBAAgB,gBAAgB,mDAsB/B"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useState } from 'react';
|
|
4
|
-
export function PwaInstallButton() {
|
|
5
|
-
const [prompt, setPrompt] = useState(null);
|
|
6
|
-
useEffect(() => {
|
|
7
|
-
const handler = (e) => {
|
|
8
|
-
e.preventDefault();
|
|
9
|
-
setPrompt(e);
|
|
10
|
-
};
|
|
11
|
-
window.addEventListener('beforeinstallprompt', handler);
|
|
12
|
-
return () => window.removeEventListener('beforeinstallprompt', handler);
|
|
13
|
-
}, []);
|
|
14
|
-
if (!prompt)
|
|
15
|
-
return null;
|
|
16
|
-
return (_jsx("button", { onClick: () => prompt.prompt(), className: "fixed bottom-20 right-6 z-50 bg-primary text-primary-foreground px-4 py-2 rounded-full shadow-lg text-sm font-medium", children: "Install App" }));
|
|
17
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AppProviders.d.ts","sourceRoot":"","sources":["../../src/layout/AppProviders.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQlC,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAYzE"}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { Provider as JotaiProvider } from "jotai";
|
|
4
|
-
import AuthSessionManager from "@myrjfa/state/dist/lib/authSessionManager";
|
|
5
|
-
import QueryProvider from "@myrjfa/state/dist/lib/QueryProvider";
|
|
6
|
-
import Navbar from "../main/navbar";
|
|
7
|
-
import { PwaInstallButton } from "../misc/pwa-install-button";
|
|
8
|
-
import IosPwaNavBar from "../misc/IosPwaNavBar";
|
|
9
|
-
export default function AppProviders({ children }) {
|
|
10
|
-
return (_jsx(JotaiProvider, { children: _jsxs(QueryProvider, { children: [_jsx(AuthSessionManager, {}), _jsx(Navbar, { dark: false }), _jsx("main", { className: "z-1", children: children }), _jsx(PwaInstallButton, {}), _jsx(IosPwaNavBar, {})] }) }));
|
|
11
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"PublicShell.d.ts","sourceRoot":"","sources":["../../src/layout/PublicShell.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGlC,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,2CAOxE"}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import Footer from "../main/footer";
|
|
3
|
-
export default function PublicShell({ children }) {
|
|
4
|
-
return (_jsxs("div", { className: "z-1", children: [_jsx("main", { className: "z-1", children: children }), _jsx(Footer, { dark: false })] }));
|
|
5
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* #12 — iPhone PWA Navigation Bar
|
|
3
|
-
* Shows a fixed bottom bar only when running as a standalone PWA on iOS.
|
|
4
|
-
* iOS Safari in standalone mode has no browser chrome (no back/forward/reload buttons),
|
|
5
|
-
* so users have no way to navigate. This provides that functionality.
|
|
6
|
-
*/
|
|
7
|
-
export default function IosPwaNavBar(): import("react/jsx-runtime").JSX.Element | null;
|
|
8
|
-
//# sourceMappingURL=IosPwaNavBar.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IosPwaNavBar.d.ts","sourceRoot":"","sources":["../../src/misc/IosPwaNavBar.tsx"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,YAAY,mDAiDnC"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useEffect, useState } from 'react';
|
|
4
|
-
import { ChevronLeft, ChevronRight, RefreshCw } from 'lucide-react';
|
|
5
|
-
import { Button } from './button';
|
|
6
|
-
import { useRouter } from 'next/navigation';
|
|
7
|
-
/**
|
|
8
|
-
* #12 — iPhone PWA Navigation Bar
|
|
9
|
-
* Shows a fixed bottom bar only when running as a standalone PWA on iOS.
|
|
10
|
-
* iOS Safari in standalone mode has no browser chrome (no back/forward/reload buttons),
|
|
11
|
-
* so users have no way to navigate. This provides that functionality.
|
|
12
|
-
*/
|
|
13
|
-
export default function IosPwaNavBar() {
|
|
14
|
-
const [isIosPwa, setIsIosPwa] = useState(false);
|
|
15
|
-
const router = useRouter();
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
const isStandalone = ('standalone' in window.navigator && window.navigator.standalone === true) ||
|
|
18
|
-
window.matchMedia('(display-mode: standalone)').matches;
|
|
19
|
-
const isIos = /iPhone|iPad|iPod/i.test(window.navigator.userAgent);
|
|
20
|
-
setIsIosPwa(isStandalone && isIos);
|
|
21
|
-
}, []);
|
|
22
|
-
if (!isIosPwa)
|
|
23
|
-
return null;
|
|
24
|
-
return (_jsxs("nav", { style: { paddingBottom: 'env(safe-area-inset-bottom)' }, className: "fixed bottom-0 left-0 right-0 z-50 bg-white/90 backdrop-blur border-t border-gray-200 flex items-center justify-around h-14", children: [_jsx(Button, { onClick: () => router.back(), "aria-label": "Go back", variant: "ghost", size: "icon", children: _jsx(ChevronLeft, { className: "h-6 w-6" }) }), _jsx(Button, { onClick: () => router.refresh(), "aria-label": "Reload page", variant: "ghost", size: "icon", children: _jsx(RefreshCw, { className: "h-5 w-5" }) }), _jsx(Button, { onClick: () => router.forward(), "aria-label": "Go forward", variant: "ghost", size: "icon", children: _jsx(ChevronRight, { className: "h-6 w-6" }) })] }));
|
|
25
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import 'leaflet/dist/leaflet.css';
|
|
2
|
-
interface LeafletMapProps {
|
|
3
|
-
position: [number, number];
|
|
4
|
-
onMarkerDrag: (lat: number, lng: number) => void;
|
|
5
|
-
}
|
|
6
|
-
export default function LeafletMap({ position, onMarkerDrag }: LeafletMapProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
-
export {};
|
|
8
|
-
//# sourceMappingURL=leafletMap.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"leafletMap.d.ts","sourceRoot":"","sources":["../../../src/misc/location/leafletMap.tsx"],"names":[],"mappings":"AAIA,OAAO,0BAA0B,CAAC;AAoDlC,UAAU,eAAe;IACrB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3B,YAAY,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACpD;AAED,MAAM,CAAC,OAAO,UAAU,UAAU,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,eAAe,2CAmC7E"}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
// Dynamically imported (no SSR) from propertyForm.tsx.
|
|
4
|
-
// Must import leaflet CSS here — this is the only safe place when using next/dynamic.
|
|
5
|
-
import 'leaflet/dist/leaflet.css';
|
|
6
|
-
import { useEffect, useRef } from 'react';
|
|
7
|
-
import { MapContainer, TileLayer, Marker, useMap, useMapEvents } from 'react-leaflet';
|
|
8
|
-
import L from 'leaflet';
|
|
9
|
-
// Fix broken Leaflet default icons in webpack / Next.js
|
|
10
|
-
const defaultIcon = L.icon({
|
|
11
|
-
iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',
|
|
12
|
-
iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',
|
|
13
|
-
shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',
|
|
14
|
-
iconSize: [25, 41],
|
|
15
|
-
iconAnchor: [12, 41],
|
|
16
|
-
popupAnchor: [1, -34],
|
|
17
|
-
shadowSize: [41, 41],
|
|
18
|
-
});
|
|
19
|
-
L.Marker.prototype.options.icon = defaultIcon;
|
|
20
|
-
// Sync map view when position prop changes (e.g. after address search)
|
|
21
|
-
function MapSyncer({ position }) {
|
|
22
|
-
const map = useMap();
|
|
23
|
-
const prev = useRef(position);
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
if (prev.current[0] !== position[0] || prev.current[1] !== position[1]) {
|
|
26
|
-
map.flyTo(position, Math.max(map.getZoom(), 13), { animate: true, duration: 0.8 });
|
|
27
|
-
prev.current = position;
|
|
28
|
-
}
|
|
29
|
-
}, [position, map]);
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
// Fixes the "half-visible" map bug by forcing a resize after mount
|
|
33
|
-
function ResizeMap() {
|
|
34
|
-
const map = useMap();
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
setTimeout(() => {
|
|
37
|
-
map.invalidateSize();
|
|
38
|
-
}, 300);
|
|
39
|
-
}, [map]);
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
// Allows clicking anywhere on map to move the marker
|
|
43
|
-
function ClickHandler({ onDrag }) {
|
|
44
|
-
useMapEvents({
|
|
45
|
-
click(e) {
|
|
46
|
-
onDrag(e.latlng.lat, e.latlng.lng);
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
export default function LeafletMap({ position, onMarkerDrag }) {
|
|
52
|
-
const markerRef = useRef(null);
|
|
53
|
-
return (_jsxs(MapContainer, { center: position, zoom: 13, style: { width: '100%', height: '100%', minHeight: '300px' }, scrollWheelZoom: true, children: [_jsx(TileLayer, { attribution: '\u00A9 <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>', url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png" }), _jsx(ResizeMap, {}), _jsx(MapSyncer, { position: position }), _jsx(ClickHandler, { onDrag: onMarkerDrag }), _jsx(Marker, { position: position, draggable: true, ref: markerRef, icon: defaultIcon, eventHandlers: {
|
|
54
|
-
dragend() {
|
|
55
|
-
const m = markerRef.current;
|
|
56
|
-
if (m) {
|
|
57
|
-
const p = m.getLatLng();
|
|
58
|
-
onMarkerDrag(p.lat, p.lng);
|
|
59
|
-
}
|
|
60
|
-
},
|
|
61
|
-
} })] }));
|
|
62
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"locationPicker.d.ts","sourceRoot":"","sources":["../../../src/misc/location/locationPicker.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAsF1C,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,UAAU,CAAC,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAA;CAAE,2CA2IzF"}
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
// ─── Nominatim address search ─────────────────────────────────────────────────
|
|
2
|
-
'use client';
|
|
3
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
-
import { Loader2, MapPin } from 'lucide-react';
|
|
5
|
-
import { useRef, useState } from 'react';
|
|
6
|
-
import { Input } from '../input';
|
|
7
|
-
import dynamic from 'next/dynamic';
|
|
8
|
-
import { FormControl, FormField, FormItem, FormLabel, FormMessage } from '../form';
|
|
9
|
-
import { Filter } from '../filter';
|
|
10
|
-
import { getCountryNames, getStates } from "@myrjfa/state/dist/lib/data/countryStates";
|
|
11
|
-
function NominatimSearch({ onSelect }) {
|
|
12
|
-
const [query, setQuery] = useState('');
|
|
13
|
-
const [results, setResults] = useState([]);
|
|
14
|
-
const [loading, setLoading] = useState(false);
|
|
15
|
-
const timer = useRef(null);
|
|
16
|
-
const search = (q) => {
|
|
17
|
-
setQuery(q);
|
|
18
|
-
if (timer.current)
|
|
19
|
-
clearTimeout(timer.current);
|
|
20
|
-
if (!q.trim()) {
|
|
21
|
-
setResults([]);
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
timer.current = setTimeout(async () => {
|
|
25
|
-
setLoading(true);
|
|
26
|
-
try {
|
|
27
|
-
const res = await fetch(`https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(q)}&format=json&addressdetails=1&limit=6`, { headers: { 'Accept-Language': 'en' } });
|
|
28
|
-
const data = (await res.json());
|
|
29
|
-
setResults(data);
|
|
30
|
-
}
|
|
31
|
-
catch (_a) {
|
|
32
|
-
setResults([]);
|
|
33
|
-
}
|
|
34
|
-
setLoading(false);
|
|
35
|
-
}, 400);
|
|
36
|
-
};
|
|
37
|
-
const pick = (r) => {
|
|
38
|
-
setQuery(r.display_name);
|
|
39
|
-
setResults([]);
|
|
40
|
-
onSelect(r);
|
|
41
|
-
};
|
|
42
|
-
return (_jsxs("div", { className: "relative", children: [_jsxs("div", { className: "relative", children: [_jsx(MapPin, { className: "absolute left-3 top-2.5 h-4 w-4 text-muted-foreground pointer-events-none" }), loading && _jsx(Loader2, { className: "absolute right-3 top-2.5 h-4 w-4 text-muted-foreground animate-spin" }), _jsx(Input, { id: "address-search", value: query, onChange: (e) => search(e.target.value), placeholder: "Search for a place or address\u2026", className: "pl-9 pr-9", autoComplete: "off" })] }), results.length > 0 && (_jsx("ul", { className: "absolute z-[9999] w-full mt-1 border border-input bg-background rounded-md shadow-lg max-h-60 overflow-auto text-sm", children: results.map((r) => (_jsxs("li", { className: "px-3 py-2 cursor-pointer hover:bg-muted truncate flex items-center gap-2", onClick: () => pick(r), children: [_jsx(MapPin, { className: "h-3.5 w-3.5 text-muted-foreground shrink-0" }), _jsx("span", { children: r.display_name })] }, r.place_id))) }))] }));
|
|
43
|
-
}
|
|
44
|
-
// Dynamic Leaflet map (SSR disabled — window not available on server)
|
|
45
|
-
const LeafletMap = dynamic(() => import('../../components/location/leafletMap'), {
|
|
46
|
-
ssr: false,
|
|
47
|
-
loading: () => (_jsx("div", { className: "w-full h-64 flex items-center justify-center bg-muted rounded-xl border text-sm text-muted-foreground", children: "Loading map\u2026" })),
|
|
48
|
-
});
|
|
49
|
-
// ─── Location picker ─────────────────────────────────────────────────────────
|
|
50
|
-
export default function LocationPicker({ form }) {
|
|
51
|
-
var _a, _b, _c, _d;
|
|
52
|
-
const [mapPos, setMapPos] = useState([
|
|
53
|
-
(_a = form.getValues('lat')) !== null && _a !== void 0 ? _a : 20.5937,
|
|
54
|
-
(_b = form.getValues('lng')) !== null && _b !== void 0 ? _b : 78.9629,
|
|
55
|
-
]);
|
|
56
|
-
const fillFromNominatim = (result, lat, lng) => {
|
|
57
|
-
const a = result.address;
|
|
58
|
-
const city = a.city || a.town || a.village || a.county || '';
|
|
59
|
-
const state = a.state || '';
|
|
60
|
-
const country = a.country || '';
|
|
61
|
-
const pin = a.postcode || '';
|
|
62
|
-
form.setValue('lat', lat, { shouldDirty: true });
|
|
63
|
-
form.setValue('lng', lng, { shouldDirty: true });
|
|
64
|
-
if (city)
|
|
65
|
-
form.setValue('city', city, { shouldDirty: true });
|
|
66
|
-
if (state)
|
|
67
|
-
form.setValue('state', state, { shouldDirty: true });
|
|
68
|
-
if (country)
|
|
69
|
-
form.setValue('country', country, { shouldDirty: true });
|
|
70
|
-
if (pin)
|
|
71
|
-
form.setValue('pinCode', pin, { shouldDirty: true });
|
|
72
|
-
form.setValue('address', result.display_name, { shouldDirty: true });
|
|
73
|
-
};
|
|
74
|
-
const handleSearchSelect = (result) => {
|
|
75
|
-
const lat = parseFloat(result.lat);
|
|
76
|
-
const lng = parseFloat(result.lon);
|
|
77
|
-
setMapPos([lat, lng]);
|
|
78
|
-
fillFromNominatim(result, lat, lng);
|
|
79
|
-
};
|
|
80
|
-
const handleMapPin = async (lat, lng) => {
|
|
81
|
-
setMapPos([lat, lng]);
|
|
82
|
-
form.setValue('lat', lat, { shouldDirty: true });
|
|
83
|
-
form.setValue('lng', lng, { shouldDirty: true });
|
|
84
|
-
try {
|
|
85
|
-
const res = await fetch(`https://nominatim.openstreetmap.org/reverse?lat=${lat}&lon=${lng}&format=json&addressdetails=1`, { headers: { 'Accept-Language': 'en' } });
|
|
86
|
-
const data = (await res.json());
|
|
87
|
-
fillFromNominatim(data, lat, lng);
|
|
88
|
-
}
|
|
89
|
-
catch ( /* silent */_a) { /* silent */ }
|
|
90
|
-
};
|
|
91
|
-
return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { children: [_jsx(FormLabel, { children: "Search Address" }), _jsx("p", { className: "text-xs text-muted-foreground mb-1", children: "Powered by OpenStreetMap \u2014 free, no API key required" }), _jsx(NominatimSearch, { onSelect: handleSearchSelect })] }), _jsx("div", { style: { height: '300px', width: '100%', borderRadius: '0.75rem', overflow: 'hidden', border: '1px solid var(--border)' }, children: _jsx(LeafletMap, { position: mapPos, onMarkerDrag: handleMapPin }) }), _jsx("p", { className: "text-xs text-muted-foreground", children: "Click anywhere on the map or drag the pin to set the exact location. Fields below auto-fill." }), _jsxs("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", children: [_jsx(FormField, { control: form.control, name: "country", render: ({ field }) => (_jsxs(FormItem, { children: [_jsx(FormLabel, { children: "Country *" }), _jsx(FormControl, { children: _jsx("div", { className: "border border-input rounded-md text-sm shadow-sm focus-within:ring-2 focus-within:ring-muted", children: _jsx(Filter, { label: "Country", formType: "autoComplete", selectedValue: field.value, values: getCountryNames(), onChange: (value) => { field.onChange(value); form.setValue('state', ''); } }) }) }), _jsx(FormMessage, {})] })) }), _jsx(FormField, { control: form.control, name: "state", render: ({ field }) => {
|
|
92
|
-
const stateOptions = form.watch('country') ? getStates(form.watch('country')) : [];
|
|
93
|
-
return (_jsxs(FormItem, { children: [_jsx(FormLabel, { children: "State *" }), _jsx(FormControl, { children: _jsx("div", { className: "border border-input rounded-md text-sm shadow-sm focus-within:ring-2 focus-within:ring-muted", children: _jsx(Filter, { label: "State", formType: "autoComplete", selectedValue: field.value, values: stateOptions, onChange: field.onChange }) }) }), _jsx(FormMessage, {})] }));
|
|
94
|
-
} }), _jsx(FormField, { control: form.control, name: "city", render: ({ field }) => (_jsxs(FormItem, { children: [_jsx(FormLabel, { children: "City *" }), _jsx(FormControl, { children: _jsx(Input, { id: "city", placeholder: "e.g. Rishikesh", ...field }) }), _jsx(FormMessage, {})] })) }), _jsx(FormField, { control: form.control, name: "pinCode", render: ({ field }) => (_jsxs(FormItem, { children: [_jsx(FormLabel, { children: "Pin / Postal Code" }), _jsx(FormControl, { children: _jsx(Input, { id: "pinCode", placeholder: "e.g. 249201", ...field }) }), _jsx(FormMessage, {})] })) })] }), _jsx(FormField, { control: form.control, name: "address", render: ({ field }) => (_jsxs(FormItem, { children: [_jsx(FormLabel, { children: "Full Address" }), _jsx(FormControl, { children: _jsx(Input, { id: "address", placeholder: "Street / Landmark\u2026", ...field }) }), _jsx(FormMessage, {})] })) }), (form.watch('lat') || form.watch('lng')) && (_jsxs("p", { className: "text-xs text-muted-foreground", children: ["\uD83D\uDCCD ", (_c = form.watch('lat')) === null || _c === void 0 ? void 0 : _c.toFixed(5), ", ", (_d = form.watch('lng')) === null || _d === void 0 ? void 0 : _d.toFixed(5)] }))] }));
|
|
95
|
-
}
|