This commit is contained in:
NotII
2025-07-30 12:25:46 +02:00
parent 1b51f29c24
commit 4d1c37de92
3 changed files with 175 additions and 3 deletions

View File

@@ -3,12 +3,13 @@
import { useState, useRef } from "react";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from "@/components/ui/dialog";
import { Send, Bold, Italic, Code, Link as LinkIcon, Image as ImageIcon, X, Eye, EyeOff } from "lucide-react";
import { Send, Bold, Italic, Code, Link as LinkIcon, Image as ImageIcon, X, Eye, EyeOff, Package } from "lucide-react";
import { toast } from "sonner";
import { apiRequest } from "@/lib/api";
import { cn } from "@/lib/utils/general";
import { Textarea } from "@/components/ui/textarea";
import ReactMarkdown from 'react-markdown';
import ProductSelector from "./product-selector";
interface BroadcastDialogProps {
open: boolean;
@@ -21,6 +22,8 @@ export default function BroadcastDialog({ open, setOpen }: BroadcastDialogProps)
const [isSending, setIsSending] = useState(false);
const [selectedImage, setSelectedImage] = useState<File | null>(null);
const [imagePreview, setImagePreview] = useState<string | null>(null);
const [selectedProducts, setSelectedProducts] = useState<string[]>([]);
const [showProductSelector, setShowProductSelector] = useState(false);
const textareaRef = useRef<HTMLTextAreaElement>(null);
const fileInputRef = useRef<HTMLInputElement>(null);
@@ -111,6 +114,9 @@ export default function BroadcastDialog({ open, setOpen }: BroadcastDialogProps)
if (broadcastMessage.trim()) {
formData.append('message', broadcastMessage);
}
if (selectedProducts.length > 0) {
formData.append('productIds', JSON.stringify(selectedProducts));
}
const res = await fetch(`/api/storefront/broadcast`, {
method: 'POST',
@@ -127,7 +133,10 @@ export default function BroadcastDialog({ open, setOpen }: BroadcastDialogProps)
response = await res.json();
} else {
response = await apiRequest("/storefront/broadcast", "POST", { message: broadcastMessage });
response = await apiRequest("/storefront/broadcast", "POST", {
message: broadcastMessage,
productIds: selectedProducts
});
}
if (response.error) throw new Error(response.error);
@@ -136,6 +145,7 @@ export default function BroadcastDialog({ open, setOpen }: BroadcastDialogProps)
setBroadcastMessage("");
setSelectedImage(null);
setImagePreview(null);
setSelectedProducts([]);
setOpen(false);
} catch (error) {
console.error("Broadcast error:", error);
@@ -207,6 +217,16 @@ export default function BroadcastDialog({ open, setOpen }: BroadcastDialogProps)
>
<ImageIcon className="h-4 w-4" />
</Button>
<Button
type="button"
variant="outline"
size="icon"
onClick={() => setShowProductSelector(!showProductSelector)}
title="Add Products"
className={selectedProducts.length > 0 ? "bg-blue-100 dark:bg-blue-900" : ""}
>
<Package className="h-4 w-4" />
</Button>
<div className="ml-auto">
<Button
type="button"
@@ -258,6 +278,34 @@ __italic text__
</Button>
</div>
)}
{showProductSelector && (
<div className="border rounded-lg p-4">
<h4 className="font-medium mb-3">Select Products to Include</h4>
<ProductSelector
selectedProducts={selectedProducts}
onSelectionChange={setSelectedProducts}
/>
</div>
)}
{selectedProducts.length > 0 && !showProductSelector && (
<div className="border rounded-lg p-3 bg-muted/50">
<div className="flex items-center justify-between mb-2">
<span className="text-sm font-medium">Selected Products ({selectedProducts.length})</span>
<Button
variant="ghost"
size="sm"
onClick={() => setShowProductSelector(true)}
>
Edit
</Button>
</div>
<div className="text-sm text-muted-foreground">
Products will be added as interactive buttons in the broadcast message.
</div>
</div>
)}
</div>
<div className="text-sm text-gray-500">