create-fullstack-scaffold 0.4.2 → 0.4.4

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.
Files changed (156) hide show
  1. package/dist/cli/index.js +513 -122
  2. package/dist/cli/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/template/dist/cli/index.js +237 -94
  5. package/template/dist/cli/index.js.map +1 -1
  6. package/template/dist/client/admin.html +15 -10
  7. package/template/dist/client/assets/App-BpFUIC-5.js +114 -0
  8. package/template/dist/client/assets/{CartPage-DESSHkaG.js → CartPage-DgDZP-R5.js} +2 -2
  9. package/template/dist/client/assets/{CategoriesPage-DqLZ_Mom.js → CategoriesPage-fuYNiSmE.js} +2 -2
  10. package/template/dist/client/assets/ContentDetailPage-BvvFU1Mr.js +1 -0
  11. package/template/dist/client/assets/ContentListPage-ShPxo6WG.js +1 -0
  12. package/template/dist/client/assets/DashboardPage-C1rZzZo4.js +11 -0
  13. package/template/dist/client/assets/{DeveloperDashboardPage-Cum7zFwO.js → DeveloperDashboardPage-_WtmbVoA.js} +2 -2
  14. package/template/dist/client/assets/{EmptyState-BK7ttK8D.js → EmptyState-DEyOQjbY.js} +1 -1
  15. package/template/dist/client/assets/LoadingSpinner-BcHjaM1m.js +6 -0
  16. package/template/dist/client/assets/LoginPage-CjeQqDdO.js +1 -0
  17. package/template/dist/client/assets/LogoutOutlined-ColFAHdd.js +1 -0
  18. package/template/dist/client/assets/NotificationPage-DRkEv02s.js +1 -0
  19. package/template/dist/client/assets/OrdersPage-7I3vPWLP.js +11 -0
  20. package/template/dist/client/assets/{PluginDetailPage-Br24YS4P.js → PluginDetailPage-CWyxdVCg.js} +3 -13
  21. package/template/dist/client/assets/PluginsPage-DRgWLeJT.js +6 -0
  22. package/template/dist/client/assets/ProfilePage-2FFkaii8.js +16 -0
  23. package/template/dist/client/assets/PublishPage-DW7yvROx.js +1 -0
  24. package/template/dist/client/assets/{RegisterPage-rPFG4Sry.js → RegisterPage-Dvaf9b0e.js} +2 -2
  25. package/template/dist/client/assets/SaveOutlined-CLQ2tsSY.js +2 -0
  26. package/template/dist/client/assets/{SearchPage-DQl1U5Uy.js → SearchPage-DvnEyswS.js} +2 -2
  27. package/template/dist/client/assets/{SettingsPage-DaYE80wj.js → SettingsPage-IrU-L9Zr.js} +2 -2
  28. package/template/dist/client/assets/{StatusBadge-BJ3W2Zc7.js → StatusBadge-CG7wVqpu.js} +1 -1
  29. package/template/dist/client/assets/{TodoPage-zC5wWNBa.js → TodoPage-B7D-bl65.js} +3 -3
  30. package/template/dist/client/assets/TopicsPage-CYCNr-mn.js +6 -0
  31. package/template/dist/client/assets/{WebSocketPage-B4NLdz1w.js → WebSocketPage-CGEg6QJE.js} +2 -2
  32. package/template/dist/client/assets/{activity-B94BUAsD.js → activity-CgTz9Mrd.js} +1 -1
  33. package/template/dist/client/assets/admin-D2iHWNOg.js +1 -0
  34. package/template/dist/client/assets/api-request-DIJocPxr.js +356 -0
  35. package/template/dist/client/assets/{arrow-left-H5JH0iU1.js → arrow-left-DtLQ3tTk.js} +1 -1
  36. package/template/dist/client/assets/{chevron-down-DwRh_wjD.js → chevron-down-CpIAV_yr.js} +1 -1
  37. package/template/dist/client/assets/{chevron-right-CpIWaqAL.js → chevron-right-CnU7oPQs.js} +1 -1
  38. package/template/dist/client/assets/{circle-check-big-CSElLscG.js → circle-check-big-CrZdwS75.js} +1 -1
  39. package/template/dist/client/assets/{circle-x-CYxr4RAw.js → circle-x-CvN9r3fW.js} +1 -1
  40. package/template/dist/client/assets/{clock-BseUJ7ex.js → clock-CTeSZBiH.js} +1 -1
  41. package/template/dist/client/assets/{download-BsGC_Xhq.js → download-OSVfVuNV.js} +1 -1
  42. package/template/dist/client/assets/{external-link-UTDzdjq8.js → external-link-fBsuHMby.js} +1 -1
  43. package/template/dist/client/assets/{eye-nR10ui7i.js → eye-CwlZZEsj.js} +1 -1
  44. package/template/dist/client/assets/index-09IqiOaE.css +1 -0
  45. package/template/dist/client/assets/index-B3CRby6r.js +51 -0
  46. package/template/dist/client/assets/index-CC_zy73y.js +17 -0
  47. package/template/dist/client/assets/main-Cn4IDo2I.js +92 -0
  48. package/template/dist/client/assets/merchant-DDDN9bMu.js +40 -0
  49. package/template/dist/client/assets/{message-square-CwWGL-Bh.js → message-square-BRaZfgbJ.js} +1 -1
  50. package/template/dist/client/assets/pluginStore-DDsWJPe6.js +1 -0
  51. package/template/dist/client/assets/{plus-pZld_nUL.js → plus-DDZfPiDJ.js} +1 -1
  52. package/template/dist/client/assets/sse-client-DGQ072hl.js +64 -0
  53. package/template/dist/client/assets/star-C7tO6w4H.js +11 -0
  54. package/template/dist/client/assets/{tag-DsiUPF90.js → tag-DBfpQDuJ.js} +1 -1
  55. package/template/dist/client/assets/tenant-CizbLaLJ.js +1 -0
  56. package/template/dist/client/assets/{trash-2-DRblNbnA.js → trash-2-BP7fkd5b.js} +1 -1
  57. package/template/dist/client/assets/{triangle-alert-D1CLh-Vd.js → triangle-alert-CrOQEdJ2.js} +1 -1
  58. package/template/dist/client/assets/{wifi-BwXjnCqI.js → wifi-CwYSE0J4.js} +1 -1
  59. package/template/dist/client/assets/{x-BH2rJdFq.js → x-t615pnNR.js} +1 -1
  60. package/template/dist/client/content/index.html +5 -4
  61. package/template/dist/client/index.html +4 -3
  62. package/template/dist/client/merchant.html +18 -0
  63. package/template/dist/client/notifications/index.html +6 -5
  64. package/template/dist/client/tenant.html +18 -0
  65. package/template/dist/client/todos/index.html +6 -5
  66. package/template/dist/client/websocket/index.html +6 -5
  67. package/template/dist/cloudflare/chunk-HX7DVRDX.js +1 -0
  68. package/template/dist/cloudflare/{chunk-QBHAPWIA.js → chunk-IXJL2LE4.js} +1 -1
  69. package/template/dist/cloudflare/chunk-Q34AN3RF.js +14 -0
  70. package/template/dist/cloudflare/{chunk-BHPTQ4K2.js → chunk-ZAMVL4EG.js} +2 -2
  71. package/template/dist/cloudflare/cloudflare.js +35 -29
  72. package/template/dist/cloudflare/db-4AQOSFAX.js +1 -0
  73. package/template/dist/cloudflare/{migrator-2ZYYKNI5.js → migrator-TEPBVUFO.js} +1 -1
  74. package/template/dist/cloudflare/permission-service-impl-RE7NPW3Q.js +1 -0
  75. package/template/dist/cloudflare/schema-DVEMT3X2.js +1 -0
  76. package/template/dist/cloudflare/test-setup-Z2RYE5B4.js +265 -0
  77. package/template/dist/server/chunk-27SIJSPF.js +1 -0
  78. package/template/dist/server/chunk-37QNGBQU.js +1 -0
  79. package/template/dist/server/chunk-FIY4CGJJ.js +1 -0
  80. package/template/dist/server/chunk-HZUDBIT4.js +1 -0
  81. package/template/dist/server/chunk-I6OBDFDU.js +1 -0
  82. package/template/dist/server/chunk-JHNYLNG7.js +1 -0
  83. package/template/dist/server/chunk-MDOVVKKD.js +1 -0
  84. package/template/dist/server/chunk-NSOCT7E5.js +1 -0
  85. package/template/dist/server/chunk-OU5IGVVO.js +1 -0
  86. package/template/dist/server/chunk-OYCBNRMK.js +1 -0
  87. package/template/dist/server/chunk-P2RJNNGD.js +1 -0
  88. package/template/dist/server/chunk-UMAQLNPE.js +1 -0
  89. package/template/dist/server/chunk-XZZTSRSN.js +1 -0
  90. package/template/dist/server/content-service-5QVHDR5X.js +1 -0
  91. package/template/dist/server/db-FLI5L5DD.js +1 -0
  92. package/template/dist/server/dispute-service-E2FCYUEM.js +1 -0
  93. package/template/dist/server/init-72JXJV3I.js +46 -0
  94. package/template/dist/server/init-FWYXSKPX.js +46 -0
  95. package/template/dist/server/node.js +34 -28
  96. package/template/dist/server/order-service-TKGG5S5K.js +1 -0
  97. package/template/dist/server/permission-service-impl-M3AKEYNY.js +1 -0
  98. package/template/dist/server/schema-V4UG7HMU.js +1 -0
  99. package/template/dist/server/tenant-service-JG6UUWXQ.js +1 -0
  100. package/template/dist/server/tenant-service-XJWZSEDX.js +1 -0
  101. package/template/dist/{cloudflare/test-setup-NMZJZLRV.js → server/test-setup-VFOPBGYM.js} +83 -2
  102. package/template/dist/server/ticket-service-3RSW7V2Z.js +1 -0
  103. package/template/dist/server/todo-service-S6BGIO7D.js +1 -0
  104. package/template/package.json +1 -1
  105. package/template/src/client/App.tsx +3 -1
  106. package/template/src/client/pages/ContentListPage.tsx +36 -4
  107. package/template/src/client/pages/PluginsPage.tsx +112 -20
  108. package/template/src/client/pages/TodoPage.tsx +9 -1
  109. package/template/src/client/preset-ui-config.ts +79 -2
  110. package/template/src/merchant/pages/DisputesPage.tsx +11 -11
  111. package/template/src/merchant/pages/OrdersPage.tsx +4 -3
  112. package/template/src/merchant/pages/ProductsPage.tsx +2 -2
  113. package/template/src/merchant/stores/merchantStore.ts +11 -6
  114. package/template/src/server/db/init.ts +5 -253
  115. package/template/src/server/module-content/routes/topics-routes.ts +250 -0
  116. package/template/src/server/module-content/services/content-service.ts +1 -1
  117. package/template/src/server/module-plugin/services/plugin-seed-service.ts +623 -0
  118. package/template/src/server/module-tenant/routes/tenant-routes.ts +2 -2
  119. package/template/src/server/module-tenant/services/tenant-service.ts +63 -17
  120. package/template/src/server/module-todos/services/todo-service.ts +1 -1
  121. package/template/src/shared/modules/merchant/index.ts +9 -0
  122. package/template/src/shared/modules/merchant/schemas.ts +37 -0
  123. package/template/src/shared/modules/tenant/index.ts +2 -0
  124. package/template/src/shared/schemas/index.ts +27 -0
  125. package/template/src/tenant/layouts/Header.tsx +1 -1
  126. package/template/src/tenant/layouts/Sidebar.tsx +1 -1
  127. package/template/src/tenant/pages/SettingsPage.tsx +4 -8
  128. package/template/src/tenant/stores/tenantStore.ts +41 -302
  129. package/template/tsconfig.json +1 -0
  130. package/template/tsup.config.ts +11 -3
  131. package/template/dist/client/assets/ContentDetailPage-DdltMANL.js +0 -1
  132. package/template/dist/client/assets/ContentListPage-B63sUB6N.js +0 -1
  133. package/template/dist/client/assets/DashboardPage-tUMilc7Z.js +0 -11
  134. package/template/dist/client/assets/LoadingSpinner-DVYOLSRM.js +0 -6
  135. package/template/dist/client/assets/LoginPage-g9mSLIMC.js +0 -6
  136. package/template/dist/client/assets/NotificationPage-COTzp-HD.js +0 -1
  137. package/template/dist/client/assets/OrdersPage-BsPh4oEI.js +0 -11
  138. package/template/dist/client/assets/PluginsPage-BNtAe_yo.js +0 -6
  139. package/template/dist/client/assets/ProfilePage-dL_iSuZN.js +0 -16
  140. package/template/dist/client/assets/PublishPage-D96FnbLA.js +0 -1
  141. package/template/dist/client/assets/TopicsPage-DyLjZa4D.js +0 -6
  142. package/template/dist/client/assets/admin-Bh1vfz_L.js +0 -486
  143. package/template/dist/client/assets/index-1bA-ixFv.js +0 -114
  144. package/template/dist/client/assets/index-CWh3vXC_.css +0 -1
  145. package/template/dist/client/assets/main-DHnArIp_.js +0 -82
  146. package/template/dist/client/assets/pluginStore-XQfsm3iR.js +0 -1
  147. package/template/dist/client/content/content-1/index.html +0 -18
  148. package/template/dist/client/content/content-13/index.html +0 -18
  149. package/template/dist/client/content/content-14/index.html +0 -18
  150. package/template/dist/client/content/content-15/index.html +0 -18
  151. package/template/dist/client/content/content-19/index.html +0 -18
  152. package/template/dist/client/content/content-2/index.html +0 -18
  153. package/template/dist/client/content/content-20/index.html +0 -18
  154. package/template/dist/cloudflare/chunk-YY6FRMAQ.js +0 -14
  155. package/template/dist/cloudflare/db-7J42RQ3T.js +0 -1
  156. package/template/dist/cloudflare/permission-service-impl-TGXVSSSA.js +0 -1
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-1bA-ixFv.js";/**
1
+ import{c as a}from"./sse-client-DGQ072hl.js";/**
2
2
  * @license lucide-react v0.576.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -0,0 +1 @@
1
+ import{b as n}from"./main-Cn4IDo2I.js";import{c}from"./index-B3CRby6r.js";function t(r){return r instanceof Error?r.message:"Unknown error"}const p=c((r,i)=>({plugins:[],currentPlugin:null,reviews:[],myPlugins:[],categories:[],stats:null,searchQuery:"",selectedCategory:null,loading:!1,error:null,pagination:{page:1,limit:20,total:0},fetchPlugins:async(a=1)=>{r({loading:!0,error:null});try{const{selectedCategory:e}=i(),s={page:a,limit:20,sort:"newest"};e&&(s.category=e);const l=await(await n.api.plugins.$get({query:s})).json();l.success?r({plugins:l.data.plugins,pagination:{page:l.data.page,limit:l.data.limit,total:l.data.total},loading:!1}):r({loading:!1,error:l.error??"Failed to fetch plugins"})}catch(e){r({error:t(e),loading:!1})}},fetchPlugin:async a=>{r({loading:!0,error:null,currentPlugin:null});try{const s=await(await n.api.plugins[":slug"].$get({param:{slug:a}})).json();s.success?r({currentPlugin:s.data,loading:!1}):r({loading:!1,error:s.error??"Plugin not found"})}catch(e){r({error:t(e),loading:!1})}},fetchReviews:async a=>{try{const s=await(await n.api.plugins[":slug"].reviews.$get({param:{slug:a}})).json();s.success&&r({reviews:s.data})}catch(e){console.error("Failed to fetch reviews:",e)}},searchPlugins:async(a,e=1)=>{r({loading:!0,error:null});try{const{selectedCategory:s}=i(),l=await(await n.api.plugins.search.$get({query:{q:a,page:e,limit:20,...s?{category:s}:{}}})).json();l.success?r({plugins:l.data.plugins,pagination:{page:l.data.page,limit:l.data.limit,total:l.data.total},loading:!1}):r({loading:!1,error:l.error??"Search failed"})}catch(s){r({error:t(s),loading:!1})}},fetchCategories:async()=>{try{const e=await(await n.api.categories.$get()).json();e.success&&r({categories:e.data})}catch(a){console.error("Failed to fetch categories:",a)}},fetchStats:async()=>{try{const e=await(await n.api.stats.$get()).json();e.success&&r({stats:e.data})}catch(a){console.error("Failed to fetch stats:",a)}},fetchMyPlugins:async()=>{r({loading:!0,error:null});try{const e=await(await n.api.plugins.mine.$get()).json();e.success?r({myPlugins:e.data,loading:!1}):r({loading:!1,error:e.error??"Failed to fetch your plugins"})}catch(a){r({error:t(a),loading:!1})}},createPlugin:async a=>{r({loading:!0,error:null});try{const s=await(await n.api.plugins.$post({json:a})).json();return s.success?(r(o=>({myPlugins:[s.data,...o.myPlugins],loading:!1})),s.data.slug):(r({loading:!1,error:s.error??"Failed to create plugin"}),null)}catch(e){return r({error:t(e),loading:!1}),null}},deletePlugin:async a=>{r({loading:!0,error:null});try{const s=await(await n.api.plugins[":slug"].$delete({param:{slug:a}})).json();s.success?r(o=>({myPlugins:o.myPlugins.filter(l=>l.slug!==a),plugins:o.plugins.filter(l=>l.slug!==a),loading:!1})):r({loading:!1,error:s.error??"Failed to delete plugin"})}catch(e){r({error:t(e),loading:!1})}},submitReview:async(a,e)=>{r({loading:!0,error:null});try{const o=await(await n.api.plugins[":slug"].reviews.$post({param:{slug:a},json:e})).json();o.success?r(l=>({reviews:[o.data,...l.reviews],loading:!1})):r({loading:!1,error:o.error??"Failed to submit review"})}catch(s){r({error:t(s),loading:!1})}},trackInstall:async a=>{try{await n.api.plugins[":slug"].install.$post({param:{slug:a}})}catch(e){console.error("Failed to track install:",e)}},setSearchQuery:a=>r({searchQuery:a}),setSelectedCategory:a=>r({selectedCategory:a}),clearError:()=>r({error:null}),clearCurrentPlugin:()=>r({currentPlugin:null,reviews:[]})}));export{p as u};
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-1bA-ixFv.js";/**
1
+ import{c as e}from"./sse-client-DGQ072hl.js";/**
2
2
  * @license lucide-react v0.576.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -0,0 +1,64 @@
1
+ var M=Object.defineProperty;var B=(s,e,t)=>e in s?M(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t;var i=(s,e,t)=>B(s,typeof e!="symbol"?e+"":e,t);import{r as E}from"./index-B3CRby6r.js";/**
2
+ * @license lucide-react v0.576.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const q=(...s)=>s.filter((e,t,r)=>!!e&&e.trim()!==""&&r.indexOf(e)===t).join(" ").trim();/**
7
+ * @license lucide-react v0.576.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const D=s=>s.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase();/**
12
+ * @license lucide-react v0.576.0 - ISC
13
+ *
14
+ * This source code is licensed under the ISC license.
15
+ * See the LICENSE file in the root directory of this source tree.
16
+ */const J=s=>s.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,r)=>r?r.toUpperCase():t.toLowerCase());/**
17
+ * @license lucide-react v0.576.0 - ISC
18
+ *
19
+ * This source code is licensed under the ISC license.
20
+ * See the LICENSE file in the root directory of this source tree.
21
+ */const $=s=>{const e=J(s);return e.charAt(0).toUpperCase()+e.slice(1)};/**
22
+ * @license lucide-react v0.576.0 - ISC
23
+ *
24
+ * This source code is licensed under the ISC license.
25
+ * See the LICENSE file in the root directory of this source tree.
26
+ */var F={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
27
+ * @license lucide-react v0.576.0 - ISC
28
+ *
29
+ * This source code is licensed under the ISC license.
30
+ * See the LICENSE file in the root directory of this source tree.
31
+ */const G=s=>{for(const e in s)if(e.startsWith("aria-")||e==="role"||e==="title")return!0;return!1};/**
32
+ * @license lucide-react v0.576.0 - ISC
33
+ *
34
+ * This source code is licensed under the ISC license.
35
+ * See the LICENSE file in the root directory of this source tree.
36
+ */const Z=E.forwardRef(({color:s="currentColor",size:e=24,strokeWidth:t=2,absoluteStrokeWidth:r,className:n="",children:a,iconNode:h,...o},f)=>E.createElement("svg",{ref:f,...F,width:e,height:e,stroke:s,strokeWidth:r?Number(t)*24/Number(e):t,className:q("lucide",n),...!a&&!G(o)&&{"aria-hidden":"true"},...o},[...h.map(([l,m])=>E.createElement(l,m)),...Array.isArray(a)?a:[a]]));/**
37
+ * @license lucide-react v0.576.0 - ISC
38
+ *
39
+ * This source code is licensed under the ISC license.
40
+ * See the LICENSE file in the root directory of this source tree.
41
+ */const x=(s,e)=>{const t=E.forwardRef(({className:r,...n},a)=>E.createElement(Z,{ref:a,iconNode:e,className:q(`lucide-${D($(s))}`,`lucide-${s}`,r),...n}));return t.displayName=$(s),t};/**
42
+ * @license lucide-react v0.576.0 - ISC
43
+ *
44
+ * This source code is licensed under the ISC license.
45
+ * See the LICENSE file in the root directory of this source tree.
46
+ */const K=[["path",{d:"M10.268 21a2 2 0 0 0 3.464 0",key:"vwvbt9"}],["path",{d:"M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326",key:"11g9vi"}]],he=x("bell",K);/**
47
+ * @license lucide-react v0.576.0 - ISC
48
+ *
49
+ * This source code is licensed under the ISC license.
50
+ * See the LICENSE file in the root directory of this source tree.
51
+ */const z=[["path",{d:"M9.671 4.136a2.34 2.34 0 0 1 4.659 0 2.34 2.34 0 0 0 3.319 1.915 2.34 2.34 0 0 1 2.33 4.033 2.34 2.34 0 0 0 0 3.831 2.34 2.34 0 0 1-2.33 4.033 2.34 2.34 0 0 0-3.319 1.915 2.34 2.34 0 0 1-4.659 0 2.34 2.34 0 0 0-3.32-1.915 2.34 2.34 0 0 1-2.33-4.033 2.34 2.34 0 0 0 0-3.831A2.34 2.34 0 0 1 6.35 6.051a2.34 2.34 0 0 0 3.319-1.915",key:"1i5ecw"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]],le=x("settings",z);/**
52
+ * @license lucide-react v0.576.0 - ISC
53
+ *
54
+ * This source code is licensed under the ISC license.
55
+ * See the LICENSE file in the root directory of this source tree.
56
+ */const Q=[["path",{d:"M16 7h6v6",key:"box55l"}],["path",{d:"m22 7-8.5 8.5-5-5L2 17",key:"1t1m79"}]],ue=x("trending-up",Q);/**
57
+ * @license lucide-react v0.576.0 - ISC
58
+ *
59
+ * This source code is licensed under the ISC license.
60
+ * See the LICENSE file in the root directory of this source tree.
61
+ */const X=[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]],de=x("user",X);function Y(s,e){let t;try{t=s()}catch{return}return{getItem:n=>{var a;const h=f=>f===null?null:JSON.parse(f,void 0),o=(a=t.getItem(n))!=null?a:null;return o instanceof Promise?o.then(h):h(o)},setItem:(n,a)=>t.setItem(n,JSON.stringify(a,void 0)),removeItem:n=>t.removeItem(n)}}const N=s=>e=>{try{const t=s(e);return t instanceof Promise?t:{then(r){return N(r)(t)},catch(r){return this}}}catch(t){return{then(r){return this},catch(r){return N(r)(t)}}}},V=(s,e)=>(t,r,n)=>{let a={storage:Y(()=>window.localStorage),partialize:c=>c,version:0,merge:(c,g)=>({...g,...c}),...e},h=!1,o=0;const f=new Set,l=new Set;let m=a.storage;if(!m)return s((...c)=>{console.warn(`[zustand persist middleware] Unable to update item '${a.name}', the given storage is currently unavailable.`),t(...c)},r,n);const S=()=>{const c=a.partialize({...r()});return m.setItem(a.name,{state:c,version:a.version})},b=n.setState;n.setState=(c,g)=>(b(c,g),S());const w=s((...c)=>(t(...c),S()),r,n);n.getInitialState=()=>w;let v;const u=()=>{var c,g;if(!m)return;const _=++o;h=!1,f.forEach(d=>{var p;return d((p=r())!=null?p:w)});const y=((g=a.onRehydrateStorage)==null?void 0:g.call(a,(c=r())!=null?c:w))||void 0;return N(m.getItem.bind(m))(a.name).then(d=>{if(d)if(typeof d.version=="number"&&d.version!==a.version){if(a.migrate){const p=a.migrate(d.state,d.version);return p instanceof Promise?p.then(H=>[!0,H]):[!0,p]}console.error("State loaded from storage couldn't be migrated since no migrate function was provided")}else return[!1,d.state];return[!1,void 0]}).then(d=>{var p;if(_!==o)return;const[H,j]=d;if(v=a.merge(j,(p=r())!=null?p:w),t(v,!0),H)return S()}).then(()=>{_===o&&(y==null||y(r(),void 0),v=r(),h=!0,l.forEach(d=>d(v)))}).catch(d=>{_===o&&(y==null||y(void 0,d))})};return n.persist={setOptions:c=>{a={...a,...c},c.storage&&(m=c.storage)},clearStorage:()=>{m==null||m.removeItem(a.name)},getOptions:()=>a,rehydrate:()=>u(),hasHydrated:()=>h,onHydrate:c=>(f.add(c),()=>{f.delete(c)}),onFinishHydration:c=>(l.add(c),()=>{l.delete(c)})},a.skipHydration||u(),v||w},fe=V;var ee=/^[\w!#$%&'*.^`|~+-]+$/,te=(s,e,t={})=>{if(!ee.test(s))throw new Error("Invalid cookie name");let r=`${s}=${e}`;if(s.startsWith("__Secure-")&&!t.secure)throw new Error("__Secure- Cookie must have Secure attributes");if(s.startsWith("__Host-")){if(!t.secure)throw new Error("__Host- Cookie must have Secure attributes");if(t.path!=="/")throw new Error('__Host- Cookie must have Path attributes with "/"');if(t.domain)throw new Error("__Host- Cookie must not have Domain attributes")}for(const n of["domain","path"])if(t[n]&&/[;\r\n]/.test(t[n]))throw new Error(`${n} must not contain ";", "\\r", or "\\n"`);if(t&&typeof t.maxAge=="number"&&t.maxAge>=0){if(t.maxAge>3456e4)throw new Error("Cookies Max-Age SHOULD NOT be greater than 400 days (34560000 seconds) in duration.");r+=`; Max-Age=${t.maxAge|0}`}if(t.domain&&t.prefix!=="host"&&(r+=`; Domain=${t.domain}`),t.path&&(r+=`; Path=${t.path}`),t.expires){if(t.expires.getTime()-Date.now()>3456e7)throw new Error("Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future.");r+=`; Expires=${t.expires.toUTCString()}`}if(t.httpOnly&&(r+="; HttpOnly"),t.secure&&(r+="; Secure"),t.sameSite&&(r+=`; SameSite=${t.sameSite.charAt(0).toUpperCase()+t.sameSite.slice(1)}`),t.priority&&(r+=`; Priority=${t.priority.charAt(0).toUpperCase()+t.priority.slice(1)}`),t.partitioned){if(!t.secure)throw new Error("Partitioned Cookie must have Secure attributes");r+="; Partitioned"}return r},re=(s,e,t)=>(e=encodeURIComponent(e),te(s,e,t)),se=(s,e)=>(s=s.replace(/\/+$/,""),s=s+"/",e=e.replace(/^\/+/,""),s+e),k=(s,e)=>{for(const[t,r]of Object.entries(e)){const n=new RegExp("/:"+t+"(?:{[^/]+})?\\??");s=s.replace(n,r?`/${r}`:"")}return s},ne=s=>{const e=new URLSearchParams;for(const[t,r]of Object.entries(s))if(r!==void 0)if(Array.isArray(r))for(const n of r)e.append(t,n);else e.set(t,r);return e},R=(s,e)=>{switch(e){case"ws":return s.replace(/^http/,"ws");case"http":return s.replace(/^ws/,"http")}},L=s=>/^https?:\/\/[^\/]+?\/index(?=\?|$)/.test(s)?s.replace(/\/index(?=\?|$)/,"/"):s.replace(/\/index(?=\?|$)/,"");function P(s){return typeof s=="object"&&s!==null&&!Array.isArray(s)}function A(s,e){if(!P(s)&&!P(e))return e;const t={...s};for(const r in e){const n=e[r];P(t[r])&&P(n)?t[r]=A(t[r],n):t[r]=n}return t}var W=(s,e)=>new Proxy(()=>{},{get(r,n){if(!(typeof n!="string"||n==="then"))return W(s,[...e,n])},apply(r,n,a){return s({path:e,args:a})}}),O=class{constructor(s,e,t){i(this,"url");i(this,"method");i(this,"buildSearchParams");i(this,"queryParams");i(this,"pathParams",{});i(this,"rBody");i(this,"cType");i(this,"fetch",async(s,e)=>{if(s){if(s.query&&(this.queryParams=this.buildSearchParams(s.query)),s.form){const o=new FormData;for(const[f,l]of Object.entries(s.form))if(l!==void 0)if(Array.isArray(l))for(const m of l)o.append(f,m);else o.append(f,l);this.rBody=o}s.json&&(this.rBody=JSON.stringify(s.json),this.cType="application/json"),s.param&&(this.pathParams=s.param)}let t=this.method.toUpperCase();const r={...s==null?void 0:s.header,...typeof(e==null?void 0:e.headers)=="function"?await e.headers():e==null?void 0:e.headers};if(s!=null&&s.cookie){const o=[];for(const[f,l]of Object.entries(s.cookie))o.push(re(f,l,{path:"/"}));r.Cookie=o.join(",")}this.cType&&(r["Content-Type"]=this.cType);const n=new Headers(r??void 0);let a=this.url;a=L(a),a=k(a,this.pathParams),this.queryParams&&(a=a+"?"+this.queryParams.toString()),t=this.method.toUpperCase();const h=!(t==="GET"||t==="HEAD");return((e==null?void 0:e.fetch)||fetch)(a,{body:h?this.rBody:void 0,method:t,headers:n,...e==null?void 0:e.init})});this.url=s,this.method=e,this.buildSearchParams=t.buildSearchParams}},me=(s,e)=>W(function t(r){var S,b,w,v;const n=(e==null?void 0:e.buildSearchParams)??ne,a=[...r.path],h=a.slice(-3).reverse();if(h[0]==="toString")return h[1]==="name"?h[2]||"":t.toString();if(h[0]==="valueOf")return h[1]==="name"?h[2]||"":t;let o="";if(/^\$/.test(h[0])){const u=a.pop();u&&(o=u.replace(/^\$/,""))}const f=a.join("/"),l=se(s,f);if(o==="url"||o==="path"){let u=l;return r.args[0]&&(r.args[0].param&&(u=k(l,r.args[0].param)),r.args[0].query&&(u=u+"?"+n(r.args[0].query).toString())),u=L(u),o==="url"?new URL(u):u.slice(s.replace(/\/+$/,"").length).replace(/^\/?/,"/")}if(o==="ws"){const u=R(r.args[0]&&r.args[0].param?k(l,r.args[0].param):l,"ws"),c=new URL(u),g=(S=r.args[0])==null?void 0:S.query;return g&&Object.entries(g).forEach(([y,d])=>{Array.isArray(d)?d.forEach(p=>c.searchParams.append(y,p)):c.searchParams.set(y,d)}),((...y)=>(e==null?void 0:e.webSocket)!==void 0&&typeof e.webSocket=="function"?e.webSocket(...y):new WebSocket(...y))(c.toString())}if(o==="sse"){const u=R(r.args[0]&&r.args[0].param?k(l,r.args[0].param):l,"http"),c=new URL(u),g=(b=r.args[0])==null?void 0:b.query;return g&&Object.entries(g).forEach(([y,d])=>{Array.isArray(d)?d.forEach(p=>c.searchParams.append(y,p)):c.searchParams.set(y,d)}),((e==null?void 0:e.sse)||(y=>new EventSource(y)))(c.toString())}if(o==="image"||o==="svg"){const u=new O(l,"get",{buildSearchParams:n});e??(e={});const c=A(e,{...r.args[1]});return u.fetch(r.args[0],c).then(g=>o==="svg"?g.text():g.blob())}if(o==="download"){const u=new O(l,"get",{buildSearchParams:n});e??(e={});const c=A(e,((w=r.args)==null?void 0:w[1])||{});return u.fetch((v=r.args)==null?void 0:v[0],c).then(g=>g.blob())}const m=new O(l,o,{buildSearchParams:n});if(o){e??(e={});const u=A(e,{...r.args[1]});return m.fetch(r.args[0],u)}return m},[]);const T=typeof globalThis<"u"&&"WebSocket"in globalThis,I=T?globalThis.WebSocket.OPEN:1,ae=T?globalThis.WebSocket.CONNECTING:0,U=T?globalThis.WebSocket:null;class C{constructor(){i(this,"binaryType","blob");i(this,"bufferedAmount",0);i(this,"extensions","");i(this,"onclose",null);i(this,"onerror",null);i(this,"onmessage",null);i(this,"onopen",null);i(this,"protocol","");i(this,"readyState",0);i(this,"url","")}send(e){return 0}close(e,t){}addEventListener(){}removeEventListener(){}dispatchEvent(){return!0}}i(C,"CONNECTING",0),i(C,"OPEN",1),i(C,"CLOSING",2),i(C,"CLOSED",3);function ie(s){return U?new U(s):new C}class ge{constructor(e){i(this,"ws");i(this,"handlers",new Map);i(this,"pendingRequests",new Map);i(this,"statusHandlers",[]);i(this,"messageBuffer",[]);i(this,"_status","closed");this.ws=ie(e.toString()),this.attachSocket()}get status(){return this._status}getSocket(){return this.ws instanceof C?null:this.ws}attachSocket(){const e=this.ws;e.readyState===I?this._status="open":e.readyState===ae?this._status="connecting":this._status="closed",e.onmessage=t=>this.handleMessage(t),e.onclose=()=>{this._status!=="closed"&&this.handleClose()},e.onerror=()=>{this._status!=="closed"&&this.updateStatus("closed")},e.onopen=()=>{this._status!=="open"&&this.handleOpen()}}handleOpen(){for(this.updateStatus("open");this.messageBuffer.length>0;){const e=this.messageBuffer.shift();e&&this.ws.send(e)}}handleClose(){this.updateStatus("closed")}handleMessage(e){try{const t=JSON.parse(e.data);if("id"in t&&!("method"in t)){const r=this.pendingRequests.get(t.id);r&&(clearTimeout(r.timer),this.pendingRequests.delete(t.id),t.error?r.reject(new Error(t.error)):r.resolve(t.result))}else if("type"in t){const r=this.handlers.get(t.type);r==null||r.forEach(n=>n(t.payload))}}catch(t){console.error("Failed to parse WS message",t)}}updateStatus(e){this._status=e,this.statusHandlers.forEach(t=>t(e))}async call(e,t,r=1e4){return new Promise((n,a)=>{const h=Math.random().toString(36).slice(2),o=setTimeout(()=>{this.pendingRequests.delete(h),a(new Error(`RPC Timeout: ${String(e)}`))},r);this.pendingRequests.set(h,{resolve:n,reject:a,timer:o}),this.sendRaw({id:h,method:e,params:t})})}emit(e,t){this.sendRaw({type:e,payload:t})}on(e,t){const r=this.handlers.get(e)||[];return r.push(t),this.handlers.set(e,r),()=>{const n=(this.handlers.get(e)||[]).filter(a=>a!==t);this.handlers.set(e,n)}}onStatusChange(e){return this.statusHandlers.push(e),()=>{this.statusHandlers=this.statusHandlers.filter(t=>t!==e)}}close(){this.ws.close()}sendRaw(e){const t=JSON.stringify(e);this.ws.readyState===I?this.ws.send(t):this.messageBuffer.push(t)}}class ye{constructor(e,t={}){i(this,"abortController",null);i(this,"handlers",new Map);i(this,"statusHandlers",[]);i(this,"errorHandlers",[]);i(this,"_status","connecting");i(this,"reconnectAttempts",0);i(this,"maxReconnectAttempts",5);i(this,"reconnectDelay",1e3);i(this,"url");i(this,"headers");this.url=e,this.headers=t,this.connect()}get status(){return this._status}async connect(){var e;this._status="connecting",this.abortController=new AbortController;try{const t=await fetch(this.url.toString(),{headers:{Accept:"text/event-stream",...this.headers},signal:this.abortController.signal});if(!t.ok)throw new Error(`HTTP ${t.status}: ${t.statusText}`);this._status="open",this.reconnectAttempts=0,this.statusHandlers.forEach(f=>f("open"));const r=(e=t.body)==null?void 0:e.getReader();if(!r)throw new Error("No response body");const n=new TextDecoder;let a="",h="message",o="";for(;;){const{done:f,value:l}=await r.read();if(f)break;a+=n.decode(l,{stream:!0});const m=a.split(`
62
+
63
+ `);a=m.pop()||"";for(const S of m){const b=S.split(`
64
+ `);h="message",o="";for(const w of b)w.startsWith("event:")?h=w.slice(6).trim():w.startsWith("data:")&&(o=w.slice(5).trim());o&&this.handleMessage(h,o)}}this._status="closed",this.statusHandlers.forEach(f=>f("closed"))}catch(t){if(t.name==="AbortError"){this._status="closed",this.statusHandlers.forEach(r=>r("closed"));return}this.errorHandlers.forEach(r=>r(t)),this.attemptReconnect()}}attemptReconnect(){this.reconnectAttempts<this.maxReconnectAttempts?(this.reconnectAttempts++,setTimeout(()=>{this.connect()},this.reconnectDelay*this.reconnectAttempts)):(this._status="closed",this.statusHandlers.forEach(e=>e("closed")))}handleMessage(e,t){try{const r=JSON.parse(t),n=this.handlers.get(e);n==null||n.forEach(a=>a(r))}catch{const r=this.handlers.get(e);r==null||r.forEach(n=>n(t))}}on(e,t){const r=e,n=this.handlers.get(r)||[];return n.push(t),this.handlers.set(r,n),()=>{const a=(this.handlers.get(r)||[]).filter(h=>h!==t);this.handlers.set(r,a)}}onStatusChange(e){return this.statusHandlers.push(e),e(this._status),()=>{this.statusHandlers=this.statusHandlers.filter(t=>t!==e)}}onError(e){return this.errorHandlers.push(e),()=>{this.errorHandlers=this.errorHandlers.filter(t=>t!==e)}}abort(){this.abortController&&(this.abortController.abort(),this.abortController=null),this._status="closed",this.statusHandlers.forEach(e=>e("closed"))}}export{he as B,ye as S,ue as T,de as U,ge as W,le as a,x as c,me as h,fe as p};
@@ -0,0 +1,11 @@
1
+ import{c as a}from"./sse-client-DGQ072hl.js";/**
2
+ * @license lucide-react v0.576.0 - ISC
3
+ *
4
+ * This source code is licensed under the ISC license.
5
+ * See the LICENSE file in the root directory of this source tree.
6
+ */const o=[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",key:"oel41y"}]],s=a("shield",o);/**
7
+ * @license lucide-react v0.576.0 - ISC
8
+ *
9
+ * This source code is licensed under the ISC license.
10
+ * See the LICENSE file in the root directory of this source tree.
11
+ */const c=[["path",{d:"M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z",key:"r04s7s"}]],t=a("star",c);export{t as S,s as a};
@@ -1,4 +1,4 @@
1
- import{c}from"./index-1bA-ixFv.js";/**
1
+ import{c}from"./sse-client-DGQ072hl.js";/**
2
2
  * @license lucide-react v0.576.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -0,0 +1 @@
1
+ import{R as T,r as i,j as e,c as We,u as _e,d as ve,B as Ge,a as fe,b as H,e as Xe}from"./index-B3CRby6r.js";import{C as ce,c as q,b as Ke,d as G,g as Ye,m as Je,u as $,r as Qe,e as Ze,f as et,h as tt,P as nt,_ as je,i as st,j as ye,R as $e,D as at,S as oe,I as ee,k as te,L as X,M as it,l as lt,n as Z,o as rt,p as ot,q as U,F as h,B as I,t as de,v as ct,w as P,x as dt,y as me,z as ue,a as z,A as D,E as mt,G as ut,T as re,H as gt,J as pt,K as ht,s as xt}from"./api-request-DIJocPxr.js";import{R as be,a as ft,b as jt,M as W,c as yt}from"./SaveOutlined-CLQ2tsSY.js";import{R as vt,S as Q,a as $t,b as bt}from"./LogoutOutlined-ColFAHdd.js";const ge=T.createContext({});ge.Consumer;var Se=function(t,n){var s={};for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&n.indexOf(a)<0&&(s[a]=t[a]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,a=Object.getOwnPropertySymbols(t);r<a.length;r++)n.indexOf(a[r])<0&&Object.prototype.propertyIsEnumerable.call(t,a[r])&&(s[a[r]]=t[a[r]]);return s};const St=t=>{var{prefixCls:n,className:s,avatar:a,title:r,description:g}=t,l=Se(t,["prefixCls","className","avatar","title","description"]);const{getPrefixCls:u}=i.useContext(ce),m=u("list",n),x=q(`${m}-item-meta`,s),d=T.createElement("div",{className:`${m}-item-meta-content`},r&&T.createElement("h4",{className:`${m}-item-meta-title`},r),g&&T.createElement("div",{className:`${m}-item-meta-description`},g));return T.createElement("div",Object.assign({},l,{className:x}),a&&T.createElement("div",{className:`${m}-item-meta-avatar`},a),(r||g)&&d)},Ct=T.forwardRef((t,n)=>{const{prefixCls:s,children:a,actions:r,extra:g,styles:l,className:u,classNames:m,colStyle:x}=t,d=Se(t,["prefixCls","children","actions","extra","styles","className","classNames","colStyle"]),{grid:b,itemLayout:p}=i.useContext(ge),{getPrefixCls:E,list:f}=i.useContext(ce),C=N=>{var S,k;return q((k=(S=f==null?void 0:f.item)===null||S===void 0?void 0:S.classNames)===null||k===void 0?void 0:k[N],m==null?void 0:m[N])},o=N=>{var S,k;return Object.assign(Object.assign({},(k=(S=f==null?void 0:f.item)===null||S===void 0?void 0:S.styles)===null||k===void 0?void 0:k[N]),l==null?void 0:l[N])},v=()=>{let N=!1;return i.Children.forEach(a,S=>{typeof S=="string"&&(N=!0)}),N&&i.Children.count(a)>1},R=()=>p==="vertical"?!!g:!v(),c=E("list",s),j=r&&r.length>0&&T.createElement("ul",{className:q(`${c}-item-action`,C("actions")),key:"actions",style:o("actions")},r.map((N,S)=>T.createElement("li",{key:`${c}-item-action-${S}`},N,S!==r.length-1&&T.createElement("em",{className:`${c}-item-action-split`})))),A=b?"div":"li",M=T.createElement(A,Object.assign({},d,b?{}:{ref:n},{className:q(`${c}-item`,{[`${c}-item-no-flex`]:!R()},u)}),p==="vertical"&&g?[T.createElement("div",{className:`${c}-item-main`,key:"content"},a,j),T.createElement("div",{className:q(`${c}-item-extra`,C("extra")),key:"extra",style:o("extra")},g)]:[a,j,Ke(g,{key:"extra"})]);return b?T.createElement(G,{ref:n,flex:1,style:x},M):M}),Ce=Ct;Ce.Meta=St;const wt=t=>{const{listBorderedCls:n,componentCls:s,paddingLG:a,margin:r,itemPaddingSM:g,itemPaddingLG:l,marginLG:u,borderRadiusLG:m}=t,x=$(t.calc(m).sub(t.lineWidth).equal());return{[n]:{border:`${$(t.lineWidth)} ${t.lineType} ${t.colorBorder}`,borderRadius:m,[`${s}-header`]:{borderRadius:`${x} ${x} 0 0`},[`${s}-footer`]:{borderRadius:`0 0 ${x} ${x}`},[`${s}-header,${s}-footer,${s}-item`]:{paddingInline:a},[`${s}-pagination`]:{margin:`${$(r)} ${$(u)}`}},[`${n}${s}-sm`]:{[`${s}-item,${s}-header,${s}-footer`]:{padding:g}},[`${n}${s}-lg`]:{[`${s}-item,${s}-header,${s}-footer`]:{padding:l}}}},Tt=t=>{const{componentCls:n,screenSM:s,screenMD:a,marginLG:r,marginSM:g,margin:l}=t;return{[`@media screen and (max-width:${a}px)`]:{[n]:{[`${n}-item`]:{[`${n}-item-action`]:{marginInlineStart:r}}},[`${n}-vertical`]:{[`${n}-item`]:{[`${n}-item-extra`]:{marginInlineStart:r}}}},[`@media screen and (max-width: ${s}px)`]:{[n]:{[`${n}-item`]:{flexWrap:"wrap",[`${n}-action`]:{marginInlineStart:g}}},[`${n}-vertical`]:{[`${n}-item`]:{flexWrap:"wrap-reverse",[`${n}-item-main`]:{minWidth:t.contentWidth},[`${n}-item-extra`]:{margin:`auto auto ${$(l)}`}}}}}},It=t=>{const{componentCls:n,antCls:s,controlHeight:a,minHeight:r,paddingSM:g,marginLG:l,padding:u,itemPadding:m,colorPrimary:x,itemPaddingSM:d,itemPaddingLG:b,paddingXS:p,margin:E,colorText:f,colorTextDescription:C,motionDurationSlow:o,lineWidth:v,headerBg:R,footerBg:c,emptyTextPadding:j,metaMarginBottom:A,avatarMarginRight:M,titleMarginBottom:N,descriptionFontSize:S}=t;return{[n]:Object.assign(Object.assign({},Qe(t)),{position:"relative","--rc-virtual-list-scrollbar-bg":t.colorSplit,"*":{outline:"none"},[`${n}-header`]:{background:R},[`${n}-footer`]:{background:c},[`${n}-header, ${n}-footer`]:{paddingBlock:g},[`${n}-pagination`]:{marginBlockStart:l,[`${s}-pagination-options`]:{textAlign:"start"}},[`${n}-spin`]:{minHeight:r,textAlign:"center"},[`${n}-items`]:{margin:0,padding:0,listStyle:"none"},[`${n}-item`]:{display:"flex",alignItems:"center",justifyContent:"space-between",padding:m,color:f,[`${n}-item-meta`]:{display:"flex",flex:1,alignItems:"flex-start",maxWidth:"100%",[`${n}-item-meta-avatar`]:{marginInlineEnd:M},[`${n}-item-meta-content`]:{flex:"1 0",width:0,color:f},[`${n}-item-meta-title`]:{margin:`0 0 ${$(t.marginXXS)} 0`,color:f,fontSize:t.fontSize,lineHeight:t.lineHeight,"> a":{color:f,transition:`all ${o}`,"&:hover":{color:x}}},[`${n}-item-meta-description`]:{color:C,fontSize:S,lineHeight:t.lineHeight}},[`${n}-item-action`]:{flex:"0 0 auto",marginInlineStart:t.marginXXL,padding:0,fontSize:0,listStyle:"none","& > li":{position:"relative",display:"inline-block",padding:`0 ${$(p)}`,color:C,fontSize:t.fontSize,lineHeight:t.lineHeight,textAlign:"center","&:first-child":{paddingInlineStart:0}},[`${n}-item-action-split`]:{position:"absolute",insetBlockStart:"50%",insetInlineEnd:0,width:v,height:t.calc(t.fontHeight).sub(t.calc(t.marginXXS).mul(2)).equal(),transform:"translateY(-50%)",backgroundColor:t.colorSplit}}},[`${n}-empty`]:{padding:`${$(u)} 0`,color:C,fontSize:t.fontSizeSM,textAlign:"center"},[`${n}-empty-text`]:{padding:j,color:t.colorTextDisabled,fontSize:t.fontSize,textAlign:"center"},[`${n}-item-no-flex`]:{display:"block"}}),[`${n}-grid ${s}-col > ${n}-item`]:{display:"block",maxWidth:"100%",marginBlockEnd:E,paddingBlock:0,borderBlockEnd:"none"},[`${n}-vertical ${n}-item`]:{alignItems:"initial",[`${n}-item-main`]:{display:"block",flex:1},[`${n}-item-extra`]:{marginInlineStart:l},[`${n}-item-meta`]:{marginBlockEnd:A,[`${n}-item-meta-title`]:{marginBlockStart:0,marginBlockEnd:N,color:f,fontSize:t.fontSizeLG,lineHeight:t.lineHeightLG}},[`${n}-item-action`]:{marginBlockStart:u,marginInlineStart:"auto","> li":{padding:`0 ${$(u)}`,"&:first-child":{paddingInlineStart:0}}}},[`${n}-split ${n}-item`]:{borderBlockEnd:`${$(t.lineWidth)} ${t.lineType} ${t.colorSplit}`,"&:last-child":{borderBlockEnd:"none"}},[`${n}-split ${n}-header`]:{borderBlockEnd:`${$(t.lineWidth)} ${t.lineType} ${t.colorSplit}`},[`${n}-split${n}-empty ${n}-footer`]:{borderTop:`${$(t.lineWidth)} ${t.lineType} ${t.colorSplit}`},[`${n}-loading ${n}-spin-nested-loading`]:{minHeight:a},[`${n}-split${n}-something-after-last-item ${s}-spin-container > ${n}-items > ${n}-item:last-child`]:{borderBlockEnd:`${$(t.lineWidth)} ${t.lineType} ${t.colorSplit}`},[`${n}-lg ${n}-item`]:{padding:b},[`${n}-sm ${n}-item`]:{padding:d},[`${n}:not(${n}-vertical)`]:{[`${n}-item-no-flex`]:{[`${n}-item-action`]:{float:"right"}}}}},Et=t=>({contentWidth:220,itemPadding:`${$(t.paddingContentVertical)} 0`,itemPaddingSM:`${$(t.paddingContentVerticalSM)} ${$(t.paddingContentHorizontal)}`,itemPaddingLG:`${$(t.paddingContentVerticalLG)} ${$(t.paddingContentHorizontalLG)}`,headerBg:"transparent",footerBg:"transparent",emptyTextPadding:t.padding,metaMarginBottom:t.padding,avatarMarginRight:t.padding,titleMarginBottom:t.paddingSM,descriptionFontSize:t.fontSize}),Nt=Ye("List",t=>{const n=Je(t,{listBorderedCls:`${t.componentCls}-bordered`,minHeight:t.controlHeightLG});return[It(n),wt(n),Tt(n)]},Et);var zt=function(t,n){var s={};for(var a in t)Object.prototype.hasOwnProperty.call(t,a)&&n.indexOf(a)<0&&(s[a]=t[a]);if(t!=null&&typeof Object.getOwnPropertySymbols=="function")for(var r=0,a=Object.getOwnPropertySymbols(t);r<a.length;r++)n.indexOf(a[r])<0&&Object.prototype.propertyIsEnumerable.call(t,a[r])&&(s[a[r]]=t[a[r]]);return s};function Ot(t,n){const{pagination:s=!1,prefixCls:a,bordered:r=!1,split:g=!0,className:l,rootClassName:u,style:m,children:x,itemLayout:d,loadMore:b,grid:p,dataSource:E=[],size:f,header:C,footer:o,loading:v=!1,rowKey:R,renderItem:c,locale:j}=t,A=zt(t,["pagination","prefixCls","bordered","split","className","rootClassName","style","children","itemLayout","loadMore","grid","dataSource","size","header","footer","loading","rowKey","renderItem","locale"]),M=s&&typeof s=="object"?s:{},[N,S]=i.useState(M.defaultCurrent||1),[k,Te]=i.useState(M.defaultPageSize||10),{getPrefixCls:Ie,direction:Ee,className:Ne,style:ze}=Ze("list"),{renderEmpty:ne}=i.useContext(ce),Oe={current:1,total:0,position:"bottom"},pe=y=>(O,B)=>{var le;S(O),Te(B),s&&((le=s==null?void 0:s[y])===null||le===void 0||le.call(s,O,B))},Re=pe("onChange"),Pe=pe("onShowSizeChange"),Me=(y,O)=>{if(!c)return null;let B;return typeof R=="function"?B=R(y):R?B=y[R]:B=y.key,B||(B=`list-item-${O}`),i.createElement(i.Fragment,{key:B},c(y,O))},Le=!!(b||s||o),w=Ie("list",a),[ke,Be,Ae]=Nt(w);let V=v;typeof V=="boolean"&&(V={spinning:V});const se=!!(V!=null&&V.spinning),He=et(f);let K="";switch(He){case"large":K="lg";break;case"small":K="sm";break}const Ue=q(w,{[`${w}-vertical`]:d==="vertical",[`${w}-${K}`]:K,[`${w}-split`]:g,[`${w}-bordered`]:r,[`${w}-loading`]:se,[`${w}-grid`]:!!p,[`${w}-something-after-last-item`]:Le,[`${w}-rtl`]:Ee==="rtl"},Ne,l,u,Be,Ae),L=tt(Oe,{total:E.length,current:N,pageSize:k},s||{}),Fe=Math.ceil(L.total/L.pageSize);L.current=Math.min(L.current,Fe);const he=s&&i.createElement("div",{className:q(`${w}-pagination`)},i.createElement(nt,Object.assign({align:"end"},L,{onChange:Re,onShowSizeChange:Pe})));let ae=je(E);s&&E.length>(L.current-1)*L.pageSize&&(ae=je(E).splice((L.current-1)*L.pageSize,L.pageSize));const Ve=Object.keys(p||{}).some(y=>["xs","sm","md","lg","xl","xxl"].includes(y)),xe=st(Ve),Y=i.useMemo(()=>{for(let y=0;y<ye.length;y+=1){const O=ye[y];if(xe[O])return O}},[xe]),De=i.useMemo(()=>{if(!p)return;const y=Y&&p[Y]?p[Y]:p.column;if(y)return{width:`${100/y}%`,maxWidth:`${100/y}%`}},[JSON.stringify(p),Y]);let ie=se&&i.createElement("div",{style:{minHeight:53}});if(ae.length>0){const y=ae.map(Me);ie=p?i.createElement($e,{gutter:p.gutter},i.Children.map(y,O=>i.createElement("div",{key:O==null?void 0:O.key,style:De},O))):i.createElement("ul",{className:`${w}-items`},y)}else!x&&!se&&(ie=i.createElement("div",{className:`${w}-empty-text`},(j==null?void 0:j.emptyText)||(ne==null?void 0:ne("List"))||i.createElement(at,{componentName:"List"})));const J=L.position,qe=i.useMemo(()=>({grid:p,itemLayout:d}),[JSON.stringify(p),d]);return ke(i.createElement(ge.Provider,{value:qe},i.createElement("div",Object.assign({ref:n,style:Object.assign(Object.assign({},ze),m),className:Ue},A),(J==="top"||J==="both")&&he,C&&i.createElement("div",{className:`${w}-header`},C),i.createElement(oe,Object.assign({},V),ie,x),o&&i.createElement("div",{className:`${w}-footer`},o),b||(J==="bottom"||J==="both")&&he)))}const Rt=i.forwardRef(Ot),_=Rt;_.Item=Ce;var Pt={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M464 144H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H212V212h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V160c0-8.8-7.2-16-16-16zm-52 268H612V212h200v200zM464 544H160c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H212V612h200v200zm452-268H560c-8.8 0-16 7.2-16 16v304c0 8.8 7.2 16 16 16h304c8.8 0 16-7.2 16-16V560c0-8.8-7.2-16-16-16zm-52 268H612V612h200v200z"}}]},name:"appstore",theme:"outlined"},Mt=function(n,s){return i.createElement(ee,te({},n,{ref:s,icon:Pt}))},Lt=i.forwardRef(Mt),kt={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M699 353h-46.9c-10.2 0-19.9 4.9-25.9 13.3L469 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H325c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8a31.8 31.8 0 0051.7 0l210.6-292c3.9-5.3.1-12.7-6.4-12.7z"}},{tag:"path",attrs:{d:"M512 64C264.6 64 64 264.6 64 512s200.6 448 448 448 448-200.6 448-448S759.4 64 512 64zm0 820c-205.4 0-372-166.6-372-372s166.6-372 372-372 372 166.6 372 372-166.6 372-372 372z"}}]},name:"check-circle",theme:"outlined"},Bt=function(n,s){return i.createElement(ee,te({},n,{ref:s,icon:kt}))},At=i.forwardRef(Bt),Ht={icon:{tag:"svg",attrs:{viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M433.1 657.7a31.8 31.8 0 0051.7 0l210.6-292c3.8-5.3 0-12.7-6.5-12.7H642c-10.2 0-19.9 4.9-25.9 13.3L459 584.3l-71.2-98.8c-6-8.3-15.6-13.3-25.9-13.3H315c-6.5 0-10.3 7.4-6.5 12.7l124.6 172.8z"}},{tag:"path",attrs:{d:"M880 112H144c-17.7 0-32 14.3-32 32v736c0 17.7 14.3 32 32 32h736c17.7 0 32-14.3 32-32V144c0-17.7-14.3-32-32-32zm-40 728H184V184h656v656z"}}]},name:"check-square",theme:"outlined"},Ut=function(n,s){return i.createElement(ee,te({},n,{ref:s,icon:Ht}))},we=i.forwardRef(Ut),Ft={icon:{tag:"svg",attrs:{"fill-rule":"evenodd",viewBox:"64 64 896 896",focusable:"false"},children:[{tag:"path",attrs:{d:"M512 64c247.4 0 448 200.6 448 448S759.4 960 512 960 64 759.4 64 512 264.6 64 512 64zm0 76c-205.4 0-372 166.6-372 372s166.6 372 372 372 372-166.6 372-372-166.6-372-372-372zm128.01 198.83c.03 0 .05.01.09.06l45.02 45.01a.2.2 0 01.05.09.12.12 0 010 .07c0 .02-.01.04-.05.08L557.25 512l127.87 127.86a.27.27 0 01.05.06v.02a.12.12 0 010 .07c0 .03-.01.05-.05.09l-45.02 45.02a.2.2 0 01-.09.05.12.12 0 01-.07 0c-.02 0-.04-.01-.08-.05L512 557.25 384.14 685.12c-.04.04-.06.05-.08.05a.12.12 0 01-.07 0c-.03 0-.05-.01-.09-.05l-45.02-45.02a.2.2 0 01-.05-.09.12.12 0 010-.07c0-.02.01-.04.06-.08L466.75 512 338.88 384.14a.27.27 0 01-.05-.06l-.01-.02a.12.12 0 010-.07c0-.03.01-.05.05-.09l45.02-45.02a.2.2 0 01.09-.05.12.12 0 01.07 0c.02 0 .04.01.08.06L512 466.75l127.86-127.86c.04-.05.06-.06.08-.06a.12.12 0 01.07 0z"}}]},name:"close-circle",theme:"outlined"},Vt=function(n,s){return i.createElement(ee,te({},n,{ref:s,icon:Ft}))},Dt=i.forwardRef(Vt);const qt=({collapsed:t,onCollapse:n})=>{const s=[{key:"/dashboard",icon:e.jsx(lt,{}),label:e.jsx("a",{href:"/tenant/dashboard",children:"Dashboard"})},{key:"/users",icon:e.jsx(Z,{}),label:e.jsx("a",{href:"/tenant/users",children:"Users"})},{key:"/subscription",icon:e.jsx(Lt,{}),label:e.jsx("a",{href:"/tenant/subscription",children:"Subscription"})},{key:"/todos",icon:e.jsx(we,{}),label:e.jsx("a",{href:"/tenant/todos",children:"Todos"})},{key:"/content",icon:e.jsx(be,{}),label:e.jsx("a",{href:"/tenant/content",children:"Content"})},{key:"/settings",icon:e.jsx(rt,{}),label:e.jsx("a",{href:"/tenant/settings",children:"Settings"})}];return e.jsxs(X.Sider,{collapsible:!0,collapsed:t,onCollapse:n,className:"bg-gray-900","data-testid":"tenant-sidebar",children:[e.jsx("div",{className:"h-16 flex items-center justify-center bg-gray-900 border-b border-gray-800",children:e.jsx("h1",{className:"text-white font-bold text-lg",children:"Tenant Admin"})}),e.jsx(it,{theme:"dark",mode:"inline",selectedKeys:[window.location.pathname.replace("/tenant","")||"/dashboard"],items:s})]})},Wt=({collapsed:t,onToggle:n})=>{const s=()=>{localStorage.removeItem("tenant-token"),window.location.href="/login"},a=[{key:"profile",icon:e.jsx(Z,{}),label:"Profile"},{key:"logout",icon:e.jsx(vt,{}),label:"Logout",onClick:s}];return e.jsxs(X.Header,{className:"bg-white px-6 flex items-center justify-between shadow-sm","data-testid":"tenant-header",children:[e.jsx("button",{onClick:n,className:"text-gray-600 hover:text-gray-900 focus:outline-none","data-testid":"tenant-sidebar-toggle",children:t?e.jsx(ft,{}):e.jsx(jt,{})}),e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("span",{className:"text-sm text-gray-600",children:"Welcome, Tenant Admin"}),e.jsx(ot,{menu:{items:a},placement:"bottomRight",children:e.jsx("div",{className:"cursor-pointer flex items-center gap-2",children:e.jsx(Z,{className:"text-gray-600"})})})]})]})},_t=({children:t})=>{const[n,s]=i.useState(!1);return e.jsxs(X,{className:"min-h-screen","data-testid":"tenant-layout",children:[e.jsx(qt,{collapsed:n,onCollapse:s}),e.jsxs(X,{children:[e.jsx(Wt,{collapsed:n,onToggle:()=>s(!n)}),e.jsx(X.Content,{className:"m-6 p-6 bg-white rounded-lg shadow-sm",style:{minHeight:"calc(100vh - 64px - 48px)"},"data-testid":"tenant-main",children:t})]})]})},F=We(t=>({isAuthenticated:!!localStorage.getItem("tenant-token"),currentTenant:null,loading:!1,users:[],todos:[],topics:[],stats:{totalUsers:0,activeTodos:0,contentCount:0,monthlyRevenue:0},subscription:null,setCurrentTenant:n=>t({currentTenant:n}),setLoading:n=>t({loading:n}),fetchUsers:async()=>{console.warn("User management not implemented for tenant module")},createUser:async()=>(console.warn("User creation not implemented for tenant module"),!1),updateUser:async()=>(console.warn("User update not implemented for tenant module"),!1),deleteUser:async()=>(console.warn("User deletion not implemented for tenant module"),!1),createTopic:async()=>(console.warn("Topic creation not implemented for tenant module"),!1),updateTopic:async()=>(console.warn("Topic update not implemented for tenant module"),!1),deleteTopic:async()=>(console.warn("Topic deletion not implemented for tenant module"),!1),fetchSubscription:async()=>{console.warn("Subscription management not implemented for tenant module")},fetchCurrentTenant:async n=>{console.warn("Tenant routes not registered - tenant module not active")},fetchTodos:async()=>{console.warn("Tenant routes not registered - tenant module not active")},createTodo:async()=>(console.warn("Tenant routes not registered - tenant module not active"),!1),updateTodo:async()=>(console.warn("Tenant routes not registered - tenant module not active"),!1),deleteTodo:async()=>(console.warn("Tenant routes not registered - tenant module not active"),!1),fetchTopics:async()=>{console.warn("Tenant routes not registered - tenant module not active")},updateTenant:async()=>(console.warn("Tenant routes not registered - tenant module not active"),!1),fetchStats:async()=>{console.warn("Stats endpoint not implemented for tenant module")},startLoading:n=>{t({loading:!0})},stopLoading:()=>{t({loading:!1})}})),Gt=()=>{const{stats:t,fetchStats:n}=F();return i.useEffect(()=>{n()},[n]),e.jsxs("div",{"data-testid":"tenant-dashboard",children:[e.jsx("h1",{className:"text-2xl font-bold mb-6",children:"Dashboard"}),e.jsxs($e,{gutter:16,children:[e.jsx(G,{span:6,children:e.jsx(U,{children:e.jsx(Q,{title:"Total Users",value:t.totalUsers,prefix:e.jsx(Z,{}),valueStyle:{color:"#3f8600"}})})}),e.jsx(G,{span:6,children:e.jsx(U,{children:e.jsx(Q,{title:"Active Todos",value:t.activeTodos,prefix:e.jsx(we,{}),valueStyle:{color:"#1890ff"}})})}),e.jsx(G,{span:6,children:e.jsx(U,{children:e.jsx(Q,{title:"Content Items",value:t.contentCount,prefix:e.jsx(be,{}),valueStyle:{color:"#722ed1"}})})}),e.jsx(G,{span:6,children:e.jsx(U,{children:e.jsx(Q,{title:"Monthly Revenue",value:t.monthlyRevenue,prefix:e.jsx($t,{}),precision:2,valueStyle:{color:"#cf1322"}})})})]})]})},Xt=()=>{const{users:t,loading:n,fetchUsers:s,createUser:a,updateUser:r,deleteUser:g}=F(),[l,u]=i.useState(!1),[m,x]=i.useState(null),[d]=h.useForm();i.useEffect(()=>{s()},[s]);const b=()=>{x(null),d.resetFields(),u(!0)},p=o=>{x(o),d.setFieldsValue(o),u(!0)},E=async o=>{W.confirm({title:"Confirm Delete",content:"Are you sure you want to delete this user?",okText:"Yes",cancelText:"No",onOk:async()=>{await g(o)&&(z.success("User deleted successfully"),s())}})},f=async()=>{try{const o=await d.validateFields();if(m){const v=m.id;await r(v,o)&&(z.success("User updated successfully"),s())}else await a(o)&&(z.success("User created successfully"),s());u(!1),d.resetFields()}catch(o){console.error("Validation failed:",o)}},C=[{title:"ID",dataIndex:"id",key:"id"},{title:"Username",dataIndex:"username",key:"username"},{title:"Email",dataIndex:"email",key:"email"},{title:"Role",dataIndex:"role",key:"role"},{title:"Actions",key:"actions",render:(o,v)=>e.jsxs(dt,{size:"middle",children:[e.jsx(I,{icon:e.jsx(me,{}),size:"small",onClick:()=>p(v),children:"Edit"}),e.jsx(I,{icon:e.jsx(ue,{}),size:"small",danger:!0,onClick:()=>E(Number(v.id)),children:"Delete"})]})}];return e.jsxs("div",{"data-testid":"tenant-users",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Users"}),e.jsx(I,{type:"primary",icon:e.jsx(de,{}),onClick:b,children:"Add User"})]}),e.jsx(ct,{columns:C,dataSource:t,loading:n,rowKey:"id"}),e.jsx(W,{title:m?"Edit User":"Add User",open:l,onOk:f,onCancel:()=>u(!1),destroyOnClose:!0,children:e.jsxs(h,{form:d,layout:"vertical",children:[e.jsx(h.Item,{name:"username",label:"Username",rules:[{required:!0}],children:e.jsx(P,{})}),e.jsx(h.Item,{name:"email",label:"Email",rules:[{required:!0,type:"email"}],children:e.jsx(P,{})}),e.jsx(h.Item,{name:"password",label:"Password",rules:[{required:!m}],children:e.jsx(P.Password,{})}),e.jsx(h.Item,{name:"role",label:"Role",rules:[{required:!0}],children:e.jsx(P,{})})]})})]})},Kt=()=>{var u;const{subscription:t,loading:n,fetchSubscription:s}=F();i.useEffect(()=>{s()},[s]);const a=m=>{switch(m){case"active":return e.jsx(At,{style:{color:"#52c41a"}});case"pending":return e.jsx(bt,{style:{color:"#faad14"}});case"cancelled":return e.jsx(Dt,{style:{color:"#ff4d4f"}});default:return null}},r=()=>{z.success("Upgrade feature coming soon!")},g=()=>{z.success("Cancel subscription feature coming soon!")};if(n)return e.jsx("div",{children:"Loading subscription..."});const l=t;return e.jsxs("div",{"data-testid":"tenant-subscription",children:[e.jsx("h1",{className:"text-2xl font-bold mb-6",children:"Subscription"}),e.jsxs(U,{children:[e.jsxs(D,{title:(l==null?void 0:l.plan)||"No Plan",bordered:!0,children:[e.jsx(D.Item,{label:"Status",children:l!=null&&l.status?e.jsxs("span",{children:[a(l.status)," ",l.status]}):"No subscription"}),e.jsx(D.Item,{label:"Start Date",children:(l==null?void 0:l.startDate)||"-"}),e.jsx(D.Item,{label:"End Date",children:(l==null?void 0:l.endDate)||"-"}),e.jsx(D.Item,{label:"Users Limit",children:(l==null?void 0:l.usersLimit)||"-"}),e.jsx(D.Item,{label:"Storage Limit",children:(l==null?void 0:l.storageLimit)||"-"}),e.jsx(D.Item,{label:"Features",children:((u=l==null?void 0:l.features)==null?void 0:u.join(", "))||"None"})]}),e.jsxs("div",{className:"mt-6 flex gap-4",children:[e.jsx(I,{type:"primary",onClick:r,children:"Upgrade Plan"}),e.jsx(I,{danger:!0,onClick:g,children:"Cancel Subscription"})]})]})]})},Yt=()=>{const{currentTenant:t,loading:n,updateTenant:s}=F(),[a]=h.useForm();i.useEffect(()=>{t&&a.setFieldsValue({name:t.name,slug:t.slug,settings:t.settings||{}})},[t,a]);const r=async g=>{if(!t){z.error("No tenant loaded");return}const l=g,u={name:l.name,settings:l.settings};await s(t.id,u)&&z.success("Settings updated successfully")};return e.jsxs("div",{"data-testid":"tenant-settings",children:[e.jsx("h1",{className:"text-2xl font-bold mb-6",children:"Settings"}),e.jsx(U,{children:e.jsxs(h,{form:a,layout:"vertical",onFinish:r,children:[e.jsx(h.Item,{name:"name",label:"Tenant Name",rules:[{required:!0}],children:e.jsx(P,{})}),e.jsx(h.Item,{name:"slug",label:"Slug",rules:[{required:!0}],children:e.jsx(P,{disabled:!0})}),e.jsx(h.Item,{name:["settings","logoUrl"],label:"Logo URL",children:e.jsx(P,{})}),e.jsx(h.Item,{name:["settings","primaryColor"],label:"Primary Color",children:e.jsx(P,{type:"color"})}),e.jsx(h.Item,{children:e.jsx(I,{type:"primary",htmlType:"submit",icon:e.jsx(yt,{}),loading:n,children:"Save Settings"})})]})})]})},Jt=()=>{const{todos:t,loading:n,fetchTodos:s,createTodo:a,updateTodo:r,deleteTodo:g}=F(),[l,u]=i.useState(!1),[m,x]=i.useState(null),[d]=h.useForm();i.useEffect(()=>{s()},[s]);const b=()=>{x(null),d.resetFields(),u(!0)},p=o=>{x(o),d.setFieldsValue(o),u(!0)},E=async o=>{W.confirm({title:"Confirm Delete",content:"Are you sure you want to delete this todo?",okText:"Yes",cancelText:"No",onOk:async()=>{await g(o)&&(z.success("Todo deleted successfully"),s())}})},f=async o=>{await r(o.id,{status:o.status==="completed"?"pending":"completed"})&&s()},C=async()=>{try{const o=await d.validateFields();m?await r(m.id,o)&&(z.success("Todo updated successfully"),s()):await a(o)&&(z.success("Todo created successfully"),s()),u(!1),d.resetFields()}catch(o){console.error("Validation failed:",o)}};return e.jsxs("div",{"data-testid":"tenant-todos",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Todos"}),e.jsx(I,{type:"primary",icon:e.jsx(de,{}),onClick:b,children:"Add Todo"})]}),e.jsx(_,{loading:n,dataSource:t,renderItem:o=>e.jsx(_.Item,{actions:[e.jsx(I,{type:"text",icon:e.jsx(mt,{}),onClick:()=>f(o),style:{color:o.status==="completed"?"#52c41a":void 0},children:o.status==="completed"?"Completed":"Complete"},"toggle"),e.jsx(I,{type:"text",icon:e.jsx(me,{}),onClick:()=>p(o),children:"Edit"},"edit"),e.jsx(I,{type:"text",danger:!0,icon:e.jsx(ue,{}),onClick:()=>E(o.id),children:"Delete"},"delete")],children:e.jsx(_.Item.Meta,{title:e.jsx("span",{style:{textDecoration:o.status==="completed"?"line-through":void 0},children:o.title}),description:o.description})})}),e.jsx(W,{title:m?"Edit Todo":"Add Todo",open:l,onOk:C,onCancel:()=>u(!1),destroyOnClose:!0,children:e.jsxs(h,{form:d,layout:"vertical",children:[e.jsx(h.Item,{name:"title",label:"Title",rules:[{required:!0}],children:e.jsx(P,{})}),e.jsx(h.Item,{name:"description",label:"Description",children:e.jsx(P.TextArea,{rows:4})}),e.jsx(h.Item,{name:"status",label:"Status",children:e.jsx(ut,{checked:d.getFieldValue("status")==="completed",children:"Completed"})})]})})]})},Qt=()=>{const{topics:t,loading:n,fetchTopics:s,createTopic:a,updateTopic:r,deleteTopic:g}=F(),[l,u]=i.useState(!1),[m,x]=i.useState(null),[d,b]=i.useState(null),[p]=h.useForm();i.useEffect(()=>{s()},[s]);const E=()=>{x(null),p.resetFields(),u(!0)},f=c=>{x(c),p.setFieldsValue({title:c.title,excerpt:c.excerpt,tags:c.tags.map(j=>j.label)}),u(!0)},C=c=>{b(c)},o=async c=>{W.confirm({title:"Confirm Delete",content:"Are you sure you want to delete this topic?",okText:"Yes",cancelText:"No",onOk:async()=>{await g(c)&&(z.success("Topic deleted successfully"),s())}})},v=async()=>{var c;try{const j=await p.validateFields(),A={title:j.title,excerpt:j.excerpt,tags:((c=j.tags)==null?void 0:c.map(M=>({label:M,color:"blue"})))||[]};m?await r(Number(m.id),A)&&(z.success("Topic updated successfully"),s()):await a(A)&&(z.success("Topic created successfully"),s()),u(!1),p.resetFields()}catch(j){console.error("Validation failed:",j)}},R=c=>{switch(c){case"hot":return"red";case"solved":return"green";default:return"default"}};return e.jsxs("div",{"data-testid":"tenant-content",children:[e.jsxs("div",{className:"flex justify-between items-center mb-6",children:[e.jsx("h1",{className:"text-2xl font-bold",children:"Content"}),e.jsx(I,{type:"primary",icon:e.jsx(de,{}),onClick:E,children:"Add Topic"})]}),e.jsx(_,{loading:n,grid:{gutter:16,xs:1,sm:2,md:3,lg:4},dataSource:t,renderItem:c=>e.jsx(_.Item,{children:e.jsx(U,{title:c.title,actions:[e.jsx(I,{type:"text",icon:e.jsx(gt,{}),onClick:()=>C(c),children:"View"},"view"),e.jsx(I,{type:"text",icon:e.jsx(me,{}),onClick:()=>f(c),children:"Edit"},"edit"),e.jsx(I,{type:"text",danger:!0,icon:e.jsx(ue,{}),onClick:()=>o(Number(c.id)),children:"Delete"},"delete")],children:e.jsx(U.Meta,{description:e.jsxs("div",{children:[e.jsx("p",{className:"mb-2",children:c.excerpt}),e.jsx(re,{color:R(c.status),children:c.status})]})})})})}),e.jsx(W,{title:m?"Edit Topic":"Add Topic",open:l,onOk:v,onCancel:()=>u(!1),destroyOnClose:!0,width:800,children:e.jsxs(h,{form:p,layout:"vertical",children:[e.jsx(h.Item,{name:"title",label:"Title",rules:[{required:!0}],children:e.jsx(P,{})}),e.jsx(h.Item,{name:"excerpt",label:"Excerpt",rules:[{required:!0}],children:e.jsx(P.TextArea,{rows:4})}),e.jsx(h.Item,{name:"tags",label:"Tags",children:e.jsx(pt,{mode:"tags",placeholder:"Add tags"})})]})}),e.jsx(W,{title:d==null?void 0:d.title,open:!!d,onCancel:()=>b(null),footer:[e.jsx(I,{onClick:()=>b(null),children:"Close"},"close")],width:800,children:d&&e.jsxs("div",{children:[e.jsx("div",{className:"mb-4",children:e.jsx(re,{color:R(d.status),children:d.status})}),e.jsx("p",{children:d.excerpt}),d.tags&&d.tags.length>0&&e.jsx("div",{className:"mt-4",children:d.tags.map((c,j)=>e.jsx(re,{children:c.label},j))})]})})]})},Zt=({children:t})=>{const n=_e(),{isAuthenticated:s,currentTenant:a,loading:r,fetchCurrentTenant:g}=F();return i.useEffect(()=>{const l=en();l&&g(l)},[g]),r?e.jsx("div",{className:"flex items-center justify-center min-h-screen",children:e.jsx(oe,{size:"large"})}):s?a?e.jsx(e.Fragment,{children:t}):e.jsx("div",{className:"flex items-center justify-center min-h-screen",children:e.jsx(oe,{size:"large",tip:"Loading tenant..."})}):e.jsx(ve,{to:"/login",state:{from:n},replace:!0})};function en(){const t=window.location.hostname;if(t==="localhost"||t==="127.0.0.1"){const s=t.split(".");return s.length>=2&&s[0]!=="localhost"?s[0]:localStorage.getItem("current-tenant-slug")}const n=t.split(".");return n.length>=3?n[0]:null}const tn=()=>e.jsx(ht,{theme:{token:{colorPrimary:"#1890ff"}},children:e.jsx(Ge,{basename:"/tenant",children:e.jsx(fe,{children:e.jsx(H,{path:"/*",element:e.jsx(Zt,{children:e.jsx(_t,{children:e.jsxs(fe,{children:[e.jsx(H,{path:"/",element:e.jsx(ve,{to:"/dashboard",replace:!0})}),e.jsx(H,{path:"/dashboard",element:e.jsx(Gt,{})}),e.jsx(H,{path:"/users",element:e.jsx(Xt,{})}),e.jsx(H,{path:"/subscription",element:e.jsx(Kt,{})}),e.jsx(H,{path:"/settings",element:e.jsx(Yt,{})}),e.jsx(H,{path:"/todos",element:e.jsx(Jt,{})}),e.jsx(H,{path:"/content",element:e.jsx(Qt,{})})]})})})})})})});xt({loadingStore:F.getState(),messageApi:z});Xe.createRoot(document.getElementById("root")).render(e.jsx(T.StrictMode,{children:e.jsx(tn,{})}));
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-1bA-ixFv.js";/**
1
+ import{c as a}from"./sse-client-DGQ072hl.js";/**
2
2
  * @license lucide-react v0.576.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-1bA-ixFv.js";/**
1
+ import{c as e}from"./sse-client-DGQ072hl.js";/**
2
2
  * @license lucide-react v0.576.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-1bA-ixFv.js";/**
1
+ import{c as a}from"./sse-client-DGQ072hl.js";/**
2
2
  * @license lucide-react v0.576.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as o}from"./index-1bA-ixFv.js";/**
1
+ import{c as o}from"./sse-client-DGQ072hl.js";/**
2
2
  * @license lucide-react v0.576.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -7,12 +7,13 @@
7
7
  <meta property="og:title" content="Biomimic App">
8
8
  <meta property="og:description" content="A full-stack application template with React and Hono">
9
9
  <meta property="og:type" content="website">
10
- <script type="module" crossorigin="" src="/assets/main-DHnArIp_.js"></script>
11
- <link rel="modulepreload" crossorigin="" href="/assets/index-1bA-ixFv.js">
12
- <link rel="stylesheet" crossorigin="" href="/assets/index-CWh3vXC_.css">
10
+ <script type="module" crossorigin="" src="/assets/main-Cn4IDo2I.js"></script>
11
+ <link rel="modulepreload" crossorigin="" href="/assets/index-B3CRby6r.js">
12
+ <link rel="modulepreload" crossorigin="" href="/assets/sse-client-DGQ072hl.js">
13
+ <link rel="stylesheet" crossorigin="" href="/assets/index-09IqiOaE.css">
13
14
  </head>
14
15
  <body>
15
- <div id="root"><div class="min-h-screen bg-white text-gray-900 " data-testid="app-container" style="font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; --preset-primary: #6366f1; --preset-primary-hover: #4f46e5; --preset-bg: #ffffff; --preset-text: #111827; --preset-secondary-bg: #f9fafb; --preset-border: #e5e7eb; --preset-radius: 12px; overflow-x: hidden;"><nav class="hidden md:block bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50" data-testid="app-nav"><div class="max-w-7xl mx-auto px-4 h-16 flex items-center justify-between gap-3"><a data-testid="app-title" class="flex items-center gap-2 group shrink-0" href="/" data-discover="true"><div class="w-8 h-8 rounded-lg flex items-center justify-center shadow-sm group-hover:shadow-md transition-shadow" style="background-color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rocket w-4 h-4 text-white" aria-hidden="true"><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"></path><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09"></path><path d="M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z"></path><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05"></path></svg></div><span class="text-lg font-semibold text-gray-900 tracking-tight whitespace-nowrap">Biomimic</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles w-3.5 h-3.5 shrink-0" aria-hidden="true" style="color: rgb(99, 102, 241);"><path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"></path><path d="M20 2v4"></path><path d="M22 4h-4"></path><circle cx="4" cy="20" r="2"></circle></svg></a><div class="flex items-center gap-0.5 overflow-x-auto flex-1 min-w-0 scrollbar-hide [&amp;::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]"><a data-testid="nav-today-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/todos" data-discover="true">Today</a><a data-testid="nav-calendar-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/todos/calendar" data-discover="true">Calendar</a><a data-testid="nav-projects-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/todos/projects" data-discover="true">Projects</a></div><div class="flex items-center gap-2"><a data-testid="auth-login" class="px-3 py-1 text-sm bg-blue-500 text-white rounded hover:bg-blue-600" href="/login" data-discover="true">Sign In</a><a data-testid="auth-register" class="px-3 py-1 text-sm border border-gray-300 text-gray-700 rounded hover:bg-gray-50" href="/register" data-discover="true">Sign Up</a></div></div></nav><main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 pb-24 md:pb-8" data-testid="app-main"><div class="flex items-center justify-center min-h-[50vh] text-gray-400">404 - Page not found</div></main><footer class="py-8 text-center text-gray-500 text-sm border-t border-gray-200 bg-white" data-testid="app-footer"><p class="flex items-center justify-center gap-2">Built with <span class="font-medium text-gray-700">Hono RPC</span> + <span class="font-medium text-gray-700">React</span> + <span class="font-medium text-gray-700">TypeScript</span></p><p class="mt-2 text-xs text-gray-400">Demonstrates: CRUD Operations | SSE (Server-Sent Events) | WebSocket</p></footer><nav class="md:hidden fixed bottom-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-md border-t border-gray-200 safe-area-inset-bottom" data-testid="bottom-tab-bar" style="padding-bottom: env(safe-area-inset-bottom, 0px);"><div class="flex items-center justify-around h-16 px-2"><a data-testid="bottom-tab-today" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 " href="/todos" data-discover="true" style="color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sun w-5 h-5 transition-transform scale-110" aria-hidden="true"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 font-semibold">Today</span><div class="absolute top-0 w-8 h-0.5 rounded-full" style="background-color: rgb(99, 102, 241);"></div></a><a data-testid="bottom-tab-calendar" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/todos/calendar" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-calendar w-5 h-5 transition-transform" aria-hidden="true"><path d="M8 2v4"></path><path d="M16 2v4"></path><rect width="18" height="18" x="3" y="4" rx="2"></rect><path d="M3 10h18"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">Calendar</span></a><a data-testid="bottom-tab-projects" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/todos/projects" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-folder-kanban w-5 h-5 transition-transform" aria-hidden="true"><path d="M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"></path><path d="M8 10v4"></path><path d="M12 10v2"></path><path d="M16 10v6"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">Projects</span></a></div></nav></div></div>
16
+ <div id="root"><div class="min-h-screen bg-white text-gray-900 " data-testid="app-container" style="font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; --preset-primary: #6366f1; --preset-primary-hover: #4f46e5; --preset-bg: #ffffff; --preset-text: #111827; --preset-secondary-bg: #f9fafb; --preset-border: #e5e7eb; --preset-radius: 12px; overflow-x: hidden;"><nav class="hidden md:block bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50" data-testid="app-nav"><div class="max-w-7xl mx-auto px-4 h-16 flex items-center justify-between gap-3"><a data-testid="app-title" class="flex items-center gap-2 group shrink-0" href="/" data-discover="true"><div class="w-8 h-8 rounded-lg flex items-center justify-center shadow-sm group-hover:shadow-md transition-shadow" style="background-color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rocket w-4 h-4 text-white" aria-hidden="true"><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"></path><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09"></path><path d="M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z"></path><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05"></path></svg></div><span class="text-lg font-semibold text-gray-900 tracking-tight whitespace-nowrap">Biomimic</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles w-3.5 h-3.5 shrink-0" aria-hidden="true" style="color: rgb(99, 102, 241);"><path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"></path><path d="M20 2v4"></path><path d="M22 4h-4"></path><circle cx="4" cy="20" r="2"></circle></svg></a><div class="flex items-center gap-0.5 overflow-x-auto flex-1 min-w-0 scrollbar-hide [&amp;::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]"><a data-testid="nav-todos-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/todos" data-discover="true">Todos</a><a data-testid="nav-sse-demo-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/notifications" data-discover="true">SSE Demo</a><a data-testid="nav-websocket-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/websocket" data-discover="true">WebSocket</a></div></div></nav><main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 pb-24 md:pb-8" data-testid="app-main"><div class="flex items-center justify-center min-h-[50vh] text-gray-400">404 - Page not found</div></main><footer class="py-8 text-center text-gray-500 text-sm border-t border-gray-200 bg-white" data-testid="app-footer"><p class="flex items-center justify-center gap-2">Built with <span class="font-medium text-gray-700">Hono RPC</span> + <span class="font-medium text-gray-700">React</span> + <span class="font-medium text-gray-700">TypeScript</span></p><p class="mt-2 text-xs text-gray-400">Demonstrates: CRUD Operations | SSE (Server-Sent Events) | WebSocket</p></footer><nav class="md:hidden fixed bottom-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-md border-t border-gray-200 safe-area-inset-bottom" data-testid="bottom-tab-bar" style="padding-bottom: env(safe-area-inset-bottom, 0px);"><div class="flex items-center justify-around h-16 px-2"><a data-testid="bottom-tab-todos" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 " href="/todos" data-discover="true" style="color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-layout-dashboard w-5 h-5 transition-transform scale-110" aria-hidden="true"><rect width="7" height="9" x="3" y="3" rx="1"></rect><rect width="7" height="5" x="14" y="3" rx="1"></rect><rect width="7" height="9" x="14" y="12" rx="1"></rect><rect width="7" height="5" x="3" y="16" rx="1"></rect></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 font-semibold">Todos</span><div class="absolute top-0 w-8 h-0.5 rounded-full" style="background-color: rgb(99, 102, 241);"></div></a><a data-testid="bottom-tab-sse" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/notifications" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell w-5 h-5 transition-transform" aria-hidden="true"><path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">SSE</span></a><a data-testid="bottom-tab-ws" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/websocket" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-layout-dashboard w-5 h-5 transition-transform" aria-hidden="true"><rect width="7" height="9" x="3" y="3" rx="1"></rect><rect width="7" height="5" x="14" y="3" rx="1"></rect><rect width="7" height="9" x="14" y="12" rx="1"></rect><rect width="7" height="5" x="3" y="16" rx="1"></rect></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">WS</span></a></div></nav></div></div>
16
17
 
17
18
 
18
19
  </body></html>
@@ -9,9 +9,10 @@
9
9
  <meta property="og:title" content="Biomimic App" />
10
10
  <meta property="og:description" content="A full-stack application template with React and Hono" />
11
11
  <meta property="og:type" content="website" />
12
- <script type="module" crossorigin src="/assets/main-DHnArIp_.js"></script>
13
- <link rel="modulepreload" crossorigin href="/assets/index-1bA-ixFv.js">
14
- <link rel="stylesheet" crossorigin href="/assets/index-CWh3vXC_.css">
12
+ <script type="module" crossorigin src="/assets/main-Cn4IDo2I.js"></script>
13
+ <link rel="modulepreload" crossorigin href="/assets/index-B3CRby6r.js">
14
+ <link rel="modulepreload" crossorigin href="/assets/sse-client-DGQ072hl.js">
15
+ <link rel="stylesheet" crossorigin href="/assets/index-09IqiOaE.css">
15
16
  </head>
16
17
  <body>
17
18
  <div id="root"></div>
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Merchant Admin</title>
8
+ <script type="module" crossorigin src="/assets/merchant-DDDN9bMu.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/assets/index-B3CRby6r.js">
10
+ <link rel="modulepreload" crossorigin href="/assets/api-request-DIJocPxr.js">
11
+ <link rel="modulepreload" crossorigin href="/assets/index-CC_zy73y.js">
12
+ <link rel="modulepreload" crossorigin href="/assets/LogoutOutlined-ColFAHdd.js">
13
+ <link rel="stylesheet" crossorigin href="/assets/index-09IqiOaE.css">
14
+ </head>
15
+ <body>
16
+ <div id="root"></div>
17
+ </body>
18
+ </html>
@@ -7,12 +7,13 @@
7
7
  <meta property="og:title" content="Biomimic App">
8
8
  <meta property="og:description" content="A full-stack application template with React and Hono">
9
9
  <meta property="og:type" content="website">
10
- <script type="module" crossorigin="" src="/assets/main-DHnArIp_.js"></script>
11
- <link rel="modulepreload" crossorigin="" href="/assets/index-1bA-ixFv.js">
12
- <link rel="stylesheet" crossorigin="" href="/assets/index-CWh3vXC_.css">
13
- <link rel="modulepreload" as="script" crossorigin="" href="/assets/NotificationPage-COTzp-HD.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/StatusBadge-BJ3W2Zc7.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/LoadingSpinner-DVYOLSRM.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/EmptyState-BK7ttK8D.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/wifi-BwXjnCqI.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/triangle-alert-D1CLh-Vd.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/circle-x-CYxr4RAw.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/circle-check-big-CSElLscG.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/trash-2-DRblNbnA.js"><meta name="description" content="Real-time notifications powered by Server-Sent Events" data-rh="true"><meta property="og:title" content="Notifications - Biomimic App" data-rh="true"><meta property="og:description" content="Real-time notifications powered by Server-Sent Events" data-rh="true"></head>
10
+ <script type="module" crossorigin="" src="/assets/main-Cn4IDo2I.js"></script>
11
+ <link rel="modulepreload" crossorigin="" href="/assets/index-B3CRby6r.js">
12
+ <link rel="modulepreload" crossorigin="" href="/assets/sse-client-DGQ072hl.js">
13
+ <link rel="stylesheet" crossorigin="" href="/assets/index-09IqiOaE.css">
14
+ <link rel="modulepreload" as="script" crossorigin="" href="/assets/NotificationPage-DRkEv02s.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/StatusBadge-CG7wVqpu.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/LoadingSpinner-BcHjaM1m.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/EmptyState-DEyOQjbY.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/wifi-CwYSE0J4.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/triangle-alert-CrOQEdJ2.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/circle-x-CvN9r3fW.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/circle-check-big-CrZdwS75.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/trash-2-BP7fkd5b.js"><meta name="description" content="Real-time notifications powered by Server-Sent Events" data-rh="true"><meta property="og:title" content="Notifications - Biomimic App" data-rh="true"><meta property="og:description" content="Real-time notifications powered by Server-Sent Events" data-rh="true"></head>
14
15
  <body>
15
- <div id="root"><div class="min-h-screen bg-white text-gray-900 " data-testid="app-container" style="font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; --preset-primary: #6366f1; --preset-primary-hover: #4f46e5; --preset-bg: #ffffff; --preset-text: #111827; --preset-secondary-bg: #f9fafb; --preset-border: #e5e7eb; --preset-radius: 12px; overflow-x: hidden;"><nav class="hidden md:block bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50" data-testid="app-nav"><div class="max-w-7xl mx-auto px-4 h-16 flex items-center justify-between gap-3"><a data-testid="app-title" class="flex items-center gap-2 group shrink-0" href="/" data-discover="true"><div class="w-8 h-8 rounded-lg flex items-center justify-center shadow-sm group-hover:shadow-md transition-shadow" style="background-color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rocket w-4 h-4 text-white" aria-hidden="true"><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"></path><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09"></path><path d="M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z"></path><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05"></path></svg></div><span class="text-lg font-semibold text-gray-900 tracking-tight whitespace-nowrap">Biomimic</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles w-3.5 h-3.5 shrink-0" aria-hidden="true" style="color: rgb(99, 102, 241);"><path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"></path><path d="M20 2v4"></path><path d="M22 4h-4"></path><circle cx="4" cy="20" r="2"></circle></svg></a><div class="flex items-center gap-0.5 overflow-x-auto flex-1 min-w-0 scrollbar-hide [&amp;::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]"><a data-testid="nav-today-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/todos" data-discover="true">Today</a><a data-testid="nav-calendar-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/todos/calendar" data-discover="true">Calendar</a><a data-testid="nav-projects-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/todos/projects" data-discover="true">Projects</a></div><div class="flex items-center gap-2"><a data-testid="auth-login" class="px-3 py-1 text-sm bg-blue-500 text-white rounded hover:bg-blue-600" href="/login" data-discover="true">Sign In</a><a data-testid="auth-register" class="px-3 py-1 text-sm border border-gray-300 text-gray-700 rounded hover:bg-gray-50" href="/register" data-discover="true">Sign Up</a></div></div></nav><main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 pb-24 md:pb-8" data-testid="app-main"><div class="max-w-3xl mx-auto p-6" data-testid="notification-container"><div class="mb-8"><h1 class="text-3xl font-bold text-gray-900 flex items-center gap-2"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell w-8 h-8 text-purple-500" aria-hidden="true"><path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path></svg>Notifications</h1><p class="text-gray-500 mt-2">Demonstrates SSE (Server-Sent Events) with Hono RPC type inference</p></div><div class="mb-6 p-4 bg-white rounded-xl shadow-sm border border-gray-200 flex flex-wrap items-center justify-between gap-4"><div class="flex items-center gap-6"><div class="flex items-center gap-2"><span class="font-medium text-gray-700">SSE Status:</span><span class="flex items-center gap-1 text-red-500" data-testid="sse-status-disconnected"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wifi-off w-4 h-4" aria-hidden="true"><path d="M12 20h.01"></path><path d="M8.5 16.429a5 5 0 0 1 7 0"></path><path d="M5 12.859a10 10 0 0 1 5.17-2.69"></path><path d="M19 12.859a10 10 0 0 0-2.007-1.523"></path><path d="M2 8.82a15 15 0 0 1 4.177-2.643"></path><path d="M22 8.82a15 15 0 0 0-11.288-3.764"></path><path d="m2 2 20 20"></path></svg>Disconnected</span></div><div class="flex items-center gap-2"><span class="font-medium text-gray-700">Unread:</span><span class="px-2.5 py-0.5 bg-blue-500 text-white text-sm font-medium rounded-full" data-testid="unread-count">0</span></div></div><div class="flex items-center gap-2"><button class="flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium transition-colors bg-green-500 text-white hover:bg-green-600" data-testid="connect-sse-button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wifi w-4 h-4" aria-hidden="true"><path d="M12 20h.01"></path><path d="M2 8.82a15 15 0 0 1 20 0"></path><path d="M5 12.859a10 10 0 0 1 14 0"></path><path d="M8.5 16.429a5 5 0 0 1 7 0"></path></svg>Connect</button><button disabled="" class="flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium transition-colors bg-gray-100 text-gray-400 cursor-not-allowed" data-testid="disconnect-sse-button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wifi-off w-4 h-4" aria-hidden="true"><path d="M12 20h.01"></path><path d="M8.5 16.429a5 5 0 0 1 7 0"></path><path d="M5 12.859a10 10 0 0 1 5.17-2.69"></path><path d="M19 12.859a10 10 0 0 0-2.007-1.523"></path><path d="M2 8.82a15 15 0 0 1 4.177-2.643"></path><path d="M22 8.82a15 15 0 0 0-11.288-3.764"></path><path d="m2 2 20 20"></path></svg>Disconnect</button><button class="flex items-center gap-1.5 px-4 py-2 bg-gray-500 text-white rounded-lg text-sm font-medium hover:bg-gray-600 transition-colors" data-testid="mark-all-read-button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-check w-4 h-4" aria-hidden="true"><path d="M18 6 7 17l-5-5"></path><path d="m22 10-7.5 7.5L13 16"></path></svg>Mark All Read</button></div></div><form class="mb-8 p-6 bg-white rounded-xl shadow-sm border border-gray-200"><div class="flex gap-4 mb-4"><select class="px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 outline-none" data-testid="notification-type-select"><option value="info">Info</option><option value="warning">Warning</option><option value="success">Success</option><option value="error">Error</option></select><input type="text" placeholder="Title..." class="flex-1 px-4 py-3 text-base border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent outline-none" data-testid="notification-title-input" value=""></div><div class="mb-4"><textarea placeholder="Message..." class="w-full px-4 py-3 text-base border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent outline-none resize-none min-h-[100px]" data-testid="notification-message-input"></textarea></div><button type="submit" disabled="" class="flex items-center gap-2 px-6 py-3 text-base font-medium text-white bg-purple-500 rounded-lg hover:bg-purple-600 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors" data-testid="create-notification-button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-send w-5 h-5" aria-hidden="true"><path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"></path><path d="m21.854 2.147-10.94 10.939"></path></svg>Create Notification</button></form><div class="mb-6 p-4 bg-red-50 border border-red-200 text-red-700 rounded-lg">Unexpected token '&lt;', "&lt;!DOCTYPE "... is not valid JSON</div><div class="space-y-4"></div><div class="flex flex-col items-center justify-center h-full text-gray-500 py-12" data-testid="empty-state"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell w-16 h-16 mb-4 text-gray-300" aria-hidden="true"><path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path></svg><p class="text-center">No notifications yet. Create one above!</p></div></div></main><footer class="py-8 text-center text-gray-500 text-sm border-t border-gray-200 bg-white" data-testid="app-footer"><p class="flex items-center justify-center gap-2">Built with <span class="font-medium text-gray-700">Hono RPC</span> + <span class="font-medium text-gray-700">React</span> + <span class="font-medium text-gray-700">TypeScript</span></p><p class="mt-2 text-xs text-gray-400">Demonstrates: CRUD Operations | SSE (Server-Sent Events) | WebSocket</p></footer><nav class="md:hidden fixed bottom-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-md border-t border-gray-200 safe-area-inset-bottom" data-testid="bottom-tab-bar" style="padding-bottom: env(safe-area-inset-bottom, 0px);"><div class="flex items-center justify-around h-16 px-2"><a data-testid="bottom-tab-today" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 " href="/todos" data-discover="true" style="color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sun w-5 h-5 transition-transform scale-110" aria-hidden="true"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 font-semibold">Today</span><div class="absolute top-0 w-8 h-0.5 rounded-full" style="background-color: rgb(99, 102, 241);"></div></a><a data-testid="bottom-tab-calendar" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/todos/calendar" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-calendar w-5 h-5 transition-transform" aria-hidden="true"><path d="M8 2v4"></path><path d="M16 2v4"></path><rect width="18" height="18" x="3" y="4" rx="2"></rect><path d="M3 10h18"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">Calendar</span></a><a data-testid="bottom-tab-projects" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/todos/projects" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-folder-kanban w-5 h-5 transition-transform" aria-hidden="true"><path d="M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"></path><path d="M8 10v4"></path><path d="M12 10v2"></path><path d="M16 10v6"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">Projects</span></a></div></nav></div></div>
16
+ <div id="root"><div class="min-h-screen bg-white text-gray-900 " data-testid="app-container" style="font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; --preset-primary: #6366f1; --preset-primary-hover: #4f46e5; --preset-bg: #ffffff; --preset-text: #111827; --preset-secondary-bg: #f9fafb; --preset-border: #e5e7eb; --preset-radius: 12px; overflow-x: hidden;"><nav class="hidden md:block bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50" data-testid="app-nav"><div class="max-w-7xl mx-auto px-4 h-16 flex items-center justify-between gap-3"><a data-testid="app-title" class="flex items-center gap-2 group shrink-0" href="/" data-discover="true"><div class="w-8 h-8 rounded-lg flex items-center justify-center shadow-sm group-hover:shadow-md transition-shadow" style="background-color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rocket w-4 h-4 text-white" aria-hidden="true"><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"></path><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09"></path><path d="M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z"></path><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05"></path></svg></div><span class="text-lg font-semibold text-gray-900 tracking-tight whitespace-nowrap">Biomimic</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles w-3.5 h-3.5 shrink-0" aria-hidden="true" style="color: rgb(99, 102, 241);"><path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"></path><path d="M20 2v4"></path><path d="M22 4h-4"></path><circle cx="4" cy="20" r="2"></circle></svg></a><div class="flex items-center gap-0.5 overflow-x-auto flex-1 min-w-0 scrollbar-hide [&amp;::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]"><a data-testid="nav-todos-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/todos" data-discover="true">Todos</a><a data-testid="nav-sse-demo-button" aria-current="page" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-white" href="/notifications" data-discover="true" style="background-color: rgba(99, 102, 241, 0.082); color: rgb(99, 102, 241);">SSE Demo</a><a data-testid="nav-websocket-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/websocket" data-discover="true">WebSocket</a></div></div></nav><main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 pb-24 md:pb-8" data-testid="app-main"><div class="max-w-3xl mx-auto p-6" data-testid="notification-container"><div class="mb-8"><h1 class="text-3xl font-bold text-gray-900 flex items-center gap-2"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell w-8 h-8 text-purple-500" aria-hidden="true"><path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path></svg>Notifications</h1><p class="text-gray-500 mt-2">Demonstrates SSE (Server-Sent Events) with Hono RPC type inference</p></div><div class="mb-6 p-4 bg-white rounded-xl shadow-sm border border-gray-200 flex flex-wrap items-center justify-between gap-4"><div class="flex items-center gap-6"><div class="flex items-center gap-2"><span class="font-medium text-gray-700">SSE Status:</span><span class="flex items-center gap-1 text-red-500" data-testid="sse-status-disconnected"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wifi-off w-4 h-4" aria-hidden="true"><path d="M12 20h.01"></path><path d="M8.5 16.429a5 5 0 0 1 7 0"></path><path d="M5 12.859a10 10 0 0 1 5.17-2.69"></path><path d="M19 12.859a10 10 0 0 0-2.007-1.523"></path><path d="M2 8.82a15 15 0 0 1 4.177-2.643"></path><path d="M22 8.82a15 15 0 0 0-11.288-3.764"></path><path d="m2 2 20 20"></path></svg>Disconnected</span></div><div class="flex items-center gap-2"><span class="font-medium text-gray-700">Unread:</span><span class="px-2.5 py-0.5 bg-blue-500 text-white text-sm font-medium rounded-full" data-testid="unread-count">0</span></div></div><div class="flex items-center gap-2"><button class="flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium transition-colors bg-green-500 text-white hover:bg-green-600" data-testid="connect-sse-button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wifi w-4 h-4" aria-hidden="true"><path d="M12 20h.01"></path><path d="M2 8.82a15 15 0 0 1 20 0"></path><path d="M5 12.859a10 10 0 0 1 14 0"></path><path d="M8.5 16.429a5 5 0 0 1 7 0"></path></svg>Connect</button><button disabled="" class="flex items-center gap-1.5 px-4 py-2 rounded-lg text-sm font-medium transition-colors bg-gray-100 text-gray-400 cursor-not-allowed" data-testid="disconnect-sse-button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-wifi-off w-4 h-4" aria-hidden="true"><path d="M12 20h.01"></path><path d="M8.5 16.429a5 5 0 0 1 7 0"></path><path d="M5 12.859a10 10 0 0 1 5.17-2.69"></path><path d="M19 12.859a10 10 0 0 0-2.007-1.523"></path><path d="M2 8.82a15 15 0 0 1 4.177-2.643"></path><path d="M22 8.82a15 15 0 0 0-11.288-3.764"></path><path d="m2 2 20 20"></path></svg>Disconnect</button><button class="flex items-center gap-1.5 px-4 py-2 bg-gray-500 text-white rounded-lg text-sm font-medium hover:bg-gray-600 transition-colors" data-testid="mark-all-read-button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-check-check w-4 h-4" aria-hidden="true"><path d="M18 6 7 17l-5-5"></path><path d="m22 10-7.5 7.5L13 16"></path></svg>Mark All Read</button></div></div><form class="mb-8 p-6 bg-white rounded-xl shadow-sm border border-gray-200"><div class="flex gap-4 mb-4"><select class="px-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 outline-none" data-testid="notification-type-select"><option value="info">Info</option><option value="warning">Warning</option><option value="success">Success</option><option value="error">Error</option></select><input type="text" placeholder="Title..." class="flex-1 px-4 py-3 text-base border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent outline-none" data-testid="notification-title-input" value=""></div><div class="mb-4"><textarea placeholder="Message..." class="w-full px-4 py-3 text-base border border-gray-300 rounded-lg focus:ring-2 focus:ring-purple-500 focus:border-transparent outline-none resize-none min-h-[100px]" data-testid="notification-message-input"></textarea></div><button type="submit" disabled="" class="flex items-center gap-2 px-6 py-3 text-base font-medium text-white bg-purple-500 rounded-lg hover:bg-purple-600 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors" data-testid="create-notification-button"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-send w-5 h-5" aria-hidden="true"><path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"></path><path d="m21.854 2.147-10.94 10.939"></path></svg>Create Notification</button></form><div class="mb-6 p-4 bg-red-50 border border-red-200 text-red-700 rounded-lg">Unexpected token '&lt;', "&lt;!DOCTYPE "... is not valid JSON</div><div class="space-y-4"></div><div class="flex flex-col items-center justify-center h-full text-gray-500 py-12" data-testid="empty-state"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell w-16 h-16 mb-4 text-gray-300" aria-hidden="true"><path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path></svg><p class="text-center">No notifications yet. Create one above!</p></div></div></main><footer class="py-8 text-center text-gray-500 text-sm border-t border-gray-200 bg-white" data-testid="app-footer"><p class="flex items-center justify-center gap-2">Built with <span class="font-medium text-gray-700">Hono RPC</span> + <span class="font-medium text-gray-700">React</span> + <span class="font-medium text-gray-700">TypeScript</span></p><p class="mt-2 text-xs text-gray-400">Demonstrates: CRUD Operations | SSE (Server-Sent Events) | WebSocket</p></footer><nav class="md:hidden fixed bottom-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-md border-t border-gray-200 safe-area-inset-bottom" data-testid="bottom-tab-bar" style="padding-bottom: env(safe-area-inset-bottom, 0px);"><div class="flex items-center justify-around h-16 px-2"><a data-testid="bottom-tab-todos" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/todos" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-layout-dashboard w-5 h-5 transition-transform" aria-hidden="true"><rect width="7" height="9" x="3" y="3" rx="1"></rect><rect width="7" height="5" x="14" y="3" rx="1"></rect><rect width="7" height="9" x="14" y="12" rx="1"></rect><rect width="7" height="5" x="3" y="16" rx="1"></rect></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">Todos</span></a><a data-testid="bottom-tab-sse" aria-current="page" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 active" href="/notifications" data-discover="true" style="color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell w-5 h-5 transition-transform scale-110" aria-hidden="true"><path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 font-semibold">SSE</span><div class="absolute top-0 w-8 h-0.5 rounded-full" style="background-color: rgb(99, 102, 241);"></div></a><a data-testid="bottom-tab-ws" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/websocket" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-layout-dashboard w-5 h-5 transition-transform" aria-hidden="true"><rect width="7" height="9" x="3" y="3" rx="1"></rect><rect width="7" height="5" x="14" y="3" rx="1"></rect><rect width="7" height="9" x="14" y="12" rx="1"></rect><rect width="7" height="5" x="3" y="16" rx="1"></rect></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">WS</span></a></div></nav></div></div>
16
17
 
17
18
 
18
19
  </body></html>
@@ -0,0 +1,18 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Tenant Admin</title>
8
+ <script type="module" crossorigin src="/assets/tenant-CizbLaLJ.js"></script>
9
+ <link rel="modulepreload" crossorigin href="/assets/index-B3CRby6r.js">
10
+ <link rel="modulepreload" crossorigin href="/assets/api-request-DIJocPxr.js">
11
+ <link rel="modulepreload" crossorigin href="/assets/SaveOutlined-CLQ2tsSY.js">
12
+ <link rel="modulepreload" crossorigin href="/assets/LogoutOutlined-ColFAHdd.js">
13
+ <link rel="stylesheet" crossorigin href="/assets/index-09IqiOaE.css">
14
+ </head>
15
+ <body>
16
+ <div id="root"></div>
17
+ </body>
18
+ </html>
@@ -7,12 +7,13 @@
7
7
  <meta property="og:title" content="Biomimic App">
8
8
  <meta property="og:description" content="A full-stack application template with React and Hono">
9
9
  <meta property="og:type" content="website">
10
- <script type="module" crossorigin="" src="/assets/main-DHnArIp_.js"></script>
11
- <link rel="modulepreload" crossorigin="" href="/assets/index-1bA-ixFv.js">
12
- <link rel="stylesheet" crossorigin="" href="/assets/index-CWh3vXC_.css">
13
- <link rel="modulepreload" as="script" crossorigin="" href="/assets/TodoPage-zC5wWNBa.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/LoadingSpinner-DVYOLSRM.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/EmptyState-BK7ttK8D.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/circle-check-big-CSElLscG.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/plus-pZld_nUL.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/clock-BseUJ7ex.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/trash-2-DRblNbnA.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/x-BH2rJdFq.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/download-BsGC_Xhq.js"><meta name="description" content="Manage your todo items with full CRUD operations" data-rh="true"><meta property="og:title" content="Todo List - Biomimic App" data-rh="true"><meta property="og:description" content="Manage your todo items with full CRUD operations" data-rh="true"></head>
10
+ <script type="module" crossorigin="" src="/assets/main-Cn4IDo2I.js"></script>
11
+ <link rel="modulepreload" crossorigin="" href="/assets/index-B3CRby6r.js">
12
+ <link rel="modulepreload" crossorigin="" href="/assets/sse-client-DGQ072hl.js">
13
+ <link rel="stylesheet" crossorigin="" href="/assets/index-09IqiOaE.css">
14
+ <link rel="modulepreload" as="script" crossorigin="" href="/assets/TodoPage-B7D-bl65.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/LoadingSpinner-BcHjaM1m.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/EmptyState-DEyOQjbY.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/circle-check-big-CrZdwS75.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/plus-DDZfPiDJ.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/clock-CTeSZBiH.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/trash-2-BP7fkd5b.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/x-t615pnNR.js"><link rel="modulepreload" as="script" crossorigin="" href="/assets/download-OSVfVuNV.js"><meta name="description" content="Manage your todo items with full CRUD operations" data-rh="true"><meta property="og:title" content="Todo List - Biomimic App" data-rh="true"><meta property="og:description" content="Manage your todo items with full CRUD operations" data-rh="true"></head>
14
15
  <body>
15
- <div id="root"><div class="min-h-screen bg-white text-gray-900 " data-testid="app-container" style="font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; --preset-primary: #6366f1; --preset-primary-hover: #4f46e5; --preset-bg: #ffffff; --preset-text: #111827; --preset-secondary-bg: #f9fafb; --preset-border: #e5e7eb; --preset-radius: 12px; overflow-x: hidden;"><nav class="hidden md:block bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50" data-testid="app-nav"><div class="max-w-7xl mx-auto px-4 h-16 flex items-center justify-between gap-3"><a data-testid="app-title" class="flex items-center gap-2 group shrink-0" href="/" data-discover="true"><div class="w-8 h-8 rounded-lg flex items-center justify-center shadow-sm group-hover:shadow-md transition-shadow" style="background-color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rocket w-4 h-4 text-white" aria-hidden="true"><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"></path><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09"></path><path d="M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z"></path><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05"></path></svg></div><span class="text-lg font-semibold text-gray-900 tracking-tight whitespace-nowrap">Biomimic</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles w-3.5 h-3.5 shrink-0" aria-hidden="true" style="color: rgb(99, 102, 241);"><path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"></path><path d="M20 2v4"></path><path d="M22 4h-4"></path><circle cx="4" cy="20" r="2"></circle></svg></a><div class="flex items-center gap-0.5 overflow-x-auto flex-1 min-w-0 scrollbar-hide [&amp;::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]"><a data-testid="nav-today-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-white" href="/todos" data-discover="true" aria-current="page" style="background-color: rgba(99, 102, 241, 0.082); color: rgb(99, 102, 241);">Today</a><a data-testid="nav-calendar-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/todos/calendar" data-discover="true">Calendar</a><a data-testid="nav-projects-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/todos/projects" data-discover="true">Projects</a></div><div class="flex items-center gap-2"><a data-testid="auth-login" class="px-3 py-1 text-sm bg-blue-500 text-white rounded hover:bg-blue-600" href="/login" data-discover="true">Sign In</a><a data-testid="auth-register" class="px-3 py-1 text-sm border border-gray-300 text-gray-700 rounded hover:bg-gray-50" href="/register" data-discover="true">Sign Up</a></div></div></nav><main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 pb-24 md:pb-8" data-testid="app-main"><div class="max-w-3xl mx-auto p-6" data-testid="todo-page"><div class="mb-8"><h1 class="text-3xl font-bold text-gray-900 flex items-center gap-2" data-testid="todo-title"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-check-big w-8 h-8 text-blue-500" aria-hidden="true"><path d="M21.801 10A10 10 0 1 1 17 3.335"></path><path d="m9 11 3 3L22 4"></path></svg>Todo List</h1><p class="text-gray-500 mt-2">Demonstrates CRUD operations with Hono RPC type inference</p></div><form class="mb-8 p-6 bg-white rounded-xl shadow-sm border border-gray-200" data-testid="todo-form"><div class="mb-4"><input type="text" placeholder="Todo title..." data-testid="todo-title-input" class="w-full px-4 py-3 text-base border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-all" value=""></div><div class="mb-4"><textarea placeholder="Description (optional)..." data-testid="todo-description-input" class="w-full px-4 py-3 text-base border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-all resize-none min-h-[100px]"></textarea></div><button type="submit" disabled="" data-testid="add-todo-button" class="flex items-center gap-2 px-6 py-3 text-base font-medium text-white bg-blue-500 rounded-lg hover:bg-blue-600 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-plus w-5 h-5" aria-hidden="true"><path d="M5 12h14"></path><path d="M12 5v14"></path></svg>Add Todo</button></form><div class="mb-6 p-4 bg-red-50 border border-red-200 text-red-700 rounded-lg" data-testid="error-message">Unexpected token '&lt;', "&lt;!DOCTYPE "... is not valid JSON</div><div class="space-y-4" data-testid="todo-list"></div><div class="flex flex-col items-center justify-center h-full text-gray-500 py-12" data-testid="empty-state"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle w-16 h-16 mb-4 text-gray-300" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle></svg><p class="text-center">No todos yet. Add one above!</p></div></div></main><footer class="py-8 text-center text-gray-500 text-sm border-t border-gray-200 bg-white" data-testid="app-footer"><p class="flex items-center justify-center gap-2">Built with <span class="font-medium text-gray-700">Hono RPC</span> + <span class="font-medium text-gray-700">React</span> + <span class="font-medium text-gray-700">TypeScript</span></p><p class="mt-2 text-xs text-gray-400">Demonstrates: CRUD Operations | SSE (Server-Sent Events) | WebSocket</p></footer><nav class="md:hidden fixed bottom-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-md border-t border-gray-200 safe-area-inset-bottom" data-testid="bottom-tab-bar" style="padding-bottom: env(safe-area-inset-bottom, 0px);"><div class="flex items-center justify-around h-16 px-2"><a data-testid="bottom-tab-today" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 active" href="/todos" data-discover="true" aria-current="page" style="color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sun w-5 h-5 transition-transform scale-110" aria-hidden="true"><circle cx="12" cy="12" r="4"></circle><path d="M12 2v2"></path><path d="M12 20v2"></path><path d="m4.93 4.93 1.41 1.41"></path><path d="m17.66 17.66 1.41 1.41"></path><path d="M2 12h2"></path><path d="M20 12h2"></path><path d="m6.34 17.66-1.41 1.41"></path><path d="m19.07 4.93-1.41 1.41"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 font-semibold">Today</span><div class="absolute top-0 w-8 h-0.5 rounded-full" style="background-color: rgb(99, 102, 241);"></div></a><a data-testid="bottom-tab-calendar" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/todos/calendar" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-calendar w-5 h-5 transition-transform" aria-hidden="true"><path d="M8 2v4"></path><path d="M16 2v4"></path><rect width="18" height="18" x="3" y="4" rx="2"></rect><path d="M3 10h18"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">Calendar</span></a><a data-testid="bottom-tab-projects" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/todos/projects" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-folder-kanban w-5 h-5 transition-transform" aria-hidden="true"><path d="M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13c0 1.1.9 2 2 2Z"></path><path d="M8 10v4"></path><path d="M12 10v2"></path><path d="M16 10v6"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">Projects</span></a></div></nav></div></div>
16
+ <div id="root"><div class="min-h-screen bg-white text-gray-900 " data-testid="app-container" style="font-family: -apple-system, BlinkMacSystemFont, &quot;Segoe UI&quot;, Roboto, sans-serif; --preset-primary: #6366f1; --preset-primary-hover: #4f46e5; --preset-bg: #ffffff; --preset-text: #111827; --preset-secondary-bg: #f9fafb; --preset-border: #e5e7eb; --preset-radius: 12px; overflow-x: hidden;"><nav class="hidden md:block bg-white/80 backdrop-blur-md border-b border-gray-200 sticky top-0 z-50" data-testid="app-nav"><div class="max-w-7xl mx-auto px-4 h-16 flex items-center justify-between gap-3"><a data-testid="app-title" class="flex items-center gap-2 group shrink-0" href="/" data-discover="true"><div class="w-8 h-8 rounded-lg flex items-center justify-center shadow-sm group-hover:shadow-md transition-shadow" style="background-color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-rocket w-4 h-4 text-white" aria-hidden="true"><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"></path><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09"></path><path d="M9 12a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.4 22.4 0 0 1-4 2z"></path><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 .05 5 .05"></path></svg></div><span class="text-lg font-semibold text-gray-900 tracking-tight whitespace-nowrap">Biomimic</span><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-sparkles w-3.5 h-3.5 shrink-0" aria-hidden="true" style="color: rgb(99, 102, 241);"><path d="M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z"></path><path d="M20 2v4"></path><path d="M22 4h-4"></path><circle cx="4" cy="20" r="2"></circle></svg></a><div class="flex items-center gap-0.5 overflow-x-auto flex-1 min-w-0 scrollbar-hide [&amp;::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]"><a data-testid="nav-todos-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-white" href="/todos" data-discover="true" aria-current="page" style="background-color: rgba(99, 102, 241, 0.082); color: rgb(99, 102, 241);">Todos</a><a data-testid="nav-sse-demo-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/notifications" data-discover="true">SSE Demo</a><a data-testid="nav-websocket-button" class="px-3 py-1.5 rounded-lg text-sm font-medium transition-all duration-200 shrink-0 whitespace-nowrap text-gray-500 hover:text-gray-900 hover:bg-gray-50" href="/websocket" data-discover="true">WebSocket</a></div></div></nav><main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8 pb-24 md:pb-8" data-testid="app-main"><div class="max-w-3xl mx-auto p-6" data-testid="todo-page"><div class="mb-8"><h1 class="text-3xl font-bold text-gray-900 flex items-center gap-2" data-testid="todo-title"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-check-big w-8 h-8 text-blue-500" aria-hidden="true"><path d="M21.801 10A10 10 0 1 1 17 3.335"></path><path d="m9 11 3 3L22 4"></path></svg>Todo List</h1><p class="text-gray-500 mt-2">Demonstrates CRUD operations with Hono RPC type inference</p></div><form class="mb-8 p-6 bg-white rounded-xl shadow-sm border border-gray-200" data-testid="todo-form"><div class="mb-4"><input type="text" placeholder="Todo title..." data-testid="todo-title-input" class="w-full px-4 py-3 text-base border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-all" value=""></div><div class="mb-4"><textarea placeholder="Description (optional)..." data-testid="todo-description-input" class="w-full px-4 py-3 text-base border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent outline-none transition-all resize-none min-h-[100px]"></textarea></div><button type="submit" disabled="" data-testid="add-todo-button" class="flex items-center gap-2 px-6 py-3 text-base font-medium text-white bg-blue-500 rounded-lg hover:bg-blue-600 disabled:bg-gray-300 disabled:cursor-not-allowed transition-colors"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-plus w-5 h-5" aria-hidden="true"><path d="M5 12h14"></path><path d="M12 5v14"></path></svg>Add Todo</button></form><div class="mb-6 p-4 bg-red-50 border border-red-200 text-red-700 rounded-lg" data-testid="error-message">Unexpected token '&lt;', "&lt;!DOCTYPE "... is not valid JSON</div><div class="space-y-4" data-testid="todo-list"></div><div class="flex flex-col items-center justify-center h-full text-gray-500 py-12" data-testid="empty-state"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle w-16 h-16 mb-4 text-gray-300" aria-hidden="true"><circle cx="12" cy="12" r="10"></circle></svg><p class="text-center">No todos yet. Add one above!</p></div></div></main><footer class="py-8 text-center text-gray-500 text-sm border-t border-gray-200 bg-white" data-testid="app-footer"><p class="flex items-center justify-center gap-2">Built with <span class="font-medium text-gray-700">Hono RPC</span> + <span class="font-medium text-gray-700">React</span> + <span class="font-medium text-gray-700">TypeScript</span></p><p class="mt-2 text-xs text-gray-400">Demonstrates: CRUD Operations | SSE (Server-Sent Events) | WebSocket</p></footer><nav class="md:hidden fixed bottom-0 left-0 right-0 z-50 bg-white/95 backdrop-blur-md border-t border-gray-200 safe-area-inset-bottom" data-testid="bottom-tab-bar" style="padding-bottom: env(safe-area-inset-bottom, 0px);"><div class="flex items-center justify-around h-16 px-2"><a data-testid="bottom-tab-todos" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 active" href="/todos" data-discover="true" aria-current="page" style="color: rgb(99, 102, 241);"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-layout-dashboard w-5 h-5 transition-transform scale-110" aria-hidden="true"><rect width="7" height="9" x="3" y="3" rx="1"></rect><rect width="7" height="5" x="14" y="3" rx="1"></rect><rect width="7" height="9" x="14" y="12" rx="1"></rect><rect width="7" height="5" x="3" y="16" rx="1"></rect></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 font-semibold">Todos</span><div class="absolute top-0 w-8 h-0.5 rounded-full" style="background-color: rgb(99, 102, 241);"></div></a><a data-testid="bottom-tab-sse" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/notifications" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-bell w-5 h-5 transition-transform" aria-hidden="true"><path d="M10.268 21a2 2 0 0 0 3.464 0"></path><path d="M3.262 15.326A1 1 0 0 0 4 17h16a1 1 0 0 0 .74-1.673C19.41 13.956 18 12.499 18 8A6 6 0 0 0 6 8c0 4.499-1.411 5.956-2.738 7.326"></path></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">SSE</span></a><a data-testid="bottom-tab-ws" class="flex flex-col items-center justify-center gap-0.5 flex-1 py-1 rounded-xl transition-all duration-200 min-w-0 text-gray-400 hover:text-gray-600" href="/websocket" data-discover="true"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-layout-dashboard w-5 h-5 transition-transform" aria-hidden="true"><rect width="7" height="9" x="3" y="3" rx="1"></rect><rect width="7" height="5" x="14" y="3" rx="1"></rect><rect width="7" height="9" x="14" y="12" rx="1"></rect><rect width="7" height="5" x="3" y="16" rx="1"></rect></svg><span class="text-[10px] font-medium leading-tight truncate w-full text-center px-1 ">WS</span></a></div></nav></div></div>
16
17
 
17
18
 
18
19
  </body></html>