Files
Ehsan/artifacts/ehsan-poc/src/pages/whatsapp-log.tsx
T

153 lines
6.0 KiB
TypeScript
Raw Normal View History

import { useLanguage } from "../contexts/LanguageContext";
import { useListWhatsappLog, useSendWhatsapp, getListWhatsappLogQueryKey, getListRequestsQueryKey } from "@workspace/api-client-react";
import { useQueryClient } from "@tanstack/react-query";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button";
import { Skeleton } from "@/components/ui/skeleton";
import { Separator } from "@/components/ui/separator";
import { MessageSquare, Phone, Send, CheckCircle, Clock, XCircle } from "lucide-react";
import { useListRequests } from "@workspace/api-client-react";
export default function WhatsappLog() {
const { t } = useLanguage();
const queryClient = useQueryClient();
const { data: logs, isLoading } = useListWhatsappLog();
const { data: allRequests } = useListRequests();
const sendWhatsapp = useSendWhatsapp();
const getRequestByCase = (caseId: string) =>
allRequests?.find((r) => r.caseId === caseId);
const handleSend = (caseId: string) => {
const req = getRequestByCase(caseId);
if (!req) return;
sendWhatsapp.mutate(
{ id: req.id },
{
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: getListWhatsappLogQueryKey() });
queryClient.invalidateQueries({ queryKey: getListRequestsQueryKey() });
},
}
);
};
const statusConfig = {
pending: {
icon: Clock,
className: "bg-amber-100 text-amber-700 border-amber-200",
label: t.whatsapp.pending,
},
sent: {
icon: CheckCircle,
className: "bg-green-100 text-green-700 border-green-200",
label: t.whatsapp.sent,
},
failed: {
icon: XCircle,
className: "bg-red-100 text-red-700 border-red-200",
label: t.whatsapp.failed,
},
};
return (
<div className="container mx-auto px-4 py-12">
<div className="mb-8 flex items-center gap-3">
<MessageSquare className="w-7 h-7 text-primary" />
<h1 className="text-3xl font-bold text-foreground">{t.whatsapp.title}</h1>
</div>
{isLoading ? (
<div className="space-y-4">
{[1, 2, 3].map((i) => (
<Skeleton key={i} className="h-48 w-full" />
))}
</div>
) : !logs || logs.length === 0 ? (
<Card>
<CardContent className="py-16 text-center text-muted-foreground">
No WhatsApp log entries yet.
</CardContent>
</Card>
) : (
<div className="space-y-4">
{logs.map((log) => {
const status = statusConfig[log.status as keyof typeof statusConfig] || statusConfig.pending;
const StatusIcon = status.icon;
return (
<Card key={log.id} className="overflow-hidden" data-testid={`card-whatsapp-${log.id}`}>
<CardHeader className="pb-3 bg-muted/20">
<div className="flex items-center justify-between flex-wrap gap-3">
<div className="flex items-center gap-3">
<CardTitle className="text-base font-mono">{log.caseId}</CardTitle>
<Badge variant="outline" className={status.className}>
<StatusIcon className="w-3 h-3 me-1" />
{status.label}
</Badge>
</div>
{log.status === "pending" && (
<Button
size="sm"
onClick={() => handleSend(log.caseId)}
disabled={sendWhatsapp.isPending}
className="gap-2"
data-testid={`button-sendWhatsapp-${log.id}`}
>
<Send className="w-3.5 h-3.5" />
{t.whatsapp.sendViaOpenClaw}
</Button>
)}
</div>
</CardHeader>
<CardContent className="pt-4">
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{/* Donor Info */}
<div>
<p className="text-xs font-semibold uppercase text-muted-foreground tracking-wide mb-2">
{t.whatsapp.donor}
</p>
<p className="font-medium">{log.donorName}</p>
<div className="flex items-center gap-1.5 text-sm text-muted-foreground mt-1">
<Phone className="w-3.5 h-3.5" />
<span>{log.donorPhone}</span>
</div>
</div>
{/* Beneficiary Message */}
<div>
<p className="text-xs font-semibold uppercase text-muted-foreground tracking-wide mb-2">
Beneficiary Message
</p>
<p className="text-sm text-foreground italic">"{log.beneficiaryMessage}"</p>
</div>
</div>
<Separator className="my-4" />
{/* WhatsApp Message Preview */}
<div>
<p className="text-xs font-semibold uppercase text-muted-foreground tracking-wide mb-2">
{t.whatsapp.message}
</p>
<div className="bg-[#dcf8c6] dark:bg-green-900/30 rounded-xl rounded-tl-sm p-4 max-w-lg text-sm whitespace-pre-line text-gray-800 dark:text-gray-200 border border-green-200 dark:border-green-700">
{log.whatsappMessage}
</div>
</div>
{log.sentAt && (
<p className="text-xs text-muted-foreground mt-3">
{t.whatsapp.sentAt}: {new Date(log.sentAt).toLocaleString()}
</p>
)}
</CardContent>
</Card>
);
})}
</div>
)}
</div>
);
}