garage-erp/apps/dashboard/shared/components/share-document-dialog.tsx
humam kerdiah fcbba6247d feat: add document sharing functionality across various modules
- Introduced ShareDocumentButton component for sharing documents.
- Added ShareDocumentDialog for email and WhatsApp sharing options.
- Integrated document sharing in estimates, invoices, inspections, job cards, bills, and purchase orders.
- Implemented useDocumentShare hook for handling share logic.
- Created DocumentShareClient for API interactions related to document sharing.
- Updated layouts and actions to include sharing options for relevant entities.
2026-05-14 12:21:01 +04:00

182 lines
7.8 KiB
TypeScript

"use client"
import { useEffect, useState } from "react"
import type { DocumentShareType } from "@garage/api"
import { Button } from "@/shared/components/ui/button"
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/shared/components/ui/dialog"
import { Input } from "@/shared/components/ui/input"
import { Label } from "@/shared/components/ui/label"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/shared/components/ui/tabs"
import { Textarea } from "@/shared/components/ui/textarea"
import { useDocumentShare } from "@/shared/hooks/use-document-share"
interface ShareDocumentDialogProps {
type: DocumentShareType
id: string | number
open: boolean
onOpenChange: (open: boolean) => void
}
const DEFAULT_MESSAGES: Record<string, { email: string; whatsapp: string }> = {
estimate: {
email: "Hello, please find your estimate at the link below. Kindly review the details and let us know if you'd like to proceed.",
whatsapp: "Hello, here is your estimate. Please review and let us know if you'd like to proceed.",
},
invoice: {
email: "Hello, please find your invoice at the link below. Let us know once payment has been arranged.",
whatsapp: "Hello, here is your invoice. Let us know once payment is arranged.",
},
job_card: {
email: "Hello, please find the job card for your vehicle at the link below.",
whatsapp: "Hello, here is the job card for your vehicle.",
},
inspection: {
email: "Hello, please find your vehicle inspection report at the link below.",
whatsapp: "Hello, here is your vehicle inspection report.",
},
payment_received: {
email: "Hello, please find your payment receipt at the link below. Thank you.",
whatsapp: "Hello, here is your payment receipt. Thank you.",
},
purchase_order: {
email: "Hello, please find our purchase order at the link below. Kindly confirm receipt.",
whatsapp: "Hello, here is our purchase order. Kindly confirm receipt.",
},
bill: {
email: "Hello, please find the bill at the link below for your reference.",
whatsapp: "Hello, here is the bill for your reference.",
},
expense: {
email: "Hello, please find the expense document at the link below.",
whatsapp: "Hello, here is the expense document.",
},
payment_made: {
email: "Hello, please find the payment confirmation at the link below.",
whatsapp: "Hello, here is the payment confirmation.",
},
}
function getDefaultMessage(type: DocumentShareType, channel: "email" | "whatsapp"): string {
return DEFAULT_MESSAGES[type as string]?.[channel] ?? ""
}
export function ShareDocumentDialog({ type, id, open, onOpenChange }: ShareDocumentDialogProps) {
const { shareEmail, shareWhatsapp, isSharing } = useDocumentShare(type, id)
const [email, setEmail] = useState("")
const [phone, setPhone] = useState("")
const [emailMessage, setEmailMessage] = useState("")
const [whatsappMessage, setWhatsappMessage] = useState("")
useEffect(() => {
if (open) {
setEmailMessage(getDefaultMessage(type, "email"))
setWhatsappMessage(getDefaultMessage(type, "whatsapp"))
}
}, [open, type])
const close = () => {
onOpenChange(false)
setEmail("")
setPhone("")
setEmailMessage("")
setWhatsappMessage("")
}
const handleEmail = async () => {
if (!email) return
await shareEmail({ email, message: emailMessage || undefined })
close()
}
const handleWhatsapp = async () => {
await shareWhatsapp({ phone: phone || undefined, message: whatsappMessage || undefined })
close()
}
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Share document</DialogTitle>
</DialogHeader>
<Tabs defaultValue="email" className="w-full">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="email">Email</TabsTrigger>
<TabsTrigger value="whatsapp">WhatsApp</TabsTrigger>
</TabsList>
<TabsContent value="email" className="space-y-3 py-2">
<div className="space-y-1.5">
<Label htmlFor="share-email">Recipient email</Label>
<Input
id="share-email"
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
placeholder="customer@example.com"
/>
</div>
<div className="space-y-1.5">
<Label htmlFor="share-email-message">Message</Label>
<Textarea
id="share-email-message"
value={emailMessage}
onChange={(e) => setEmailMessage(e.target.value)}
rows={4}
/>
</div>
<DialogFooter className="pt-2">
<Button variant="outline" type="button" onClick={close}>
Cancel
</Button>
<Button type="button" onClick={handleEmail} disabled={!email || isSharing}>
{isSharing ? "Sending..." : "Send email"}
</Button>
</DialogFooter>
</TabsContent>
<TabsContent value="whatsapp" className="space-y-3 py-2">
<div className="space-y-1.5">
<Label htmlFor="share-phone">Phone with country code (optional)</Label>
<Input
id="share-phone"
type="tel"
value={phone}
onChange={(e) => setPhone(e.target.value)}
placeholder="+971501234567"
/>
<p className="text-xs text-muted-foreground">
Leave empty to pick recipient inside WhatsApp.
</p>
</div>
<div className="space-y-1.5">
<Label htmlFor="share-wa-message">Message</Label>
<Textarea
id="share-wa-message"
value={whatsappMessage}
onChange={(e) => setWhatsappMessage(e.target.value)}
rows={4}
/>
</div>
<DialogFooter className="pt-2">
<Button variant="outline" type="button" onClick={close}>
Cancel
</Button>
<Button type="button" onClick={handleWhatsapp} disabled={isSharing}>
{isSharing ? "Opening..." : "Open WhatsApp"}
</Button>
</DialogFooter>
</TabsContent>
</Tabs>
<p className="text-xs text-muted-foreground text-center">
Share link expires 24 hours after creation.
</p>
</DialogContent>
</Dialog>
)
}