@catandbox/schrodinger-shopify-adapter 0.1.15 → 0.1.17

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.
@@ -16,6 +16,8 @@ const STATUS_OPTIONS = [
16
16
  { label: "Archived", value: "Archived" }
17
17
  ];
18
18
  const SORT_OPTIONS = [
19
+ { label: "Newest first", value: "created_desc" },
20
+ { label: "Oldest first", value: "created_asc" },
19
21
  { label: "Updated (newest)", value: "updated_desc" },
20
22
  { label: "Updated (oldest)", value: "updated_asc" },
21
23
  { label: "Title (A-Z)", value: "title_asc" },
@@ -26,8 +28,9 @@ export function SupportTicketList(props) {
26
28
  const [selectedTab, setSelectedTab] = useState(0);
27
29
  const isArchivedTab = selectedTab === 1;
28
30
  const [status, setStatus] = useState(props.initialStatus ?? "All");
31
+ const [category, setCategory] = useState("All");
29
32
  const [search, setSearch] = useState("");
30
- const [sort, setSort] = useState("updated_desc");
33
+ const [sort, setSort] = useState("created_desc");
31
34
  const [selectedIds, setSelectedIds] = useState({});
32
35
  const [archiveError, setArchiveError] = useState(null);
33
36
  const [toastContent, setToastContent] = useState(null);
@@ -35,6 +38,7 @@ export function SupportTicketList(props) {
35
38
  const effectiveStatus = isArchivedTab ? "Archived" : status;
36
39
  const tickets = useTickets({
37
40
  status: effectiveStatus,
41
+ category,
38
42
  search,
39
43
  sort
40
44
  }, {
@@ -48,6 +52,15 @@ export function SupportTicketList(props) {
48
52
  }
49
53
  return map;
50
54
  }, [portalConfig.data]);
55
+ const categoryOptions = useMemo(() => {
56
+ const options = [
57
+ { label: "All categories", value: "All" }
58
+ ];
59
+ for (const cat of portalConfig.data?.categories ?? []) {
60
+ options.push({ label: cat.name, value: cat.id });
61
+ }
62
+ return options;
63
+ }, [portalConfig.data]);
51
64
  const allItems = tickets.data ?? [];
52
65
  const selectedTicketIds = useMemo(() => allItems.filter((ticket) => selectedIds[ticket.id]).map((ticket) => ticket.id), [allItems, selectedIds]);
53
66
  const allChecked = allItems.length > 0 && selectedTicketIds.length === allItems.length;
@@ -105,17 +118,21 @@ export function SupportTicketList(props) {
105
118
  { id: "active", content: "My Tickets" },
106
119
  { id: "archived", content: "Archived" }
107
120
  ];
108
- return (_jsx(Frame, { children: _jsx(Page, { title: "Support tickets", subtitle: "Customer portal queue", children: _jsxs(BlockStack, { gap: "400", children: [_jsx(Card, { padding: "0", children: _jsx(Tabs, { tabs: tabs, selected: selectedTab, onSelect: handleTabChange, fitted: true, children: _jsx(Box, { padding: "400", children: _jsxs(BlockStack, { gap: "300", children: [_jsxs(InlineGrid, { columns: { xs: "1fr", md: isArchivedTab ? "1fr 1fr" : "2fr 1fr 1fr" }, gap: "300", children: [_jsx(TextField, { label: "Search", value: search, onChange: setSearch, placeholder: "Search by title or ticket id", autoComplete: "off" }), !isArchivedTab ? (_jsx(Select, { label: "Status", options: STATUS_OPTIONS.map((option) => ({
121
+ return (_jsx(Frame, { children: _jsx(Page, { title: "Support tickets", subtitle: "Customer portal queue", children: _jsxs(BlockStack, { gap: "400", children: [_jsx(Card, { padding: "0", children: _jsx(Tabs, { tabs: tabs, selected: selectedTab, onSelect: handleTabChange, fitted: true, children: _jsx(Box, { padding: "400", children: _jsxs(BlockStack, { gap: "300", children: [_jsxs(InlineGrid, { columns: {
122
+ xs: "1fr",
123
+ md: isArchivedTab ? "1fr 1fr 1fr" : "2fr 1fr 1fr 1fr"
124
+ }, gap: "300", children: [_jsx(TextField, { label: "Search", value: search, onChange: setSearch, placeholder: "Search by title or ticket id", autoComplete: "off" }), !isArchivedTab ? (_jsx(Select, { label: "Status", options: STATUS_OPTIONS.map((option) => ({
109
125
  label: option.label,
110
126
  value: option.value
111
- })), value: status, onChange: (value) => setStatus(value) })) : null, _jsx(Select, { label: "Sort", options: SORT_OPTIONS, value: sort, onChange: (value) => setSort(value) })] }), !isArchivedTab ? (_jsxs(InlineStack, { align: "space-between", blockAlign: "center", children: [_jsx(Checkbox, { label: "Select all", checked: allChecked, onChange: toggleSelectAll }), _jsx(Button, { tone: "critical", disabled: !hasSelection || archiving, loading: archiving, onClick: () => void runBulkArchive(), children: "Archive selected" })] })) : null] }) }) }) }), _jsx(ErrorBanner, { error: tickets.error }), _jsx(ErrorBanner, { error: archiveError }), tickets.loading ? (_jsx(Card, { children: _jsx(InlineStack, { align: "center", children: _jsx(Spinner, { size: "large" }) }) })) : allItems.length === 0 ? (_jsx(Card, { children: _jsx(EmptyState, { heading: isArchivedTab ? "No archived tickets" : "No tickets match the current filters", action: isArchivedTab
127
+ })), value: status, onChange: (value) => setStatus(value) })) : null, _jsx(Select, { label: "Category", options: categoryOptions, value: category, onChange: setCategory }), _jsx(Select, { label: "Order", options: SORT_OPTIONS, value: sort, onChange: (value) => setSort(value) })] }), !isArchivedTab ? (_jsxs(InlineStack, { align: "space-between", blockAlign: "center", children: [_jsx(Checkbox, { label: "Select all", checked: allChecked, onChange: toggleSelectAll }), _jsx(Button, { tone: "critical", disabled: !hasSelection || archiving, loading: archiving, onClick: () => void runBulkArchive(), children: "Archive selected" })] })) : null] }) }) }) }), _jsx(ErrorBanner, { error: tickets.error }), _jsx(ErrorBanner, { error: archiveError }), tickets.loading ? (_jsx(Card, { children: _jsx(InlineStack, { align: "center", children: _jsx(Spinner, { size: "large" }) }) })) : allItems.length === 0 ? (_jsx(Card, { children: _jsx(EmptyState, { heading: isArchivedTab ? "No archived tickets" : "No tickets match the current filters", action: isArchivedTab
112
128
  ? undefined
113
129
  : {
114
130
  content: "Reset filters",
115
131
  onAction: () => {
116
132
  setSearch("");
117
133
  setStatus("All");
118
- setSort("updated_desc");
134
+ setCategory("All");
135
+ setSort("created_desc");
119
136
  }
120
137
  }, image: "https://cdn.shopify.com/s/files/1/0262/4071/2726/files/emptystate-files.png", children: _jsx(Text, { as: "p", variant: "bodyMd", children: isArchivedTab
121
138
  ? "Archived tickets will appear here."
@@ -1,8 +1,9 @@
1
1
  import type { Ticket, TicketStatus } from "@catandbox/schrodinger-contracts";
2
2
  import type { QueryHookOptions, QueryHookState } from "./types";
3
- export type TicketSort = "updated_desc" | "updated_asc" | "title_asc" | "title_desc";
3
+ export type TicketSort = "updated_desc" | "updated_asc" | "created_desc" | "created_asc" | "title_asc" | "title_desc";
4
4
  interface UseTicketsParams {
5
5
  status?: TicketStatus | "All";
6
+ category?: string | "All";
6
7
  search?: string;
7
8
  sort?: TicketSort;
8
9
  }
@@ -45,14 +45,24 @@ function toTicketListItem(ticket) {
45
45
  }
46
46
  function applyTicketFiltersAndSort(items, params) {
47
47
  const search = (params.search ?? "").trim().toLowerCase();
48
- const filtered = search
48
+ let filtered = search
49
49
  ? items.filter((item) => item.title.toLowerCase().includes(search) || item.id.toLowerCase().includes(search))
50
50
  : items.slice();
51
+ const category = params.category;
52
+ if (category && category !== "All") {
53
+ filtered = filtered.filter((item) => item.categoryId === category);
54
+ }
51
55
  const sort = params.sort ?? "updated_desc";
52
56
  switch (sort) {
53
57
  case "updated_asc":
54
58
  filtered.sort((left, right) => left.updatedAt - right.updatedAt);
55
59
  break;
60
+ case "created_desc":
61
+ filtered.sort((left, right) => right.createdAt - left.createdAt);
62
+ break;
63
+ case "created_asc":
64
+ filtered.sort((left, right) => left.createdAt - right.createdAt);
65
+ break;
56
66
  case "title_asc":
57
67
  filtered.sort((left, right) => left.title.localeCompare(right.title));
58
68
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@catandbox/schrodinger-shopify-adapter",
3
- "version": "0.1.15",
3
+ "version": "0.1.17",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",