dstpabuaran.com/resources/js/pages/admin/manage/invoice/invoice-share-button.tsx
Yoga Pangestu 2a0b99c599 feat: implement invoice management features including index, create, update, delete, and print functionalities
- Added InvoiceIndex component for displaying a list of invoices with pagination and search capabilities.
- Created InvoiceShareButton component for sharing invoice details via WhatsApp.
- Developed InvoicePrint component for printing invoice details.
- Defined routes for invoice management including share and print functionalities.
- Implemented InvoiceTest to cover authentication, authorization, and CRUD operations for invoices.
2026-08-22 15:13:28 +07:00

128 lines
3.7 KiB
TypeScript

import { Share2 } from 'lucide-react';
import { useState } from 'react';
import { Button } from '@/components/ui/button';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from '@/components/ui/tooltip';
import { share as invoiceShare } from '@/routes/admin/manage/invoices';
export type ShareableInvoice = {
id: number;
invoice_number: string;
customer_name: string;
formatted_amount: string;
formatted_date: string;
formatted_due_date?: string | null;
status_label: string;
};
function generateShareLink(invoiceId: number): string {
return window.location.origin + invoiceShare.url(invoiceId);
}
function generateWhatsappText(invoice: ShareableInvoice): string {
const shareLink = generateShareLink(invoice.id);
let text = `*Invoice ${invoice.invoice_number}*\n`;
text += `Kepada: ${invoice.customer_name}\n`;
text += `Tanggal: ${invoice.formatted_date}\n`;
if (invoice.formatted_due_date) {
text += `Jatuh Tempo: ${invoice.formatted_due_date}\n`;
}
text += `Status: ${invoice.status_label}\n`;
text += `Total: ${invoice.formatted_amount}\n`;
text += `\nLihat detail invoice:\n${shareLink}`;
return text;
}
function openWAWeb(text: string) {
const encoded = encodeURIComponent(text);
window.open(`https://wa.me/?text=${encoded}`, '_blank');
}
function openWAAndroid(text: string, pkg: string) {
const encoded = encodeURIComponent(text);
window.open(
`intent://send?text=${encoded}#Intent;scheme=whatsapp;package=${pkg};end`,
'_blank',
);
}
function shareViaWhatsAppMessenger(text: string) {
if (/android/i.test(navigator.userAgent)) {
openWAAndroid(text, 'com.whatsapp');
} else {
openWAWeb(text);
}
}
function shareViaWhatsAppBusiness(text: string) {
if (/android/i.test(navigator.userAgent)) {
openWAAndroid(text, 'com.whatsapp.w4b');
} else {
openWAWeb(text);
}
}
type Props = {
invoice: ShareableInvoice;
};
export function InvoiceShareButton({ invoice }: Props) {
const [shareOpen, setShareOpen] = useState(false);
const shareText = generateWhatsappText(invoice);
function handleShareWAMessenger() {
shareViaWhatsAppMessenger(shareText);
setShareOpen(false);
}
function handleShareWABusiness() {
shareViaWhatsAppBusiness(shareText);
setShareOpen(false);
}
return (
<Tooltip>
<Popover open={shareOpen} onOpenChange={setShareOpen}>
<TooltipTrigger asChild>
<PopoverTrigger asChild>
<Button variant="ghost" size="icon" className="h-8 w-8">
<Share2 className="h-4 w-4" />
</Button>
</PopoverTrigger>
</TooltipTrigger>
<TooltipContent>Bagikan ke WhatsApp</TooltipContent>
<PopoverContent align="end" className="w-48 space-y-1 p-2">
<Button
variant="ghost"
size="sm"
className="w-full justify-start gap-2"
onClick={handleShareWAMessenger}
>
WhatsApp Messenger
</Button>
<Button
variant="ghost"
size="sm"
className="w-full justify-start gap-2"
onClick={handleShareWABusiness}
>
WhatsApp Business
</Button>
</PopoverContent>
</Popover>
</Tooltip>
);
}