Files
alla-allaos-fullstack/src/features/crm/customers/components/contact-share-sheet.tsx
phaichayon 3f28fde39f task-c.1
2026-06-22 15:49:31 +07:00

174 lines
5.7 KiB
TypeScript

'use client';
import { useMemo, useState } from 'react';
import { useMutation } from '@tanstack/react-query';
import { toast } from 'sonner';
import { Icons } from '@/components/icons';
import { Button } from '@/components/ui/button';
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle
} from '@/components/ui/dialog';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue
} from '@/components/ui/select';
import { Textarea } from '@/components/ui/textarea';
import {
shareCustomerContactMutation,
unshareCustomerContactMutation
} from '../api/mutations';
import type { CustomerContactRecord, CustomerReferenceData } from '../api/types';
import { formatDateTime } from '@/lib/format';
export function ContactShareSheet({
customerId,
contact,
referenceData,
open,
onOpenChange,
canManage
}: {
customerId: string;
contact: CustomerContactRecord | null;
referenceData: CustomerReferenceData;
open: boolean;
onOpenChange: (open: boolean) => void;
canManage: boolean;
}) {
const [sharedToUserId, setSharedToUserId] = useState('');
const [remark, setRemark] = useState('');
const existingSharedIds = useMemo(
() => new Set(contact?.shares.map((item) => item.sharedToUserId) ?? []),
[contact]
);
const candidates = useMemo(
() => referenceData.crmUsers.filter((user) => !existingSharedIds.has(user.id)),
[existingSharedIds, referenceData.crmUsers]
);
const shareMutation = useMutation({
...shareCustomerContactMutation,
onSuccess: () => {
toast.success('แชร์ contact เรียบร้อย');
setSharedToUserId('');
setRemark('');
},
onError: (error) =>
toast.error(error instanceof Error ? error.message : 'ไม่สามารถแชร์ contact ได้')
});
const unshareMutation = useMutation({
...unshareCustomerContactMutation,
onSuccess: () => {
toast.success('ยกเลิกการแชร์เรียบร้อย');
},
onError: (error) =>
toast.error(error instanceof Error ? error.message : 'ไม่สามารถยกเลิกการแชร์ได้')
});
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent>
<DialogHeader>
<DialogTitle>Shared With</DialogTitle>
<DialogDescription> contact </DialogDescription>
</DialogHeader>
<div className='space-y-4'>
{!contact?.shares.length ? (
<div className='text-muted-foreground text-sm'> contact </div>
) : (
<div className='space-y-2'>
{contact.shares.map((share) => (
<div
key={share.id}
className='flex items-start justify-between gap-3 rounded-lg border p-3'
>
<div className='space-y-1 text-sm'>
<div className='font-medium'>{share.sharedToName ?? share.sharedToUserId}</div>
<div className='text-muted-foreground text-xs'>
{formatDateTime(share.sharedAt)} {share.sharedByName ?? share.sharedByUserId}
</div>
{share.remark ? <div className='text-xs'>{share.remark}</div> : null}
</div>
{canManage ? (
<Button
variant='outline'
size='sm'
onClick={() =>
unshareMutation.mutate({
customerId,
contactId: contact.id,
shareId: share.id
})
}
>
<Icons.trash className='mr-2 h-4 w-4' />
Remove
</Button>
) : null}
</div>
))}
</div>
)}
{canManage ? (
<div className='space-y-3 border-t pt-4'>
<Select value={sharedToUserId} onValueChange={setSharedToUserId}>
<SelectTrigger aria-label='Shared user'>
<SelectValue placeholder='Select user' />
</SelectTrigger>
<SelectContent>
{candidates.map((user) => (
<SelectItem key={user.id} value={user.id}>
{user.name}
</SelectItem>
))}
</SelectContent>
</Select>
<Textarea
value={remark}
onChange={(event) => setRemark(event.target.value)}
placeholder='Remark'
/>
</div>
) : null}
</div>
<DialogFooter>
<Button variant='outline' onClick={() => onOpenChange(false)}>
</Button>
{canManage ? (
<Button
isLoading={shareMutation.isPending}
disabled={!contact || !sharedToUserId}
onClick={() => {
if (!contact) {
return;
}
shareMutation.mutate({
customerId,
contactId: contact.id,
values: {
sharedToUserId,
remark
}
});
}}
>
<Icons.check className='mr-2 h-4 w-4' />
Share
</Button>
) : null}
</DialogFooter>
</DialogContent>
</Dialog>
);
}