@djangocfg/ext-support 1.0.21 → 1.0.23

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/hooks.js CHANGED
@@ -3,7 +3,8 @@ import pRetry, { AbortError } from 'p-retry';
3
3
  import { z } from 'zod';
4
4
  import { initializeExtensionAPI, createExtensionAPI } from '@djangocfg/ext-base/api';
5
5
  import { Clock, MessageSquare, Loader2, Send, Plus, Headphones, User, ArrowLeft, LifeBuoy } from 'lucide-react';
6
- import React7, { createContext, useContext, useState, useCallback, useEffect, useRef } from 'react';
6
+ import React8, { createContext, useContext, useMemo, useCallback, useState, useEffect, useRef } from 'react';
7
+ import { useLocale } from 'next-intl';
7
8
  import { Card, CardContent, Badge, Skeleton, ScrollArea, Button, Textarea, useToast as useToast$1, Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, Form, FormField, FormItem, FormLabel, FormControl, Input, FormMessage, Avatar, AvatarImage, AvatarFallback, ResizablePanelGroup, ResizablePanel, ResizableHandle } from '@djangocfg/ui-core';
8
9
  import useSWR, { useSWRConfig } from 'swr';
9
10
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -1615,6 +1616,233 @@ var API = class {
1615
1616
  };
1616
1617
  initializeExtensionAPI(configureAPI);
1617
1618
  var apiSupport = createExtensionAPI(API);
1619
+
1620
+ // src/i18n/locales/en.ts
1621
+ var en = {
1622
+ layout: {
1623
+ title: "Support Center",
1624
+ titleShort: "Support",
1625
+ subtitle: "Get help from our support team",
1626
+ newTicket: "New Ticket"
1627
+ },
1628
+ status: {
1629
+ open: "Open",
1630
+ waitingForUser: "Waiting for you",
1631
+ waitingForAdmin: "Waiting for support",
1632
+ resolved: "Resolved",
1633
+ closed: "Closed"
1634
+ },
1635
+ ticketList: {
1636
+ noTickets: "No tickets yet",
1637
+ noTicketsDescription: "Create your first support ticket to get help",
1638
+ loadingMore: "Loading more...",
1639
+ loadMore: "Load more",
1640
+ allLoaded: "All {count} tickets loaded"
1641
+ },
1642
+ createTicket: {
1643
+ title: "New Support Ticket",
1644
+ description: "Describe your issue and we will help you",
1645
+ subjectLabel: "Subject",
1646
+ subjectPlaceholder: "Brief description of your issue",
1647
+ messageLabel: "Message",
1648
+ messagePlaceholder: "Describe your issue in detail...",
1649
+ cancel: "Cancel",
1650
+ creating: "Creating...",
1651
+ create: "Create Ticket"
1652
+ },
1653
+ validation: {
1654
+ subjectRequired: "Subject is required",
1655
+ subjectTooLong: "Subject is too long (max 200 characters)",
1656
+ messageRequired: "Message is required",
1657
+ messageTooLong: "Message is too long (max 5000 characters)"
1658
+ },
1659
+ messages: {
1660
+ ticketCreated: "Ticket created successfully",
1661
+ ticketCreateFailed: "Failed to create ticket",
1662
+ messageSent: "Message sent",
1663
+ messageSendFailed: "Failed to send message"
1664
+ },
1665
+ messageInput: {
1666
+ placeholder: "Type your message...",
1667
+ ticketClosed: "Ticket closed",
1668
+ ticketClosedDescription: "This ticket has been closed. Create a new ticket if you need further assistance."
1669
+ },
1670
+ messageList: {
1671
+ noTicketSelected: "No ticket selected",
1672
+ noTicketSelectedDescription: "Select a ticket from the list to view messages",
1673
+ noMessages: "No messages yet",
1674
+ noMessagesDescription: "Start the conversation by sending a message",
1675
+ loadingOlder: "Loading older messages...",
1676
+ loadOlder: "Load older messages",
1677
+ supportTeam: "Support Team",
1678
+ staff: "Staff"
1679
+ },
1680
+ time: {
1681
+ justNow: "Just now",
1682
+ minutesAgo: "{count} min ago",
1683
+ hoursAgo: "{count}h ago",
1684
+ daysAgo: "{count}d ago"
1685
+ }
1686
+ };
1687
+
1688
+ // src/i18n/locales/ru.ts
1689
+ var ru = {
1690
+ layout: {
1691
+ title: "\u0426\u0435\u043D\u0442\u0440 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0438",
1692
+ titleShort: "\u041F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0430",
1693
+ subtitle: "\u041F\u043E\u043B\u0443\u0447\u0438\u0442\u0435 \u043F\u043E\u043C\u043E\u0449\u044C \u043E\u0442 \u043D\u0430\u0448\u0435\u0439 \u043A\u043E\u043C\u0430\u043D\u0434\u044B \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0438",
1694
+ newTicket: "\u041D\u043E\u0432\u043E\u0435 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435"
1695
+ },
1696
+ status: {
1697
+ open: "\u041E\u0442\u043A\u0440\u044B\u0442",
1698
+ waitingForUser: "\u041E\u0436\u0438\u0434\u0430\u0435\u0442 \u0432\u0430\u0441",
1699
+ waitingForAdmin: "\u041E\u0436\u0438\u0434\u0430\u0435\u0442 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0443",
1700
+ resolved: "\u0420\u0435\u0448\u0451\u043D",
1701
+ closed: "\u0417\u0430\u043A\u0440\u044B\u0442"
1702
+ },
1703
+ ticketList: {
1704
+ noTickets: "\u041D\u0435\u0442 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0439",
1705
+ noTicketsDescription: "\u0421\u043E\u0437\u0434\u0430\u0439\u0442\u0435 \u043F\u0435\u0440\u0432\u043E\u0435 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435, \u0447\u0442\u043E\u0431\u044B \u043F\u043E\u043B\u0443\u0447\u0438\u0442\u044C \u043F\u043E\u043C\u043E\u0449\u044C",
1706
+ loadingMore: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430...",
1707
+ loadMore: "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0435\u0449\u0451",
1708
+ allLoaded: "\u0412\u0441\u0435 {count} \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0439 \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043D\u043E"
1709
+ },
1710
+ createTicket: {
1711
+ title: "\u041D\u043E\u0432\u043E\u0435 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435",
1712
+ description: "\u041E\u043F\u0438\u0448\u0438\u0442\u0435 \u0432\u0430\u0448\u0443 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u0443, \u0438 \u043C\u044B \u043F\u043E\u043C\u043E\u0436\u0435\u043C \u0432\u0430\u043C",
1713
+ subjectLabel: "\u0422\u0435\u043C\u0430",
1714
+ subjectPlaceholder: "\u041A\u0440\u0430\u0442\u043A\u043E\u0435 \u043E\u043F\u0438\u0441\u0430\u043D\u0438\u0435 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u044B",
1715
+ messageLabel: "\u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435",
1716
+ messagePlaceholder: "\u041E\u043F\u0438\u0448\u0438\u0442\u0435 \u0432\u0430\u0448\u0443 \u043F\u0440\u043E\u0431\u043B\u0435\u043C\u0443 \u043F\u043E\u0434\u0440\u043E\u0431\u043D\u043E...",
1717
+ cancel: "\u041E\u0442\u043C\u0435\u043D\u0430",
1718
+ creating: "\u0421\u043E\u0437\u0434\u0430\u043D\u0438\u0435...",
1719
+ create: "\u0421\u043E\u0437\u0434\u0430\u0442\u044C \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435"
1720
+ },
1721
+ validation: {
1722
+ subjectRequired: "\u0422\u0435\u043C\u0430 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u0430",
1723
+ subjectTooLong: "\u0422\u0435\u043C\u0430 \u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u0430\u044F (\u043C\u0430\u043A\u0441. 200 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432)",
1724
+ messageRequired: "\u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043E\u0431\u044F\u0437\u0430\u0442\u0435\u043B\u044C\u043D\u043E",
1725
+ messageTooLong: "\u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u0441\u043B\u0438\u0448\u043A\u043E\u043C \u0434\u043B\u0438\u043D\u043D\u043E\u0435 (\u043C\u0430\u043A\u0441. 5000 \u0441\u0438\u043C\u0432\u043E\u043B\u043E\u0432)"
1726
+ },
1727
+ messages: {
1728
+ ticketCreated: "\u041E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u0441\u043E\u0437\u0434\u0430\u043D\u043E",
1729
+ ticketCreateFailed: "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u0441\u043E\u0437\u0434\u0430\u0442\u044C \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435",
1730
+ messageSent: "\u0421\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435 \u043E\u0442\u043F\u0440\u0430\u0432\u043B\u0435\u043D\u043E",
1731
+ messageSendFailed: "\u041D\u0435 \u0443\u0434\u0430\u043B\u043E\u0441\u044C \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435"
1732
+ },
1733
+ messageInput: {
1734
+ placeholder: "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435...",
1735
+ ticketClosed: "\u041E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u0437\u0430\u043A\u0440\u044B\u0442\u043E",
1736
+ ticketClosedDescription: "\u042D\u0442\u043E \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u0437\u0430\u043A\u0440\u044B\u0442\u043E. \u0421\u043E\u0437\u0434\u0430\u0439\u0442\u0435 \u043D\u043E\u0432\u043E\u0435, \u0435\u0441\u043B\u0438 \u0432\u0430\u043C \u043D\u0443\u0436\u043D\u0430 \u043F\u043E\u043C\u043E\u0449\u044C."
1737
+ },
1738
+ messageList: {
1739
+ noTicketSelected: "\u041E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u043D\u0435 \u0432\u044B\u0431\u0440\u0430\u043D\u043E",
1740
+ noTicketSelectedDescription: "\u0412\u044B\u0431\u0435\u0440\u0438\u0442\u0435 \u043E\u0431\u0440\u0430\u0449\u0435\u043D\u0438\u0435 \u0438\u0437 \u0441\u043F\u0438\u0441\u043A\u0430 \u0434\u043B\u044F \u043F\u0440\u043E\u0441\u043C\u043E\u0442\u0440\u0430 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439",
1741
+ noMessages: "\u041D\u0435\u0442 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439",
1742
+ noMessagesDescription: "\u041D\u0430\u0447\u043D\u0438\u0442\u0435 \u0434\u0438\u0430\u043B\u043E\u0433, \u043E\u0442\u043F\u0440\u0430\u0432\u0438\u0432 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0435",
1743
+ loadingOlder: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430 \u0441\u0442\u0430\u0440\u044B\u0445 \u0441\u043E\u043E\u0431\u0449\u0435\u043D\u0438\u0439...",
1744
+ loadOlder: "\u0417\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044C \u0441\u0442\u0430\u0440\u044B\u0435",
1745
+ supportTeam: "\u0421\u043B\u0443\u0436\u0431\u0430 \u043F\u043E\u0434\u0434\u0435\u0440\u0436\u043A\u0438",
1746
+ staff: "\u0421\u043E\u0442\u0440\u0443\u0434\u043D\u0438\u043A"
1747
+ },
1748
+ time: {
1749
+ justNow: "\u0422\u043E\u043B\u044C\u043A\u043E \u0447\u0442\u043E",
1750
+ minutesAgo: "{count} \u043C\u0438\u043D \u043D\u0430\u0437\u0430\u0434",
1751
+ hoursAgo: "{count}\u0447 \u043D\u0430\u0437\u0430\u0434",
1752
+ daysAgo: "{count}\u0434 \u043D\u0430\u0437\u0430\u0434"
1753
+ }
1754
+ };
1755
+
1756
+ // src/i18n/locales/ko.ts
1757
+ var ko = {
1758
+ layout: {
1759
+ title: "\uACE0\uAC1D\uC9C0\uC6D0 \uC13C\uD130",
1760
+ titleShort: "\uACE0\uAC1D\uC9C0\uC6D0",
1761
+ subtitle: "\uACE0\uAC1D\uC9C0\uC6D0\uD300\uC758 \uB3C4\uC6C0\uC744 \uBC1B\uC73C\uC138\uC694",
1762
+ newTicket: "\uC0C8 \uBB38\uC758"
1763
+ },
1764
+ status: {
1765
+ open: "\uC5F4\uB9BC",
1766
+ waitingForUser: "\uD68C\uC2E0 \uB300\uAE30",
1767
+ waitingForAdmin: "\uC9C0\uC6D0\uD300 \uB300\uAE30",
1768
+ resolved: "\uD574\uACB0\uB428",
1769
+ closed: "\uC885\uB8CC"
1770
+ },
1771
+ ticketList: {
1772
+ noTickets: "\uBB38\uC758 \uB0B4\uC5ED \uC5C6\uC74C",
1773
+ noTicketsDescription: "\uCCAB \uBC88\uC9F8 \uBB38\uC758\uB97C \uB4F1\uB85D\uD558\uC5EC \uB3C4\uC6C0\uC744 \uBC1B\uC73C\uC138\uC694",
1774
+ loadingMore: "\uBD88\uB7EC\uC624\uB294 \uC911...",
1775
+ loadMore: "\uB354 \uBCF4\uAE30",
1776
+ allLoaded: "\uCD1D {count}\uAC1C\uC758 \uBB38\uC758\uAC00 \uB85C\uB4DC\uB428"
1777
+ },
1778
+ createTicket: {
1779
+ title: "\uC0C8 \uBB38\uC758",
1780
+ description: "\uBB38\uC81C\uB97C \uC124\uBA85\uD574 \uC8FC\uC2DC\uBA74 \uB3C4\uC6C0\uC744 \uB4DC\uB9AC\uACA0\uC2B5\uB2C8\uB2E4",
1781
+ subjectLabel: "\uC81C\uBAA9",
1782
+ subjectPlaceholder: "\uBB38\uC81C\uC5D0 \uB300\uD55C \uAC04\uB7B5\uD55C \uC124\uBA85",
1783
+ messageLabel: "\uB0B4\uC6A9",
1784
+ messagePlaceholder: "\uBB38\uC81C\uB97C \uC790\uC138\uD788 \uC124\uBA85\uD574 \uC8FC\uC138\uC694...",
1785
+ cancel: "\uCDE8\uC18C",
1786
+ creating: "\uC0DD\uC131 \uC911...",
1787
+ create: "\uBB38\uC758 \uB4F1\uB85D"
1788
+ },
1789
+ validation: {
1790
+ subjectRequired: "\uC81C\uBAA9\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694",
1791
+ subjectTooLong: "\uC81C\uBAA9\uC774 \uB108\uBB34 \uAE41\uB2C8\uB2E4 (\uCD5C\uB300 200\uC790)",
1792
+ messageRequired: "\uB0B4\uC6A9\uC744 \uC785\uB825\uD574 \uC8FC\uC138\uC694",
1793
+ messageTooLong: "\uB0B4\uC6A9\uC774 \uB108\uBB34 \uAE41\uB2C8\uB2E4 (\uCD5C\uB300 5000\uC790)"
1794
+ },
1795
+ messages: {
1796
+ ticketCreated: "\uBB38\uC758\uAC00 \uB4F1\uB85D\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
1797
+ ticketCreateFailed: "\uBB38\uC758 \uB4F1\uB85D\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4",
1798
+ messageSent: "\uBA54\uC2DC\uC9C0\uAC00 \uC804\uC1A1\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
1799
+ messageSendFailed: "\uBA54\uC2DC\uC9C0 \uC804\uC1A1\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4"
1800
+ },
1801
+ messageInput: {
1802
+ placeholder: "\uBA54\uC2DC\uC9C0\uB97C \uC785\uB825\uD558\uC138\uC694...",
1803
+ ticketClosed: "\uBB38\uC758 \uC885\uB8CC\uB428",
1804
+ ticketClosedDescription: "\uC774 \uBB38\uC758\uB294 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uCD94\uAC00 \uB3C4\uC6C0\uC774 \uD544\uC694\uD558\uC2DC\uBA74 \uC0C8 \uBB38\uC758\uB97C \uB4F1\uB85D\uD574 \uC8FC\uC138\uC694."
1805
+ },
1806
+ messageList: {
1807
+ noTicketSelected: "\uBB38\uC758\uAC00 \uC120\uD0DD\uB418\uC9C0 \uC54A\uC74C",
1808
+ noTicketSelectedDescription: "\uBA54\uC2DC\uC9C0\uB97C \uBCF4\uB824\uBA74 \uBAA9\uB85D\uC5D0\uC11C \uBB38\uC758\uB97C \uC120\uD0DD\uD558\uC138\uC694",
1809
+ noMessages: "\uBA54\uC2DC\uC9C0 \uC5C6\uC74C",
1810
+ noMessagesDescription: "\uBA54\uC2DC\uC9C0\uB97C \uBCF4\uB0B4 \uB300\uD654\uB97C \uC2DC\uC791\uD558\uC138\uC694",
1811
+ loadingOlder: "\uC774\uC804 \uBA54\uC2DC\uC9C0 \uBD88\uB7EC\uC624\uB294 \uC911...",
1812
+ loadOlder: "\uC774\uC804 \uBA54\uC2DC\uC9C0 \uBCF4\uAE30",
1813
+ supportTeam: "\uACE0\uAC1D\uC9C0\uC6D0\uD300",
1814
+ staff: "\uB2F4\uB2F9\uC790"
1815
+ },
1816
+ time: {
1817
+ justNow: "\uBC29\uAE08 \uC804",
1818
+ minutesAgo: "{count}\uBD84 \uC804",
1819
+ hoursAgo: "{count}\uC2DC\uAC04 \uC804",
1820
+ daysAgo: "{count}\uC77C \uC804"
1821
+ }
1822
+ };
1823
+
1824
+ // src/i18n/useSupportT.ts
1825
+ var translations = { en, ru, ko };
1826
+ function getNestedValue(obj, path) {
1827
+ const keys = path.split(".");
1828
+ let result = obj;
1829
+ for (const key of keys) {
1830
+ if (result && typeof result === "object" && key in result) {
1831
+ result = result[key];
1832
+ } else {
1833
+ return path;
1834
+ }
1835
+ }
1836
+ return typeof result === "string" ? result : path;
1837
+ }
1838
+ function useSupportT() {
1839
+ const locale = useLocale();
1840
+ const t = useMemo(() => translations[locale] || translations.en, [locale]);
1841
+ return useCallback(
1842
+ (key) => getNestedValue(t, key),
1843
+ [t]
1844
+ );
1845
+ }
1618
1846
  function useSupportTicketsList(params, client) {
1619
1847
  return useSWR(
1620
1848
  params ? ["cfg-support-tickets", params] : "cfg-support-tickets",
@@ -1829,18 +2057,35 @@ var getStatusBadgeVariant = (status) => {
1829
2057
  return "default";
1830
2058
  }
1831
2059
  };
1832
- var formatRelativeTime = (date) => {
1833
- if (!date) return "N/A";
1834
- const m = moment2.utc(date).local();
1835
- const now = moment2();
1836
- const diffInSeconds = now.diff(m, "seconds");
1837
- if (diffInSeconds < 60) return "Just now";
1838
- if (diffInSeconds < 3600) return `${Math.floor(diffInSeconds / 60)}m ago`;
1839
- if (diffInSeconds < 86400) return `${Math.floor(diffInSeconds / 3600)}h ago`;
1840
- if (diffInSeconds < 604800) return `${Math.floor(diffInSeconds / 86400)}d ago`;
1841
- return m.format("MMM D, YYYY");
1842
- };
1843
2060
  var TicketCard = ({ ticket, isSelected, onClick }) => {
2061
+ const st = useSupportT();
2062
+ const labels = useMemo(() => ({
2063
+ status: {
2064
+ open: st("status.open"),
2065
+ waiting_for_user: st("status.waitingForUser"),
2066
+ waiting_for_admin: st("status.waitingForAdmin"),
2067
+ resolved: st("status.resolved"),
2068
+ closed: st("status.closed")
2069
+ },
2070
+ time: {
2071
+ justNow: st("time.justNow"),
2072
+ minutesAgo: st("time.minutesAgo"),
2073
+ hoursAgo: st("time.hoursAgo"),
2074
+ daysAgo: st("time.daysAgo")
2075
+ }
2076
+ }), [st]);
2077
+ const formatRelativeTime = useCallback((date) => {
2078
+ if (!date) return "N/A";
2079
+ const m = moment2.utc(date).local();
2080
+ const now = moment2();
2081
+ const diffInSeconds = now.diff(m, "seconds");
2082
+ if (diffInSeconds < 60) return labels.time.justNow;
2083
+ if (diffInSeconds < 3600) return labels.time.minutesAgo.replace("{count}", String(Math.floor(diffInSeconds / 60)));
2084
+ if (diffInSeconds < 86400) return labels.time.hoursAgo.replace("{count}", String(Math.floor(diffInSeconds / 3600)));
2085
+ if (diffInSeconds < 604800) return labels.time.daysAgo.replace("{count}", String(Math.floor(diffInSeconds / 86400)));
2086
+ return m.format("MMM D, YYYY");
2087
+ }, [labels.time]);
2088
+ const statusLabel = labels.status[ticket.status] || ticket.status || labels.status.open;
1844
2089
  return /* @__PURE__ */ jsx(
1845
2090
  Card,
1846
2091
  {
@@ -1864,7 +2109,7 @@ var TicketCard = ({ ticket, isSelected, onClick }) => {
1864
2109
  )
1865
2110
  ] }),
1866
2111
  /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between text-xs text-muted-foreground", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
1867
- /* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(ticket.status || "open"), className: "text-xs", children: ticket.status || "open" }),
2112
+ /* @__PURE__ */ jsx(Badge, { variant: getStatusBadgeVariant(ticket.status || "open"), className: "text-xs", children: statusLabel }),
1868
2113
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
1869
2114
  /* @__PURE__ */ jsx(Clock, { className: "h-3 w-3" }),
1870
2115
  /* @__PURE__ */ jsx("span", { children: formatRelativeTime(ticket.created_at) })
@@ -2139,6 +2384,7 @@ function useSupportLayoutContext() {
2139
2384
  return context;
2140
2385
  }
2141
2386
  var TicketList = () => {
2387
+ const st = useSupportT();
2142
2388
  const { selectedTicket, selectTicket } = useSupportLayoutContext();
2143
2389
  const {
2144
2390
  tickets,
@@ -2149,6 +2395,13 @@ var TicketList = () => {
2149
2395
  totalCount,
2150
2396
  refresh
2151
2397
  } = useInfiniteTickets();
2398
+ const labels = useMemo(() => ({
2399
+ noTickets: st("ticketList.noTickets"),
2400
+ noTicketsDescription: st("ticketList.noTicketsDescription"),
2401
+ loadingMore: st("ticketList.loadingMore"),
2402
+ loadMore: st("ticketList.loadMore"),
2403
+ allLoaded: st("ticketList.allLoaded")
2404
+ }), [st]);
2152
2405
  const scrollRef = useRef(null);
2153
2406
  const observerRef = useRef(null);
2154
2407
  const loadMoreRef = useRef(null);
@@ -2194,8 +2447,8 @@ var TicketList = () => {
2194
2447
  if (!tickets || tickets.length === 0) {
2195
2448
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-full p-8 text-center animate-in fade-in zoom-in-95 duration-300", children: [
2196
2449
  /* @__PURE__ */ jsx(MessageSquare, { className: "h-16 w-16 text-muted-foreground mb-4 animate-bounce" }),
2197
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "No tickets yet" }),
2198
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: "Create your first support ticket to get help from our team" })
2450
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: labels.noTickets }),
2451
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: labels.noTicketsDescription })
2199
2452
  ] });
2200
2453
  }
2201
2454
  return /* @__PURE__ */ jsx(ScrollArea, { className: "h-full", viewportRef: scrollRef, children: /* @__PURE__ */ jsxs("div", { className: "p-4 space-y-2", children: [
@@ -2218,7 +2471,7 @@ var TicketList = () => {
2218
2471
  /* @__PURE__ */ jsx("div", { ref: loadMoreRef, className: "h-2" }),
2219
2472
  isLoadingMore && /* @__PURE__ */ jsx("div", { className: "flex justify-center py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
2220
2473
  /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
2221
- /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Loading more tickets..." })
2474
+ /* @__PURE__ */ jsx("span", { className: "text-sm", children: labels.loadingMore })
2222
2475
  ] }) }),
2223
2476
  hasMore && !isLoadingMore && /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-2 pb-4", children: /* @__PURE__ */ jsxs(
2224
2477
  Button,
@@ -2228,17 +2481,14 @@ var TicketList = () => {
2228
2481
  onClick: loadMore,
2229
2482
  className: "text-xs",
2230
2483
  children: [
2231
- "Load more (",
2484
+ labels.loadMore,
2485
+ " (",
2232
2486
  totalCount > 0 ? `${tickets.length}/${totalCount}` : "",
2233
2487
  ")"
2234
2488
  ]
2235
2489
  }
2236
2490
  ) }),
2237
- !hasMore && tickets.length > 0 && /* @__PURE__ */ jsxs("div", { className: "text-center py-4 text-sm text-muted-foreground", children: [
2238
- "All ",
2239
- totalCount,
2240
- " tickets loaded"
2241
- ] })
2491
+ !hasMore && tickets.length > 0 && /* @__PURE__ */ jsx("div", { className: "text-center py-4 text-sm text-muted-foreground", children: labels.allLoaded.replace("{count}", String(totalCount)) })
2242
2492
  ] }) });
2243
2493
  };
2244
2494
  var formatTime = (date) => {
@@ -2249,7 +2499,7 @@ var formatDate = (date) => {
2249
2499
  if (!date) return "";
2250
2500
  return moment2.utc(date).local().format("MMM D, YYYY");
2251
2501
  };
2252
- var MessageBubble = ({ message, isFromUser, currentUser }) => {
2502
+ var MessageBubble = ({ message, isFromUser, currentUser, labels }) => {
2253
2503
  const sender = message.sender;
2254
2504
  const senderInitial = sender?.display_username?.charAt(0)?.toUpperCase() || sender?.initials || "S";
2255
2505
  const userInitial = currentUser?.display_username?.charAt(0)?.toUpperCase() || currentUser?.email?.charAt(0)?.toUpperCase() || currentUser?.initials || null;
@@ -2259,11 +2509,11 @@ var MessageBubble = ({ message, isFromUser, currentUser }) => {
2259
2509
  className: `flex gap-3 ${isFromUser ? "justify-end" : "justify-start"}
2260
2510
  animate-in fade-in slide-in-from-bottom-2 duration-300`,
2261
2511
  children: [
2262
- !isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: sender?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: sender.avatar, alt: sender.display_username || "Support" }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary text-primary-foreground", children: sender?.is_staff ? /* @__PURE__ */ jsx(Headphones, { className: "h-4 w-4" }) : senderInitial }) }),
2512
+ !isFromUser && /* @__PURE__ */ jsx(Avatar, { className: "h-8 w-8 shrink-0", children: sender?.avatar ? /* @__PURE__ */ jsx(AvatarImage, { src: sender.avatar, alt: sender.display_username || labels.supportTeam }) : /* @__PURE__ */ jsx(AvatarFallback, { className: "bg-primary text-primary-foreground", children: sender?.is_staff ? /* @__PURE__ */ jsx(Headphones, { className: "h-4 w-4" }) : senderInitial }) }),
2263
2513
  /* @__PURE__ */ jsxs("div", { className: `flex flex-col gap-1 flex-1 max-w-[80%] ${isFromUser ? "items-end" : "items-start"}`, children: [
2264
2514
  !isFromUser && sender && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground px-1", children: [
2265
- sender.display_username || sender.email || "Support Team",
2266
- sender.is_staff && " (Staff)"
2515
+ sender.display_username || sender.email || labels.supportTeam,
2516
+ sender.is_staff && ` (${labels.staff})`
2267
2517
  ] }),
2268
2518
  /* @__PURE__ */ jsx(
2269
2519
  Card,
@@ -2280,8 +2530,19 @@ var MessageBubble = ({ message, isFromUser, currentUser }) => {
2280
2530
  );
2281
2531
  };
2282
2532
  var MessageList = () => {
2533
+ const st = useSupportT();
2283
2534
  const { selectedTicket } = useSupportLayoutContext();
2284
2535
  const { user } = useAuth();
2536
+ const labels = useMemo(() => ({
2537
+ noTicketSelected: st("messageList.noTicketSelected"),
2538
+ noTicketSelectedDescription: st("messageList.noTicketSelectedDescription"),
2539
+ noMessages: st("messageList.noMessages"),
2540
+ noMessagesDescription: st("messageList.noMessagesDescription"),
2541
+ loadingOlder: st("messageList.loadingOlder"),
2542
+ loadOlder: st("messageList.loadOlder"),
2543
+ supportTeam: st("messageList.supportTeam"),
2544
+ staff: st("messageList.staff")
2545
+ }), [st]);
2285
2546
  const {
2286
2547
  messages,
2287
2548
  isLoading,
@@ -2339,8 +2600,8 @@ var MessageList = () => {
2339
2600
  if (!selectedTicket) {
2340
2601
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-full p-8 text-center animate-in fade-in zoom-in-95 duration-300", children: [
2341
2602
  /* @__PURE__ */ jsx(MessageSquare, { className: "h-16 w-16 text-muted-foreground mb-4 animate-bounce" }),
2342
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "No ticket selected" }),
2343
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: "Select a ticket from the list to view the conversation" })
2603
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: labels.noTicketSelected }),
2604
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: labels.noTicketSelectedDescription })
2344
2605
  ] });
2345
2606
  }
2346
2607
  if (isLoading) {
@@ -2360,15 +2621,15 @@ var MessageList = () => {
2360
2621
  if (!messages || messages.length === 0) {
2361
2622
  return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-full p-8 text-center animate-in fade-in zoom-in-95 duration-300", children: [
2362
2623
  /* @__PURE__ */ jsx(MessageSquare, { className: "h-16 w-16 text-muted-foreground mb-4 animate-bounce" }),
2363
- /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: "No messages yet" }),
2364
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: "Start the conversation by sending a message below" })
2624
+ /* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold mb-2", children: labels.noMessages }),
2625
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground max-w-sm", children: labels.noMessagesDescription })
2365
2626
  ] });
2366
2627
  }
2367
2628
  return /* @__PURE__ */ jsx(ScrollArea, { className: "h-full bg-muted/50", viewportRef: scrollAreaRef, children: /* @__PURE__ */ jsxs("div", { className: "p-6 space-y-4", ref: scrollRef, children: [
2368
2629
  /* @__PURE__ */ jsx("div", { ref: loadMoreRef, className: "h-2" }),
2369
2630
  isLoadingMore && /* @__PURE__ */ jsx("div", { className: "flex justify-center py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-muted-foreground", children: [
2370
2631
  /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
2371
- /* @__PURE__ */ jsx("span", { className: "text-sm", children: "Loading older messages..." })
2632
+ /* @__PURE__ */ jsx("span", { className: "text-sm", children: labels.loadingOlder })
2372
2633
  ] }) }),
2373
2634
  hasMore && !isLoadingMore && /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-2 pb-4", children: /* @__PURE__ */ jsxs(
2374
2635
  Button,
@@ -2378,7 +2639,8 @@ var MessageList = () => {
2378
2639
  onClick: handleLoadMore,
2379
2640
  className: "text-xs",
2380
2641
  children: [
2381
- "Load older messages (",
2642
+ labels.loadOlder,
2643
+ " (",
2382
2644
  totalCount > 0 ? `${messages.length}/${totalCount}` : "",
2383
2645
  ")"
2384
2646
  ]
@@ -2393,7 +2655,7 @@ var MessageList = () => {
2393
2655
  const isFromUser = message.sender?.id && user?.id && String(message.sender.id) === String(user.id) || message.sender?.email && user?.email && message.sender.email === user.email || message.is_from_author && selectedTicket?.user && user?.id && String(selectedTicket.user) === String(user.id);
2394
2656
  const previousMessage = index > 0 ? messages[index - 1] : null;
2395
2657
  const showDateSeparator = previousMessage && moment2.utc(previousMessage.created_at || "").format("YYYY-MM-DD") !== moment2.utc(message.created_at || "").format("YYYY-MM-DD");
2396
- return /* @__PURE__ */ jsxs(React7.Fragment, { children: [
2658
+ return /* @__PURE__ */ jsxs(React8.Fragment, { children: [
2397
2659
  showDateSeparator && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 my-4", children: [
2398
2660
  /* @__PURE__ */ jsx("div", { className: "flex-1 h-px bg-border" }),
2399
2661
  /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground", children: formatDate(message.created_at) }),
@@ -2404,7 +2666,8 @@ var MessageList = () => {
2404
2666
  {
2405
2667
  message,
2406
2668
  isFromUser: !!isFromUser,
2407
- currentUser: user
2669
+ currentUser: user,
2670
+ labels: { supportTeam: labels.supportTeam, staff: labels.staff }
2408
2671
  }
2409
2672
  ) })
2410
2673
  ] }, message.uuid);
@@ -2418,10 +2681,18 @@ var logger = createConsola({
2418
2681
  }).withTag("ext-support");
2419
2682
  var supportLogger = logger;
2420
2683
  var MessageInput = () => {
2684
+ const st = useSupportT();
2421
2685
  const { selectedTicket, sendMessage } = useSupportLayoutContext();
2422
2686
  const { toast } = useToast();
2423
2687
  const [message, setMessage] = useState("");
2424
2688
  const [isSending, setIsSending] = useState(false);
2689
+ const labels = useMemo(() => ({
2690
+ placeholder: st("messageInput.placeholder"),
2691
+ ticketClosed: st("messageInput.ticketClosed"),
2692
+ ticketClosedDescription: st("messageInput.ticketClosedDescription"),
2693
+ messageSent: st("messages.messageSent"),
2694
+ messageSendFailed: st("messages.messageSendFailed")
2695
+ }), [st]);
2425
2696
  const handleSubmit = async (e) => {
2426
2697
  e.preventDefault();
2427
2698
  if (!message.trim() || !selectedTicket) return;
@@ -2429,10 +2700,10 @@ var MessageInput = () => {
2429
2700
  try {
2430
2701
  await sendMessage(message.trim());
2431
2702
  setMessage("");
2432
- toast.success("Message sent successfully");
2703
+ toast.success(labels.messageSent);
2433
2704
  } catch (error) {
2434
2705
  supportLogger.error("Failed to send message:", error);
2435
- toast.error("Failed to send message");
2706
+ toast.error(labels.messageSendFailed);
2436
2707
  } finally {
2437
2708
  setIsSending(false);
2438
2709
  }
@@ -2455,8 +2726,8 @@ var MessageInput = () => {
2455
2726
  value: message,
2456
2727
  onChange: (e) => setMessage(e.target.value),
2457
2728
  onKeyDown: handleKeyDown,
2458
- placeholder: canSendMessage ? "Type your message... (Shift+Enter for new line)" : "This ticket is closed",
2459
- className: "min-h-[60px] max-h-[200px] transition-all duration-200 \n focus:ring-2 focus:ring-primary/20",
2729
+ placeholder: canSendMessage ? labels.placeholder : labels.ticketClosed,
2730
+ className: "min-h-[60px] max-h-[200px] transition-all duration-200\n focus:ring-2 focus:ring-primary/20",
2460
2731
  disabled: !canSendMessage || isSending
2461
2732
  }
2462
2733
  ),
@@ -2471,17 +2742,37 @@ var MessageInput = () => {
2471
2742
  }
2472
2743
  )
2473
2744
  ] }),
2474
- !canSendMessage && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-2 animate-in fade-in slide-in-from-top-1 duration-200", children: "This ticket is closed. You cannot send new messages." })
2745
+ !canSendMessage && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground mt-2 animate-in fade-in slide-in-from-top-1 duration-200", children: labels.ticketClosedDescription })
2475
2746
  ] });
2476
2747
  };
2477
- var createTicketSchema = z.object({
2478
- subject: z.string().min(1, "Subject is required").max(200, "Subject too long"),
2479
- message: z.string().min(1, "Message is required").max(5e3, "Message too long")
2480
- });
2481
2748
  var CreateTicketDialog = () => {
2749
+ const st = useSupportT();
2482
2750
  const { uiState, createTicket, closeCreateDialog } = useSupportLayoutContext();
2483
2751
  const { toast } = useToast$1();
2484
- const [isSubmitting, setIsSubmitting] = React7.useState(false);
2752
+ const [isSubmitting, setIsSubmitting] = React8.useState(false);
2753
+ const labels = useMemo(() => ({
2754
+ title: st("createTicket.title"),
2755
+ description: st("createTicket.description"),
2756
+ subjectLabel: st("createTicket.subjectLabel"),
2757
+ subjectPlaceholder: st("createTicket.subjectPlaceholder"),
2758
+ messageLabel: st("createTicket.messageLabel"),
2759
+ messagePlaceholder: st("createTicket.messagePlaceholder"),
2760
+ cancel: st("createTicket.cancel"),
2761
+ creating: st("createTicket.creating"),
2762
+ create: st("createTicket.create"),
2763
+ ticketCreated: st("messages.ticketCreated"),
2764
+ ticketCreateFailed: st("messages.ticketCreateFailed"),
2765
+ validation: {
2766
+ subjectRequired: st("validation.subjectRequired"),
2767
+ subjectTooLong: st("validation.subjectTooLong"),
2768
+ messageRequired: st("validation.messageRequired"),
2769
+ messageTooLong: st("validation.messageTooLong")
2770
+ }
2771
+ }), [st]);
2772
+ const createTicketSchema = useMemo(() => z.object({
2773
+ subject: z.string().min(1, labels.validation.subjectRequired).max(200, labels.validation.subjectTooLong),
2774
+ message: z.string().min(1, labels.validation.messageRequired).max(5e3, labels.validation.messageTooLong)
2775
+ }), [labels.validation]);
2485
2776
  const form = useForm({
2486
2777
  resolver: zodResolver(createTicketSchema),
2487
2778
  defaultValues: {
@@ -2494,10 +2785,10 @@ var CreateTicketDialog = () => {
2494
2785
  try {
2495
2786
  await createTicket(data);
2496
2787
  form.reset();
2497
- toast.success("Support ticket created successfully");
2788
+ toast.success(labels.ticketCreated);
2498
2789
  } catch (error) {
2499
2790
  supportLogger.error("Failed to create ticket:", error);
2500
- toast.error("Failed to create ticket. Please try again.");
2791
+ toast.error(labels.ticketCreateFailed);
2501
2792
  } finally {
2502
2793
  setIsSubmitting(false);
2503
2794
  }
@@ -2510,9 +2801,9 @@ var CreateTicketDialog = () => {
2510
2801
  /* @__PURE__ */ jsxs(DialogHeader, { children: [
2511
2802
  /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
2512
2803
  /* @__PURE__ */ jsx(Plus, { className: "h-5 w-5" }),
2513
- "Create Support Ticket"
2804
+ labels.title
2514
2805
  ] }),
2515
- /* @__PURE__ */ jsx(DialogDescription, { children: "Describe your issue and we'll help you resolve it as quickly as possible." })
2806
+ /* @__PURE__ */ jsx(DialogDescription, { children: labels.description })
2516
2807
  ] }),
2517
2808
  /* @__PURE__ */ jsx(Form, { ...form, children: /* @__PURE__ */ jsxs("form", { onSubmit: form.handleSubmit(onSubmit), className: "space-y-6", children: [
2518
2809
  /* @__PURE__ */ jsx(
@@ -2521,8 +2812,8 @@ var CreateTicketDialog = () => {
2521
2812
  control: form.control,
2522
2813
  name: "subject",
2523
2814
  render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
2524
- /* @__PURE__ */ jsx(FormLabel, { children: "Subject" }),
2525
- /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, { placeholder: "Brief description of your issue...", ...field }) }),
2815
+ /* @__PURE__ */ jsx(FormLabel, { children: labels.subjectLabel }),
2816
+ /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(Input, { placeholder: labels.subjectPlaceholder, ...field }) }),
2526
2817
  /* @__PURE__ */ jsx(FormMessage, {})
2527
2818
  ] })
2528
2819
  }
@@ -2533,11 +2824,11 @@ var CreateTicketDialog = () => {
2533
2824
  control: form.control,
2534
2825
  name: "message",
2535
2826
  render: ({ field }) => /* @__PURE__ */ jsxs(FormItem, { children: [
2536
- /* @__PURE__ */ jsx(FormLabel, { children: "Message" }),
2827
+ /* @__PURE__ */ jsx(FormLabel, { children: labels.messageLabel }),
2537
2828
  /* @__PURE__ */ jsx(FormControl, { children: /* @__PURE__ */ jsx(
2538
2829
  Textarea,
2539
2830
  {
2540
- placeholder: "Describe your issue in detail. Include any error messages, steps to reproduce, or relevant information...",
2831
+ placeholder: labels.messagePlaceholder,
2541
2832
  className: "min-h-[120px]",
2542
2833
  ...field
2543
2834
  }
@@ -2554,24 +2845,31 @@ var CreateTicketDialog = () => {
2554
2845
  variant: "outline",
2555
2846
  onClick: handleClose,
2556
2847
  disabled: isSubmitting,
2557
- children: "Cancel"
2848
+ children: labels.cancel
2558
2849
  }
2559
2850
  ),
2560
2851
  /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSubmitting, children: isSubmitting ? /* @__PURE__ */ jsxs(Fragment, { children: [
2561
2852
  /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 mr-2 animate-spin" }),
2562
- "Creating..."
2853
+ labels.creating
2563
2854
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
2564
2855
  /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2565
- "Create Ticket"
2856
+ labels.create
2566
2857
  ] }) })
2567
2858
  ] })
2568
2859
  ] }) })
2569
2860
  ] }) });
2570
2861
  };
2571
2862
  var SupportLayoutContent = () => {
2863
+ const st = useSupportT();
2572
2864
  const { selectedTicket, selectTicket, openCreateDialog, getUnreadCount } = useSupportLayoutContext();
2573
- const [isMobile, setIsMobile] = React7.useState(false);
2574
- React7.useEffect(() => {
2865
+ const [isMobile, setIsMobile] = React8.useState(false);
2866
+ const labels = useMemo(() => ({
2867
+ title: st("layout.title"),
2868
+ titleShort: st("layout.titleShort"),
2869
+ subtitle: st("layout.subtitle"),
2870
+ newTicket: st("layout.newTicket")
2871
+ }), [st]);
2872
+ React8.useEffect(() => {
2575
2873
  const checkMobile = () => setIsMobile(window.innerWidth <= 768);
2576
2874
  checkMobile();
2577
2875
  window.addEventListener("resize", checkMobile);
@@ -2592,12 +2890,12 @@ var SupportLayoutContent = () => {
2592
2890
  children: /* @__PURE__ */ jsx(ArrowLeft, { className: "h-5 w-5" })
2593
2891
  }
2594
2892
  ) : /* @__PURE__ */ jsx(LifeBuoy, { className: "h-6 w-6 text-primary" }),
2595
- /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold", children: selectedTicket ? selectedTicket.subject : "Support" }),
2893
+ /* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold", children: selectedTicket ? selectedTicket.subject : labels.titleShort }),
2596
2894
  unreadCount > 0 && !selectedTicket && /* @__PURE__ */ jsx("div", { className: "h-5 w-5 bg-red-500 text-white text-xs rounded-full flex items-center justify-center", children: unreadCount })
2597
2895
  ] }),
2598
2896
  !selectedTicket && /* @__PURE__ */ jsxs(Button, { onClick: openCreateDialog, size: "sm", children: [
2599
2897
  /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2600
- "New Ticket"
2898
+ labels.newTicket
2601
2899
  ] })
2602
2900
  ] }),
2603
2901
  /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: selectedTicket ? (
@@ -2618,14 +2916,14 @@ var SupportLayoutContent = () => {
2618
2916
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
2619
2917
  /* @__PURE__ */ jsx(LifeBuoy, { className: "h-7 w-7 text-primary" }),
2620
2918
  /* @__PURE__ */ jsxs("div", { children: [
2621
- /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: "Support Center" }),
2622
- /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Get help from our support team" })
2919
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold", children: labels.title }),
2920
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: labels.subtitle })
2623
2921
  ] }),
2624
2922
  unreadCount > 0 && /* @__PURE__ */ jsx("div", { className: "h-6 w-6 bg-red-500 text-white text-sm rounded-full flex items-center justify-center", children: unreadCount })
2625
2923
  ] }),
2626
2924
  /* @__PURE__ */ jsxs(Button, { onClick: openCreateDialog, children: [
2627
2925
  /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4 mr-2" }),
2628
- "New Ticket"
2926
+ labels.newTicket
2629
2927
  ] })
2630
2928
  ] }),
2631
2929
  /* @__PURE__ */ jsx("div", { className: "flex-1 min-h-0 overflow-hidden", children: /* @__PURE__ */ jsxs(ResizablePanelGroup, { direction: "horizontal", className: "h-full", children: [
@@ -2646,7 +2944,7 @@ var SupportLayout = () => {
2646
2944
  // package.json
2647
2945
  var package_default = {
2648
2946
  name: "@djangocfg/ext-support",
2649
- version: "1.0.21",
2947
+ version: "1.0.23",
2650
2948
  description: "Support ticket system extension for DjangoCFG",
2651
2949
  keywords: [
2652
2950
  "django",
@@ -2692,6 +2990,11 @@ var package_default = {
2692
2990
  types: "./dist/config.d.ts",
2693
2991
  import: "./dist/config.js",
2694
2992
  require: "./dist/config.cjs"
2993
+ },
2994
+ "./i18n": {
2995
+ types: "./dist/i18n.d.ts",
2996
+ import: "./dist/i18n.js",
2997
+ require: "./dist/i18n.cjs"
2695
2998
  }
2696
2999
  },
2697
3000
  files: [
@@ -2707,27 +3010,31 @@ var package_default = {
2707
3010
  peerDependencies: {
2708
3011
  "@djangocfg/api": "workspace:*",
2709
3012
  "@djangocfg/ext-base": "workspace:*",
3013
+ "@djangocfg/i18n": "workspace:*",
2710
3014
  "@djangocfg/ui-core": "workspace:*",
3015
+ "@hookform/resolvers": "^5.2.2",
2711
3016
  consola: "^3.4.2",
2712
3017
  "lucide-react": "^0.545.0",
2713
3018
  moment: "^2.30.1",
2714
3019
  next: "^16",
3020
+ "next-intl": "^4",
2715
3021
  "p-retry": "^7.0.0",
2716
3022
  react: "^19",
2717
3023
  "react-hook-form": "^7.69.0",
2718
- "@hookform/resolvers": "^5.2.2",
2719
3024
  swr: "^2.3.7",
2720
3025
  zod: "^4.3.4"
2721
3026
  },
2722
3027
  devDependencies: {
2723
3028
  "@djangocfg/api": "workspace:*",
2724
3029
  "@djangocfg/ext-base": "workspace:*",
3030
+ "@djangocfg/i18n": "workspace:*",
2725
3031
  "@djangocfg/ui-core": "workspace:*",
2726
3032
  "@djangocfg/typescript-config": "workspace:*",
2727
3033
  "@types/node": "^24.7.2",
2728
3034
  "@types/react": "^19.0.0",
2729
3035
  consola: "^3.4.2",
2730
3036
  moment: "^2.30.1",
3037
+ "next-intl": "^4.1.0",
2731
3038
  "p-retry": "^7.0.0",
2732
3039
  swr: "^2.3.7",
2733
3040
  tsup: "^8.5.0",