@impakers/debug 1.0.1 → 1.2.1

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/react.js CHANGED
@@ -1785,11 +1785,38 @@ async function apiFetch(url, options = {}) {
1785
1785
  }
1786
1786
  return res;
1787
1787
  }
1788
+ var cache = /* @__PURE__ */ new Map();
1789
+ var CACHE_TTL = 3e4;
1790
+ function getCached(key) {
1791
+ const entry = cache.get(key);
1792
+ if (!entry) return null;
1793
+ if (Date.now() - entry.timestamp > CACHE_TTL) {
1794
+ cache.delete(key);
1795
+ return null;
1796
+ }
1797
+ return entry.data;
1798
+ }
1799
+ function setCache(key, data) {
1800
+ cache.set(key, { data, timestamp: Date.now() });
1801
+ }
1802
+ function invalidateCache(pattern) {
1803
+ if (!pattern) {
1804
+ cache.clear();
1805
+ return;
1806
+ }
1807
+ for (const key of cache.keys()) {
1808
+ if (key.includes(pattern)) cache.delete(key);
1809
+ }
1810
+ }
1788
1811
  async function submitFeedback(endpoint, payload) {
1789
1812
  const res = await apiFetch(endpoint, {
1790
1813
  method: "POST",
1791
1814
  body: JSON.stringify(payload)
1792
1815
  });
1816
+ if (payload.feedbackUrl) {
1817
+ invalidateCache(`feedbacks:${payload.feedbackUrl}`);
1818
+ }
1819
+ invalidateCache("feedbacks:");
1793
1820
  try {
1794
1821
  return await res.json();
1795
1822
  } catch {
@@ -1797,50 +1824,76 @@ async function submitFeedback(endpoint, payload) {
1797
1824
  }
1798
1825
  }
1799
1826
  async function fetchFeedbacks(endpoint, url) {
1827
+ const cacheKey = `feedbacks:${url}`;
1828
+ const cached = getCached(cacheKey);
1829
+ if (cached) return cached;
1800
1830
  const res = await apiFetch(`${endpoint}?url=${encodeURIComponent(url)}`);
1801
1831
  const data = await res.json();
1802
- return data.tasks || [];
1832
+ const tasks = data.tasks || [];
1833
+ setCache(cacheKey, tasks);
1834
+ return tasks;
1803
1835
  }
1804
1836
  async function fetchComments(endpoint, taskId) {
1837
+ const cacheKey = `comments:${taskId}`;
1838
+ const cached = getCached(cacheKey);
1839
+ if (cached) return cached;
1805
1840
  const res = await apiFetch(`${endpoint}/${taskId}/comments`);
1806
1841
  const data = await res.json();
1807
- return data.comments || [];
1842
+ const comments = data.comments || [];
1843
+ setCache(cacheKey, comments);
1844
+ return comments;
1808
1845
  }
1809
1846
  async function postComment(endpoint, taskId, content, authorName, authorId) {
1847
+ const tempComment = {
1848
+ id: `temp-${Date.now()}`,
1849
+ content,
1850
+ authorName,
1851
+ authorId,
1852
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1853
+ };
1854
+ const cacheKey = `comments:${taskId}`;
1855
+ const existing = getCached(cacheKey) || [];
1856
+ setCache(cacheKey, [...existing, tempComment]);
1810
1857
  const res = await apiFetch(`${endpoint}/${taskId}/comments`, {
1811
1858
  method: "POST",
1812
1859
  body: JSON.stringify({ content, authorName, authorId })
1813
1860
  });
1814
1861
  const data = await res.json();
1815
- return data.comment;
1862
+ const serverComment = data.comment;
1863
+ const updated = (getCached(cacheKey) || []).map(
1864
+ (c) => c.id === tempComment.id ? serverComment : c
1865
+ );
1866
+ setCache(cacheKey, updated);
1867
+ invalidateCache("feedbacks:");
1868
+ return serverComment;
1816
1869
  }
1817
1870
 
1818
1871
  // src/core/sourcemap-resolver.ts
1819
1872
  var import_trace_mapping = require("@jridgewell/trace-mapping");
1820
- var cache = /* @__PURE__ */ new Map();
1873
+ var cache2 = /* @__PURE__ */ new Map();
1821
1874
  var failedUrls = /* @__PURE__ */ new Set();
1822
1875
  function getSourceMapUrl(bundleUrl) {
1823
1876
  if (bundleUrl.endsWith(".map")) return bundleUrl;
1824
1877
  return `${bundleUrl}.map`;
1825
1878
  }
1826
1879
  async function loadSourceMap(bundleUrl) {
1827
- if (cache.has(bundleUrl)) return cache.get(bundleUrl) ?? null;
1880
+ if (cache2.has(bundleUrl)) return cache2.get(bundleUrl) ?? null;
1828
1881
  if (failedUrls.has(bundleUrl)) return null;
1829
1882
  const mapUrl = getSourceMapUrl(bundleUrl);
1830
1883
  try {
1831
1884
  const res = await fetch(mapUrl, { cache: "force-cache" });
1832
1885
  if (!res.ok) {
1833
1886
  failedUrls.add(bundleUrl);
1834
- cache.set(bundleUrl, null);
1887
+ cache2.set(bundleUrl, null);
1835
1888
  return null;
1836
1889
  }
1837
1890
  const rawMap = await res.json();
1838
1891
  const traceMap = new import_trace_mapping.TraceMap(rawMap);
1839
- cache.set(bundleUrl, traceMap);
1892
+ cache2.set(bundleUrl, traceMap);
1840
1893
  return traceMap;
1841
1894
  } catch {
1842
1895
  failedUrls.add(bundleUrl);
1843
- cache.set(bundleUrl, null);
1896
+ cache2.set(bundleUrl, null);
1844
1897
  return null;
1845
1898
  }
1846
1899
  }
@@ -2340,8 +2393,8 @@ var import_react5 = require("react");
2340
2393
  var import_react_dom = require("react-dom");
2341
2394
 
2342
2395
  // src/components/inbox-panel/styles.module.scss
2343
- var css5 = '@keyframes styles-module__slideIn___0o0s- {\n from {\n transform: translateX(100%);\n }\n to {\n transform: translateX(0);\n }\n}\n@keyframes styles-module__slideOut___nKrBX {\n from {\n transform: translateX(0);\n }\n to {\n transform: translateX(100%);\n }\n}\n@keyframes styles-module__fadeIn___j09Ts {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n.styles-module__backdrop___zYhcU {\n position: fixed;\n inset: 0;\n z-index: 100003;\n animation: styles-module__fadeIn___j09Ts 0.15s ease-out;\n}\n\n.styles-module__panel___6YS8k {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 420px;\n max-width: 100vw;\n background: #fafafa;\n z-index: 100004;\n display: flex;\n flex-direction: column;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.08);\n animation: styles-module__slideIn___0o0s- 0.2s ease-out;\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n}\n.styles-module__panel___6YS8k.styles-module__exiting___6A-Ag {\n animation: styles-module__slideOut___nKrBX 0.15s ease-in forwards;\n}\n\n.styles-module__header___fBbGz {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid #e5e7eb;\n background: #fff;\n flex-shrink: 0;\n}\n\n.styles-module__headerLeft___e0YLf {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.styles-module__headerTitle___oEPJa {\n font-size: 14px;\n font-weight: 600;\n color: #18181b;\n}\n\n.styles-module__closeBtn___-H8ra {\n width: 32px;\n height: 32px;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n color: #6b7280;\n transition: background 0.12s, color 0.12s;\n}\n.styles-module__closeBtn___-H8ra:hover {\n background: #f3f4f6;\n color: #18181b;\n}\n.styles-module__closeBtn___-H8ra svg {\n width: 18px;\n height: 18px;\n}\n\n.styles-module__tabs___nfuX7 {\n display: flex;\n padding: 0 20px;\n gap: 0;\n border-bottom: 1px solid #e5e7eb;\n background: #fff;\n flex-shrink: 0;\n}\n\n.styles-module__tab___Hc-jn {\n padding: 10px 16px;\n font-size: 13px;\n font-weight: 500;\n color: #6b7280;\n border: none;\n background: none;\n cursor: pointer;\n border-bottom: 2px solid transparent;\n transition: color 0.12s, border-color 0.12s;\n font-family: inherit;\n}\n.styles-module__tab___Hc-jn:hover {\n color: #374151;\n}\n.styles-module__tab___Hc-jn.styles-module__active___ZQzA5 {\n color: #18181b;\n border-bottom-color: #18181b;\n}\n\n.styles-module__tabBadge___IdFDQ {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n border-radius: 9px;\n background: #e5e7eb;\n color: #374151;\n font-size: 11px;\n font-weight: 600;\n padding: 0 5px;\n margin-left: 6px;\n}\n\n.styles-module__content___L2lRw {\n flex: 1;\n overflow-y: auto;\n padding: 12px;\n}\n.styles-module__content___L2lRw::-webkit-scrollbar {\n width: 4px;\n}\n.styles-module__content___L2lRw::-webkit-scrollbar-thumb {\n background: #d1d5db;\n border-radius: 2px;\n}\n\n.styles-module__card___F8qwd {\n background: #fff;\n border-radius: 12px;\n border: 1px solid #e5e7eb;\n margin-bottom: 12px;\n overflow: hidden;\n transition: box-shadow 0.12s;\n cursor: pointer;\n}\n.styles-module__card___F8qwd:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n}\n\n.styles-module__cardHeader___QOVGR {\n padding: 14px 16px 8px;\n display: flex;\n align-items: flex-start;\n gap: 10px;\n}\n\n.styles-module__cardAvatar___FfKmW {\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background: #16a34a;\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.styles-module__cardInfo___BmrdF {\n flex: 1;\n min-width: 0;\n}\n\n.styles-module__cardMeta___7p9KD {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 4px;\n}\n\n.styles-module__cardAuthor___YvnuR {\n font-size: 13px;\n font-weight: 600;\n color: #18181b;\n}\n\n.styles-module__cardTime___N1Png {\n font-size: 12px;\n color: #9ca3af;\n}\n\n.styles-module__cardActions___7QF72 {\n display: flex;\n gap: 2px;\n flex-shrink: 0;\n}\n\n.styles-module__cardAction___t4b3V {\n width: 26px;\n height: 26px;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 5px;\n color: #9ca3af;\n transition: background 0.12s, color 0.12s;\n padding: 0;\n}\n.styles-module__cardAction___t4b3V:hover {\n background: #f3f4f6;\n color: #374151;\n}\n.styles-module__cardAction___t4b3V svg {\n width: 14px;\n height: 14px;\n}\n\n.styles-module__cardTitle___xJxDN {\n font-size: 13px;\n color: #1a1a1a;\n line-height: 1.5;\n padding: 0 16px 8px;\n}\n\n.styles-module__cardScreenshot___I5-QL {\n margin: 0 16px 8px;\n border-radius: 8px;\n border: 1px solid #e5e7eb;\n overflow: hidden;\n position: relative;\n max-height: 160px;\n}\n.styles-module__cardScreenshot___I5-QL img {\n width: 100%;\n height: auto;\n display: block;\n object-fit: cover;\n}\n\n.styles-module__cardRoute___U4gB6 {\n margin: 0 16px 10px;\n padding: 8px 12px;\n background: #f9fafb;\n border: 1px solid #f3f4f6;\n border-radius: 8px;\n font-size: 12px;\n color: #6b7280;\n line-height: 1.4;\n}\n\n.styles-module__cardRouteName___BDH75 {\n font-weight: 500;\n color: #374151;\n}\n\n.styles-module__cardRoutePath___zP-fh {\n color: #9ca3af;\n}\n\n.styles-module__cardFooter___wfPa4 {\n padding: 8px 16px 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.styles-module__cardReplyDot___YnqzI {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #16a34a;\n flex-shrink: 0;\n}\n\n.styles-module__cardReplyCount___O1khL {\n font-size: 12px;\n font-weight: 500;\n color: #374151;\n}\n\n.styles-module__statusDot___l4IHG {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n.styles-module__statusDot___l4IHG.styles-module__todo___894P6 {\n background: #f59e0b;\n}\n.styles-module__statusDot___l4IHG.styles-module__inProgress___IZ1mJ {\n background: #3b82f6;\n}\n.styles-module__statusDot___l4IHG.styles-module__done___n4cWP {\n background: #16a34a;\n}\n\n.styles-module__empty___IADrw {\n text-align: center;\n padding: 48px 20px;\n color: #9ca3af;\n font-size: 13px;\n line-height: 1.6;\n}\n\n.styles-module__emptyIcon___1x5wT {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: #f3f4f6;\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 12px;\n color: #9ca3af;\n}\n.styles-module__emptyIcon___1x5wT svg {\n width: 24px;\n height: 24px;\n}';
2344
- var classNames5 = { "backdrop": "styles-module__backdrop___zYhcU", "fadeIn": "styles-module__fadeIn___j09Ts", "panel": "styles-module__panel___6YS8k", "slideIn": "styles-module__slideIn___0o0s-", "exiting": "styles-module__exiting___6A-Ag", "slideOut": "styles-module__slideOut___nKrBX", "header": "styles-module__header___fBbGz", "headerLeft": "styles-module__headerLeft___e0YLf", "headerTitle": "styles-module__headerTitle___oEPJa", "closeBtn": "styles-module__closeBtn___-H8ra", "tabs": "styles-module__tabs___nfuX7", "tab": "styles-module__tab___Hc-jn", "active": "styles-module__active___ZQzA5", "tabBadge": "styles-module__tabBadge___IdFDQ", "content": "styles-module__content___L2lRw", "card": "styles-module__card___F8qwd", "cardHeader": "styles-module__cardHeader___QOVGR", "cardAvatar": "styles-module__cardAvatar___FfKmW", "cardInfo": "styles-module__cardInfo___BmrdF", "cardMeta": "styles-module__cardMeta___7p9KD", "cardAuthor": "styles-module__cardAuthor___YvnuR", "cardTime": "styles-module__cardTime___N1Png", "cardActions": "styles-module__cardActions___7QF72", "cardAction": "styles-module__cardAction___t4b3V", "cardTitle": "styles-module__cardTitle___xJxDN", "cardScreenshot": "styles-module__cardScreenshot___I5-QL", "cardRoute": "styles-module__cardRoute___U4gB6", "cardRouteName": "styles-module__cardRouteName___BDH75", "cardRoutePath": "styles-module__cardRoutePath___zP-fh", "cardFooter": "styles-module__cardFooter___wfPa4", "cardReplyDot": "styles-module__cardReplyDot___YnqzI", "cardReplyCount": "styles-module__cardReplyCount___O1khL", "statusDot": "styles-module__statusDot___l4IHG", "todo": "styles-module__todo___894P6", "inProgress": "styles-module__inProgress___IZ1mJ", "done": "styles-module__done___n4cWP", "empty": "styles-module__empty___IADrw", "emptyIcon": "styles-module__emptyIcon___1x5wT" };
2396
+ var css5 = '@keyframes styles-module__slideIn___0o0s- {\n from {\n transform: translateX(100%);\n }\n to {\n transform: translateX(0);\n }\n}\n@keyframes styles-module__slideOut___nKrBX {\n from {\n transform: translateX(0);\n }\n to {\n transform: translateX(100%);\n }\n}\n@keyframes styles-module__fadeIn___j09Ts {\n from {\n opacity: 0;\n }\n to {\n opacity: 1;\n }\n}\n.styles-module__backdrop___zYhcU {\n position: fixed;\n inset: 0;\n z-index: 100003;\n animation: styles-module__fadeIn___j09Ts 0.15s ease-out;\n}\n\n.styles-module__panel___6YS8k {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: 420px;\n max-width: 100vw;\n background: #fafafa;\n z-index: 100004;\n display: flex;\n flex-direction: column;\n box-shadow: -4px 0 24px rgba(0, 0, 0, 0.08);\n animation: styles-module__slideIn___0o0s- 0.2s ease-out;\n font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;\n -webkit-font-smoothing: antialiased;\n}\n.styles-module__panel___6YS8k.styles-module__exiting___6A-Ag {\n animation: styles-module__slideOut___nKrBX 0.15s ease-in forwards;\n}\n\n.styles-module__header___fBbGz {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 16px 20px;\n border-bottom: 1px solid #e5e7eb;\n background: #fff;\n flex-shrink: 0;\n}\n\n.styles-module__headerLeft___e0YLf {\n display: flex;\n align-items: center;\n gap: 8px;\n}\n\n.styles-module__headerTitle___oEPJa {\n font-size: 14px;\n font-weight: 600;\n color: #18181b;\n}\n\n.styles-module__closeBtn___-H8ra {\n width: 32px;\n height: 32px;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n color: #6b7280;\n transition: background 0.12s, color 0.12s;\n}\n.styles-module__closeBtn___-H8ra:hover {\n background: #f3f4f6;\n color: #18181b;\n}\n.styles-module__closeBtn___-H8ra svg {\n width: 18px;\n height: 18px;\n}\n\n.styles-module__tabs___nfuX7 {\n display: flex;\n padding: 0 20px;\n gap: 0;\n border-bottom: 1px solid #e5e7eb;\n background: #fff;\n flex-shrink: 0;\n}\n\n.styles-module__tab___Hc-jn {\n padding: 10px 16px;\n font-size: 13px;\n font-weight: 500;\n color: #6b7280;\n border: none;\n background: none;\n cursor: pointer;\n border-bottom: 2px solid transparent;\n transition: color 0.12s, border-color 0.12s;\n font-family: inherit;\n}\n.styles-module__tab___Hc-jn:hover {\n color: #374151;\n}\n.styles-module__tab___Hc-jn.styles-module__active___ZQzA5 {\n color: #18181b;\n border-bottom-color: #18181b;\n}\n\n.styles-module__tabBadge___IdFDQ {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 18px;\n height: 18px;\n border-radius: 9px;\n background: #e5e7eb;\n color: #374151;\n font-size: 11px;\n font-weight: 600;\n padding: 0 5px;\n margin-left: 6px;\n}\n\n.styles-module__content___L2lRw {\n flex: 1;\n overflow-y: auto;\n padding: 12px;\n}\n.styles-module__content___L2lRw::-webkit-scrollbar {\n width: 4px;\n}\n.styles-module__content___L2lRw::-webkit-scrollbar-thumb {\n background: #d1d5db;\n border-radius: 2px;\n}\n\n.styles-module__card___F8qwd {\n background: #fff;\n border-radius: 12px;\n border: 1px solid #e5e7eb;\n margin-bottom: 12px;\n overflow: hidden;\n transition: box-shadow 0.12s;\n cursor: pointer;\n}\n.styles-module__card___F8qwd:hover {\n box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);\n}\n\n.styles-module__cardHeader___QOVGR {\n padding: 14px 16px 8px;\n display: flex;\n align-items: flex-start;\n gap: 10px;\n}\n\n.styles-module__cardAvatar___FfKmW {\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background: #16a34a;\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.styles-module__cardInfo___BmrdF {\n flex: 1;\n min-width: 0;\n}\n\n.styles-module__cardMeta___7p9KD {\n display: flex;\n align-items: center;\n gap: 6px;\n margin-bottom: 4px;\n}\n\n.styles-module__cardAuthor___YvnuR {\n font-size: 13px;\n font-weight: 600;\n color: #18181b;\n}\n\n.styles-module__cardTime___N1Png {\n font-size: 12px;\n color: #9ca3af;\n}\n\n.styles-module__cardActions___7QF72 {\n display: flex;\n gap: 2px;\n flex-shrink: 0;\n}\n\n.styles-module__cardAction___t4b3V {\n width: 26px;\n height: 26px;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 5px;\n color: #9ca3af;\n transition: background 0.12s, color 0.12s;\n padding: 0;\n}\n.styles-module__cardAction___t4b3V:hover {\n background: #f3f4f6;\n color: #374151;\n}\n.styles-module__cardAction___t4b3V svg {\n width: 14px;\n height: 14px;\n}\n\n.styles-module__cardTitle___xJxDN {\n font-size: 13px;\n color: #1a1a1a;\n line-height: 1.5;\n padding: 0 16px 8px;\n}\n\n.styles-module__cardScreenshot___I5-QL {\n margin: 0 16px 8px;\n border-radius: 8px;\n border: 1px solid #e5e7eb;\n overflow: hidden;\n position: relative;\n max-height: 160px;\n}\n.styles-module__cardScreenshot___I5-QL img {\n width: 100%;\n height: auto;\n display: block;\n object-fit: cover;\n}\n\n.styles-module__cardRoute___U4gB6 {\n margin: 0 16px 10px;\n padding: 8px 12px;\n background: #f9fafb;\n border: 1px solid #f3f4f6;\n border-radius: 8px;\n font-size: 12px;\n color: #6b7280;\n line-height: 1.4;\n}\n\n.styles-module__cardRouteName___BDH75 {\n font-weight: 500;\n color: #374151;\n}\n\n.styles-module__cardRoutePath___zP-fh {\n color: #9ca3af;\n}\n\n.styles-module__cardFooter___wfPa4 {\n padding: 8px 16px 12px;\n display: flex;\n align-items: center;\n gap: 6px;\n}\n\n.styles-module__cardReplyDot___YnqzI {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #16a34a;\n flex-shrink: 0;\n}\n\n.styles-module__cardReplyCount___O1khL {\n font-size: 12px;\n font-weight: 500;\n color: #374151;\n}\n\n.styles-module__statusDot___l4IHG {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n.styles-module__statusDot___l4IHG.styles-module__todo___894P6 {\n background: #f59e0b;\n}\n.styles-module__statusDot___l4IHG.styles-module__inProgress___IZ1mJ {\n background: #3b82f6;\n}\n.styles-module__statusDot___l4IHG.styles-module__done___n4cWP {\n background: #16a34a;\n}\n\n.styles-module__empty___IADrw {\n text-align: center;\n padding: 48px 20px;\n color: #9ca3af;\n font-size: 13px;\n line-height: 1.6;\n}\n\n.styles-module__emptyIcon___1x5wT {\n width: 48px;\n height: 48px;\n border-radius: 50%;\n background: #f3f4f6;\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 12px;\n color: #9ca3af;\n}\n.styles-module__emptyIcon___1x5wT svg {\n width: 24px;\n height: 24px;\n}\n\n.styles-module__checkBtn___KjHxm {\n width: 28px;\n height: 28px;\n border: 2px solid #d1d5db;\n border-radius: 50%;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n color: transparent;\n transition: all 0.15s;\n padding: 0;\n flex-shrink: 0;\n}\n.styles-module__checkBtn___KjHxm svg {\n width: 14px;\n height: 14px;\n}\n.styles-module__checkBtn___KjHxm:hover {\n border-color: #16a34a;\n color: #16a34a;\n}\n.styles-module__checkBtn___KjHxm.styles-module__checked___8pype {\n border-color: #16a34a;\n background: #16a34a;\n color: #fff;\n}\n\n.styles-module__cardDone___-m4w- {\n opacity: 0.6;\n}\n.styles-module__cardDone___-m4w- .styles-module__cardTitle___xJxDN {\n text-decoration: line-through;\n color: #9ca3af;\n}\n\n.styles-module__backBtn___PTIAl {\n width: 28px;\n height: 28px;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n color: #6b7280;\n transition: background 0.12s, color 0.12s;\n padding: 0;\n flex-shrink: 0;\n}\n.styles-module__backBtn___PTIAl:hover {\n background: #f3f4f6;\n color: #18181b;\n}\n\n.styles-module__detailView___36cvH {\n flex: 1;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n}\n\n.styles-module__detailHeader___Hepgq {\n display: flex;\n gap: 10px;\n padding: 16px 20px;\n border-bottom: 1px solid #f3f4f6;\n}\n\n.styles-module__detailTitle___7TvrX {\n font-size: 13px;\n color: #1a1a1a;\n line-height: 1.5;\n margin-top: 4px;\n}\n\n.styles-module__detailScreenshot___UPF0f {\n margin: 0 20px 0;\n border-radius: 8px;\n border: 1px solid #e5e7eb;\n overflow: hidden;\n max-height: 180px;\n}\n.styles-module__detailScreenshot___UPF0f img {\n width: 100%;\n height: auto;\n display: block;\n object-fit: cover;\n}\n\n.styles-module__commentsList___5Uigg {\n flex: 1;\n overflow-y: auto;\n padding: 8px 0;\n}\n.styles-module__commentsList___5Uigg::-webkit-scrollbar {\n width: 4px;\n}\n.styles-module__commentsList___5Uigg::-webkit-scrollbar-thumb {\n background: #d1d5db;\n border-radius: 2px;\n}\n\n.styles-module__commentItem___5u78u {\n display: flex;\n gap: 10px;\n padding: 10px 20px;\n}\n.styles-module__commentItem___5u78u:hover {\n background: #f9fafb;\n}\n\n.styles-module__commentAvatar___OatKg {\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background: #16a34a;\n color: #fff;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 11px;\n font-weight: 600;\n flex-shrink: 0;\n}\n\n.styles-module__commentBody___gmv1J {\n flex: 1;\n min-width: 0;\n}\n\n.styles-module__commentMeta___JNJa3 {\n display: flex;\n gap: 6px;\n align-items: center;\n margin-bottom: 2px;\n}\n\n.styles-module__commentAuthorName___XNVRk {\n font-size: 13px;\n font-weight: 600;\n color: #1a1a1a;\n}\n\n.styles-module__commentTime___CokGf {\n font-size: 12px;\n color: #9ca3af;\n}\n\n.styles-module__commentContent___yMiLR {\n font-size: 13px;\n color: #374151;\n line-height: 1.5;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.styles-module__loadingComments___zpATD, .styles-module__noComments___kvl90 {\n text-align: center;\n padding: 24px 20px;\n color: #9ca3af;\n font-size: 13px;\n}\n\n.styles-module__replyBox___FO-XS {\n display: flex;\n align-items: flex-end;\n gap: 8px;\n padding: 12px 20px;\n border-top: 1px solid #f3f4f6;\n background: #fff;\n}\n\n.styles-module__replyInput___k8C9e {\n flex: 1;\n border: 1px solid #e5e7eb;\n border-radius: 8px;\n padding: 8px 12px;\n font-size: 13px;\n font-family: inherit;\n color: #1a1a1a;\n resize: none;\n outline: none;\n min-height: 20px;\n max-height: 80px;\n line-height: 1.5;\n transition: border-color 0.12s;\n}\n.styles-module__replyInput___k8C9e:focus {\n border-color: #18181b;\n}\n.styles-module__replyInput___k8C9e::placeholder {\n color: #9ca3af;\n}\n\n.styles-module__sendBtn___pBzWa {\n width: 32px;\n height: 32px;\n border: none;\n background: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n border-radius: 6px;\n color: #d1d5db;\n transition: color 0.12s;\n padding: 0;\n flex-shrink: 0;\n}\n.styles-module__sendBtn___pBzWa.styles-module__active___ZQzA5 {\n color: #3b82f6;\n}\n.styles-module__sendBtn___pBzWa:hover {\n color: #3b82f6;\n}';
2397
+ var classNames5 = { "backdrop": "styles-module__backdrop___zYhcU", "fadeIn": "styles-module__fadeIn___j09Ts", "panel": "styles-module__panel___6YS8k", "slideIn": "styles-module__slideIn___0o0s-", "exiting": "styles-module__exiting___6A-Ag", "slideOut": "styles-module__slideOut___nKrBX", "header": "styles-module__header___fBbGz", "headerLeft": "styles-module__headerLeft___e0YLf", "headerTitle": "styles-module__headerTitle___oEPJa", "closeBtn": "styles-module__closeBtn___-H8ra", "tabs": "styles-module__tabs___nfuX7", "tab": "styles-module__tab___Hc-jn", "active": "styles-module__active___ZQzA5", "tabBadge": "styles-module__tabBadge___IdFDQ", "content": "styles-module__content___L2lRw", "card": "styles-module__card___F8qwd", "cardHeader": "styles-module__cardHeader___QOVGR", "cardAvatar": "styles-module__cardAvatar___FfKmW", "cardInfo": "styles-module__cardInfo___BmrdF", "cardMeta": "styles-module__cardMeta___7p9KD", "cardAuthor": "styles-module__cardAuthor___YvnuR", "cardTime": "styles-module__cardTime___N1Png", "cardActions": "styles-module__cardActions___7QF72", "cardAction": "styles-module__cardAction___t4b3V", "cardTitle": "styles-module__cardTitle___xJxDN", "cardScreenshot": "styles-module__cardScreenshot___I5-QL", "cardRoute": "styles-module__cardRoute___U4gB6", "cardRouteName": "styles-module__cardRouteName___BDH75", "cardRoutePath": "styles-module__cardRoutePath___zP-fh", "cardFooter": "styles-module__cardFooter___wfPa4", "cardReplyDot": "styles-module__cardReplyDot___YnqzI", "cardReplyCount": "styles-module__cardReplyCount___O1khL", "statusDot": "styles-module__statusDot___l4IHG", "todo": "styles-module__todo___894P6", "inProgress": "styles-module__inProgress___IZ1mJ", "done": "styles-module__done___n4cWP", "empty": "styles-module__empty___IADrw", "emptyIcon": "styles-module__emptyIcon___1x5wT", "checkBtn": "styles-module__checkBtn___KjHxm", "checked": "styles-module__checked___8pype", "cardDone": "styles-module__cardDone___-m4w-", "backBtn": "styles-module__backBtn___PTIAl", "detailView": "styles-module__detailView___36cvH", "detailHeader": "styles-module__detailHeader___Hepgq", "detailTitle": "styles-module__detailTitle___7TvrX", "detailScreenshot": "styles-module__detailScreenshot___UPF0f", "commentsList": "styles-module__commentsList___5Uigg", "commentItem": "styles-module__commentItem___5u78u", "commentAvatar": "styles-module__commentAvatar___OatKg", "commentBody": "styles-module__commentBody___gmv1J", "commentMeta": "styles-module__commentMeta___JNJa3", "commentAuthorName": "styles-module__commentAuthorName___XNVRk", "commentTime": "styles-module__commentTime___CokGf", "commentContent": "styles-module__commentContent___yMiLR", "loadingComments": "styles-module__loadingComments___zpATD", "noComments": "styles-module__noComments___kvl90", "replyBox": "styles-module__replyBox___FO-XS", "replyInput": "styles-module__replyInput___k8C9e", "sendBtn": "styles-module__sendBtn___pBzWa" };
2345
2398
  if (typeof document !== "undefined") {
2346
2399
  let style = document.getElementById("impakers-debug-styles-inbox-panel-styles");
2347
2400
  if (!style) {
@@ -2374,15 +2427,85 @@ function InboxPanel({
2374
2427
  allItems,
2375
2428
  currentPath,
2376
2429
  serviceName,
2430
+ endpoint,
2431
+ currentUserName,
2432
+ currentUserId,
2377
2433
  onClose,
2378
- onItemClick
2434
+ onStatusChange
2379
2435
  }) {
2380
2436
  const [tab, setTab] = (0, import_react5.useState)("page");
2381
2437
  const [exiting, setExiting] = (0, import_react5.useState)(false);
2438
+ const [selectedItem, setSelectedItem] = (0, import_react5.useState)(null);
2439
+ const [comments, setComments] = (0, import_react5.useState)([]);
2440
+ const [loadingComments, setLoadingComments] = (0, import_react5.useState)(false);
2441
+ const [replyText, setReplyText] = (0, import_react5.useState)("");
2442
+ const replyRef = (0, import_react5.useRef)(null);
2443
+ const commentsEndRef = (0, import_react5.useRef)(null);
2382
2444
  const handleClose = (0, import_react5.useCallback)(() => {
2445
+ if (selectedItem) {
2446
+ setSelectedItem(null);
2447
+ setComments([]);
2448
+ setReplyText("");
2449
+ return;
2450
+ }
2383
2451
  setExiting(true);
2384
2452
  setTimeout(() => onClose(), 150);
2385
- }, [onClose]);
2453
+ }, [onClose, selectedItem]);
2454
+ const handleItemClick = (0, import_react5.useCallback)(async (item) => {
2455
+ if (item.feedbackUrl && item.feedbackUrl !== window.location.pathname) {
2456
+ window.location.href = item.feedbackUrl;
2457
+ return;
2458
+ }
2459
+ setSelectedItem(item);
2460
+ setLoadingComments(true);
2461
+ try {
2462
+ const data = await fetchComments(endpoint, item.id);
2463
+ setComments(data);
2464
+ } catch {
2465
+ setComments([]);
2466
+ } finally {
2467
+ setLoadingComments(false);
2468
+ }
2469
+ }, [endpoint]);
2470
+ (0, import_react5.useEffect)(() => {
2471
+ commentsEndRef.current?.scrollIntoView({ behavior: "smooth" });
2472
+ }, [comments.length]);
2473
+ (0, import_react5.useEffect)(() => {
2474
+ if (selectedItem) replyRef.current?.focus();
2475
+ }, [selectedItem]);
2476
+ const handleSendReply = (0, import_react5.useCallback)(async () => {
2477
+ if (!replyText.trim() || !selectedItem) return;
2478
+ const content = replyText.trim();
2479
+ setReplyText("");
2480
+ const temp = {
2481
+ id: `temp-${Date.now()}`,
2482
+ content,
2483
+ authorName: currentUserName,
2484
+ authorId: currentUserId,
2485
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
2486
+ };
2487
+ setComments((prev) => [...prev, temp]);
2488
+ try {
2489
+ const serverComment = await postComment(endpoint, selectedItem.id, content, currentUserName, currentUserId);
2490
+ setComments((prev) => prev.map((c) => c.id === temp.id ? serverComment : c));
2491
+ } catch (err) {
2492
+ console.error("[@impakers/debug] \uCF54\uBA58\uD2B8 \uC804\uC1A1 \uC2E4\uD328:", err);
2493
+ }
2494
+ }, [replyText, selectedItem, endpoint, currentUserName, currentUserId]);
2495
+ const handleReplyKeyDown = (0, import_react5.useCallback)((e) => {
2496
+ e.stopPropagation();
2497
+ if (e.nativeEvent.isComposing) return;
2498
+ if (e.key === "Enter" && !e.shiftKey) {
2499
+ e.preventDefault();
2500
+ handleSendReply();
2501
+ }
2502
+ if (e.key === "Escape") handleClose();
2503
+ }, [handleSendReply, handleClose]);
2504
+ const handleToggleStatus = (0, import_react5.useCallback)((item, e) => {
2505
+ e.stopPropagation();
2506
+ const newStatus = item.status === "done" ? "todo" : "done";
2507
+ onStatusChange?.(item.id, newStatus);
2508
+ }, [onStatusChange]);
2386
2509
  const items = tab === "page" ? pageItems : allItems;
2387
2510
  if (typeof document === "undefined") return null;
2388
2511
  return (0, import_react_dom.createPortal)(
@@ -2390,77 +2513,114 @@ function InboxPanel({
2390
2513
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.backdrop, onClick: handleClose }),
2391
2514
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `${styles_module_default5.panel} ${exiting ? styles_module_default5.exiting : ""}`, "data-impakers-debug": "", children: [
2392
2515
  /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.header, children: [
2393
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.headerLeft, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.headerTitle, children: serviceName || "Feedback" }) }),
2394
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: styles_module_default5.closeBtn, onClick: handleClose, type: "button", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M18 6L6 18M6 6l12 12" }) }) })
2395
- ] }),
2396
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.tabs, children: [
2397
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2398
- "button",
2399
- {
2400
- className: `${styles_module_default5.tab} ${tab === "page" ? styles_module_default5.active : ""}`,
2401
- onClick: () => setTab("page"),
2402
- type: "button",
2403
- children: [
2404
- "This Page",
2405
- pageItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.tabBadge, children: pageItems.length })
2406
- ]
2407
- }
2408
- ),
2409
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2410
- "button",
2411
- {
2412
- className: `${styles_module_default5.tab} ${tab === "all" ? styles_module_default5.active : ""}`,
2413
- onClick: () => setTab("all"),
2414
- type: "button",
2415
- children: [
2416
- "All",
2417
- allItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.tabBadge, children: allItems.length })
2418
- ]
2419
- }
2420
- )
2516
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.headerLeft, children: [
2517
+ selectedItem && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: styles_module_default5.backBtn, onClick: handleClose, type: "button", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "16", height: "16", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "15 18 9 12 15 6" }) }) }),
2518
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.headerTitle, children: selectedItem ? selectedItem.title.replace(/^\[피드백\]\s*/, "") : serviceName || "Feedback" })
2519
+ ] }),
2520
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: styles_module_default5.closeBtn, onClick: () => {
2521
+ setExiting(true);
2522
+ setTimeout(() => onClose(), 150);
2523
+ }, type: "button", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M18 6L6 18M6 6l12 12" }) }) })
2421
2524
  ] }),
2422
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.content, children: items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.empty, children: [
2423
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.emptyIcon, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" }) }) }),
2424
- tab === "page" ? "\uC774 \uD398\uC774\uC9C0\uC5D0 \uD53C\uB4DC\uBC31\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" : "\uD53C\uB4DC\uBC31\uC774 \uC5C6\uC2B5\uB2C8\uB2E4"
2425
- ] }) : items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2426
- "div",
2427
- {
2428
- className: styles_module_default5.card,
2429
- onClick: () => onItemClick?.(item),
2430
- children: [
2431
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.cardHeader, children: [
2432
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardAvatar, children: getInitials2(item.authorName) }),
2433
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardInfo, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.cardMeta, children: [
2434
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardAuthor, children: item.authorName }),
2435
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardTime, children: timeAgo2(item.createdAt) })
2436
- ] }) }),
2437
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.cardActions, children: [
2438
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: styles_module_default5.cardAction, type: "button", title: "\uC644\uB8CC \uCC98\uB9AC", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "20 6 9 17 4 12" }) }) }),
2439
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { className: styles_module_default5.cardAction, type: "button", title: "\uB354\uBCF4\uAE30", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
2440
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "12", cy: "12", r: "1" }),
2441
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "19", cy: "12", r: "1" }),
2442
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("circle", { cx: "5", cy: "12", r: "1" })
2443
- ] }) })
2444
- ] })
2445
- ] }),
2446
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardTitle, children: item.title.replace(/^\[피드백\]\s*/, "") }),
2447
- item.screenshot && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardScreenshot, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: item.screenshot, alt: "screenshot" }) }),
2448
- tab === "all" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.cardRoute, children: [
2449
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardRouteName, children: serviceName || "Service" }),
2450
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardRoutePath, children: item.feedbackUrl })
2525
+ selectedItem ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.detailView, children: [
2526
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.detailHeader, children: [
2527
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardAvatar, children: getInitials2(selectedItem.authorName) }),
2528
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { children: [
2529
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.cardMeta, children: [
2530
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardAuthor, children: selectedItem.authorName }),
2531
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardTime, children: timeAgo2(selectedItem.createdAt) })
2451
2532
  ] }),
2452
- item.commentCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.cardFooter, children: [
2453
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardReplyDot }),
2454
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: styles_module_default5.cardReplyCount, children: [
2455
- item.commentCount,
2456
- " ",
2457
- item.commentCount === 1 ? "Reply" : "Replies"
2533
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.detailTitle, children: selectedItem.title.replace(/^\[피드백\]\s*/, "") })
2534
+ ] })
2535
+ ] }),
2536
+ selectedItem.screenshot && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.detailScreenshot, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: selectedItem.screenshot, alt: "screenshot" }) }),
2537
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.commentsList, children: [
2538
+ loadingComments && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.loadingComments, children: "\uB313\uAE00 \uB85C\uB529 \uC911..." }),
2539
+ !loadingComments && comments.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.noComments, children: "\uC544\uC9C1 \uB313\uAE00\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" }),
2540
+ comments.map((c) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.commentItem, children: [
2541
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.commentAvatar, style: { width: 22, height: 22, fontSize: 10 }, children: getInitials2(c.authorName) }),
2542
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.commentBody, children: [
2543
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.commentMeta, children: [
2544
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.commentAuthorName, children: c.authorName }),
2545
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.commentTime, children: timeAgo2(c.createdAt) })
2546
+ ] }),
2547
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.commentContent, children: c.content })
2548
+ ] })
2549
+ ] }, c.id)),
2550
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: commentsEndRef })
2551
+ ] }),
2552
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.replyBox, children: [
2553
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2554
+ "textarea",
2555
+ {
2556
+ ref: replyRef,
2557
+ className: styles_module_default5.replyInput,
2558
+ placeholder: "Reply...",
2559
+ value: replyText,
2560
+ onChange: (e) => setReplyText(e.target.value),
2561
+ onKeyDown: handleReplyKeyDown,
2562
+ rows: 1
2563
+ }
2564
+ ),
2565
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2566
+ "button",
2567
+ {
2568
+ className: `${styles_module_default5.sendBtn} ${replyText.trim() ? styles_module_default5.active : ""}`,
2569
+ onClick: handleSendReply,
2570
+ disabled: !replyText.trim(),
2571
+ type: "button",
2572
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", width: "16", height: "16", children: [
2573
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
2574
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
2458
2575
  ] })
2576
+ }
2577
+ )
2578
+ ] })
2579
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
2580
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.tabs, children: [
2581
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { className: `${styles_module_default5.tab} ${tab === "page" ? styles_module_default5.active : ""}`, onClick: () => setTab("page"), type: "button", children: [
2582
+ "This Page",
2583
+ pageItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.tabBadge, children: pageItems.length })
2584
+ ] }),
2585
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("button", { className: `${styles_module_default5.tab} ${tab === "all" ? styles_module_default5.active : ""}`, onClick: () => setTab("all"), type: "button", children: [
2586
+ "All",
2587
+ allItems.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.tabBadge, children: allItems.length })
2588
+ ] })
2589
+ ] }),
2590
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.content, children: items.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.empty, children: [
2591
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.emptyIcon, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("path", { d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2z" }) }) }),
2592
+ tab === "page" ? "\uC774 \uD398\uC774\uC9C0\uC5D0 \uD53C\uB4DC\uBC31\uC774 \uC5C6\uC2B5\uB2C8\uB2E4" : "\uD53C\uB4DC\uBC31\uC774 \uC5C6\uC2B5\uB2C8\uB2E4"
2593
+ ] }) : items.map((item) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `${styles_module_default5.card} ${item.status === "done" ? styles_module_default5.cardDone : ""}`, onClick: () => handleItemClick(item), children: [
2594
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.cardHeader, children: [
2595
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardAvatar, children: getInitials2(item.authorName) }),
2596
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardInfo, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.cardMeta, children: [
2597
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardAuthor, children: item.authorName }),
2598
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardTime, children: timeAgo2(item.createdAt) })
2599
+ ] }) }),
2600
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2601
+ "button",
2602
+ {
2603
+ className: `${styles_module_default5.checkBtn} ${item.status === "done" ? styles_module_default5.checked : ""}`,
2604
+ onClick: (e) => handleToggleStatus(item, e),
2605
+ type: "button",
2606
+ title: item.status === "done" ? "\uBBF8\uC644\uB8CC\uB85C \uBCC0\uACBD" : "\uC644\uB8CC \uCC98\uB9AC",
2607
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("polyline", { points: "20 6 9 17 4 12" }) })
2608
+ }
2609
+ )
2610
+ ] }),
2611
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardTitle, children: item.title.replace(/^\[피드백\]\s*/, "") }),
2612
+ item.screenshot && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardScreenshot, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("img", { src: item.screenshot, alt: "screenshot" }) }),
2613
+ tab === "all" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: styles_module_default5.cardRoute, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardRoutePath, children: item.feedbackUrl }) }),
2614
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: styles_module_default5.cardFooter, children: [
2615
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: styles_module_default5.cardReplyDot }),
2616
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: styles_module_default5.cardReplyCount, children: [
2617
+ item.commentCount,
2618
+ " ",
2619
+ item.commentCount === 1 ? "Reply" : "Replies"
2459
2620
  ] })
2460
- ]
2461
- },
2462
- item.id
2463
- )) })
2621
+ ] })
2622
+ ] }, item.id)) })
2623
+ ] })
2464
2624
  ] })
2465
2625
  ] }),
2466
2626
  document.body
@@ -2735,13 +2895,8 @@ function DebugWidget({ endpoint, getUser, onHide }) {
2735
2895
  isFixed: t.feedbackMarker.isFixed,
2736
2896
  boundingBox: t.feedbackMarker.boundingBox
2737
2897
  }));
2738
- if (serverAnnotations.length > 0) {
2739
- setAnnotations((prev) => {
2740
- const existingIds = new Set(prev.map((a) => a.id));
2741
- const newOnes = serverAnnotations.filter((a) => !existingIds.has(a.id));
2742
- return [...prev, ...newOnes];
2743
- });
2744
- }
2898
+ setAnnotations(serverAnnotations);
2899
+ saveRouteAnnotations(serverAnnotations);
2745
2900
  }).catch(() => {
2746
2901
  });
2747
2902
  }, [endpoint]);
@@ -3061,6 +3216,10 @@ ${elementInfo.join("\n")}`);
3061
3216
  }));
3062
3217
  } catch (err) {
3063
3218
  console.error("[@impakers/debug] \uCF54\uBA58\uD2B8 \uC804\uC1A1 \uC2E4\uD328:", err);
3219
+ setThreadComments((prev) => ({
3220
+ ...prev,
3221
+ [taskId]: (prev[taskId] || []).filter((c) => c.id !== tempComment.id)
3222
+ }));
3064
3223
  }
3065
3224
  }, [getUser, endpoint]);
3066
3225
  const handleThreadClose = (0, import_react7.useCallback)(() => {
@@ -3182,7 +3341,15 @@ ${elementInfo.join("\n")}`);
3182
3341
  allItems: allRouteItems,
3183
3342
  currentPath,
3184
3343
  serviceName: getServiceName() || void 0,
3185
- onClose: () => setShowInbox(false)
3344
+ endpoint,
3345
+ currentUserName: getUser?.()?.name ? String(getUser().name) : "\uC775\uBA85",
3346
+ currentUserId: getUser?.()?.id ? String(getUser().id) : void 0,
3347
+ onClose: () => setShowInbox(false),
3348
+ onStatusChange: (taskId, status) => {
3349
+ setAnnotations(
3350
+ (prev) => prev.map((a) => a.id === taskId ? { ...a, status } : a)
3351
+ );
3352
+ }
3186
3353
  }
3187
3354
  ),
3188
3355
  showSettings && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(