@greatapps/greatchat-ui 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +50 -1
- package/dist/index.js +942 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/src/components/contact-avatar.tsx +59 -0
- package/src/components/contact-info-panel.tsx +139 -0
- package/src/components/inbox-item.tsx +149 -0
- package/src/components/inbox-sidebar.tsx +148 -0
- package/src/components/index.ts +15 -0
- package/src/components/new-conversation-dialog.tsx +172 -0
- package/src/components/ui/avatar.tsx +51 -0
- package/src/components/ui/command.tsx +106 -0
- package/src/components/ui/dialog.tsx +133 -0
- package/src/components/ui/input.tsx +19 -0
- package/src/components/ui/scroll-area.tsx +50 -0
- package/src/components/ui/separator.tsx +26 -0
- package/src/components/ui/tabs.tsx +64 -0
- package/src/components/ui/tooltip.tsx +58 -0
- package/src/index.ts +20 -2
package/dist/index.js
CHANGED
|
@@ -1537,14 +1537,956 @@ function ChatView({
|
|
|
1537
1537
|
/* @__PURE__ */ jsx9(ChatInput, { onSend, disabled: sendDisabled })
|
|
1538
1538
|
] });
|
|
1539
1539
|
}
|
|
1540
|
+
|
|
1541
|
+
// src/components/ui/avatar.tsx
|
|
1542
|
+
import { Avatar as AvatarPrimitive } from "radix-ui";
|
|
1543
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
1544
|
+
function Avatar({
|
|
1545
|
+
className,
|
|
1546
|
+
...props
|
|
1547
|
+
}) {
|
|
1548
|
+
return /* @__PURE__ */ jsx10(
|
|
1549
|
+
AvatarPrimitive.Root,
|
|
1550
|
+
{
|
|
1551
|
+
"data-slot": "avatar",
|
|
1552
|
+
className: cn(
|
|
1553
|
+
"relative flex size-8 shrink-0 overflow-hidden rounded-full",
|
|
1554
|
+
className
|
|
1555
|
+
),
|
|
1556
|
+
...props
|
|
1557
|
+
}
|
|
1558
|
+
);
|
|
1559
|
+
}
|
|
1560
|
+
function AvatarFallback({
|
|
1561
|
+
className,
|
|
1562
|
+
...props
|
|
1563
|
+
}) {
|
|
1564
|
+
return /* @__PURE__ */ jsx10(
|
|
1565
|
+
AvatarPrimitive.Fallback,
|
|
1566
|
+
{
|
|
1567
|
+
"data-slot": "avatar-fallback",
|
|
1568
|
+
className: cn(
|
|
1569
|
+
"flex size-full items-center justify-center rounded-full bg-muted",
|
|
1570
|
+
className
|
|
1571
|
+
),
|
|
1572
|
+
...props
|
|
1573
|
+
}
|
|
1574
|
+
);
|
|
1575
|
+
}
|
|
1576
|
+
|
|
1577
|
+
// src/components/contact-avatar.tsx
|
|
1578
|
+
import { jsx as jsx11 } from "react/jsx-runtime";
|
|
1579
|
+
var COLORS = [
|
|
1580
|
+
"bg-red-100 text-red-700 dark:bg-red-900 dark:text-red-300",
|
|
1581
|
+
"bg-orange-100 text-orange-700 dark:bg-orange-900 dark:text-orange-300",
|
|
1582
|
+
"bg-amber-100 text-amber-700 dark:bg-amber-900 dark:text-amber-300",
|
|
1583
|
+
"bg-emerald-100 text-emerald-700 dark:bg-emerald-900 dark:text-emerald-300",
|
|
1584
|
+
"bg-cyan-100 text-cyan-700 dark:bg-cyan-900 dark:text-cyan-300",
|
|
1585
|
+
"bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300",
|
|
1586
|
+
"bg-violet-100 text-violet-700 dark:bg-violet-900 dark:text-violet-300",
|
|
1587
|
+
"bg-pink-100 text-pink-700 dark:bg-pink-900 dark:text-pink-300"
|
|
1588
|
+
];
|
|
1589
|
+
var SIZE_MAP = {
|
|
1590
|
+
sm: "h-8 w-8 text-xs",
|
|
1591
|
+
md: "h-10 w-10 text-xs",
|
|
1592
|
+
lg: "h-16 w-16 text-lg"
|
|
1593
|
+
};
|
|
1594
|
+
function hashCode(str) {
|
|
1595
|
+
let hash = 0;
|
|
1596
|
+
for (let i = 0; i < str.length; i++) {
|
|
1597
|
+
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
|
1598
|
+
}
|
|
1599
|
+
return Math.abs(hash);
|
|
1600
|
+
}
|
|
1601
|
+
function getInitials(name) {
|
|
1602
|
+
const parts = name.trim().split(/\s+/);
|
|
1603
|
+
if (parts.length >= 2) {
|
|
1604
|
+
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
1605
|
+
}
|
|
1606
|
+
return (name[0] || "?").toUpperCase();
|
|
1607
|
+
}
|
|
1608
|
+
function ContactAvatar({
|
|
1609
|
+
name,
|
|
1610
|
+
className,
|
|
1611
|
+
size = "md"
|
|
1612
|
+
}) {
|
|
1613
|
+
const displayName = name || "?";
|
|
1614
|
+
const color = COLORS[hashCode(displayName) % COLORS.length];
|
|
1615
|
+
const initials = getInitials(displayName);
|
|
1616
|
+
return /* @__PURE__ */ jsx11(Avatar, { className: cn(SIZE_MAP[size], className), children: /* @__PURE__ */ jsx11(AvatarFallback, { className: cn("font-medium", color), children: initials }) });
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
// src/components/inbox-item.tsx
|
|
1620
|
+
import { useState as useState3 } from "react";
|
|
1621
|
+
|
|
1622
|
+
// src/components/ui/badge.tsx
|
|
1623
|
+
import { cva as cva2 } from "class-variance-authority";
|
|
1624
|
+
import { Slot as Slot2 } from "radix-ui";
|
|
1625
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
1626
|
+
var badgeVariants = cva2(
|
|
1627
|
+
"h-5 gap-1 rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium transition-all [&>svg]:size-3! inline-flex items-center justify-center w-fit whitespace-nowrap shrink-0 [&>svg]:pointer-events-none overflow-hidden",
|
|
1628
|
+
{
|
|
1629
|
+
variants: {
|
|
1630
|
+
variant: {
|
|
1631
|
+
default: "bg-primary text-primary-foreground",
|
|
1632
|
+
secondary: "bg-secondary text-secondary-foreground",
|
|
1633
|
+
destructive: "bg-destructive/10 text-destructive dark:bg-destructive/20",
|
|
1634
|
+
outline: "border-border text-foreground",
|
|
1635
|
+
ghost: "hover:bg-muted hover:text-muted-foreground"
|
|
1636
|
+
}
|
|
1637
|
+
},
|
|
1638
|
+
defaultVariants: {
|
|
1639
|
+
variant: "default"
|
|
1640
|
+
}
|
|
1641
|
+
}
|
|
1642
|
+
);
|
|
1643
|
+
function Badge({
|
|
1644
|
+
className,
|
|
1645
|
+
variant = "default",
|
|
1646
|
+
asChild = false,
|
|
1647
|
+
...props
|
|
1648
|
+
}) {
|
|
1649
|
+
const Comp = asChild ? Slot2.Root : "span";
|
|
1650
|
+
return /* @__PURE__ */ jsx12(
|
|
1651
|
+
Comp,
|
|
1652
|
+
{
|
|
1653
|
+
"data-slot": "badge",
|
|
1654
|
+
className: cn(badgeVariants({ variant }), className),
|
|
1655
|
+
...props
|
|
1656
|
+
}
|
|
1657
|
+
);
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
// src/components/ui/tooltip.tsx
|
|
1661
|
+
import { Tooltip as TooltipPrimitive } from "radix-ui";
|
|
1662
|
+
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
1663
|
+
function TooltipProvider({
|
|
1664
|
+
delayDuration = 0,
|
|
1665
|
+
...props
|
|
1666
|
+
}) {
|
|
1667
|
+
return /* @__PURE__ */ jsx13(
|
|
1668
|
+
TooltipPrimitive.Provider,
|
|
1669
|
+
{
|
|
1670
|
+
"data-slot": "tooltip-provider",
|
|
1671
|
+
delayDuration,
|
|
1672
|
+
...props
|
|
1673
|
+
}
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
function Tooltip({
|
|
1677
|
+
...props
|
|
1678
|
+
}) {
|
|
1679
|
+
return /* @__PURE__ */ jsx13(TooltipProvider, { children: /* @__PURE__ */ jsx13(TooltipPrimitive.Root, { "data-slot": "tooltip", ...props }) });
|
|
1680
|
+
}
|
|
1681
|
+
function TooltipTrigger({
|
|
1682
|
+
...props
|
|
1683
|
+
}) {
|
|
1684
|
+
return /* @__PURE__ */ jsx13(TooltipPrimitive.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
1685
|
+
}
|
|
1686
|
+
function TooltipContent({
|
|
1687
|
+
className,
|
|
1688
|
+
sideOffset = 4,
|
|
1689
|
+
children,
|
|
1690
|
+
...props
|
|
1691
|
+
}) {
|
|
1692
|
+
return /* @__PURE__ */ jsx13(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx13(
|
|
1693
|
+
TooltipPrimitive.Content,
|
|
1694
|
+
{
|
|
1695
|
+
"data-slot": "tooltip-content",
|
|
1696
|
+
sideOffset,
|
|
1697
|
+
className: cn(
|
|
1698
|
+
"z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
1699
|
+
className
|
|
1700
|
+
),
|
|
1701
|
+
...props,
|
|
1702
|
+
children
|
|
1703
|
+
}
|
|
1704
|
+
) });
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
// src/components/inbox-item.tsx
|
|
1708
|
+
import { formatDistanceToNow } from "date-fns";
|
|
1709
|
+
import { ptBR as ptBR2 } from "date-fns/locale";
|
|
1710
|
+
import { Trash2 as Trash22 } from "lucide-react";
|
|
1711
|
+
import { Fragment, jsx as jsx14, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1712
|
+
var statusColors = {
|
|
1713
|
+
open: "bg-green-500/10 text-green-600 border-green-200",
|
|
1714
|
+
pending: "bg-yellow-500/10 text-yellow-600 border-yellow-200",
|
|
1715
|
+
resolved: "bg-zinc-500/10 text-zinc-500 border-zinc-200"
|
|
1716
|
+
};
|
|
1717
|
+
var statusLabels = {
|
|
1718
|
+
open: "Aberta",
|
|
1719
|
+
pending: "Pendente",
|
|
1720
|
+
resolved: "Resolvida"
|
|
1721
|
+
};
|
|
1722
|
+
function InboxItem({
|
|
1723
|
+
inbox,
|
|
1724
|
+
isSelected,
|
|
1725
|
+
onClick,
|
|
1726
|
+
onDelete,
|
|
1727
|
+
renderActions
|
|
1728
|
+
}) {
|
|
1729
|
+
const [showDeleteDialog, setShowDeleteDialog] = useState3(false);
|
|
1730
|
+
const timestamp = inbox.last_message_at || inbox.datetime_add;
|
|
1731
|
+
const timeAgo = formatDistanceToNow(new Date(timestamp), {
|
|
1732
|
+
addSuffix: true,
|
|
1733
|
+
locale: ptBR2
|
|
1734
|
+
});
|
|
1735
|
+
const lastMessage = inbox.last_message_content_type === "text" ? inbox.last_message_content : inbox.last_message_content_type ? `[${inbox.last_message_content_type}]` : null;
|
|
1736
|
+
const directionPrefix = inbox.last_message_direction === "outbound" ? "Voc\xEA: " : "";
|
|
1737
|
+
return /* @__PURE__ */ jsxs7(Fragment, { children: [
|
|
1738
|
+
/* @__PURE__ */ jsxs7(
|
|
1739
|
+
"div",
|
|
1740
|
+
{
|
|
1741
|
+
className: cn(
|
|
1742
|
+
"flex w-full items-start gap-3 rounded-md p-3 text-left transition-colors hover:bg-accent group relative cursor-pointer",
|
|
1743
|
+
isSelected && "bg-accent"
|
|
1744
|
+
),
|
|
1745
|
+
onClick,
|
|
1746
|
+
children: [
|
|
1747
|
+
/* @__PURE__ */ jsx14(
|
|
1748
|
+
ContactAvatar,
|
|
1749
|
+
{
|
|
1750
|
+
name: inbox.contact_name,
|
|
1751
|
+
className: "mt-0.5",
|
|
1752
|
+
size: "md"
|
|
1753
|
+
}
|
|
1754
|
+
),
|
|
1755
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex-1 overflow-hidden", children: [
|
|
1756
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-2", children: [
|
|
1757
|
+
/* @__PURE__ */ jsx14("span", { className: "truncate font-medium text-sm", children: inbox.contact_name || "Desconhecido" }),
|
|
1758
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1 shrink-0", children: [
|
|
1759
|
+
/* @__PURE__ */ jsx14("span", { className: "text-xs text-muted-foreground", children: timeAgo }),
|
|
1760
|
+
renderActions?.(inbox),
|
|
1761
|
+
onDelete && /* @__PURE__ */ jsxs7(Tooltip, { children: [
|
|
1762
|
+
/* @__PURE__ */ jsx14(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx14(
|
|
1763
|
+
"button",
|
|
1764
|
+
{
|
|
1765
|
+
className: "h-5 w-5 rounded flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity hover:bg-muted text-destructive",
|
|
1766
|
+
onClick: (e) => {
|
|
1767
|
+
e.stopPropagation();
|
|
1768
|
+
setShowDeleteDialog(true);
|
|
1769
|
+
},
|
|
1770
|
+
children: /* @__PURE__ */ jsx14(Trash22, { className: "h-3.5 w-3.5" })
|
|
1771
|
+
}
|
|
1772
|
+
) }),
|
|
1773
|
+
/* @__PURE__ */ jsx14(TooltipContent, { children: "Excluir conversa" })
|
|
1774
|
+
] })
|
|
1775
|
+
] })
|
|
1776
|
+
] }),
|
|
1777
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-center justify-between gap-2 mt-0.5", children: [
|
|
1778
|
+
/* @__PURE__ */ jsx14("p", { className: "truncate text-xs text-muted-foreground", children: lastMessage ? `${directionPrefix}${lastMessage}` : "Sem mensagens" }),
|
|
1779
|
+
/* @__PURE__ */ jsx14(
|
|
1780
|
+
Badge,
|
|
1781
|
+
{
|
|
1782
|
+
variant: "outline",
|
|
1783
|
+
className: cn(
|
|
1784
|
+
"shrink-0 text-[10px] px-1.5 py-0",
|
|
1785
|
+
statusColors[inbox.status]
|
|
1786
|
+
),
|
|
1787
|
+
children: statusLabels[inbox.status] || inbox.status
|
|
1788
|
+
}
|
|
1789
|
+
)
|
|
1790
|
+
] })
|
|
1791
|
+
] })
|
|
1792
|
+
]
|
|
1793
|
+
}
|
|
1794
|
+
),
|
|
1795
|
+
/* @__PURE__ */ jsx14(AlertDialog, { open: showDeleteDialog, onOpenChange: setShowDeleteDialog, children: /* @__PURE__ */ jsxs7(AlertDialogContent, { children: [
|
|
1796
|
+
/* @__PURE__ */ jsxs7(AlertDialogHeader, { children: [
|
|
1797
|
+
/* @__PURE__ */ jsx14(AlertDialogTitle, { children: "Excluir conversa?" }),
|
|
1798
|
+
/* @__PURE__ */ jsxs7(AlertDialogDescription, { children: [
|
|
1799
|
+
"A conversa com ",
|
|
1800
|
+
inbox.contact_name || "este contato",
|
|
1801
|
+
" ser\xE1 removida da lista. As mensagens n\xE3o ser\xE3o apagadas do WhatsApp."
|
|
1802
|
+
] })
|
|
1803
|
+
] }),
|
|
1804
|
+
/* @__PURE__ */ jsxs7(AlertDialogFooter, { children: [
|
|
1805
|
+
/* @__PURE__ */ jsx14(AlertDialogCancel, { children: "Cancelar" }),
|
|
1806
|
+
/* @__PURE__ */ jsx14(
|
|
1807
|
+
AlertDialogAction,
|
|
1808
|
+
{
|
|
1809
|
+
className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
1810
|
+
onClick: () => onDelete?.(inbox.id),
|
|
1811
|
+
children: "Excluir"
|
|
1812
|
+
}
|
|
1813
|
+
)
|
|
1814
|
+
] })
|
|
1815
|
+
] }) })
|
|
1816
|
+
] });
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
// src/components/inbox-sidebar.tsx
|
|
1820
|
+
import { useState as useState4, useMemo as useMemo3 } from "react";
|
|
1821
|
+
|
|
1822
|
+
// src/components/ui/input.tsx
|
|
1823
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1824
|
+
function Input({ className, type, ...props }) {
|
|
1825
|
+
return /* @__PURE__ */ jsx15(
|
|
1826
|
+
"input",
|
|
1827
|
+
{
|
|
1828
|
+
type,
|
|
1829
|
+
"data-slot": "input",
|
|
1830
|
+
className: cn(
|
|
1831
|
+
"flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
|
1832
|
+
className
|
|
1833
|
+
),
|
|
1834
|
+
...props
|
|
1835
|
+
}
|
|
1836
|
+
);
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
// src/components/ui/tabs.tsx
|
|
1840
|
+
import { Tabs as TabsPrimitive } from "radix-ui";
|
|
1841
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1842
|
+
function Tabs({
|
|
1843
|
+
className,
|
|
1844
|
+
...props
|
|
1845
|
+
}) {
|
|
1846
|
+
return /* @__PURE__ */ jsx16(
|
|
1847
|
+
TabsPrimitive.Root,
|
|
1848
|
+
{
|
|
1849
|
+
"data-slot": "tabs",
|
|
1850
|
+
className: cn("flex flex-col gap-2", className),
|
|
1851
|
+
...props
|
|
1852
|
+
}
|
|
1853
|
+
);
|
|
1854
|
+
}
|
|
1855
|
+
function TabsList({
|
|
1856
|
+
className,
|
|
1857
|
+
...props
|
|
1858
|
+
}) {
|
|
1859
|
+
return /* @__PURE__ */ jsx16(
|
|
1860
|
+
TabsPrimitive.List,
|
|
1861
|
+
{
|
|
1862
|
+
"data-slot": "tabs-list",
|
|
1863
|
+
className: cn(
|
|
1864
|
+
"inline-flex h-9 w-fit items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
|
|
1865
|
+
className
|
|
1866
|
+
),
|
|
1867
|
+
...props
|
|
1868
|
+
}
|
|
1869
|
+
);
|
|
1870
|
+
}
|
|
1871
|
+
function TabsTrigger({
|
|
1872
|
+
className,
|
|
1873
|
+
...props
|
|
1874
|
+
}) {
|
|
1875
|
+
return /* @__PURE__ */ jsx16(
|
|
1876
|
+
TabsPrimitive.Trigger,
|
|
1877
|
+
{
|
|
1878
|
+
"data-slot": "tabs-trigger",
|
|
1879
|
+
className: cn(
|
|
1880
|
+
"inline-flex items-center justify-center gap-1.5 rounded-md px-2.5 py-1 text-sm font-medium whitespace-nowrap transition-all disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:size-4",
|
|
1881
|
+
className
|
|
1882
|
+
),
|
|
1883
|
+
...props
|
|
1884
|
+
}
|
|
1885
|
+
);
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
// src/components/ui/scroll-area.tsx
|
|
1889
|
+
import { ScrollArea as ScrollAreaPrimitive } from "radix-ui";
|
|
1890
|
+
import { jsx as jsx17, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1891
|
+
function ScrollArea({
|
|
1892
|
+
className,
|
|
1893
|
+
children,
|
|
1894
|
+
...props
|
|
1895
|
+
}) {
|
|
1896
|
+
return /* @__PURE__ */ jsxs8(
|
|
1897
|
+
ScrollAreaPrimitive.Root,
|
|
1898
|
+
{
|
|
1899
|
+
"data-slot": "scroll-area",
|
|
1900
|
+
className: cn("relative", className),
|
|
1901
|
+
...props,
|
|
1902
|
+
children: [
|
|
1903
|
+
/* @__PURE__ */ jsx17(ScrollAreaPrimitive.Viewport, { className: "h-full w-full rounded-[inherit] [&>div]:!block", children }),
|
|
1904
|
+
/* @__PURE__ */ jsx17(ScrollBar, {}),
|
|
1905
|
+
/* @__PURE__ */ jsx17(ScrollAreaPrimitive.Corner, {})
|
|
1906
|
+
]
|
|
1907
|
+
}
|
|
1908
|
+
);
|
|
1909
|
+
}
|
|
1910
|
+
function ScrollBar({
|
|
1911
|
+
className,
|
|
1912
|
+
orientation = "vertical",
|
|
1913
|
+
...props
|
|
1914
|
+
}) {
|
|
1915
|
+
return /* @__PURE__ */ jsx17(
|
|
1916
|
+
ScrollAreaPrimitive.Scrollbar,
|
|
1917
|
+
{
|
|
1918
|
+
"data-slot": "scroll-bar",
|
|
1919
|
+
orientation,
|
|
1920
|
+
className: cn(
|
|
1921
|
+
"flex touch-none p-px transition-colors select-none",
|
|
1922
|
+
orientation === "vertical" && "h-full w-2.5 border-l border-l-transparent",
|
|
1923
|
+
orientation === "horizontal" && "h-2.5 flex-col border-t border-t-transparent",
|
|
1924
|
+
className
|
|
1925
|
+
),
|
|
1926
|
+
...props,
|
|
1927
|
+
children: /* @__PURE__ */ jsx17(ScrollAreaPrimitive.Thumb, { className: "relative flex-1 rounded-full bg-border" })
|
|
1928
|
+
}
|
|
1929
|
+
);
|
|
1930
|
+
}
|
|
1931
|
+
|
|
1932
|
+
// src/components/inbox-sidebar.tsx
|
|
1933
|
+
import { Search, Plus, Inbox as InboxIcon } from "lucide-react";
|
|
1934
|
+
import { jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1935
|
+
var STATUS_TABS = [
|
|
1936
|
+
{ value: "all", label: "Todas" },
|
|
1937
|
+
{ value: "open", label: "Abertas" },
|
|
1938
|
+
{ value: "pending", label: "Pendentes" },
|
|
1939
|
+
{ value: "resolved", label: "Resolvidas" }
|
|
1940
|
+
];
|
|
1941
|
+
function InboxSidebar({
|
|
1942
|
+
inboxes,
|
|
1943
|
+
isLoading,
|
|
1944
|
+
selectedInboxId,
|
|
1945
|
+
onSelectInbox,
|
|
1946
|
+
onDeleteInbox,
|
|
1947
|
+
onCreateInbox,
|
|
1948
|
+
filterChannelId,
|
|
1949
|
+
renderHeader,
|
|
1950
|
+
renderFooter
|
|
1951
|
+
}) {
|
|
1952
|
+
const [search, setSearch] = useState4("");
|
|
1953
|
+
const [statusFilter, setStatusFilter] = useState4("all");
|
|
1954
|
+
const filtered = useMemo3(() => {
|
|
1955
|
+
if (!inboxes) return [];
|
|
1956
|
+
let list = inboxes;
|
|
1957
|
+
if (filterChannelId != null) {
|
|
1958
|
+
list = list.filter((i) => i.id_channel === filterChannelId);
|
|
1959
|
+
}
|
|
1960
|
+
if (statusFilter !== "all") {
|
|
1961
|
+
list = list.filter((i) => i.status === statusFilter);
|
|
1962
|
+
}
|
|
1963
|
+
if (search) {
|
|
1964
|
+
const q = search.toLowerCase();
|
|
1965
|
+
list = list.filter(
|
|
1966
|
+
(i) => i.contact_name?.toLowerCase().includes(q) || i.contact_phone?.toLowerCase().includes(q) || i.contact_identifier?.toLowerCase().includes(q) || i.last_message_content?.toLowerCase().includes(q)
|
|
1967
|
+
);
|
|
1968
|
+
}
|
|
1969
|
+
return [...list].sort((a, b) => {
|
|
1970
|
+
const dateA = a.last_message_at || a.datetime_add;
|
|
1971
|
+
const dateB = b.last_message_at || b.datetime_add;
|
|
1972
|
+
return new Date(dateB).getTime() - new Date(dateA).getTime();
|
|
1973
|
+
});
|
|
1974
|
+
}, [inboxes, statusFilter, search, filterChannelId]);
|
|
1975
|
+
return /* @__PURE__ */ jsxs9("div", { className: "flex h-full flex-col", children: [
|
|
1976
|
+
renderHeader,
|
|
1977
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex flex-col gap-3 p-3", children: [
|
|
1978
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex items-center justify-between gap-2", children: [
|
|
1979
|
+
/* @__PURE__ */ jsxs9("div", { className: "relative flex-1", children: [
|
|
1980
|
+
/* @__PURE__ */ jsx18(Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
1981
|
+
/* @__PURE__ */ jsx18(
|
|
1982
|
+
Input,
|
|
1983
|
+
{
|
|
1984
|
+
placeholder: "Buscar...",
|
|
1985
|
+
value: search,
|
|
1986
|
+
onChange: (e) => setSearch(e.target.value),
|
|
1987
|
+
className: "pl-9 h-8 text-sm"
|
|
1988
|
+
}
|
|
1989
|
+
)
|
|
1990
|
+
] }),
|
|
1991
|
+
onCreateInbox && /* @__PURE__ */ jsx18(
|
|
1992
|
+
Button,
|
|
1993
|
+
{
|
|
1994
|
+
size: "icon",
|
|
1995
|
+
className: "h-8 w-8 shrink-0",
|
|
1996
|
+
onClick: onCreateInbox,
|
|
1997
|
+
children: /* @__PURE__ */ jsx18(Plus, { className: "h-4 w-4" })
|
|
1998
|
+
}
|
|
1999
|
+
)
|
|
2000
|
+
] }),
|
|
2001
|
+
/* @__PURE__ */ jsx18(Tabs, { value: statusFilter, onValueChange: setStatusFilter, children: /* @__PURE__ */ jsx18(TabsList, { className: "w-full", children: STATUS_TABS.map((tab) => /* @__PURE__ */ jsx18(
|
|
2002
|
+
TabsTrigger,
|
|
2003
|
+
{
|
|
2004
|
+
value: tab.value,
|
|
2005
|
+
className: "flex-1 text-xs",
|
|
2006
|
+
children: tab.label
|
|
2007
|
+
},
|
|
2008
|
+
tab.value
|
|
2009
|
+
)) }) })
|
|
2010
|
+
] }),
|
|
2011
|
+
/* @__PURE__ */ jsx18(ScrollArea, { className: "flex-1 px-2", children: isLoading ? /* @__PURE__ */ jsx18("div", { className: "space-y-2 p-2", children: Array.from({ length: 6 }).map((_, i) => /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-3 p-3", children: [
|
|
2012
|
+
/* @__PURE__ */ jsx18(Skeleton, { className: "h-10 w-10 rounded-full shrink-0" }),
|
|
2013
|
+
/* @__PURE__ */ jsxs9("div", { className: "flex-1 space-y-1.5", children: [
|
|
2014
|
+
/* @__PURE__ */ jsx18(Skeleton, { className: "h-4 w-28" }),
|
|
2015
|
+
/* @__PURE__ */ jsx18(Skeleton, { className: "h-3 w-40" })
|
|
2016
|
+
] })
|
|
2017
|
+
] }, i)) }) : filtered.length === 0 ? /* @__PURE__ */ jsxs9("div", { className: "flex flex-col items-center justify-center gap-2 py-8 text-sm text-muted-foreground", children: [
|
|
2018
|
+
/* @__PURE__ */ jsx18(InboxIcon, { className: "h-8 w-8 opacity-50" }),
|
|
2019
|
+
"Nenhuma conversa encontrada"
|
|
2020
|
+
] }) : filtered.map((inbox) => /* @__PURE__ */ jsx18(
|
|
2021
|
+
InboxItem,
|
|
2022
|
+
{
|
|
2023
|
+
inbox,
|
|
2024
|
+
isSelected: inbox.id === selectedInboxId,
|
|
2025
|
+
onClick: () => onSelectInbox(inbox),
|
|
2026
|
+
onDelete: onDeleteInbox
|
|
2027
|
+
},
|
|
2028
|
+
inbox.id
|
|
2029
|
+
)) }),
|
|
2030
|
+
renderFooter
|
|
2031
|
+
] });
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
// src/components/ui/separator.tsx
|
|
2035
|
+
import { Separator as SeparatorPrimitive } from "radix-ui";
|
|
2036
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
2037
|
+
function Separator({
|
|
2038
|
+
className,
|
|
2039
|
+
orientation = "horizontal",
|
|
2040
|
+
decorative = true,
|
|
2041
|
+
...props
|
|
2042
|
+
}) {
|
|
2043
|
+
return /* @__PURE__ */ jsx19(
|
|
2044
|
+
SeparatorPrimitive.Root,
|
|
2045
|
+
{
|
|
2046
|
+
"data-slot": "separator",
|
|
2047
|
+
decorative,
|
|
2048
|
+
orientation,
|
|
2049
|
+
className: cn(
|
|
2050
|
+
"shrink-0 bg-border data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
|
2051
|
+
className
|
|
2052
|
+
),
|
|
2053
|
+
...props
|
|
2054
|
+
}
|
|
2055
|
+
);
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
// src/components/contact-info-panel.tsx
|
|
2059
|
+
import {
|
|
2060
|
+
X,
|
|
2061
|
+
Phone,
|
|
2062
|
+
Fingerprint,
|
|
2063
|
+
Calendar,
|
|
2064
|
+
CalendarClock,
|
|
2065
|
+
Hash
|
|
2066
|
+
} from "lucide-react";
|
|
2067
|
+
import { format as format2 } from "date-fns";
|
|
2068
|
+
import { ptBR as ptBR3 } from "date-fns/locale";
|
|
2069
|
+
import { Fragment as Fragment2, jsx as jsx20, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
2070
|
+
function InfoRow({
|
|
2071
|
+
icon: Icon,
|
|
2072
|
+
label,
|
|
2073
|
+
value
|
|
2074
|
+
}) {
|
|
2075
|
+
if (!value) return null;
|
|
2076
|
+
return /* @__PURE__ */ jsxs10("div", { className: "flex items-start gap-3 py-2", children: [
|
|
2077
|
+
/* @__PURE__ */ jsx20(Icon, { className: "h-4 w-4 text-muted-foreground mt-0.5 shrink-0" }),
|
|
2078
|
+
/* @__PURE__ */ jsxs10("div", { className: "min-w-0", children: [
|
|
2079
|
+
/* @__PURE__ */ jsx20("p", { className: "text-xs text-muted-foreground", children: label }),
|
|
2080
|
+
/* @__PURE__ */ jsx20("p", { className: "text-sm break-all", children: value })
|
|
2081
|
+
] })
|
|
2082
|
+
] });
|
|
2083
|
+
}
|
|
2084
|
+
function ContactInfoPanel({
|
|
2085
|
+
contact,
|
|
2086
|
+
isLoading,
|
|
2087
|
+
onClose,
|
|
2088
|
+
className
|
|
2089
|
+
}) {
|
|
2090
|
+
return /* @__PURE__ */ jsxs10(
|
|
2091
|
+
"div",
|
|
2092
|
+
{
|
|
2093
|
+
className: cn(
|
|
2094
|
+
"flex h-full w-[320px] shrink-0 flex-col border-l",
|
|
2095
|
+
className
|
|
2096
|
+
),
|
|
2097
|
+
children: [
|
|
2098
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [
|
|
2099
|
+
/* @__PURE__ */ jsx20("span", { className: "text-sm font-medium", children: "Informa\xE7\xF5es do contato" }),
|
|
2100
|
+
onClose && /* @__PURE__ */ jsx20(
|
|
2101
|
+
Button,
|
|
2102
|
+
{
|
|
2103
|
+
variant: "ghost",
|
|
2104
|
+
size: "icon",
|
|
2105
|
+
className: "h-7 w-7",
|
|
2106
|
+
onClick: onClose,
|
|
2107
|
+
children: /* @__PURE__ */ jsx20(X, { className: "h-4 w-4" })
|
|
2108
|
+
}
|
|
2109
|
+
)
|
|
2110
|
+
] }),
|
|
2111
|
+
/* @__PURE__ */ jsx20("div", { className: "flex-1 overflow-y-auto p-4", children: isLoading ? /* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-center gap-3 pt-4", children: [
|
|
2112
|
+
/* @__PURE__ */ jsx20(Skeleton, { className: "h-16 w-16 rounded-full" }),
|
|
2113
|
+
/* @__PURE__ */ jsx20(Skeleton, { className: "h-5 w-32" }),
|
|
2114
|
+
/* @__PURE__ */ jsx20(Skeleton, { className: "h-4 w-24" })
|
|
2115
|
+
] }) : contact ? /* @__PURE__ */ jsxs10(Fragment2, { children: [
|
|
2116
|
+
/* @__PURE__ */ jsxs10("div", { className: "flex flex-col items-center gap-2 pb-4", children: [
|
|
2117
|
+
/* @__PURE__ */ jsx20(ContactAvatar, { name: contact.name, size: "lg" }),
|
|
2118
|
+
/* @__PURE__ */ jsx20("h3", { className: "text-base font-medium text-center", children: contact.name || "Desconhecido" })
|
|
2119
|
+
] }),
|
|
2120
|
+
/* @__PURE__ */ jsx20(Separator, {}),
|
|
2121
|
+
/* @__PURE__ */ jsxs10("div", { className: "mt-3 space-y-1", children: [
|
|
2122
|
+
/* @__PURE__ */ jsx20(InfoRow, { icon: Hash, label: "ID", value: contact.id?.toString() }),
|
|
2123
|
+
/* @__PURE__ */ jsx20(
|
|
2124
|
+
InfoRow,
|
|
2125
|
+
{
|
|
2126
|
+
icon: Phone,
|
|
2127
|
+
label: "Telefone",
|
|
2128
|
+
value: contact.phone_number
|
|
2129
|
+
}
|
|
2130
|
+
),
|
|
2131
|
+
/* @__PURE__ */ jsx20(
|
|
2132
|
+
InfoRow,
|
|
2133
|
+
{
|
|
2134
|
+
icon: Fingerprint,
|
|
2135
|
+
label: "Identificador",
|
|
2136
|
+
value: contact.identifier
|
|
2137
|
+
}
|
|
2138
|
+
),
|
|
2139
|
+
/* @__PURE__ */ jsx20(
|
|
2140
|
+
InfoRow,
|
|
2141
|
+
{
|
|
2142
|
+
icon: Calendar,
|
|
2143
|
+
label: "Criado em",
|
|
2144
|
+
value: contact.datetime_add ? format2(
|
|
2145
|
+
new Date(contact.datetime_add),
|
|
2146
|
+
"dd/MM/yyyy '\xE0s' HH:mm",
|
|
2147
|
+
{ locale: ptBR3 }
|
|
2148
|
+
) : null
|
|
2149
|
+
}
|
|
2150
|
+
),
|
|
2151
|
+
/* @__PURE__ */ jsx20(
|
|
2152
|
+
InfoRow,
|
|
2153
|
+
{
|
|
2154
|
+
icon: CalendarClock,
|
|
2155
|
+
label: "Atualizado em",
|
|
2156
|
+
value: contact.datetime_alt ? format2(
|
|
2157
|
+
new Date(contact.datetime_alt),
|
|
2158
|
+
"dd/MM/yyyy '\xE0s' HH:mm",
|
|
2159
|
+
{ locale: ptBR3 }
|
|
2160
|
+
) : null
|
|
2161
|
+
}
|
|
2162
|
+
)
|
|
2163
|
+
] })
|
|
2164
|
+
] }) : null })
|
|
2165
|
+
]
|
|
2166
|
+
}
|
|
2167
|
+
);
|
|
2168
|
+
}
|
|
2169
|
+
|
|
2170
|
+
// src/components/new-conversation-dialog.tsx
|
|
2171
|
+
import { useState as useState5, useCallback, useEffect as useEffect2 } from "react";
|
|
2172
|
+
|
|
2173
|
+
// src/components/ui/dialog.tsx
|
|
2174
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
2175
|
+
import { X as X2 } from "lucide-react";
|
|
2176
|
+
import { jsx as jsx21, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2177
|
+
function Dialog({
|
|
2178
|
+
...props
|
|
2179
|
+
}) {
|
|
2180
|
+
return /* @__PURE__ */ jsx21(DialogPrimitive.Root, { "data-slot": "dialog", ...props });
|
|
2181
|
+
}
|
|
2182
|
+
function DialogPortal({
|
|
2183
|
+
...props
|
|
2184
|
+
}) {
|
|
2185
|
+
return /* @__PURE__ */ jsx21(DialogPrimitive.Portal, { "data-slot": "dialog-portal", ...props });
|
|
2186
|
+
}
|
|
2187
|
+
function DialogOverlay({
|
|
2188
|
+
className,
|
|
2189
|
+
...props
|
|
2190
|
+
}) {
|
|
2191
|
+
return /* @__PURE__ */ jsx21(
|
|
2192
|
+
DialogPrimitive.Overlay,
|
|
2193
|
+
{
|
|
2194
|
+
"data-slot": "dialog-overlay",
|
|
2195
|
+
className: cn(
|
|
2196
|
+
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
2197
|
+
className
|
|
2198
|
+
),
|
|
2199
|
+
...props
|
|
2200
|
+
}
|
|
2201
|
+
);
|
|
2202
|
+
}
|
|
2203
|
+
function DialogContent({
|
|
2204
|
+
className,
|
|
2205
|
+
children,
|
|
2206
|
+
...props
|
|
2207
|
+
}) {
|
|
2208
|
+
return /* @__PURE__ */ jsxs11(DialogPortal, { children: [
|
|
2209
|
+
/* @__PURE__ */ jsx21(DialogOverlay, {}),
|
|
2210
|
+
/* @__PURE__ */ jsxs11(
|
|
2211
|
+
DialogPrimitive.Content,
|
|
2212
|
+
{
|
|
2213
|
+
"data-slot": "dialog-content",
|
|
2214
|
+
className: cn(
|
|
2215
|
+
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
|
2216
|
+
className
|
|
2217
|
+
),
|
|
2218
|
+
...props,
|
|
2219
|
+
children: [
|
|
2220
|
+
children,
|
|
2221
|
+
/* @__PURE__ */ jsxs11(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground", children: [
|
|
2222
|
+
/* @__PURE__ */ jsx21(X2, { className: "h-4 w-4" }),
|
|
2223
|
+
/* @__PURE__ */ jsx21("span", { className: "sr-only", children: "Close" })
|
|
2224
|
+
] })
|
|
2225
|
+
]
|
|
2226
|
+
}
|
|
2227
|
+
)
|
|
2228
|
+
] });
|
|
2229
|
+
}
|
|
2230
|
+
function DialogHeader({ className, ...props }) {
|
|
2231
|
+
return /* @__PURE__ */ jsx21(
|
|
2232
|
+
"div",
|
|
2233
|
+
{
|
|
2234
|
+
"data-slot": "dialog-header",
|
|
2235
|
+
className: cn("flex flex-col gap-2 text-center sm:text-left", className),
|
|
2236
|
+
...props
|
|
2237
|
+
}
|
|
2238
|
+
);
|
|
2239
|
+
}
|
|
2240
|
+
function DialogFooter({ className, ...props }) {
|
|
2241
|
+
return /* @__PURE__ */ jsx21(
|
|
2242
|
+
"div",
|
|
2243
|
+
{
|
|
2244
|
+
"data-slot": "dialog-footer",
|
|
2245
|
+
className: cn(
|
|
2246
|
+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-2",
|
|
2247
|
+
className
|
|
2248
|
+
),
|
|
2249
|
+
...props
|
|
2250
|
+
}
|
|
2251
|
+
);
|
|
2252
|
+
}
|
|
2253
|
+
function DialogTitle({
|
|
2254
|
+
className,
|
|
2255
|
+
...props
|
|
2256
|
+
}) {
|
|
2257
|
+
return /* @__PURE__ */ jsx21(
|
|
2258
|
+
DialogPrimitive.Title,
|
|
2259
|
+
{
|
|
2260
|
+
"data-slot": "dialog-title",
|
|
2261
|
+
className: cn("text-lg font-semibold leading-none tracking-tight", className),
|
|
2262
|
+
...props
|
|
2263
|
+
}
|
|
2264
|
+
);
|
|
2265
|
+
}
|
|
2266
|
+
function DialogDescription({
|
|
2267
|
+
className,
|
|
2268
|
+
...props
|
|
2269
|
+
}) {
|
|
2270
|
+
return /* @__PURE__ */ jsx21(
|
|
2271
|
+
DialogPrimitive.Description,
|
|
2272
|
+
{
|
|
2273
|
+
"data-slot": "dialog-description",
|
|
2274
|
+
className: cn("text-sm text-muted-foreground", className),
|
|
2275
|
+
...props
|
|
2276
|
+
}
|
|
2277
|
+
);
|
|
2278
|
+
}
|
|
2279
|
+
|
|
2280
|
+
// src/components/ui/command.tsx
|
|
2281
|
+
import { Command as CommandPrimitive } from "cmdk";
|
|
2282
|
+
import { Search as Search2 } from "lucide-react";
|
|
2283
|
+
import { jsx as jsx22, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2284
|
+
function Command({
|
|
2285
|
+
className,
|
|
2286
|
+
...props
|
|
2287
|
+
}) {
|
|
2288
|
+
return /* @__PURE__ */ jsx22(
|
|
2289
|
+
CommandPrimitive,
|
|
2290
|
+
{
|
|
2291
|
+
"data-slot": "command",
|
|
2292
|
+
className: cn(
|
|
2293
|
+
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
|
2294
|
+
className
|
|
2295
|
+
),
|
|
2296
|
+
...props
|
|
2297
|
+
}
|
|
2298
|
+
);
|
|
2299
|
+
}
|
|
2300
|
+
function CommandInput({
|
|
2301
|
+
className,
|
|
2302
|
+
...props
|
|
2303
|
+
}) {
|
|
2304
|
+
return /* @__PURE__ */ jsxs12("div", { className: "flex h-9 items-center gap-2 border-b px-3", "data-slot": "command-input-wrapper", children: [
|
|
2305
|
+
/* @__PURE__ */ jsx22(Search2, { className: "size-4 shrink-0 opacity-50" }),
|
|
2306
|
+
/* @__PURE__ */ jsx22(
|
|
2307
|
+
CommandPrimitive.Input,
|
|
2308
|
+
{
|
|
2309
|
+
"data-slot": "command-input",
|
|
2310
|
+
className: cn(
|
|
2311
|
+
"flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
2312
|
+
className
|
|
2313
|
+
),
|
|
2314
|
+
...props
|
|
2315
|
+
}
|
|
2316
|
+
)
|
|
2317
|
+
] });
|
|
2318
|
+
}
|
|
2319
|
+
function CommandList({
|
|
2320
|
+
className,
|
|
2321
|
+
...props
|
|
2322
|
+
}) {
|
|
2323
|
+
return /* @__PURE__ */ jsx22(
|
|
2324
|
+
CommandPrimitive.List,
|
|
2325
|
+
{
|
|
2326
|
+
"data-slot": "command-list",
|
|
2327
|
+
className: cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className),
|
|
2328
|
+
...props
|
|
2329
|
+
}
|
|
2330
|
+
);
|
|
2331
|
+
}
|
|
2332
|
+
function CommandEmpty({
|
|
2333
|
+
...props
|
|
2334
|
+
}) {
|
|
2335
|
+
return /* @__PURE__ */ jsx22(
|
|
2336
|
+
CommandPrimitive.Empty,
|
|
2337
|
+
{
|
|
2338
|
+
"data-slot": "command-empty",
|
|
2339
|
+
className: "py-6 text-center text-sm",
|
|
2340
|
+
...props
|
|
2341
|
+
}
|
|
2342
|
+
);
|
|
2343
|
+
}
|
|
2344
|
+
function CommandGroup({
|
|
2345
|
+
className,
|
|
2346
|
+
...props
|
|
2347
|
+
}) {
|
|
2348
|
+
return /* @__PURE__ */ jsx22(
|
|
2349
|
+
CommandPrimitive.Group,
|
|
2350
|
+
{
|
|
2351
|
+
"data-slot": "command-group",
|
|
2352
|
+
className: cn(
|
|
2353
|
+
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
|
2354
|
+
className
|
|
2355
|
+
),
|
|
2356
|
+
...props
|
|
2357
|
+
}
|
|
2358
|
+
);
|
|
2359
|
+
}
|
|
2360
|
+
function CommandItem({
|
|
2361
|
+
className,
|
|
2362
|
+
...props
|
|
2363
|
+
}) {
|
|
2364
|
+
return /* @__PURE__ */ jsx22(
|
|
2365
|
+
CommandPrimitive.Item,
|
|
2366
|
+
{
|
|
2367
|
+
"data-slot": "command-item",
|
|
2368
|
+
className: cn(
|
|
2369
|
+
"relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled=true]:pointer-events-none data-[selected=true]:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
2370
|
+
className
|
|
2371
|
+
),
|
|
2372
|
+
...props
|
|
2373
|
+
}
|
|
2374
|
+
);
|
|
2375
|
+
}
|
|
2376
|
+
|
|
2377
|
+
// src/components/new-conversation-dialog.tsx
|
|
2378
|
+
import { Loader2 } from "lucide-react";
|
|
2379
|
+
import { jsx as jsx23, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
2380
|
+
function NewConversationDialog({
|
|
2381
|
+
open,
|
|
2382
|
+
onOpenChange,
|
|
2383
|
+
contacts,
|
|
2384
|
+
channels,
|
|
2385
|
+
existingInboxes,
|
|
2386
|
+
onCreateInbox,
|
|
2387
|
+
isCreating,
|
|
2388
|
+
onCreated
|
|
2389
|
+
}) {
|
|
2390
|
+
const [selectedContact, setSelectedContact] = useState5(null);
|
|
2391
|
+
const [selectedChannelId, setSelectedChannelId] = useState5(
|
|
2392
|
+
null
|
|
2393
|
+
);
|
|
2394
|
+
const effectiveChannelId = selectedChannelId ?? (channels.length === 1 ? channels[0]?.id : null);
|
|
2395
|
+
useEffect2(() => {
|
|
2396
|
+
if (!open) {
|
|
2397
|
+
setSelectedContact(null);
|
|
2398
|
+
setSelectedChannelId(null);
|
|
2399
|
+
}
|
|
2400
|
+
}, [open]);
|
|
2401
|
+
const handleCreate = useCallback(() => {
|
|
2402
|
+
if (!selectedContact || !effectiveChannelId) return;
|
|
2403
|
+
if (existingInboxes) {
|
|
2404
|
+
const existing = existingInboxes.find(
|
|
2405
|
+
(i) => i.id_contact === selectedContact.id && i.id_channel === effectiveChannelId
|
|
2406
|
+
);
|
|
2407
|
+
if (existing) {
|
|
2408
|
+
onCreated?.(existing.id);
|
|
2409
|
+
onOpenChange(false);
|
|
2410
|
+
return;
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
onCreateInbox(selectedContact.id, effectiveChannelId);
|
|
2414
|
+
}, [
|
|
2415
|
+
selectedContact,
|
|
2416
|
+
effectiveChannelId,
|
|
2417
|
+
existingInboxes,
|
|
2418
|
+
onCreateInbox,
|
|
2419
|
+
onCreated,
|
|
2420
|
+
onOpenChange
|
|
2421
|
+
]);
|
|
2422
|
+
return /* @__PURE__ */ jsx23(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs13(DialogContent, { className: "sm:max-w-md p-0 gap-0", children: [
|
|
2423
|
+
/* @__PURE__ */ jsxs13(DialogHeader, { className: "px-4 pt-4 pb-2", children: [
|
|
2424
|
+
/* @__PURE__ */ jsx23(DialogTitle, { children: "Nova conversa" }),
|
|
2425
|
+
/* @__PURE__ */ jsx23(DialogDescription, { children: "Selecione um contato para iniciar uma conversa" })
|
|
2426
|
+
] }),
|
|
2427
|
+
channels.length > 1 && /* @__PURE__ */ jsx23("div", { className: "px-4 pb-2", children: /* @__PURE__ */ jsxs13(
|
|
2428
|
+
Select,
|
|
2429
|
+
{
|
|
2430
|
+
value: selectedChannelId?.toString() ?? "",
|
|
2431
|
+
onValueChange: (v) => setSelectedChannelId(Number(v)),
|
|
2432
|
+
children: [
|
|
2433
|
+
/* @__PURE__ */ jsx23(SelectTrigger, { className: "h-9", children: /* @__PURE__ */ jsx23(SelectValue, { placeholder: "Selecione um canal" }) }),
|
|
2434
|
+
/* @__PURE__ */ jsx23(SelectContent, { children: channels.map((ch) => /* @__PURE__ */ jsx23(SelectItem, { value: ch.id.toString(), children: ch.name }, ch.id)) })
|
|
2435
|
+
]
|
|
2436
|
+
}
|
|
2437
|
+
) }),
|
|
2438
|
+
/* @__PURE__ */ jsxs13(Command, { className: "rounded-none border-none shadow-none", children: [
|
|
2439
|
+
/* @__PURE__ */ jsx23("div", { className: "px-2", children: /* @__PURE__ */ jsx23(CommandInput, { placeholder: "Buscar contato..." }) }),
|
|
2440
|
+
/* @__PURE__ */ jsxs13(CommandList, { className: "max-h-64 px-2", children: [
|
|
2441
|
+
/* @__PURE__ */ jsx23(CommandEmpty, { children: "Nenhum contato encontrado" }),
|
|
2442
|
+
/* @__PURE__ */ jsx23(CommandGroup, { children: contacts.map((contact) => /* @__PURE__ */ jsxs13(
|
|
2443
|
+
CommandItem,
|
|
2444
|
+
{
|
|
2445
|
+
value: `${contact.name} ${contact.phone_number || ""}`,
|
|
2446
|
+
onSelect: () => setSelectedContact(contact),
|
|
2447
|
+
"data-checked": selectedContact?.id === contact.id,
|
|
2448
|
+
className: "gap-3",
|
|
2449
|
+
children: [
|
|
2450
|
+
/* @__PURE__ */ jsx23(ContactAvatar, { name: contact.name, size: "sm" }),
|
|
2451
|
+
/* @__PURE__ */ jsxs13("div", { className: "min-w-0 flex-1", children: [
|
|
2452
|
+
/* @__PURE__ */ jsx23("p", { className: "truncate text-sm font-medium", children: contact.name }),
|
|
2453
|
+
/* @__PURE__ */ jsx23("p", { className: "truncate text-xs text-muted-foreground", children: contact.phone_number || contact.identifier || "Sem telefone" })
|
|
2454
|
+
] })
|
|
2455
|
+
]
|
|
2456
|
+
},
|
|
2457
|
+
contact.id
|
|
2458
|
+
)) })
|
|
2459
|
+
] })
|
|
2460
|
+
] }),
|
|
2461
|
+
/* @__PURE__ */ jsxs13(DialogFooter, { className: "px-4 py-3 border-t", children: [
|
|
2462
|
+
/* @__PURE__ */ jsx23(Button, { variant: "outline", onClick: () => onOpenChange(false), children: "Cancelar" }),
|
|
2463
|
+
/* @__PURE__ */ jsxs13(
|
|
2464
|
+
Button,
|
|
2465
|
+
{
|
|
2466
|
+
disabled: !selectedContact || !effectiveChannelId || isCreating,
|
|
2467
|
+
onClick: handleCreate,
|
|
2468
|
+
children: [
|
|
2469
|
+
isCreating && /* @__PURE__ */ jsx23(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
2470
|
+
"Iniciar conversa"
|
|
2471
|
+
]
|
|
2472
|
+
}
|
|
2473
|
+
)
|
|
2474
|
+
] })
|
|
2475
|
+
] }) });
|
|
2476
|
+
}
|
|
1540
2477
|
export {
|
|
1541
2478
|
ChatInput,
|
|
1542
2479
|
ChatView,
|
|
2480
|
+
ContactAvatar,
|
|
2481
|
+
ContactInfoPanel,
|
|
1543
2482
|
DEFAULT_CHANNEL_STATUS_POLLING,
|
|
1544
2483
|
DEFAULT_INBOX_POLLING,
|
|
1545
2484
|
DEFAULT_MESSAGES_POLLING,
|
|
1546
2485
|
DEFAULT_QR_POLLING,
|
|
2486
|
+
InboxItem,
|
|
2487
|
+
InboxSidebar,
|
|
1547
2488
|
MessageBubble,
|
|
2489
|
+
NewConversationDialog,
|
|
1548
2490
|
cn,
|
|
1549
2491
|
createGchatClient,
|
|
1550
2492
|
formatDateGroup,
|